web-dev-qa-db-ja.com

printf vs. std :: cout

重複の可能性:
C++コードでprintfを使用する必要がありますか?

画面にstringを印刷したいだけの場合は、次の2つの方法を使用して印刷できます。

printf("abc");

std::cout << "abc" << std::endl;

ケースは、上記の例では、std::coutよりもprintfを使用する利点がありますか、またはその逆ですか?

13
aali

coutは適切なC++の方法ですが、一部の人や企業( Google を含む)は、はるかに簡単なため、C++コードでprintfを引き続き使用していると思います。 printfよりもcoutでフォーマットされた出力。

これが私が見つけた興味深い例です ここ

比較:

printf( "%-20s %-20s %5s\n" , "Name" , "Surname" , "Id" );

そして

cout << setw( -20 ) << "Name" << setw( 20 ) << "Surname"  << setw( 5 ) << "Id" << endl;
32
dandan78

printf およびそれに関連するフレンドはC関数です。これらはC++で動作しますが、C++の型安全性はありません std::ostreamsprintf関数を使用して、ユーザー入力(またはファイルからの入力)に基づいて出力をフォーマットするプログラムでは、問題が発生する可能性があります。例えば:

int main()
{
    char[] a = {'1', '2', '3', '4'}; // a string that isn't 0-terminated
    int i = 50;
    printf("%s", a); // will continue printing characters until a 0 is found in memory
    printf("%s", i); // will attempt to print a string, but this is actually an integer
}

C++は、はるかに強力な型安全性を備えています(そして、std::string class)このような問題を防ぐのに役立ちます。

17
Zac Howland

実際にあなたの特定の例のために、あなたはどちらが好ましいか、プットまたはカウトを尋ねるべきでした。 printfはフォーマットされたテキストを印刷しますが、コンソールにプレーンテキストを出力しているだけです。

一般的な使用では、ストリーム(iostream、coutがその一部)はより拡張可能であり(独自のタイプを印刷できます)、関数を生成して、コンソール(またはリダイレクトされた出力)。 FILE *を実際のファイルではないことが多いのでfprintfを使用して、printfで一般的なストリーム動作を作成することもできますが、これはより注意が必要です。

ストリームは、印刷するタイプでオーバーロードするという点で「タイプセーフ」です。 printfは省略記号を使用するためタイプセーフではないため、フォーマット文字列と一致しない間違ったパラメータータイプを入力すると、未定義の結果が得られる可能性がありますが、コンパイラーは文句を言いません。パラメータを見逃したり、悪いパラメータを渡したりすると(たとえば、%sの数値であり、とにかくポインタとして扱われる)、セグメンテーション違反/未定義の動作が発生する可能性があります(ただし、誤って使用するとcoutを使用する可能性があります)。

printfにはいくつかの利点があります。フォーマット文字列をテンプレート化してから、そのデータが構造体にない場合でも、そのフォーマット文字列を別のデータに再利用できます。また、1つの変数にフォーマット操作を使用しても、そのフォーマットを「固定」してさらに使用することはできません。各変数の形式を指定します。 printfはスレッドセーフであることが知られていますが、coutは実際にはそうではありません。

boostは、それぞれの利点をboost :: formatライブラリと組み合わせています。

2
CashCow

私はこの質問に自分自身で苦労しています。 printfは一般にフォーマットされた印刷に使用する方が簡単ですが、C++のiostreams機能には、オブジェクトのカスタムフォーマッターを作成できるという大きな利点があります。必要に応じて、コードで両方を使用することになります。

両方を使用して混合する場合の問題は、printfとcoutで使用される出力バッファーが同じではないため、バッファーなしまたは明示的にフラッシュ出力を実行しない限り、出力が破損する可能性があることです。

C++に対する私の主な反対意見は、printfのような高速出力フォーマット機能がないため、整数、16進数、および浮動小数点フォーマットの出力を簡単に制御する方法がないことです。

Javaにも同じ問題がありました。言語は最終的にprintfを取得しました。

ウィキペディアでは、この問題について http://en.wikipedia.org/wiki/Printf#C.2B.2B_alternatives_to_sprintf_for_numeric_conversion で詳しく説明しています。

2
vy32

printfはCから借用されており、いくつかの制限があります。 printfの最も一般的な制限は、フォーマット文字列を引数と正しく一致させるためにプログラマーに依存しているため、型の安全性です。 varargs環境から再び生じる2番目の制限は、ユーザー定義型で動作を拡張できないことです。 printfは、一連の型を印刷する方法を知っています。それだけで、そこから得られます。それでも、使用できるいくつかの点で、c ++ストリームよりもprintfを使用して文字列をフォーマットする方が高速で簡単です。

最新のコンパイラのほとんどは、型安全性の制限に対処し、少なくとも警告を提供できますが(コンパイラはフォーマット文字列を解析し、呼び出しで提供された引数をチェックできます)、2番目の制限を克服することはできません。最初のケースでも、null終了をチェックするなど、コンパイラが実際には役に立たないことがありますが、同じ配列を出力するために使用すると、_std::cout_でも同じ問題が発生します。

一方、ストリーム(_std::cout_を含む)は、任意のユーザー定義型typeのオーバーロードされたstd::ostream& operator<<( std::ostream&, type const & )を使用して、ユーザー定義型を処理するように拡張できます。それらはそれ自体でタイプセーフです-オーバーロードされていないタイプを渡すと、コンパイラは文句を言います_operator<<_。一方、フォーマットされた出力を生成するのは面倒です。

それで、あなたは何を使うべきですか?自分の型の_operator<<_のオーバーロードは単純であり、すべての型で均一に使用できるため、一般的にはストリームの使用を好みます。

これらの2つの例は異なることをします。後者は、改行文字とフラッシュ出力(std::endlの結果)を追加します。 std::coutも遅くなります。それ以外は、printfstd::coutは同じことを実現し、好きな方を選択できます。好みの問題として、C++コードではstd::coutを使用します。それはより読みやすく、より安全です。

std::coutを使用して出力をフォーマットする必要がある場合は、 この記事 を参照してください。

1
moinudin

一般に、coutはタイプセーフで一般的であるため、coutを選択する必要があります。 printfはタイプセーフではなく、一般的なものでもありません。 printfを好む唯一の理由は、メモリからの速度です。printfはcoutよりも何倍も高速です。

0
Puppy