即使使用fflush(stdin),程序也不会在scanf()之后执行gets()

在浪费了太多时间搜索为什么我的程序在使用scanf()之后没有执行gets()时,我找到了一个解决方案,即在scanf()之后使用fflush(stdin)来使gets()获得一个字符串。

问题是fflush(stdin)没有做到预期的结果:程序继续跳过gets(),我不能在控制台中写任何短语来读取。

我的代码是下一个:

#include  #include  int main(){ char nombre[10]; char mensaje[80]; printf("Type your name:\n"); scanf("%s", nombre); fflush(stdin); printf("Now, type a message:\n"); gets(mensaje); printf("3/%s:%s",nombre,mensaje); return 0; } 

如果刷新std不起作用,那么尝试读取额外的字符并丢弃,如此处所示 。

这将有效:

 #include  #include  int main(){ char nombre[10]; char mensaje[80]; int c; printf("Type your name:\n"); scanf("%9s", nombre); while((c= getchar()) != '\n' && c != EOF) /* discard */ ; printf("Now, type a message:\n"); gets(mensaje); printf("%s:%s",nombre,mensaje); return 0; } 

两个重大问题:

  1. 不要在输入流上使用fflush ; 未定义fflush对输入流的行为。 仅仅因为它似乎在这种情况下起作用并不意味着它是正确的。

  2. 永远不会永远不会永远不会使用gets – 它在C99标准中被弃用,并且已完全从C2011标准中删除。 它将(不会, 将会 )在您的代码中引入一个主要的失败点。

使用gets调用跟踪scanf调用永远不是一个好主意,因为gets不会跳过scanf在输入流中留下的任何前导换行符。 使用scanf读取nombremesaje

 printf("Type your name:\n"); scanf("%9s", nombre); printf("Now, type a message:\n"); scanf("%79s", mensaje); 

%s%[scanf调用中使用显式长度说明符是个好主意,否则你会引入相同的安全漏洞。

编辑

D’哦。 我是个白痴。 如果您尝试读取包含空格的字符串,则无法使用%s转换说明符。 请改用%[转换说明符:

 scanf( "%79[^\n]", mensage ); 

这将读取接下来的79个字符或换行符,以先到者为准,并在输入流中保留换行符。

试试这个:

 scanf("%s\n", nombre); 

scanf在读取零件时停在空白处。 获取读取直到第一个新行。 所以会发生什么是scanf在缓冲区中留下一个换行符,它会立即看到并认为它被赋予一个空行。

如果您使用原始代码并输入“名称消息”,两行全部在一行上,您可以看到此操作 – 获取仍将立即返回,但它将看到第二部分。

scanf中的\ n告诉它继续使用它。

尝试gets(stdin); 代替

 fflush(stdin); 
 while (fgetc(stdin) != '\n'); // seems to work