2016-11-16 68 views
4

所以在代码中,我正在读来自用户的选项,然后再决定是否执行规定动作以下位:如何停止输入字符卡在缓冲区中? ç

printf("Do you want to execute %s: ", exe); 

char input = getchar(); 

if (input == 'y') { 
    return execute(exe); 
} return 0; 

我遇到的问题是该行char input = getchar()一个字符后(我假设输入密钥或换行符)卡在stdin中,并且从我的​​函数调用fgets()(从stdin读取)将消耗此卡住的字符,并且不会提示用户输入所需的内容。

现在我可以定义下面的函数来“吃”的任何杂散字符我,如果调用​​之前调用...

void iflush() { 
    int c; 

    while ((c = getchar()) != EOF && c != '\n') { 
     continue; 
    } 
} 

...这解决了这个问题。但我仍然想知道为什么这首先发生?是否有更合适的方式从得到没有造成这种流浪的性格,然后弄乱我的其他方法?我对C很陌生,很想确定我正在学习良好的习惯。

看起来很奇怪,我不得不添加一个辅助方法,即使很简单,以防止我的程序中的错误只是记录一些用户输入。我试过使用fgetc()也是同样的问题。

+0

你试过'fflush(stdin);'在你调用'getchar()'的语句之后? – VHS

+0

是啊,没有做任何事情 – transiti0nary

+5

@VHS你知道这是一个非常糟糕的建议吗? 'fflush(stdin);'调用未定义的行为。 –

回答

3

我还想知道为什么这是发生在第一个地方?

这是因为当你可以用字符%c(或fgetc()),它没有忽视AY的空白字符的输入流。 某些格式说明符(例如%d)会忽略输入流中留下的任何空格。所以,这不是问题。但%c不会忽略它。因此,你通常使用那些“吃”功能。

想象一下,如果你正在扫描一个空白字符(如空间,换行符等),你怎么能够使用scanf()来扫描它? 显然,有不同的和更好的方式,如使用fgets()

我对C很陌生,很想确定自己正在学习良好的习惯。

我的建议是完全避免scanf()。请使用fgets()来读取一行,然后使用sscanf()解析该行。请阅读:Why does everyone say not to use scanf? What should I use instead?

有一件事要注意有关fgets()是,如果你输入缓冲区有足够的空间,那么它会读取换行符为好, 你想避免在大多数用户输入。所以,你需要检查最后一个字符是否是换行符,然后删除它。

可以使用strcspn()功能,如实现这一目标:

char line[256]; 
if (fgets(line, sizeof line, stdin) == NULL) { 
    /* handle failure */ 
} 
line[strcspn(line, "\n")] = 0; /* remove the newline char if present */ 

如果你的主要兴趣是读书只是一个字符,那么阵列3个字符就足够了。仍然使用更大的缓冲区不会伤害:

char line[256]; 
char ch; 
if (fgets(line, sizeof line, stdin) == NULL) { 
    /* handle failure */ 
} 
if (sscanf(line, "%c", &ch) != 1) { 
    /* handle failure */   
} 
/* Now you can use 'ch' to check if it's 'y' */ 
+0

非常好,除了“只读一个字符,然后数组2个字符就足够了”。通常阅读一个'char',人们不会计算'\ n'。可能需要至少3个字符,换行符和空字符。建议缓冲区大小两倍,你认为最大值应该是。 256是很好的用户输入。 – chux

+0

如果缓冲区中没有空间,'fgets()'只会存储'\ n'。所以,2就足够了:1个字符和零字节。所以当读取一个字符(即使是换行符)时,2个字节的缓冲区大小已经足够了。 – usr

+0

没错,然而'\ n''仍然在'stdin'中用于下一个输入操作 - 如果一个用户在'“y \ n”'下只读取“一个”字符,OP似乎想避免这种情况。如果代码需要一次读取一个字符,包括'\ n'',只需使用'fgetc()' - 这会处理读取空字符,这对'fgets()'有问题。 – chux