C++之fmt庫介紹和使用(1)

C++之fmt庫介紹與使用(1)


Author: Once Day Date: 2025年5月12日

一位熱衷于Linux學習和開發的菜鳥,試圖譜寫一場冒險之旅,也許終點只是一場白日夢…

漫漫長路,有人對你微笑過嘛…

全系列文章可參考專欄: 源碼分析_Once-Day的博客-CSDN博客

參考文章:

  • Get Started - {fmt}
  • fmtlib/fmt: A modern formatting library

文章目錄

  • C++之fmt庫介紹與使用(1)
        • 1. 介紹
          • 1.1 概述
          • 1.2 性能對比
          • 1.3 編譯時間和代碼膨脹
          • 1.4 CMake編譯
        • 2. API介紹
          • 2.1 基礎API
          • 2.2 格式化用戶定義類型
          • 2.3 編譯時檢測
          • 2.4 命名參數(Named Arguments)
          • 2.5 類型擦除
          • 2.6 兼容性

1. 介紹
1.1 概述

fmtlib是一個現代化的C++格式化庫,它提供了一種安全、高效、靈活的方式來格式化和輸出文本。該庫由Victor Zverovich開發,旨在替代C++標準庫中的iostream和printf等傳統格式化方法。

使用fmtlib非常簡單,只需包含fmt/core.h頭文件,然后使用fmt::format()函數或fmt::print()函數即可。例如:

#include <fmt/core.h>int main() {std::string name = "Alice";int age = 18;fmt::print("Her name is {} and she is {} years old.\n", name, age);return 0;
}

以上代碼將輸出:“Her name is Alice and she is 18 years old.”

fmtlib具有具有如下的特性:

(1)安全性:受 Python 格式化功能的啟發,{fmt} 為printf系列函數提供了安全的替代方案。格式字符串中的錯誤在 C 語言中是常見的漏洞來源,而在 {fmt} 中,這類錯誤會在編譯時被報告出來。

fmt::format("{:d}", "I am not a number");

上述代碼會產生編譯時錯誤,因為d不是字符串的有效格式說明符。像fmt::format這樣的 API 通過自動內存管理來防止緩沖區溢出錯誤。

(2)可擴展性:{fmt} 開箱即支持大多數標準類型的格式化,包括所有容器、日期和時間。例如:

fmt::print("{}", std::vector{1, 2, 3});

上述代碼會以類似 JSON 的格式打印向量:

[1, 2, 3]

你可以讓自己定義的類型支持格式化,甚至還能對它們進行編譯時檢查。

(3)性能:{fmt} 比輸入輸出流(iostreams)和sprintf快 20 - 30 倍,在數值格式化方面表現尤為突出。

在這里插入圖片描述

{fmt} 庫盡量減少動態內存分配,并且可以選擇將格式字符串編譯為最優代碼。

(4)Unicode 支持:{fmt} 在主要操作系統上通過 UTF - 8 和char字符串提供可移植的 Unicode 支持。例如:

fmt::print("Слава Укра?н?!");

上述代碼在 Linux、macOS 甚至 Windows 控制臺上都能正確打印,而無需考慮代碼頁問題。

{fmt} 默認與區域設置無關,但你也可以選擇進行本地化格式化,{fmt} 能夠使其與 Unicode 協同工作,解決了標準庫中存在的相關問題。

(5)快速編譯:該庫廣泛使用類型擦除技術來實現快速編譯。fmt/base.h提供了一部分 API,其包含的依賴關系極少,并且具備足夠的功能來替代所有*printf的使用場景。

使用 {fmt} 的代碼編譯速度通常比等效的輸入輸出流代碼快幾倍。雖然printf的編譯速度仍然更快,但兩者之間的差距正在逐漸縮小。

(6)較小的二進制體積:類型擦除技術還用于防止模板膨脹,從而生成緊湊的單次調用二進制代碼。例如,調用帶單個參數的fmt::print僅需幾條指令,盡管它增加了運行時安全性,但其二進制體積與printf相當,并且比等效的輸入輸出流代碼小得多。

