问个关于STL的小问题

nightfallrove 2003-11-05 04:38:32
程序如下:
map<char*,int,mycmp> ph;//一个电话本map,mycmp用来比较char*的类,重载了()参数类型为(const char*,const int),char*是名字
char name[20];
int num=0;
do{
cin>>name;//输入姓名
cin>>num;
ph[name]=num;
}while(num>0);//无论输入多少电话记录,ph中只能保存最后一次的输入结果,也就是说ph中永远只有一条记录,这是这什么?我把循环中的ph[name]=num;换成:ph.insert(make_pair(name,num));//编译出错,说不能把char*转换成const cahr[20]什么的,总之是类型转换错误。 但是我把map<char*,int,mycmp>换成map<string,int>后就没有问题了,好象是char*做为键类型出了问题,但不知道是什么问题,哪位帮我解说一下。
...全文
33 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
birth_chen 2003-11-10
  • 打赏
  • 举报
回复
根本不是map的错,你看看代码:
char name[20];
int num=0;
do{
cin>>name;//输入姓名
cin>>num;
ph[name]=num; // 这一句永远只是把name加进去
}while(num>0);

ph[name] = num;这一句永远只是把name加进map里,它是一个地址,所以复制进map里去的只是一个地址,并没有把字符串内容存下来。第一个循环,加进一个字符串指针,第二个循环,把指针指向的字符串改了,然后再加一次!看清楚了没有?
结果,map里面会有很多个元素,但他们指向同一块内存!而且他们比较起来(用mycmp)是相等的!因此输出的时候只是输出了一个!
正确的办法是用new为每一个字符串申请空间!但这种情况下最好还是应该用string!
nightfallrove 2003-11-10
  • 打赏
  • 举报
回复
总算懂了,

谢谢各位!
begginginstorm 2003-11-10
  • 打赏
  • 举报
回复
我觉得主要是对类的概念没有搞清楚。在map的定义中
template <
class Key,
class Type,
class Traits = less<Key>,
class Allocator=allocator<pair <const Key, Type> >
>
这时键值的类型是class Key,在map中每一个节点都会生成一个类型Key的实例,这个实例一般是在堆中建立的。
在map<char*, int, ...>中,Key是char*,如果typedef char* MyKey的话,map内部会做类似下面的操作: MyKey *pKey = new MyKey。请注意,这里pKey指向什么类型呢?是char*,也就是字符串的地址。
在map<string, int, ...>中,Key是string,对于MyKey *pKey = new MyKey, 这里确实创建了一个string的实例,而且这个实例是属于map所有的。
以上差不多就是为什么map<char*,int...>会出现问题而map<string,int...>没有问题的原因了。
下面是一个实例:
class MyCmp
{
public:
bool operator()(const char* p1, const char* p2)
{
return ::lstrcmp(p1,p2) < 0;
}
bool operator()(const string& s1, const string& s2)
{
return s1.compare(s2) < 0;
}
};

map<char*, int, MyCmp> Test()
{
map<char*, int, MyCmp> ph;
char name[20];
lstrcpy(name, _T("hello"));
ph[name] = 100;

cout << "The following is content of ph of the map with char*:" << endl;
for(map<char*, int, MyCmp>::iterator it = ph.begin(); it != ph.end(); ++it)
{
cout << "name: " << it->first << " code:" << it->second << endl;
}

map<char*, int, MyCmp>::iterator first = ph.begin();
cout << (void*)name << endl;
cout << (void*)(first->first) << endl;

return ph;
}

map<string, int, MyCmp> TestUsingString()
{
map<string, int, MyCmp> ph;
char name[20];
lstrcpy(name, _T("hello"));
ph[name] = 100;

cout << "The following is content of ph of the map with string:" << endl;
for(map<string, int, MyCmp>::iterator it = ph.begin(); it != ph.end(); ++it)
{
cout << "name: " << it->first << " code:" << it->second << endl;
}

map<string, int, MyCmp>::iterator first = ph.begin();
cout << hex;
cout << (void*)name << endl;
cout << (void*)(first->first.data()) << endl;

return ph;
}

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
cout << hex;
map<char*, int, MyCmp> ph = Test();

