17

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

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

printf("abc");

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

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

4

7 に答える 7

37

whilecoutは適切な C++ の方法ですが、一部の人々や企業 ( Googleを含む) は C++ コードを使用し続けているとprintf思います。printfcout

ここで見つけた興味深い例を次に示します。

比較:

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

cout << setw( -20 ) << "Name" << setw( 20 ) << "Surname"  << setw( 5 ) << "Id" << endl;
于 2011-01-24T12:18:42.433 に答える
19

printfおよびそれに関連する仲間は C 関数です。std::ostreamこれらは C++ で動作しますが、C++ 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このような問題を防ぐのに役立つ、より強力なタイプ セーフ (およびクラス) があります。

于 2011-01-24T12:22:03.317 に答える
3

私はまさにこの質問に苦労しています。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でよく議論されています。

于 2011-01-24T12:24:59.750 に答える
2

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

一般的な用途では、ストリーム (cout が含まれる iostream) はより拡張性が高く (独自の型を出力できます)、関数を生成して任意の型のストリームに出力できるという点でより汎用的です。コンソール (またはリダイレクトされた出力)。FILE* を FILE* として受け取る fprintf を使用して、printf で一般的なストリーム動作を作成することもできますが、これは多くの場合、実際のファイルではありませんが、これはよりトリッキーです。

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

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

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

于 2011-01-24T12:23:49.750 に答える
2

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

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

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

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

于 2011-01-24T12:59:00.903 に答える
1

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

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

于 2011-01-24T12:17:07.020 に答える
0

一般に、cout の方がタイプセーフで汎用性が高いため、cout を使用することをお勧めします。printf はタイプセーフではなく、まったくジェネリックでもありません。printf を好む唯一の理由は速度です。メモリから見ると、printf は c よりも何倍も高速です。

于 2011-01-24T12:18:03.090 に答える