接收输入时出错

时间:2012-01-10 03:03:34

标签: c

我经常看到在一系列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!

4 个答案:

答案 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终止符留出了空间。

修改:某些来源(例如thisthis)表示您应该避免调用fflush(stdin),这是不正确的。 然而Linux man page州:

  
    

对于输入流,fflush()会丢弃从底层文件中提取但尚未被应用程序使用的任何缓冲数据。

         

符合C89,C99,POSIX.1-2001,POSIX.1-2008。     标准未指定输入流的行为。大多数其他实现与Linux的行为相同。

  

另外MSDN除了以下内容之外没有提及fflush(stdin)

  
    

如果流打开输入,fflush将清除缓冲区的内容。

  

有人会认为,如果调用fflush(stdin)是一个问题,那么fflush上两个最大的文档来源之一就会提到这一点。