8

理解に苦しむgetchar()。次のプログラムgetcharでは、期待どおりに動作します。

#include <stdio.h>


int main()
{
    printf("Type Enter to continue...");
    getchar();
    return 0; 
} 

ただし、次のプログラムでは、getcharは遅延を作成せず、プログラムは終了します。

#include <stdio.h>

int main()
{
    char command[100];
    scanf("%s", command );
    printf("Type Enter to continue...");
    getchar();
    return 0; 
} 

次の奇妙な回避策がありますが、これは機能しますが、理由がわかりません。

#include <stdio.h>

int main()
{
    char command[100];
    int i;
    scanf("%s", command );
    printf("Type Enter to continue...");
    while ( getchar() != '\n') {
      i=0; 
    }
    getchar();
    return 0;    
}

私の質問は次のとおり
です。 1. 何をしているのscanfですか? なぜscanfこれを行うのですか?
2. 回避策が機能するのはなぜですか?
3. 次の Python コードをエミュレートする良い方法は何ですか?

raw_input("Type Enter to continue")
4

5 に答える 5

12

入力は、改行を入力した後にのみプログラムに送信されますが、

scanf("%s", command );

%s(1)形式は、非空白文字の後に最初の空白文字が検出されると停止するため、改行を入力バッファーに残します。getchar()その後、すぐにその改行を返し、それ以上の入力を待つ必要はありません。

getchar()もう一度呼び出す前に入力バッファーから改行をクリアするため、回避策は機能します。

動作をエミュレートするには、メッセージを出力する前に入力バッファをクリアします。

scanf("%s", command);
int c;
do {
    c = getchar();
}while(c != '\n' && c != EOF);
if (c == EOF) {
    // input stream ended, do something about it, exit perhaps
} else {
    printf("Type Enter to continue\n");
    getchar();
}

(1)%s in の使用は非常に安全ではないことに注意してscanfください。フィールド幅でバッファが保持できる範囲に入力を制限する必要があります。scanf("%99s", command)最大 99 ( sizeof(command) - 1)) 文字を に読み込みcommand、0 ターミネータ用のスペースを残します。

于 2012-09-29T15:13:17.273 に答える
3

空白は 5y3 %s フォーマット指定子の区切り文字であり、改行は空白と見なされるため、バッファリングされたままになります。コンソール入力は通常行指向なので、「行」がバッファリングされたままになるため、getchar() への後続の呼び出しはすぐに返されます。

scanf("%s", command );
while( getchar() != '\n' ){ /* flush to end of input line */ }

同様に、getchar() または %c を使用して単一の文字を取得する場合、通常は行をフラッシュする必要がありますが、この場合、入力された文字自体が改行である可能性があるため、少し異なる解決策が必要です。

scanf("%c", ch );
while( ch != '\n' && getchar() != '\n' ){ /* flush to end of input line */ }

getchar() についても同様です。

ch = getchar();
while( ch != '\n' && getchar() != '\n' ){ /* flush to end of input line */ }

もちろん、賢明なことは、これらのソリューションを、再利用できるスタンドアロンの特殊な入力関数にラップし、一般的な入力検証およびエラーチェックコードを配置する場所としても使用することです (ダニエルフィッシャーの回答のように、EOF を賢明にチェックします-通常、これらのチェックとエラー処理をどこでも複製する必要はありません)。

于 2012-09-29T15:36:15.707 に答える
2

最初に使用してから、入力を解析するためにfgets使用したいと思います。sscanf私はこのようなことを長い間行ってきましたが、動作は plain を使用するよりも予測可能scanfでした。

于 2012-09-29T19:09:45.083 に答える
-4

コマンド入力を取得した後、標準入力をフラッシュします。

fflush(stdin);

ただし、入力ストリームをフラッシュすると、未定義の動作が発生します (ただし、Microsoft の C ライブラリでは動作が拡張機能として定義されています)。

于 2012-09-29T15:21:55.610 に答える