{fmt} é uma biblioteca de formatação de código aberto que fornece uma alternativa rápida e segura para C stdio e C++ iostreams.
Se você gosta deste projeto, considere fazer uma doação para um dos fundos que ajudam as vítimas da guerra na Ucrânia: https://www.stopputin.net/.
Documentação
Folhas de dicas
Perguntas e respostas: faça perguntas no StackOverflow com a tag fmt.
Experimente {fmt} no Compiler Explorer.
API de formato simples com argumentos posicionais para localização
Implementação de C++20 std::format e C++23 std::print
Sintaxe de string de formato semelhante ao formato do Python
Formatador rápido de ponto flutuante IEEE 754 com garantias corretas de arredondamento, encurtamento e ida e volta usando o algoritmo Dragonbox
Suporte Unicode portátil
Implementação segura de printf incluindo a extensão POSIX para argumentos posicionais
Extensibilidade: suporte para tipos definidos pelo usuário
Alto desempenho: mais rápido que implementações de bibliotecas padrão comuns de (s)printf
, iostreams, to_string
e to_chars
, consulte Testes de velocidade e Convertendo cem milhões de números inteiros em strings por segundo
Tamanho de código pequeno tanto em termos de código-fonte com configuração mínima composta por apenas três arquivos, core.h
, format.h
e format-inl.h
, quanto código compilado; consulte Tempo de compilação e inchaço de código
Confiabilidade: a biblioteca possui um extenso conjunto de testes e é continuamente confundida
Segurança: a biblioteca é totalmente segura, erros em strings de formato podem ser relatados em tempo de compilação, gerenciamento automático de memória evita erros de buffer overflow
Facilidade de uso: pequena base de código independente, sem dependências externas, licença permissiva do MIT
Portabilidade com saída consistente entre plataformas e suporte para compiladores mais antigos
Base de código limpa e sem avisos, mesmo em altos níveis de aviso, como -Wall -Wextra -pedantic
Independência de localidade por padrão
Configuração opcional somente de cabeçalho habilitada com a macro FMT_HEADER_ONLY
Consulte a documentação para obter mais detalhes.
Imprimir para stdout (executar)
#include <fmt/core.h>int main() { fmt::print("Olá, mundo!n"); }
Formatar uma string (executar)
std::string s = fmt::format("A resposta é {}.", 42);// s == "A resposta é 42."
Formate uma string usando argumentos posicionais (executar)
std::string s = fmt::format("Prefiro ser {1} do que {0}.", "certo", "feliz");// s == "Prefiro estar feliz do que certo ."
Imprimir datas e horários (execução)
#include <fmt/chrono.h>int main() { auto agora = std::chrono::system_clock::now(); fmt::print("Data e hora: {}n", agora); fmt::print("Hora: {:%H:%M}n", agora); }
Saída:
Date and time: 2023-12-26 19:10:31.557195597 Time: 19:10
Imprimir um contêiner (executar)
#include <vetor>#include <fmt/ranges.h>int main() { std::vetor<int> v = {1, 2, 3}; fmt::print("{}n", v); }
Saída:
[1, 2, 3]
Verifique uma string de formato em tempo de compilação
std::string s = fmt::format("{:d}", "Eu não sou um número");
Isso gera um erro em tempo de compilação em C++20 porque d
é um especificador de formato inválido para uma string.
Escreva um arquivo a partir de um único thread
#include <fmt/os.h>int main() { auto out = fmt::output_file("guide.txt"); out.print("Não {}", "Pânico"); }
Isso pode ser de 5 a 9 vezes mais rápido que o fprintf.
Imprimir com cores e estilos de texto
#include <fmt/color.h>int main() { fmt::print(fg(fmt::color::crimson) | fmt::emphasis::bold, "Olá, {}!n", "mundo" ); fmt::print(fg(fmt::color::floral_white) | bg(fmt::color::slate_gray) | fmt::emphasis::underline, "Olá, {}!n", "Mundo"); fmt::print(fg(fmt::color::steel_blue) | fmt::emphasis::italic, "你好{}!n", "世界"); }
Saída em um terminal moderno com suporte Unicode:
Biblioteca | Método | Tempo de execução, s |
---|---|---|
libc | imprimir | 0,91 |
libc++ | std::ostream | 2,49 |
{fmt} 9.1 | fmt::imprimir | 0,74 |
Formato de reforço 1.80 | impulsionar::formato | 6.26 |
Formato de loucura | loucura::formato | 1,87 |
{fmt} é o mais rápido dos métodos de referência, cerca de 20% mais rápido que printf
.
Os resultados acima foram gerados construindo tinyformat_test.cpp
no macOS 12.6.1 com clang++ -O3 -DNDEBUG -DSPEED_TEST -DHAVE_FORMAT
e realizando a melhor de três execuções. No teste, a string de formato "%0.10f:%04d:%+g:%s:%p:%c:%%n"
ou equivalente é preenchida 2.000.000 vezes com saída enviada para /dev/null
; para mais detalhes consulte a fonte.
{fmt} é até 20-30x mais rápido que std::ostringstream
e sprintf
em float
IEEE754 e formatação double
(dtoa-benchmark) e mais rápido que conversão dupla e ryu:
O script bloat-test.py do benchmark de formato testa o tempo de compilação e o inchaço do código para projetos não triviais. Ele gera 100 unidades de tradução e usa printf()
ou sua alternativa cinco vezes em cada uma para simular um projeto de médio porte. O tamanho do executável resultante e o tempo de compilação (Apple clang versão 15.0.0 (clang-1500.1.0.2.5), macOS Sonoma, melhor de três) são mostrados nas tabelas a seguir.
Construção otimizada (-O3)
Método | Tempo de compilação, s | Tamanho executável, KiB | Tamanho despojado, KiB |
---|---|---|---|
imprimir | 1.6 | 54 | 50 |
IOStreams | 25,9 | 98 | 84 |
fmt83652df | 4.8 | 54 | 50 |
formato minúsculo | 29.1 | 161 | 136 |
Formato de reforço | 55,0 | 530 | 317 |
{fmt} é rápido de compilar e é comparável a printf
em termos de tamanho binário por chamada (dentro de um erro de arredondamento neste sistema).
Compilação não otimizada
Método | Tempo de compilação, s | Tamanho executável, KiB | Tamanho despojado, KiB |
---|---|---|---|
imprimir | 1.4 | 54 | 50 |
IOStreams | 23.4 | 92 | 68 |
{fmt} 83652df | 4.4 | 89 | 85 |
formato minúsculo | 24,5 | 204 | 161 |
Formato de reforço | 36,4 | 831 | 462 |
libc
, lib(std)c++
e libfmt
estão todos vinculados como bibliotecas compartilhadas para comparar apenas a sobrecarga da função de formatação. Boost Format é uma biblioteca somente de cabeçalho, portanto não fornece nenhuma opção de ligação.
Consulte Construindo a biblioteca para obter instruções sobre como construir a biblioteca e executar os testes de unidade.
Os benchmarks residem em um repositório separado, format-benchmarks, então para executar os benchmarks você primeiro precisa clonar este repositório e gerar Makefiles com CMake:
$ git clone --recursive https://github.com/fmtlib/format-benchmark.git $ cd format-benchmark $ cmake .
Então você pode executar o teste de velocidade:
$ make speed-test
ou o teste de inchaço:
$ make bloat-test
clang-tidy v18 fornece a verificação modernize-use-std-print que é capaz de converter ocorrências de printf
e fprintf
em fmt::print
se configurado para isso. (Por padrão, ele converte para std::print
.)
0 AD: um jogo de estratégia em tempo real gratuito, de código aberto e multiplataforma
AMPL/MP: uma biblioteca de código aberto para programação matemática
FoundationDB da Apple: um armazenamento de valores-chave transacional, distribuído e de código aberto
Aseprite: editor de sprites animados e ferramenta de pixel art
AvioBook: um pacote abrangente de operações de aeronaves
Blizzard Battle.net: uma plataforma de jogos online
Celestia: visualização 3D do espaço em tempo real
Ceph: um sistema de armazenamento distribuído escalável
ccache: um cache do compilador
ClickHouse: um sistema de gerenciamento de banco de dados analítico
ContextVision: software de imagens médicas
Contour: um emulador de terminal moderno
CUAUV: veículo subaquático autônomo da Universidade Cornell
Drake: uma caixa de ferramentas de planejamento, controle e análise para sistemas dinâmicos não lineares (MIT)
Envoy: proxy C++ L7 e barramento de comunicação (Lyft)
FiveM: uma estrutura de modificação para GTA V
fmtlog: uma biblioteca de registro no estilo fmtlib de alto desempenho com latência em nanossegundos
Folly: biblioteca de código aberto do Facebook
GemRB: uma implementação portátil de código aberto do Infinity Engine da Bioware
Grand Mountain Adventure: um lindo jogo de esqui e snowboard em mundo aberto
HarpyWar/pvpgn: Rede de jogos jogador contra jogador com ajustes
KBEngine: um mecanismo de servidor MMOG de código aberto
Keypirinha: um launcher semântico para Windows
Kodi (anteriormente xbmc): software de home theater
Knuth: nó completo Bitcoin de alto desempenho
libunicode: uma moderna biblioteca Unicode C++17
MariaDB: sistema de gerenciamento de banco de dados relacional
Microsoft Verona: pesquise linguagem de programação para propriedade simultânea
MongoDB: banco de dados de documentos distribuídos
MongoDB Smasher: uma pequena ferramenta para gerar conjuntos de dados aleatórios
OpenSpace: uma estrutura de astrovisualização de código aberto
PenUltima Online (POL): um servidor MMO, compatível com a maioria dos clientes Ultima Online
PyTorch: uma biblioteca de aprendizado de máquina de código aberto
quasardb: um banco de dados associativo distribuído e de alto desempenho
Quill: biblioteca de registro assíncrono de baixa latência
QKW: generalizando alias para simplificar a navegação e executar sequências complexas de comandos de terminal multilinha
redis-cerberus: um proxy de cluster Redis
redpanda: um substituto Kafka® 10x mais rápido para sistemas de missão crítica escritos em C++
rpclib: um servidor C++ msgpack-RPC moderno e uma biblioteca cliente
Salesforce Analytics Cloud: software de inteligência de negócios
Scylla: um armazenamento de dados NoSQL compatível com Cassandra que pode lidar com 1 milhão de transações por segundo em um único servidor
Seastar: uma estrutura C++ avançada e de código aberto para aplicativos de servidor de alto desempenho em hardware moderno
spdlog: biblioteca de registro C++ super rápida
Stellar: plataforma financeira
Touch Surgery: simulador de cirurgia
TrinityCore: estrutura MMORPG de código aberto
? estrutura userver: estrutura assíncrona de código aberto com um rico conjunto de abstrações e drivers de banco de dados
Terminal Windows: o novo terminal Windows
Mais...
Se você tiver conhecimento de outros projetos que usam esta biblioteca, informe-me por e-mail ou enviando um problema.
Então, por que mais uma biblioteca de formatação?
Existem muitos métodos para realizar essa tarefa, desde os padrão, como a família de funções printf e iostreams, até as bibliotecas Boost Format e FastFormat. O motivo para criar uma nova biblioteca é que todas as soluções existentes que encontrei apresentavam problemas sérios ou não forneciam todos os recursos necessários.
A vantagem do printf
é que ele é muito rápido e está prontamente disponível, fazendo parte da biblioteca padrão C. A principal desvantagem é que ele não oferece suporte a tipos definidos pelo usuário. printf
também tem problemas de segurança, embora sejam um tanto atenuados com __attribute__ ((format (printf, ...)) no GCC. Há uma extensão POSIX que adiciona argumentos posicionais necessários para i18n para printf
, mas não faz parte do C99 e pode não estará disponível em algumas plataformas.
O principal problema com iostreams é melhor ilustrado com um exemplo:
std::cout << std::setprecision(2) << std::fixed << 1.23456 << "n";
o que é muita digitação em comparação com printf:
printf("%.2fn", 1,23456);
Matthew Wilson, autor do FastFormat, chamou isso de "inferno chevron". iostreams não suportam argumentos posicionais por design.
A parte boa é que os iostreams suportam tipos definidos pelo usuário e são seguros, embora o tratamento de erros seja complicado.
Esta é uma biblioteca muito poderosa que suporta strings de formato semelhante printf
e argumentos posicionais. Sua principal desvantagem é o desempenho. De acordo com vários benchmarks, é muito mais lento do que outros métodos considerados aqui. O Boost Format também apresenta tempos de construção excessivos e graves problemas de inchaço de código (consulte Benchmarks).
Esta é uma biblioteca interessante, rápida, segura e com argumentos posicionais. No entanto, apresenta limitações significativas, citando seu autor:
Três recursos que não têm esperança de serem acomodados no design atual são:
Zeros à esquerda (ou qualquer outro preenchimento que não seja espaço)
Codificação octal/hexadecimal
Especificação de largura/alinhamento do tempo de execução
Também é bastante grande e depende fortemente do STLSoft, o que pode ser muito restritivo para uso em alguns projetos.
Esta não é uma biblioteca de formatação, mas decidi incluí-la aqui para completar. Assim como o iostreams, ele sofre do problema de misturar texto literal com argumentos. A biblioteca é muito rápida, mas mais lenta na formatação de inteiros do que fmt::format_to
com compilação de string de formato no próprio benchmark do Karma, consulte Convertendo cem milhões de inteiros em strings por segundo.
{fmt} é distribuído sob a licença do MIT.
A seção Format String Syntax na documentação é baseada na documentação do módulo de string do Python. Por este motivo, a documentação é distribuída sob a licença Python Software Foundation disponível em doc/python-license.txt. Só se aplica se você distribuir a documentação de {fmt}.
A biblioteca {fmt} é mantida por Victor Zverovich (vitaut) com contribuições de muitas outras pessoas. Consulte Colaboradores e versões para alguns dos nomes. Informe-nos se sua contribuição não estiver listada ou mencionada incorretamente e nós consertaremos.
Para relatar um problema de segurança, divulgue-o no comunicado de segurança.
Este projeto é mantido por uma equipe de voluntários com base em esforços razoáveis. Sendo assim, dê-nos pelo menos 90 dias para trabalharmos em uma solução antes da exposição pública.