該庫本身的二進制體積較小,像浮點格式化這樣的一些組件可以被禁用,以便在資源受限的設備上進一步減小其體積。

(7)可移植性:{fmt} 擁有一個小巧且自包含的代碼庫,其核心僅由三個頭文件組成,并且沒有外部依賴。

該庫具有高度的可移植性,僅需要 C++11 的一小部分特性,這些特性在 GCC 4.9、Clang 3.4、MSVC 19.10(2017)及更高版本中均可用。如果編譯器和標準庫支持更新的特性,{fmt} 會加以利用,從而啟用更多功能。
在可能的情況下,格式化函數的輸出在各個平臺上保持一致。

在可能的情況下,格式化函數的輸出在各個平臺上保持一致。

(8)開源:{fmt} 是 GitHub 上排名前一百的開源 C++ 庫,擁有數百名貢獻者。

該庫基于寬松的 MIT 許可證分發,被許多開源項目所依賴,包括 Blender、PyTorch、蘋果的 FoundationDB、Windows Terminal、MongoDB 等。

fmtlib的主要特點包括:

  1. 簡單的 格式化 API,支持位置參數以方便本地化。
  2. 實現了 C++20 的 std::format 和 C++23 的 std::print
  3. 格式化字符串語法 類似于 Python 的 format。
  4. 快速的 IEEE 754 浮點數格式化器,使用 Dragonbox 算法,保證正確的舍入、最短表示和往返轉換。
  5. 可移植的 Unicode 支持。
  6. 安全的 printf 實現,包括支持位置參數的 POSIX 擴展。
  7. 可擴展性:支持用戶自定義類型。
  8. 高性能:比常見的標準庫實現(如 (s)printf、iostreams、to_string)更快。
  9. 安全性:該庫是完全類型安全的,格式化字符串中的錯誤可以在編譯時報告,自動內存管理可防止緩沖區溢出錯誤。
  10. 易用性:代碼庫小巧且自包含,無外部依賴,采用寬松的 MIT 許可證。
  11. 可移植性:跨平臺輸出一致,支持較舊的編譯器。
  12. 代碼干凈,即使在高警告級別(如 -Wall -Wextra -pedantic)下也無警告。
  13. 默認與區域設置無關。
  14. 可通過 FMT_HEADER_ONLY 宏啟用可選的僅頭文件配置。
1.2 性能對比

{fmt}是基準測試中最快的方法,比printf快約20%。

LibraryMethodRun Time, s
libcprintf0.91
libc++std::ostream2.49
{fmt} 9.1fmt::print0.74
Boost Format 1.80boost::format6.26
Folly Formatfolly::format1.87

上述結果是在macOS 12.6.1上使用clang++ -O3 -DNDEBUG -DSPEED_TEST -DHAVE_FORMAT編譯tinyformat_test.cpp,并取三次運行中的最佳結果生成的。

在測試中,格式字符串%0.10f:%04d:%+g:%s:%p:%c:%%\n或等效字符串被填充2,000,000次,輸出被發送到/dev/null

在IEEE754浮點數和雙精度格式化(dtoa-benchmark)方面,{fmt}比std::ostringstream和sprintf快20-30倍,并且比double-conversion和ryu更快:

在這里插入圖片描述

1.3 編譯時間和代碼膨脹

format-benchmark中的腳本bloat-test.py測試了非平凡項目的編譯時間和代碼膨脹。它生成100個翻譯單元,并在每個單元中使用printf()或其替代方法五次,以模擬一個中等規模的項目。生成的可執行文件大小和編譯時間(Apple clang version 15.0.0 (clang-1500.1.0.2.5),macOS Sonoma,三次中的最佳結果)如下表所示。

優化構建(-O3)

MethodCompile Time, sExecutable size, KiBStripped size, KiB
printf1.65450
IOStreams25.99884
fmt 83652df4.85450
tinyformat29.1161136
Boost Format55.0530317

