95

I know that std::cout is the C++ equivalent of printf.

What is the C++ equivalent of sprintf?

Smi
  • 13,151
  • 9
  • 55
  • 63
lital maatuk
  • 5,695
  • 18
  • 55
  • 78

7 Answers7

72

std::ostringstream

Example:

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

Output:

name: nemo, age: 1000
Vijay Mathew
  • 26,037
  • 4
  • 58
  • 92
  • 4
    I don't think that sprintf writes to stdout. I would remove the insertion statement above. – Raffi Khatchadourian May 18 '11 at 01:08
  • 97
    How is this even remotely similar to `sprintf (...)`? You cannot format the data arbitrarily, you have to rely on the type being known when you feed it into the stream using the `< – Andon M. Coleman Feb 27 '14 at 15:40
  • 1
    I need to agree with @AndonM.Coleman about this one. This is not really a sprintf replacement. [This](http://qt-project.org/doc/qt-5/qstring.html#arg) would be more like that, but this is Qt. – lpapp Mar 06 '14 at 17:25
  • as @vinkris says in his answer, iomanip achieves formatting. Instead of printing to stdoit, I would say "result = out.str()". – Dmitri Oct 03 '14 at 04:09
  • sprintf / snprintf allows formating and printing to a user allocated character array, may be on stack. In case of snprintf(), it ensures there is no overrun. Here we are allocating memory multiple times and the caller has no direct access it. Have to convert to a string to get the output. An std::ostream with a custom std::streambuf, which takes user buffer would be a better match - of course construction/destruction of ostream/streambuf adds more in-efficiency. – MGH Aug 09 '18 at 20:39
  • @AndonM.Coleman: You are right, but the context of the answer makes sense when considering the OP's initial sentence. – jxh Feb 19 '19 at 23:55
  • @MGH: `< – Guss Nov 25 '20 at 21:05
38

Update, August 2019:

It looks like C++20 will have std::format. The reference implementation is {fmt}. If you are looking for a printf() alternative now, this will become the new "standard" approach and is worth considering.

Original:

Use Boost.Format. It has printf-like syntax, type safety, std::string results, and lots of other nifty stuff. You won't go back.

janm
  • 17,422
  • 1
  • 41
  • 60
  • 18
    ... unless you are concerned about the size of your executable.. :P – pradyunsg Sep 07 '14 at 15:11
  • How much of an impact would this have? The Boost dependency would be header-only, no linking, correct? – Ken Williams Nov 09 '17 at 19:25
  • 1
    @KenWilliams Yes, Boost.Format is header only. A simple "hello, world" test on my Mac increases from 10kB to 78kB. In a real project the extra size will be amortised across compilation units (give the right linker options), and the type safety brings other benefits. – janm Nov 09 '17 at 21:14
  • When executable size bloats, always try to use shared libraries! – Hunter Kohler Feb 11 '22 at 16:18
20

sprintf works just fine in C++.

Chris Klepeis
  • 9,504
  • 16
  • 81
  • 147
Steve Rowe
  • 19,315
  • 9
  • 50
  • 81
10

Here's a nice function for a c++ sprintf. Streams can get ugly if you use them too heavily.

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

In C++11 and later, std::string is guaranteed to use contiguous storage that ends with '\0', so it is legal to cast it to char * using &str[0].

It has been pointed out that variadic arguments are not supposed to follow pass-by-reference, and c++ is good about not copying strings if it doesn't have to. In that case, this fixes it.

std::string string_format(std::string fmt, ...) {
Erik Aronesty
  • 10,225
  • 4
  • 54
  • 36
7

You can use iomanip header file to format the output stream. Check this!

Community
  • 1
  • 1
vinkris
  • 129
  • 1
  • 6
  • Why did somebody downvote this? Isn't iomanip the pure-C++ way of achieving formatting in streams? I think the goal here is to avoid storing data in C-style strings, which is achieved with iomanip. – Dmitri Oct 03 '14 at 04:06
0

Depending on what exactly you plan on sprintf()ing, std::to_string() might be useful and more idiomatic than other options:

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

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

The main advantage of std::to_string(), IMHO, is that it can be extended easily to support additional types that sprintf() can't even dream of stringifying - kind of like Java's Object.toString() method.

Guss
  • 27,350
  • 15
  • 95
  • 119
-1

Use a stringstream to achieve the same effect. Also, you can include <cstdio> and still use snprintf.

bstpierre
  • 28,439
  • 14
  • 66
  • 101
regality
  • 6,428
  • 6
  • 28
  • 26