C++20 std::format

news2024/9/22 15:18:23

一、前言

1、传统 C++ 格式化的问题与挑战

  1. 可读性差:使用 C++ 中的 printf 和 scanf 家族函数进行格式化输出和输入时,它们的语法较为复杂,难以阅读。在较大的代码项目中,可读性差会导致维护困难。
  2. 类型安全性差:printf 和 scanf 等函数无法在编译期间检查参数的类型是否正确,这可能导致运行时错误,甚至引发程序崩溃。
  3. 不够灵活:对于复杂的格式化需求,printf 和 scanf 等函数提供的功能有限。例如,它们不支持自定义类型的格式化,也不方便处理宽字符和多字节字符集
  4. 性能开销:由于传统的格式化方法在运行时需要处理格式字符串,它们可能导致额外的性能开销。

2、C++20 引入 std::format 的背景

鉴于传统 C++ 格式化方法的局限性,C++20 标准中引入了 std::format 库,目的是提供一种更现代、更安全、更灵活的格式化方法。引入 std::format 的主要目的:

  1. 提高可读性:std::format 采用了一种更加简洁、易懂的语法,使得格式化字符串更具可读性
  2. 增强类型安全:std::format 在编译期间就可以检查参数类型的正确性,从而降低运行时错误的风险。
  3. 扩展功能:std::format 支持自定义类型的格式化,同时兼容宽字符和多字节字符集。这使得开发人员能够满足更为复杂的格式化需求。
  4. 性能优化:std::format 设计时充分考虑了性能问题,相比传统的格式化方法,它在许多场景下能够提供更高的性能。

总之,std::format 作为 C++20 标准的一部分,旨在解决传统 C++ 格式化方法的问题,并为开发者提供一种更现代、更安全、更灵活的格式化工具。


二、std::format 简介

1、std::format 的基本概念

std::format 是 C++20 标准库中新增的一个格式化工具,它基于 Python 中的 str.format() 函数,提供了一种类型安全且易于阅读的字符串格式化方法。std::format 的主要特点包括:

  1. 替换字段:std::format 使用花括号 {} 作为替换字段的占位符,这些替换字段在格式化时会被相应的参数值替换
  2. 格式规范:std::format 支持在替换字段内部定义格式规范,例如指定输出宽度、对齐方式和填充字符等。格式规范使用冒号:分隔,放在花括号内。
  3. 编译时类型检查:std::format 在编译期间检查参数类型的正确性,以提高类型安全性。
  4. 自定义类型支持:std::format 以通过重载 formatter 特化来支持自定义类型的格式化。

2、std::format 与 printf、iostreams 的对比

下面我们将对比 std::format 与 printf 和 iostreams 之间的主要差异:

  1. 可读性: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
  2. 类型安全:std::format 在编译期间检查参数类型的正确性,而 printf 在运行时检查类型。iostreams 也具有类型安全性,但 std::format 更接近 printf 的语法,使得从 printf 迁移到std::format 更容易。
  3. 扩展性:std::format 支持自定义类型的格式化,而 printf 仅支持内置类型。iostreams 通过重载插入和提取操作符支持自定义类型,但 std::format 提供更为统一的扩展方法。
  4. 性能:std::format 在设计时充分考虑了性能问题,因此在许多场景下性能优于 iostreams。而与 printf 相比,std::format 的性能表现也非常出色。

综上所述,std::format 在可读性、类型安全性、扩展性和性能方面都表现优异,成为现代 C++ 编程中推荐的字符串格式化工具。


3、高效使用std::format的理由

  1. 统一的格式化语法:std::format 提供了一种统一的格式化语法,无论是内置类型还是自定义类型,都可以使用相同的方法进行格式化。这有助于简化代码并降低维护成本。
  2. 简化代码:由于 std::format 提供了更简洁的语法,使用它可以减少代码量,使代码更易于理解。相较于 printf 和 iostreams,std::format 更适合处理复杂的字符串格式化需求。
  3. 避免运行时错误:std::format 在编译期间检查参数类型,能够减少因类型错误导致的运行时错误。这有助于提高代码的健壮性和稳定性。
  4. 易于迁移:对于已经习惯使用 printf 的开发者,std::format 提供了类似的语法和功能,可以轻松从 printf 迁移到 std::format。
  5. 便于调试和优化: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() 成员函数。实现自定义类型格式化输出的步骤:

  1. 包含头文件。
  2. 为自定义类型特化 std::formatter。
  3. 在特化的 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.14
    return 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 在很多方面都比传统的格式化方法更高效,但在某些情况下,性能仍然是一个值得关注的问题。以下是一些建议,可以帮助提高格式化性能:

  1. 避免频繁构建和销毁格式化字符串:在循环或高频调用的函数中避免重复构建格式化字符串。考虑将格式化字符串预先计算并存储为常量或静态变量。
  2. 减少不必要的字符串连接:在可能的情况下,尽量避免使用 + 运算符连接字符串。可以使用 std::format 直接构建最终字符串,而不是分段拼接。例如,可以将多个 std::format 调用替换为一个带有多个占位符的调用。
  3. 使用预分配的内存:为频繁使用的字符串分配足够的预先分配的内存,以减少内存分配和重新分配的开销。例如,您可以使用std::string::reserve() 函数为字符串预留足够的空间。
  4. 避免不必要的类型转换:在可能的情况下,尽量避免在格式化之前将数据类型转换为其他类型。例如,不要在格式化之前将 int 转换为 std::string,而是直接使用 int 类型的格式规范。
  5. 选择合适的容器和算法:根据具体应用场景选择合适的容器和算法,以实现最佳性能。例如,对于需要快速插入和删除元素的场景,使用 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++ 标准提供了一个坚实的基础。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2155346.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

