std::string aware options for vsprintf - c++

I have an old MUD codebase in C (>80k lines) that uses printf-style string formatting. It is pervasive -- almost every bit of text runs through calls to either sprintf or a wrapper around vsprintf. However, I have recently moved to compiling with g++ to take advantage of the STL, and would like to use std::string (actually a derived class for default case-insensitive comparisons) where it makes sense.
Obviously, you can't pass std::string as one of the variadic arguments to any of the printf functions: I need .c_str() in every case. I don't want to do that, mostly because I don't want to modify 2000+ calls to printf functions. My question is: how can I make a std::string aware vsprintf?
The way I see it, I have two options: write my own printf functions that iterate through the arguments changing pointers to std::string to std::string.data (or c_out()) before passing to std::vsprintf, or I can borrow the guts of printf and roll my own. The first option sounds like less work, obviously.
Of course, a better option is if someone has done this before, but my googling is yielding nothing. Any tips on what the best option would look like?
EDIT:
This question was closed as a duplicate of How to use C++ std::ostream with printf-like formatting?, which I don't believe answers the question. I'm not asking how to output strings with std::ostream vs the old C printf. I'm asking for help with a patch solution for an old C codebase that makes extensive use of sprintf/vsprintf, without rewriting thousands of calls to those functions to use output streams.

You can make your own printf wrapper, that extracts char const* from std::string. E.g.:
#include <iostream>
#include <string>
#include <cstdio>
template<class T>
inline auto to_c(T&& arg) -> decltype(std::forward<T>(arg)) {
return std::forward<T>(arg);
}
inline char const* to_c(std::string const& s) { return s.c_str(); }
inline char const* to_c(std::string& s) { return s.c_str(); }
template<class... Args>
int my_printf(char const* fmt, Args&&... args) {
return std::printf(fmt, to_c(args)...);
}
int main() {
std::string name = "World";
my_printf("Hello, %s!\n", name);
}
Or, better, switch to a modern C++ formatting library, such as fmt.

The common advice is Boost.Format
Taking their example:
// printf directives's type-flag can be used to pass formatting options :
std::cout << format("_%1$4d_ is : _%1$#4x_, _%1$#4o_, and _%1$s_ by default\n") % 18;
// prints "_ 18_ is : _0x12_, _ 022_, and _18_ by default\n"
Now this assumes std::ostream&, so you'll need a std::stringstream to use a std::string as the backing buffer.
PS. using a derived class for case-insensitive comparisons sounds like a bad idea waiting to bite you. You just need a custom order; all the STL functions that assume ordering have overloads to support custom orderings.

Related

C# String.Format with Parameters standard equivalent in C++?

