Scanf在C中跳过每一个while循环

我正在尝试开发一个简单的基于文本的hang子手游戏,主游戏循环以提示input每个字母的猜测开始,然后继续检查字母是否在单词中,如果是不是。 但是,当我运行游戏时,提示每次出现两次,程序不会等待用户的input。 它也是一种生活(如果是正确的input,则是一种生活,如果不是,则两种),所以不pipeinput与之前的input是不一样的。 这是我的游戏循环,简化了一下:

while (!finished) { printf("Guess the word '%s'\n",covered); scanf("%c", &currentGuess); i=0; while (i<=wordLength) { if (i == wordLength) { --numLives; printf("Number of lives: %i\n", numLives); break; } else if (currentGuess == secretWord[i]) { covered[i] = secretWord[i]; secretWord[i] = '*'; break; } ++i; } j=0; while (j<=wordLength) { if (j == (wordLength)) { finished = 1; printf("Congratulations! You guessed the word!\n"); break; } else { if (covered[j] == '-') { break; } } ++j; if (numLives == 0) { finished = 1; } } } 

我认为这个问题是scanf认为它是在什么时候没有,但我不知道为什么。 有没有人有任何想法? 我在Mac OS X 10.5上使用gcc 4.0.1。

当用scanf()读取键盘input时,在input被按下后input被读取,但是由enter键生成的换行符没有被scanf()调用消耗。 这意味着下一次您从标准input读取将有一个换行符等待您(这将使下一个scanf()调用立即返回没有数据)。

为了避免这种情况,你可以修改你的代码,如下所示:

 scanf("%c%*c", &currentGuess); 

%*c匹配单个字符,但星号表示该字符不会被存储在任何地方。 这会消耗由input键生成的换行符,以便下一次调用scanf()您将以空input缓冲区开始。

警告:如果用户按下两个键然后按下Enter键, scanf()将返回第一个按键,吃掉第二个按键,并保留下一个input呼叫的换行符。 像这样的怪癖是为什么scanf()和朋友被许多程序员避免的原因之一。

换行。

第一次通过循环,scanf()读取字符。 然后它读取换行符。 然后它读取下一个字符; 重复。

怎么修?

我很less使用scanf(),但是如果使用格式化string"%.1s" ,它应该跳过空格(包括换行符),然后读取非空白字符。 但是,它会期待一个字符数组而不是单个字符:

 char ibuff[2]; while ((scanf("%.1s", ibuff) == 1) { ... } 

把问题分解成更小的部分:

 int main(void) { char val; while (1) { printf("enter val: "); scanf("%c", &val); printf("got: %d\n", val); } } 

这里的输出是:

 enter val: g got: 103 enter val: got: 10 

为什么scanf会在那里再给你一个'10'?

由于我们打印的ASCII码是我们的值,因此ASCII中的“10”是“enter”,所以scanf也必须把“enter”键作为一个字符。

果然,看着你的scanfstring,你每次都在循环中要求单个字符。 控制字符也被认为是字符,将被拿起。 例如,您可以在上面的循环中按“esc”,然后“enter”并获得:

 enter val: ^[ got: 27 enter val: got: 10 

只是一个猜测,但是你正在用scanfinput一个单独的字符,但是用户必须input猜测加上一个换行符,这个换行符正在作为一个单独的猜测字符被使用。

 scanf(" %c", &fooBar); 

注意%c之前的空格。 这很重要,因为它匹配所有前面的空格。

吉姆和乔纳森说得对。

为了让你的scanf行做你想做的(消耗换行符,不要把它放在缓冲区中),我会改变它

 scanf("%c\n", &currentGuess); 

(注意\n

虽然这个error handling是残酷的。 至less应该检查scanf的返回值1,如果没有返回,则忽略input(带有警告)。

我注意到了几点:

  • scanf("%c")将读取1个字符,并在下一次循环中将ENTER保留在input缓冲区中
  • 即使从用户读取的字符与secretWord字符中的字符不匹配, i也正在递增
  • 什么时候covered[j]永远成为' – '?

我猜想:当你input数据时,你的代码将把新行当作猜测之一。 由于无法控制的error handling,我一直避免使用* scanf()系列。 尝试使用fgets(),然后拔出第一个字符/字节。

我在代码中看到了一些东西:

  1. scanf返回它读取的项目数。 您可能会想要处理返回0或EOF的情况。
  2. 我的猜测是用户正在打字+ Enter,并且你得到换行符作为第二个字符。 一个简单的方法来检查将添加一个debuggingprintf语句来显示input的字符。
  3. 你的代码只会匹配匹配字母的第一个匹配项,也就是说,如果单词是“test”,而用户input了“t”,那么你的代码只会匹配第一个“t”,而不是两个匹配。 你需要调整你的第一个循环来处理这个问题。

input字符时,必须input空格字符才能继续。 该空格字符存在于input缓冲区stdin文件中,并由scanf()函数读取。 这个问题可以通过消耗这个额外的字符来解决。 这可以通过使用getchar()函数来完成。

的scanf( “%C”,&currentGuess);
的getchar(); //消耗空白字符。

我宁愿build议你避免使用scanf(),而是使用getchar()。 scanf()需要大量的内存空间。 getchar()是一个轻量级的函数。 所以你也可以使用 –

char currentGuess;
currentGuess = getchar函数();
的getchar(); //消耗空白字符。