我正在尝试开发一个简单的基于文本的刽子手游戏,并且主游戏循环以提示输入每个字母的猜测开始,然后继续检查字母是否在单词中并且如果它生命关闭不是。但是,当我运行游戏时,每次提示两次,程序不会等待用户的输入。它也会夺去生命(如果它是正确的输入,则为一生,如果不是,则为两个生命),因此无论它采取的是什么都与之前的输入不同。这是我的游戏循环,简化了一下:
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()
读取键盘输入时,在按下enter后读取输入,但是输入键生成的换行不会被调用scanf()
消耗。这意味着下次你从标准输入读取时会有一个等待你的换行符(这将使下一个scanf()
调用立即返回而没有数据)。
为避免这种情况,您可以将代码修改为:
scanf("%c%*c", ¤tGuess);
%*c
匹配单个字符,但星号表示该字符不会存储在任何地方。这会消耗enter键生成的换行符,以便下次调用scanf()
时,您将使用空输入缓冲区。
警告:如果用户按下两个键然后按Enter键,scanf()
将返回第一个击键,吃第二个键,然后保留换行符以进行下一个输入调用。像这样的怪癖是许多程序员避免使用scanf()
和朋友的原因之一。
输入字符时,必须输入空白字符才能继续。此空白字符存在于输入缓冲区stdin
文件中,并由scanf()
函数读取。消耗这个额外的角色可以解决这个问题。这可以通过使用getchar()
函数来完成。
scanf("%c",¤tGuess);
getchar(); // To consume the whitespace character.
我宁愿建议你避免使用scanf()
而是使用getchar()
。 scanf()
re需要大量的内存空间。 getchar()
是一个轻功能。所以你也可以用 -
char currentGuess;
currentGuess=getchar();
getchar(); // To consume the whitespace character.
第一次通过循环,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数字,因此ASCII中的“10”是“输入”,因此scanf
也必须将“输入”键作为字符。
果然,看着你的scanf
字符串,你每次通过循环都要求一个字符。控制字符也被视为字符,将被拾取。例如,您可以在上面的循环中按“esc”然后“enter”并获取:
enter val: ^[
got: 27
enter val: got: 10
只是一个猜测,但你输入的是一个带有scanf的单个字符,但是用户必须输入猜测加上换行符,换行符作为单独的猜测字符使用。
scanf(" %c", &fooBar);
注意%c
之前的空间。这很重要,因为它匹配所有前面的空格。
吉姆和乔纳森做对了。
让你的scanf行做你想做的事情(使用换行符而不把它放在缓冲区中)我将它改为
scanf("%c\n", ¤tGuess);
(注意\n
)
对此的错误处理是非常糟糕的。至少你应该检查scanf的返回值是否为1,如果没有返回,则忽略输入(带警告)。
我注意到几点:
scanf("%c")
将读取1个字符,并将ENTER保留在输入缓冲区中以供下次循环使用i
中的字符不匹配,你也会增加secretWord
covered[j]
什么时候成为' - '?我猜:当你输入数据时,你的代码将新行视为猜测之一。由于无法控制的错误处理,我总是避免使用* scanf()系列。尝试使用fgets()代替,然后拔出第一个char / byte。
我在你的代码中看到了几件事: