mapp;mapp[A] = 10;Но когда я пытаюсь получить доступ к значению, сопоставленн" />

Отобразить строку в стиле C в int с использованием C ++ STL?

c++ string dictionary stl

662 просмотра

2 ответа

859 Репутация автора

Отображение 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?

Автор: cryptomanic Источник Размещён: 18.07.2016 10:20

Ответы (2)


0 плюса

19904 Репутация автора

Это можно сделать, но вам нужна более умная версия строки:

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;

Но, как вы, вероятно, видите, это огромные хлопоты. Вероятно, есть некоторые вещи, которые я пропустил или упустил из виду.

Вы также можете использовать функцию сравнения:

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память уходит, а карта остается, UB. Это все еще кошмар.

Просто используйте std::string.

Автор: Fantastic Mr Fox Размещён: 18.07.2016 10:51

4 плюса

112065 Репутация автора

Решение
map<char*,int> mapp;

Тип ключа здесь не является "строкой" . По крайней мере, нет, если мы определим строку c как «массив символов с нулевым терминатором». Тип ключа, который char*является указателем на символьный объект. Различие важно. Вы не храните строки на карте. Вы храните указатели, а строки живут в другом месте.

Если вы не используете пользовательский объект функции сравнения, std::mapиспользуется operator<(const key_type&,key_type&)по умолчанию. Два указателя равны тогда и только тогда, когда они указывают на один и тот же объект.

Вот пример трех объектов:

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

Первые два - это массивы, третья - это ссылка на lvalue, которая связана со строковым литералом, который также является массивом. Будучи отдельными объектами, их адрес, конечно, также отличается. Итак, если вы должны были написать:

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.

Автор: eerorika Размещён: 18.07.2016 10:53
Вопросы из категории :
32x32