C++中的sprintf等价函数是什么?

103
我知道 std::cout 是 C++ 中的 printf 等价物。
那么,C++ 中的 sprintf 等价于什么?
7个回答

76

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

4
我认为sprintf不会写入stdout。我建议删除上文的插入语句。 - khatchad
106
这怎么和sprintf(...)有一点相似之处?你不能随意格式化数据,必须依靠在使用<<操作符把数据输入流时已知的数据类型。 - Andon M. Coleman
1
我必须同意@AndonM.Coleman的看法。这并不是sprintf的替代品。这个更像那样,但这是Qt。 - László Papp
1
正如 @vinkris 在他的回答中所说,iomanip 可以实现格式化。我会建议使用 "result = out.str()" 而不是打印到 stdoit。 - Dmitri
@AndonM.Coleman:你说得对,但考虑到问题提出者最初的句子,回答的上下文是有意义的。 - jxh
显示剩余2条评论

42

2019年8月更新:

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

原始内容:

使用Boost.Format。它具有类似于printf的语法,类型安全性,std::string结果和许多其他巧妙的功能。您将不会后悔选用。


20
除非您关心可执行文件的大小,否则不需要担心。 :P - pradyunsg
这会产生多大的影响?Boost 依赖将仅为头文件,不需要链接,对吗? - Ken Williams
1
@KenWilliams 是的,Boost.Format是仅有头文件的。在我的Mac上进行一个简单的“hello, world”测试,大小从10kB增加到78kB。在实际项目中,额外的大小将通过编译单元分摊(给出正确的链接器选项),并且类型安全性带来其他好处。 - janm
当可执行文件大小膨胀时,总是尝试使用共享库! - Hunter Kohler

21

7
我认为OP的意思是STL而不是C++。 - Jean-Michaël Celerier
5
sprintf需要您分配字符缓冲区。我希望有像“std :: string”的“附加”方法那样的东西,它允许我添加格式化数据,并在幕后负责分配内存。 - Victor Eijkhout

12

这是一个不错的 C++ sprintf 函数。如果过度使用流,它们可能会变得难看。

std::string string_format(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'结尾的连续存储空间,因此可以使用&str[0]将其转换为char *

非常好的解决方案!我已经在这里进行了调整:https://dev59.com/PHE95IYBdhLWcg3wXcvd#3742999,以更贴近`sprintf`的使用方式。 - slashmais
12
非法的操作:(char*) str.c_str()强制转换去掉了const - MSalters
还有一个缓冲区溢出问题潜伏着。 - Barney Szabolcs
@MSalters 正确。在C++11中有一种合法的方法来实现这个功能。 - whitequark
@whitequark:随意添加到答案中。在 Stack Overflow 上,好问题保持开放,以允许新的回答。 - MSalters
显示剩余5条评论

7
你可以使用头文件来格式化输出流。 查看这里

为什么有人踩了这个?难道不是使用iomanip在流中实现格式化的纯C++方式吗?我认为这里的目标是避免使用C风格字符串存储数据,而这可以通过使用iomanip来实现。 - Dmitri

2

根据你计划使用sprintf()的具体内容,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");
}
< p > 我认为 < code > std::to_string() 的主要优点是它可以轻松扩展以支持其他类型,而 < code > sprintf() 甚至无法将其转换为字符串 - 类似于 Java 的 < code > Object.toString() 方法。 < / p >

-1

使用stringstream可以实现相同的效果。此外,您还可以包含<cstdio>并仍然使用snprintf。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接