Help !高手过来看看 STL map 插入出错

miker86 2008-04-04 12:25:17
#include<string>
#include<map>
#include<iostream>

using namespace std;

struct arrtibute
{
const char* name;
int id;
};

typedef std::map<std::string, arrtibute*> AtrributMap;
AtrributMap atrributeMap_g;

void InitData()
{
for (int i = 0; i < 5; i++)
{

static arrtibute atrr;
std::string str;

cout <<"Input the name: ";
cin>>str;

atrr.id = i;
atrr.name = str.c_str();

std::pair<AtrributMap::iterator,bool> insResult;
insResult = atrributeMap_g.insert(std::make_pair(atrr.name, &atrr));

// Make sure added successfully
if (!insResult.second)
{
cout<<"insert to transfer map failed, id and name is: "
<<atrr.id<<" "<<atrr.name<<endl;
}
}
}



void PrintData()
{
cout<<"**********print the map*********"<<endl;
AtrributMap::const_iterator Itor;
for( Itor = atrributeMap_g.begin();
Itor != atrributeMap_g.end();
++Itor )
{
cout<<"name is: "<<Itor->second->name<<" "<<"Id is : "<<Itor->second->id<<endl;
}
cout<<"**********end of the map*********"<<endl;
}

以上代码有个问题我在InitData()里面初始化一个全局map变量atrributeMap_g, 但是在PrintData()里面却得不到我刚才插入的元素,有时候是乱码,有时候只有一个值而且都是最后一个插入的值,前面的值都被冲调了。我查了些资料说是map的kay一定要不一样,代码里面是const char*, 每次比较的是字符串地址,而且每次该地址都是一样的,所以插入只会更新value值。
但是我想在不改变struct 定义的情况下,试图把const char* 的字符串的值作为Key插入,即:std::string strName(atrr.name), 然后以该字符串作为Key 插入到map里仍然和前面的情况一样。请问在不改变struct 和 map 定义的情况下,怎样正确循环插入元素。
...全文
360 7 打赏 收藏 举报
写回复
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
miker86 2008-04-05
  • 打赏
  • 举报
回复
多谢,你给的代码有一定道理但是不完全对。
strcpy(atrr->name, str.c_str());
atrr->name[str.size()] = '\0' ;
因为atrr->name是const char* 因此这两句不行。
而且你的插入map之前先查找是否存在,我感觉没有必要的,因为map插入的时候自动会比较key值。
如果相同的话也不一定就不插入了,比如value值更新了,那么这个更新的value也会插入替换old value.
【呵呵不知道是不是这样的 :) 】
如果map不存指针而存值,可能就容易些吧
typedef std::map <std::string, arrtibute> AtrributMap;
这样子也不需要最后的内存释放了。
因此代码改为如下:
#include <string>
#include <map>
#include <iostream>

using namespace std;

struct arrtibute
{
const char* name;
int id;
};

typedef std::map <std::string, arrtibute> AtrributMap;
AtrributMap atrributeMap_g;
const int MaxCount = 3;

void InitData()
{
for (int i = 0; i < MaxCount; i++)
{
arrtibute atrr;
memset(&atrr, 0, sizeof(arrtibute));
std::string str;

cout <<"Input the name: ";
cin>>str;

atrr.id = i;
atrr.name = str.c_str();

std::pair <AtrributMap::iterator,bool> insResult;
insResult = atrributeMap_g.insert(std::make_pair(atrr.name, atrr));

// Make sure added successfully
if (!insResult.second)
{
cout <<"insert to transfer map failed, id and name is: "
<<atrr.id <<" " <<atrr.name <<endl;
}
}
}

void PrintData()
{
cout <<"**********print the map*********" <<endl;

AtrributMap::const_iterator Itor;
for( Itor = atrributeMap_g.begin();
Itor != atrributeMap_g.end();
++Itor )
{
cout <<"name is: " <<Itor->second.name <<" " <<"Id is : " <<
Itor->second.id <<endl;
}
cout <<"**********end of the map*********" <<endl;
}

void main()
{
InitData();

PrintData();
}
这段代码还是有问题,估计是把栈内存赋值给全局内存引起的,大家看看有什么办法可以消除,能保证正确插入。
多谢各位了 :)
星羽 2008-04-05
  • 打赏
  • 举报
回复
你的arrtibute设计有问题,然而你又不让改,只能。。。



#include <string>
#include <map>
#include <iostream>

using namespace std;

