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


当前回答

Boost::format()提供了你想要的功能:

Boost格式库简介如下:

format对象由format-string构造,然后通过反复调用运算符%来给出参数。 然后,每个参数都被转换为字符串,这些字符串又根据format-string组合成一个字符串。

#include <boost/format.hpp>

cout << boost::format("writing %1%,  x=%2% : %3%-th try") % "toto" % 40.23 % 50; 
// prints "writing toto,  x=40.230 : 50-th try"

其他回答

Boost::format()提供了你想要的功能:

Boost格式库简介如下:

format对象由format-string构造,然后通过反复调用运算符%来给出参数。 然后,每个参数都被转换为字符串,这些字符串又根据format-string组合成一个字符串。

#include <boost/format.hpp>

cout << boost::format("writing %1%,  x=%2% : %3%-th try") % "toto" % 40.23 % 50; 
// prints "writing toto,  x=40.230 : 50-th try"

非常简单的解决方案。

std::string strBuf;
strBuf.resize(256);
int iCharsPrinted = sprintf_s((char *)strPath.c_str(), strPath.size(), ...);
strBuf.resize(iCharsPrinted);
inline void format(string& a_string, const char* fmt, ...)
{
    va_list vl;
    va_start(vl, fmt);
    int size = _vscprintf( fmt, vl );
    a_string.resize( ++size );
    vsnprintf_s((char*)a_string.data(), size, _TRUNCATE, fmt, vl);
    va_end(vl);
}

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

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

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

从Dacav和pixelpoint的答案中获得灵感。我玩了一下,得到了这个:

#include <cstdarg>
#include <cstdio>
#include <string>

std::string format(const char* fmt, ...)
{
    va_list vl;

    va_start(vl, fmt);
    int size = vsnprintf(0, 0, fmt, vl) + sizeof('\0');
    va_end(vl);

    char buffer[size];

    va_start(vl, fmt);
    size = vsnprintf(buffer, size, fmt, vl);
    va_end(vl);

    return std::string(buffer, size);
}

通过合理的编程实践,我相信代码应该足够了,但是我仍然对更安全的替代方案持开放态度,这些替代方案仍然足够简单,不需要c++ 11。


下面是另一个版本,它使用初始缓冲区来防止在初始缓冲区已经足够多时再次调用vsnprintf()。

std::string format(const char* fmt, ...)
{

    va_list vl;
    int size;

    enum { INITIAL_BUFFER_SIZE = 512 };

    {
        char buffer[INITIAL_BUFFER_SIZE];

        va_start(vl, fmt);
        size = vsnprintf(buffer, INITIAL_BUFFER_SIZE, fmt, vl);
        va_end(vl);

        if (size < INITIAL_BUFFER_SIZE)
            return std::string(buffer, size);
    }

    size += sizeof('\0');

    char buffer[size];

    va_start(vl, fmt);
    size = vsnprintf(buffer, size, fmt, vl);
    va_end(vl);

    return std::string(buffer, size);
}

(事实证明,这个版本与Piti Ongmongkolkul的答案相似,只是它没有使用new和delete[],并且在创建std::string时指定了大小。

The idea here of not using new and delete[] is to imply usage of the stack over the heap since it doesn't need to call allocation and deallocation functions, however if not properly used, it could be dangerous to buffer overflows in some (perhaps old, or perhaps just vulnerable) systems. If this is a concern, I highly suggest using new and delete[] instead. Note that the only concern here is about the allocations as vsnprintf() is already called with limits, so specifying a limit based on the size allocated on the second buffer would also prevent those.)