std::string formatting like sprintf

前端 未结 30 2923
野趣味
野趣味 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:09

    C++11 solution that uses vsnprintf() internally:

    #include   // For va_start, etc.
    
    std::string string_format(const std::string fmt, ...) {
        int size = ((int)fmt.size()) * 2 + 50;   // Use a rubric appropriate for your code
        std::string str;
        va_list ap;
        while (1) {     // Maximum two passes on a POSIX system...
            str.resize(size);
            va_start(ap, fmt);
            int n = vsnprintf((char *)str.data(), size, fmt.c_str(), ap);
            va_end(ap);
            if (n > -1 && n < size) {  // Everything worked
                str.resize(n);
                return str;
            }
            if (n > -1)  // Needed size returned
                size = n + 1;   // For null char
            else
                size *= 2;      // Guess at a larger size (OS specific)
        }
        return str;
    }
    

    A safer and more efficient (I tested it, and it is faster) approach:

    #include   // For va_start, etc.
    #include     // For std::unique_ptr
    
    std::string string_format(const std::string fmt_str, ...) {
        int final_n, n = ((int)fmt_str.size()) * 2; /* Reserve two times as much as the length of the fmt_str */
        std::unique_ptr formatted;
        va_list ap;
        while(1) {
            formatted.reset(new char[n]); /* Wrap the plain char array into the unique_ptr */
            strcpy(&formatted[0], fmt_str.c_str());
            va_start(ap, fmt_str);
            final_n = vsnprintf(&formatted[0], n, fmt_str.c_str(), ap);
            va_end(ap);
            if (final_n < 0 || final_n >= n)
                n += abs(final_n - n + 1);
            else
                break;
        }
        return std::string(formatted.get());
    }
    

    The fmt_str is passed by value to conform with the requirements of va_start.

    NOTE: The "safer" and "faster" version doesn't work on some systems. Hence both are still listed. Also, "faster" depends entirely on the preallocation step being correct, otherwise the strcpy renders it slower.

提交回复
热议问题