简体   繁体   English

使用C ++ STL将C样式的字符串映射到int?

[英]Map C-style string to int using C++ STL?

Mapping of string to int is working fine. stringint映射工作正常。

std::map<std::string, int> // working

But I want to map C-style string to int 但是我想将C-style字符串映射到int

For example: 例如:

char A[10] = "apple";
map<char*,int> mapp;
mapp[A] = 10;

But when I try to access the value mapped to "apple" I am getting a garbage value instead of 10. Why it doesn't behave the same as std::string ? 但是,当我尝试访问映射到“苹果”的值时,我得到的是垃圾值而不是10。为什么它的行为与std::string

 map<char*,int> mapp; 

They key type here is not "c string" . 它们的键类型不是“ c string” At least not, if we define c string to be "an array of characters, with null terminator". 至少不是这样,如果我们将c字符串定义为“带有空终止符的字符数组”。 The key type, which is char* , is a pointer to a character object. 键类型为char* ,它是指向字符对象的指针。 The distinction is important. 区别很重要。 You aren't storing strings in the map. 您没有在地图中存储字符串。 You are storing pointers, and the strings live elsewhere. 您正在存储指针,并且字符串位于其他位置。

Unless you use a custom comparison function object, std::map uses operator<(const key_type&,key_type&) by default. 除非您使用自定义比较功能对象,否则默认情况下std::map使用operator<(const key_type&,key_type&) Two pointers are equal if, and only if they point to the same object. 当且仅当两个指针指向同一个对象时,它们才相等。

Here is an example of three objects: 这是三个对象的示例:

char A[] = "apple";
char B[] = "apple";
const char (&C)[6] = "apple"

First two are arrays, the third is an lvalue reference that is bound to a string literal object that is also an array. 前两个是数组,第三个是左值引用,该引用绑定到也是数组的字符串文字对象。 Being separate objects, their address is of course also different. 作为单独的对象,它们的地址当然也不同。 So, if you were to write: 因此,如果您要编写:

mapp[A] = 10;
std::cout << mapp[B];
std::cout << mapp[C];

The output would be 0 for each, because you hadn't initialized mapp[B] nor mapp[C] , so they will be value initialized by operator[] . 每个输出将为0,因为您尚未初始化mapp[B]mapp[C] ,因此它们将由operator[]进行值初始化。 The key values are different, even though each array contains the same characters. 即使每个数组包含相同的字符,键值也不同。

Solution: Don't use operator< to compare pointers to c strings. 解决方案:不要使用operator<来比较指向c字符串的指针。 Use std::strcmp instead. 使用std::strcmp代替。 With std::map , this means using a custom comparison object. 对于std::map ,这意味着使用自定义比较对象。 However, you aren't done with caveats yet. 但是,您尚未完成警告。 You must still make sure that the strings must stay in memory as long as they are pointed to by the keys in the map. 您仍然必须确保字符串必须保留在内存中,只要它们由映射中的键指向即可。 For example, this would be a mistake: 例如,这将是一个错误:

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

Solution: Take care of scope, or just use std::string . 解决方案:请注意范围,或仅使用std::string

It can be done but you need a smarter version of string: 可以做到,但是您需要更智能的string版本:

struct CString {
    CString(const char *str) {
        strcpy(string, str);
    }
    CString(const CString &copy); // 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;

But as you can likely see, this is a huge hassle. 但是,您可能会看到,这是一个巨大的麻烦。 There are probably some things that i have missed or overlooked as well. 可能有些事情我也错过或忽略了。

You could also use a comparison function: 您还可以使用比较功能:

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;

But there is a lot of external memory management, what happens if A s memory goes but the map remains, UB. 但是有很多外部内存管理,如果A s内存消失但映射仍然存在,UB会发生什么。 This is still a nightmare. 这仍然是一场噩梦。

Just use a std::string . 只需使用std::string

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM