C++20 std::format
一、前言
1、传统 C++ 格式化的问题与挑战
- 可读性差:使用 C++ 中的 printf 和 scanf 家族函数进行格式化输出和输入时,它们的语法较为复杂,难以阅读。在较大的代码项目中,可读性差会导致维护困难。
- 类型安全性差:printf 和 scanf 等函数无法在编译期间检查参数的类型是否正确,这可能导致运行时错误,甚至引发程序崩溃。
- 不够灵活:对于复杂的格式化需求,printf 和 scanf 等函数提供的功能有限。例如,它们不支持自定义类型的格式化,也不方便处理宽字符和多字节字符集。
- 性能开销:由于传统的格式化方法在运行时需要处理格式字符串,它们可能导致额外的性能开销。
2、C++20 引入 std::format 的背景
鉴于传统 C++ 格式化方法的局限性,C++20 标准中引入了 std::format 库,目的是提供一种更现代、更安全、更灵活的格式化方法。引入 std::format 的主要目的:
- 提高可读性:std::format 采用了一种更加简洁、易懂的语法,使得格式化字符串更具可读性。
- 增强类型安全:std::format 在编译期间就可以检查参数类型的正确性,从而降低运行时错误的风险。
- 扩展功能:std::format 支持自定义类型的格式化,同时兼容宽字符和多字节字符集。这使得开发人员能够满足更为复杂的格式化需求。
- 性能优化:std::format 设计时充分考虑了性能问题,相比传统的格式化方法,它在许多场景下能够提供更高的性能。
总之,std::format 作为 C++20 标准的一部分,旨在解决传统 C++ 格式化方法的问题,并为开发者提供一种更现代、更安全、更灵活的格式化工具。
二、std::format 简介
1、std::format 的基本概念
std::format 是 C++20 标准库中新增的一个格式化工具,它基于 Python 中的 str.format() 函数,提供了一种类型安全且易于阅读的字符串格式化方法。std::format 的主要特点包括:
- 替换字段:std::format 使用花括号 {} 作为替换字段的占位符,这些替换字段在格式化时会被相应的参数值替换。
- 格式规范:std::format 支持在替换字段内部定义格式规范,例如指定输出宽度、对齐方式和填充字符等。格式规范使用冒号
:
分隔,放在花括号内。 - 编译时类型检查:std::format 在编译期间检查参数类型的正确性,以提高类型安全性。
- 自定义类型支持:std::format 以通过重载 formatter 特化来支持自定义类型的格式化。
2、std::format 与 printf、iostreams 的对比
下面我们将对比 std::format 与 printf 和 iostreams 之间的主要差异:
- 可读性:std::format 使用花括号作为占位符,并允许在占位符内定义格式规范。这使得格式化字符串更具可读性,相较于 printf 和 iostreams 更为简洁明了。
std::cout << std::format("Hello, {}!\n", "World"); // std::format printf("Hello, %s!\n", "World"); // printf std::cout << "Hello, " << "World" << "!\n"; // iostreams
- 类型安全:std::format 在编译期间检查参数类型的正确性,而 printf 在运行时检查类型。iostreams 也具有类型安全性,但 std::format 更接近 printf 的语法,使得从 printf 迁移到std::format 更容易。
- 扩展性:std::format 支持自定义类型的格式化,而 printf 仅支持内置类型。iostreams 通过重载插入和提取操作符支持自定义类型,但 std::format 提供更为统一的扩展方法。
- 性能:std::format 在设计时充分考虑了性能问题,因此在许多场景下性能优于 iostreams。而与 printf 相比,std::format 的性能表现也非常出色。
综上所述,std::format 在可读性、类型安全性、扩展性和性能方面都表现优异,成为现代 C++ 编程中推荐的字符串格式化工具。
3、高效使用std::format的理由
- 统一的格式化语法:std::format 提供了一种统一的格式化语法,无论是内置类型还是自定义类型,都可以使用相同的方法进行格式化。这有助于简化代码并降低维护成本。
- 简化代码:由于 std::format 提供了更简洁的语法,使用它可以减少代码量,使代码更易于理解。相较于 printf 和 iostreams,std::format 更适合处理复杂的字符串格式化需求。
- 避免运行时错误:std::format 在编译期间检查参数类型,能够减少因类型错误导致的运行时错误。这有助于提高代码的健壮性和稳定性。
- 易于迁移:对于已经习惯使用 printf 的开发者,std::format 提供了类似的语法和功能,可以轻松从 printf 迁移到 std::format。
- 便于调试和优化:std::format 的性能表现优异,且支持各种格式化选项,方便开发者进行调试和性能优化。
总之,std::format 作为 C++20 标准库的一部分,为开发者提供了强大、易用的字符串格式化工具。使用 std::format 可以简化代码、提高可读性、增强类型安全性,并有助于提高代码的健壮性和性能。因此,在现代 C++ 编程中,高效使用 std::format 是非常重要的。
三、基本用法
1、格式字符串与占位符
std::format 使用格式字符串来定义输出的格式。格式字符串中的占位符用花括号 {} 表示,可以包含以下几个部分:
- 参数索引:位于花括号内的数字,用于指定要替换的参数的位置。例如,{0} 表示第一个参数,{1} 表示第二个参数,依此类推。
- 格式规范:位于冒号
:
之后的部分,用于指定参数的格式选项。例如,{:d} 表示将参数格式化为十进制整数。 - 文本:花括号之间可以包含任意文本,这些文本将原样输出。例如,{0} is {1} 中的 is 会原样输出。
#include <iostream>
#include <format>int main()
{int age = 30;double pi = 3.1415926;std::string name = "Alice";std::cout << std::format("My name is {0} and I am {1} years old.\n", name, age);std::cout << std::format("Pi is approximately {0}.\n", pi);return 0;
}
2、类型规格与格式选项
std::format 支持各种类型规格与格式选项,以便对输出进行详细的控制。以下是一些常见的类型规格与格式选项
(1)整数
std::cout << std::format("{0:d} {0:x} {0:X} {0:o} {0:b}\n", 42);
(2)浮点数
std::cout << std::format("{0:f} {0:e} {0:E} {0:g} {0:G}\n", 3.1415926535);
(3)字符串
- s:字符串
std::cout << std::format("{:s}\n", "Hello, World!");
(4)宽度、对齐和填充
- <:左对齐
- >:右对齐
- ^:居中对齐
- 数字:指定输出宽度
- 字符:指定填充字符
std::cout << std::format("{:<10} | {:>10} | {:^10}\n", "left", "right", "center");
std::cout << std::format("{:*<10} | {:#>10} | {:_^10}\n", "left", "right", "center");
(5)精度
对于浮点数,精度用于指定小数点后的位数;对于字符串,精度用于指定最大输出长度。
std::cout << std::format("{:.2f} | {:.3e} | {:.4s}\n", 3.1415926, 12345.6789, "abcdefgh");
(6)整数和浮点数的进位
整数和浮点数的进位可以使用 # 选项,它会在八进制和十六进制数字前添加 0 或 0x(0X)前缀,或在浮点数上强制输出小数点。
std::cout << std::format("{:#x} | {:#o} | {:#f}\n", 42, 42, 3.14);
(7)正负号
使用 + 选项可以强制输出正数的正号。
std::cout << std::format("{:+d} | {:+f}\n", 42, 3.14);
(8)自定义类型
要格式化自定义类型,需要为类型特化 std::formatter 模板,并提供 parse 和 format 成员函数,这使得 std::format 可以以一种统一的方式处理内置类型和自定义类型。
struct Point
{int x;int y;
};template<>
struct std::formatter<Point>
{auto parse(format_parse_context& ctx){return ctx.begin();}auto format(const Point& p, format_context& ctx){return std::format_to(ctx.out(), "({:d}, {:d})", p.x, p.y);}
};std::cout << std::format("{0}\n", Point{3, 4});
四、格式化数字
在使用 std::format 时,可能会需要更多地控制数字的格式。
1、控制数字的宽度、精度与填充
要控制数字的宽度,请在格式说明符中指定一个整数。此外还可以使用 0 指定填充字符,例如 {:05} 表示将数字格式化为至少 5 个字符宽,不足部分用 0 填充。
std::cout << std::format("{:5}", 42); // " 42"
std::cout << std::format("{:05}", 42); // "00042"
对于浮点数,可以使用 . 后接一个整数来指定精度。
std::cout << std::format("{:.2f}", 3.14159); // "3.14"
2、显示或隐藏正负号
要显示数字的正负号,可以使用 + 标志。
std::cout << std::format("{:+}", 42); // "+42"
std::cout << std::format("{:+}", -42); // "-42"
3、进制转换(十进制、十六进制、八进制等)
要将数字格式化为其他进制,可以使用以下格式说明符:
- d:十进制(默认)
- x:十六进制(小写字母)
- X:十六进制(大写字母)
- o:八进制
- b:二进制(小写字母)
- B:二进制(大写字母)
std::cout << std::format("{:x}", 42); // "2a"
std::cout << std::format("{:X}", 42); // "2A"
std::cout << std::format("{:o}", 42); // "52"
std::cout << std::format("{:b}", 42); // "101010"
4、浮点数格式化选项
对于浮点数,可以使用以下格式说明符:
- f:定点表示(默认)
- F:定点表示(无穷大和非数字为大写表示)
- e:科学计数法(小写字母)
- E:科学计数法(大写字母)
- g:通用格式,根据值的大小和指定精度自动选择定点表示或科学计数法(小写字母)
- G:通用格式,根据值的大小和指定精度自动选择定点表示或科学计数法(大写字母)
可以看到不同浮点数格式化选项的使用方法。这使得 std::format 成为一个非常灵活和强大的工具,能够处理各种数字格式化需求。
五、格式化文本
在使用 std::format 时,除了处理数字之外,还需要考虑如何格式化文本。
1、控制字符串的宽度与填充
要设置字符串的最小宽度,请在格式说明符中指定一个整数。您还可以通过在整数前加上填充字符来设置填充字符。
std::cout << std::format("{:10}", "hello"); // "hello "
std::cout << std::format("{:_<10}", "hello"); // "hello_____"
2、处理特殊字符与转义
要在格式化字符串中包含大括号 {},可以使用两个连续的大括号 {{ 或 }} 进行转义。
std::cout << std::format("The set contains {{1, 2, 3}}"); // "The set contains {1, 2, 3}"
要在格式化字符串中包含反斜杠和其他特殊字符,请使用反斜杠进行转义,如 \n 表示换行符,\t 表示制表符等。
std::cout << std::format("Line 1\\nLine 2"); // "Line 1\nLine 2"
3、使用 std::format 处理多语言与 Unicode
std::format 支持 Unicode 字符和多语言文本处理。为了确保正确处理 Unicode 字符,请使用 u8 前缀表示 UTF-8 编码的字符串字面值。
std::cout << std::format(u8"你好,世界!"); // "你好,世界!"
在处理 Unicode 字符串时,确保使用正确的编码,否则可能会导致乱码或无法解释的字符。std::format 兼容 C++17 及更高版本的 std::u8string 类型,能够更轻松地处理多语言文本。
std::format 提供了处理字符串宽度、填充、特殊字符、转义以及多语言和 Unicode 字符的能力,这使得 std::format 成为一个非常适用于现代 C++ 应用程序的强大工具。
六、格式化日期与时间
std::format 可以与 C++ 的 chrono 库一起使用,方便地格式化日期和时间。
1、使用 chrono 库处理时间点与持续时间
chrono 库提供了表示时间点和持续时间的类,如 system_clock::time_point、steady_clock::time_point、duration 等。要使用 std::format 格式化这些类型,首先需要包含和头文件。
#include <iostream>
#include <chrono>
#include <format>int main()
{auto now = std::chrono::system_clock::now();auto seconds_since_epoch = std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch());std::cout << std::format("Seconds since epoch: {}\n", seconds_since_epoch.count());
}
2、时间格式化选项
要格式化日期和时间,可以使用扩展的格式说明符:
- %Y:四位年份
- %m:月份(01-12)
- %d:月份中的第几天(01-31)
- %H:小时(00-23)
- %M:分钟(00-59)
- %S:秒(00-60,因闰秒可能为60)
为了使用这些格式化选项,需要先将 chrono 中的 time_point 转换为 std::tm 结构,并包含头文件。
#include <iostream>
#include <chrono>
#include <format>
#include <iomanip>int main()
{auto now = std::chrono::system_clock::now();auto now_t = std::chrono::system_clock::to_time_t(now);auto now_tm = *std::localtime(&now_t);std::cout << std::format("{:%Y-%m-%d %H:%M:%S}\n", now_tm);return 0;
}
3、本地化日期与时间的显示
要显示本地化的日期和时间,可以使用 std::locale,使用 imbue() 函数将流与特定的语言环境关联起来。
#include <iostream>
#include <chrono>
#include <format>
#include <iomanip>
#include <locale>int main()
{auto now = std::chrono::system_clock::now();auto now_t = std::chrono::system_clock::to_time_t(now);auto now_tm = *std::localtime(&now_t);std::locale::global(std::locale(""));std::cout.imbue(std::locale());std::cout << std::format("{:%c}\n", now_tm);return 0;
}
注意:std::locale::global() 和 imbue() 函数的参数取决于平台和语言设置,也可以为特定的流或字符串指定语言环境。
通过以上方法,可以使用 std::format 来灵活地处理和格式化日期与时间。与 C++ 的 chrono 库结合使用,可以更方便地处理时间点和持续时间,同时允许定制时间格式化选项以适应不同的应用场景。同时,通过 std::locale 类,还可以实现日期和时间的本地化显示,以适应不同地区的用户。
#include <iostream>
#include <chrono>
#include <format>
#include <iomanip>
#include <locale>int main()
{auto now = std::chrono::system_clock::now();auto now_t = std::chrono::system_clock::to_time_t(now);auto now_tm = *std::localtime(&now_t);std::cout << std::format("{:%A, %B %d, %Y}\n", now_tm); // 显示星期、月份、日期和年份,例如:"Sunday, April 09, 2023"std::cout << std::format("{:%D}\n", now_tm); // 以MM/DD/YY格式显示日期,例如:"04/09/23"std::cout << std::format("{:%T}\n", now_tm); // 以HH:MM:SS格式显示时间,例如:"17:30:59"std::cout << std::format("{:%r}\n", now_tm); // 以12小时制显示时间,例如:"05:30:59 PM"return 0;
}
七、自定义类型的格式化
std::format 允许为自定义类型实现格式化支持,这为自定义类型提供了更好的输出显示。要实现自定义类型的格式化支持,需要特化 std::formatter。
1、实现自定义类型的格式化支持
要为自定义类型实现格式化支持,您需要为其特化 std::formatter,并重载 parse() 和 format() 成员函数。实现自定义类型格式化输出的步骤:
- 包含头文件。
- 为自定义类型特化 std::formatter。
- 在特化的 std::formatter 中,重载 parse() 和 format() 成员函数。
2、使用 fmt::formatter 特化
#include <iostream>
#include <format>
#include <string>struct Person
{std::string name;int age;
};template <>
struct std::formatter<Person>
{constexpr auto parse(format_parse_context& ctx){auto it = ctx.begin();auto end = ctx.end();if (it != end && *it != '}')throw format_error("Invalid format");return it;}auto format(const Person& p, format_context& ctx){return format_to(ctx.out(), "{} ({})", p.name, p.age);}
};
3、为自定义类型实现格式化输出
现在已经为 Person 类型实现了 std::formatter 特化,可以使用 std::format 函数轻松格式化 Person对象了:
int main()
{Person alice{"Alice", 30};std::cout << std::format("{}", alice) << std::endl; // Alice (30)
}
通过实现 std::formatte r特化并重载 parse() 和 format() 成员函数,可以为自定义类型提供灵活且易于使用的格式化支持,这可以大大提高 C++ 代码的可读性和维护性。
八、std::format的高级技巧与应用
1、格式字符串的动态生成
在某些情况下,可能需要根据运行时参数动态生成格式字符串,可以使用 std::string 或其他字符串处理方法来实现这一点。
根据用户输入设置小数点后的位数:
#include <iostream>
#include <format>int main()
{double pi = 3.141592653589793;int precision = 2;std::string format_str = "{:." + std::to_string(precision) + "f}";std::cout << std::format(format_str, pi) << std::endl; // 3.14return 0;
}
2、使用 std::format 与其他标准库组件
std::format 可以与其他标准库组件(如容器、文件操作等)一起使用,以提供更高级的格式化功能。
(1)与 STL 容器完美结合
#include <iostream>
#include <format>
#include <vector>int main()
{std::vector<int> numbers = {1, 2, 3, 4, 5};std::string result = std::format("Numbers: [");for (const auto& num : numbers){result += std::format("{}, ", num);}result = result.substr(0, result.size() - 2) + "]";std::cout << result << std::endl; // Numbers: [1, 2, 3, 4, 5]return 0;
}
(2)文件操作一起使用
#include <iostream>
#include <format>
#include <fstream>int main()
{std::ofstream output_file("output.txt");output_file << std::format("{:<10} {:>10}\n", "Name", "Score");output_file << std::format("{:<10} {:>10}\n", "Alice", 95);output_file << std::format("{:<10} {:>10}\n", "Bob", 80);output_file.close();std::cout << "Output saved to output.txt" << std::endl;return 0;
}
3、提高格式化性能的建议
虽然 std::format 在很多方面都比传统的格式化方法更高效,但在某些情况下,性能仍然是一个值得关注的问题。以下是一些建议,可以帮助提高格式化性能:
- 避免频繁构建和销毁格式化字符串:在循环或高频调用的函数中避免重复构建格式化字符串。考虑将格式化字符串预先计算并存储为常量或静态变量。
- 减少不必要的字符串连接:在可能的情况下,尽量避免使用 + 运算符连接字符串。可以使用 std::format 直接构建最终字符串,而不是分段拼接。例如,可以将多个 std::format 调用替换为一个带有多个占位符的调用。
- 使用预分配的内存:为频繁使用的字符串分配足够的预先分配的内存,以减少内存分配和重新分配的开销。例如,您可以使用std::string::reserve() 函数为字符串预留足够的空间。
- 避免不必要的类型转换:在可能的情况下,尽量避免在格式化之前将数据类型转换为其他类型。例如,不要在格式化之前将 int 转换为 std::string,而是直接使用 int 类型的格式规范。
- 选择合适的容器和算法:根据具体应用场景选择合适的容器和算法,以实现最佳性能。例如,对于需要快速插入和删除元素的场景,使用 std::list 或 std::deque 而不是 std::vector。
通过遵循以上建议,可以确保在使用 std::format 进行格式化操作时实现最佳性能。这将有助于提高 C++ 应用程序的整体性能和响应速度。
九、结论与展望
1、std::format在现代C++中的地位与作用
std::format 是 C++20 中引入的一个重要特性,它在现代 C++ 中扮演着重要的角色。与传统的 C++ 格式化方法相比,如 printf 和 iostreams,std::format 提供了更为强大、灵活和安全的格式化功能。它支持类型安全,易于扩展,支持自定义类型和多语言环境。std::format 有助于提高代码的可读性和维护性,使得 C++ 在格式化方面与其他现代编程语言保持同步。
2、与其他语言的格式化库的比较
std::format 的设计受到了其他编程语言中格式化库的启发,如 Python 的 str.format() 和 f-string,以及 Rust 的 std::fmt。与这些库相比,std::format 具有类似的功能和语法,同时充分利用了 C++ 的类型系统和编译时特性,以实现最佳性能。
3、C++标准化进程中格式化相关的未来发展
C++ 标准化进程将继续发展和完善格式化功能。例如,C++23 中可能会引入 std::format 的扩展,以提供更丰富的格式选项和本地化支持。此外,C++ 社区也将继续关注其他语言的发展,以确保 C++ 在格式化方面与时俱进。
总之,std::format 为 C++ 开发者提供了一种强大且易于使用的格式化工具。它不仅带来了更好的类型安全和扩展性,还为未来的 C++ 标准提供了一个坚实的基础。
相关文章:

C++20 std::format
一、前言 1、传统 C 格式化的问题与挑战 可读性差:使用 C 中的 printf 和 scanf 家族函数进行格式化输出和输入时,它们的语法较为复杂,难以阅读。在较大的代码项目中,可读性差会导致维护困难。类型安全性差:printf 和…...

Python基础知识 (九)os模块、异常、异常的传递性
目录 OS模块 目录的具体操作 什么是异常 异常常见处理方式 异常分类: 捕获一个指定异常 捕获多个异常 捕获所有异常 异常具有传递性 OS模块 在Python中,os模块的常用函数分为两类: (a)通过os.path调用的函数…...

鸿蒙手势交互(三:组合手势)
三、组合手势 由多种单一手势组合而成,通过在GestureGroup中使用不同的GestureMode来声明该组合手势的类型,支持顺序识别、并行识别和互斥识别三种类型。 GestureGroup(mode:GestureMode, gesture:GestureType[]) //- mode:为GestureMode枚…...

【计算机方向】中科院二区TOP神刊!国人发文友好,刊文量高,录用容易!
期刊解析 🚩本 期 期 刊 看 点 🚩 中科院二区TOP期刊! 审稿友好,IF4.8,自引率6.2% 最新年度发文530。 今天小编带来计算机领域SCI快刊的解读! 如有相关领域作者有意投稿,可作为重点关注&am…...

