Scanf在C中跳过每一个while循环
我正在尝试开发一个简单的基于文本的hang子手游戏,主游戏循环以提示input每个字母的猜测开始,然后继续检查字母是否在单词中,如果是不是。 但是,当我运行游戏时,提示每次出现两次,程序不会等待用户的input。 它也是一种生活(如果是正确的input,则是一种生活,如果不是,则两种),所以不pipeinput与之前的input是不一样的。 这是我的游戏循环,简化了一下:
while (!finished) { printf("Guess the word '%s'\n",covered); scanf("%c", ¤tGuess); 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", ¤tGuess);
%*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”键作为一个字符。
果然,看着你的scanf
string,你每次都在循环中要求单个字符。 控制字符也被认为是字符,将被拿起。 例如,您可以在上面的循环中按“esc”,然后“enter”并获得:
enter val: ^[ got: 27 enter val: got: 10
只是一个猜测,但是你正在用scanfinput一个单独的字符,但是用户必须input猜测加上一个换行符,这个换行符正在作为一个单独的猜测字符被使用。
scanf(" %c", &fooBar);
注意%c
之前的空格。 这很重要,因为它匹配所有前面的空格。
吉姆和乔纳森说得对。
为了让你的scanf行做你想做的(消耗换行符,不要把它放在缓冲区中),我会改变它
scanf("%c\n", ¤tGuess);
(注意\n
)
虽然这个error handling是残酷的。 至less应该检查scanf的返回值1,如果没有返回,则忽略input(带有警告)。
我注意到了几点:
-
scanf("%c")
将读取1个字符,并在下一次循环中将ENTER保留在input缓冲区中 - 即使从用户读取的字符与
secretWord
字符中的字符不匹配,i
也正在递增 - 什么时候
covered[j]
永远成为' – '?
我猜想:当你input数据时,你的代码将把新行当作猜测之一。 由于无法控制的error handling,我一直避免使用* scanf()系列。 尝试使用fgets(),然后拔出第一个字符/字节。
我在代码中看到了一些东西:
- scanf返回它读取的项目数。 您可能会想要处理返回0或EOF的情况。
- 我的猜测是用户正在打字+ Enter,并且你得到换行符作为第二个字符。 一个简单的方法来检查将添加一个debuggingprintf语句来显示input的字符。
- 你的代码只会匹配匹配字母的第一个匹配项,也就是说,如果单词是“test”,而用户input了“t”,那么你的代码只会匹配第一个“t”,而不是两个匹配。 你需要调整你的第一个循环来处理这个问题。
input字符时,必须input空格字符才能继续。 该空格字符存在于input缓冲区stdin文件中,并由scanf()函数读取。 这个问题可以通过消耗这个额外的字符来解决。 这可以通过使用getchar()函数来完成。
的scanf( “%C”,&currentGuess);
的getchar(); //消耗空白字符。
我宁愿build议你避免使用scanf(),而是使用getchar()。 scanf()需要大量的内存空间。 getchar()是一个轻量级的函数。 所以你也可以使用 –
char currentGuess;
currentGuess = getchar函数();
的getchar(); //消耗空白字符。