458

C++のprintf()との違いは何ですか?cout

4

16 に答える 16

445

質問が違いを求めただけであっても、この質問の誰もが よりもはるかにstd::cout優れていると主張していることに驚いています。printfここで違いがあります -std::coutは C++ であり、printfC です (ただし、C の他のほとんどのものと同様に、C++ でも使用できます)。ここで正直に言います。両方printfstd::cout利点があります。

本当の違い

拡張性

std::cout拡張可能です。それも拡張可能だと人々が言うことprintfは知っていますが、そのような拡張はC標準では言及されていません(したがって、非標準機能を使用する必要があります-しかし、一般的な非標準機能は存在しません)。 (そのため、既存の形式と競合するのは簡単です)。

とは異なりprintfstd::cout完全に演算子のオーバーロードに依存するため、カスタム フォーマットに問題はありませんstd::ostream。最初の引数としてサブルーチンを定義し、2 番目に型を定義するだけです。そのため、名前空間の問題はありません。クラス (1 文字に限定されない) がある限り、そのクラスのstd::ostreamオーバーロードを機能させることができます。

しかし、多くの人が拡張を望んでいるとは思えostreamません (正直なところ、簡単に作成できる拡張機能であっても、そのような拡張機能はめったに見ませんでした)。ただし、必要な場合はここにあります。

構文

簡単にわかるように、printfstd::coutは異なる構文を使用します。printfパターン文字列と可変長引数リストを使用する標準関数構文を使用します。実際、printfこれが C にそれらがある理由printfです。形式は複雑すぎて、それらなしでは使用できません。ただし、std::cout別の API (operator <<それ自体を返す API) を使用します。

一般に、これは C バージョンの方が短くなることを意味しますが、ほとんどの場合は問題になりません。多くの引数を出力すると、違いが顕著になります。エラー番号を想定して のようなものを記述する必要がError 2: File not found.あり、その説明がプレースホルダーである場合、コードは次のようになります。どちらの例も同じように機能します (つまり、std::endl実際にバッファーをフラッシュします)。

printf("Error %d: %s.\n", id, errors[id]);
std::cout << "Error " << id << ": " << errors[id] << "." << std::endl;

これはそれほどおかしくはありませんが (2 倍の長さです)、引数を出力するだけでなく、実際にフォーマットすると、さらにおかしなことになります。たとえば、次のような印刷は0x0424クレイジーです。これは、std::cout状態と実際の値が混在していることが原因です。のようなものが型になる言語を見たことがありませんstd::setfill(もちろん、C++ 以外)。printf引数と実際の型を明確に分離します。私はそれのバージョン(ノイズが多すぎるため)と比較して、そのバージョンを維持することを本当に好みprintfます(たとえそれがちょっと不可解に見えるとしても)。iostream

printf("0x%04x\n", 0x424);
std::cout << "0x" << std::hex << std::setfill('0') << std::setw(4) << 0x424 << std::endl;

翻訳

これが本当の利点ですprintfprintfフォーマット文字列はまあ...文字列です。operator <<これにより、の乱用と比較して、翻訳が非常に簡単になりiostreamます。gettext()関数が変換され、 を表示したいと仮定するとError 2: File not found.、前に表示された書式文字列の変換を取得するコードは次のようになります。

printf(gettext("Error %d: %s.\n"), id, errors[id]);

ここで、エラー番号が説明の後にある Fictionish に翻訳すると仮定しましょう。翻訳された文字列は次のようになります%2$s oru %1$d.\n。では、C++ でそれを行うにはどうすればよいでしょうか。まあ、私にはわかりません。翻訳の目的で、に渡すことができるiostream構造体などを偽造できると思います。もちろん、C標準ではありませんが、非常に一般的であるため、安全に使用できると思います。printfgettext$

特定の整数型構文を覚えたり調べたりする必要がない

C には多くの整数型があり、C++ も同様です。std::coutはすべての型を処理しますがprintf、整数型に応じて特定の構文が必要です (非整数型もありますが、実際に使用する非整数型printfは(C 文字列、メソッド をconst char *使用して取得できます) のみです)。たとえば、 を印刷するには を使用する必要がありますが、を使用する必要があります。テーブルはhttp://en.cppreference.com/w/cpp/io/c/fprintfおよびhttp://en.cppreference.com/w/cpp/types/integerで入手できます。to_cstd::stringsize_t%zuint64_t%"PRId64"

NUL バイトを印刷することはできません。\0

