C++20格式化字符串:std::format的使用與實踐

在C++編程中,字符串格式化是一項常見的任務。在C++20引入std::format之前,開發者通常依賴于一些傳統的解決方案,如printf系列函數、sstream,或者第三方庫如boost.format。然而,這些方法在代碼可讀性、類型安全性和靈活性方面存在一定的局限性。本文將首先回顧這些舊方法及其問題,然后詳細介紹C++20中std::format的使用與實踐。

一、C++20之前的字符串格式化方法

在C++20之前,開發者主要依賴以下幾種方法進行字符串格式化:

  1. printf系列函數
  2. sstream
  3. 第三方庫(如boost.format

1. printf系列函數

printf函數是C語言中常用的字符串格式化工具,它通過格式說明符來指定參數的類型和格式。雖然簡單易用,但printf存在一些嚴重的問題:

  • 類型不安全printf無法檢查參數的類型和數量是否與格式說明符匹配,容易導致運行時錯誤。
  • 難以維護:復雜的格式化需求需要多個printf調用,代碼可讀性差。

示例:

#include <cstdio>int main() {printf("整數: %d, 浮點數: %.2f\n", 123, 45.67);return 0;
}

輸出:

整數: 123, 浮點數: 45.67

2. sstream

sstream是C++標準庫中提供的類,通過std::ostringstream可以方便地進行字符串格式化。sstream具有類型安全性和可維護性的優點,但其語法相對繁瑣,不夠靈活。

示例:

#include <sstream>
#include <string>int main() {std::ostringstream oss;oss << "整數: " << 123 << ", 浮點數: " << 45.67;std::string result = oss.str();// result 的值為 "整數: 123, 浮點數: 45.67"return 0;
}

優點:

  • 類型安全:編譯器會檢查操作數的類型,避免類型不匹配的問題。
  • 可維護性高:代碼結構清晰,易于維護。

缺點:

  • 語法不夠靈活:無法像printfstd::format那樣通過格式說明符指定復雜的格式。

3. 第三方庫(如boost.format

boost.format是Boost庫中提供的一個格式化字符串工具,它提供了類似于Python的格式化功能。雖然功能強大,但需要引入額外的依賴,可能不適合所有項目。

示例:

#include <boost/format.hpp>
#include <string>int main() {std::string result = boost::format("整數: %1%, 浮點數: %.2f") % 123 % 45.67;// result 的值為 "整數: 123, 浮點數: 45.67"return 0;
}

優點:

  • 功能強大:支持復雜的格式化需求。
  • 類型安全:編譯器會檢查參數的類型和數量是否匹配。

缺點:

  • 需要引入第三方庫:增加了項目的依賴。
  • 學習成本較高:需要學習Boost庫的使用方法。

二、C++20之前的字符串格式化方法對比

下表對C++20之前的幾種字符串格式化方法進行了對比,展示了它們的常規用法和主要問題:

方法名稱示例代碼輸出結果主要問題
printfprintf("整數: %d, 浮點數: %.2f\n", 123, 45.67);整數: 123, 浮點數: 45.67類型不安全,難以維護
sstreamoss << "整數: " << 123 << ", 浮點數: " << 45.67;整數: 123, 浮點數: 45.67語法繁瑣,不夠靈活
boost.formatboost::format("整數: %1%, 浮點數: %.2f") % 123 % 45.67;整數: 123, 浮點數: 45.67需要第三方庫,學習成本較高

三、C++20的std::format:現代、安全、靈活的字符串格式化

C++20引入的std::format庫,整合了上述方法的優點,提供了一種現代、安全、靈活的字符串格式化解決方案。它支持與Python類似的格式化語法,能夠處理多種數據類型,并且可以自定義格式化方式。

1. std::format的基本用法

std::format的基本語法如下:

#include <format>
#include <string>int main() {std::string result = std::format("Hello, {}!", "World");// result 的值為 "Hello, World!"return 0;
}

2. 格式說明符

std::format支持多種格式說明符,可以對整數、浮點數、字符串等多種數據類型進行格式化。

a. 整數格式化

