在C中循环时,Scanf会相互跳过

ben*_*wad 16 c gcc scanf

我正在尝试开发一个简单的基于文本的刽子手游戏,并且主游戏循环以提示输入每个字母的猜测开始,然后继续检查字母是否在单词中并且如果它生命关闭不是.但是,当我运行游戏时,每次提示两次,程序不会等待用户的输入.它也会夺去生命(如果它是正确的输入就会有一个生命,如果没有,则为两个生命),所以无论它采取的是什么都与之前的输入不同.这是我的游戏循环,简化了一下:

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;
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

我认为问题是scanf认为它没有,但我不明白为什么.有谁有想法吗?我在Mac OS X 10.5上使用gcc 4.0.1.

bta*_*bta 21

当您读取键盘输入时scanf(),按下输入后读取输入,但输入键生成的换行不会被调用消耗scanf().这意味着下次你从标准输入读取时会有一个等待你的换行符(这将使下一个scanf()呼叫立即返回而没有数据).

为避免这种情况,您可以将代码修改为:

scanf("%c%*c", &currentGuess);
Run Code Online (Sandbox Code Playgroud)

%*c匹配单个字符,但星号表示该角色会不会被存储在任何地方.这会产生消耗enter键生成的换行符的效果,这样下次调用时scanf()就会以空输入缓冲区开始.

警告: 如果用户按下两个键然后按Enter键,scanf()将返回第一个击键,吃第二个键,然后保留换行符以进行下一个输入调用.像这样的怪癖是scanf()许多程序员避免和朋友避开的原因之一.

  • @Craig Ringer-“%c%* c”将吃掉附加到当前输入字符的换行符。事后,您将使用“%* c%c”来从* previous *输入中换行。从技术上讲,这两种方法都是正确的,但最好是自己清理一下,而不是在缓冲区中留下流浪字符,以便其他人去处理。 (2认同)

Jon*_*ler 8

换行.

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

怎么修?

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

char ibuff[2];

while ((scanf("%.1s", ibuff) == 1)
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

  • `scanf("%c",&currentguess)`也应该做,不需要改变变量的类型.`scanf`格式字符串中的空格与输入中的"任意数量的空格,包括无空格"相匹配. (2认同)

jhe*_*ngs 5

将问题分解为更小的部分:

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

这里的输出是:

enter val: g
got: 103
enter val: got: 10
Run Code Online (Sandbox Code Playgroud)

为什么scanf会给你另外一个'10'?

由于我们为我们的值打印了ASCII码,因此ASCII中的'10'是"enter",因此scanf还必须将"enter"键作为一个字符.

果然,看着你的scanf字符串,你每次循环都要求一个字符.控制字符也被视为字符,将被拾取.例如,您可以在上面的循环中按"esc"然后"enter"并获取:

enter val: ^[
got: 27
enter val: got: 10
Run Code Online (Sandbox Code Playgroud)