gets と scanf の混合の問題

1.getsと scanf の違い.
Gets はスペースの文字列を読み取ることができ、復帰に遭遇すると停止しますが、scanf は
スペースまたは復帰に遭遇すると読み取りを停止します。

2.

scanf("%d\n",&a);

このとき、データを入力するときにもう 1 行入力する必要がありますが、scanf("%d\n",&n); などのステートメントで数値 5 を入力すると、データの最初の行だけが読み取られます。 Enterを押すと、すべての5\nが読み取られます。scanfに進み、nに5が割り当てられましたが、この時点ではバッファに空白文字がないため終了できません。その後、の規則に従って、 scanf、入力を終了するには空白文字が必要なので、入力を続ける必要があります。\n 読み取りを続けるには空白以外の文字に遭遇する必要があります。そうでない場合は、入力を求めるプロンプトが表示され続けるため、入力してください別の非空白文字と空白文字により、scanf の停止を正常に完了できます。

3. Gets と scanf が混在しています。
この問題は、私が書いた PTA の質問から生じています。
タイトル:
n 冊の本の名前と価格が与えられた場合、この質問では、最も高い本の名前と価格を検索して出力するプログラムを作成する必要があります。最低価格。

入力形式:
1行目に正の整数n(<10)を入力し、その後n冊の書籍の情報を入力します。各書籍には、タイトルが 30 文字以内の文字列で 1 行に記載され、その後に正の実質価格が 1 行で表示されます。タイトルは、同じ価格の本が存在しないことを保証します。

出力形式:
「価格、書籍名」の形式で、最高価格の書籍と最低価格の書籍を連続して出力します。価格は小数点第 2 位を保持します。

#include <stdio.h>
#include <stdlib.h>
struct Book
{
    
    
    char name[31];
    double price;
}book;

int main()
{
    
    
    int n;
    scanf("%d",&n);

    struct Book book[n];
    int i,max=0,min=0;
    for(i=0;i<n;i++)
    {
    
    
        scanf("\n");                     //关键所在
        gets(book[i].name);
        scanf("%lf",&book[i].price);
        if(book[i].price>book[max].price)
        {
    
    
            max=i;
        }
        if(book[i].price<book[min].price)
        {
    
    
            min=i;
        }
    }
    printf("%.2lf, %s\n",book[max].price,book[max].name);
    printf("%.2lf, %s\n",book[min].price,book[min].name);
    return 0;
}

デバッグ後、scanf ("\n"); を削除すると、プログラムが gets の次の文を読み込まないことがわかりました。その理由は、

scanf の後に gets を使用する場合は注意が必要です。gets は '\n' に遭遇すると直接戻り、scanf と入力して Enter を押すと入力バッファに '\n' が残り、gets はたまたま '\ に遭遇します。 n' が直接返されるため、入力する必要はありません。

gets() が scanf() の後にある場合、scanf() の入力が完了して Enter キーを押すと、gets() は Enter キーを受け取ります。重要なのは、この 2 つで使用される終了タグが異なるということです。文字列を入力するときに、scanf() はスペース、キャリッジ リターン、およびタブの末尾を検出しますが、これらのターミネータはバッファにまだ残っています。その後、gets() を使用して文字列の次の行を取得すると、前回の復帰が残っている場合 (または復帰の前にスペースなどの空白がある場合)、今度は gets() は直接失敗します。

推測では、プログラムの先頭に scanf があり、Enter キーを押した直後にスキップすると、解決策は次のようになります。

方法 1、while(getchar()!='\n'); を使用してバッファ内の復帰文字と改行文字を処理すると、gets() が正常になります。
方法 2、バッファー内にキャリッジ リターンとライン フィードがまだあることが明確にわかっている場合は、それを直接読み取ります: scanf("\n"); または getchar() で文字を読み取り、次に get()問題ないでしょう。

おすすめ

転載: blog.csdn.net/Bad_foxS/article/details/104507135