fmt 库用法简介
C++ 的 fmt
库是一个开源、轻量和高性能的格式化库,它实现了 C++20 的 std::format 标准,用来替代 C 中的 stdio
和 C++ 的 iostream
。
fmt 库 的性能相比于 printf
和 iostream
有显著的提升,经过官方文档测试,速度分别快 0.3
和 4
倍,且该库提供了类似 Python
的字符串格式化语法,使用起来非常容易上手,在具备高效率和易用性的同时,fmt 也是完全类型安全地,可以在编译时报告格式字符串中的错误,其自动内存管理亦可防止缓冲区溢出错误。
fmt 库使用较为简单,常用的函数有两个: fmt::print
和 fmt::format
。该库可以直接在 PowerShell
中通过 vcpkg
用下面命令进行安装:
.\vcpkg install fmt:x64-windows
一、fmt::print 函数
该函数用于直接将数据进行格式化并输出到控制台。
1 打印整型数据
需要 #include <fmt/core.h>
:
// 基本上同 printf 中的类型,d 表示整数、f/F/g/G/e/E 表示浮点数,
// s 表示字符串,p 表示指针,b/B/o/x/X 用二/八/十六进制表示整数
fmt::print("整型数据:{0:d} {1:d}\r\n\n", 100, 101); // 0 指第一个参数,1 指第二个参数,可省略
结果如下:
2 打印浮点型数据
fmt::print("PI is {:.2f}\r\n", 3.1415926); // 保留小数点后两位,".2f" 前面 的 ':' 是一个特殊的标记,用来引入格式化说明符
fmt::print("PI is {:>10.2f}\r\n", 3.1415926); // 10 个字符宽度,右对齐(不足的用空格填充在左侧)
fmt::print("PI is {:<10.2f}\r\n", 3.1415926); // 10 个字符宽度,左对齐(不足的用空格填充在右侧)
fmt::print("PI is {:^10.2f}\r\n", 3.1415926); // 10 个字符宽度,居中对齐(不足的用空格填充在两侧)
fmt::print("PI is {:*^10.2f}\r\n\n", 3.1415926); // 10 个字符宽度,居中对齐(不足的用 `*` 字符填充在两侧)
结果如下:
3 打印布尔型数据
fmt::print("{}\r\n\n", true);
结果如下:
4 打印 vector
需要 #include <vector>、<fmt/core.h>、<fmt/ranges.h>
:
fmt::print("vec: {}\r\n\n", std::vector<int>{1, 4, 7});
结果如下:
5 设置控制台输出的文本样式
需要 #include <fmt/core.h>、<fmt/color.h>
:
fmt::print(fg(fmt::color::red) | fmt::emphasis::bold,
"Hello, World!\r\n"); // 设置前景色(文字颜色)为红色,且文本样式为加粗
fmt::print(fg(fmt::color::white) | bg(fmt::color::gray) | fmt::emphasis::underline,
"Hello, World!\r\n"); // 设置前景色为白色、背景色为灰色,且文本样式为下划线
fmt::print(fg(fmt::color::blue) | fmt::emphasis::italic,
"Hello, World!\r\n\n"); // 设置前景色为蓝色,且文本样式为斜体
结果如下:
6 打印格式化时间
需要 #include <fmt/core.h>、<fmt/chrono.h>、<chrono>、<ctime>
:
auto now = std::chrono::system_clock::now(); // 获取 Unix 纳秒时间(1970 年 1月 1 日 00::00::00 UTC)
std::time_t now_c = std::chrono::system_clock::to_time_t(now); // 将纳秒时间转为秒(UTC)
fmt::print("Current time(UTC: s): {}\r\n", now_c);
fmt::print("Current time(Local: formatted): {:%Y-%m-%d %H:%M:%S}\r\n\n", fmt::localtime(now_c));
结果如下:
7 格式化输出到文件
fmt::print 主要关注格式化输出到控制台,其他更多的文件输入与输出操作可以使用 C++ 标准库中的文件流结合 fmt::format 来实现:
auto fout = fmt::output_file("output.txt"); // 默认以写入模式打开文件
fout.print("The value of pi is approximately {:.2f}.\r\n", 3.14159);
fout.close();
结果如下:
二、fmt::format 函数
该函数通过格式化数据,返回 std::string
类型方便处理。
1 格式化打印 vector 中结构体数据
需要 #include <fmt/format.h>
:
struct Person
{
std::string name;
int age;
};
std::vector<Person> people =
{
{"Alice", 18},
{"Bob", 19},
{"Tom", 20}
};
std::string output;
for (const auto& person : people)
{
output += fmt::format("Name: {0:<10} | Age: {1}\r\n", person.name, person.age);
}
fmt::print("List of people:\n{}\n", output);
结果如下:
2 结合输入输出流操作读写文件
需要 #include <fstream>、<fmt/format.h>
:
std::ofstream ofs("output.txt", std::ios::out | std::ios::app);
if (ofs.is_open())
{
for (int i = 0; i < 2; ++i)
{
ofs << fmt::format("The value is {:d}.\r\n", i);
}
ofs.close();
}
std::ifstream ifs("output.txt");
if (ifs.is_open())
{
std::string line;
while (std::getline(ifs, line))
{
fmt::print("{}\r\n", line);
}
ifs.close();
}
结果如下: