8

I'm used to easy-to-read syntax for string interpolation like this in c# or JavaScript, so when I started learning c++ I expected that it will have a similar feature, but when googling for string interpolation in c++ I couldn't find anything like that.

In c# strings are interpolated like this:

$"My variable has value {myVariable}"

In JavaScript it looks like this:

`My variable has value ${myVariable}`

Inserting multiple values in different places in a string literal is such a common problem I'm sure there is some standard way of doing this in c++. I want to know what is the simplest way of doing this in c++ and how do people usually do it.

Kacper
  • 520
  • 5
  • 20
  • 2
    You can't actually do that in standard c++. But from c++20, [``](https://en.cppreference.com/w/cpp/utility/format/format) should do what you want. – cigien Jul 27 '20 at 18:57
  • [std:printf](https://en.cppreference.com/w/cpp/io/c/fprintf), [fmt::print](https://fmt.dev/latest/index.html), [std::format](https://en.cppreference.com/w/cpp/utility/format/format) – Thomas Sablik Jul 27 '20 at 18:58
  • [Doc page for `std::format`](https://en.cppreference.com/w/cpp/utility/format/format) – user4581301 Jul 27 '20 at 18:58
  • You can use classical `sprintf` and also `std::stringstream`. – Thomas Matthews Jul 27 '20 at 18:59
  • 1
    Be cautious with `printf` It's handy, but very easy to up. – user4581301 Jul 27 '20 at 18:59
  • [std::to_string](https://en.cppreference.com/w/cpp/string/basic_string/to_string) – Jesper Juhl Jul 27 '20 at 19:08
  • 3
    Does this answer your question? [How to construct a std::string with embedded values, i.e. "string interpolation"?](https://stackoverflow.com/questions/37956090/how-to-construct-a-stdstring-with-embedded-values-i-e-string-interpolation) – Chris Long Dec 16 '20 at 18:28

3 Answers3

8

From c++20 you can use the <format> header to do something like this:

auto s = std::format("My variable has value {}", myVariable);

which is quite similar to how it's done in c# or JavaScript.

cigien
  • 57,834
  • 11
  • 73
  • 112
  • That's cool -- as soon as I start using C++20 I am switching to that... – wcochran Jul 27 '20 at 19:08
  • 1
    @wcochran Of course, who isn't? :) If you don't want to wait, you could consider using [fmt](https://fmt.dev/latest/index.html) on which this header is inspired. – cigien Jul 27 '20 at 19:10
  • Not as easy-to-read as c#/js but still quite nice. But if this is will be in c++20 then what methods do people usually use now? – Kacper Jul 28 '20 at 13:36
  • 1
    @Kacper Depends on the use case, but people often use things like `printf` or `to_string`, or some external library like `fmt`. – cigien Jul 28 '20 at 13:37
  • 1
    that is not easy-to-read. You should start the answer with something like "not really, but..." – Superior Oct 02 '20 at 16:05
  • @Superior No, I disagree. I think it's very readable actually :) – cigien Oct 02 '20 at 16:11
  • @cigien It does actually answers the question, however, it's nothing as beautiful as or alike C# or JavaScript. It is clear in bigger formats with many members. There you have to follow & count every `{}` to understand what goes where – Superior Oct 03 '20 at 14:03
  • @Superior No, you can provide the index as well. e.g. the above example could be written as `std::format("My variable has value {0}", myVariable)` so it's much easier to see what goes where if there are multiple arguments. Also, I'm not trying to compare c++ to other languages so much as trying to show the simplest way currently possible in c++ :) – cigien Oct 03 '20 at 14:06
8

FWIW, here is a C++11 safe version of sprintf that returns a std::string

template<typename... Args>
std::string Sprintf(const char *fmt, Args... args)
{
    const size_t n = snprintf(nullptr, 0, fmt, args...);
    std::vector<char> buf(n+1);
    snprintf(buf.data(), n+1, fmt, args...);
    return std::string(buf.data());
}

You can then do this:

float var = 0.123f;
std::string str = Sprintf("My variable has value %0.4f\n", var);

I like @cigien's answer if you are using C++20.

wcochran
  • 10,089
  • 6
  • 61
  • 69
3

A possible way, particularly in embedded environment, is to utilize the C standard library:

#include <cstdio>

...
printf("My variable is %s\n", myVariable)
...

myVariable has to be a char*. For C++ strings, myVariable.c_str() should be used.

peterh
  • 11,875
  • 18
  • 85
  • 108
  • 1
    BTW, `sprintf` is available for printing to strings. – Thomas Matthews Jul 27 '20 at 19:08
  • 1
    `sprintf` prints to C-string (not `std::string`) and `sprintf` is not safe and you should get compiler warnings when using it. At least use `snprintf` which will help avoid buffer overflow. – wcochran Jul 27 '20 at 21:05
  • Possibly also an `asprintf(...)` could be used in a GNU environment, which would handle the dynamical memory allocations. Or, alternatively, a `vsnprintf(...)` into a buffer on the stack, and then generate an `std::string` from that buffer. Possibly there is same stl API call for this functionality. – peterh Jul 27 '20 at 21:20