C ++ tolower / toupper char char

Ребята, вы знаете, почему следующий код вылетает во время выполнения?

char* word;
word = new char[20];
word = "HeLlo";
for (auto it = word; it != NULL; it++){
*it = (char) tolower(*it);

Я пытаюсь строчные буквы * (строка). Я использую визуальную студию.

Спасибо

0

Решение

Вы не можете сравнить it в NULL, Вместо этого вы должны сравнивать *it в '\0', Или еще лучше, используйте std::string и никогда не переживай об этом 🙂

Таким образом, при цикле по строке в стиле C. Вы должны быть в цикле, пока персонаж вы видите это '\0', Сам итератор никогда не будет NULL, поскольку он просто указывает место в строке. Тот факт, что итератор имеет тип, который можно сравнить с NULL это деталь реализации, которую вы не должны касаться напрямую.

Кроме того, вы пытаетесь записать строковый литерал. Что нет-нет :-).

РЕДАКТИРОВАТЬ:
Как отмечено @Cheers и hth. — Альф, tolower может сломаться, если даны отрицательные значения. К сожалению, нам нужно добавить приведение, чтобы оно не сломалось, если вы передадите ему данные в кодировке Latin-1 или аналогичные.

Это должно работать:

char word[] = "HeLlo";
for (auto it = word; *it != '\0'; ++it) {
*it = tolower(static_cast<unsigned char>(*it));
}
6

Другие решения

Вы устанавливаете word указывать на строковый литерал, но литералы доступны только для чтения, поэтому при назначении *it, Вам необходимо сделать копию этого в динамически распределенной памяти.

char *word = new char[20];
strcpy(word, "HeLlo");

Также в вашем цикле вы должны сравнить *it != '\0', Конец строки обозначается символом, являющимся нулевым байтом, а не указателем, являющимся нулевым.

4

Данный код (как я пишу это):

char* word;
word = new char[20];
word = "HeLlo";
for (auto it = word; it != NULL; it++){
*it = (char) tolower(*it);

Этот код имеет Неопределенное поведение 2 различными способами, и UB также будет иметь третий способ, если только текстовые данные будут немного отличаться:

  • Переполнение буфера.
    Условие продолжения it != NULL не будет false пока указатель it обернул в конце диапазона адресов, если это так.

  • Модификация только для чтения памяти.
    Указатель word установлен, чтобы указать на первый char строкового литерала, а затем цикл перебирает эту строку и присваивает каждому char,

  • Передача возможного отрицательного значения в tolower,
    char классификационным функциям требуется неотрицательный аргумент или специальное значение EOF, Это прекрасно работает со строкой "HeLlo" в предположении ASCII или без знака char тип. Но в целом, например со строкой "Blåbærsyltetøy", проходя мимо каждого char значение для tolower приведет к передаче отрицательных значений; правильный вызов с ch типа char является (char) tolower( (unsigned char)ch ),

Кроме того, код имеет утечка памяти, выделив немного памяти с new а потом просто забываешь об этом.

Правильный способ кодирования очевидного намерения:

using Byte = unsigned char;

auto to_lower( char const c )
-> char
{ return Byte( tolower( Byte( c ) ) ); }

// ...
string word = "Hello";
for( char& ch : word ) { ch = to_lower( ch ); }
2

Уже есть два хороших ответа о том, как решить ваши проблемы, используя завершенные нулем c-строки и poitners. Для полноты картины я предлагаю вам подход, использующий строки c ++:

string word;           // instead of char*
//word = new char[20]; // no longuer needed: strings take care for themseves
word = "HeLlo";        //  no worry about deallocating previous values: strings take care for themselves
for (auto &it : word)  // use of range for, to iterate through all the string elements
it = (char) tolower(it);
1

Это сбой, потому что вы модифицируете строковый литерал.

1

для этого есть специальные функции
использование
strupr для создания строки в верхнем регистре и strlwr для создания строки в нижнем регистре.

Вот пример использования:

char str[ ] = "make me upper";
printf("%s\n",strupr(str));char str[ ] = "make me lower";
printf("%s\n",strlwr (str));
0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector