web-dev-qa-db-ja.com

引数のコレクションを使用してstd :: stringをフォーマットするにはどうすればよいですか?

引数のセットを渡してstd::stringをフォーマットすることは可能ですか?

現在、文字列を次のようにフォーマットしています。

string helloString = "Hello %s and %s";
vector<string> tokens; //initialized vector of strings
const char* helloStringArr = helloString.c_str();
char output[1000];
sprintf_s(output, 1000, helloStringArr, tokens.at(0).c_str(), tokens.at(1).c_str());

ただし、ベクトルのサイズは実行時に決定されます。引数のコレクションを取り、std :: string/char *をフォーマットするsprintf_sに類似した関数はありますか?私の開発環境はMSVisual C++ 2010Expressです。

編集:私は似たようなことを達成したいと思います:

sprintf_s(output, 1000, helloStringArr, tokens);
15
jilt3d

Boost.Format ライブラリを使用してこれを行うことができます。これは、引数を1つずつフィードできるためです。

これにより、すべての引数を一度に渡す必要があるprintfファミリとはまったく異なり、実際に目標を達成できます(つまり、コンテナ内の各アイテムに手動でアクセスする必要があります)。

例:

#include <boost/format.hpp>
#include <string>
#include <vector>
#include <iostream>
std::string format_range(const std::string& format_string, const std::vector<std::string>& args)
{
    boost::format f(format_string);
    for (std::vector<std::string>::const_iterator it = args.begin(); it != args.end(); ++it) {
        f % *it;
    }
    return f.str();
}

int main()
{
    std::string helloString = "Hello %s and %s";
    std::vector<std::string> args;
    args.Push_back("Alice");
    args.Push_back("Bob");
    std::cout << format_range(helloString, args) << '\n';
}

ここから作業したり、テンプレート化したりできます。

ベクトルに正確な量の引数が含まれていない場合は、例外(ドキュメントを参照)がスローされることに注意してください。それらの処理方法を決定する必要があります。

9
visitor

Sprintfのような機能を実現するための最もC++風の方法は、 stringstreams を使用することです。

コードに基づく例を次に示します。

#include <sstream>

// ...

std::stringstream ss;
std::vector<std::string> tokens;
ss << "Hello " << tokens.at(0) << " and " << tokens.at(1);

std::cout << ss.str() << std::endl;

かなり便利ですね。

もちろん、さまざまなsprintfフラグを置き換えるIOStream操作の利点を最大限に活用できます。参照については、ここ http://www.fredosaurus.com/notes-cpp/io/omanipulators.html を参照してください。

より完全な例:

#include <string>
#include <sstream>
#include <iostream>
#include <iomanip>

int main() {
  std::stringstream s;
  s << "coucou " << std::setw(12) << 21 << " test";

  std::cout << s.str() << std::endl;
  return 0;
}

印刷するもの:

coucou           21 test

編集

OPが指摘しているように、この方法では可変個引数引数を使用できません。これは、ストリームがベクトルを反復処理し、プレースホルダーに従ってデータを挿入できるようにする事前に作成された「テンプレート」文字列がないためです。

12
SirDarius

boost :: format ライブラリは、出力バッファを手動で処理する必要がないようにする場合に役立ちます。

プレーンベクトルを入力として使用する場合、tokens.size()<2の場合はどうなりますか?いずれにせよ、ベクトルが要素0と1にインデックスを付けるのに十分な大きさであることを確認する必要はありませんか?

1
Martin Stone