std::string result = std::format("整數: {:d}, 十六進制: {:x}, 八進制: {:o}", 123, 123, 123);
// result 的值為 "整數: 123, 十六進制: 7b, 八進制: 173"
  • :d:以十進制形式顯示整數。
  • :x:以小寫十六進制形式顯示整數。
  • :o:以八進制形式顯示整數。

b. 浮點數格式化

std::string result = std::format("浮點數: {:f}, 科學計數法: {:e}, 保留三位小數: {:.3f}", 123.456, 123.456, 123.456);
// result 的值為 "浮點數: 123.456000, 科學計數法: 1.234560e+02, 保留三位小數: 123.456"
  • :f:以固定點格式顯示浮點數。
  • :e:以科學計數法顯示浮點數。
  • :.3f:保留三位小數。

c. 字符串格式化

std::string result = std::format("字符串: {}", "Hello, World!");
// result 的值為 "字符串: Hello, World!"

字符串的格式化相對簡單,直接使用{}即可。

3. 自定義格式

std::format允許通過自定義格式說明符來實現更復雜的格式化需求。

a. 對齊和填充

std::string result = std::format("左對齊: {:<10}, 右對齊: {:>10}, 居中對齊: {:^10}", "a", "b", "c");
// result 的值為 "左對齊: a         , 右對齊:         b, 居中對齊:    c    "
  • :<10:左對齊,總寬度為10個字符,不足部分用空格填充。
  • :>10:右對齊,總寬度為10個字符,不足部分用空格填充。
  • :^10:居中對齊,總寬度為10個字符,不足部分用空格填充。

b. 自定義填充字符

std::string result = std::format("左對齊: {:*<10}, 右對齊: {:*>10}, 居中對齊: {:*^10}", "a", "b", "c");
// result 的值為 "左對齊: a*********, 右對齊: *********b, 居中對齊: **c*******"

通過在格式說明符中添加填充字符(如*),可以自定義填充方式。

4. 格式化日期和時間

std::format可以與std::chrono庫結合使用,實現日期和時間的格式化。

#include <format>
#include <chrono>
#include <string>int main() {auto now = std::chrono::system_clock::now();std::string time_str = std::format("{:%Y-%m-%d %H:%M:%S}", now);// time_str 的值為類似 "2023-10-05 14:23:45" 的字符串return 0;
}
  • %Y:四位年份。
  • %m:兩位月份。
  • %d:兩位日期。
  • %H:兩位小時(24小時制)。
  • %M:兩位分鐘。
  • %S:兩位秒。

5. 其他功能

a. 格式化布爾值

std::format可以格式化布爾值為truefalse

std::string result = std::format("布爾值: {}", true);
// result 的值為 "布爾值: true"

b. 格式化指針

std::format可以格式化指針為十六進制地址。

int value = 42;
std::string result = std::format("指針地址: {:p}", &value);
// result 的值為類似 "指針地址: 0x7ffeeb0b6c3c" 的字符串

c. 格式化枚舉

std::format可以格式化枚舉為整數或字符串(需要自定義格式化器)。

enum class Color { Red, Green, Blue };std::string result = std::format("{:d}", Color::Red);
// result 的值為 "0"

四、替代方案

如果你的編譯器暫時不支持C++20的std::format,可以考慮使用第三方庫,如fmt庫,它提供了類似的功能,并且已經被廣泛使用。

#include <fmt/core.h>
#include <string>int main() {std::string result = fmt::format("Hello, {}!", "World");// result 的值為 "Hello, World!"return 0;
}

五、總結

C++20的std::format是一個非常強大的工具,能夠方便地進行字符串格式化。它支持多種數據類型和格式說明符,并且可以與std::chrono等庫結合使用,實現復雜的格式化需求。如果你的項目支持C++20,那么std::format是一個值得嘗試的工具。希望本文能夠幫助你更好地理解和使用C++20的std::format

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

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

相關文章

【漏洞復現】CVE-2025-8088|WinRAR 路徑穿越漏洞:從原理到藍屏攻擊全流程

【漏洞復現】CVE-2025-8088&#xff5c;WinRAR 路徑穿越漏洞&#xff1a;從原理到藍屏攻擊全流程 前言 WinRAR 作為 Windows 平臺最常用的壓縮管理工具之一&#xff0c;幾乎是每臺電腦的 “標配軟件”。但在 2025 年 8 月&#xff0c;一款影響范圍覆蓋 WinRAR 0 至 7.12 全版本…