Stable Diffusion 保姆级教程
1. 引言 近年来,Stable Diffusion 成为了图像生成领域的热门技术,它是一种基于扩散模型的生成模型,可以通过输入简单的文本描述生成高质量的图像。相比传统的生成对抗网络(GAN),Stable Diffusion 更具稳定…...

踩坑记录:adb修改settings数据库ContentObserver无回调
在Android 14版本开发过程中遇到一个,通过adb修改settings数据库,发现生效但是监听的ContentObserver无回调 以背光亮度值调节为例 adb shell settings put system screen_brightness 18 调节亮度值到指定值,修改完后查看 adb shell set…...

JAVA毕业设计183—基于Java+Springboot+vue的旅游小程序系统(源代码+数据库)
毕设所有选题: https://blog.csdn.net/2303_76227485/article/details/131104075 基于JavaSpringbootvue的旅游小程序系统(源代码数据库)183 一、系统介绍 本项目前后端不分离,分为用户、管理员两种角色 1、用户: 注册、登录、公告信息(…...

[大语言模型] 情感认知在大型语言模型中的近期进展-2024-09-26
[大语言模型] 情感认知在大型语言模型中的近期进展-2024-09-26 论文信息 Title: Recent Advancement of Emotion Cognition in Large Language Models Authors: Yuyan Chen, Yanghua Xiao https://arxiv.org/abs/2409.13354 情感认知在大型语言模型中的近期进展 《Recent A…...