{fmt}編譯速度快,在每次調用的二進制大小方面與printf相當(在此系統上在舍入誤差范圍內)。

非優化構建

MethodCompile Time, sExecutable size, KiBStripped size, KiB
printf1.45450
IOStreams23.49268
{fmt} 83652df4.48985
tinyformat24.5204161
Boost Format36.4831462

libc、lib(std)c++和libfmt都作為共享庫進行鏈接,以僅比較格式化函數的開銷。Boost Format是一個僅包含頭文件的庫,因此它不提供任何鏈接選項。

1.4 CMake編譯

{fmt} 提供了兩個 CMake 目標:fmt::fmt用于編譯庫,fmt::fmt-header-only用于僅包含頭文件的庫。為了縮短構建時間,建議使用編譯庫。

在 CMake 中使用 {fmt} 主要有三種方式:

FetchContent:從 CMake 3.11 開始,可以使用FetchContent在配置時自動下載 {fmt} 作為依賴項:

include(FetchContent)FetchContent_Declare(fmtGIT_REPOSITORY https://github.com/fmtlib/fmtGIT_TAG        e69e5f977d458f2650bb346dadf2ad30c5320281) # 10.2.1FetchContent_MakeAvailable(fmt)target_link_libraries(<your-target> fmt::fmt)

已安裝版本:可以在CMakeLists.txt文件中查找并使用已安裝的 {fmt} 版本,如下所示:

find_package(fmt)
target_link_libraries(<your-target> fmt::fmt)

嵌入方式:可以將 {fmt} 的源文件目錄添加到項目中,并在CMakeLists.txt文件中包含它:

add_subdirectory(fmt)
target_link_libraries(<your-target> fmt::fmt)

安裝發布版本:要在 Ubuntu 的 Linux 發行版上安裝 {fmt},請使用以下命令:

apt install libfmt-dev

從源代碼構建:CMake 通過生成原生的 makefile 或項目文件來工作,這些文件可以在你選擇的編譯器環境中使用。典型的工作流程如下:

mkdir build  # 創建一個目錄來存放構建輸出。
cd build
cmake ..     # 生成原生構建腳本。

常見的Cmake編譯構建選項如下所示:

# 編譯 thirdparty/fmt-11.1.4
# FMT_MASTER_PROJECT=OFF 非主項目
# FMT_UNICODE=OFF 不支持Unicode
$SOURCE_DIR/devops/scripts/cmake_build.sh thirdparty/fmt-11.1.4 \-DFMT_MASTER_PROJECT=OFF \-DFMT_UNICODE=OFF
2. API介紹

{fmt} 庫的 API 由以下組件構成:

  1. fmt/base.h:基礎 API,提供面向 char/UTF-8 的主要格式化函數,具備 C++20 編譯時檢查功能,且依賴極少。
  2. fmt/format.h:包含 fmt::format 及其他格式化函數,同時提供本地化支持。
  3. fmt/ranges.h:用于格式化范圍(ranges)和元組(tuples)。
  4. fmt/chrono.h:實現日期和時間的格式化。
  5. fmt/std.h:為標準庫類型提供格式化器。
  6. fmt/compile.h:用于格式化字符串編譯。
  7. fmt/color.h:提供終端顏色和文本樣式功能。
  8. fmt/os.h:包含系統相關 API。
  9. fmt/ostream.h:提供對 std::ostream 的支持。
  10. fmt/args.h:支持動態參數列表。
  11. fmt/printf.h:提供安全的 printf 功能。
  12. fmt/xchar.h:提供可選的 wchar_t 支持。

該庫提供的所有函數和類型都位于 fmt 命名空間中,而宏則以 FMT_ 為前綴。

2.1 基礎API

fmt/base.h 定義了基礎 API,它為 char/UTF-8 提供主要的格式化函數,并具備 C++20 編譯時檢查功能。為了優化編譯速度,它的頭文件依賴被減至最少。這個頭文件僅在將 {fmt} 作為庫使用時(默認方式)才有優勢,在僅頭文件模式下并無作用。它還為以下類型提供了格式化器特化:

  • intlong long
  • unsignedunsigned long long
  • floatdoublelong double
  • bool
  • char
  • const char*fmt::string_view
  • const void*

以下函數使用的格式字符串語法類似于 Python 中 str.format 的語法。它們接受 fmtargs 作為參數:

  • fmt 是一個格式字符串,包含普通文本和用花括號 {} 包圍的替換字段。這些字段會在結果字符串中被格式化為對應的參數。fmt::format_string 是一種格式字符串,它可以從字符串字面量或 constexpr 字符串隱式構造,并在 C++20 中進行編譯時檢查。若要傳遞運行時格式字符串,需將其包裝在 fmt::runtime 中。
  • args 是一個參數列表,表示要格式化的對象。

除非另有說明,I/O 錯誤會以 std::system_error 異常的形式報告。

template <typename... T>
void print(format_string<T...> fmt, T&&... args);fmt::print("The answer is {}.", 42);

根據 fmt 中的規范格式化 args,并將輸出寫入標準輸出(stdout)。

template <typename... T>
void print(FILE* f, format_string<T...> fmt, T&&... args);fmt::print(stderr, "Don't {}!", "panic");

根據 fmt 中的規范格式化 args,并將輸出寫入文件 f

template <typename... T>
void println(format_string<T...> fmt, T&&... args);

根據 fmt 中的規范格式化 args,將輸出寫入標準輸出(stdout),并在末尾添加一個換行符。

template <typename... T>
void println(FILE* f, format_string<T...> fmt, T&&... args);

根據 fmt 中的規范格式化 args,將輸出寫入文件 f,并在末尾添加一個換行符。

template <typename OutputIt, typename... T>
auto format_to(OutputIt&& out, format_string<T...> fmt, T&&... args) -> remove_cvref_t<OutputIt>;auto out = std::vector<char>();
fmt::format_to(std::back_inserter(out), "{}", 42);

根據 fmt 中的規范格式化 args,將結果寫入輸出迭代器 out,并返回指向輸出范圍末尾之后的迭代器。format_to 不會追加終止空字符。

template <typename OutputIt, typename... T>
auto format_to_n(OutputIt out, size_t n, format_string<T...> fmt, T&&... args) -> format_to_n_result<OutputIt>;

根據 fmt 中的規范格式化 args,將結果的最多 n 個字符寫入輸出迭代器 out,并返回總輸出大小(未截斷)和指向輸出范圍末尾之后的迭代器。format_to_n 不會追加終止空字符。

template <typename OutputIt>
struct format_to_n_result;

OutputIt out;:指向輸出范圍末尾之后的迭代器。size_t size;:總輸出大小(未截斷)。

template <typename... T>
auto formatted_size(format_string<T...> fmt, T&&... args) -> size_t;

返回 format(fmt, args...) 輸出的字符數。

2.2 格式化用戶定義類型

{fmt} 庫為許多標準 C++ 類型提供了格式化器。有關范圍(ranges)和元組(包括 std::vector 等標準容器)的格式化器,請參閱 fmt/ranges.h;有關日期和時間的格式化器,請參閱 fmt/chrono.h;有關其他標準庫類型的格式化器,請參閱 fmt/std.h

有兩種方法可以使自定義類型支持格式化:提供 format_as 函數或特化 formatter 結構體模板。

如果你希望將自定義類型按照另一種具有相同格式說明符的類型進行格式化,可以使用 format_as 方法。該函數應接受你的類型對象,并返回一個可格式化類型的對象。它應與你的類型定義在同一命名空間中。

#include <fmt/format.h>namespace kevin_namespacy {enum class film {house_of_cards, american_beauty, se7en = 7
};auto format_as(film f) { return fmt::underlying(f); }}int main() {fmt::print("{}\n", kevin_namespacy::film::se7en); // 輸出: 7
}

