0

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.

2

5 Answers 5

8

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.

Sign up to request clarification or add additional context in comments.

1 Comment

While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes.
5

I would use a std::stringstream (in combination with setprecision) instead and use .str() afterwards to get the std::string.

Comments

5

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

Comments

2

New answer 10 years later: C++20 std::format

Finally, this will be the superior choice once you can use it:

#include <format> #include <string> int main() { std::cout << std::format("{:4.3}\n{:4.3}\n", 3.1, 3.1415); } 

Expected output:

 3.1 3.14 

This will therefore completely overcome the madness of modifying std::cout state.

The existing fmt library implements it for before it gets official support: https://github.com/fmtlib/fmt Install on Ubuntu 22.04:

sudo apt install libfmt-dev 

Modify source to replace:

  • <format> with <fmt/core.h>
  • std::format to fmt::format

main.cpp

#include <iostream> #include <fmt/core.h> int main() { std::cout << fmt::format("{:4.3}\n{:4.3}\n", 3.1, 3.1415); } 

and compile and run with:

g++ -std=c++11 -o main.out main.cpp -lfmt ./main.out 

Output:

 3.1 3.14 

Old answer

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

Comments

1

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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.