重複の可能性:
C++コードでprintfを使用する必要がありますか?
画面にstring
を印刷したいだけの場合は、次の2つの方法を使用して印刷できます。
printf("abc");
std::cout << "abc" << std::endl;
ケースは、上記の例では、std::cout
よりもprintf
を使用する利点がありますか、またはその逆ですか?
printf
およびそれに関連するフレンドはC関数です。これらはC++で動作しますが、C++の型安全性はありません std::ostream
s 。 printf
関数を使用して、ユーザー入力(またはファイルからの入力)に基づいて出力をフォーマットするプログラムでは、問題が発生する可能性があります。例えば:
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)このような問題を防ぐのに役立ちます。
実際にあなたの特定の例のために、あなたはどちらが好ましいか、プットまたはカウトを尋ねるべきでした。 printfはフォーマットされたテキストを印刷しますが、コンソールにプレーンテキストを出力しているだけです。
一般的な使用では、ストリーム(iostream、coutがその一部)はより拡張可能であり(独自のタイプを印刷できます)、関数を生成して、コンソール(またはリダイレクトされた出力)。 FILE *を実際のファイルではないことが多いのでfprintfを使用して、printfで一般的なストリーム動作を作成することもできますが、これはより注意が必要です。
ストリームは、印刷するタイプでオーバーロードするという点で「タイプセーフ」です。 printfは省略記号を使用するためタイプセーフではないため、フォーマット文字列と一致しない間違ったパラメータータイプを入力すると、未定義の結果が得られる可能性がありますが、コンパイラーは文句を言いません。パラメータを見逃したり、悪いパラメータを渡したりすると(たとえば、%sの数値であり、とにかくポインタとして扱われる)、セグメンテーション違反/未定義の動作が発生する可能性があります(ただし、誤って使用するとcoutを使用する可能性があります)。
printfにはいくつかの利点があります。フォーマット文字列をテンプレート化してから、そのデータが構造体にない場合でも、そのフォーマット文字列を別のデータに再利用できます。また、1つの変数にフォーマット操作を使用しても、そのフォーマットを「固定」してさらに使用することはできません。各変数の形式を指定します。 printfはスレッドセーフであることが知られていますが、coutは実際にはそうではありません。
boostは、それぞれの利点をboost :: formatライブラリと組み合わせています。
私はこの質問に自分自身で苦労しています。 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 で詳しく説明しています。
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
も遅くなります。それ以外は、printf
とstd::cout
は同じことを実現し、好きな方を選択できます。好みの問題として、C++コードではstd::cout
を使用します。それはより読みやすく、より安全です。
std::cout
を使用して出力をフォーマットする必要がある場合は、 この記事 を参照してください。
一般に、coutはタイプセーフで一般的であるため、coutを選択する必要があります。 printfはタイプセーフではなく、一般的なものでもありません。 printfを好む唯一の理由は、メモリからの速度です。printfはcoutよりも何倍も高速です。