0

ここではCから始めます。ints文字列とがのさまざまなフィールドに入力されるループを実行しようとしていますstruct。「ラストネーム」の入力を求められたら、ユーザーは他の入力なしでEnterキーを押すことができ、ループは終了します。

問題は、このコードではループが終了せず(姓と名の入力要求が同じ行で一緒に実行される)、salaryの値が常に間違っている(0またはいくつかの大きな数)ことです。

while (employee_num <= 2)
{
    printf("Enter last name ");
    fgets(employee[employee_num].last_name, sizeof(employee[employee_num].last_name), stdin);                   

    if(strlen(employee[employee_num].last_name) == 0)
        break;

    printf("Enter first name ");
    fgets(employee[employee_num].first_name, sizeof(employee[employee_num].first_name), stdin);

    printf("Enter title ");
    fgets(employee[employee_num].title, sizeof(employee[employee_num].title), stdin);

    printf("Enter salary ");
    fgets(strng_buffer, 1, stdin);
    sscanf(strng_buffer, "%d", &employee[employee_num].salary);     
    ++employee_num;
    getchar();
}

代わりにこのコードを試してみると、最初の実行後にループを適切に終了できますが、その後は終了できません(名前の部分でEnterキーを押すと、おそらく\ nクリアできないように見えますか?):

char strng_buffer[16];
while (employee_num <= 5)
{
    printf("Enter last name ");
    fgets(strng_buffer, sizeof(strng_buffer), stdin);                   
    sscanf(strng_buffer, "%s", employee[employee_num].last_name);       

    if(strlen(employee[employee_num].last_name) == 0)
        break;

    printf("Enter first name ");
    fgets(strng_buffer, sizeof(strng_buffer), stdin);
    sscanf(strng_buffer, "%s", employee[employee_num].first_name);


    printf("Enter title ");
    fgets(strng_buffer, sizeof(strng_buffer), stdin);
    sscanf(strng_buffer, "%s", employee[employee_num].title);

    printf("Enter salary ");
    scanf("%d", &employee[employee_num].salary);        
    ++employee_num;
    getchar();
}

これを意図したとおりに機能させる方法と、このようなエントリのベストプラクティス(つまり、sscanf、fgetsなどの使用)について知りたいです。

前もって感謝します!

4

3 に答える 3

2

ループは、breakステートメントに遭遇すると、途中で中断します。

if(strlen(strng_buffer) == 0)
        break;

初期化されていない文字バッファstrng_bufferは、偶然にも最初の文字としてnullを持っているためstrlen0

私はあなたが意図したかもしれないと信じています

if(strlen(employee[employee_num].last_name) == 0)
            break;

ループターミネータとして、そしてそれはあなたの部分のタイプミスが時期尚早のループ終了を引き起こしていました。

于 2013-01-23T03:35:09.687 に答える
1

問題は、fgets改行(\n)が含まれている文字列を返すことです。したがって、ユーザーが情報を入力せずにReturnキーを押しても、文字列は空になりません。また、のバッファサイズsalaryが小さすぎます。

したがって、\nすべてfgetsを削除するか、チェックを次のように変更します。

if(strlen(employee[employee_num].last_name) == 1) break;

また、バッファを取得するときは、1を次のような大きなものに変更します。

fgets(strng_buffer, 10, stdin);

ただし、各fgetsからを削除したい場合は、次の\nようにすることができます。

employee[employee_num].last_name[strlen(employee[employee_num].last_name)-1] = 0;

これはすべての文字列に対して実行できますが、さらに良いことに、それを実行する関数を作成することもできます。

編集:ユーザーが各入力の後にEnterキーを押すことを保証できる場合は、これを安全に想定できます。ただし、常にそうであるとは限らない場合は、最後の文字がそうではない\n可能性があり、この方法で削除するだけで問題が発生する可能性があります。

于 2013-01-23T04:27:25.060 に答える
1

Abhijitによって言及された修正を想定して、なぜ最初のものを2番目のものに変換するのですか??が追加されているため、2番目の動作が最初の動作と異なることに気づいていますsscanfか?あなたの意図が最初のものを短くすることであったなら、2番目はかなりかさばるようです。状況に追加sscanfするのではなく、aを宣言しstruct employee *e = employee + employee_num;、代わりにそれを繰り返し使用して、最初のを短くしてみませんemployee[employee_num]か?

に関する「ベストプラクティス」の1つfgetsは、戻り値を確認することです。fgets遭遇した場合、何が返ってくると思いますEOFか?成功したら何fgetsが返ってくると思いますか?

に関する「ベストプラクティス」の1つscanfは、戻り値を確認することです。の戻り値に関しては、このマニュアルを注意深く読み、次の質問に答えるscanfことをお勧めします。scanf

  1. int x = scanf("%d", &employee[employee_num].salary);入力として入力xするとどうなると思いますか?"fubar\n"
  2. 'f'フロムはどこに行くと思います"fubar\n"か?
  3. ungetc'に戻った場合stdin、次の従業員の名前は何になりますか?
  4. int x = scanf("%d", &employee[employee_num].salary);xこのコードをWindowsで実行し、CTRL + Zを押して送信EOFするとどうなると思いますstdinか?
  5. int x = scanf("%d %d", &y, &z);値が2つの変数に正常に入れxられると仮定すると、何を期待しますか?scanfyz

PSは、他のプログラムやファイルからの入力をリダイレクトするためのパイプとリダイレクトを使用することに加えて、WindowsではCTRL + Zで、Linuxやその仲間ではCTRL+DでEOF送信できます。stdin

于 2013-01-23T04:27:27.190 に答える