WiFi无线连接管理安卓设备工具:WiFiADB
介绍 WiFi ADB 使您能够通过 WiFi TCP/IP 连接直接在设备上轻松调试和测试 Android 应用,无需使用 USB 数据线。在启用 WiFi 上的 ADB 后,打开控制台将电脑连接到设备。 手机和电脑在同一个WiFi然后电脑上运行adb connect x.x.x.x:x命令即可 下载 谷…...

Django项目配置日志
需求 在Django项目中实现控制台输出到日志文件,并且设置固定的大小以及当超过指定大小后覆盖最早的信息。 系统日志 使用Django自带的配置,可以自动记录Django的系统日志。 可以使用logging模块来配置。下面是一个完整的示例代码,展示了如…...

在IntelliJ IDEA中设置文件自动定位
当然,以下是一个整理成博客格式的内容,关于如何在IntelliJ IDEA中设置文件自动定位功能。 在IntelliJ IDEA中设置文件自动定位 背景 最近由于公司项目开发的需求,我从VSCode转到了IntelliJ IDEA。虽然IDEA提供了许多强大的功能,…...

机器学习笔记 - week6 -(十一、机器学习系统的设计)
11.1 首先要做什么 在接下来的视频中,我将谈到机器学习系统的设计。这些视频将谈及在设计复杂的机器学习系统时,你将遇到的主要问题。同时我们会试着给出一些关于如何巧妙构建一个复杂的机器学习系统的建议。下面的课程的的数学性可能不是那么强…...

