即使使用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; }
两个重大问题:
-
不要在输入流上使用
fflush
; 未定义fflush
对输入流的行为。 仅仅因为它似乎在这种情况下起作用并不意味着它是正确的。 -
永远不会永远不会永远不会使用
gets
– 它在C99标准中被弃用,并且已完全从C2011标准中删除。 它将(不会, 将会 )在您的代码中引入一个主要的失败点。
使用gets
调用跟踪scanf
调用永远不是一个好主意,因为gets
不会跳过scanf
在输入流中留下的任何前导换行符。 使用scanf
读取nombre
和mesaje
。
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