Scanf会不自觉地擦除字符数组。

3
请参见以下程序:
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>

main(void){
  printf("Array concatenateor\n-------------------------\n");

  //declarations
  char s1[50],s2[50],s3[50];
  short int n=0;

  //Array initialisation
  printf("Array 1: ");
  gets(s1);
  printf("Array 2: ");
  gets(s2);

  strcpy(s3, s1); //asure initial form of s1 in s3
  strcat(s1, s2); //concatenate s1 with s2  
  //at this point s1 is in the concatenation form and s3 is s1's initial form

  printf("Arrays concatenated with STRCPY: \"%s\"\n", s1); //print concatenation, s3 ok
  printf("Number of characters to concatenate: "); //scan number, s3 ok
  scanf("%d",&n); //beyond this point s3 becomes null... peculiar
  printf("S3: %s\n",s3);    //this is the proof of s3 being null
  strncat(s3,s2,n); //s3 concatenates with n chars of s2
  printf("Arrays concatenated with STRNCAT(%d chars): %s\n", n, s3);  //print s3
  system("PAUSE");
  return 0;
}

有趣的是,特定的scanf在没有明示的情况下擦除了s3数组。这是为什么呢?


1
请在术语上更加准确。数组并不会“变成null”;null只是指针的一种状态,而数组的内存仍然存在。发生的是缓冲区现在看起来包含一个空字符串,即其第一个字符被设置为'\0'。(ASCII NUL或“null字节”'\0'不应与NULL指针值混淆。) - Karl Knechtel
2个回答

4

尝试将“n”更改为“int”,而不是“short int”,运行它,看看是否可以解决问题。如果可以,我会解释原因。

正如Soren指出的那样,scanf期望读取32位数据;当缓冲区仅为16位时,额外的内存被移动到不应该存在的地方,从本质上讲清零了内存(假设用户输入的数字足够小)。


1
%d 需要一个指向整数的指针,但你给了它一个比那更短的东西的指针,因此破坏了栈。如果你确实想把一些东西读到 'short'中,那么请阅读scanf手册以获取正确的%%字符串。 - Soren
1
啊,索伦...我会告诉他的。只是我不确定那是不是出了问题的全部。 - Patrick87
@Soren:哦...没注意到...不错! - zw324
2
哦,忘记将格式说明符调整为SHORT INT了...应该在scanf中尝试%hd(也可以工作)。无论如何,感谢您的反馈。 - andreihondrari
@Thomas Carpenter:如果用户输入一个更大的数字,那么会发生什么?这个输入会将字符串修改成其他什么东西吗? - andreihondrari

4

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接