{fmt} es una biblioteca de formato de código abierto que proporciona una alternativa rápida y segura a C stdio y C++ iostreams.
Si le gusta este proyecto, considere hacer una donación a uno de los fondos que ayudan a las víctimas de la guerra en Ucrania: https://www.stopputin.net/.
Documentación
Hojas de trucos
Preguntas y respuestas: haga preguntas en StackOverflow con la etiqueta fmt.
Pruebe {fmt} en el Explorador de compiladores.
API de formato simple con argumentos posicionales para localización
Implementación de C++20 std::format y C++23 std::print
Formato de sintaxis de cadena similar al formato de Python
Rápido formateador de punto flotante IEEE 754 con garantías de redondeo, brevedad y ida y vuelta correctos utilizando el algoritmo Dragonbox
Soporte Unicode portátil
Implementación segura de printf, incluida la extensión POSIX para argumentos posicionales
Extensibilidad: soporte para tipos definidos por el usuario
Alto rendimiento: más rápido que las implementaciones de bibliotecas estándar comunes de (s)printf
, iostreams, to_string
y to_chars
, consulte Pruebas de velocidad y Conversión de cien millones de enteros en cadenas por segundo.
Tamaño de código pequeño tanto en términos de código fuente con la configuración mínima que consta de solo tres archivos, core.h
, format.h
y format-inl.h
, como de código compilado; ver Tiempo de compilación y exceso de código
Fiabilidad: la biblioteca tiene un amplio conjunto de pruebas y se actualiza continuamente
Seguridad: la biblioteca es totalmente segura, los errores en las cadenas de formato se pueden informar en el momento de la compilación, la gestión automática de la memoria evita errores de desbordamiento del búfer
Facilidad de uso: base de código pequeña e independiente, sin dependencias externas, licencia MIT permisiva
Portabilidad con resultados consistentes en todas las plataformas y soporte para compiladores más antiguos.
Base de código limpia y sin advertencias incluso en niveles de advertencia altos como -Wall -Wextra -pedantic
Independencia local por defecto
Configuración opcional de solo encabezado habilitada con la macro FMT_HEADER_ONLY
Consulte la documentación para obtener más detalles.
Imprimir en salida estándar (ejecutar)
#include <fmt/core.h>int main() { fmt::print("¡Hola mundo!n"); }
Formatear una cadena (ejecutar)
std::string s = fmt::format("La respuesta es {}.", 42);// s == "La respuesta es 42."
Formatear una cadena usando argumentos posicionales (ejecutar)
std::string s = fmt::format("Prefiero ser {1} que {0}.", "correcto", "feliz");// s == "Prefiero ser feliz que tener razón ".
Imprimir fechas y horas (ejecutar)
#include <fmt/chrono.h>int main() { auto ahora = std::chrono::system_clock::now(); fmt::print("Fecha y hora: {}n", ahora); fmt::print("Hora: {:%H:%M}n", ahora); }
Producción:
Date and time: 2023-12-26 19:10:31.557195597 Time: 19:10
Imprimir un contenedor (ejecutar)
#include <vector>#include <fmt/ranges.h>int main() { std::vector<int> v = {1, 2, 3}; fmt::print("{}n", v); }
Producción:
[1, 2, 3]
Verificar una cadena de formato en tiempo de compilación
std::string s = fmt::format("{:d}", "No soy un número");
Esto genera un error en tiempo de compilación en C++ 20 porque d
es un especificador de formato no válido para una cadena.
Escribir un archivo desde un solo hilo
#include <fmt/os.h>int main() { salida automática = fmt::output_file("guide.txt"); out.print("No {}", "Entrar en pánico"); }
Esto puede ser de 5 a 9 veces más rápido que fprintf.
Imprime con colores y estilos de texto.
#include <fmt/color.h>int main() { fmt::print(fg(fmt::color::crimson) | fmt::emphasis::bold, "Hola, {}!n", "mundo" ); fmt::print(fg(fmt::color::floral_blanco) | bg(fmt::color::pizarra_gris) | fmt::emphasis::underline, "Olá, {}!n", "Mundo"); fmt::print(fg(fmt::color::steel_blue) | fmt::emphasis::italic, "你好{}!n", "世界"); }
Salida en una terminal moderna con soporte Unicode:
Biblioteca | Método | Tiempo de ejecución, s |
---|---|---|
libc | imprimirf | 0,91 |
libc++ | std::ostream | 2.49 |
{fmt} 9.1 | fmt::imprimir | 0,74 |
Formato de impulso 1.80 | impulso::formato | 6.26 |
Formato de locura | locura::formato | 1,87 |
{fmt} es el más rápido de los métodos evaluados, ~20% más rápido que printf
.
Los resultados anteriores se generaron compilando tinyformat_test.cpp
en macOS 12.6.1 con clang++ -O3 -DNDEBUG -DSPEED_TEST -DHAVE_FORMAT
y tomando lo mejor de tres ejecuciones. En la prueba, la cadena de formato "%0.10f:%04d:%+g:%s:%p:%c:%%n"
o equivalente se completa 2.000.000 de veces con la salida enviada a /dev/null
; para más detalles consulte la fuente.
{fmt} es hasta 20-30 veces más rápido que std::ostringstream
y sprintf
en IEEE754 float
y double
formato (dtoa-benchmark) y más rápido que doble conversión y ryu:
El script bloat-test.py de las pruebas de referencia de formato compila el tiempo y el código para proyectos no triviales. Genera 100 unidades de traducción y utiliza printf()
o su alternativa cinco veces en cada una para simular un proyecto de tamaño mediano. El tamaño del ejecutable resultante y el tiempo de compilación (Apple clang versión 15.0.0 (clang-1500.1.0.2.5), macOS Sonoma, mejor de tres) se muestran en las siguientes tablas.
Construcción optimizada (-O3)
Método | Tiempo de compilación, s | Tamaño ejecutable, KiB | Tamaño despojado, KiB |
---|---|---|---|
imprimirf | 1.6 | 54 | 50 |
IOStreams | 25,9 | 98 | 84 |
fmt 83652df | 4.8 | 54 | 50 |
formato pequeño | 29.1 | 161 | 136 |
Formato de impulso | 55.0 | 530 | 317 |
{fmt} es rápido de compilar y es comparable a printf
en términos de tamaño binario por llamada (dentro de un error de redondeo en este sistema).
Construcción no optimizada
Método | Tiempo de compilación, s | Tamaño ejecutable, KiB | Tamaño despojado, KiB |
---|---|---|---|
imprimirf | 1.4 | 54 | 50 |
IOStreams | 23.4 | 92 | 68 |
{fmt} 83652df | 4.4 | 89 | 85 |
formato pequeño | 24,5 | 204 | 161 |
Formato de impulso | 36.4 | 831 | 462 |
libc
, lib(std)c++
y libfmt
están vinculados como bibliotecas compartidas para comparar únicamente la sobrecarga de la función de formato. Boost Format es una biblioteca de solo encabezados, por lo que no proporciona ninguna opción de vinculación.
Consulte Creación de la biblioteca para obtener instrucciones sobre cómo crear la biblioteca y ejecutar las pruebas unitarias.
Los puntos de referencia residen en un repositorio separado, format-benchmarks, por lo que para ejecutar los puntos de referencia primero necesita clonar este repositorio y generar Makefiles con CMake:
$ git clone --recursive https://github.com/fmtlib/format-benchmark.git $ cd format-benchmark $ cmake .
Luego puedes ejecutar la prueba de velocidad:
$ make speed-test
o la prueba de hinchazón:
$ make bloat-test
clang-tidy v18 proporciona la verificación modernize-use-std-print que es capaz de convertir apariciones de printf
y fprintf
a fmt::print
si está configurado para hacerlo. (De forma predeterminada, se convierte a std::print
).
0 AD: un juego de estrategia en tiempo real multiplataforma, gratuito y de código abierto
AMPL/MP: una biblioteca de código abierto para programación matemática
FoundationDB de Apple: un almacén de valores clave transaccional, distribuido y de código abierto
Aseprite: editor de sprites animados y herramienta de pixel art
AvioBook: una suite integral de operaciones de aeronaves
Blizzard Battle.net: una plataforma de juegos online
Celestia: visualización 3D del espacio en tiempo real
Ceph: un sistema de almacenamiento distribuido escalable
ccache: un caché del compilador
ClickHouse: un sistema de gestión de bases de datos analíticas
ContextVision: software de imágenes médicas
Contour: un emulador de terminal moderno
CUAUV: el vehículo submarino autónomo de la Universidad de Cornell
Drake: una caja de herramientas de planificación, control y análisis para sistemas dinámicos no lineales (MIT)
Envoy: proxy C++ L7 y bus de comunicación (Lyft)
FiveM: un marco de modificación para GTA V
fmtlog: una biblioteca de registro de alto rendimiento estilo fmtlib con latencia en nanosegundos
Folly: biblioteca de código abierto de Facebook
GemRB: una implementación portátil de código abierto de Infinity Engine de Bioware
Grand Mountain Adventure: un hermoso juego de esquí y snowboard de mundo abierto
HarpyWar/pvpgn: Red de juegos jugador contra jugador con ajustes
KBEngine: un motor de servidor MMOG de código abierto
Keypirinha: un lanzador semántico para Windows
Kodi (anteriormente xbmc): software de cine en casa
Knuth: nodo completo de Bitcoin de alto rendimiento
libunicode: una biblioteca Unicode C++17 moderna
MariaDB: sistema de gestión de bases de datos relacionales
Microsoft Verona: lenguaje de programación de investigación para propiedad concurrente
MongoDB: base de datos de documentos distribuidos
MongoDB Smasher: una pequeña herramienta para generar conjuntos de datos aleatorios
OpenSpace: un marco de astrovisualización de código abierto
PenUltima Online (POL): un servidor MMO, compatible con la mayoría de los clientes de Ultima Online
PyTorch: una biblioteca de aprendizaje automático de código abierto
quasardb: una base de datos asociativa distribuida y de alto rendimiento
Quill: biblioteca de registro asíncrono de baja latencia
QKW: generalización de alias para simplificar la navegación y ejecutar secuencias complejas de comandos de terminal multilínea
redis-cerberus: un proxy de clúster de Redis
redpanda: un reemplazo de Kafka® 10 veces más rápido para sistemas de misión crítica escritos en C++
rpclib: una moderna biblioteca de cliente y servidor msgpack-RPC en C++
Salesforce Analytics Cloud: software de inteligencia empresarial
Scylla: un almacén de datos NoSQL compatible con Cassandra que puede manejar 1 millón de transacciones por segundo en un solo servidor
Seastar: un marco C++ avanzado y de código abierto para aplicaciones de servidor de alto rendimiento en hardware moderno
spdlog: biblioteca de registro C++ súper rápida
Estelar: plataforma financiera
Touch Surgery: simulador de cirugía
TrinityCore: marco MMORPG de código abierto
? Marco de usuario: marco asíncrono de código abierto con un rico conjunto de abstracciones y controladores de bases de datos.
Terminal de Windows: la nueva terminal de Windows
Más...
Si conoce otros proyectos que utilizan esta biblioteca, hágamelo saber por correo electrónico o enviando un problema.
Entonces, ¿por qué otra biblioteca de formato?
Hay muchos métodos para realizar esta tarea, desde los estándar como la familia de funciones printf e iostreams hasta las bibliotecas Boost Format y FastFormat. La razón para crear una nueva biblioteca es que todas las soluciones existentes que encontré tenían problemas graves o no proporcionaban todas las funciones que necesitaba.
Lo bueno de printf
es que es bastante rápido y está fácilmente disponible al ser parte de la biblioteca estándar de C. El principal inconveniente es que no admite tipos definidos por el usuario. printf
también tiene problemas de seguridad, aunque se mitigan de alguna manera con __attribute__ ((format (printf, ...)) en GCC. Hay una extensión POSIX que agrega argumentos posicionales necesarios para i18n a printf
, pero no forma parte de C99 y puede no estará disponible en algunas plataformas.
El principal problema con iostreams se ilustra mejor con un ejemplo:
std::cout << std::setprecision(2) << std::fixed << 1.23456 << "n";
que es mucho escribir en comparación con printf:
printf("%.2fn", 1.23456);
Matthew Wilson, autor de FastFormat, lo llamó "infierno de chevrones". iostreams no admite argumentos posicionales por diseño.
Lo bueno es que iostreams admite tipos definidos por el usuario y son seguros, aunque el manejo de errores es complicado.
Esta es una biblioteca muy poderosa que admite cadenas de formato tipo printf
y argumentos posicionales. Su principal inconveniente es el rendimiento. Según varios puntos de referencia, es mucho más lento que otros métodos considerados aquí. Boost Format también tiene tiempos de compilación excesivos y problemas graves de sobrecarga de código (consulte Puntos de referencia).
Esta es una biblioteca interesante que es rápida, segura y tiene argumentos posicionales. Sin embargo, tiene importantes limitaciones, citando a su autor:
Tres características que no tienen esperanzas de ser incluidas en el diseño actual son:
Ceros a la izquierda (o cualquier otro relleno que no sea espacio)
Codificación octal/hexadecimal
Especificación de ancho/alineación en tiempo de ejecución
También es bastante grande y tiene una gran dependencia de STLSoft, lo que puede ser demasiado restrictivo para su uso en algunos proyectos.
Esta no es una biblioteca de formato, pero decidí incluirla aquí para que esté completa. Como iostreams, sufre el problema de mezclar texto palabra por palabra con argumentos. La biblioteca es bastante rápida, pero más lenta en el formato de enteros que fmt::format_to
con compilación de cadenas de formato en el propio punto de referencia de Karma, consulte Conversión de cien millones de enteros en cadenas por segundo.
{fmt} se distribuye bajo la licencia MIT.
La sección Formato de sintaxis de cadena en la documentación se basa en la de la documentación del módulo de cadena de Python. Por este motivo, la documentación se distribuye bajo la licencia Python Software Foundation disponible en doc/python-license.txt. Sólo aplica si distribuyes la documentación de {fmt}.
La biblioteca {fmt} está mantenida por Victor Zverovich (vitaut) con contribuciones de muchas otras personas. Consulte Colaboradores y comunicados para conocer algunos de los nombres. Háganos saber si su contribución no aparece en la lista o se menciona incorrectamente y lo corregiremos.
Para informar un problema de seguridad, infórmelo en el aviso de seguridad.
Este proyecto es mantenido por un equipo de voluntarios con un esfuerzo razonable. Por lo tanto, dénos al menos 90 días para trabajar en una solución antes de la exposición pública.