!!版權聲明:本文為博主原創文章,版權歸原文作者和博客園共有,謝絕任何形式的 轉載!!
作者:mohist
fmt
- fmt 源碼: https://github.com/fmtlib/fmt
- 本文翻譯:https://fmt.dev/latest/syntax.html
- fmt版本:7.0.1
- 本文僅為參考,請以官方文檔為准。
- 水平有限,歡迎指正。有興趣,參閱 官方文檔。
- 本文僅為參考,請以 實際情況 為准。
正文
本文將介紹 fmt::format()和fmt::print()之類的格式化函數使用
A、格式化字符串有占位符,用大括號 {}表示占位,格式化字符串放在{}中間。沒有放在{}之間的字符串被視為字符串輸出。 如果需要輸出的字符串中有大括號{},可以額外增加一個大括號來實現。例如:{ { 和 } }
B、占位符語法如下:
replacement_field :: = "{"[arg_id][":" format_spec] "}"
arg_id :: = integer | identifier
integer :: = digit +
digit :: = "0"..."9"
identifier :: = id_start id_continue*
id_start :: = "a"..."z" | "A"..."Z" | "_"
id_continue :: = id_start | digit
1、替換字段可用以 arg_id 開頭,該參數指定要格式化其值並將其插入輸出的參數,而不是替換字段。可選的arg_id放在format_spec的后面,其后是冒號':'。這些指定替換值的非默認格式。
2、如果格式字符串中的數字arg_ids依次為0、1、2,...,則可以全部省略(不只是某些數字),數字0、1、2,...將按此順序自動插入。
3、命名參數可以通過其名稱或索引來引用。例如:
"First, thou shalt count to {0}" // 替換第一個參數
"Bring me a {}" // 隱式引用第一個參數
"From {} to {}" // 這行代碼和 "From {0} to {1}"功效相同
4、format_spec 字段包含有關如何顯示值的規范,包括字段寬度,對齊方式,填充,小數精度等詳細信息。每種值類型都可以定義自己的“formatting mini - language”或對format_spec的解釋。
5、大多數內置類型都支持通用的formatting mini - language,這將在下一節中進行介紹。
6、format_spec字段還可以在其中的某些位置包含嵌套的替換字段。這些嵌套的替換字段只能包含一個參數id。格式規格是不允許的。這將允許動態指定值的格式。
C、Mini - Language的格式規范
1、在格式字符串中包含的替換字段中使用“格式規范”來定義如何顯示單個值。每種格式表類型可以定義如何解釋格式規范。
2、 盡管某些格式化選項僅受數字類型支持,但大多數內置類型都為格式規范實現了以下選項。
3、標准格式說明符的一般形式為:
format_spec :: = [[fill]align][sign]["#"]["0"][width]["." precision][type]
fill :: = <a character other than '{' or '}'>
align :: = "<" | ">" | "^"
sign :: = "+" | "-" | " "
width :: = integer | "{"[arg_id] "}"
precision :: = integer | "{"[arg_id] "}"
type :: = int_type | "a" | "A" | "c" | "e" | "E" | "f" | "F" | "g" | "G" | "L" | "p" | "s"
int_type :: = "b" | "B" | "d" | "o" | "x" | "X"
4、填充字符可以是'{'或'}'以外的任何Unicode代碼點。填充字符的存在由其后的字符表示,該字符必須是對齊選項之一。如果format_spec的第二個字符不是有效的對齊選項,則假定填充字符和對齊選項都不存在。
5、各種對齊選項的含義如下:
Option Meaning
'<' 強制字段在可用空間內左對齊((大多數對象的默認設置).
'>' 強制字段在可用空間內右對齊(這是數字的默認設置).
'^' 強制字段在可用空間內居中.
6、請注意,除非定義了最小字段寬度,否則字段寬度將始終與填充它的數據大小相同。因此在這種情況下,對齊選項沒有任何意義。
7、符號選項僅對數字類型有效,並且可以是以下之一:
Option Meaning
'+' 表示正負數均應使用符號,例如: + 5, - 2。
'-' 表示符號只能用於負數(負數默認設置顯示)。
space 表示應在正數上使用前導空格,在負數上使用減號。
8、“#”選項使“替代形式”用於轉換。替代形式對於不同類型的定義不同。此選項僅對整數和浮點類型有效。對於整數,使用二進制,八進制或十六進制輸出時,此選項將前綴“ 0b”(“ 0B”),“ 0”或“ 0x”(“ 0X”)添加到輸出值。前綴是小寫還是大寫取決於類型說明符的大小寫,例如,前綴“ 0x”用於類型“ x”,“ 0X”用於“ X”。對於浮點數,替代格式會導致轉換結果始終包含小數點字符,即使后面沒有數字也是如此。通常,只有在數字后面跟隨小數點字符,這些轉換的結果才會出現。另外,對於“ g”和“ G”轉換,不會從結果中刪除部零。
9、width是定義最小字段寬度的十進制整數。如果未指定,則字段寬度將由內容確定。
10、在寬度字段前面加上零('0'),字符可啟用數字類型的符號識別0填充.它強制將填充內容放置在符號或基數(如果有)之后但在數字之前。這用於以“ + 000000120”形式打印字段。此選項僅對數字類型有效,並且對無窮大和NaN的格式無效。
11、precision是一個十進制數字,表示以'f'和'F'格式設置的浮點值在小數點后應顯示多少位數,用'g'或'G'格式化的浮點值小數點前后。對於非數字類型,該字段指示最大字段大小,換句話說,字段內容中將使用多少個字符。整數,字符,布爾值和指針值不允許使用精度。
12、type字段決定了應如何顯示數據。
13、可用的字符串表示類型為:
Type Meaning
's' 字符串格式。字符串的默認類型,可以省略
none 與's'相同
14、可用的字符顯示類型為:
Type Meaning
'c' 字符格式。字符的默認類型,可以省略。
none 與'c'相同
15、可用的整數表示類型為:
Type | Meaning |
---|---|
'b' | 二進制格式。輸出以2為進制的數字。在此類型中使用'#'選項,會將前綴“ 0b”添加到輸出值中。value. |
'B' | 二進制格式。輸出以2為進制的數字。對此類型使用'#'選項,可在輸出值中添加前綴“ 0B”。 |
'd' | 十進制整數。輸出以10為進制的數字。 |
'0' | 八進制格式。輸出以8為進制的數字。 |
'x' | 十六進制格式。輸出以16為進制的數字,對9以上的數字使用小寫字母。將'#'選項與該類型一起使用時,會將前綴“ 0x”添加到輸出值中。 |
'X' | 十六進制格式。輸出以16為進制的數字,對9以上的數字使用大寫字母。將'#'選項與該類型一起使用時,會將前綴“ 0X”添加到輸出值中。 |
'L' | 特定於語言環境的格式。這與'd'相同,除了它使用當前的語言環境設置來插入適當的數字分隔符。 |
none | 與 'd' 相同 |
16、整數表示類型也可以與字符和布爾值一起使用。如果未指定輸出類型,布爾值使用文本表示形式設置為true或false,
17、浮點值的可用顯示類型為:
Type Meaning
'a' 十六進制浮點格式。打印以16為底的數字,前綴為“ 0x”,小寫字母表示9以上的數字。使用'p'表示指數。
'A' 與 'a' 相同,不同之處在於它使用大寫字母作為前綴,數字大於9並表示指數。
'e' 指數表示法。使用字母“ e”以科學計數法打印數字以表示指數。
'E' 指數表示法。與'e'相同,除了它使用大寫字母'E'作為分隔符。
'f' 固定點。將數字顯示為定點數字。
'F' 固定點。與'f'相同,但是將nan轉換為NAN,將inf轉換為INF。
'g' 通用格式。對於給定的精度p > = 1,這會將數字四舍五入為p個有效數字,然后根據結果的大小以定點格式或科學計數法格式化結果。精度0等同於精度1。
'G' 通用格式。與“ g”相同,但如果數字太大則切換到 'E'。無限大和NaN的表示也都是大寫的。
'L' 特定於語言環境的格式。這與'g'相同,只是它使用當前的語言環境設置來插入適當的數字分隔符。
none 與“'g'相似,不同之處在於定點表示法在使用時,其小數點后至少有一位數字。默認精度與表示特定值所需的精度一樣高。
18、指針的可用顯示類型為:
Type Meaning
'p' 指針格式。這是指針的默認類型,可以省略。
none 與 'p'相同
D、格式范例
本節包含格式語法的示例以及與printf格式的比較。
1、大多數情況下,語法類似於printf格式,加上{} 和 :代替%。例如,“%03.2f”可以轉換為“{ :03.2f }”。
2、新格式的語法還支持新的和不同的選項,如以下示例所示。
2.1、按位置訪問參數:
fmt::format("{0}, {1}, {2}", 'a', 'b', 'c');
// Result: "a, b, c"
fmt::format("{}, {}, {}", 'a', 'b', 'c');
// Result: "a, b, c"
fmt::format("{2}, {1}, {0}", 'a', 'b', 'c');
// Result: "c, b, a"
fmt::format("{0}{1}{0}", "abra", "cad");
// Result: "abracadabra"
2.2、對齊文本並指定寬度:
fmt::format("{:<30}", "left aligned");
// Result: "left aligned "
fmt::format("{:>30}", "right aligned");
// Result: " right aligned"
fmt::format("{:^30}", "centered");
// Result: " centered "
fmt::format("{:*^30}", "centered"); // use '*' as a fill char
// Result: "***********centered***********"
2.3、動態寬度:
fmt::format("{:<{}}", "left aligned", 30);
// Result: "left aligned
2.4、動態精度:
fmt::format("{:.{}f}", 3.14, 1);
// Result: "3.1"
2.5、% + f,% - f和%f並指定符號:
fmt::format("{:+f}; {:+f}", 3.14, -3.14); // show it always
// Result: "+3.140000; -3.140000"
fmt::format("{: f}; {: f}", 3.14, -3.14); // show a space for positive numbers
// Result: " 3.140000; -3.140000"
fmt::format("{:-f}; {:-f}", 3.14, -3.14); // show only the minus -- same as '{:f}; {:f}'
// Result: "3.140000; -3.140000"
2.6、%x和%o並將值轉換為不同的進制:
fmt::format("int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}", 42);
// Result: "int: 42; hex: 2a; oct: 52; bin: 101010"
// with 0x or 0 or 0b as prefix:
fmt::format("int: {0:d}; hex: {0:#x}; oct: {0:#o}; bin: {0:#b}", 42);
// Result: "int: 42; hex: 0x2a; oct: 052; bin: 0b101010"
2.7、用前綴填充十六進制字節,並始終打印兩個十六進制字符:
fmt::format("{:#04x}", 0);
// Result: "0x00"
2.8、使用Unicode填充的方框圖:
fmt::print(
"┌{0:─^{2}}┐\n"
"│{1: ^{2}}│\n"
"└{0:─^{2}}┘\n", "", "Hello, world!", 20);
輸出結果:
┌────────────────────┐
│ Hello, world!│
└────────────────────┘
2.9、使用特定於類型的格式:
#include <fmt/chrono.h>
auto t = tm();
t.tm_year = 2010 - 1900;
t.tm_mon = 6;
t.tm_mday = 4;
t.tm_hour = 12;
t.tm_min = 15;
t.tm_sec = 58;
fmt::print("{:%Y-%m-%d %H:%M:%S}", t);
// Prints: 2010-08-04 12:15:58
2.10、使用逗號作為千位分隔符:
#include <fmt/locale.h>
auto s = fmt::format(std::locale("en_US.UTF-8"), "{:L}", 1234567890);
// s == "1,234,567,890"
------------完------------ -
可見fmt的強大之處,類比python的格式化。 c++傳統的格式化也該掃進歷史的垃圾桶了。
還等什么,趕緊試試吧。