下面這種方法更復雜,但能完全控制解析和格式化過程。要使用此方法,需為你的類型特化 formatter 結構體模板,并實現 parseformat 方法。

推薦的定義格式化器的方法是通過繼承或組合復用現有的格式化器。這樣可以支持標準格式說明符而無需自己實現。例如:

// color.h:
#include <fmt/base.h>enum class color {red, green, blue};template <> struct fmt::formatter<color>: formatter<string_view> {// parse 方法繼承自 formatter<string_view>。auto format(color c, format_context& ctx) const-> format_context::iterator;
};// color.cc:
#include "color.h"
#include <fmt/format.h>auto fmt::formatter<color>::format(color c, format_context& ctx) const-> format_context::iterator {string_view name = "unknown";switch (c) {case color::red:   name = "red"; break;case color::green: name = "green"; break;case color::blue:  name = "blue"; break;}return formatter<string_view>::format(name, ctx);
}

注意,formatter<string_view>::format 定義在 fmt/format.h 中,因此必須在源文件中包含該頭文件。由于 parse 方法繼承自 formatter<string_view>,它將識別所有字符串格式規范,例如:

fmt::format("{:>10}", color::blue)

將返回 " blue"

一般來說,格式化器具有以下形式:

template <> struct fmt::formatter<T> {// 解析格式說明符并將其存儲在格式化器中。//// [ctx.begin(), ctx.end()) 是一個可能為空的字符范圍,// 包含從要解析的格式規范開始的格式字符串的一部分,例如在////   fmt::format("{:f} continued", ...);//// 該范圍將包含 "f} continued"。格式化器應解析說明符直到 '}' 或范圍結束。// 在這個例子中,格式化器應解析 'f' 說明符并返回指向 '}' 的迭代器。constexpr auto parse(format_parse_context& ctx)-> format_parse_context::iterator;// 使用存儲在格式化器中的已解析格式規范格式化 value,// 并將輸出寫入 ctx.out()。auto format(const T& value, format_context& ctx) const-> format_context::iterator;
};

