[英]Map C-style string to int using C++ STL?
string
到int
映射工作正常。
std::map<std::string, int> // working
但是我想将C-style
字符串映射到int
例如:
char A[10] = "apple";
map<char*,int> mapp;
mapp[A] = 10;
但是,当我尝试访问映射到“苹果”的值时,我得到的是垃圾值而不是10。为什么它的行为与std::string
?
map<char*,int> mapp;
它们的键类型不是“ c string” 。 至少不是这样,如果我们将c字符串定义为“带有空终止符的字符数组”。 键类型为char*
,它是指向字符对象的指针。 区别很重要。 您没有在地图中存储字符串。 您正在存储指针,并且字符串位于其他位置。
除非您使用自定义比较功能对象,否则默认情况下std::map
使用operator<(const key_type&,key_type&)
。 当且仅当两个指针指向同一个对象时,它们才相等。
这是三个对象的示例:
char A[] = "apple";
char B[] = "apple";
const char (&C)[6] = "apple"
前两个是数组,第三个是左值引用,该引用绑定到也是数组的字符串文字对象。 作为单独的对象,它们的地址当然也不同。 因此,如果您要编写:
mapp[A] = 10;
std::cout << mapp[B];
std::cout << mapp[C];
每个输出将为0,因为您尚未初始化mapp[B]
或mapp[C]
,因此它们将由operator[]
进行值初始化。 即使每个数组包含相同的字符,键值也不同。
解决方案:不要使用operator<
来比较指向c字符串的指针。 使用std::strcmp
代替。 对于std::map
,这意味着使用自定义比较对象。 但是,您尚未完成警告。 您仍然必须确保字符串必须保留在内存中,只要它们由映射中的键指向即可。 例如,这将是一个错误:
char A[] = "apple";
mapp[A] = 10;
return mapp; // oops, we returned mapp outside of the scope
// but it contains a pointer to the string that
// is no longer valid outside of this scope
解决方案:请注意范围,或仅使用std::string
。
可以做到,但是您需要更智能的string版本:
struct CString {
CString(const char *str) {
strcpy(string, str);
}
CString(const CString ©); // Copy constructor will be needed.
char string[50]; // Or char * if you want to go that way, but you will need
// to be careful about memory so you can already see hardships ahead.
bool operator<(const CString &rhs) {
return strcmp(string, rhs.string) < 0;
}
}
map<CString,int> mapp;
mapp["someString"] = 5;
但是,您可能会看到,这是一个巨大的麻烦。 可能有些事情我也错过或忽略了。
您还可以使用比较功能:
struct cmpStr{
bool operator()(const char *a, const char *b) const {
return strcmp(a, b) < 0;
}
};
map<char *,int> mapp;
char A[5] = "A";
mapp[A] = 5;
但是有很多外部内存管理,如果A
s内存消失但映射仍然存在,UB会发生什么。 这仍然是一场噩梦。
只需使用std::string
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.