1

私はcを学んでおり、この言語は低レベルであり、このコンテキストでは例外処理が欠けていることを理解しています.

ユーザーがメニューからいくつかの選択肢の中から選択する簡単なプログラムを作成しました。とてもシンプルです。

プログラムはいくつかのメソッドに分割されています。メソッドの 1 つは、ユーザーがキーを押すのを待ちます。整数が必要です。次に、この整数をスイッチ構造を保持する別のメソッドに返します。

文字が押されたときに問題が発生します。ほとんどの場合、else ブロックの無限ループが開始されます。

別の 0 から 2 を選択する必要があります。もう一度お試しください :-)

別の 0 から 2 を選択する必要があります。もう一度お試しください :-)

別の 0 から 2 を選択する必要があります。もう一度お試しください :-)

...... 等々

私は実際にこれを解決する方法を知りません。scanf 関数からの戻り値を使用しようとしましたが、成功しませんでした。また、scanf関数の引数として(整数ではなく)文字を渡そうとしましたが、これも成功しませんでした。

この問題を処理する方法について何か提案はありますか?

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

void menu();
void runSelection(int selection);
int getSelection();
int pause();


int main(void) {

do{
    menu();
    runSelection(getSelection());
}while(pause());

return 0;
}

int pause() {
int c;
printf("\n\nPress enter to continue!");
fflush(stdout);
/* flush inputstream */
while((c = getchar()) != '\n' && c != EOF);
getchar();
return 1;

}

void menu() {

puts(" * * * * * *   M E N U  * * * * * * *");
puts("1. Do something 1");
puts("2. Do something 2");
puts("3. Do something 3");
fflush(stdout);
}

void runSelection(int selection) {

switch (selection) {
    case 0:
        puts("you pressed 0");
        break;
    case 1:
        puts("you pressed 1");
        break;
    case 2:
        puts("you pressed 2");
        break;
}
}

int getSelection() {

int key;
int true = 0;
do {

    scanf("%d", &key);

    if (key >= 0 && key <=2) {
        true = 1;
    }
    else {
        puts("You must choose an alternative 0 - 2. Please try again :-)");
        fflush(stdout);
    }

} while (true == 0);

return key;
}
4

3 に答える 3

2

scanf が入力バッファから文字を読み取っているため、無限ループが発生しました。改行がバッファに残っている文字があります'\n'

scanf directelly を使用する代わりに、次のマクロを使用します。

#define SCAN_ONEENTRY_WITHCHECK(FORM,X,COND) \
do {\
    char tmp;\
    while(((scanf(" "FORM"%c",X,&tmp)!=2 || !isspace(tmp)) && !scanf("%*[^\n]"))\
            || !(COND)) {\
        printf("Invalid input, please enter again: ");\
    }\
} while(0)


int main()

{
    int decision;

    printf("Input data, valid choice 1 or 0: ");
    SCAN_ONEENTRY_WITHCHECK("%d",&decision,(decision==0 || decision==1));
    printf("You have entered good input : %d\n", decision);
}

次のトピックでは、このマクロとその使用方法について説明します: 入力データを読み取り、その有効性をチェックするための共通マクロ

于 2013-10-05T20:15:17.760 に答える
0

他の場所のように末尾'\n'を削除しなかったのはなぜですか?getSelection

使用する:

int c;
scanf("%d", &key);
while((c = getchar()) != '\n' && c != EOF); //Add this line

getSelectionあまりにも

于 2013-10-05T20:17:01.987 に答える
0

編集:この回答を最初に書いたとき、私は愚かで、どのように機能するかについて無知scanf()でした。

  • まず最初に、何かを明確にさせてください。scanf()これは機能が壊れているわけではありません。どのようscanf()に動作するか、使用方法がわからない場合は、おそらくマニュアルを読んでおらず、それは's のせいscans()ではありません。 scanf().
  • 次に、コードの何が問題なのかを理解するには、どのように機能するかを知る必要がありますscanf()

scanf("%d", &key)コードでを使用すると、 scanf() は入力から整数を読み取ろうとしますが、数値以外の値を入力すると、scanf()それが適切なデータ型ではないことを認識し、読み取った入力をバッファーに戻します。ただし、次のループ サイクルでは、無効な入力がまだバッファ内にありscanf()、バッファが空になっていないため再び失敗する原因となり、このサイクルは永久に続きます。

この問題に取り組むために、 の戻り値を使用できますscanf()。これは、正常に読み取られた入力の数になります。ただし、無限ループを回避するためにバッファをフラッシュして無効な入力を破棄する必要があります。入力バッファは次の場合にフラッシュされます。enterキーが押された場合、入力を取得するために一時停止する機能を使用してこれを行うことができます。これにはgetchar()、Enter キーを押す必要があるため、無効な入力を破棄します。はまだバッファ内にあるenterため、正しいデータ型を入力しませんでした。入力からの整数の読み取りが正常に終了したnewline character後、バッファーに戻されるため、 getchar() はそれを読み取りますが、それは必要ないため、安全に破棄できます。scanf()\n

do
{
    status = scanf("%d", &key);
    getchar();  // flush the buffer by reading a character and discarding it
    if (key >= 0 && key <=2)
    {
        true = 1;
    }
    else
    {
        puts("You must choose an alternative 0 - 2. Please try again :-)");
        fflush(stdout);
    }
} while (true == 0 && status != 1);
于 2013-12-31T12:00:25.823 に答える