使用scanf时getchar不会停止

时间:2012-09-29 15:11:31

标签: c getchar

我很难理解getchar()。在以下程序getchar按预期工作:

#include <stdio.h>


int main()
{
    printf("Type Enter to continue...");
    getchar();
    return 0; 
} 

但是,在以下程序中,getchar不会产生延迟,程序结束:

#include <stdio.h>

int main()
{
    char command[100];
    scanf("%s", command );
    printf("Type Enter to continue...");
    getchar();
    return 0; 
} 

我有以下可行的解决方法,但是我不明白为什么:

#include <stdio.h>

int main()
{
    char command[100];
    int i;
    scanf("%s", command );
    printf("Type Enter to continue...");
    while ( getchar() != '\n') {
      i=0; 
    }
    getchar();
    return 0;    
}

所以我的问题是:
  1. scanf在做什么?为什么scanf会这样做?   2.为什么我的工作在工作?   3.模拟以下Python代码的好方法是什么:

raw_input("Type Enter to continue")

5 个答案:

答案 0 :(得分:10)

输入仅在您输入换行符后发送到程序,但

scanf("%s", command );

将换行符保留在输入缓冲区中,因为%s (1)格式在某些非空格后遇到第一个空白字符时停止,getchar()然后返回该换行符立即生成,无需等待进一步输入。

您的解决方法有效,因为它会在再次调用getchar()之前清除输入缓冲区中的换行符。

要模拟行为,请在打印消息之前清除输入缓冲区,

scanf("%s", command);
int c;
do {
    c = getchar();
}while(c != '\n' && c != EOF);
if (c == EOF) {
    // input stream ended, do something about it, exit perhaps
} else {
    printf("Type Enter to continue\n");
    getchar();
}

(1)请注意,在%s中使用scanf非常不安全,您应该将输入限制为缓冲区可以使用字段宽度保存的内容{{ 1}}将最多99个(scanf("%99s", command))字符读入sizeof(command) - 1),为0终结符留出空间。

答案 1 :(得分:2)

Whitespace是5y3%s格式说明符的分隔符, newline 被视为空格,因此它保持缓冲。控制台输入通常是面向行的,因此随后对getchar()的调用将立即返回,因为“行”仍保持缓冲状态。

scanf("%s", command );
while( getchar() != '\n' ){ /* flush to end of input line */ }

同样,如果您使用getchar()或%c来获取单个字符,通常需要刷新该行,但在这种情况下输入的字符本身可能是换行符所以您需要稍微不同的解决方案:

scanf("%c", ch );
while( ch != '\n' && getchar() != '\n' ){ /* flush to end of input line */ }

类似于getchar():

ch = getchar();
while( ch != '\n' && getchar() != '\n' ){ /* flush to end of input line */ }

理所当然的事情是将这些解决方案包装成可以重复使用的独立专用输入函数,并将其用作放置常见输入验证和错误检查代码的地方(如Daniel Fischer的答案中明智地检查一样)对于EOF - 您通常希望避免在任何地方复制这些检查和错误处理。

答案 2 :(得分:2)

我宁愿先使用fgets,然后使用sscanf来解析输入。我很长一段时间都在做这样的事情,而且行为比使用普通scanf更容易预测。

答案 3 :(得分:-1)

好吧,我有更简单的事情:添加另一个getchar() ...问题已解决!!

答案 4 :(得分:-2)

在获取命令输入后刷新stdin。

fflush(stdin);

但是刷新输入流会导致未定义的行为(尽管Microsoft的C库将行为定义为扩展名)。