2016-03-19 13 views
2
// Some initialization code 

dup2(fd[0], fileno(stdin)); 

// This process is receiving the output of "ls -1" 

while (scanf("%[^\n]s", someCharArray) > 0) { 
    scanf("%*c"); 
    printf("%s\n", someCharArray); 
} 

これですべてのファイルが正常に印刷されます。ただし、ループは終了しません。 scanf("%*c")を取り除くと終了しますが、最初のファイル名だけが出力されます。改行文字を使うときにscanf whileループが終了しないのはなぜですか?

改行文字を消費すると、外側のファイル名scanfが次のファイル名をスキャンする準備ができていると思います。しかし、最終的なファイル名がスキャンされた後、ネストされたscanfは何もスキャンしないことが期待されます。その後、外側のscanfは何もスキャンしません。 whileループは終了します。

どうしてですか?

+5

変換指定子の最後にある 's'は、あなたが思うものは何もしません。 – EOF

+0

あなたはchelしたいと思うかもしれません。 [この 'scanf'(および家族)のリファレンス](http://en.cppreference.com/w/c/io/fscanf)。 –

+2

私はちょうど 'fgets'を使っていると思っていて、改行を取り除くほうが簡単でしょう。 – WhozCraig

答えて

2

入力待ちのままループが終了しません。それが(実装固有の方法で)第二\n、または近い

  • stdinをスキャンするので、scanf()リターンEOFを失敗したとして

    あなたが

    1. \n\nのでscanf("%[^\n]... 0を返すのペアを送信することができます負の数です。

    fgets()を使用すると便利です。 @WhozCraigループを終了させる条件(stdin閉包以外)は、どのような条件でもまだ不明ですが、

    while (fgets(someCharArray, sizeof someCharArray, stdin)) { 
        // Lop off potential trailing \n if desired 
        someCharArray[strcspn(someCharArray, "\n")] = '\0'; 
    
        printf("%s\n", someCharArray); 
    } 
    

    scanf("%[^\n]s", someCharArray)"s"無目的を果たしていない - それをドロップ。また、幅を持たないこのフォーマットでは、スキャンされる文字の最大数はsomeCharArrayに制限されず、品質コードで使用しないでください。


    私はそれをやっているように見えるものです次のファイル名を、スキャンする外側scanf関数を用意しております改行文字の消費を期待します。

    はい - そうです。以前のscanf("%[^\n]...では、未定義の動作(UB)につながる可能性のあるスキャンされる文字数に制限がないため、残りのコードが動作するのを期待するのはなぜですか?

    最終的なファイル名がスキャンされた後、ネストされたscanfが何もスキャンしないことが予想されます。

    最後の最終ファイル名の後に'\n'がある場合は、scanf("%*c");がそれを消費します。最終的なファイル名に続く文字がない場合、scanf("%*c");は辛抱強く文字を待つでしょう。入力ストリームが閉じている場合は、待機する代わりにEOFを返します。コードは、scanf("%*c");の結果を報告/テストしないので、推測する必要があります。

    次に、外側のscanfは何もスキャンしません。 whileループは終了します。スキャンする最初の文字が'\n'ある場合

    真、それはstdinが閉じている場合、scanf()は負の数EOFを返します0を返します。stdinscanf()のままになります。

  • 関連する問題