C++20引入了std::format
。与printf
或std::cout
相比,它有什么优势?
我该如何使用它?能否举个例子?
C++20引入了std::format
。与printf
或std::cout
相比,它有什么优势?
我该如何使用它?能否举个例子?
与printf相比,有哪些优势
类型安全。对于printf,程序员必须仔细匹配格式说明符和参数的类型。如果他们犯了一个错误,程序的行为是未定义的。这是一个非常常见的错误源,尤其是对于初学者。
公平地说,只要使用常量格式字符串,只要程序员记得/知道如何启用警告,像样的编译器会诊断这些错误。但无论如何,使用模板参数推导自动选择格式化类型更加方便、安全。
此外,没有一种方法可以扩展printf以支持打印类类型。
还是std::cout呢
流操作符修改器相当麻烦且冗长,并且具有不一致的行为。某些修改器是“粘性的”,影响所有后续插入,而其他的则只影响单个插入。
在iostream API中,格式和参数之间缺乏分离,这可能使(预期的)结果更难理解。
我该如何使用它
要么等待您的编译器/标准库实现支持它。或者,如果不想等待,请使用原始的非标准版本。然后按照文档操作。
规范规格是C++标准。还有一些网站以更方便的格式呈现标准,包括此库。另一个很好的信息来源是标准提案。非标准版本的仓库(链接在上一个段落中)也有大量文档,尽管与标准不同。
有人能给出一个例子吗?
这里您可以看到一个例子(改编自libfmt文档):
std::string s = std::format("I'd rather be {1} than {0}.", "right", "happy");
format("The {} {} is broken", color, furniture)
,因为在英语中是 "red table",但在法语中则是不同顺序的 table rouge
。相反,应选择类似于 format("由P1指定的对象,颜色为P2,已经损坏(P1={}, P2={})", furniture, color)
这样的表达方式。唯一需要更改的是完全自包含的格式字符串的语言特定部分,可以根据每种语言进行调整。变量部分的顺序是无关紧要的。 - paxdiabloC++20的std::format
主要是包含许多人已经在使用的fmt
库(我们将其作为spdlog
日志框架的一部分使用)。
因此,如果您想使用它,只需下载fmt
即可。
至于优点,它具有流的类型安全性,但不含冗长(传统的C语言printf
虽然简洁,但既不具备类型安全性也不具备可扩展性)。以下是一个稍作修改的示例,来自我们自己的代码库:
std::string idStr = fmt::format("prefix.{:05d}.suffix", id);
否则需要使用不太简洁的标准C ++:
std::string idStr;
{
std::stringstream ss;
ss << "prefix." << std::setfill('0') << std::setw(5) << id << ".suffix";
idStr = ss.str();
}
ss << "prefix." << std::format(":05d") << id << ".suffix";
,有效地将下一个输出项的完整格式捆绑在一个操作器中。(不确定这是否可以在静态类型安全性方面完成得比 printf 更加类型安全)。 - Peter - Reinstate Monicaf'prefix.{id:05d}.suffix'
。 - paxdiablostrstream
并自动将std::sstream
和std::strstream
视为std::stringstream
,我会非常高兴。这将使我不必每次在需要使用它时(当然,在没有fmt
的情况下)都要查找它。即使是现在,我也不确定我是否已经在这个评论中放置了正确的内容 :-) - paxdiablostd::strstream
。我从未见过它被使用,但显然它在我开始编程之前就已经被弃用了。我甚至不知道你可以在第一个标准迭代中废弃某些东西。看着这个接口,我觉得自己很幸运没有不得不使用它。 - walnutchar*
。该转换在C++11中已被移除。 - eerorika
std::format
的作用更接近于std::ostringstream
和std::sprintf
,而不是std::cout
和printf
。 - walnut