建議至少支持適用于整個對象的填充(fill)、對齊(align)和寬度(width)選項,它們的語義應與標準格式化器中的相同。

你還可以為類層次結構編寫格式化器:

// demo.h:
#include <type_traits>
#include <fmt/core.h>struct A {virtual ~A() {}virtual std::string name() const { return "A"; }
};struct B : A {virtual std::string name() const { return "B"; }
};template <typename T>
struct fmt::formatter<T, std::enable_if_t<std::is_base_of_v<A, T>, char>> :fmt::formatter<std::string> {auto format(const A& a, format_context& ctx) const {return formatter<std::string>::format(a.name(), ctx);}
};// demo.cc:
#include "demo.h"
#include <fmt/format.h>int main() {B b;A& a = b;fmt::print("{}", a); // 輸出: B
}

注意:不允許同時提供格式化器特化和 format_as 重載。

上下文類型定義

template <typename Char>
using basic_format_parse_context = parse_context<Char>;class context;context(iterator out, format_args args, detail::locale_ref loc);

構造一個上下文對象。對象中存儲了對參數的引用,因此請確保這些參數具有適當的生命周期。

using format_context = context;
2.3 編譯時檢測

在支持 C++20 consteval的編譯器上,編譯時格式字符串檢查默認是啟用的。在較舊的編譯器上,你可以使用fmt/format.h中定義的FMT_STRING宏來替代。

和 Python 的str.format以及普通函數一樣,{fmt} 允許存在未使用的參數。

template <typename Char, typename... T>
using basic_format_string = basic_fstring<Char, T...>;template <typename... T>
using format_string = typename fstring<T...>::t;auto runtime(string_view s) -> runtime_format_string<>;

創建一個運行時格式字符串。

// 在運行時而不是編譯時檢查格式字符串。
fmt::print(fmt::runtime("{:d}"), "I am not a number");
2.4 命名參數(Named Arguments)
template <typename Char, typename T>
auto arg(const Char* name, const T& arg) -> detail::named_arg<Char, T>;

返回一個用于格式化函數的命名參數。它只能在調用格式化函數時使用。