uniapp中使用echarts并且支持pc端的拖動、拖拽和其他交互事件

npm install echarts -D ? // "echarts": "^5.3.2", [推薦版本] // "zrender": "^5.3.2" [如果報錯的話就安裝這個]<template><view class"container"><view id"myChart" class"chart"…

Qt中QProxyStyledrawControl函數4個參數的意義

Qt中QProxyStyle::drawControl函數4個參數的意義 我們來詳細解釋一下 Qt 中 QProxyStyle::drawControl 函數的四個參數。 這個函數是 Qt 樣式系統中的一個核心方法&#xff0c;用于繪制標準 UI 元素&#xff08;如按鈕、復選框、菜單欄等&#xff09;。當你繼承 QProxyStyle 并…

idf-esp32 PWM呼吸燈(LEDC頭文件)

相關宏和變量#define LED_PIN GPIO_NUM_3 #define LEDC_CHANNEL LEDC_CHANNEL_0 #define LEDC_TIMER LEDC_TIMER_0 #define LEDC_MODE LEDC_LOW_SPEED_MODE #define LEDC_DUTY_RES LEDC_TIMER_13_BIT // 2^13 8192級亮度 #define LEDC_FREQUENCY 50…

PLC_博圖系列?基本指令”S_ODTS:分配保持型接通延時定時器參數并啟動“

PLC_博圖系列?基本指令”S_ODTS&#xff1a;分配保持型接通延時定時器參數并啟動“ 文章目錄PLC_博圖系列?基本指令”S_ODTS&#xff1a;分配保持型接通延時定時器參數并啟動“背景介紹S_ODTS&#xff1a; 分配保持型接通延時定時器參數并啟動說明參數脈沖時序圖示例關鍵字&a…

OneCode 可視化揭秘系列(三):AI MCP驅動的智能工作流邏輯編排

OneCode 可視化揭秘系列&#xff08;三&#xff09;&#xff1a;AI MCP驅動的智能工作流邏輯編排 引言 在前兩篇系列博文中&#xff0c;我們詳細探討了OneCode可視化動作的基礎配置與界面設計&#xff0c;以及組件交互與數據流管理。在本篇文章中&#xff0c;我們將深入剖析邏輯…

TypeORM、Sequelize、Hibernate 的優缺點對比:新手常見 SQL 與 ORM 踩坑總結

1. ORM 與關系型數據庫&#xff08;MySQL、PostgreSQL&#xff09; 的使用 SQL 語句編寫&#xff08;JOIN、GROUP BY、索引使用、事務控制&#xff09;與 ORM 映射&#xff08;如 Sequelize、TypeORM、Hibernate&#xff09;之間的差異會讓新手非常糾結&#xff1b;尤其是理解…

JavaScript 創建型設計模式詳解

1. 單例模式1.1. 使用場景在前端開發中&#xff0c;全局狀態管理、配置信息、數據庫連接等往往需要在應用中只存在一個實例&#xff0c;避免多次實例化帶來的數據不一致性。例如&#xff0c;在一個前端應用中&#xff0c;全局的 loading 狀態通常需要一個單例模式來確保其唯一性…

k8s除了主server服務器可正常使用kubectl命令,其他節點不能使用原因,以及如何在其他k8s節點正常使用kubectl命令??

kubectl 并不是“只能”在主節點&#xff08;Control Plane Node&#xff09;使用&#xff0c;而是因為它需要訪問 Kubernetes 的 kube-apiserver&#xff0c;而 kube-apiserver 通常只在主節點上運行并監聽內部網絡。簡單來說kubectl 需要連接 kube-apiserver&#xff01;&…

Custom SRP - Complex Maps

https://catlikecoding.com/unity/tutorials/custom-srp/complex-maps/1 創建材質球我們的材質已經支持光照,并且支持 Albedo 和 Emission 貼圖.創建材質球,并應用下面的電路板的圖分別作為 albedo emission設置材質球的金屬度為 1 , 光滑度為 0.952 Mask Map在 albedo 圖上的不…