IS-ISv4/6双栈

文章目录 IS-ISv4/6双栈实验要求配置 IS-ISv4/6双栈 实验要求 配置双栈 R1、2、3、4配置 IS-ISv4 和 IS-ISv6&#xff0c;配置IPv6多拓扑 上面为Level-1类型、中间为Level-1-2、下面是Level-2类型 还有就是说ATT位置1有一定要求连接L1/2连接L1或者L2类型路由器&#xff0c;至…

java23发布啦

2024年9月java23发布啦&#xff01;&#xff01;! JDK 23 提供了12 项增强功能&#xff0c;这些功能足以保证其自己的JDK 增强提案 - JEP &#xff0c;其中包括 8 项预览功能和 1 项孵化器功能。它们涵盖了对 Java 语言、API、性能和 JDK 中包含的工具的改进。除了 Java 平台上…

KVM环境下制作ubuntu qcow2格式镜像

如果是Ubuntu KVM环境是VMware虚拟机&#xff0c;需要CPU开启虚拟化 1、配置镜像源 wget -O /etc/apt/sources.list https://www.qingtongqing.cc/ubuntu/sources.list2、安装kvm qemu-img libvirt kvm虚拟化所需环境组件 apt -y install qemu-kvm virt-manager libvirt-da…

安装黑群晖,并使用NAS公网助手实现DDNS动态域名解析

很多人都会安装安装一个黑群晖进行练手&#xff0c;黑群晖有很多玩法和NAS套件&#xff0c;而且黑群晖安装比较简单&#xff0c;没有复杂的步骤&#xff0c;这也是很多人玩黑裙的理由&#xff0c;这里教大家如何安装黑群晖&#xff0c;并且安装神卓互联NAS公网助手实现DDNS动态…

arthas -- xxljob本地调试

方案一&#xff1a;测试类 package cn.wanda.wic.content.job.xxljob;import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest;import javax.annotation.Resource;SpringBootTest public class ShopResourceMigrationJobTest {Reso…

C\C++内存管理详解

本次内容大纲&#xff1a; 1.C/C内存分布 大家看看下面的代码 int globalVar 1; static int staticGlobalVar 1; void Test() {static int staticVar 1;int localVar 1;int num1[10] { 1, 2, 3, 4 };char char2[] "abcd";char* pChar3 "abcd";int…

本地快速部署一个简洁美观的个人Halo博客网站并发布公网远程访问

文章目录 前言1. Docker部署Halo1.1 检查Docker版本如果未安装Docker可参考已安装Docker步骤&#xff1a;1.2 在Docker中部署Halo 2. Linux安装Cpolar2.1 打开服务器防火墙2.2 安装cpolar内网穿透 3. 配置Halo个人博客公网地址4. 固定Halo公网地址 前言 本文主要介绍如何在Cen…

【Python日记】好丝滑的贪吃蛇

文章目录 原文&#xff1a;https://blog.c12th.cn/archives/39.htmlPython 贪吃蛇(pygame)前言部分代码完整代码 原文&#xff1a;https://blog.c12th.cn/archives/39.html Python 贪吃蛇(pygame) 前言 源代码参考B站: BV1cs411T7wW 效果展示 部分代码 框架 # 初始化 pygam…

基于微信小程序校园订餐的设计与开发+ssm(lw+演示+源码+运行)

摘 要 人民生活水平的提高就会造成生活节奏越来越快&#xff0c;很多人吃饭都采用点外卖的方式。现在点外卖的平台已有很多&#xff0c;大多都需要安装它们的APP才可以使用&#xff0c;并且没有针对校园。如果一味的使用外卖平台不仅会造成商家成本的增加&#xff0c;还不利于…

