std::string formatting like sprintf

前端 未结 30 2598
野趣味
野趣味 2020-11-22 04:42

I have to format std::string with sprintf and send it into file stream. How can I do this?

30条回答
  •  忘了有多久
    2020-11-22 05:14

    My two cents on this very popular question.

    To quote the manpage of printf-like functions:

    Upon successful return, these functions return the number of characters printed (excluding the null byte used to end output to strings).

    The functions snprintf() and vsnprintf() do not write more than size bytes (including the terminating null byte ('\0')). If the output was truncated due to this limit then the return value is the number of characters (excluding the terminating null byte) which would have been written to the final string if enough space had been available. Thus, a return value of size or more means that the output was truncated.

    In other words, a sane C++11 implementation should be the following:

    #include 
    #include 
    
    template 
    std::string fmt (const std::string &fmt, Ts... vs)
    {
        char b;
        size_t required = std::snprintf(&b, 0, fmt.c_str(), vs...) + 1;
            // See comments: the +1 is necessary, while the first parameter
            //               can also be set to nullptr
    
        char bytes[required];
        std::snprintf(bytes, required, fmt.c_str(), vs...);
    
        return std::string(bytes);
    }
    

    It works quite well :)

    Variadic templates are supported only in C++11. The answer from pixelpoint show a similar technique using older programming styles.

    It's weird that C++ does not have such a thing out of the box. They recently added to_string(), which in my opinion is a great step forward. I'm wondering if they will add a .format operator to the std::string eventually...

    Edit

    As alexk7 pointed out, A +1 is needed on the return value of std::snprintf, since we need to have space for the \0 byte. Intuitively, on most architectures missing the +1 will cause the required integer to be partially overwritten with a 0. This will happen after the evaluation of required as actual parameter for std::snprintf, so the effect should not be visible.

    This problem could however change, for instance with compiler optimization: what if the compiler decides to use a register for the required variable? This is the kind of errors which sometimes result in security issues.

提交回复
热议问题