guía de uso de la biblioteca c++ {fmt} 1

1. Origen

Era tarde en la noche y la manecilla de la hora marcaba silenciosamente las once y media, pero mis pensamientos surgían como un resorte y no podía dormir en absoluto. En ese momento, estaba ansioso por hacer algo significativo y decidí aprovechar esta tranquilidad para calmarme y escribir una guía sobre el uso de la biblioteca fmt.
La biblioteca fmt es una biblioteca de formato C ++ eficiente y fácil de usar que puede ayudarnos a realizar cómodamente el formateo de cadenas, la salida, el registro y otras operaciones. En esta guía, presentaré el uso básico de la biblioteca fmt, la sintaxis de cadenas formateadas, el mecanismo de manejo de excepciones, etc., con la esperanza de ayudar a todos. ¡Empecemos!

2. Uso básico

Instalar la biblioteca fmt

github: https://github.com/fmtlib/fmt
guía de API: https://fmt.dev/latest/api.html

Introducir la biblioteca fmt en el proyecto.
  1. El método antiguo cmake (no recomendado)
    mkdir build
    cd build
    cmake...
    crea o usa IDE para abrir el archivo de proyecto generado para generar la biblioteca estática correspondiente\
  2. Incluya solo archivos de encabezado (se recomienda #definir FMT_HEADER_ONLY antes de incluir archivos de encabezado)
    • fmt/core.h: la función de formato principal de char/UTF-8, admite la verificación en tiempo de compilación de C++20 y minimiza las dependencias.
    • fmt/format.h: API de formato completa, además de funciones de formato adicionales, admite localización (soporte en varios idiomas).
    • fmt/ranges.h: Formatear rangos y tuplas
    • fmt/chrono.h: formato de fecha y hora.
    • fmt/std.h: soporte de formato para tipos de biblioteca estándar de C++.
    • fmt/compile.h: compilación de cadenas de formato (detección de cadenas de formato en tiempo de compilación). FMT_STRING(es)
    • fmt/color.h: color de terminal y estilo de texto.
    • fmt/os.h: proporciona la API del sistema.
    • fmt/ostream.h: Soporte std::ostream.
    • fmt/printf.h: admite el formato printf.
    • fmt/xchar.h: soporte opcional para wchar_t.

Hola Mundo

    #define FMT_HEADER_ONLY 
    #include "fmt/core.h"
    #include <string>
    int main()
    {
    
    
        // {} 占位符,可以占位int float double ....
        std::string world = fmt::format("Hello {}", "World");
        fmt::print("{}", world);
    }

3. Sintaxis de formato de caracteres

Las funciones de formato como fmt::format() y fmt::print() usan la misma sintaxis, que es un "campo de reemplazo" rodeado por {}.
Todo lo que no esté entre llaves se trata como texto literal y se copiará en la salida sin modificaciones. Si necesita incluir un carácter de llave en un texto literal, puede escaparlo repitiendo la llave: { { y }}.
En la mayoría de los casos, la sintaxis es similar al formato printf, pero se agrega {} y se usa : en lugar de %. Por ejemplo, "%03.2f" se puede convertir a "{:03.2f}", simplemente reemplazando % con {}, pero fmt es más potente. El
formato de salida es el siguiente:
replacement_field ::= "{" [arg_id] [":" (format_spec | crono_format_spec)] “}” // Carácter de reemplazo = {[parameter id]:[format_spec] | [chrono_format_spec]} arg_id ::=
entero | identificador // Entero 0-9 az AZ, lo siguiente indica cuál significa qué
entero ::= dígito+
dígito ::= “0”…“9”
identificador ::= id_start id_continue*
id_start ::= “a”…“z” | “A”…“Z” | “_ ”
id_continue ::= id_start | dígito\

El formato de reemplazo utiliza ":" como delimitador. El que está antes de ":" representa la identificación del parámetro, que se refiere al orden de los parámetros. Puede ser 1, 2, 3, 4,... o puede ser un , b, c... después de ":" es un formato definido específicamente para tipos de tiempo numéricos (entero, punto flotante). [] representa opcional, | representa o, solo puede existir uno

3.1 La identificación del parámetro está antes de ":"

    // 只有参数id时候,: 可以省略不写
    fmt::print("name:{1}, age: {0:}", 42, "knox");

