我经常看到在一系列printf语句中要求输入的情况 语句不接受输入,即
printf_statement1:
printf_statement2: /*Enter input here*/
即。在用户输入 statement1 的输入之前,打印 statement2 ,允许用户输入输入,然后使用 statement3 重复输入&安培; 即statement4
是什么促使这种情况?
我遇到了这个,但不再是,在:
printf("\n\n\t\tName: ");
scanf("%s", name); //initially used gets
printf("\n\n\t\tType: ");
scanf("%c", &type);
printf("\n\n\t\tAddress: "); //initially used gets
scanf("%s", address);
printf("\n\n\t\tDate - of - Birth: ");
scanf("%s", dob); //initially used gets
输出:
Name:
Type: I enter something!
Address:
Date - of - Birth: I enter something!
答案 0 :(得分:4)
我知道这个问题已经标记为已回答,但由于fflush(stdin)
让我感到畏缩,我想发布一个清除stdin
的替代方案:
void clear_stdin(void)
{
int c;
do {
c = fgetc(stdin);
} while (c != '\n' && c != EOF);
}
这将清除所有char
,直到遇到新行或EOF
为止。 (您可以将do..while
的主体和条件粘贴到while
循环的条件中,但我更喜欢这样写。)
在想要读入单个char
之后调用该函数是有用的,以防止在用户输入多于1个字符时似乎跳过后续提示。
另请考虑使用fgets()
或使用scanf()
提供宽度说明符以防止溢出。
答案 1 :(得分:2)
在“Jonathon Reinhart”答案中替换fflush(stdin),我建议这个功能符合标准:
void clean_stdin(void)
{
int c;
do {
c = getchar();
} while (c != '\n' && c != EOF);
}
答案 2 :(得分:0)
问题的根源是"%c"
转换说明符不会跳过空格。假设您输入“Joe”作为名称;输入流将包含字符'J','o','e','\ n'。第一次调用scanf
会查找字符串("%s"
转换说明符);它将使用'J','o'和'e',并在输入流中保留'\ n'。在响应下一个提示时,键入一个类似'A'的字符,因此输入流现在包含'\ n','A','\ n'。下一次调用scanf
会查找单个字符;它将消耗第一个换行符并返回,在输入流中留下“A”和“\ n”。
最好不要使用stdin
转换说明符进行交互式输入,而不是刷新"%c"
(不根据语言定义定义明确的操作) ;坦率地说,最好避免使用scanf
进行交互式输入,而是使用fgets
。
快速而肮脏的解决方案是将type
的类型从简单的char
更改为char
的数组,并将其作为字符串读取:
char type[2];
...
fgets(type, sizeof type, stdin);
这将跳过输入流中的任何新行,而不必刷新任何内容。然后,您只需使用type[0]
作为类型值。
修改强>
如果您不想更改type
的类型,可以执行以下操作:
#include <ctype.h>
...
while ((type = fgetc(stdin)) && isspace(type))
;
将从stdin
读取单个字符,直到看到非空格字符。
答案 3 :(得分:-6)
有时候在这些情况下,在fflush()
之前致电stdin
会有所帮助:
char name[40+1];
printf("\n\tName: ");
fflush(stdin);
scanf("%40s", name);
根据具体情况,输入缓冲区中可能会有一个换行符导致第一个scanf
被跳过(没有输入)。
另请注意,您应在scanf
中指定缓冲区的大小,以避免buffer overflows。
scanf的格式说明符如下所示:
%[*][width][modifiers]type
width:指定当前读取操作中要读取的最大字符数
因此,%40s
指定只能将40个字符读入字符串。请注意,缓冲区为41个字符,为NULL终止符留出了空间。
修改:某些来源(例如this和this)表示您应该避免调用fflush(stdin)
,这是不正确的。 然而,Linux man page州:
对于输入流,fflush()会丢弃从底层文件中提取但尚未被应用程序使用的任何缓冲数据。
符合C89,C99,POSIX.1-2001,POSIX.1-2008。 标准未指定输入流的行为。大多数其他实现与Linux的行为相同。
另外:MSDN除了以下内容之外没有提及fflush(stdin)
:
如果流打开输入,fflush将清除缓冲区的内容。
有人会认为,如果调用fflush(stdin)
是一个问题,那么fflush
上两个最大的文档来源之一就会提到这一点。