0

我有字符串,“helLo,wORld!” 我希望我的程序将其更改为“Hello, World!”。我的程序有效,字符更改正确,但感叹号后不断出现多余的字符。我可能做错了什么?

void normalize_case(char str[], char result[])
{
   if (islower(str[0]) == 1)
   {
      result[0] = toupper(str[0]);
   }

   for (int i = 1; str[i] != '\0'; i++)
   {
      if (isupper(str[i]) == 1)
      {
         result[i] = tolower(str[i]);
      }

      else if (islower(str[i]) == 1)
      {
         result[i] = str[i];
      }

      if (islower(str[i]) == 0 && isupper(str[i]) == 0)
      {
         result[i] = str[i];
      }

      if (str[i] == ' ')
      {
         result[i] = str[i];
      }

      if (str[i - 1] == ' ' && islower(str[i]) == 1)
      {
         result[i] = toupper(str[i]);
      }
   }
}  
4

4 回答 4

3

字符串末尾的额外随机字符通常意味着您忘记了空终止('\0')您的字符串。您的循环将所有内容复制到结果中,但不包括终端 null 。

result[i] = '\0';在返回之前在循环之后添加。

通常,您将isxxxx()函数(宏)视为返回布尔条件,并确保您只执行了一个条件链。您可以通过更谨慎地使用else子句来做到这一点。如果它是空白的,您的代码实际上会复制str[i]多次。实际上,我认为您可以将循环压缩为:

int i;

for (i = 1; str[i] != '\0'; i++)
{
   if (isupper(str[i]))
       result[i] = tolower(str[i]);
   else if (str[i - 1] == ' ' && islower(str[i]))
       result[i] = toupper(str[i]);
   else
       result[i] = str[i];
}
result[i] = '\0';

如果我放在result[i]for 循环之外,编译器不会抱怨i吗?

是的,它会的。在这种情况下,您需要i在循环控制之外定义,因为您需要循环之后的值。请参阅上面的修改后的代码。

您可能还注意到,如果字符串的第一个字符不是小写,您的循环前代码会悄悄地跳过它,将垃圾作为结果的第一个字符。你真的应该写:

result[0] = toupper(str[0]);

所以result[0]总是设置的。

于 2013-06-06T03:11:47.993 回答
2

您不是 null 终止result,因此当您将其打印出来时,它将继续运行,直到找到 null。如果将 to 的声明移到循环i之前:for

int i ;
for ( i = 1; str[i] != '\0'; i++)

你可以加:

result[i] = '\0' ;

for循环之后,这是假设result足够大。

于 2013-06-06T03:12:15.183 回答
1

result[i] = '\0'您应该在循环的末尾添加一条语句,因为在 C 语言中,字符串数组应该以特殊字符 '\0' 结尾,它告诉编译器“这是字符串的结尾”。

于 2013-06-06T05:45:15.357 回答
1

我冒昧地简化了您的代码,因为您所做的许多检查都是不必要的。其他人已经解释了一些要记住的基本要点:

#include <stdio.h> /* for printf */
#include <ctype.h> /* for islower and the like */

void normalise_case(char str[], char result[])
{
    if (islower(str[0]))
    {
        result[0] = toupper(str[0]); /* capitalise at the start */
    }

    int i; /* older C standards (pre C99) won't like it if you don't pre-declare 'i' so I've put it here */

    for (i = 1; str[i] != '\0'; i++)
    {
        result[i] = str[i]; /* I've noticed that you copy the string in each if case, so I've put it here at the top */

        if (isupper(result[i]))
        {
            result[i] = tolower(result[i]);
        }

        if (result[i - 1] == ' ' && islower(result[i])) /* at the start of a word, capitalise! */
        {
            result[i] = toupper(result[i]);
        }

    }

    result[i] = '\0'; /* this has already been explained */
}

int main()
{
    char  in[20] = "tESt tHIs StrinG";

    char out[20] = ""; /* space to store the output */

    normalise_case(in, out);

    printf("%s\n", out); /* Prints 'Test This String' */

    return 0;
}
于 2013-06-06T03:40:35.427 回答