将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 函数 strspn
和 strcspn
.
而不是 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;
}
我必须将每个单词的首字母大写(单词由 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 函数 strspn
和 strcspn
.
这是一个演示程序。
#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;
}