!!版權聲明:本文為博主原創文章,版權歸原文作者和博客園共有,謝絕任何形式的 轉載!!
作者:mohist
fmt 源碼: https://github.com/fmtlib/fmt
fmt官方文檔: https://fmt.dev/latest/index.html#compact-binary-code
本文源自對官方文檔的理解。
本文使用 fmt version: 7.0.1
-----------------> <---------------------
1、准備:
A、下載源碼,使用cmake配置生成VS解決方案
B、編譯成功的動態庫fmt 文件: .dll + .lib
2、使用
這里演示,創建了一個空的項目,添加了一個main.cpp文件,文件內容如下:
添加fmt頭文件:
#include "3rd_part/fmt/core.h"
鏈接lib文件
#pragma comment(lib, "lib/fmtd.lib")
3、示例
A、fmt::format 返回一個字符串
auto str = fmt::format("1、{0} = {1}\n\n", "1+1", 2);
B、使用 fmt::memory_buffer 可以避免構造使用string
fmt::memory_buffer out; format_to(out, "2、For a moment, {} happened.\n\n", "nothing"); // 這里輸出的也是一個char字符串
fmt::print(out.data());
注意,使用 fmt::memory_buffer 需要額外包含頭文件:
// 使用 memory_buffer 包含的頭文件
#include "3rd_part/fmt/format.h"
C、fmt::print輸出結果
auto err_no = 1; fmt::print(stderr, "3、System error code = {}\n\n", err_no); fmt::print("3、Don't {}\n\n", "panic");
D、 Format API也支持設置位置索引(格式化)
fmt::print("4、I'd rather be {1} than {0}.\n\n", "right", "happy");
E、可以使用fmt::arg指定替換參數的值, 這樣就可以很清晰的知道每個參數的值
fmt::print("5、Hello, {name}! The answer is {number}. Goodbye, {name}.\n\n", fmt::arg("name", "World"), fmt::arg("number", 99) );
F、若編譯器支持c++ 11用戶自定義的文本, 后綴 _a提供了一種可以選。 更加簡明的語法示例如下:
fmt::print("6、Hello, {name}! The answer is {number}. Goodbye, {name}.\n\n", "name"_a = "World", "number"_a = 42);
3、其他
fmt的類型是安全的。 自動內存管理避免了內存泄漏的情況,使用 異常捕獲 或者在編譯時提示格式化字符串中的錯誤。例如:
fmt::format("The answer is {:d}", "forty-two");上面的代碼將會拋出異常: format_error 。 format_error的內容:未知的格式字符格式‘d’
因為 "forty-two" 是一個字符串, 而 格式化字符串中‘d’僅僅表示接收的是一個整數。
下面的代碼 在編譯的時候會拋出一個錯誤,原因和上面是一樣的,
format(FMT_STRING("The answer is {:d}"), "forty-two");
4、寬字符的格式化
下面的代碼, 當編譯時,也會拋出一個錯誤, 因為 寬字符 L'\x42e'無法格式為一個普通字符串。
fmt::format("Cyrillic letter {}", L'\x42e');
若需要使用寬字符, 可以使用下面的方法,格式化得到一個寬字符的字符串。 注意:格式化 字符串中多了一個 【L】
fmt::format(L"Cyrillic letter {}", L'\x42e');
----------------------------------------------------------------------------------------------
main.cpp的完整源碼如下:
#include "3rd_part/fmt/core.h"
// ------------------------------------------------------------------------------- // 使用 memory_buffer 包含的頭文件
#include "3rd_part/fmt/format.h" #include <string> #include <iostream>
// _a前綴必須引用的命名空間
using namespace fmt::literals; #pragma comment(lib, "lib/fmtd.lib")
int main(int argc, char * argv[]) { // 1、fmt::format 返回一個字符串
auto str = fmt::format("1、{0} = {1}\n\n", "1+1", 2); std::cout << str << std::endl; // 2、使用 fmt::memory_buffer 可以避免構造使用string
fmt::memory_buffer out; format_to(out, "2、For a moment, {} happened.\n\n", "nothing"); // 這里輸出的也是一個char字符串
fmt::print(out.data()); // 3、fmt::print輸出結果
auto err_no = 1; fmt::print(stderr, "3、System error code = {}\n\n", err_no); fmt::print("3、Don't {}\n\n", "panic"); // 4、Format API也支持設置位置索引(格式化)
fmt::print("4、I'd rather be {1} than {0}.\n\n", "right", "happy"); // 5、可以使用fmt::arg指定替換參數的值, 這樣就可以很清晰的知道每個參數的值
fmt::print("5、Hello, {name}! The answer is {number}. Goodbye, {name}.\n\n", fmt::arg("name", "World"), fmt::arg("number", 99) ); // 6、若編譯器支持c++ 11用戶自定義的文本, 后綴 _a提供了一種可以選。 更加簡明的語法示例如下:
fmt::print("6、Hello, {name}! The answer is {number}. Goodbye, {name}.\n\n", "name"_a = "World", "number"_a = 42); // ------------------------------------------------------------------------------- // 7、fmt的類型是安全的。 自動內存管理避免了內存泄漏的情況,使用 異常捕獲 或者在編譯時提示格式化字符串中的錯誤。例如: // fmt::format("The answer is {:d}", "forty-two"); // 上面的代碼將會拋出異常: format_error 。 format_error的內容:未知的格式字符格式‘d’ // 因為 "forty-two" 是一個字符串, 而 格式化字符串中‘d’僅僅表示接收的是一個整數。 // 下面的代碼 在編譯的時候會拋出一個錯誤,原因和上面是一樣的, // format(FMT_STRING("The answer is {:d}"), "forty-two"); // ------------------------------------------------------------------------------- // 8、下面的代碼, 當編譯時,也會拋出一個錯誤, 因為 寬字符 L'\x42e'無法格式為一個普通字符串。 // fmt::format("Cyrillic letter {}", L'\x42e'); // 若需要使用寬字符, 可以使用下面的方法,格式化得到一個寬字符的字符串。 注意:格式化 字符串中多了一個 【L】
fmt::format(L"Cyrillic letter {}", L'\x42e'); system("pause"); return 0; }
編譯輸出結果:
:D 完。
繼續閱讀文檔與源碼