I have a lot of C# Code that I have to write in C++. I don't have much experience in C++.
I am using Visual Studio 2012 to build. The project is an Static Library in C++ (not in C++/CLI).
In many places they were using String.Format, like this:
C#
String.Format("Some Text {0}, some other Text {1}", parameter0, parameter1);
Now, I know similar things have been asked before, but It is not clear to me what is the most standard/safe way to do this.
Would it be safe to use something like sprintf or printf? I read some people mentioning like they are not standard. Something like this? (would this be the C++ way, or is more the C way?)
C++ (or is it C?)
char buffer [50];
int n, a=5, b=3;
n=sprintf (buffer, "Some Text %d, some other Text %d", a, b);
Other people suggested to do your own class, and I saw many different implementations.
For the time being, I have a class that uses std::to_string, ostringstream, std::string.replace and std::string.find, with Templates. My class is rather limited, but for the cases I have in the C# code, it works. Now I don't know this is the most efficient way (or even correct at all):
C++
template <typename T>
static std::string ToString(T Number)
{
std::ostringstream stringStream;
stringStream << Number;
std::string string = stringStream.str();
return string;
};
template <typename T,unsigned S>
static std::string Format(const std::string& stringValue, const T (&parameters)[S])
{
std::string stringToReturn = std::string(stringValue);
for (int i = 0; i < S; ++i)
{
std::string toReplace = "{"+ std::to_string(i) +"}";
size_t f = stringToReturn.find(toReplace);
if(std::string::npos != f)
stringToReturn.replace(f, toReplace.length(), ToString(parameters[i]));
}
return stringToReturn;
};
//I have some other overloads that call the Format function that receives an array.
template <typename T>
static std::string Format(const std::string& stringValue, const T parameter, const T parameter2)
{
T parameters[] = {parameter, parameter2};
return Format(stringValue, parameters);
};
And I need my code to work both in Linux and Windows, so I need different compilers to be able to build it, that is why I need to be sure I am using a standard way. And my environment can not be updated so easily, so I can not use C++11. I can not use Boost either, because I can not be sure I will be able to add the libraries in the different environments I need it to work.
What is the best approach I can take in this case?
Here's a 1-header library I've been writing just for that purpose: fakeformat
Test:
REQUIRE(ff::format("{2}ff{1}").with('a').also_with(7).now()=="7ffa");
The library is configurable, so that you can start parameter indexing from 0. You can also write a wrapper, so that it would look exactly like String.Format.
It builds on linux and doesn't need c++11.
There's no standard way yet...
Or, you could use Boost.Locale formatting
Here it is, with indices starting from 0:
#include ...
struct dotnet_config {
static const char scope_begin='{';
static const char scope_end='}';
static const char separator=',';
static const char equals='=';
static const size_t index_begin=0;
static bool string_to_key(std::string const& to_parse,int& res) {
std::istringstream ss(to_parse);
ss.imbue(std::locale::classic());
ss >> res;
if (!ss.fail() && ss.eof())
return true;
return false;
}
};
template <typename T1>
std::string Format (std::string const& format_string,T1 p1) {
return ff::formatter<dotnet_config>(format_string).with(p1).now();
}
template <typename T1,typename T2>
std::string Format (std::string const& format_string,T1 p1,T2 p2) {
return ff::formatter<dotnet_config>(format_string).with(p1).with(p2).now();
}
int main() {
std::cout<<Format("test={0}",42)<<std::endl;
std::cout<<Format("{0}!={1}",33,42)<<std::endl;
return 0;
}
Output:
test=42
33!=42
sprintf works if all you have are non-object types (or you manually convert them to C-strings, or convert them to strings and then call the c_str() member function). You may want the extra protection against buffer overflow that snprintf provides.
If you're willing to learn more to do what you have to, you can use the Boost Format library. I'm sure you can write a script to convert String.format calls to Boost's syntax.
If you can't use Boost, and you can't use C++11, you have to go with sprintf and be careful about buffer overflow (possibly snprintf if you can rely on your compiler having it). You might want to write a script to wrap all the parameters so that they all convert to strings:
String.Format("Some Text {0}, some other Text {1}", to_printf(p0), to_printf(p1));
Also, note that C's format doesn't use braces. So that's a big problem. You may need to implement your own variadic function.
If everything is simple like {0}, you can probably write a script to replace most instances of String.Format (and none of the more complicated ones) with something like
`mystring = "Some Text "+tostring(p0)+", some other Text "+tostring(p1);`
which wouldn't be the most efficient way, but most likely won't matter unless you're doing thousands of formats per second. Or possibly slightly more efficient (no intermediate strings):
`"mystring = static_cast<std::ostringstream&>(std::ostringstream().flush()<<Some Text "<<p0<<", some other Text "<<p1).str();`,
which creates a temporary. The flush sort of tricks the compiler into thinking it's not a temporary, and that solves a specific problem about not being able to use non-member operator<<.
Why don't you use the << operator to format your string?
string strOutput;
stringstream strn;
int i = 10;
float f = 20.0f;
strn << "Sally scored "<<i<< " out of "<<f << ". She failed the test!";
strn >> strOutput;
cout << strOutput;

Why doesn't the string class have a << operator (operator<<) predefined so that strings work like ostringstreams?

