题
我正在尝试开发一个简单的基于文本的刽子手游戏,主游戏循环从提示输入每个字母的猜测开始,然后继续检查该字母是否在单词中,如果出现则夺走生命。不是。但是,当我运行游戏时,每次都会出现两次提示,并且程序不会等待用户的输入。它还会夺走一条生命(如果输入正确,则一条生命,如果不正确,则两条生命),因此无论它吸收什么,都与之前的输入不同。这是我的游戏循环,稍微简化了一些:
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()
键盘输入,输入之后读取输入按下而是由输入密钥生成的新行不会被调用scanf()
消耗。这意味着你从标准输入读取下一次会有等着你(这将使没有数据的下一scanf()
呼叫立即返回)一个换行符。
要避免这种情况,你可以修改你的代码是这样的:
scanf("%c%*c", ¤tGuess);
在%*c
匹配单个字符,但星号表示该字符将不被存储在任何地方。这具有通过消耗输入键产生的换行字符,使得下一次调用scanf()
你开始使用空输入缓冲器的效果。
<强>警告:如果用户按下两个键,然后按下回车,scanf()
将返回第一次击键,吃第二和离开换行的下一个输入呼叫。像这样的怪癖是原因之一scanf()
和朋友被许多程序员避免。
其他提示
换行。
在第一次循环时,scanf()的读出的字符。 然后,它读取换行符。 然后,它读取下一个字符;重复。
如何解决?
我很少用scanf()的,但是如果使用的格式串"%.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数字,“10”在ASCII是“输入”,所以scanf
还必须抓住“输入”键作为一个字符。
果然,看着你scanf
字符串,你通过你的循环每次都询问一个字符。控制字符也被视为字符,并会有所回升。例如,可以按“ESC”那么在上述循环“输入”,并得到:
enter val: ^[
got: 27
enter val: got: 10
只是一个猜测,但你输入与scanf的单个字符,但用户必须键入猜测加一个新行,其被消耗作为一个单独的猜测字符。
scanf(" %c", &fooBar);
注意%c
之前的空间。这是重要的,因为它前面的所有空白匹配。
吉姆和Jonathan有它的权利。
要得到你的scanf线做你想要的(消费换行符的W / O把它在缓存),我将其更改为
scanf("%c\n", ¤tGuess);
(注意\n
)
处理在这个错误是恶劣虽然。在至少应检查从scanf的返回值对1,而忽视了输入(具有警告),如果它不返回。
我注意到几点:
scanf("%c")
将读取 1 个字符并将 ENTER 保留在输入缓冲区中以供下次循环使用- 你正在增加
i
即使从用户读取的字符与中的字符不匹配secretWord
- 什么时候
covered[j]
曾经成为“-”吗?
我想:你的代码是处理一个换行符,当您输入数据的猜测之一。我一直回避* scanf()系列,由于无法控制的错误处理。尝试使用与fgets()代替,然后拉出第一个字符/字节。
我在您的代码中看到了一些内容:
- scanf 返回它读取的项目数。您可能需要处理返回 0 或 EOF 的情况。
- 我的猜测是用户按下字母 + Enter 并且您将换行符作为第二个字符。一种简单的检查方法是添加调试 printf 语句以显示输入的字符。
- 您的代码将仅匹配匹配字母的第一次出现,即如果单词是“test”并且用户输入“t”,则您的代码将仅匹配第一个“t”,而不是两者。您需要调整第一个循环来处理这个问题。
当你输入的字符,你必须输入一个空格字符继续前进。此空白字符是存在于输入缓冲器,stdin
文件,并且由scanf()
功能读取。
这个问题可以通过这种消耗多余的字符来解决。这可以通过一个usnig功能getchar()
来完成。
scanf("%c",¤tGuess);
getchar(); // To consume the whitespace character.
我宁愿建议你避免使用scanf()
,而使用getchar()
。该scanf()
requires大量的内存空间。 getchar()
是一个光功能。所以,你也可以使用 -
char currentGuess;
currentGuess=getchar();
getchar(); // To consume the whitespace character.