C++ 相当于 sprintf?

Posted

技术标签:

【中文标题】C++ 相当于 sprintf?【英文标题】:C++ equivalent of sprintf? 【发布时间】:2011-02-13 07:50:54 【问题描述】:

我知道std::coutprintf 的 C++ 等价物。

sprintf 的 C++ 等价物是什么?

【问题讨论】:

【参考方案1】:

std::ostringstream

例子:

#include <iostream>
#include <sstream> // for ostringstream
#include <string>

int main()

  std::string name = "nemo";
  int age = 1000;
  std::ostringstream out;  
  out << "name: " << name << ", age: " << age;
  std::cout << out.str() << '\n';
  return 0;

输出:

name: nemo, age: 1000

【讨论】:

我认为 sprintf 不会写入标准输出。我会删除上面的插入语句。 这与sprintf (...) 有何相似之处?您不能任意格式化数据,当您使用 &lt;&lt; 运算符将数据输入流时,您必须依赖已知的类型。 我需要同意@AndonM.Coleman 关于这一点。这并不是真正的 sprintf 替代品。 This 会更像这样,但这是 Qt。 正如@vinkris 在他的回答中所说,iomanip 实现了格式化。我会说“result = out.str()”,而不是打印到 stdoit。 sprintf / snprintf 允许格式化和打印到用户分配的字符数组,可能在堆栈上。在 snprintf() 的情况下,它确保没有溢出。这里我们多次分配内存,调用者无法直接访问它。必须转换为字符串才能获得输出。带有自定义 std::streambuf 的 std::ostream 会更好地匹配用户缓冲区 - 当然,ostream/streambuf 的构造/销毁会增加效率。【参考方案2】:

2019 年 8 月更新:

看起来 C++20 会有std::format。参考实现是fmt。如果您现在正在寻找printf() 替代方案,这将成为新的“标准”方法,值得考虑。

原文:

使用Boost.Format。它具有类似printf 的语法、类型安全、std::string 结果以及许多其他漂亮的东西。你不会回去的。

【讨论】:

...除非您担心可执行文件的大小.. :P 这会产生多大的影响? Boost 依赖项仅是标头,没有链接,对吗? @KenWilliams 是的,Boost.Format 只是标题。我的 Mac 上的一个简单的“hello, world”测试从 10kB 增加到 78kB。在实际项目中,额外的大小将在编译单元之间分摊(提供正确的链接器选项),并且类型安全带来其他好处。 当可执行文件大小膨胀时,总是尝试使用共享库!【参考方案3】:

sprintf 在 C++ 中工作得很好。

【讨论】:

我认为 OP 的意思是 STL 而不是 C++。 sprintf 要求您分配字符缓冲区。我想要类似“std::string”的“append”方法,它允许我添加格式化数据,并在幕后处理分配。【参考方案4】:

这是一个很好的 c++ sprintf 函数。如果过度使用 Streams,它们会变得很丑。

std::string string_format(const std::string &fmt, ...) 
    int size=100;
    std::string str;
    va_list ap;

    while (1) 
        str.resize(size);
        va_start(ap, fmt);
        int n = vsnprintf(&str[0], size, fmt.c_str(), ap);
        va_end(ap);
   
        if (n > -1 && n < size) 
            str.resize(n); // Make sure there are no trailing zero char
            return str;
        
        if (n > -1)
            size = n + 1;
        else
            size *= 2;
    

在 C++11 及更高版本中,std::string 保证使用以'\0' 结尾的连续存储,因此使用&amp;str[0] 将其转换为char * 是合法的。

已经指出,可变参数不应该遵循传递引用,并且 c++ 最好不要复制字符串,如果它不需要的话。在这种情况下,这可以解决它。

std::string string_format(std::string fmt, ...) 

【讨论】:

非常好的解决方案!我在这里对其进行了调整:***.com/a/3742999/15161 以更贴合sprintf-usage。 非法,但:(char*) str.c_str() 抛弃了const 还有潜伏的缓冲区溢出问题 @MSalters 正确。在 C++11 中有一种合法的方式来做到这一点。 @whitequark:随意添加它作为答案。在 Stack Overflow 上,好的问题仍然存在,以允许新的答案。【参考方案5】:

您可以使用iomanip 头文件来格式化输出流。 检查this!

【讨论】:

为什么有人反对这个? iomanip 不是在流中实现格式化的纯 C++ 方式吗?我认为这里的目标是避免将数据存储在 C 风格的字符串中,这是通过 iomanip 实现的。【参考方案6】:

根据您对sprintf()ing 的具体计划,std::to_string() 可能比其他选项更有用且更惯用:

void say(const std::string& message) 
 // ...


int main() 
  say(std::to_string(5));
  say("Which is to say " + std::to_string(5) + " words");

std::to_string()(恕我直言)的主要优点是它可以轻松扩展以支持 sprintf() 甚至无法实现字符串化的其他类型 - 有点像 Java 的 Object.toString() 方法。

【讨论】:

【参考方案7】:

使用字符串流来达到同样的效果。此外,您可以包含 &lt;cstdio&gt; 并仍然使用 snprintf。

【讨论】:

以上是关于C++ 相当于 sprintf?的主要内容,如果未能解决你的问题,请参考以下文章

带有 unsigned long long 和 sprintf 的 Visual C++ 6.0

转载C++中替代sprintf的std::ostringstream输出流详解

关于sprintf()

c++流中有类似 C语言的sprintf函数的函数吗?

sprintf()函数 和 printf()函数

C++:Visual Studio 2015 中未解析的外部符号 _sprintf 和 _sscanf