首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >std::字符串格式,如sprintf

std::字符串格式,如sprintf
EN

Stack Overflow用户
提问于 2010-02-26 22:15:54
回答 29查看 1M关注 0票数 534

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

EN

回答 29

Stack Overflow用户

回答已采纳

发布于 2010-02-26 22:17:59

您不能直接这样做,因为您没有对底层缓冲区的写访问权限(直到C++11为止;请参阅Dietrich Epp的comment)。您必须首先在c-string中执行此操作,然后将其复制到std::string中:

代码语言:javascript
复制
  char buff[100];
  snprintf(buff, sizeof(buff), "%s", "Hello");
  std::string buffAsStdStr = buff;

但我不确定你为什么不直接使用字符串流?我假设你有特定的理由不这么做:

代码语言:javascript
复制
  std::ostringstream stringStream;
  stringStream << "Hello";
  std::string copyOfStr = stringStream.str();
票数 394
EN

Stack Overflow用户

发布于 2011-11-12 02:04:02

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

代码语言:javascript
复制
#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;
}

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

代码语言:javascript
复制
#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());
}

为了符合va_start的要求,通过值传递fmt_str

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

票数 247
EN

Stack Overflow用户

发布于 2012-04-14 10:04:27

我使用vsnprintf编写了自己的代码,这样它就可以返回字符串,而不必创建自己的缓冲区。

代码语言:javascript
复制
#include <string>
#include <cstdarg>

//missing string printf
//this is safe and convenient but not exactly efficient
inline std::string format(const char* fmt, ...){
    int size = 512;
    char* buffer = 0;
    buffer = new char[size];
    va_list vl;
    va_start(vl, fmt);
    int nsize = vsnprintf(buffer, size, fmt, vl);
    if(size<=nsize){ //fail delete buffer and try again
        delete[] buffer;
        buffer = 0;
        buffer = new char[nsize+1]; //+1 for /0
        nsize = vsnprintf(buffer, size, fmt, vl);
    }
    std::string ret(buffer);
    va_end(vl);
    delete[] buffer;
    return ret;
}

所以你可以像这样使用它

代码语言:javascript
复制
std::string mystr = format("%s %d %10.5f", "omg", 1, 10.5);
票数 20
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2342162

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档