printfC++ 文字列ではなく C 文字列を使用するため、特定のトリックなしでは NUL バイトを出力できません。場合によっては%cwith'\0'を引数として使用できますが、これは明らかにハックです。

誰も気にしない違い

パフォーマンス

更新:iostreamは非常に遅いため、通常はハード ドライブよりも遅いことがわかります (プログラムをファイルにリダイレクトする場合)。大量のデータを出力する必要がある場合は、 との同期を無効にするとstdio役立つ場合があります。(STDOUT に複数の行を書き込むのではなく) パフォーマンスが本当に重要な場合は、単にprintf.

誰もがパフォーマンスを気にかけていると思っていますが、わざわざ測定する人はいません。printf私の答えは、またはを使用するかどうかに関係なく、とにかく I/O がボトルネックであるということですiostream。アセンブリを簡単に調べると、より高速になるprintf 可能性があると思います(-O3コンパイラオプションを使用してclangでコンパイル)。私のエラーの例を仮定すると、printf例は例よりもはるかに少ない呼び出しを行いcoutます。これは次int mainprintfとおりです。

main:                                   @ @main
@ BB#0:
        push    {lr}
        ldr     r0, .LCPI0_0
        ldr     r2, .LCPI0_1
        mov     r1, #2
        bl      printf
        mov     r0, #0
        pop     {lr}
        mov     pc, lr
        .align  2
@ BB#1:

2 つの文字列と(数値) が引数2としてプッシュされていることがすぐにわかります。printfそれだけです。他に何もありません。比較のために、これはiostreamアセンブリにコンパイルされます。いいえ、インライン化はありません。すべての単一operator <<の呼び出しは、別の引数セットを持つ別の呼び出しを意味します。

