102

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

What is the C++ equivalent of sprintf?

Smi
  • 13,850
  • 9
  • 56
  • 64
lital maatuk
  • 5,921
  • 20
  • 57
  • 79

7 Answers7

75

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
Benjamin Loison
  • 3,782
  • 4
  • 16
  • 33
Vijay Mathew
  • 26,737
  • 4
  • 62
  • 93
  • 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
  • 105
    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 `<<` operator. – 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. – László Papp Mar 06 '14 at 17:25
  • 1
    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: `<<` supports formatting (e.g. `<< std::hex() << 42`), otherwise these are all features, not bugs. I tend to think that in most `sprintf()` uses, the requirement to manage memory and protect from over-run is a hassle that should be avoided if possible. C++ offers you easier coding practices (optimize for development time) and are usually not that worse off in terms of CPU time. If you need something super-optimized, there are a few options (including writing C-style or even `asm`) otherwise - come to the darkside of idiomatic C++, we have cookies. – Guss Nov 25 '20 at 21:05
41

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,976
  • 1
  • 43
  • 61
  • 20
    ... 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
21

sprintf works just fine in C++.

Chris Klepeis
  • 9,783
  • 16
  • 83
  • 149
Steve Rowe
  • 19,411
  • 9
  • 51
  • 82
12

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

std::string string_format(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].

Erik Aronesty
  • 11,620
  • 5
  • 64
  • 44
7

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

Community
  • 1
  • 1
vinkris
  • 139
  • 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
1

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
  • 30,470
  • 17
  • 104
  • 128
-1

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

bstpierre
  • 30,042
  • 15
  • 70
  • 103
regality
  • 6,496
  • 6
  • 29
  • 26