cout << "The following is content of the map with char* in Main:" << endl;
for(map<char*, int, MyCmp>::iterator it = ph.begin(); it != ph.end(); ++it)
{
cout << "name: " << it->first << " code:" << it->second << endl;
}

map<string, int, MyCmp> ph1 = TestUsingString();
cout << "The following is content of the map with string in Main:" << endl;
for(map<string, int, MyCmp>::iterator its = ph1.begin(); its != ph1.end(); ++its)
{
cout << "name: " << its->first << " code:" << its->second << endl;
}
return 1;
}
在我的机器上运行的结果是:
The following is content of ph of the map with char*:
name: hello code:64
0012FED4
0012FED4
The following is content of the map with char* in Main:
name: 羹 code:64
The following is content of ph of the map with string:
name: hello code:64
0012FEC0
00C74629
The following is content of the map with string in Main:
name: hello code:64
Press any key to continue
第3行和第4行输出了相同的地址表明二者使用了同一块内存。
第6行输出了乱码是因为字符串是创建在栈里的,因为函数Test已经退出,相关内存也已释放,所以会出现乱码。
而第9和第10行则表明他没并没有使用相同的内存。
第12行输出了正确的name。
nightfallrove 2003-11-08
  • 打赏
  • 举报
回复
mycmp
class mycmp
{
public:mycmp(){}
bool operator ()(const char*a,const char*b){return strcmp(a,b)<0}
};
我觉得mycmp没错了只是不知道为什么用char*构造MAP没用。。。
birth_chen 2003-11-07
  • 打赏
  • 举报
回复
晕,你不把你的mycomp代码贴出来,谁知道你哪里错了

“不要把指针和 stl 容器搭配使用”这种说法是不对的!
其实为了实现多态性,指针经常和stl容器搭配使用的,但使用时有不少要注意的地方!
nightfallrove 2003-11-07
  • 打赏
  • 举报
回复
简直胡来!

mycmp用来比较char*的类,重载了()参数类型为(const char*,const int)??????????

应该是(const char*,const char*)吧?还有,把你的mycmp贴出来看看

打错了,是(const char*,const char*)


为什么不要把指针和 stl 容器搭配使用?
Wolf0403 2003-11-06
  • 打赏
  • 举报
回复
不要把指针和 stl 容器搭配使用。
Wolf0403 2003-11-06
  • 打赏
  • 举报
回复
struct MyStringCmp
{
mycmp m;
bool operator()(const string& _a, const string& _b)
{
return m(_a.c_str(), _b.c_str());
}
}

map<string, int, MyStringCmp>
这样好了吧?呵呵。
darcymei 2003-11-06
  • 打赏
  • 举报
回复
当然加不进拉,你每次穿的都是同一个char * 即name。同样的key就覆盖了
除非你用multimap
birth_chen 2003-11-06
  • 打赏
  • 举报
回复
简直胡来!

mycmp用来比较char*的类,重载了()参数类型为(const char*,const int)??????????

应该是(const char*,const char*)吧?还有,把你的mycmp贴出来看看
蝎子i软件 2003-11-06
  • 打赏
  • 举报
回复
mmlymlymly(mly)说的没错.
用map<string, int, mycmp>吧
darcymei 2003-11-06
  • 打赏
  • 举报
回复
晕,拜托仔细看看好伐。
你的key是char *是一个地址
你每次传入的都是name,是name[20]得首地址,这个又不会变的,只是name[20]的内容在变罢了。
nightfallrove 2003-11-06
  • 打赏
  • 举报
回复
楼上,
怎么会是同一个name呢
我用了循环,每次输入不同的name和num
可是在输出的时候就只有最后输入的那个记录了.
nightfallrove 2003-11-05
  • 打赏
  • 举报
回复
为什么ph[name]=num;会加不进呢?
byzxy 2003-11-05
  • 打赏
  • 举报
回复
用 path_back 试试.

24,854

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 工具平台和程序库
社区管理员
  • 工具平台和程序库社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