fmt::print("The answer is {answer}.", fmt::arg("answer", 42));

目前,編譯時檢查不支持命名參數。

2.5 類型擦除

你可以創建自己的具有編譯時檢查和較小二進制體積的格式化函數,例如:

#include <fmt/format.h>void vlog(const char* file, int line,fmt::string_view fmt, fmt::format_args args) {fmt::print("{}: {}: {}", file, line, fmt::vformat(fmt, args));
}template <typename... T>
void log(const char* file, int line,fmt::format_string<T...> fmt, T&&... args) {vlog(file, line, fmt, fmt::make_format_args(args...));
}#define MY_LOG(fmt, ...) log(__FILE__, __LINE__, fmt, __VA_ARGS__)MY_LOG("invalid squishiness: {}", 42);

注意,與完全參數化的版本相比,vlog 沒有對參數類型進行參數化,這提高了編譯速度并減小了二進制代碼大小。

template <typename Context, typename... T, int NUM_ARGS, int NUM_NAMED_ARGS, unsigned long long DESC>
constexpr auto make_format_args(T&... args) -> detail::format_arg_store<Context, NUM_ARGS, NUM_NAMED_ARGS, DESC>;

構造一個存儲對參數的引用的對象,并且該對象可以隱式轉換為 format_argsContext 可以省略,在這種情況下它默認為 context

template <typename Context>
class basic_format_args;void vlog(fmt::string_view fmt, fmt::format_args args);  // 正確
fmt::format_args args = fmt::make_format_args();  // 懸空引用

格式化參數集合的視圖。為了避免生命周期問題,它應該僅用作類型擦除函數(如 vformat)中的參數類型:

constexpr basic_format_args(const store<NUM_ARGS, NUM_NAMED_ARGS, DESC>& s);

format_arg_store 構造一個 basic_format_args 對象。

constexpr basic_format_args(const format_arg* args, int count, bool has_named);

從動態參數列表構造一個 basic_format_args 對象。

auto get(int id) -> format_arg;

返回具有指定 id 的參數。

using format_args = basic_format_args<context>;template <typename Context>
class basic_format_arg;auto visit(Visitor&& vis) -?> decltype(vis(0));

根據參數類型調用適當的 visit 方法來訪問參數。例如,如果參數類型是 double,則將使用 double 類型的值調用 vis(value)

2.6 兼容性
template <typename Char>
class basic_string_view;

basic_string_view 是針對 C++17 之前版本實現的 std::basic_string_view。它提供了該類型 API 的一個子集。即使存在 std::basic_string_viewfmt::basic_string_view 也會被用于格式字符串,這樣做是為了防止在庫和客戶端代碼使用不同的 -std 選項進行編譯時出現問題(不推薦使用不同的 -std 選項)。

constexpr basic_string_view(const Char* s, size_t count);

從一個 C 字符串和一個大小構造一個字符串引用對象。

basic_string_view(const Char* s);

從一個 C 字符串構造一個字符串引用對象。

basic_string_view(const S& s);

從一個 std::basic_stringstd::basic_string_view 對象構造一個字符串引用。

constexpr auto data() -> const Char*;

返回指向字符串數據的指針。

constexpr auto size() -> size_t;

返回字符串的大小。

using string_view = basic_string_view<char>;

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/79828.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/79828.shtml
英文地址,請注明出處:http://en.pswp.cn/web/79828.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

設計模式(9)——創建型模式之工廠方法

設計模式(9)——創建型模式之工廠方法 工廠方法作用結構偽代碼適用場景工廠方法 作用 工廠方法是一種創建型設計模式,其在父類中提供一個創建對象的方法,允許子類決定實例化對象的類型。 結構 產品(Product)將會對接口進行聲明。對于所有由創建者及其子類構建的對象,…

Docker 疑難雜癥解決指南:從入門到進階的全面剖析

