问题
What is the best way (short, using standard libraries and easy to understand) to do this in c++:
std::string s = magic_command("%4.2f", 123.456f)
- without length limitations (char s[1000] = ...)
- where "%4.2f" is any c format string (which would be given to printf for example)
I am aware of the snprintf malloc combo suggested for pure c in
writing formatted data of unknown length to a string (C programming)
but is there a better, less verbose, way to do this with c++?
I am also aware of the std::ostringstream method suggested in
Convert float to std::string in C++
but I want to pass a c format string such as "%4.2f", and I could not find a way to do this with ostringstream.
回答1:
You can try Boost.Format:
std::string s = boost::str(boost::format("%4.2f") % 123.456f);
It's not included in the standard, but Boost is about as standard as a non-standard library can get.
回答2:
I would use a std::stringstream
(in combination with setprecision
) instead and use .str()
afterwards to get the std::string
.
回答3:
C++ completely abandons the concept of format string, so there will be no standard way to do it. You could implement magic_command
yourself using asprintf
(its vasprintf
variant actually), though.
Note that *asprintf
are GNU/BSD extensions. As such, they don't exist on Windows. Also, this solution is not type-safe, and will only accept POD types (so no classes, structs or unions).
std::string magic_command(const std::string& format, ...)
{
char* ptr;
va_list args;
va_start(args, format);
vasprintf(&ptr, format.c_str(), args);
va_end(args);
std::unique_ptr<char, decltype(free)&> free_chars(ptr, free);
return std::string(ptr);
}
回答4:
If you literally want to use your syntax and forgo type safety, I'd write a little wrapper class that wraps snprintf
. I'd make it start out with a local, automatic buffer of some small size (say 2048?) and call snprintf
once. If it succeeds, return a std::string
created from that buffer. If you overran, allocate a std::string
of the correct size and repeat the snprintf
.
回答5:
All answers given are good since there seems to be no really standard way of doing what I want, I'll vote you all up, and accept my own sum up course of action:
- if the string is short enough to estimate its size by hand, do it, multiply your estimative by 4, and allocate it statically.
- if you can get away with stringstream + setprecision, do it since it is standard
- if not, and you are willing to write and include a short helper function based on snprintf/check overflow/dynamic allocation, do it and put it into your project "utils" file
- finnally consider which dependency is less restrictive for your project (maybe you are already using one of them):
- if boost is less restrictive, use Boost.Format
- if GNU/BSD extensions are less restrictive, use asprintf
来源:https://stackoverflow.com/questions/12039647/how-to-get-a-formatted-stdstring-in-c-without-length-liminations