main:                                   @ @main
@ BB#0:
        push    {r4, r5, lr}
        ldr     r4, .LCPI0_0
        ldr     r1, .LCPI0_1
        mov     r2, #6
        mov     r3, #0
        mov     r0, r4
        bl      _ZSt16__ostream_insertIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_PKS3_l
        mov     r0, r4
        mov     r1, #2
        bl      _ZNSolsEi
        ldr     r1, .LCPI0_2
        mov     r2, #2
        mov     r3, #0
        mov     r4, r0
        bl      _ZSt16__ostream_insertIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_PKS3_l
        ldr     r1, .LCPI0_3
        mov     r0, r4
        mov     r2, #14
        mov     r3, #0
        bl      _ZSt16__ostream_insertIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_PKS3_l
        ldr     r1, .LCPI0_4
        mov     r0, r4
        mov     r2, #1
        mov     r3, #0
        bl      _ZSt16__ostream_insertIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_PKS3_l
        ldr     r0, [r4]
        sub     r0, r0, #24
        ldr     r0, [r0]
        add     r0, r0, r4
        ldr     r5, [r0, #240]
        cmp     r5, #0
        beq     .LBB0_5
@ BB#1:                                 @ %_ZSt13__check_facetISt5ctypeIcEERKT_PS3_.exit
        ldrb    r0, [r5, #28]
        cmp     r0, #0
        beq     .LBB0_3
@ BB#2:
        ldrb    r0, [r5, #39]
        b       .LBB0_4
.LBB0_3:
        mov     r0, r5
        bl      _ZNKSt5ctypeIcE13_M_widen_initEv
        ldr     r0, [r5]
        mov     r1, #10
        ldr     r2, [r0, #24]
        mov     r0, r5
        mov     lr, pc
        mov     pc, r2
.LBB0_4:                                @ %_ZNKSt5ctypeIcE5widenEc.exit
        lsl     r0, r0, #24
        asr     r1, r0, #24
        mov     r0, r4
        bl      _ZNSo3putEc
        bl      _ZNSo5flushEv
        mov     r0, #0
        pop     {r4, r5, lr}
        mov     pc, lr
.LBB0_5:
        bl      _ZSt16__throw_bad_castv
        .align  2
@ BB#6:

ただし、正直なところ、I/O がボトルネックであるため、これは何の意味もありません。iostream「タイプセーフ」であるため、高速ではないことを示したかっただけです。ほとんどの C 実装はprintf、計算された goto を使用してフォーマットを実装するため、printfコンパイラが認識していなくても、 は可能な限り高速ですprintf(そうではないというわけではありません - 一部のコンパイラは特定のケースで最適化できます-通常、 でprintf終わる定数文字列は に最適化されます) 。 .\nputs

継承

なぜ継承したいのかわかりませんがostream、気にしません。とFILEも可能です。

class MyFile : public FILE {}

型安全性

確かに、可変長の引数リストには安全性がありませんが、それは問題ではありませんprintf。警告を有効にすると、一般的な C コンパイラはフォーマット文字列の問題を検出できるからです。実際、Clang は警告を有効にせずにそれを行うことができます。

$ cat safety.c

#include <stdio.h>

int main(void) {
    printf("String: %s\n", 42);
    return 0;
}

$ clang safety.c

safety.c:4:28: warning: format specifies type 'char *' but the argument has type 'int' [-Wformat]
    printf("String: %s\n", 42);
                    ~~     ^~
                    %d
1 warning generated.
$ gcc -Wall safety.c
safety.c: In function ‘main’:
safety.c:4:5: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=]
     printf("String: %s\n", 42);
     ^
于 2013-11-27T09:23:41.020 に答える
217

C++ FAQから:

[15.1]<iostream> 従来の の代わりに使用する必要があるのはなぜ<cstdio>ですか?

型の安全性を高め、エラーを減らし、拡張性を許可し、継承性を提供します。

printf()間違いなく壊れておらscanf()ず、エラーが発生しやすいにもかかわらず、おそらく住みやすいですが、どちらも C++ I/O ができることに関して制限されています。C++ I/O (<<とを使用>>) は、C (printf()とを使用scanf()) に関連しています。

  • よりタイプセーフ: を使用<iostream>すると、I/O されるオブジェクトのタイプがコンパイラによって静的に認識されます。対照的に、<cstdio>「%」フィールドを使用して型を動的に把握します。
  • エラーが発生しにくい: では<iostream>、I/O される実際のオブジェクトと一致する必要がある冗長な "%" トークンはありません。冗長性を削除すると、エラーのクラスが削除されます。
  • 拡張可能: C++<iostream>メカニズムにより、既存のコードを壊すことなく、新しいユーザー定義型を I/O できます。誰もが互換性のない新しい「%」フィールドを同時に と に追加した場合の混乱を想像してみて printf()くださいscanf()
  • 継承可能: C++メカニズムは、や <iostream>などの実際のクラスから構築されます。の とは異なり、これらは実際のクラスであるため、継承可能です。これは、ストリームのように見えて動作する他のユーザー定義のものを作成できることを意味します。知らないユーザーが書いた膨大な数の I/O コードを自動的に使用できるようになり、ユーザーはあなたの「拡張ストリーム」クラスについて知る必要がありません。std::ostreamstd::istream<cstdio>FILE*

一方、は非常に高速であるため、非常に特殊で限られたケースよりもprintf優先して使用することが正当化される場合があります。常に最初にプロファイルします。(たとえば、http://programming-designs.com/2009/02/c-speed-test-part-2-printf-vs-cout / を参照)cout

于 2010-05-20T09:47:14.750 に答える
47

人々はしばしばそれprintfがはるかに速いと主張します。これは主に神話です。テストしたところ、次の結果が得られました。

cout with only endl                     1461.310252 ms
cout with only '\n'                      343.080217 ms
printf with only '\n'                     90.295948 ms
cout with string constant and endl      1892.975381 ms
cout with string constant and '\n'       416.123446 ms
printf with string constant and '\n'     472.073070 ms
cout with some stuff and endl           3496.489748 ms
cout with some stuff and '\n'           2638.272046 ms
printf with some stuff and '\n'         2520.318314 ms

結論: 改行のみが必要な場合は、printf;を使用します。それ以外の場合coutは、ほぼ同じか、さらに高速です。詳細については、私のブログをご覧ください。

明確にするために、私はs が常に;iostreamよりも優れていると言いたいわけではありません。printf私が言いたいのは、実際のデータに基づいて十分な情報に基づいた決定を下すべきであり、よくある誤解を招くような仮定に基づいた大雑把な推測ではありません。

更新: テストに使用した完全なコードは次のとおりです。g++追加のオプションなしでコンパイルされ-lrtました (タイミングは別として)。

#include <stdio.h>
#include <iostream>
#include <ctime>

class TimedSection {
    char const *d_name;
    timespec d_start;
    public:
        TimedSection(char const *name) :
            d_name(name)
        {
            clock_gettime(CLOCK_REALTIME, &d_start);
        }
        ~TimedSection() {
            timespec end;
            clock_gettime(CLOCK_REALTIME, &end);
            double duration = 1e3 * (end.tv_sec - d_start.tv_sec) +
                              1e-6 * (end.tv_nsec - d_start.tv_nsec);
            std::cerr << d_name << '\t' << std::fixed << duration << " ms\n"; 
        }
};

int main() {
    const int iters = 10000000;
    char const *text = "01234567890123456789";
    {
        TimedSection s("cout with only endl");
        for (int i = 0; i < iters; ++i)
            std::cout << std::endl;
    }
    {
        TimedSection s("cout with only '\\n'");
        for (int i = 0; i < iters; ++i)
            std::cout << '\n';
    }
    {
        TimedSection s("printf with only '\\n'");
        for (int i = 0; i < iters; ++i)
            printf("\n");
    }
    {
        TimedSection s("cout with string constant and endl");
        for (int i = 0; i < iters; ++i)
            std::cout << "01234567890123456789" << std::endl;
    }
    {
        TimedSection s("cout with string constant and '\\n'");
        for (int i = 0; i < iters; ++i)
            std::cout << "01234567890123456789\n";
    }
    {
        TimedSection s("printf with string constant and '\\n'");
        for (int i = 0; i < iters; ++i)
            printf("01234567890123456789\n");
    }
    {
        TimedSection s("cout with some stuff and endl");
        for (int i = 0; i < iters; ++i)
            std::cout << text << "01234567890123456789" << i << std::endl;
    }
    {
        TimedSection s("cout with some stuff and '\\n'");
        for (int i = 0; i < iters; ++i)
            std::cout << text << "01234567890123456789" << i << '\n';
    }
    {
        TimedSection s("printf with some stuff and '\\n'");
        for (int i = 0; i < iters; ++i)
            printf("%s01234567890123456789%i\n", text, i);
    }
}
于 2010-05-20T11:35:40.717 に答える
42

そして私は引用します

大まかに言うと、主な違いはタイプ セーフ (cstdio にはありません)、パフォーマンス (ほとんどの iostream 実装は cstdio 実装より遅い)、および拡張性 (iostream はカスタム出力ターゲットとユーザー定義型のシームレスな出力を可能にします) です。

于 2010-05-20T09:45:57.417 に答える
30

1 つは stdout に出力する関数です。もう 1 つは、いくつかのメンバー関数とoperator<<その出力を stdout にオーバーロードするオブジェクトです。列挙できる違いは他にもたくさんありますが、あなたが何を求めているのかわかりません。

于 2010-05-20T09:46:13.063 に答える
13

私にとって、「printf」ではなく「cout」を選択する本当の違いは次のとおりです。

1) <<演算子は、クラスに対してオーバーロードできます。

2) cout の出力ストリームは、簡単にファイルに変更できます: (: コピー ペースト :)

#include <iostream>
#include <fstream>
using namespace std;

int main ()
{
    cout << "This is sent to prompt" << endl;
    ofstream file;
    file.open ("test.txt");
    streambuf* sbuf = cout.rdbuf();
    cout.rdbuf(file.rdbuf());
    cout << "This is sent to file" << endl;
    cout.rdbuf(sbuf);
    cout << "This is also sent to prompt" << endl;
    return 0;
}

3) 特に多くのパラメータがある場合、cout の方が読みやすいと思います。

1 つの問題cout、書式設定オプションです。データ (精度、正当化など) の書式設定printfは簡単です。

于 2010-05-20T12:01:25.697 に答える
5

プリミティブの場合、どちらを使用するかはおそらく問題ではありません。複雑なオブジェクトを出力したい場合に便利です。

たとえば、クラスがある場合、

#include <iostream>
#include <cstdlib>

using namespace std;

class Something
{
public:
        Something(int x, int y, int z) : a(x), b(y), c(z) { }
        int a;
        int b;
        int c;

        friend ostream& operator<<(ostream&, const Something&);
};

ostream& operator<<(ostream& o, const Something& s)
{
        o << s.a << ", " << s.b << ", " << s.c;
        return o;
}

int main(void)
{
        Something s(3, 2, 1);

        // output with printf
        printf("%i, %i, %i\n", s.a, s.b, s.c);

        // output with cout
        cout << s << endl;

        return 0;
}

上記はそれほど素晴らしいものではないように見えるかもしれませんが、これをコードの複数の場所に出力する必要があるとしましょう。それだけでなく、「int d」フィールドを追加するとします。cout を使用すると、1 か所で変更するだけで済みます。ただし、printf を使用すると、おそらく多くの場所で変更する必要があり、それだけでなく、出力する場所を思い出す必要があります。

そうは言っても、cout を使用すると、コードのメンテナンスに費やす時間を大幅に削減できます。それだけでなく、オブジェクト「何か」を新しいアプリケーションで再利用する場合、出力について心配する必要がありません。

于 2010-05-20T18:02:13.043 に答える
3

私はプログラマーではありませんが、人間工学のエンジニアでした。プログラミング言語は簡単に習得でき、理解しやすく、使いやすいものであるべきだと思います。そのためには、シンプルで一貫した言語構造が必要です。すべての言語は記号的であり、したがって、その核心は恣意的ですが、慣習があり、それらに従うことで、言語の習得と使用が容易になります。

C++ やその他の言語には、関数 (パラメーター) として記述された膨大な数の関数があります。この構文は、コンピューター以前の時代に数学の関数関係に使用されていました。printf()この構文に従い、C++ の作成者がファイルを読み書きするための論理的に異なる方法を作成したい場合は、同様の構文を使用して別の関数を作成するだけで済みます。

Python では、変数はオブジェクトであるため、かなり標準的なobject.method構文、つまり variablename.print を使用してもちろん印刷できますが、C++ ではそうではありません。

<< 演算子は規則に従わないため、cout 構文は好きではありません。これはメソッドまたは関数です。つまり、パラメーターを取り、それに対して何かを行います。ただし、数学的な比較演算子であるかのように記述されています。これは、人的要因の観点からは不十分なアプローチです。

于 2016-03-07T05:09:50.397 に答える
2

その他の違い: 「printf」は整数値 (印刷された文字数に等しい) を返し、「cout」は何も返しません。

と。

cout << "y = " << 7;アトミックではありません。

printf("%s = %d", "y", 7);アトミックです。

cout は型チェックを実行しますが、printf は実行しません。

に相当する iostream はありません"% d"

于 2012-12-05T13:34:56.383 に答える
2
cout<< "Hello";
printf("%s", "Hello"); 

どちらも値を出力するために使用されます。それらは完全に異なる構文を持っています。C++ には両方があり、C には printf しかありません。

于 2010-05-20T09:47:03.367 に答える
2

もちろん、メンテナンスを維持するために「何か」をもう少しうまく書くことができます。

#include <iostream>
#include <cstdlib>

using namespace std;

class Something
{
    public:
        Something(int x, int y, int z) : a(x), b(y), c(z) { }
        int a;
        int b;
        int c;

        friend ostream& operator<<(ostream&, const Something&);

        void print() const { printf("%i, %i, %i\n", a, b, c); }
};

ostream& operator<<(ostream& o, const Something& s)
{
    o << s.a << ", " << s.b << ", " << s.c;
    return o;
}

int main(void)
{
    Something s(3, 2, 1);

    // Output with printf
    s.print(); // Simple as well, isn't it?

    // Output with cout
    cout << s << endl;

    return 0;
}

また、cout と printf のテストを少し拡張し、「double」のテストを追加しました (Visual Studio 2008、実行可能ファイルのリリース バージョン)。

#include <stdio.h>
#include <iostream>
#include <ctime>

class TimedSection {
    char const *d_name;
    //timespec d_start;
    clock_t d_start;

    public:
        TimedSection(char const *name) :
            d_name(name)
        {
            //clock_gettime(CLOCK_REALTIME, &d_start);
            d_start = clock();
        }
        ~TimedSection() {
            clock_t end;
            //clock_gettime(CLOCK_REALTIME, &end);
            end = clock();
            double duration = /*1e3 * (end.tv_sec - d_start.tv_sec) +
                              1e-6 * (end.tv_nsec - d_start.tv_nsec);
                              */
                              (double) (end - d_start) / CLOCKS_PER_SEC;

            std::cerr << d_name << '\t' << std::fixed << duration * 1000.0 << " ms\n";
        }
};


int main() {
    const int iters = 1000000;
    char const *text = "01234567890123456789";
    {
        TimedSection s("cout with only endl");
        for (int i = 0; i < iters; ++i)
            std::cout << std::endl;
    }
    {
        TimedSection s("cout with only '\\n'");
        for (int i = 0; i < iters; ++i)
            std::cout << '\n';
    }
    {
        TimedSection s("printf with only '\\n'");
        for (int i = 0; i < iters; ++i)
            printf("\n");
    }
    {
        TimedSection s("cout with string constant and endl");
        for (int i = 0; i < iters; ++i)
            std::cout << "01234567890123456789" << std::endl;
    }
    {
        TimedSection s("cout with string constant and '\\n'");
        for (int i = 0; i < iters; ++i)
            std::cout << "01234567890123456789\n";
    }
    {
        TimedSection s("printf with string constant and '\\n'");
        for (int i = 0; i < iters; ++i)
            printf("01234567890123456789\n");
    }
    {
        TimedSection s("cout with some stuff and endl");
        for (int i = 0; i < iters; ++i)
            std::cout << text << "01234567890123456789" << i << std::endl;
    }
    {
        TimedSection s("cout with some stuff and '\\n'");
        for (int i = 0; i < iters; ++i)
            std::cout << text << "01234567890123456789" << i << '\n';
    }
    {
        TimedSection s("printf with some stuff and '\\n'");
        for (int i = 0; i < iters; ++i)
            printf("%s01234567890123456789%i\n", text, i);
    }
    {
        TimedSection s("cout with formatted double (width & precision once)");
        std::cout << std::fixed << std::scientific << std::right << std::showpoint;
        std::cout.width(8);
        for (int i = 0; i < iters; ++i)
            std::cout << text << 8.315 << i << '\n';
    }
    {
        TimedSection s("cout with formatted double (width & precision on each call)");
        std::cout << std::fixed << std::scientific << std::right << std::showpoint;

        for (int i = 0; i < iters; ++i)
            { std::cout.width(8);
              std::cout.precision(3);
              std::cout << text << 8.315 << i << '\n';
            }
    }
    {
        TimedSection s("printf with formatted double");
        for (int i = 0; i < iters; ++i)
            printf("%8.3f%i\n", 8.315, i);
    }
}

結果は次のとおりです。

cout with only endl    6453.000000 ms
cout with only '\n'    125.000000 ms
printf with only '\n'    156.000000 ms
cout with string constant and endl    6937.000000 ms
cout with string constant and '\n'    1391.000000 ms
printf with string constant and '\n'    3391.000000 ms
cout with some stuff and endl    9672.000000 ms
cout with some stuff and '\n'    7296.000000 ms
printf with some stuff and '\n'    12235.000000 ms
cout with formatted double (width & precision once)    7906.000000 ms
cout with formatted double (width & precision on each call)    9141.000000 ms
printf with formatted double    3312.000000 ms
于 2011-11-25T08:10:26.630 に答える
1

printf拡張性の欠如は完全に真実ではないと言いたいです:
C では、それは真実です。しかし、C には実際のクラスはありません。
C++ では、キャスト演算子をオーバーロードできるため、演算子をオーバーロードして次のよう char*に使用します。printf

Foo bar;
...;
printf("%s",bar);

Foo が適切な演算子をオーバーロードする場合は可能です。または、あなたが良い方法を作った場合。要するに、私 printfと同じくらい拡張可能です。cout

C++ストリーム(一般的に... coutだけでなく)について私が見ることができる技術的な議論は次のとおりです。

  • タイプセーフ。'\n'(ちなみに、私が使用する単一のものを印刷したい場合はputchar('\n')...昆虫を殺すために核爆弾を使用しません。)

  • より簡単に学べます。(「複雑な」パラメーターを学習する必要はなく、<<and>>演算子を使用するだけです)

  • でネイティブに動作しますstd::stringprintfあるためstd::string::c_str()、しかしscanf?)

私が見るためprintfに:

  • より簡単に、または少なくとも (書かれた文字に関して) より短い複雑な書式設定。私にとっては、はるかに読みやすいです(好みの問題だと思います)。

  • 関数が何を作成したかのより良い制御 (書き込まれた文字数とフォーマッタがある場所を返します%n- C++ リファレンス)

  • より良いデバッグの可能性。最後の引数と同じ理由で。

私の個人的な好みは、主に短い行が好きで、テキストを印刷する際のタイプの問題を回避するのが本当に難しいとは思わないため、printf(および) 関数に行きます。scanfC スタイルの関数で私が嘆いているのstd::stringは、サポートされていないことだけです。char*に渡す前に を通過する必要がありますprintf(std::string::c_str()読みたい場合は を使用しますが、どのように書くのですか?)

于 2012-01-11T10:09:30.153 に答える
-3

printfは関数coutですが、変数です。

于 2014-01-22T20:35:44.673 に答える