17

簡単なテキストベースの絞首刑執行人ゲームを開発しようとしています。メインのゲームループは、各文字の推測を入力するプロンプトで始まり、文字が単語に含まれているかどうかを確認し、単語に含まれているかどうかを確認します。そうではありません。ただし、ゲームを実行すると、プロンプトが毎回2回表示され、プログラムはユーザーの入力を待機しません。また、ライフ(正しい入力の場合は1ライフ、正しくない場合は2ライフ)が失われるため、取り込んだものは前の入力と同じではありません。これが私のゲームループです。少し簡略化しています。

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

    }
}

問題は、スキャンされていないのに何かが取り込まれたと思っていることだと思いますが、その理由はわかりません。誰かが何か考えを持っていますか?Mac OSX10.5でgcc4.0.1を使用しています。

4

10 に答える 10

22

でキーボード入力を読み取る場合scanf()、Enter キーが押された後に入力が読み取られますが、Enter キーによって生成された改行は の呼び出しによって消費されませんscanf()。つまり、次に標準入力から読み取るときに、改行が待っていることを意味します (これにより、次のscanf()呼び出しがデータなしで即座に返されます)。

これを回避するには、コードを次のように変更します。

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

%*c1 文字に一致しますが、アスタリスクはその文字がどこにも格納されないことを示します。これには、Enter キーによって生成された改行文字を消費する効果があるため、次に呼び出すscanf()ときに空の入力バッファーから開始します。

警告: ユーザーが 2 つのキーを押してから Enter キーを押すとscanf()、最初のキーストロークが返され、2 番目のキーストロークが実行され、次の入力呼び出しのために改行が残されます。scanf()このような癖は、多くのプログラマーが友達を避ける理由の 1 つです。

于 2009-11-03T21:35:21.437 に答える
8

改行。

初めてループを通過するとき、scanf() は文字を読み取ります。次に、改行を読み取ります。次に、次の文字を読み取ります。繰り返す。

直し方?

scanf() はめったに使用しませんが、フォーマット文字列を使用する場合は、"%.1s"空白 (改行を含む) をスキップしてから、空白以外の文字を読み取る必要があります。ただし、単一の文字ではなく文字配列が必要です。

char ibuff[2];

while ((scanf("%.1s", ibuff) == 1)
{
    ...
}
于 2009-11-03T20:13:18.710 に答える
6

問題をより小さな部分に分割します。

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文字列を見ると、ループのたびに 1 文字を要求しています。制御文字も文字と見なされ、ピックアップされます。たとえば、上記のループで「esc」を押してから「enter」を押すと、次のようになります。

enter val: ^[
got: 27
enter val: got: 10
于 2009-11-03T20:16:17.550 に答える
3
scanf(" %c", &fooBar);

の前のスペースに注意してください%c。これは、先行するすべての空白と一致するため、重要です。

于 2011-09-15T01:13:37.820 に答える
3

ただの推測ですが、scanf で単一の文字を入力していますが、ユーザーは推測と改行を入力する必要があり、これは別の推測文字として消費されます。

于 2009-11-03T20:12:28.260 に答える
2

ジムとジョナサンはそれを正しく理解しています。

scanf 行に必要な処理を実行させるには (バッファに入れずに改行文字を消費します)、次のように変更します。

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

( に注意してください\n)

ただし、これに関するエラー処理はひどいものです。少なくとも、scanf からの戻り値を 1 に対してチェックし、それが返されない場合は入力を (警告付きで) 無視する必要があります。

于 2009-11-03T20:21:50.113 に答える
1

私が気づいたいくつかの点:

  • scanf("%c")1文字を読み取り、ループを介して次回のためにENTERを入力バッファに保持します
  • iユーザーから読み取った文字がの文字と一致しない場合でも、インクリメントしていますsecretWord
  • covered[j]「-」になるのはいつですか?
于 2009-11-03T20:17:40.357 に答える
1

私は推測します:あなたのコードは、データを入力するときに改行を推測の1つとして扱っています。*scanf() ファミリは、エラー処理が制御できないため、常に避けてきました。代わりに fgets() を使用してから、最初の文字/バイトを取り出してみてください。

于 2009-11-03T20:18:18.880 に答える
0

文字を入力すると、次に進むには空白文字を入力する必要があります。この空白文字は入力バッファ、stdinファイルに存在し、scanf()関数によって読み取られます。この問題は、この余分な文字を消費することで解決できます。これは、getchar()関数を使用して実行できます。

scanf("%c",&currentGuess);  
getchar();   // To consume the whitespace character.

scanf()の使用を避け、代わりに を使用することをお勧めしますgetchar()。にはscanf()多くのメモリ領域が必要です。getchar()軽い機能です。だからあなたも使うことができます-

char currentGuess;  
currentGuess=getchar();  
getchar();  // To consume the whitespace character.
于 2010-10-03T04:33:28.323 に答える
0

私はあなたのコードでいくつかのことを見ます:

  1. scanf は、読み取ったアイテムの数を返します。おそらく、0 または EOF を返すケースを処理したいと思うでしょう。
  2. 私の推測では、ユーザーが文字 + Enter を押して、2 番目の文字として改行を取得していると思います。確認する簡単な方法は、デバッグ用の printf ステートメントを追加して、入力された文字を表示することです。
  3. コードは一致文字の最初の出現のみに一致します。つまり、単語が「test」でユーザーが「t」と入力した場合、コードは最初の「t」のみに一致し、両方には一致しません。これを処理するには、最初のループを調整する必要があります。
于 2009-11-03T20:20:46.713 に答える