将C中字符串中单词的首字母大写

Capitalize first letter of a word in a string in C

我必须将每个单词的首字母大写(单词由 space 分隔)到给定的 char 数组中。我写了代码,但我不明白为什么它不起作用,也没有在输出中显示任何内容。

代码如下:

void LetterCapitalize(char *str) {
    char *str2;
    int i = 0;
    str2[i] = toupper(str[0]);
    i++;
    while (str[i]) {
        if (str[i] == ' ') {
            str2[i] = str[i];
            str2[i + 1] = toupper(str[i] + 1);
            i += 2;
        } else {
            str2[i] = str[i];
            i++;
        }
    }
    printf ("%s", str2);
}

这是主要内容:

int main(void) {
    char stringa[16] = "some string here";
    LetterCapitalize(stringa);
    return 0;
}

对于初学者这个数组

char stringa[16] = "some string here";

不包含字符串,因为它没有 space 来容纳用作初始值设定项的字符串文字的终止零字符 '[=17=]'

如果不显式指定其大小,最好按以下方式声明它

char stringa[] = "some string here";

所以这个 while 循环

while (str[i])

可以调用未定义的行为。

你还使用了未初始化的指针str2

char *str2;
//...
str2[i] = toupper (str[0]);

再次调用未定义的行为。

注意,传递的字符串可以包含多个 space 之间的单词,而且可以包含前导和尾随 space s。因此,由于跳过源字符串

的终止零字符 '[=17=]',此 if 语句也可以调用未定义的行为
    if (str[i] == ' ')
    {

      str2[i] = str[i];
      str2[i + 1] = toupper (str[i] + 1);
      i += 2;
    }

因此您的方法通常是错误的。

这样的函数应该return修改后的源字符串。

最好使用标准 C 函数 strspnstrcspn.

而不是 for 循环

这是一个演示程序。

#include <string.h>
#include <stdio.h>
#include <ctype.h>

char * LetterCapitalize( char *s )
{
    const char *delim = " \t";

    for (char *p = s; *p; p += strcspn( p, delim ) )
    {
        p += strspn( p, delim );

        if (*p) *p = toupper( ( unsigned char )*p );
    }

    return s;
}

int main( void )
{
    char stringa[] = "some string here";
    puts( stringa );
    puts( LetterCapitalize( stringa ) );
}

程序输出为

some string here
Some String Here

存在多个问题:

  • main中定义的字符串不是空终止符,因为初始化器恰好有16个字符,即数组定义的长度,所以没有space作为空终止符。省略数组长度并让编译器从初始化程序计算它更安全,包括空终止符:
   char stringa[] = "some string here";  // sizeof stringa == 17
  • str2 未初始化:将字符存储到其中具有未定义的行为。您可以改为修改参数字符串或分配一个副本并修改它。

  • LetterCapitalize 中的逻辑是有风险的:您假设单词由单个 space 分隔并且字符串不以 space 结尾。

  • toupper()char 参数应转换为 (unsigned char) 以避免在类型为 char 默认签名。

这是修改后的版本:

#include <ctype.h>
#include <stdio.h>

char *LetterCapitalize(char *str) {
    unsigned char c, last = ' ';
    // uppercase characters that follow a space or at the start of the string
    for (size_t i = 0; (c = str[i]) != '[=11=]'; last = c, i++) {
        if (last == ' ')
            str[i] = toupper(c);
    }
    return str;
}

int main() {
    char stringa[] = "some string here";
    puts(LetterCapitalize(stringa));
    return 0;
}