web-dev-qa-db-ja.com

printfでリードするのではなく、末尾の改行を使用するのはなぜですか?

printfを使用するときは、改行の先頭を避ける必要があると聞きました。そのため、printf("\nHello World!")の代わりにprintf("Hello World!\n")を使用する必要があります

上記のこの特定の例では、出力が異なるため、意味がありませんが、次のことを考慮してください。

printf("Initializing");
init();
printf("\nProcessing");
process_data();
printf("\nExiting");

に比べ:

printf("Initializing\n");
init();
printf("Processing\n");
process_data();
printf("Exiting");

見栄えがよくなることを除いて、末尾の改行を使用してもメリットはありません。他に理由はありますか?

編集:

私はここと今、近い投票に取り組みます。この質問は主にデザインに関するものであるため、これはスタックオーバーフローに属するとは思わない。この件についての意見かもしれませんが、 Kilian Fothの回答cmasterの回答 は、1つのアプローチで非常に客観的なメリットがあることを証明しているとも言えます。

81
klutt

端末I/Oのかなりの量はline-bufferedであるため、メッセージを\ nで終了することで、メッセージがタイムリーに表示されることが確実になります。先頭に\ nを付けると、メッセージは一度に表示される場合とされない場合があります。多くの場合、これは、各ステップがpreviousステップの進行メッセージを表示することを意味します。これにより、プログラムの動作を理解しようとするときに混乱や時間の無駄がなくなります。

221
Kilian Foth

POSIXシステム(基本的にはすべてのLinux、BSD、オープンソースベースのシステムを見つけることができます)では、行は改行\nで終了する文字列として定義されます。これは、wcgrepsedawkvim。これは、一部のエディタ(vimなど)が常にファイルの最後に\nを追加する理由でもあり、Cの以前の標準ではヘッダーが\n文字で終了する必要があった理由も。

ところで:\nで終了する行があると、テキストの処理がはるかに簡単になります。ターミネーターを取得したら、完全な行を取得できることは確かです。そして、ターミネーターにまだ遭遇していない場合は、もっと多くのキャラクターを見る必要があることは確かです。

もちろん、これはプログラムの入力側ですが、プログラム出力はプログラム入力として非常によく使用されます。したがって、他のプログラムへのシームレスな入力を可能にするために、出力は規則に従う必要があります。

他の人が述べたことに加えて、もっと単純な理由があるように感じます。それが標準だからです。何かがSTDOUTに出力されるときはいつでも、ほとんど常にそれがすでにオンの新しい行であると想定しているため、新しい行を開始する必要はありません。また、書き込まれる次の行も同じように機能することを前提としているため、新しい行を開始することで終了します。

標準の末尾の改行行とインターリーブされた先頭の改行行を出力すると、次のようになります。

Trailing-newline-line
Trailing-newline-line

Leading-newline-line
Leading-newline-line
Leading-newline-lineTrailing-newline-line
Trailing-newline-line

Leading-newline-lineTrailing-newline-line
Trailing-newline-line
Trailing-newline-line

...それはおそらくあなたが望むものではありません。

コードで先頭の改行のみを使用し、それをIDEでのみ実行する場合は、問題ないかもしれません。端末で実行するか、コードとともにSTDOUTに書き込む他の人のコードを導入するとすぐに、上記のような望ましくない出力が表示されます。

31

非常に高く投票された回答は、末尾の改行を優先すべきであるという優れた技術的理由をすでに与えているので、私は別の角度からそれに取り組みます。

私の意見では、次のようにするとプログラムが読みやすくなります。

  1. 高いS/N比(単純ではあるが単純ではない)
  2. 重要なアイデアが最初に来る

以上の点から、末尾の改行の方が良いと言えます。改行はメッセージと比較したときに「ノイズ」をフォーマットします。メッセージは目立つため、最初に来る必要があります(構文の強調表示も役立ちます)。

17
Alex Vong

末尾の改行を使用すると、後の変更が簡単になります。

OPのコードに基づく(非常に些細な)例として、出力before "Initializing"メッセージを生成する必要があり、その出力がコードの異なる論理部分から、別のソースファイル。

最初のテストを実行し、「Initializing」が他の出力の行の末尾に追加されていることを確認したら、コードを検索してどこで印刷されたかを見つけ、「Initializing」を「\ nInitializing」に変更する必要があります。 "別の状況で、何か他の形式を台無しにしないでください。

ここで、新しい出力が実際にはオプションであるという事実をどのように処理するかを考えます。そのため、「\ nInitializing」に変更すると、出力の先頭に不要な空白行が生成されることがあります...

以前の出力があったかどうかを示すグローバル(shock horror ?? !!!)フラグを設定し、オプションの先頭に「\ n」を付けて「初期化」を印刷するかどうかをテストしますか、それとも出力しますか? "\ n"を以前の出力と一緒にして、今後のコードリーダーに、なぜこの "初期化" しないが他のすべての出力メッセージのように先頭に "\ n"があるのか​​疑問に思うままにしておきますか?

末尾の改行を一貫して出力する場合は、終了する必要がある行の終わりに達したことがわかった時点で、これらの問題をすべて回避します。いくつかのロジックの最後に個別のputs( "\ n")ステートメントが必要になる場合がありますが、ポイントごとに行を出力しますが、重要なのは、改行を出力することですコードの最も早い場所)あなたがそれをする必要があることを知っています、他の場所ではありません。

16
alephzero

Printfでリードするのではなく、末尾の改行を使用するのはなぜですか?

C仕様とほぼ一致

Cライブラリは、終了として改行文字'\n'

テキストストリームは、で構成される文字の順序付けられたシーケンスであり、各行は0個以上の文字と終端の改行文字で構成されます。最後の行に終了改行文字が必要かどうかは、実装によって定義されます。 C11§7.21.22

linesとしてデータを書き込むコードは、ライブラリの概念と一致します。

printf("Initializing"); // Write part of a line
printf("\nProcessing"); // Finish prior line & write part of a line
printf("\nExiting");    // Finish prior line & write an implementation-defined last line

printf("Initializing\n");//Write a line 
printf("Processing\n");  //Write a line
printf("Exiting");       //Write an implementation-defined last line

Re:最後の行には、終了改行文字が必要です。私は常に出力に最後の'\n'を書き、入力での不在を許容することをお勧めします。


スペルチェック

スペルチェッカーが文句を言う。おそらくあなたもそうです。

  v---------v Not a valid Word
"\nProcessing"

 v--------v OK
"Processing\n");

たとえば、先頭に改行を付けると、条件文がある場合にコードを簡単に記述できます。

printf("Initializing");
if (jobName != null)
    printf(": %s", jobName);
init();
printf("\nProcessing");

(ただし、他の場所で言及されているように、CPU時間のかかる手順を実行する前に、出力バッファーをフラッシュする必要がある場合があります。)

したがって、両方の方法で良いケースを作成できますが、個人的にはprintf()は好きではなく、カスタムクラスを使用して出力を作成します。

4
Ian

先頭の改行は、他のライブラリ関数、特に標準ライブラリのputs()perrorではうまく機能しませんが、使用する可能性のある他のライブラリでも同様です。

事前に記述された行(定数、またはsprintf()などで既にフォーマットされている行)を印刷する場合、puts()が自然な(そして効率的な)選択です。ただし、puts()が前の行を終了して未終了の行を書き込む方法はありません。常に行ターミネータが書き込まれます。

1
Toby Speight