对c语言中的指针进行深入全面的解析
1.普通的指针: 实际上指针就是存放地址的变量,eg: int a10; int *p&a; 拆分一下int *中的*说明p是一个指针,int是它所指向的类型; 2.字符串指针和字符串数组 char*str1"abcd"; 先看这一个,这个就是一个字符串…...

xxl-job 适配达梦数据库
前言 在数字化转型的浪潮中,任务调度成为了后端服务不可或缺的一部分。XXL-JOB 是一个轻量级、分布式的任务调度框架,广泛应用于各种业务场景。达梦数据库(DM),作为一款国内领先的数据库产品,已经被越来越…...

Linux 配置与管理 SWAP(虚拟内存)
Linux 配置与管理 SWAP(虚拟内存) 一、作用二、创建交换文件(以创建一个2GB的交换文件为例)1. 创建交换文件2. 设置文件权限2.1. **关于 sudo chmod 600 /root/swapfile 是否一定要执行**2.2. **关于其他用户启动是否没权限用到交换分区** 3.…...

yolo自动化项目实例解析(七)自建UI--工具栏选项
在上一章我们基本实现了关于预览窗口的显示,现在我们主要完善一下工具栏菜单按键 一、添加工具栏ui 1、配置文件读取 我们后面要改的东西越来越多了,先加个变量文件方便我们后面调用 下面我们使用的config.get意思是从./datas/setting.ini文件中读取关键…...

