3

我想将一些printf//语句重构为sprintf//语句。有问题的代码使用空白填充和固定的小数点数漂亮地打印了一系列整数和浮点数。fprintfostreamsstreamfstream

在我看来,这将是 Martin Fowler 风格的安全、逐步重构的写作的一个很好的候选者,并指出了重要的陷阱。当然,第一步是将遗留代码放入测试工具中,我已经这样做了。

我可以采取哪些缓慢而谨慎的步骤来执行此重构?

4

2 回答 2

2

如果重构本身不是目标,您可以通过使用诸如tinyformat 之类的格式化库来完全避免它(嗯,几乎),它提供了一个类似于printf但类型安全的接口并在内部使用 IOStreams。

于 2013-02-05T21:01:35.903 回答
2

转换的基本机制:

  • 将每个printf-style 子句%w.pf%w.pe,其中w是字段宽度和p精度位数,转换为<< setw(w) << setprecision(p) << fixed
  • 将每个printf-style 子句%wd%wi(其中w是字段宽度)转换为<< setw(w).
  • 转换"\n"endl适当的地方。

处理printf

  • 创建一个具有足够总宽度的char[](我们称之为)。text
  • 将 转换printf(...)sprintf(text, ...),并用于cout << text实际打印文本。
  • 使用通用指令完成。

处理fprintf

  • 与 相同printf,但使用适当的fstream而不是cout
    • 如果您已经有一个打开的 C 样式FILE对象,此时您不想重构,它会变得有点棘手(但可以完成)。
  • 使用通用指令完成。

处理sprintf

  • 如果要写入的字符串仅用于在当前上下文中输出到流,请参阅上面的两个重构之一。
    • 否则,首先创建一个stringstream并将char[]您正在写入的内容流式传输到其中。如果您仍打算从中提取 a char*,则可以执行std::stringstream::str().c_str().
  • 使用通用指令完成。

常用指令:

  • 将每个子句一一转换为 C++ 风格。
  • 完成后根据需要删除*printf和声明。char[]
  • 必要时应用其他重构,特别是“提取方法”(Fowler,重构)。
于 2013-02-05T21:01:51.757 回答