3.2format_spec después de ":" (Minilenguaje de especificación de formato de minilenguaje)

  1. Formato_spec ::= [[relleno]alinear][signo][“#”][ “
    0”][ancho][“.” precisión][“L”][tipo]
    relleno ::= <un carácter distinto de '{' o '}'>
    align ::= “<” | “>” | Signo “^”
    ::= “+” | “-” | " "
    ancho ::= entero | “{” [arg_id] “}”
    precisión ::= entero | “{” [arg_id] “}”
    tipo ::= “a” | “A” | “b” | “B” | “c” | “d” | “mi” | “E” | “f” | “F” | “g” | “G” |
    “o” | “pag” | “s” | “x” | "X"\

  2. El archivo representa el carácter de relleno, que puede ser cualquier punto de código Unicode excepto "{" y "}". La presencia de un carácter de pad está indicada por el carácter que le sigue, que debe ser una de las opciones de alineación. Si el segundo carácter de format_spec no es una opción de alineación válida (<, >, ^), se supone que no están presentes ni los caracteres de relleno ni las opciones de alineación.

  3. align representa alineación, < representa alineación izquierda, > representa alineación derecha, ^ representa centrado

  4. El signo es solo para números, "+" significa que tanto los números positivos como los negativos usan signos. "-" significa que sólo los números negativos requieren un signo (este es el comportamiento predeterminado). Un espacio significa que se debe agregar un espacio antes de un número positivo y un signo menos antes de un número negativo.

  5. Esta opción sólo está disponible para tipos de punto flotante y entero. Para números enteros, cuando se utiliza salida binaria, octal o hexadecimal, esta opción agrega el prefijo apropiado "0b" ("0B"), "0" o "0x" ("0X") al valor de salida. El formato de caracteres en minúsculas está en minúsculas, como {:#0X}, 255 = 0XFF, , {:#0x}, 255 = 0xff, otras bases son similares,

  6. ancho es un entero decimal, solo aplicable a tipos numéricos, utilizado para definir el ancho mínimo del campo. Si no se especifica, el ancho del campo estará determinado por el contenido. Preceder el campo de ancho con un carácter cero ("0") habilita el relleno de ceros con reconocimiento de signos para tipos numéricos.
    Obliga a que el relleno se coloque después del signo o la base (si corresponde) pero antes del número. Esto se utiliza para imprimir el campo en el formulario "+000000120".

  7. "." La precisión representa la precisión. La precisión solo existe en tipos de punto flotante. Los números enteros, caracteres, valores booleanos y de puntero no pueden usar precisión. Para tipos no numéricos, el campo indica el tamaño máximo de campo, incluso si se especifica el tamaño. Las cadenas C deben terminar con un carácter nulo.
    El precision.nf general, no el precision.nn, representa varios formatos que deben formatearse.

    // 非数字指定的是输出的字符的个数。
    fmt::print("name:{1}, age: {0:.5}", "1234567890", "knox");
    // 输出:name:knox, age: 12345
    
    // c字符串不够怎么办呢,最大字符串长
    fmt::print("name:{1}, age: {0:.5}", "123", "knox");
    // 输出:name:knox, age: 123
    
    // 对于数字代表精度,只对浮点型有用
    fmt::print("{:.2f}", 42.0f);
    // 输出:42.00
    //fmt::print("{:.2f}", 42); 编译报错
    //fmt::print("{:.2f}", true); 编译报错

  1. La opción "L" utiliza la configuración regional actual para insertar separadores de números apropiados. Esta opción sólo está disponible para tipos numéricos.
    auto s = fmt::format(std::locale("en_US.UTF-8"), "{:L}", 1234567890);
    fmt::print("{}", s);
    // 输出: 1,234,567,890
  1. escriba
    la notación exponencial 'e'. La notación de índice utiliza la letra minúscula 'e'.
    Notación de índice 'E'. La notación de índice utiliza una letra mayúscula 'E'.
    Notación de punto fijo 'f'. Muestra números como números de punto fijo.
    Notación de punto fijo 'F'. Muestra números como números de punto fijo. Lo mismo que 'f'.
    formato general 'g'. Dependiendo del tamaño del número y de la precisión especificada, se utiliza notación de punto fijo o exponencial.
    Formato general 'G'. Igual que 'g', pero usa una 'E' mayúscula para la notación de índice.
    'x' entero hexadecimal. Muestra números como números hexadecimales.
    'X' entero hexadecimal. Muestra los números como números hexadecimales en mayúsculas.
    'un' número de coma flotante hexadecimal. Utilice 'a' minúscula para la notación de índice.
    'Un' número de coma flotante hexadecimal. Utilice la letra 'A' mayúscula para la notación del índice.
    Carácter 'c'. Interpretar números enteros como caracteres Unicode.
    cadena 's'. Formatee los parámetros como cadenas.
    puntero 'p'. Formatee el puntero como número hexadecimal.

crono_format_spec formato de hora

1. Composición
crono_formato_spec ::= [[relleno]alinear][ancho][“.” precisión][chrono_specs]
crono_specs ::= [chrono_specs] conversión_spec | crono_specs literal_char
conversión_spec ::= “%” [modificador] crono_tipo
literal_char :: = <un carácter distinto de '{', '}' o '%'>\ // Excepto { } %, estos tres caracteres se pueden usar como
modificador de carácter de enlace::= “E” | “O”
crono_tipo ::= “ a" | "A" | "b" | "B" | "c" | "C" | "d" | "D" | "e" | "F" | "g" | "G" | "h
" | "H" | "I" | "j" | "m" | "M" | "n" | "p" | "q" | "Q" | "r" | "R" | "S" |
"t" | "T" | "u" | "U" | "V" | "
w" | "W" | "x" | "X" | "y" | "Y" | "z" | "Z " | "%"\

  1. [[fill]align] Similar a 3.2.1
  2. Si el número de días es inferior a 10, el número de minutos, segundos o meses se agregará con 0 delante.
    Para obtener una sintaxis más detallada de la cadena en formato fmt, vaya a https://fmt.dev/latest/syntax .html#grammar-token-sf -identificador

Ejemplo de cadena de formato

Salida en orden de arg_id, id comienza desde 0
    // 序号从零开始
    fmt::print("{0}, {1}, {2}\n", 'a', 'b', 'c');
    // print: "a, b, c"


    fmt::print("{}, {}, {}\n", 'a', 'b', 'c');
    // print: "a, b, c"

    fmt::print("{2}, {1}, {0} \n", 'a', 'b', 'c');
    // print: "c, b, a"
    // fmt::print("{2}, {1}, {0} {3}\n", 'a', 'b', 'c'); 编译报错,没有第四个参数

    // 输出
    // a, b, c  
    // a, b, c  
    // c, b, a  
Complete los espacios en blanco con caracteres personalizados y especifique el método de centrado
    // 不指定填充符号默认为空格, 如果不存在 <>^ 就假定填充符号都不存在
    fmt::print("{:<30}\n", "left aligned");
    // 
    fmt::print("{:<<30}\n", "left aligned");
                
    fmt::print("{:>30}\n", "right aligned");
    fmt::print("{:>>30}\n", "right aligned");

    fmt::print("{:^30}\n", "centered");
          
    fmt::print("{:^^30}\n", "centered"); 

    // 输出
    //left aligned                  
    //left aligned<<<<<<<<<<<<<<<<<<
    //                right aligned 
    //>>>>>>>>>>>>>>>>>right aligned
    //        centered              
    //^^^^^^^^^^^centered^^^^^^^^^^^

Establecer dinámicamente el ancho y la precisión
    // 可以动态设置宽度和精度,但仅仅限制于此,
    // 动态设置宽度的时候,宽度arg_id 为 参数+1, 
    //           0 1   2 3  参数arg_id 可以数{ 的个数,当然{} 一定是成对出现的。
    fmt::print("{:<{}} {:.{}f} \n", "left aligned", 30, 3.14, 1);
    fmt::print("{:.{}f}\n", 3.14, 1);
    // 输出
    // left aligned                   3.1  
    // 3.1  

Uso de :+ :- signo
    // + 代表正数加+号,负数加-号
    fmt::print("{:+f}; {:+f}\n", 3.14, -3.14); 
    // 空格正数加空格,负数加-号
    fmt::print("{: f}; {: f}\n", 3.14, -3.14); 
    // -号代表正数不变,负数加-号 same as '{:f}; {:f}' 相当于是默认行为
    fmt::print("{:-f}; {:-f}\n", 3.14, -3.14);

    fmt::print("{:+}; {:+}\n", 3, -3);
    fmt::print("{:-}; {:-}\n", 3, -3);
    fmt::print("{: }; {: }\n", 3, -3);
    fmt::print("{:}; {:}\n", 3, -3);

    // 输出
    //+3.140000; -3.140000
    // 3.140000; -3.140000
    //3.140000; -3.140000
    //+3; -3
    //3; -3
    // 3; -3
    //3; -3
salida hexadecimal
    // # 加上符号 0x 0 0b
    fmt::print("int: {0:d};  hex: {0:x};  oct: {0:o}; bin: {0:b}\n", 42);
    
    fmt::print("int: {0:d};  hex: {0:#x};  oct: {0:#o};  bin: {0:#b}\n", 42);

    // #06 代表宽度为6个, 不够的在进制之前使用0填充, 超出指定大小被忽略
    fmt::print("int: {0:d};  hex: {0:#06x};  oct: {0:#06o};  bin: {0:#06b}\n", 42);
    fmt::print("int: {0:d};  hex: {0:#01x};  oct: {0:#02o};  bin: {0:#03b}\n", 42);
    // 输出
    // int: 42;  hex: 2a;  oct: 52; bin: 101010
    // int: 42;  hex: 0x2a;  oct: 052;  bin: 0b101010
    // int: 42;  hex: 0x002a;  oct: 000052;  bin: 0b101010
    // int: 42;  hex: 0x2a;  oct: 052;  bin: 0b101010
Imprimir bordes usando caracteres de relleno
    fmt::print(
        "┌{0:─^{2}}┐\n"
        "│{1: ^{2}}│\n"
        "└{0:─^{2}}┘\n", "", "Hello, knox!", 20);

No puedo resistirme más, así que me detendré aquí hoy. Mañana continuaremos con el uso detallado de la API de la biblioteca fmt.

Supongo que te gusta

Origin blog.csdn.net/qq_33944628/article/details/129943438
Recomendado
Clasificación