3

我正在关注 Kernighan 和 Ritchie 的 C 书,但在处理字符串时遇到了一些困难。

在下面的代码中,似乎我的字符串虽然是从用户输入的,但在 null ( ) 字符getchar()之前包含额外的,我想说的是垃圾字符。\0

这是代码:

#include <stdio.h>
main() {

        char s[200];
        int c, i;

        printf("Enter input string:\n");
        for (i = 0; ( c = getchar()) != '\n'; i++) {
                s[i] = c;
        }   

        printf("Contents of input string:\n");
        for (i = 0; s[i] != '\0'; i++) {
                printf("%d: (%d) = ", i, s[i]);
                putchar(s[i]);
                printf("\n");
        }   

        return 0;
}

这是一个一个显示字符数组的每个元素的输出。这意味着以下内容:

Array_element: (ascii_number) = ascii_character

0: (72) = H
1: (101) = e
2: (108) = l
3: (108) = l
4: (111) = o
5: (32) =  
6: (87) = W
7: (111) = o
8: (114) = r
9: (108) = l
10: (100) = d
11: (33) = !
12: (-1) = ?
13: (127) = 

你看到元素 12 和 13 了吗?(元素 14 可能是空字符\0)。威士忌酒。探戈。狐步舞。

这是真正的关键,如果我将字符数组定义为只有100 个元素,而不是 200 个,那么输出是合理的。例如,如果我简单地替换

char s[200]char s[100]

那么输出如下:

0: (72) = H
1: (101) = e
2: (108) = l
3: (108) = l
4: (111) = o
5: (32) =  
6: (87) = W
7: (111) = o
8: (114) = r
9: (108) = l
10: (100) = d
11: (33) = !
12: (9) = 

(我仍然不确定换行符在哪里。那不是 ascii 字符#10吗?)

再次,威士忌探戈狐步舞。

这里发生了什么?

更新

因此,根据下面的答案,当我将字符数组的大小设置为 100 或 200 个元素时,输出的差异似乎真的是巧合——我只是在未初始化的内存中处理垃圾/噪声。

\0正如答案敏锐地表明的那样,我需要明确地终止我的数组。

4

3 回答 3

7

在本练习中,如果您希望输入后的字符串中存在空字符,那么您需要自己添加它。

您正在观察奇怪的字符,因为 C 中的变量和数组未初始化:它们可以包含任何垃圾值,可能包括随机放置的空字符。

当您更改数组大小时,您可能会观察到不同的输出,但不要期望任何合理的、预期的或可重复的行为——它是未定义的——因为这些数组值可以是任何东西。

于 2012-08-23T01:48:41.943 回答
3

您需要将空终止符 ( \0) 放在收到的字符串的末尾,以便在字符串末尾停止下一次检查。

否则,循环将进入垃圾内存。

于 2012-08-23T01:48:32.043 回答
1

您必须s[i] = '\0';在阅读完键盘输入后添加到您的程序中。否则,您的字符串将不正确。它不会包含“\0”终止字符。

这是更改后的代码:

#include <stdio.h> main() 
{         
 char s[200];        
 int c, i;        
  printf("Enter input string:\n");       
  for (i = 0; ( c = getchar()) != '\n'; i++)
 {               
  s[i] = c;        
 }     

s[i] = '\0';  //here, I added the '\0' character. (the only change i made in your code.)

  printf("Contents of input string:\n");      
   for (i = 0; s[i] != '\0'; i++) {        
         printf("%d: (%d) = ", i, s[i]);  
               putchar(s[i]);            
     printf("\n");       
  }           
  return 0;
 } 

2 - 字符串 s 的大小是 200,所以你必须关心缓冲区溢出:(for (i = 0; ( c = getchar()) != '\n' && i < 199 ; i++)最后一个字符是\0)。您还可以在读取输入字符时调整字符串的大小:

int size = 200;
char* s = malloc(size);
 for (i = 0; ( c = getchar()) != '\n'; i++)
 {  
   if(i >= size)
   {
      char* tmp = malloc(size + 200);
      memcpy(tmp , s , size);
      size += 200;
      free(s);
   }   

   s[i] = c;        
 }  

并且,在代码末尾添加:

free(s);// 当你不再需要它时释放最后创建的字符串。

于 2012-08-23T06:48:21.093 回答