贝锐洋葱头浏览器随时随地访问教务系统,轻松搞定选课
教育网的“拥堵”早已是老生常谈,学生数量庞大、上网时间集中、带宽有限,导致网络速度慢。尤其是从外部网络访问教育网时,更是因为跨运营商的缘故变得缓慢。 而学校内网也是类似的情况,课余时间和上课时间的网络使用情况差别巨大…...

django drf to_internal_value
使用场景 用于将接收到的输入转换为内部可用的数据形式; 例子 to_internal_value主要在反序列化时用到,其作用处理API请求携带的数据,对其进行验证并转化为Python的数据类型。 假如我们的API客户端通过请求提交了额外的数据,比…...

map(lambda x: x[0], sorted(count.items(), key=lambda x: (-x[1], x[0]))[:n])
被解析的代码行 map(lambda x: x[0], sorted(count.items(), keylambda x: (-x[1], x[0]))[:n])假设的输入 假设我们有以下的 count 字典,其中包括一些字符串及其对应的计数: count {apple: 3,banana: 1,orange: 2,grape: 2 }1. count.items() 首先…...

灰度重心法求取图像重心
1 概述 灰度重心法(Gray-scale Center of Mass Method)是一种在图像处理和计算机视觉中常用的方法。这种方法主要用于确定图像中物体的质心或重心位置,特别是在灰度图像中。 灰度重心法的基本思想是,根据图像中每个像素的灰度值及其位置信息来计算一个加权重心,这个重心…...

