2

如果这是一个愚蠢的问题,我对 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 位数字,即使我没有在命令窗口中输入字符串,也会打印“输入字符串”行。谁能解释为什么?有没有办法阻止它发生?

谢谢!

4

3 回答 3

4

使用 读入数据后scanf,换行符仍位于输入队列中等待读取。 gets读取换行符并停止(因为它已到达行尾!)

请注意,使用它是一个坏主意gets:它无法限制读取到缓冲区的字符数,因此如果您输入的字符数超过缓冲区的容量,最终会溢出缓冲区,导致数据损坏、应用程序崩溃、巨大的安全漏洞和/或任何数量的其他不可预测的结果。为了安全起见,您可以使用fgetswith 代替stdin

fgets(string, sizeof(string), stdin);

(请注意,您可能希望使用某种符号常量来表示大小,string这样您就不会在多个地方重复它 - 或者sizeof(string)在数组定义可见时使用。)

于 2010-09-18T01:19:22.710 回答
3

猜测一下,scanf()没有使用您必须输入的换行符,以便它可以处理您想要在字符串之前获取的十个整数。因此,在最后一次调用 之后scanf()gets()将面临一个以换行符开头的输入缓冲区。Presto,它已经满足了它的规范,所以它没有复制任何东西到它的缓冲区并返回。

一般来说,对于新代码来说scanf()gets()这是糟糕的选择。它们都有一些问题,使它们难以正确使用,甚至使用起来很危险。

具体来说,gets()它不会也无法检查其输出缓冲区大小,因此它将很容易覆盖恰好位于其缓冲区之后的任何内存。那就是全局状态或堆栈的损坏。如果是堆栈,则可以利用它来控制程序并使其执行任意代码。那不是一件好事。

最好使用fgets()对其缓冲区大小有限制的输入流,并在sscanf()读取后使用其他函数解析它。

于 2010-09-18T01:25:07.860 回答
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 数组 s[1] 用于捕获 scanf 未处理的换行符

于 2015-03-14T11:01:28.550 回答