repo 學習教程

你現在會用 git 了&#xff0c;接下來學 repo&#xff08;Google 推出來的多倉庫管理工具&#xff09;&#xff0c;其實就是在 Git 的基礎上做了一層封裝&#xff0c;方便同時管理很多 Git 倉庫。像 Android 源碼、Rockchip 全套 SDK 都是靠 repo 來拉取和管理的。 我給你分幾個…

[SWERC 2020] Safe Distance題解

[SWERC 2020] Safe Distance 題意 給定 NNN 個點與一個坐標 (X,Y)(X,Y)(X,Y)&#xff0c;求從點 (0,0)(0,0)(0,0) 到點 (X,Y)(X,Y)(X,Y) 規劃一條路線&#xff0c;不能走出 (0,0)(0,0)(0,0) 與 (X,Y)(X,Y)(X,Y) 間形成的矩形&#xff0c;使得通過這條路線時距離最近的點的距離…

Rewind-你人生的搜索引擎

本文轉載自&#xff1a;Rewind-你人生的搜索引擎 - Hello123工具導航 ** 一、&#x1f50d; Rewind 是什么&#xff1f;你的數字記憶增強神器 Rewind 是一款人工智能驅動的個人記憶助手&#xff0c;就像為你配備了一個「數字第二大腦」。它能自動記錄、保存并索引你在電腦和手…

開發小點 - 存

開發小點 1.Req注解 EqualsAndHashCode(callSuper true) Data public class BillSituationReq extends BillQueryReq {/*** Whether to display the ring ratio, default is not displayed*/ApiModelProperty("Whether to Display YoY Comparison")private Boolean …

只會npm install?這5個隱藏技巧讓你效率翻倍!

原文鏈接&#xff1a;https://mp.weixin.qq.com/s/nijxVWj-E5U08DX2fl3vgg最近有個剛學前端的小伙伴問我&#xff1a;“為什么我的node_modules這么大&#xff1f;為什么別人裝依賴那么快&#xff1f;npx到底是啥玩意兒&#xff1f;” 相信不少人都跟他一樣&#xff0c;對npm的…

(二).net面試(static)

文章目錄項目地址一、基礎501.1 new keyword1.2 static class vs. static method1. static class2. static method3. static constructor 靜態構造函數4. 靜態成員的生命周期1.3 LinQ1.what is LinQ2. List<T>、IEnumerable<T>、IQueryable<T>3. 在數據庫里用…

docker,本地目錄掛載

理解Docker本地目錄掛載的基本概念Docker本地目錄掛載允許容器與宿主機共享文件或目錄&#xff0c;實現數據持久化和實時交互。掛載方式分為bind mount和volume兩種&#xff0c;前者直接映射宿主機路徑&#xff0c;后者由Docker管理存儲路徑。本地目錄掛載的核心方法bind mount…

IO多路復用相關知識

select、poll、epoll 在傳入的性能差異是不是體現在&#xff0c;當有新的連接過來&#xff0c;此時需要將新的fd傳入到內核中&#xff0c;但是poll/select需要出入整個數組&#xff0c;而epoll方式只需要出入單個fd&#xff1f; 1. select/poll 的情況它們沒有內核中“長期保存…

【CF】Day139——雜題 (絕對值變換 | 異或 + 二分 | 隨機數據 + 圖論)

B. Meeting on the Line題目&#xff1a;思路&#xff1a;數形結合首先考慮如果沒有 t 的影響該怎么寫顯然我們就是讓最大時間最小化&#xff0c;那么顯然選擇最左端點和最右端點的中間值即可&#xff0c;即 (mi mx) / 2&#xff0c;那么現在有了 t 該怎么辦我們不妨考慮拆開絕…

在 Ubuntu 上安裝和配置 PostgreSQL 實錄

一、查看ubuntu版本 lsb_release -a postgresq盡量安裝在新的穩定版本的ubuntu上 二、安裝postgresql 2.1 直接安裝 sudo apt install postgresql 結果如下 2.2 使用PPA源安裝 Ubuntu官方源提供了PostgreSQL的PPA(Personal Package Archive),通過PPA源安裝可以確保獲取…