我必须用sprintf格式化std::string,并将其发送到文件流。我该怎么做呢?


当前回答

String没有你需要的东西,但是std::stringstream有。使用stringstream创建字符串,然后提取字符串。这里有一个关于你可以做的事情的全面列表。例如:

cout.setprecision(10); //stringstream is a stream like cout

将在打印双精度或浮点数时提供10位小数点后的精度。

其他回答

这个问题已经解决了。但是,我认为这是c++中格式化字符串的另一种方式

class string_format {
private:
    std::string _result;
public:
    string_format( ) { }
    ~string_format( ) { std::string( ).swap( _result ); }
    const std::string& get_data( ) const { return _result; }
    template<typename T, typename... Targs>
    void format( const char* fmt, T value, Targs... Fargs ) {
        for ( ; *fmt != '\0'; fmt++ ) {
            if ( *fmt == '%' ) {
                _result += value;
                this->format( fmt + 1, Fargs..., 0 ); // recursive call
                return;
            }
            _result += *fmt;
        }
    }
    friend std::ostream& operator<<( std::ostream& ostream, const string_format& inst );
};
inline std::string& operator+=( std::string& str, int val ) {
    str.append( std::to_string( val ) );
    return str;
}
inline std::string& operator+=( std::string& str, double val ) {
    str.append( std::to_string( val ) );
    return str;
}
inline std::string& operator+=( std::string& str, bool val ) {
    str.append( val ? "true" : "false" );
    return str;
}
inline std::ostream& operator<<( std::ostream& ostream, const string_format& inst ) {
    ostream << inst.get_data( );
    return ostream;
}

并测试这个类:

string_format fmt;
fmt.format( "Hello % and is working ? Ans: %", "world", true );
std::cout << fmt;

你可以在这里查一下

Poco Foundation库有一个非常方便的格式函数,它在格式字符串和值中都支持std::string:

道格:http://pocoproject.org/docs/Poco.html # 7308 来源:https://github.com/pocoproject/poco/blob/develop/Foundation/src/Format.cpp

更新了一些答案,不同的是-函数将正确接受std::string为%s

namespace format_helper
{

    template <class Src>
    inline Src cast(Src v)
    {
        return v;
    }

    inline const char *cast(const std::string& v)
    {
        return v.c_str();
    }
};

template <typename... Ts>
inline std::string stringfmt (const std::string &fmt, Ts&&... vs)
{
    using namespace format_helper;
    char b;
    size_t required = std::snprintf(&b, 0, fmt.c_str(), cast(std::forward<Ts>(vs))...);//not counting the terminating null character.
    std::string result;
    //because we use string as container, it adds extra 0 automatically
    result.resize(required , 0);
    //and snprintf will use n-1 bytes supplied
    std::snprintf(const_cast<char*>(result.data()), required + 1, fmt.c_str(), cast(std::forward<Ts>(vs))...);

    return result;
}

生活:http://cpp.sh/5ajsv

c++ 11内部使用vsnprintf()的解决方案:

#include <stdarg.h>  // 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;
}

一种更安全、更有效的方法(我测试过,它更快):

#include <stdarg.h>  // For va_start, etc.
#include <memory>    // 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<char[]> 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());
}

fmt_str是按值传递的,以符合va_start的要求。

注意:“更安全”和“更快”的版本在某些系统上不起作用。因此,两家公司仍在上市。此外,“更快”完全取决于预分配步骤是否正确,否则strcpy会使其变慢。

我通常用这个:

std::string myformat(const char *const fmt, ...)
{
        char *buffer = NULL;
        va_list ap;

        va_start(ap, fmt);
        (void)vasprintf(&buffer, fmt, ap);
        va_end(ap);

        std::string result = buffer;
        free(buffer);

        return result;
}

缺点:并非所有系统都支持vasprint