Go Mail设置指南:如何提升发送邮件效率?
Go Mail使用技巧与配置教程?如何用Go Mail实现发信? 随着工作负载的增加,如何高效地发送和管理邮件成为了许多职场人士面临的挑战。AokSend将为您提供一份详细的Go Mail设置指南,帮助您提升发送邮件的效率,让您的邮件…...

kali的tplmap使用报错解决
问题 当我们直接使用kali下的tplmap时报错了。 Tplmap 0.5 Automatic Server-Side Template Injection Detection and Exploitation Tool Testing if GET parameter name is injectable Exiting: module collections has no attribute Mapping 这是因为tplmap要求的版本…...

DAY16||513.找树左下角的值 |路径总和|从中序与后序遍历序列构造二叉树
513.找树左下角的值 题目:513. 找树左下角的值 - 力扣(LeetCode) 给定一个二叉树的 根节点 root,请找出该二叉树的 最底层 最左边 节点的值。 假设二叉树中至少有一个节点。 示例 1: 输入: root [2,1,3] 输出: 1示例 2: 输入: […...

使用jQuery处理Ajax
使用jQuery处理Ajax HTTP协议 超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议 设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法 所有的WWW文件都必须遵守这个标准 一次HTTP操作称为一个事务&am…...

uni-app App版本更新
效果图: 前言 在移动应用开发中,确保用户能够及时更新到最新版本是非常重要的。本文将介绍如何在 uni-app 中实现 App 整包更新功能,并提供相关代码示例以帮助理解。 代码实现 2.1 引入模块 首先,我们需要引入用于处理更新的模块…...

Python Web 与低代码/无代码平台的深度融合
Python Web 与低代码/无代码平台的深度融合 目录 🚀 低代码与无代码平台的兴起🔗 Python 与低代码平台集成🌐 低代码开发的最佳实践📊 数据集成与自动化 1. 🚀 低代码与无代码平台的兴起 低代码和无代码平台的出现&…...

js 如何监听 body 内容是否改变
如果您想监听body内容的变化,并作出响应,可以使用MutationObserver。以下是一个简单的例子,它会在body内容变化时在控制台输出一条消息: // 创建一个观察者对象 const observer new MutationObserver(function(mutations, obser…...

python: 数字类型的一些函数
len(str) round(x, d) 对x进行四舍五入保留小数点后d位 round(3.45,1) 即 3.5 pow(x, y) # x的y次幂. x ** y pow(x, y[,z]) # 幂余 ( x ** y) % z print(pow(3, pow(3, 99), 10000)) #4587 浮点数…...

MapReduce学习与理解
MapReduce为google分布式三驾马车之一。分别为《The Google File System》、《MapReduce: Simplified Data Processing on Large Clusters》、《Bigtable: A Distributed Storage System for Structured Data》。三遍论文奠定了分布式存储和计算的基础。本篇文章来说说mapreduc…...

Animal objDog = new Dog()和 Dog objDog = new Dog()的区别
文章目录 1、Animal objDog new Dog()和 Dog objDog new Dog()的区别1. **对象类型(引用类型)**2. **调用和可用成员**3. **示例代码来说明**使用示例总结 2、Animal objDog new Dog();不能调用dog的方法和属性是为什么?原因解析解决方法小…...