String.Format alternative in C++

The C++ way would be to use a std::stringstream object as:

std::stringstream fmt;
fmt << a << " " << b << " > " << c;

The C way would be to use sprintf.

The C way is difficult to get right since:

  • It is type unsafe
  • Requires buffer management

Of course, you may want to fall back on the C way if performance is an issue (imagine you are creating fixed-size million little stringstream objects and then throwing them away).


For the sake of completeness, you may use std::stringstream:

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

int main() {
    std::string a = "a", b = "b", c = "c";
    // apply formatting
    std::stringstream s;
    s << a << " " << b << " > " << c;
    // assign to std::string
    std::string str = s.str();
    std::cout << str << "\n";
}

Or (in this case) std::string's very own string concatenation capabilities:

#include <iostream>
#include <string>

int main() {
    std::string a = "a", b = "b", c = "c";
    std::string str = a + " " + b + " > " + c;
    std::cout << str << "\n";
}

For reference:

  • http://en.cppreference.com/w/cpp/string/basic_string/operator+

If you really want to go the C way. Here you are:

#include <iostream>
#include <string>
#include <vector>
#include <cstdio>

int main() {
    std::string a = "a", b = "b", c = "c";
    const char fmt[] = "%s %s > %s";
    // use std::vector for memory management (to avoid memory leaks)
    std::vector<char>::size_type size = 256;
    std::vector<char> buf;
    do {
        // use snprintf instead of sprintf (to avoid buffer overflows)
        // snprintf returns the required size (without terminating null)
        // if buffer is too small initially: loop should run at most twice
        buf.resize(size+1);
        size = std::snprintf(
                &buf[0], buf.size(),
                fmt, a.c_str(), b.c_str(), c.c_str());
    } while (size+1 > buf.size());
    // assign to std::string
    std::string str(buf.begin(), buf.begin()+size);
    std::cout << str << "\n";
}

For reference:

  • http://en.cppreference.com/w/cpp/io/c/fprintf

Since C++11 you can "simplify" this to:

#include <iostream>
#include <string>
#include <vector>
#include <cstdio>

int main() {
    std::string a = "a", b = "b", c = "c";
    const char fmt[] = "%s %s > %s";
    // can use std::string as buffer directly (since C++11)
    std::string::size_type size = 256;
    std::string str;
    do {
        str.resize(size+1);
        // use snprintf instead of sprintf (to avoid buffer overflows)
        // snprintf returns the required size (without terminating null)
        // if buffer is too small initially: loop should run at most twice
        size = std::snprintf(
                &str[0], str.size(),
                fmt, a.c_str(), b.c_str(), c.c_str());
    } while (size+1 > str.size());
    // need to shrink in case the buffer was too big
    str.resize(size+1);
    // done
    std::cout << str << "\n";
}

For reference:

  • Directly write into char* buffer of std::string

Then, there's the Boost Format Library. For the sake of your example:

#include <iostream>
#include <string>
#include <boost/format.hpp>

int main() {
    std::string a = "a", b = "b", c = "c";
    // apply format
    boost::format fmt = boost::format("%s %s > %s") % a % b % c; 
    // assign to std::string
    std::string str = fmt.str();
    std::cout << str << "\n";
}