Docker 作為容器化技術的代表&#xff0c;憑借其輕量級、可移植性和高效資源利用率&#xff0c;已成為開發、測試和部署應用的標準工具。然而&#xff0c;在實際使用中&#xff0c;用戶常常會遇到鏡像構建失敗、容器啟動異常、網絡配置問題等疑難雜癥。本文將從鏡像構建、容器生…

搶跑「中央計算+區域控制」市場,芯馳科技高端智控MCU“芯”升級

伴隨著整車EE架構的加速變革&#xff0c;中國高端車規MCU正在迎來“新格局”。 在4月23日開幕的上海國際車展期間&#xff0c;芯馳科技面向新一代AI座艙推出了X10系列芯片&#xff0c;以及面向區域控制器、電驅和動力域控、高階輔助駕駛和艙駕融合系統等的高端智控MCU產品E3系…

DeepPrep:深度學習提升神經影像預處理

DeepPrep&#xff1a;深度學習提升神經影像預處理 一、DeepPrep介紹和BIDS格式介紹 神經影像預處理的痛點&#xff1a;傳統工具&#xff08;如fMRIPrep&#xff09;在大規模數據處理時效率低下&#xff0c;臨床樣本魯棒性不足。DeepPrep通過深度學習工作流管理實現突破&#…

pytorch 數據預處理和常用工具

文章目錄 NumPyNumpy數據結構安裝和使用NumPy Matplotlib的安裝和導入安裝和導入Matplotlib繪制基礎圖畫折線圖散點圖柱狀圖圖例 數據清洗據清洗的作用Pandas進行數據清洗Pandas數據結構Series 數據結構DataFrame數據結構 Pandas數據清洗常用代碼 特征工程主成分分析線性判別分…

MATLAB 中常用的微分函數介紹

MATLAB 中常用的微分函數介紹 在 MATLAB 中&#xff0c;微分運算是數值計算和符號計算中常用的功能。無論是在進行數據分析、優化算法&#xff0c;還是數學建模時&#xff0c;微分都扮演著重要的角色。本文將介紹 MATLAB 中常用的微分函數&#xff0c;并通過簡單的示例幫助大家…

按指定位置或關鍵字批量刪除工作表-Excel易用寶

在一個工作簿中有多個工作表&#xff0c;有些工作表不需要了&#xff0c;如果一個一個手動刪除&#xff0c;那實在是太慢了&#xff0c;有沒有什么好的方法可以批量刪除工作表。 批量刪除工作表很簡單&#xff0c;單擊【易用寶】→【工作表】→【批量刪除工作表】。 在打開的批…

TypeScript裝飾器:從入門到精通

TypeScript裝飾器&#xff1a;從入門到精通 什么是裝飾器&#xff1f; 裝飾器&#xff08;Decorator&#xff09;是TypeScript中一個非常酷的特性&#xff0c;它允許我們在不修改原有代碼的情況下&#xff0c;給類、方法、屬性等添加額外的功能。想象一下裝飾器就像給你的代碼…

【SSL證書系列】客戶端如何檢查中間CA簽名是否由根CA簽發

客戶端通過以下步驟檢查中間CA的簽名是否由受信任的根CA簽發&#xff1a; 1. 證書鏈的構建 服務器發送的證書鏈通常包含&#xff1a; ? 服務器證書&#xff08;由中間CA簽發&#xff09; ? 中間CA證書&#xff08;由根CA簽發&#xff09; ? 根CA證書&#xff08;通常不發送…

【android bluetooth 協議分析 12】【A2DP詳解 1】【車機側藍牙音樂免切源介紹】

“車機藍牙音樂免切源” 是近年來車載系統&#xff08;IVI&#xff0c;In-Vehicle Infotainment&#xff09;中常見的一個用戶體驗優化功能。它主要是為了簡化藍牙音樂播放流程、減少用戶操作&#xff0c;提升使用便捷性。 一、什么是“切源”&#xff1f; 在車機系統中&#…

Android usb網絡共享詳解

