C:如何将 fprintf 结果作为 std::string w/o sprintf

新手上路,请多包涵

我正在使用一个用 C++ 实现的开源 UNIX 工具,我需要更改一些代码来让它做我想做的事情。我想做最小的改变,希望我的补丁在上游被接受。首选可在标准 C++ 中实现且不会创建更多外部依赖项的解决方案。

这是我的问题。我有一个 C++ 类——我们称之为“A”——它目前使用 fprintf() 将其高度格式化的数据结构打印到文件指针。在它的打印函数中,它还递归地调用了几个成员类的相同定义的打印函数(“B”就是一个例子)。还有另一个类 C 有一个成员 std::string “foo”,需要将其设置为 A 实例的 print() 结果。将其视为 A 的 to_str() 成员函数。

在伪代码中:

 class A {
public:
  ...

  void print(FILE* f);
  B b;

  ...
};

...

void A::print(FILE *f)
{
  std::string s = "stuff";
  fprintf(f, "some %s", s);
  b.print(f);
}

class C {
  ...
  std::string foo;
  bool set_foo(std::str);
  ...
}

...

A a = new A();
C c = new C();

...

// wish i knew how to write A's to_str()
c.set_foo(a.to_str());

我应该提到 C 相当稳定,但 A 和 B(以及 A 的其他依赖项)处于不断变化的状态,因此所需的代码更改越少越好。当前的 print(FILE* F) 接口也需要保留。我考虑了几种实现 A::to_str() 的方法,每种方法都有优点和缺点:

  1. 将对 fprintf() 的调用更改为 sprintf()

    • 我不必重写任何格式字符串
    • print() 可以重新实现为: fprint(f, this.to_str());
    • 但我需要手动分配 char[]s,合并很多 c 字符串,最后将字符数组转换为 std::string
  2. 尝试在字符串流中捕获 a.print() 的结果

    • 我必须将所有格式字符串转换为 << 输出格式。有数百个 fprintf() 可以转换:-{
    • print() 必须重写,因为我知道没有标准方法可以从 UNIX 文件句柄创建输出流(尽管 这个人说这可能是可能的)。
  3. 使用 Boost 的字符串 格式库

    • 更多的外部依赖。呸。
    • Format 的语法与 printf() 的不同之处足以令人讨厌:

printf(format_str, args) -> cout << boost::format(format_str) % arg1 % arg2 % etc

  1. 使用 Qt 的 QString::asprintf()

    • 不同的外部依赖。

那么,我是否已经用尽了所有可能的选择?如果是这样,你认为哪个是我最好的选择?如果没有,我忽略了什么?

谢谢。

原文由 underspecified 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 828
2 个回答

我正在使用#3:boost 字符串格式库——但我不得不承认我从来没有对格式规范的差异有任何问题。

对我来说就像一个魅力 - 外部依赖可能更糟(一个非常稳定的库)

编辑:添加一个示例如何使用 boost::format 而不是 printf:

 sprintf(buffer, "This is a string with some %s and %d numbers", "strings", 42);

boost::format 库会是这样的:

 string = boost::str(boost::format("This is a string with some %s and %d numbers") %"strings" %42);

希望这有助于澄清 boost::format 的用法

我在 4 或 5 个应用程序中使用 boost::format 作为 sprintf / printf 替换(将格式化字符串写入文件,或自定义输出到日志文件),并且从未遇到格式差异问题。可能有一些(或多或少晦涩难懂的)格式说明符是不同的——但我从来没有遇到过问题。

相比之下,我有一些格式规范,我真的不能用流做(据我记得)

原文由 bernhardrusch 发布,翻译遵循 CC BY-SA 2.5 许可协议

{fmt} 库 提供 fmt::sprintf 执行 printf 兼容格式(包括根据 POSIX 规范 的位置参数)的函数,并将结果返回为 std::string

 std::string s = fmt::sprintf("The answer is %d.", 42);

免责声明:我是这个库的作者。

原文由 vitaut 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题