C++ tolower/toupper 字符指针

C++ tolower/toupper char pointer

你们知道为什么下面的代码会在运行时崩溃吗?

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

我正在尝试将 char*(字符串)小写。我正在使用 visual studio.

谢谢

您无法将 itNULL 进行比较。相反,您应该将 *it'[=14=]' 进行比较。或者更好的是,使用 std::string 并且永远不用担心 :-)

总而言之,当遍历 C 风格的字符串时。你应该循环直到你看到的字符是一个'[=14=]'。迭代器本身永远不会是 NULL,因为它只是指向字符串中的一个位置。迭代器具有可以与 NULL 进行比较的类型这一事实是您不应直接接触的实现细节。

此外,您正在尝试写入字符串文字。这是一个禁忌:-)。

编辑: 正如@Cheers 和 hth 所指出的。 - Alf,tolower 可以在给定负值时中断。很遗憾,我们需要添加一个强制转换,以确保如果您向它提供 Latin-1 编码数据或类似数据,它不会中断。

这应该有效:

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

您将 word 设置为指向字符串文字,但文字是只读的,因此当您分配给 *it 时会导致未定义的行为。您需要在动态分配的内存中复制它。

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

同样在你的循环中你应该比较*it != '[=13=]'。字符串的结尾由字符表示为空字节,而不是指针为空。

给出的代码(我正在写这篇文章):

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

这段代码在两种不同的方式中有未定义的行为,如果只是文本数据略有不同,那么在第三种方式中也会有 UB:

  • 缓冲区溢出。
    继续条件 it != NULL 将不会是 false 直到指针 it 在地址范围的末尾回绕,如果是的话。

  • 正在修改只读内存。
    指针 word 设置为指向字符串文字的第一个 char,然后循环遍历该字符串并分配给每个 char.

  • 将可能的负值传递给 tolower
    char 分类函数需要非负参数,否则需要特殊值 EOF。在 ASCII 或无符号 char 类型的假设下,这适用于字符串 "HeLlo"。但总的来说,例如使用字符串 "Blåbærsyltetøy",直接将每个 char 值传递给 tolower 将导致传递负值; char 类型的 ch 的正确调用是 (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 ); }

关于如何使用空终止的 c 字符串和指针来解决您的问题,已经有两个不错的答案。为了完整起见,我向您推荐一种使用 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);

它正在崩溃,因为您正在修改字符串文字。

有专门的功能 采用 strupr 使字符串大写,strlwr 使字符串小写。

这是一个用法示例:

char str[ ] = "make me upper";
printf("%s\n",strupr(str));


char str[ ] = "make me lower";
printf("%s\n",strlwr (str));