django应用JWT(JSON Web Token)实战

文章目录 一、什么是JWT二、为什么使用JWT三、在django项目中如何应用JWT1、安装djangorestframework-simplejwt库&#xff1a;2、在settings.py中配置JWT认证&#xff1a;3、在urls.py中配置JWT的获取和刷新路由&#xff1a; 四、JWT如何使用1、调用生成JWT的接口获取JWT2、客…

C++:类型转换(static_cast、reinterpret_cast、const_cast、dynamic_cast)、RTTI

C&#xff1a;类型转换&#xff08;static_cast、reinterpret_cast、const_cast、dynamic_cast&#xff09;、RTTI 一、C语言类型转换二、C新增强制类型转换2.1 新增类型转换&#xff1a;static_cast2.2 新增类型转换&#xff1a; reinterpret_cast2.3 新增类型转换&#xff1a…

新手上路:在Windows CPU上安装Anaconda和PyCharm

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一. 确认自己是CPU为什么选择CPU教程&#xff1f;GPU与CPU的区别如何判断自己是CPU 二. Anaconda 安装包 和 Pycharm 安装包步骤1&#xff1a;下载Anaconda步骤2&am…

【d46】【Java】【力扣】234.回文链表

思路 判断是否是回文&#xff0c;需要&#xff1a;一个指针指向头&#xff0c;一个指针指向尾&#xff0c;两个指针一边向中间靠拢&#xff0c;一边判断数值是否相同 对于单链表&#xff0c;不方便获得pre&#xff0c;如果将节点放进 数组/list &#xff0c;数组/list可以直接…

2024年9月22日历史上的今天大事件早读

189年9月22日 &#xff08;汉灵帝中平六年八月戊辰&#xff09;大将军何进入宫&#xff0c;策划铲除宦官&#xff0c;事败被杀 1499年9月22日 瑞士独立。 1630年9月22日 明朝抗清将领袁崇焕被崇祯皇帝凌迟处死于北京 1776年9月22日 美国间谍黑尔未经审判即被处绞刑 1860年9…

buucft hashcat

使用文本编辑器打开时乱码 使用010editor打开发现时xml文档 拷贝到kali&#xff0c;使用binwalk查看&#xff0c;发现时xml文档&#xff0c;改后缀名为ppt。打开发现有密码 Accent OFFICE Password Recovery 64位-Office密码恢复软件 v20.09 免费版 - 下载吧 试试这个Accent O…

[云服务器14] 搭建属于你自己的Git服务器

Git是由Linux Torvalds开发的一个版本控制系统(VCS,Version Control System)&#xff0c;而目前最大的Git仓库托管公司就是大名鼎鼎的GitHub啦&#xff01; 而这次&#xff0c;我们主要讲在自己的服务器上&#xff0c;搭建一个GitLab驱动的Git服务器&#xff01; [请CSDN审核…

大模型的威力,远不只是聊天框

自2022年底ChatGPT发布以来&#xff0c;我们真正看到了大模型的威力&#xff0c;也引发了技术圈种种畅想。有相当一部分观点认为&#xff0c;大模型是一种工业革命级的产物&#xff0c;相信更多的人会和笔者一样&#xff0c;认为大模型是一个操作系统级的产品&#xff0c;会彻底…

基于波特图的控制系统设计算法

波特图&#xff08;Bode Plot&#xff09;是一种用于描述线性控制系统频率响应的图形表示方法&#xff0c;通常用于分析和设计控制系统。它以控制系统的传递函数&#xff08;或频域传递函数&#xff09;为基础&#xff0c;将系统的幅频特性&#xff08;振幅-频率响应&#xff0…

统信服务器操作系统【刻录镜像制作U盘启动盘的工具】

统信服务器操作系统各版本上刻录镜像制作U盘启动盘的工具方案 文章目录 应用场景一、问题现象二、问题分析解决方案应用场景 硬件/整机信息:全平台 CPU架构:全架构 OS版本信息:服务器a版,e版,d版(其中d版遇到的刻录类问题较少) 软件信息:dd工具、Fedora Media Writer工…

每日学习一个数据结构-倒排表

文章目录 示意图倒排表的基本概念倒排表的数据结构示例 倒排表的优点应用场景 倒排表&#xff08;Inverted Index&#xff09;&#xff0c;也称为反向索引或倒排文件&#xff0c;在信息检索系统中是一种重要的数据结构。它主要用于快速搜索文档中的关键词&#xff0c;并找到包含…