Android usb網絡共享詳解 文章目錄 Android usb網絡共享詳解一、前言二、USB網絡共享使用的前提1、Android設備支持adb 并且打開usb開關2、原生Settings能看到USB網絡共享開關3、代碼中檢測USB網絡共享是否支持 三、Settings 中USB網絡共享代碼的部分代碼1、Settings\res\xml\t…

Step1

項目 SchedulerSim 已搭建完成 ? ? ? 你現在擁有的&#xff1a; ? &#x1f527; 兩種調度器&#xff08;Round Robin SJF&#xff09; ? &#x1f4e6; 模擬進程類 Process ? &#x1f9f1; 清晰結構&#xff1a;OOP 風格 便于擴展 ? ?? 主函數已演示調度器運行效…

初探 Skynet:輕量級分布式游戲服務器框架實戰

在游戲服務器開發領域&#xff0c;高效、穩定且易于擴展的框架一直是開發者追求的目標。Skynet 作為一款輕量級、高性能的分布式游戲服務器框架&#xff0c;憑借其獨特的設計理念和強大的功能&#xff0c;贏得了眾多開發者的青睞 一.Skynet底層架構支持 1.Actor erlang 從語言…

Oracle數據庫中,WITH..AS 子句用法解析

前言 在Oracle數據庫中&#xff0c;WITH子句&#xff08;也成為“子查詢因子化” 或“公共表表達式”&#xff0c;Common Table Expression, CTE)用于定義一個臨時命名的結果集&#xff0c;這個結果集可以在后續的查詢中引用。 一、基本語法 WITH sjtab AS &#xff08;SELE…

什么是衛星電話?衛星電話與普通電話有什么區別?

在信息時代&#xff0c;通信技術已滲透到人類生活的方方面面&#xff0c;但傳統地面通信網絡仍存在盲區&#xff0c;無論是海洋、沙漠、高山&#xff0c;還是災害現場&#xff0c;普通手機往往因基站信號無法覆蓋而失效。此時&#xff0c;衛星電話便成為連接世界的“生命線”。…

【C/C++】高階用法_筆記

1. 模板元編程&#xff08;TMP&#xff09;與編譯時計算 (1) 類型萃取與 SFINAE 類型萃取&#xff08;Type Traits&#xff09;&#xff1a;利用模板特化在編譯時推斷類型屬性。 template<typename T> struct is_pointer { static constexpr bool value false; };templ…

鴻蒙OSUniApp 實現一個精致的日歷組件#三方框架 #Uniapp

使用 UniApp 實現一個精致的日歷組件 前言 最近在開發一個約會小程序時&#xff0c;需要實現一個既美觀又實用的日歷組件。市面上雖然有不少現成的組件庫&#xff0c;但都不太符合我們的設計需求。于是&#xff0c;我決定從零開始&#xff0c;基于 UniApp 自己實現一個功能完…

PyQt5完整指南:從入門到實踐

引言 PyQt5是Python編程語言的一個GUI&#xff08;圖形用戶界面&#xff09;工具包&#xff0c;它是Qt5應用程序框架的Python綁定。Qt是一個跨平臺的C應用程序開發框架&#xff0c;被廣泛用于開發GUI程序和非GUI程序。PyQt5讓Python開發者能夠使用Python語言享受到Qt框架的強大…

Excel的詳細使用指南

### **一、Excel基礎操作** #### **1. 界面與基本概念** - **工作簿&#xff08;Workbook&#xff09;**&#xff1a;一個Excel文件&#xff08;擴展名.xlsx&#xff09;。 - **工作表&#xff08;Worksheet&#xff09;**&#xff1a;工作簿中的單個表格&#xff08;默認名…

Linux grep -r 查找依賴包是否存在依賴類 Class

方法一&#xff1a;通過 Linux &#xff0c;grep -r ClassPath 命令 grep -f org.apache.kafka.connect.source.SourceRecord在 jar 包所在 lib 或者 lib/plugins 目錄下執行&#xff0c;grep -r&#xff0c; flink-sql-connector-sqlserver-cdc-3.3.0.jar 中此 kafka Source…