-1

私は、C++ で柔軟なコマンド ライン (ただし長くはない!) のダイアモンド スクエア ジェネレーターを作成しています。ユーザー入力の半分を書き終えました。ただし、最後のコマンドでは、入力が「スリップ」し、改行が getchar() に自動的に入力されます。何らかのオーバーフローが発生しないように予防措置を講じました。つまり、stdin と、適切な方法として stdout の両方をフラッシュします。問題は解決しません。これが私のコードです:

#include <stdio.h>
#include <stdlib.h>

int main () {
    unsigned  long seed = 0, x = 0, y = 0, initial = 0, range = 0;
    int smooth = 0, fail = 1;
    char flagchar1 = 'n';
    printf("Welcome to my diamond-square generator! This isn't full-feature yet, so I'm just gonna have you input the variables one by one. ");
    do {
        printf("Please input the seed (this is a positive integer):\n");
        fail = scanf("%lu", &seed);
        while (fail == 0) {
            printf("Try again, smartass.\n");
            fail = scanf("%lu", &seed);
        }
        fail = 1;
        printf("Now input the x, or horizontal, size of your grid:\n");
        fail = scanf("%lu", &x);
        while (fail == 0) {
            printf("An integer. Not a string. An integer. You can do that, can't you?\n");
            fail = scanf("%lu", &x);
        }
        fail = 1;
        printf("Now input the y, or vertical, size of your grid:\n");
        fail = scanf("%lu", &y);
        while (fail == 0) {
            printf("What was that supposed to be? An integer, please.\n");
            fail = scanf("%lu", &y);
        }
        fail = 1;
        printf("Now input about how high you'd like the grid to be (this goes from a scale of 1 to 256):\n");
        fail = scanf("%lu", &initial);
        while (initial == 0 || initial > 256 || fail == 0) {
            printf("ahahahahaha how HIGH do you have to be just to HAVE that hieght........\n");
            fail = scanf("%lu", &initial);
        }
        fail = 1;
        printf("Now input the range of the heights on your grid (this must be equal to or less than 256):\n");
        scanf("%lu", &range);
        while (range >= 256 || fail == 0) {
            printf("What did I say about being equal to or less than 256? Give me something reasonable to work with here.\n");
            fail = scanf("%lu", &range);
        }
        fail = 1;
        printf("Just one more variable to go! Now, I need you to input the smoothness of your grid. Smaller numbers make spikier grids. You can make this negative, but beware!\n");
        fail = scanf("%d", &smooth);
        while (fail == 0) {
            printf("That... was not a number.\n");
            fail = scanf("%d", &smooth);
        }
        fail = 1;
        printf("\nOkay. Are these the values you want?\n   Seed:       %lu\n   Width:      %lu\n   Length:     %lu\n   Height:     %lu\n   Range:      %lu\n   Smoothness: %d\nDo you want to keep these? Type Y/n.\n", seed, x, y, initial, range, smooth);
        fflush(stdin);
        fflush(stdout);
        flagchar1 = getchar();
    } while (flagchar1 != 'y' && flagchar1 != 'Y' && flagchar1 != '\n');
}

これが私の出力であり、プログラムは終了しています(&& flagchar1 != '\n'fromを削除すると、プログラムは do-while ループ全体を繰り返すだけですwhile()):

    私のダイアモンド スクエア ジェネレーターへようこそ! これはまだフル機能ではないので、変数を 1 つずつ入力してもらいます。シードを入力してください (これは正の整数です):
    12345678
    次に、グリッドの x (水平) サイズを入力します。
    40
    次に、グリッドの y (垂直) サイズを入力します。
    30
    次に、グリッドの高さを入力します (これは 1 から 256 のスケールになります)。
    1288
    ああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああ!
    128
    次に、グリッドの高さの範囲を入力します (これは 256 以下である必要があります)。
    30
    残りの変数はあと 1 つです。ここで、グリッドの滑らかさを入力する必要があります。数値が小さいほど、より尖ったグリッドになります。これを否定的にすることもできますが、注意してください!
    10

わかった。これらはあなたが望む値ですか?
  種: 12345678
  幅: 40
  長さ: 30
  身長:128
  範囲: 30
  滑らかさ: 10
これらを保持しますか?Y/n と入力します。

何が起こっていますか? どうすれば修正できますか?

PS 入力検証が本質的に役に立たないことはわかっています。これに関するヘルプも大歓迎です。

4

5 に答える 5

2

ループの終わりを次のようにします。

    // Ignore remaining characters on current line.
    int ch;
    while( (ch = getchar()) != EOF && ch != '\n')
      ;
    // fetch first character on next line
    flagchar1 = getchar();
} while (flagchar1 != 'y' && flagchar1 != 'Y' && flagchar1 != '\n');

'\n'への最後の呼び出しの後、stdinを離れますscanf

fflush(stdin)特定の行動に依存してはなりません。入力ストリームを呼び出しfflushた結果は未定義です。fflush(stdin)の使用を参照してください

于 2012-03-05T19:48:52.803 に答える
0

コードは、指示どおりに動作しています。ユーザーが 'y'、'Y'、または enter を入力すると、while ループの条件の 1 つが false になり、終了します。

あなたが望むものは:

while (flagchar1 == 'y' || flagchar1 == 'Y' || flagchar1 == '\n');

編集: fflush(stdin) も削除し、getchar() を fgets() に置き換えます。これにより、問題になる可能性のある fflush を使用しなくても、行全体が読み取られることが保証されます。

于 2012-03-05T19:33:31.113 に答える
0

Linuxを使用していると思いますか?これは、Windows の VS で正常に動作します。プロンプトが表示され、キーボードから読み取られ、検査された場合、問題の正しい「y」または「Y」が含まれます。

最後の scanf を次のように変更することをお勧めします。

fail = scanf("%d ", &smooth);

fflush() の代わりに fpurge() を呼び出すこともできますが、それは標準的ではありません。フォーマット文字列の末尾にスペースを入れると、必要なものが得られると思います。

末尾のスペースは、入力データ内の余分な空白 (改行を含む) を消費するように scanf に要求します。fflush() はおそらく、入力に必要な処理を実行しません。

あなたが使用しているシステムが実際にキャリッジリターンをストリームに残しているのではないかと思います.flagchar1をintとして出力すると、10が得られますか?

于 2012-03-05T20:12:35.113 に答える
0

提案:

  1. C++ ストリームを使用します。
  2. 文字を比較する前にtolowerorを使用します。toupper
  3. を使用しstd::stringます。

を使用する C 言語にはfgets, gets, fflush, strcmp,、この分野で多くの問題があります。C++ 言語は、これらの問題の多くをstd::streamクラスで解決しました。

C++ 機能を使用していないため、C++タグをCに変更する必要があります。

于 2012-03-05T20:36:39.077 に答える
-1

試す

while (flagchar1 != 'y' || flagchar1 != 'Y' || flagchar1 != '\n');

それ以外の

} while (flagchar1 != 'y' && flagchar1 != 'Y' && flagchar1 != '\n');

于 2012-03-05T19:36:26.813 に答える