2011-01-24 20 views
11

可能性の重複:printfの対のstd :: coutを


Should I use printf in my C++ code?

私は、画面上のstringを印刷したい場合は、私はそれらの二つの方法を使用していることを行うことができます

printf("abc"); 

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

上記の例では、printfを0123よりも使用するメリットがあります、またはその逆?

+6

もしあなたがC++コードを書いているのであれば、一般的にC++のイディオムとライブラリを好むべきです。 –

+0

あなたのプログラムを書いている言語は、C言語かC++言語かによって異なります。この2つの方法は異なる言語のため、直接比較することはできません。 –

+1

@Paul R.ご返信ありがとうございます。だから、 "printf()"はC++イディオムと見なされていませんか? –

答えて

1

これらの2つの例は、異なることを行います。後者は改行文字を追加し、出力をフラッシュします(結果はstd::endl)。 std::coutも遅くなります。それ以外の場合、printfstd::coutは同じことを達成し、どちらを選んでもかまいません。私は、C++コードではstd::coutを使用したいと思っています。より読みやすく、安全です。

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

+0

あなたの返事をありがとう。なぜあなたが言及しているように "std :: cout"は遅いですか?ここで「遅い」とは何ですか?例えば、何の面で?ありがとう。 –

+0

@aali他の答えが詳しく説明されている理由から、遅くなっています。コンパイラに依存していますが、古いバージョンのGCCはすべてのケースで10倍以上遅くなっています。 – marcog

+0

g ++ 4.xでは、私がコミットしたテストケースでは、 'sync_with_stdio(false)'ならostreamsはprintfsと同じくらい速いです。 –

0

一般に、より安全で一般的なので、coutを使用することをお勧めします。 printfは型セーフではなく、まったく汎用的でもありません。あなたがprintfを好むかもしれない唯一の理由は、メモリからのスピードです.printfはcoutより数倍高速です。

+0

ご返信ありがとうございます。私は "printf()"がフォーマットを可能にすることを見ました。 "cout"もそれを提供していますか? –

+0

「printfは型保証されておらず、まったく汎用的でもありません。あなたがprintfを好む唯一の理由はメモリからのスピードです.printfは何倍も高速です。あなたはそれについて少しわかりますか?ありがとう。 –

+0

@aali:coutは出力フォーマットも提供します。 –

26

coutが適切なC++方法ですが、私はcoutよりもprintfでフォーマットされた出力を行うことがはるかに簡単であるため、(Google含む)何人かの人々や企業がC++コードでprintfを使用し続けると信じています。

私が見つけた興味深い例はhereです。

は比較:

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

cout << setw(-20) << "Name" << setw(20) << "Surname" << setw(5) << "Id" << endl; 
+3

+1、あなたはprintfの利点の1つを述べてくれました。 – CashCow

+3

小さなコード行が常により読みやすいということを示す例です。 'std :: cout'のバージョンは、途中で何をしているのかを明示しています。 'printf'は暗号化された書式設定文字列を持っています。 –

+2

これは当てはまりますが、慣れてしまうと、printfはこの2つを使いやすくなると主張できます。個人的には、私は常にストリームのフォーマットが非常にclunkyであることを発見しました。 – dandan78

14

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クラス)があります。

+1

お返事をありがとうございます。 0より上で宣言した文字列がなぜ終了しないのですか?文字列は常に0で終了していませんか?そして、「タイプセーフティ」とはどういう意味ですか?ありがとう。 –

+0

文字列リテラルを印刷するときには、これはあまり関係がないと思います。 – marcog

+3

@ aali彼は文字配列を定義しています。文字配列はCで文字列として解釈できるだけで、配列の最後に自動的にゼロバイトを追加することはありません。 –

2

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

一般的には、ストリーム(iostreamはcoutの一部です)は、より拡張性があり(独自の型を使用して印刷することができます)、あらゆるタイプのストリームに印刷する関数を生成できるコンソール(またはリダイレクトされた出力)だけではありません。 FILE *をFILE *として扱うfprintfを使ってprintfで汎用ストリーム動作を作成することもできます*はしばしば実ファイルではありませんが、これはもっと難解です。

ストリームは、印刷しているタイプでオーバーロードするという点で「タイプセーフ」です。 printfは省略記号を使用すると型保証されないので、フォーマット文字列と一致しない間違ったパラメータ型を置くと、未定義の結果を得ることができますが、コンパイラは不平を言わないでしょう。パラメータを逃したり、悪いものを渡した場合(たとえ%sの数値であっても、それをポインタとして扱うなど)、seg-fault/undefinedの動作をすることさえあります。

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

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

+0

+1のための+1 boost :: format – GrahamS

+0

+1 "あなたはどちらが良いか、" puts "か" cout'_ "を求めているはずです。私は誰が内部的に誰に電話をかけるのかを探そうとしていますが、puts()には '叫び声 'の呼び出しがありますか? – LoneXcoder

2

私はこの非常に疑問に苦しんでいます。 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

printfはCから借用されており、いくつかの制限があります。 printfの最も一般的な制限は、書式文字列と引数を正しく一致させるためにプログラマが必要とするため、型の安全性です。 varargs環境からもう一度来る第2の制限は、ユーザー定義型で動作を拡張できないことです。 printfは、一連のタイプの印刷方法を認識しています。それでも、それが使用できるいくつかの点では、C++ストリームよりもprintfで文字列の書式を設定する方が高速で簡単です。

最新のコンパイラのほとんどは、型の安全性の制限に対処でき、少なくとも警告を出すことができます(コンパイラは書式文字列を解析し、呼び出しで提供された引数を調べることができます)。最初のケースでも、null終端のチェックとしてコンパイラが本当に助けないことがありますが、同じ配列を印刷する場合は同じ問題がstd::coutとなります。

一方、ストリーム(std::coutを含む)は、指定された任意のユーザー定義タイプtypeに対してオーバーロードされたstd::ostream& operator<<(std::ostream&, type const &)によってユーザー定義タイプを処理するように拡張できます。それらはそれ自身で型の安全です - あなたがオーバーロードされていない型を渡す場合operator<<コンパイラが文句を言うでしょう。一方、書式設定された出力を生成するのは面倒です。

だから何を使うべきですか?一般的に私は自分のタイプのためにoperator<<のオーバーロードが簡単で、すべてのタイプで一様に使うことができるので、ストリームを使う方が好きです。

関連する問題