It seems to me that defining the << operator (operator<<) to work directly with strings is more elegant than having to work with ostringstreams and then converting back to strings. Is there a reason why c++ doesn't do this out of the box?
#include <string>
#include <sstream>
#include <iostream>
using namespace std;
template <class T>
string& operator<<(string& s, T a) {
ostringstream ss;
ss << a;
s.append(ss.str());
return s;
}
int main() {
string s;
// this prints out: "inserting text and a number(1)"
cout << (s << "inserting text and a number (" << 1 << ")\n");
// normal way
ostringstream os;
os << "inserting text and a number(" << 1 << ")\n";
cout << os.str();
}
Streams contain additional state. Imagine if this were possible:
std::string str;
int n = 1234;
str << std::hex;
str << n;
return str; // returns "0x4d2" (or something, I forget)
In order to maintain this additional state, strings would have to have storage for this state. The C++ standards committee (and C++ programmers in general) have generally frowned upon superfluous resource consumption, under the motto "pay only for what you use". So, no extra fields in the string class.
The subjective answer: is that I think the std::string class was quite poorly designed to begin with, especially compared to other parts of C++'s excellent standard library, and adding features to std::string is just going to make things worse. This is a very subjective opinion and feel free to dismiss me as a raving lunatic.
The problem with the idea of strings being output streams is that they would become too heavy.
Strings are intended to "hold string data", not to format some output. Output streams have a heavy "state" which can be manipulated (see <iomanip>) and thus has to be stored. This means that, of course, this has to be stored for every string in every program, but almost none of them are used as an output stream; so it's a huge waste of resources.
C++ follows the "zero overhead" design principle (or at least no more overhead than totally necessary). Not having a string class which doesn't add any unnecessary overhead would be a huge violation of this design principle. If this was the case: what would people do in overhead-critical cases? Use C-strings... ouch!
In C++11, an alternative is to use the operator+= with std::to_string to append to a string, which can also be chained like the operator<< of the output stream. You can wrap both += and to_string in a nice operator<< for string if you like:
template <class Number>
std::string& operator<<(std::string& s, Number a) {
return s += std::to_string(a);
}
std::string& operator<<(std::string& s, const char* a) {
return s += a;
}
std::string& operator<<(std::string& s, const std::string &a) {
return s += a;
}
Your example, updated using this method: http://ideone.com/4zbVtD
Probably lost in the depths of time now but formatted output was always associated with streams in C (since they didn't have "real" strings) and this may have been carried over into C++ (which was, after all, C with classes). In C, the way to format to a string is to use sprintf, a variation on fprintf, the output-to-stream function.
Obviously conjecture on my part but someone probably thought similarly to yourself that these formatting things in the streams would be brilliant to have on strings as well, so they subclassed the stream classes to produce one that used a string as it's "output".
That seems the elegant solution to getting it working as quickly as possible. Otherwise, you would have had formatting code duplicated in streams and strings.

Using templates for implementing a generic string parser

I am trying to come up with a generic solution for parsing strings (with a given format). For instance, I would like to be able to parse a string containing a list of numeric values (integers or floats) and return a std::vector. This is what I have so far:
template<typename T, typename U>
T parse_value(const U& u) {
throw std::runtime_error("no parser available");
}
template<typename T>
std::vector<T> parse_value(const std::string& s) {
std::vector<std::string> parts;
boost::split(parts, s, boost::is_any_of(","));
std::vector<T> res;
std::transform(parts.begin(), parts.end(), std::back_inserter(res),
[](const std::string& s) { return boost::lexical_cast<T>(s); });
return res;
}
Additionally, I would like to be able to parse strings containing other type of values. For instance:
struct Foo { /* ... */ };
template<>
Foo parse_value(const std::string& s) {
/* parse string and return a Foo object */
}
The reason to maintain a single "hierarchy" of parse_value functions is because, sometimes, I want to parse an optional value (which may exist or not), using boost::optional. Ideally, I would like to have just a single parse_optional_value function that would delegate on the corresponding parse_value function:
template<typename T>
boost::optional<T> parse_optional_value(const boost::optional<std::string>& s) {
if (!s) return boost::optional<T>();
return boost::optional<T>(parse_value<T>(*s));
}
So far, my current solution does not work (the compiler cannot deduce the exact function to use). I guess the problem is that my solution relies on deducing the template value based on the return type of parse_value functions. I am not really sure how to fix this (or even whether it is possible to fix it, since the design approach could just be totally flawed). Does anyone know a way to solve what I am trying to do? I would really appreciate if you could just point me to a possible way to address the issues that I am having with my current implementation. BTW, I am definitely open to completely different ideas for solving this problem too.
You cannot overload functions based on return value [1]. This is precisely why the standard IO library uses the construct:
std::cin >> a >> b;
which may not be your piece of cake -- many people don't like it, and it is truly not without its problems -- but it does a nice job of providing a target type to the parser. It also has the advantage over a static parse<X>(const std::string&) prototype that it allows for chaining and streaming, as above. Sometimes that's not needed, but in many parsing contexts it is essential, and the use of operator>> is actually a pretty cool syntax. [2]
The standard library doesn't do what would be far and away the coolest thing, which is to skip string constants scanf style and allow interleaved reading.
vector<int> integers;
std::cin >> "[" >> interleave(integers, ",") >> "]";
However, that could be defined. (Possibly it would be better to use an explicit wrapper around the string literals, but actually I prefer it like that; but if you were passing a variable you'd want to use a wrapper).
[1] With the new auto declaration, the reason for this becomes even clearer.
[2] IO manipulators, on the other hand, are a cruel joke. And error handling is pathetic. But you can't have everything.
Here is an example of libsass parser:
const char* interpolant(const char* src) {
return recursive_scopes< exactly<hash_lbrace>, exactly<rbrace> >(src);
}
// Match a single character literal.
// Regex equivalent: /(?:x)/
template <char chr>
const char* exactly(const char* src) {
return *src == chr ? src + 1 : 0;
}
where rules could be passed into the lex method.

Should I use printf in my C++ code?

I generally use cout and cerr to write text to the console. However sometimes I find it easier to use the good old printf statement. I use it when I need to format the output.
One example of where I would use this is:
// Lets assume that I'm printing coordinates...
printf("(%d,%d)\n", x, y);
// To do the same thing as above using cout....
cout << "(" << x << "," << y << ")" << endl;
I know I can format output using cout but I already know how to use the printf. Is there any reason I shouldn't use the printf statement?
My students, who learn cin and cout first, then learn printf later, overwhelmingly prefer printf (or more usually fprintf). I myself have found the printf model sufficiently readable that I have ported it to other programming languages. So has Olivier Danvy, who has even made it type-safe.
Provided you have a compiler that is capable of type-checking calls to printf, I see no reason not to use fprintf and friends in C++.
Disclaimer: I am a terrible C++ programmer.
If you ever hope to i18n your program, stay away from iostreams. The problem is that it can be impossible to properly localize your strings if the sentence is composed of multiple fragments as is done with iostream.
Besides the issue of message fragments, you also have an issue of ordering. Consider a report that prints a student's name and their grade point average:
std::cout << name << " has a GPA of " << gpa << std::endl;
When you translate that to another language, the other language's grammar may need you to show the GPA before the name. AFAIK, iostreams has not way to reorder the interpolated values.
If you want the best of both worlds (type safety and being able to i18n), use Boost.Format.
I use printf because I hate the ugly <<cout<< syntax.
Adaptability
Any attempt to printf a non-POD results in undefined behaviour:
struct Foo {
virtual ~Foo() {}
operator float() const { return 0.f; }
};
printf ("%f", Foo());
std::string foo;
printf ("%s", foo);
The above printf-calls yield undefined behaviour. Your compiler may warn you indeed, but those warnings are not required by the standards and not possible for format strings only known at runtime.
IO-Streams:
std::cout << Foo();
std::string foo;
std::cout << foo;
Judge yourself.
Extensibility
struct Person {
string first_name;
string second_name;
};
std::ostream& operator<< (std::ostream &os, Person const& p) {
return os << p.first_name << ", " << p.second_name;
}
cout << p;
cout << p;
some_file << p;
C:
// inline everywhere
printf ("%s, %s", p.first_name, p.second_name);
printf ("%s, %s", p.first_name, p.second_name);
fprintf (some_file, "%s, %s", p.first_name, p.second_name);
or:
// re-usable (not common in my experience)
int person_fprint(FILE *f, const Person *p) {
return fprintf(f, "%s, %s", p->first_name, p->second_name);
}
int person_print(const Person *p) {
return person_fprint(stdout, p);
}
Person p;
....
person_print(&p);
Note how you have to take care of using the proper call arguments/signatures in C (e.g. person_fprint(stderr, ..., person_fprint(myfile, ...), where in C++, the "FILE-argument" is automatically "derived" from the expression. A more exact equivalent of this derivation is actually more like this:
FILE *fout = stdout;
...
fprintf(fout, "Hello World!\n");
person_fprint(fout, ...);
fprintf(fout, "\n");
I18N
We reuse our Person definition:
cout << boost::format("Hello %1%") % p;
cout << boost::format("Na %1%, sei gegrüßt!") % p;
printf ("Hello %1$s, %2$s", p.first_name.c_str(), p.second_name.c_str());
printf ("Na %1$s, %2$s, sei gegrüßt!",
p.first_name.c_str(), p.second_name.c_str());
Judge yourself.
I find this less relevant as of today (2017). Maybe just a gut feeling, but I18N is not something that is done on a daily basis by your average C or C++ programmer. Plus, it's a pain in the a...natomy anyways.
Performance
Have you measured the actual significance of printf performance? Are your bottleneck applications seriously so lazy that the output of computation results is a bottleneck? Are you sure you need C++ at all?
The dreaded performance penalty is to satisfy those of you who want to use a mix of printf and cout. It is a feature, not a bug!
If you use iostreams consistently, you can
std::ios::sync_with_stdio(false);
and reap equal runtime with a good compiler:
#include <cstdio>
#include <iostream>
#include <ctime>
#include <fstream>
void ios_test (int n) {
for (int i=0; i<n; ++i) {
std::cout << "foobarfrob" << i;
}
}
void c_test (int n) {
for (int i=0; i<n; ++i) {
printf ("foobarfrob%d", i);
}
}
int main () {
const clock_t a_start = clock();
ios_test (10024*1024);
const double a = (clock() - a_start) / double(CLOCKS_PER_SEC);
const clock_t p_start = clock();
c_test (10024*1024);
const double p = (clock() - p_start) / double(CLOCKS_PER_SEC);
std::ios::sync_with_stdio(false);
const clock_t b_start = clock();
ios_test (10024*1024);
const double b = (clock() - b_start) / double(CLOCKS_PER_SEC);
std::ofstream res ("RESULTS");
res << "C ..............: " << p << " sec\n"
<< "C++, sync with C: " << a << " sec\n"
<< "C++, non-sync ..: " << b << " sec\n";
}
Results (g++ -O3 synced-unsynced-printf.cc, ./a.out > /dev/null, cat RESULTS):
C ..............: 1.1 sec
C++, sync with C: 1.76 sec
C++, non-sync ..: 1.01 sec
Judge ... yourself.
No. You won't forbid me my printf.
You can haz a typesafe, I18N friendly printf in C++11, thanks to variadic templates. And you will be able to have them very, very performant using user-defined literals, i.e. it will be possible to write a fully static incarnation.
I have a proof of concept. Back then, support for C++11 was not as mature as it is now, but you get an idea.
Temporal Adaptability
// foo.h
...
struct Frob {
unsigned int x;
};
...
// alpha.cpp
... printf ("%u", frob.x); ...
// bravo.cpp
... printf ("%u", frob.x); ...
// charlie.cpp
... printf ("%u", frob.x); ...
// delta.cpp
... printf ("%u", frob.x); ...
Later, your data grows so big you must do
// foo.h
...
unsigned long long x;
...
It is an interesting exercise maintaining that and doing it bug-free. Especially when other, non-coupled projects use foo.h.
Other.
Bug Potential: There's a lot of space to commit mistakes with printf, especially when you throw user input bases strings in the mix (think of your I18N team). You must take care to properly escape every such format string, you must be sure to pass the right arguments, etc. etc..
IO-Streams make my binary bigger: If this is a more important issue than maintainability, code-quality, reuseability, then (after verifying the issue!) use printf.
Use boost::format. You get type safety, std::string support, printf like interface, ability to use cout, and lots of other good stuff. You won't go back.
Use printf. Do not use C++ streams. printf gives you much better control (such as float precision etc.). The code is also usually shorter and more readable.
Google C++ style guide agrees.
Do not use streams, except where
required by a logging interface. Use
printf-like routines instead.
There are various pros and cons to
using streams, but in this case, as in
many other cases, consistency trumps
the debate. Do not use streams in your
code.
No reason at all. I think it's just some strange ideology that drives people towards using only C++ libraries even though good old C libs are still valid. I'm a C++ guy and I use C functions a lot too. Never had any problems with them.
On the whole I agree (hate the << syntax especially if you need complex formatting)
But I should point out the safety aspects.
printf("%x",2.0f)
printf("%x %x",2)
printf("%x",2,2)
Probably won't be noticed by the compiler but could crash your app.
Streams are the canonical way. Try making this code work with printf:
template <typename T>
void output(const T& pX)
{
std::cout << pX << std::endl;
}
Good luck.
What I mean is, you can make operators to allow your types to be outputted to ostream's, and without hassle use it just like any other type. printf doesn't fit the the generality of C++, or more specifically templates.
There's more than usability. There's also consistency. In all my projects, I have cout (and cerr and clog) tee'd to also output to a file. If you use printf, you skip all of that. Additionally, consistency itself is a good thing; mixing cout and printf, while perfectly valid, is ugly.
If you have an object, and you want to make it output-able, the cleanest way to do this is overload operator<< for that class. How are you going to use printf then? You're going to end up with code jumbled with cout's and printf's.
If you really want formatting, use Boost.Format while maintaining the stream interface. Consistency and formatting.
Use whatever fits your needs and preferences. If you're comfortable with printf then by all means use it. If you're happier with iostreams stick to 'em. Mix and match as best fits your requirements. This is software, after all - there's better ways and worse ways, but seldom is there only ONE way.
Share and enjoy.
You can get the best of both worlds with the {fmt} library which combines safety and extensibility of iostreams with usability and performance of (s)printf. Example:
fmt::print("The answer is {}.", 42);
The library supports Python-like and printf format string syntax.
Disclaimer: I'm the author of this library.
I do not like printf. Its lack of type-safety makes it dangerous to use, plus the need to remember format specifiers is a pain. The templated operators that smartly do the right thing are much better. So I always use the C++ streams in C++.
Granted, many people prefer printf, for other reasons, enumerated elsewhere.
I often "drop back" to using printf(), but more often snprintf() for easier formatted output. When programming in C++ I use this wrapper I wrote a while back, called like this (to use your example as above): cout << format("(%d,%d)\n", x, y);
Here's the header (stdiomm.h):
#pragma once
#include <cstdarg>
#include <string>
template <typename T>
std::basic_string<T> format(T const *format, ...);
template <typename T>
std::basic_string<T> vformat(T const *format, va_list args);
And the source (stdiomm.cpp):
#include "stdiomm.h"
#include <boost/scoped_array.hpp>
#include <cstdio>
template <>
std::wstring vformat(wchar_t const *format, va_list arguments)
{
#if defined(_WIN32)
int required(_vscwprintf(format, arguments));
assert(required >= 0);
boost::scoped_array<wchar_t> buffer(new wchar_t[required + 1]);
int written(vswprintf(buffer.get(), required + 1, format, arguments));
assert(written == required);
return std::wstring(buffer.get(), written);
#else
# error "No implementation yet"
#endif
}
template <>
std::string vformat(char const *format, va_list arguments)
{
#if defined(_WIN32)
int required(_vscprintf(format, arguments));
assert(required >= 0);
boost::scoped_array<char> buffer(new char[required + 1]);
int written(vsnprintf(buffer.get(), required + 1, format, arguments));
assert(written == required);
return std::string(buffer.get(), written);
#else
char *buffer;
int printed = vasprintf(&buffer, format, arguments);
assert(printed != -1);
std::string retval(buffer, printed);
free(buffer);
return retval;
#endif
}
template <typename T>
std::basic_string<T> format(T const *format, ...)
{
va_list ap;
va_start(ap, format);
std::basic_string<T> retval(vformat(format, ap));
va_end(ap);
return retval;
}
template std::wstring format(wchar_t const *format, ...);
template std::string format(char const *format, ...);
Update
After reading some of the other answers, I might have to make a switch to boost::format() myself!
I almost always use printf for temporary debugging statements. For more permanent code, I prefer the 'c' streams as they are The C++ Way. Although boost::format looks promising and might replace my stream usage (especially for complexly formatted output), probably nothing will replace printf for me for a long time.
C++ streams are overrated, after all they're in fact just classes with an overloaded operator <<.
I've read many times that streams are the C++ way as printf is the C way, but they are both library features available in C++, so you should use what suits best.
I mostly prefer printf, but I've also used streams, which provide cleaner code and prevent you from having to match % placeholders to arguments.
Even though the question is rather old, I want to add my two cents.
Printing user-created objects with printf()
This is rather simple if you think about it - you can stringify your type and sent the string to printf:
std::string to_string(const MyClass &x)
{
return to_string(x.first)+" "+to_string(x.second);
}
//...
printf("%s is awesome", to_string(my_object).c_str()); //more or less
A shame there wasn't (there is C++11 to_string()) standarized C++ interface to stringify objects...
printf() pitfall
A single flag - %n
The only one that is an output parameter - it expects pointer to int. It writes number of succesfully written characters to location pointed by this pointer. Skillful use of it can trigger overrun, which is security vulnerability (see printf() format string attack).
I have read warnings saying that cout and cerr are unsafe for multithreading. If true, this is a good reason to avoid using them. Note: I use GNU g++ with openMP.
(See the fmt library homepage)
In C++20, the fmt library is standardized for the formatting part:
std::format("({},{})\n", x, y) // returns a std::string
You can avoid the dynamic allocation overhead by using format_to:
std::format_to(/* output iterator */, "({},{})\n", x, y);
This should be considered the canonical way of formatting because it combines the benefits of streams:
Safety: the library is fully type safe. Automatic memory management prevents buffer overflow. Errors in format strings are reported using exceptions or at compile time.
Extensibility: overloading operator<< is easy, whereas extending printf is ... not so easy.
and that of printf:
Ease to use: the % syntax is supported rather than the verbose manipulators. The {} syntax is also introduced to eliminate the specifiers.
Performance: measurement has shown that the fmt library is so far the fastest output method in C++. Faster than printf and streams.
It depends on the situation. Nothing is perfect. I use both. Streams are good for custom types as you can overload the >> operator in ostream. But when it comes to spacing and etc it's better to use printf(). stringstream and like are better than the C style strcat(). So use one that's appropriate for the situation.
streams are preferred in cpp as they adhere to the object oriented paradigm of cpp,
beside being type safe.
printf , on the other hand is more of a functional approach.
only reason for not using printf in cpp code that i can think of is not being object oriented.
its more of a personal choice.

C++: what is the optimal way to convert a double to a string?

What is the most optimal way to achieve the same as this?
void foo(double floatValue, char* stringResult)
{
sprintf(stringResult, "%f", floatValue);
}
I'm sure someone will say boost::lexical_cast, so go for that if you're using boost, but it's basically the same as this anyway:
#include <sstream>
#include <string>
std::string doubleToString(double d)
{
std::ostringstream ss;
ss << d;
return ss.str();
}
Note that you could easily make this into a template that works on anything that can be stream-inserted (not just doubles).
http://www.cplusplus.com/reference/iostream/stringstream/
double d=123.456;
stringstream s;
s << d; // insert d into s
Boost::lexical_cast<>
On dinkumware STL, the stringstream is filled out by the C library snprintf.
Thus using snprintf formatting directly will be comparable with the STL formatting part.
But someone once told me that the whole is greater than or equal to the sum of its known parts.
As it will be platform dependent as to whether stringstream will do an allocation (and I am quite sure that DINKUMWARE DOES NOT YET include a small buffer in stringstream for conversions of single items like yours) it is truely doubtful that ANYTHING that requires an allocation (ESPECIALLY if MULTITHREADED) can compete with snprintf.
In fact (formatting+allocation) has a chance of being really terrible as an allocation and a release might well require 2 full read-modify-write cycles in a multithreaded environment unless the allocation implementation has a thread local small heap.
That being said, if I was truely concerned about performance, I would take the advice from some of the other comments above, change the interface to include a size and use snprintf - i.e.
bool
foo(const double d, char* const p, const size_t n){
use snprintf......
determine if it fit, etc etc etc.
}
If you want a std::string you are still better off using the above and instantiating the string from the resultant char* as there will be 2 allocations + 2 releases involved with the std::stringstream, std::string solution.
BTW I cannot tell if the "string" in the question is std::string or just generic ascii chars usage of "string"
The best thing to do would be to build a simple templatized function to convert any streamable type into a string. Here's the way I do it:
#include <sstream>
#include <string>
template <typename T>
const std::string to_string(const T& data)
{
std::ostringstream conv;
conv << data;
return conv.str();
}
If you want a const char* representation, simply substitute conv.str().c_str() in the above.
I'd probably go with what you suggested in your question, since there's no built-in ftoa() function and sprintf gives you control over the format. A google search for "ftoa asm" yields some possibly useful results, but I'm not sure you want to go that far.
I'd say sprintf is pretty much the optimal way. You may prefer snprintf over it, but it doesn't have much to do with performance.
Herb Sutter has done an extensive study on the alternatives for converting an int to a string, but I would think his arguments hold for a double as well.
He looks at the balances between safety, efficiency, code clarity and usability in templates.
Read it here: http://www.gotw.ca/publications/mill19.htm
_gcvt or _gcvt_s.
If you use the Qt4 frame work you could go :
double d = 5.5;
QString num = QString::number(d);
This is very useful thread. I use sprintf_s for it but I started to doubt if it is really faster than other ways. I came across following document on Boost website which shows performance comparison between Printf/scanf, StringStream and Boost.
Double to String is most common conversion we do in our code, so i'll stick with what i've been using. But, using Boost in other scenarios could be your deciding factor.
http://www.boost.org/doc/libs/1_58_0/doc/html/boost_lexical_cast/performance.html
In the future, you can use std::to_chars to write code like https://godbolt.org/z/cEO4Sd . Unfortunately, only VS2017 and VS2019 support part of this functionality...
#include <iostream>
#include <charconv>
#include <system_error>
#include <string_view>
#include <array>
int main()
{
std::array<char, 10> chars;
auto [parsed, error] = std::to_chars(
chars.data(),
chars.data() + chars.size(),
static_cast<double>(12345.234)
);
std::cout << std::string_view(chars.data(), parsed - chars.data());
}
For a lengthy discussion on MSVC details, see
https://www.reddit.com/r/cpp/comments/a2mpaj/how_to_use_the_newest_c_string_conversion/eazo82q/