简体   繁体   English

为什么我在字符串的末尾总是得到多余的字符?

[英]Why do I keep getting extra characters at the end of my string?

I have the string, "helLo, wORld!" 我有字符串“ helLo,wORld!” and I want my program to change it to "Hello, World!". 我希望我的程序将其更改为“ Hello,World!”。 My program works, the characters are changed correctly, but I keep getting extra characters after the exclamation mark. 我的程序正常运行,字符正确更改,但是在感叹号之后,我仍然得到更多字符。 What could I be doing wrong? 我可能做错了什么?

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]);
      }
   }
}  

Extra random-ish characters at the end of a string usually means you've forgotten to null-terminate ( '\\0' ) your string. 字符串末尾的多余随机字符通常意味着您忘记了对字符串进行零终止( '\\0' )。 Your loop copies everything up to, but not including, the terminal null into the result. 循环将所有内容复制到结果中,但不包括终端null。

Add result[i] = '\\0'; 添加result[i] = '\\0'; after the loop before you return. 循环之后再返回。

Normally, you treat the isxxxx() functions (macros) as returning a boolean condition, and you'd ensure that you only have one of the chain of conditions executed. 通常,您将isxxxx()函数(宏)视为返回布尔条件,并确保只执行条件链之一。 You'd do that with more careful use of else clauses. 您可以更仔细地使用else子句来做到这一点。 Your code actually copies str[i] multiple times if it is a blank. 您的代码实际上是多次复制str[i]如果为空)。 In fact, I think you can compress your loop to: 实际上,我认为您可以将循环压缩为:

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';

If I put result[i] outside of the for loop, won't the compiler complain about i ? 如果我将result[i]放在for循环之外,那么编译器不会抱怨i吗?

Yes, it will. 是的,它会的。 In this context, you need i defined outside the loop control, because you need the value after the loop. 在这种情况下,你需要i的闭环控制之外定义的,因为你需要在循环后的值。 See the amended code above. 请参阅上面的修改代码。

You might also note that your pre-loop code quietly skips the first character of the string if it is not lower-case, leaving garbage as the first character of the result. 您可能还注意到,如果不是小写字母,则循环前代码会悄悄地跳过字符串的第一个字符,而将垃圾作为结果的第一个字符。 You should really write: 您应该真正写:

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

so that result[0] is always set. 因此总是设置result[0]

You are not null terminating result so when you print it out it will keep going until a null is found. 您不是空值终止result因此当您将其打印出来时,它将持续进行直到找到空值为止。 If you move the declaration of i to before the for loop: 如果将i的声明移到for循环之前:

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

you can add: 你可以加:

result[i] = '\0' ;

after the for loop, this is assuming result is large enough. for循环之后,这假设result足够大。

I took the liberty of simplifying your code as a lot of the checks you do are unnecessary. 我自由地简化了代码,因为您所做的许多检查都是不必要的。 The others have already explained some basic points to keep in mind: 其他人已经解释了一些基本注意事项:

#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;
}

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM