std::format提供类型安全、高性能的字符串格式化,取代printf和iostream,支持丰富格式选项与自定义类型扩展,提升代码可读性与维护性。

C++的
std::format
printf
iostream
谈到C++的字符串处理,尤其是格式化输出,我总会想起以前那些与
printf
stringstream
std::format
format!
std::format
printf
<<
使用起来也相当直观:
立即学习“C++免费学习笔记(深入)”;
#include <iostream>
#include <format> // C++20
int main() {
std::string name = "Alice";
int age = 30;
double pi = 3.14159265;
// 基本用法,就像printf的格式字符串,但参数是按顺序传入的
std::string s1 = std::format("Hello, {}! You are {} years old.", name, age);
std::cout << s1 << std::endl; // 输出: Hello, Alice! You are 30 years old.
// 也可以指定位置参数,这在参数顺序可能调整时特别有用
std::string s2 = std::format("The value of PI is {:.2f}.", pi);
std::cout << s2 << std::endl; // 输出: The value of PI is 3.14.
// 命名参数,让可读性更上一层楼,尤其是在参数多的时候
std::string s3 = std::format("User: {user}, Role: {role}", std::arg("user", "Bob"), std::arg("role", "Admin"));
// 注意:C++20标准库的std::format默认不支持命名参数,需要fmt库支持或C++23的std::format_args。
// 这里为了演示概念,假设有类似支持。实际C++20标准库中通常是基于位置的。
// 如果是fmt库,会是这样:fmt::format("User: {user}, Role: {role}", fmt::arg("user", "Bob"), fmt::arg("role", "Admin"));
// 或是:fmt::format("User: {0}, Role: {1}", "Bob", "Admin");
// 鉴于C++20 std::format的限制,我们还是用位置参数来演示,以免误导。
// 让我们修正一下,用C++20标准库的std::format演示更常见的用法
std::string s4 = std::format("Width: {:<10}, Value: {:>5}", "Item", 123);
std::cout << s4 << std::endl; // 输出: Width: Item , Value: 123
// 写入到现有字符串
std::string buffer;
std::format_to(std::back_inserter(buffer), "Current time: {}", "2023-10-27");
std::cout << buffer << std::endl; // 输出: Current time: 2023-10-27
}std::format
str.format()
printf("%d", "hello")std::format
说实话,C++在字符串格式化这块,以前的选择确实有点“古老”或“笨重”。我们有C风格的
printf
sprintf
iostream
std::format
printf
sprintf
再看
iostream
std::cout << "Hello, " << name << "!" << std::endl;
std::fixed
std::setprecision
std::setw
std::stringstream
std::format
printf
std::format("{:<10.2f}", 123.456)iostream
stringstream
所以,我个人认为,
std::format
std::format
在实际项目中,我们经常会遇到需要格式化输出自定义类型的情况,或者对标准类型有更精细的格式控制需求。
std::format
首先,对于标准类型,
std::format
std::format("{:08X}", 255)000000FF
#include <iostream>
#include <format>
#include <string>
// 举例:格式化浮点数,保留两位小数,宽度10,左对齐,用'-'填充
void format_float_example() {
double value = 123.4567;
std::string s = std::format("{:-<10.2f}", value);
std::cout << "Formatted float: '" << s << "'" << std::endl; // 输出: '123.46----'
}
// 举例:格式化整数,八进制和十六进制
void format_int_example() {
int num = 255;
std::string oct_s = std::format("Octal: {:o}", num);
std::string hex_s = std::format("Hex: {:X}", num);
std::cout << oct_s << std::endl; // 输出: Octal: 377
std::cout << hex_s << std::endl; // 输出: Hex: FF
}更高级一点,当你有一个自定义的类或结构体,想让它也能被
std::format
std::formatter
parse
format
parse
Point
x,y
y,x
format
#include <iostream>
#include <format>
#include <string>
// 自定义结构体
struct Point {
int x;
int y;
};
// 为Point类型特化std::formatter
template <>
struct std::formatter<Point> {
char presentation = 'c'; // 'c' for default (x,y), 'r' for reversed (y,x)
// parse函数:解析格式字符串中的选项
// ctx.begin()指向格式字符串的当前位置,ctx.end()指向结束
// 返回一个迭代器,指向解析完选项后的下一个字符
constexpr auto parse(std::format_parse_context& ctx) {
auto it = ctx.begin();
if (it != ctx.end() && (*it == 'c' || *it == 'r')) {
presentation = *it;
++it;
}
// 如果还有其他格式选项(如宽度、精度),它们会由默认的格式化器处理
// 这里我们只处理自定义的'c'和'r'
return it;
}
// format函数:实际执行格式化
// value是待格式化的Point对象,ctx是格式化上下文
template <typename FormatContext>
auto format(const Point& p, FormatContext& ctx) const {
if (presentation == 'r') {
return std::format_to(ctx.out(), "({1}, {0})", p.x, p.y);
} else { // default 'c'
return std::format_to(ctx.out(), "({}, {})", p.x, p.y);
}
}
};
int main() {
Point p = {10, 20};
// 使用默认格式化
std::string s1 = std::format("Point: {}", p);
std::cout << s1 << std::endl; // 输出: Point: (10, 20)
// 使用自定义格式选项 'r'
std::string s2 = std::format("Reversed Point: {:r}", p);
std::cout << s2 << std::endl; // 输出: Reversed Point: (20, 10)
// 结合其他格式选项(例如宽度,尽管对Point意义不大,但语法上支持)
// 注意:std::formatter的parse方法需要处理这些,这里我们只处理了'c'/'r'
// std::string s3 = std::format("Padded Point: {:>15}", p); // 这会失败,因为我们没有处理对齐/宽度
// 实际使用时,如果自定义类型需要支持通用格式选项,parse需要更复杂地转发给默认的解析器
// 但对于简单自定义类型,如上即可。
return 0;
}通过这种方式,你可以让你的自定义类型无缝地融入
std::format
to_string()
operator<<
std::format
虽然
std::format
常见问题:
C++20标准库的可用性:
std::format
fmt
std::format
stringstream
printf
编译期错误信息:
std::format
命名参数的限制: 在C++20的
std::format
fmt::format("Hello, {name}", fmt::arg("name", "Alice"))std::format
std::format_args
fmt
std::format
自定义类型特化std::formatter
std::formatter
std::format
性能考量:
std::format
std::stringstream
printf
预计算和减少内存分配:
std::format
stringstream
编译期优化: 编译器可以对
std::format
与printf
printf
std::format
printf
std::format
std::format_to
std::format_to
总的来说,对于绝大多数应用场景,
std::format
std::format
以上就是C++格式化输出 std format字符串处理的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号