struct arrtibute
{
const char* name;
int id;
};

typedef std::map <std::string, arrtibute> AtrributMap;
AtrributMap atrributeMap_g;
const int MaxCount = 3;


void ReleaseData()
{
for (AtrributMap::iterator i = atrributeMap_g.begin();
i != atrributeMap_g.end(); ++i)
{
delete[] i->second.name;
}
}

void InitData()
{
for (int i = 0; i < MaxCount; i++)
{
arrtibute atrr;
memset(&atrr, 0, sizeof(arrtibute));
std::string str;

cout <<"Input the name: ";
cin>>str;

atrr.id = i;
char* temp = new char[128];
strcpy(temp, str.c_str());
atrr.name = temp;

std::pair <AtrributMap::iterator,bool> insResult;
insResult = atrributeMap_g.insert(std::make_pair(atrr.name, atrr));

// Make sure added successfully
if (!insResult.second)
{
cout <<"insert to transfer map failed, id and name is: "
<<atrr.id <<" " <<atrr.name <<endl;
}
}
}

void PrintData()
{
cout <<"**********print the map*********" <<endl;

AtrributMap::const_iterator Itor;
for( Itor = atrributeMap_g.begin();
Itor != atrributeMap_g.end();
++Itor )
{
cout <<"name is: " <<Itor->second.name <<" " <<"Id is : " <<
Itor->second.id <<endl;
}
cout <<"**********end of the map*********" <<endl;
}

void main()
{
InitData();

PrintData();

ReleaseData();


}




miker86 2008-04-04
  • 打赏
  • 举报
回复
各位大哥 本人是用map而不是multimap,因为需求是这样的
其次,我说了在不改变struct arrtibute 定义的情况下,即不能 const char* name; 改为string name。
有没有其他的办法在循环体内修改。
csdn5211 2008-04-04
  • 打赏
  • 举报
回复
struct arrtibute
{
const string name;
int id;
};

指针只是指向str,下次循环就没有了,string有拷贝构造函数。
  • 打赏
  • 举报
回复
注意生存周期
struct arrtibute
{
const char* name; <=========string name;
int id;
};
kuchao 2008-04-04
  • 打赏
  • 举报
回复
#include <string>
#include <map>
#include <iostream>

using namespace std;

struct arrtibute
{
const char* name;
int id;
};

typedef std::map <std::string, arrtibute*> AtrributMap;
AtrributMap atrributeMap_g;

void InitData()
{
for (int i = 0; i < 5; i++)
{

//static arrtibute atrr;
arrtibute* atrr = new arrtibute;
std::string str;

cout < <"Input the name: ";
cin>>str;

atrr->id = i;
atrr->name = new char[str.size() + 1];
strcpy(atrr->name, str.c_str());
atrr->name[str.size()] = '\0'
//atrr.name = str.c_str();


if (atrributeMap_g.find(str) == atrributeMap_g.end())
{
atrributeMap_g[str] = atrr;
}
else
{
cout < <"insert to transfer map failed, id and name is: "
< <atrr->id < <" " < <atrr->name < <endl;
}

//std::pair <AtrributMap::iterator,bool> insResult;
//insResult = atrributeMap_g.insert(std::make_pair(atrr.name, &atrr));

// Make sure added successfully
//if (!insResult.second)
//{
// cout < <"insert to transfer map failed, id and name is: "
// < <atrr.id < <" " < <atrr.name < <endl;
//}
}
}



void PrintData()
{
cout < <"**********print the map*********" < <endl;
AtrributMap::const_iterator Itor;
for( Itor = atrributeMap_g.begin();
Itor != atrributeMap_g.end();
++Itor )
{
cout < <"name is: " < <(*Itor).second->name < <" " < <"Id is : " < <(*Itor).second->id < <endl;
}
cout < <"**********end of the map*********" < <endl;
}


最后别忘记释放内存
for (AtrributMap::iterator pos = atrributeMap_g.begin(); pos != atrributeMap_g.end(); ++pos )
{
arrtibute* attr = (*pos).second;
if (attr->name)
delete [] attr->name;

delete attr;
}
atrributeMap_g.clear();


你还没有了解内存分配,STL内存分配的用法,推荐去看一些基础一些的书.
abupie 2008-04-04
  • 打赏
  • 举报
回复
multimap , 它与 map 类似,但允许重复键。
相关推荐
发帖
C++ 语言

6.3w+

社区成员

C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
帖子事件
创建了帖子
2008-04-04 12:25
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下