我对C很新,很抱歉,如果这是一个愚蠢的问题,但是当我运行以下代码时:
#include <stdio.h>
int main () {
int i;
int test[10];
char string[81];
for(i = 0; i < 10; i++){
scanf("%d", &test[i]);
}
for(i=0; i < 7; i++){
gets(string);
printf("String was entered\n");
}
}
输入任意10位数字,即使我没有在命令窗口中输入字符串,也会打印“输入字符串”行。有谁能解释为什么?有没有办法阻止它发生?
谢谢!
答案 0 :(得分:4)
使用scanf
读入数据后,换行符仍然位于输入队列中等待读取。 gets
读取该换行符并停止(因为它已到达该行的末尾!)
请注意使用gets
一个坏主意:它无法限制读取缓冲区中的字符数,因此如果输入的字符多于将适合缓冲区,您将最终溢出缓冲区,导致数据损坏,应用程序崩溃,巨大的安全漏洞和/或任何其他不可预测的结果。为了安全起见,您可以使用fgets
代替stdin
:
fgets(string, sizeof(string), stdin);
(请注意,您可能希望使用某种符号常量作为string
的大小,以便您不会在多个位置重复它 - 或者在数组中使用sizeof(string)
定义是可见的。)
答案 1 :(得分:3)
猜测,scanf()
没有消耗你必须输入的换行符,这样它就可以处理你想要在字符串之前获得的十个整数。因此,在最后一次调用scanf()
之后,gets()
面临一个以换行符开头的输入缓冲区。 Presto,它已满足其规范,因此它不会复制到缓冲区并返回。
通常,scanf()
和gets()
是新代码的不良选择。它们都有一些问题会使它们使用起来很痛苦,甚至根本不会使用它们。
具体来说,gets()
没有也无法检查其输出缓冲区大小,因此很容易覆盖其缓冲区后发生的任何内存。这种方式是全球国家或堆栈的腐败。如果它是堆栈,则可以利用它来获得对程序的控制并使其执行任意代码。这不是一件好事。
最好使用fgets()
来使用输入流,它对缓冲区大小有限制,并在读取后用sscanf()
和其他函数解析它。
答案 2 :(得分:0)
以下代码可以使用
#include <stdio.h>
int main () {
int i;
int test[10];
char string[81],s[1];
for(i = 0; i < 10; i++){
scanf("%d", &test[i]);
}
gets(s);
for(i=0; i < 7; i++){
gets(string);
printf("String was entered\n");
}
}
char数组[1]用于捕获scanf未经过修改的换行符