How can I format a std::string using a collection of arguments?

jilt3d picture jilt3d · Feb 22, 2011 · Viewed 37.6k times · Source

Is it possible to format std::string passing a set of arguments?

Currently I am formatting the string this way:

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());

But the size of the vector is determined at runtime. Is there any similar function to sprintf_s which takes a collection of arguments and formats a std::string/char*? My development environment is MS Visual C++ 2010 Express.

EDIT: I would like to achieve something similar:

sprintf_s(output, 1000, helloStringArr, tokens);

Answer

SirDarius picture SirDarius · Feb 22, 2011

The most C++-ish way to achieve sprintf-like functionality would be to use stringstreams.

Here is an example based on your code:

#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;

Pretty handy, isn't it ?

Of course, you get the full benefit of IOStream manipulation to replace the various sprintf flags, see here http://www.fredosaurus.com/notes-cpp/io/omanipulators.html for reference.

A more complete example:

#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;
}

which prints:

coucou           21 test

Edit:

As pointed by the OP, this way of doing things does not allow for variadic arguments, because there is no `template' string built beforehand allowing the stream to iterate over the vector and insert data according to placeholders.