sprintfと同等のC ++?


85

私はそれstd::coutがC ++と同等であることを知っていますprintf。にます。

C ++に相当するものは何sprintfですか?

回答:


70

std::ostringstream

例:

#include <iostream>
#include <sstream> // for ostringstream
#include <string>

int main()
{
  std::string name = "nemo";
  int age = 1000;
  std::ostringstream out;  
  out << "name: " << name << ", age: " << age;
  std::cout << out.str() << '\n';
  return 0;
}

出力:

name: nemo, age: 1000

3
sprintfがstdoutに書き込むとは思わない。上記の挿入ステートメントを削除します。
Raffi Khatchadourian 2011年

81
これはリモートでもどのように似ていsprintf (...)ますか?データを任意にフォーマットすることはできません<<。演算子を使用してデータをストリームにフィードするときに認識されているタイプに依存する必要があります。
Andon M. Coleman

1
これについては@ AndonM.Colemanに同意する必要があります。これは実際にはsprintfの代替ではありません。これはもっと似ているでしょうが、これはQtです。
lpapp 2014年

@vinkrisが彼の答えで言っているように、iomanipはフォーマットを実現します。stdoitに出力する代わりに、「result = out.str()」と言います。
dmitri

sprintf / snprintfを使用すると、ユーザーが割り当てた文字配列をフォーマットして印刷できます。スタック上にある場合もあります。snprintf()の場合、オーバーランがないことを保証します。ここでは、メモリを複数回割り当てており、呼び出し元はメモリに直接アクセスできません。出力を取得するには、文字列に変換する必要があります。ユーザーバッファを使用するカスタムstd :: streambufを使用したstd :: ostreamの方が適しています。もちろん、ostream / streambufの構築/破棄により、非効率性が高まります。
MGH 2018

35

更新、2019年8月:

C ++ 20にはが含まれるようstd::formatです。リファレンス実装は{fmt}です。あなたが探しているならprintf()今代替案、これは新しい「標準的な」アプローチになり、検討する価値があります。

元の:

Boost.Formatを使用します。それは持っているprintf様な構文、型の安全性、std::string結果、および他の気の利いたものがたくさん。あなたは戻らないでしょう。


15
...実行可能ファイルのサイズが気にならない限り..:P
pradyunsg 2014

これはどのくらいの影響がありますか?Boostの依存関係はヘッダーのみで、リンクはありませんよね?
ケンウィリアムズ

1
@KenWilliamsはい、Boost.Formatはヘッダーのみです。Macでの単純な「Hello、World」テストが10kBから78kBに増加します。実際のプロジェクトでは、余分なサイズはコンパイルユニット全体で償却され(適切なリンカーオプションを指定)、型の安全性は他の利点をもたらします。
janm 2017年

18

sprintfはC ++で問題なく動作します。


5
OPはC ++ではなくSTLを意味していると思います。
ジャンマイケルCelerier

4
sprintfでは、文字バッファを割り当てる必要があります。「std :: string」の「append」メソッドのように、フォーマットされたデータを追加し、バックグラウンドでの割り当てを処理できるものが欲しいのですが。
ビクターアイフハウト2015年

7

iomanipヘッダーファイルを使用して、出力ストリームをフォーマットできます。これをチェックしてください!


なぜ誰かがこれに反対したのですか?iomanipは、ストリームのフォーマットを実現する純粋なC ++の方法ではありませんか?ここでの目標は、iomanipで実現されるCスタイルの文字列にデータを格納しないようにすることだと思います。
dmitri

7

これがc ++ sprintfの素晴らしい関数です。ストリームを多用しすぎると、ストリームが醜くなる可能性があります。

std::string string_format(const std::string &fmt, ...) {
    int size=100;
    std::string str;
    va_list ap;

    while (1) {
        str.resize(size);
        va_start(ap, fmt);
        int n = vsnprintf(&str[0], size, fmt.c_str(), ap);
        va_end(ap);
   
        if (n > -1 && n < size) {
            str.resize(n); // Make sure there are no trailing zero char
            return str;
        }
        if (n > -1)
            size = n + 1;
        else
            size *= 2;
    }
}

C ++ 11以降では、STD ::文字列があることで両端を連続したストレージを使用することが保証されて'\0'、それをキャストするために合法であるので、char *使用します&str[0]

可変個引数は参照渡しに従うべきではないことが指摘されており、c ++は、必要がなければ文字列をコピーしないのが得意です。その場合、これで修正されます。

std::string string_format(std::string fmt, ...) {

とても素敵な解決策です!私はここでそれを適応させました:stackoverflow.com/a/3742999/15161-usageにもっとぴったり合うようにsprintf
slashmais 2012

10
ただし、違法(char*) str.c_str()ですconst
MSalters 2013年

また、バッファオーバーフローの問題が潜んでいます
Barney Szabolcs 2015年

@MSalters正解です。C ++ 11でそれを行う合法的な方法があります。
ホワイトクォーク2015

@whitequark:それを答えとして自由に追加してください。Stack Overflowでは、新しい回答を可能にするために良い質問が開かれたままです。
MSalters 2015

1

あなたが上で計画して正確に何によってsprintf()ING、std::to_string()便利および他のオプションよりも慣用的であるかもしれません。

void say(const std::string& message) {
 // ...
}

int main() {
  say(std::to_string(5));
  say("Which is to say " + std::to_string(5) + " words");
}

std::to_string()IMHOの主な利点は、sprintf()JavaのObject.toString()メソッドのように、文字列化を夢見ることさえできない追加の型をサポートするように簡単に拡張できることです。


0

同じ効果を達成するには、stringstreamを使用します。また、<cstdio>snprintfを含めて引き続き使用することもできます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.