在null字符之前的这些附加字符是什么?

时间:2012-08-23 01:44:57

标签: c ascii getchar

我正在关注Kernighan和Ritchie的C书,但我在使用字符串方面遇到了一些困难。

在下面的代码中,我看到我的字符串在用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显式终止我的数组,因为答案清楚地表明了这一点。

3 个答案:

答案 0 :(得分:7)

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

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

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

答案 1 :(得分:3)

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

否则,循环将进入垃圾记忆库。

答案 2 :(得分: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); //当你不再需要它时,释放最后创建的字符串。