A biblioteca fmt é integrada diretamente ao spdlog, disponibilizando toda a sintaxe de formatação do fmt para uso imediato.
A sintaxe completa de um especificador de formato é:
{[índice]:[alinhamento][sinal][#][0][largura][.precisão][tipo]}
- Formatação básica de números
Exemplos com inteiros, hexadecimais e notação científica.
#include <fmt/format.h>
#include <iostream>
#include <cmath>
int main() {
int valor = 255;
unsigned uvalor = 4294967295u;
double cient = 12345.6789;
// Decimal
auto res = fmt::format("Decimal: {}", valor);
std::cout << res << "\n"; // Decimal: 255
res = fmt::format("Decimal (sem sinal): {}", uvalor);
std::cout << res << "\n"; // Decimal (sem sinal): 4294967295
// Hexadecimal
res = fmt::format("hex minúsculo: {:x}", valor);
std::cout << res << "\n"; // hex minúsculo: ff
res = fmt::format("hex maiúsculo: {:X}", valor);
std::cout << res << "\n"; // hex maiúsculo: FF
res = fmt::format("hex com prefixo: {:#x}", valor);
std::cout << res << "\n"; // hex com prefixo: 0xff
res = fmt::format("hex com prefixo maiúsculo: {:#X}", valor);
std::cout << res << "\n"; // hex com prefixo maiúsculo: 0XFF
// Notação científica
res = fmt::format("científica (e): {:e}", cient);
std::cout << res << "\n"; // científica (e): 1.234568e+04
res = fmt::format("científica (E): {:E}", cient);
std::cout << res << "\n"; // científica (E): 1.234568E+04
return 0;
}
- Largura, alinhamento e preenchimento
Controel de espaçamento e posicionamento.
#include <fmt/format.h>
#include <iostream>
int main() {
int num = 42;
double flt = 123.456;
std::cout << "=== Largura ===\n";
auto r = fmt::format("largura 10: |{:10}|", num);
std::cout << r << "\n"; // | 42|
r = fmt::format("largura 10 (float): |{:10}|", flt);
std::cout << r << "\n"; // | 123.456|
r = fmt::format("hex largura 8: |{:8x}|", 0xFF);
std::cout << r << "\n"; // | ff|
r = fmt::format("hex largura 8 com zeros: |{:08x}|", 0xFF);
std::cout << r << "\n"; // |000000ff|
std::cout << "\n=== Alinhamento ===\n";
r = fmt::format("esquerda: |{:<10}|", num);
std::cout << r << "\n"; // |42 |
r = fmt::format("direita (padrão): |{:>10}|", num);
std::cout << r << "\n"; // | 42|
r = fmt::format("centro: |{:^10}|", num);
std::cout << r << "\n"; // | 42 |
r = fmt::format("preencher com '*': |{:*^10}|", num);
std::cout << r << "\n"; // |****42****|
r = fmt::format("preencher com '-', direita: |{:->10}|", num);
std::cout << r << "\n"; // |--------42|
return 0;
}
- Precisão de ponto flutuante
Controla o número de casas decimais.
#include <fmt/format.h>
#include <iostream>
#include <cmath>
int main() {
double pi = M_PI;
double grande = 1234567.8901234567;
double pequeno = 0.00000123456789;
std::cout << "=== Precisão ===\n";
auto r = fmt::format("padrão: {}", pi);
std::cout << r << "\n"; // 3.141592653589793
r = fmt::format("2 casas: {:.2f}", pi);
std::cout << r << "\n"; // 3.14
r = fmt::format("5 casas: {:.5f}", pi);
std::cout << r << "\n"; // 3.14159
r = fmt::format("not. científica com 2 casas: {:.2e}", grande);
std::cout << r << "\n"; // 1.23e+06
r = fmt::format("not. científica (E) 2 casas: {:.2E}", grande);
std::cout << r << "\n"; // 1.23E+06
r = fmt::format("automática (g) 3 casas: {:.3g}", pi);
std::cout << r << "\n"; // 3.14
return 0;
}
- Combinações comuns
Exemplos que unem largura, alinhamento, precisão e tipo.
#include <fmt/format.h>
#include <iostream>
int main() {
std::cout << "=== Combinações ===\n";
auto r = fmt::format("inteiro: |{:0>10d}|", 42);
std::cout << r << "\n"; // |0000000042|
r = fmt::format("hex: |{:*<10x}|", 255);
std::cout << r << "\n"; // |ff********|
r = fmt::format("hex maiúsculo centralizado: |{:#^12X}|", 0xBEEF);
std::cout << r << "\n"; // | 0XBEEF |
r = fmt::format("float à direita: |{:>10.2f}|", 123.456);
std::cout << r << "\n"; // | 123.46|
r = fmt::format("float à esquerda: |{:-<10.3f}|", 123.456);
std::cout << r << "\n"; // |123.456---|
r = fmt::format("hex com prefixo e zeros: |{:#010x}|", 255);
std::cout << r << "\n"; // |0x000000ff|
return 0;
}
- Largura e precisão dinâmicas
Os valores de largura e precisão podem ser passados como argumentos adicionais.
#include <fmt/format.h>
#include <iostream>
int main() {
int larg = 15;
int prec = 6;
double val = 123.456789;
auto r = fmt::format("largura dinâmica: |{:{}}|", val, larg);
std::cout << r << "\n"; // | 123.457|
r = fmt::format("largura e precisão: |{:{}.{}f}|", val, larg, prec);
std::cout << r << "\n"; // | 123.456789|
int hex_larg = 8;
r = fmt::format("hex dinâmico: |{:0{}x}|", 255, hex_larg);
std::cout << r << "\n"; // |000000ff|
r = fmt::format("hex com prefixo dinâmico: |{:#0{}X}|", 255, hex_larg + 2);
std::cout << r << "\n"; // |0X0000FF|
return 0;
}
- Funções utilitárias para formatação
Encapsulamento de formatadores com parâmetros reutilizáveis.
#include <fmt/format.h>
#include <iostream>
std::string formataHex(uint64_t valor, int largura = 0, char alinhamento = '>', bool maiusculo = false, bool prefixo = false) {
std::string fmt_str = "{:";
if (alinhamento != '>') fmt_str += alinhamento;
if (largura > 0) {
if (prefixo) fmt_str += "0";
fmt_str += std::to_string(largura);
}
if (prefixo) fmt_str += "#";
fmt_str += maiusculo ? "X}" : "x}";
return fmt::format(fmt::runtime(fmt_str), valor);
}
std::string formataCientifica(double valor, int precisao = 6, int largura = 0, char alinhamento = '>', bool maiusculo = false) {
std::string fmt_str = "{:";
if (alinhamento != '>') fmt_str += alinhamento;
if (largura > 0) fmt_str += std::to_string(largura);
fmt_str += "." + std::to_string(precisao);
fmt_str += maiusculo ? "E}" : "e}";
return fmt::format(fmt::runtime(fmt_str), valor);
}
int main() {
std::cout << "Utilitários:\n";
auto r = formataHex(0xABCD, 8);
std::cout << "hex largura 8: " << r << "\n"; // abcd
r = formataHex(0xBEEF, 12, '>', false, true);
std::cout << "hex com prefixo: " << r << "\n"; // 0xbeef
r = formataCientifica(123456.789, 3, 15, '>', true);
std::cout << "científica: " << r << "\n"; // 1.235E+05
return 0;
}
- Exemplo prático: tabela de sensores
Formatação de múltiplas colunas com diferentes tipos.
#include <fmt/format.h>
#include <iostream>
#include <vector>
struct Sensor {
int id;
unsigned raw;
double tensao;
double temp;
};
int main() {
std::vector<Sensor> dados = {
{1, 0x1A3F, 3.14159265, 25.123456},
{2, 0xBEEF, 5.0, -10.56789},
{3, 0x00FF, 12.3456789, 100.0},
{4, 0xABCD, 0.00123456, 0.0}
};
std::cout << "Tabela de Sensores\n";
std::cout << fmt::format("{:─^80}\n", "");
std::cout << fmt::format("{:<4} | {:<10} | {:<12} | {:<15} | {:<20}\n",
"ID", "Raw (Hex)", "Tensão (V)", "Temperatura (C)", "Notação Cient.");
std::cout << fmt::format("{:─^80}\n", "");
for (const auto& s : dados) {
auto r = fmt::format("{:<4} | {:#<10X} | {:>12.4f} | {:>15.3f} | {:>20.3e}",
s.id, s.raw, s.tensao, s.temp, s.temp);
std::cout << r << "\n";
}
std::cout << fmt::format("{:─^80}\n", "");
return 0;
}
- Configuração de formatação encapsulada
Estrutura que agrupa parâmetros e aplica a formatação.
#include <fmt/format.h>
#include <iostream>
struct ConfigFormato {
int largura;
int precisao;
bool maiusculo;
bool prefixo;
char alinhamento;
std::string formatInt(int valor) const {
return fmt::format("{:{}{}d}", valor, alinhamento, largura);
}
std::string formatHex(unsigned valor) const {
std::string f = "{:";
f += alinhamento;
if (prefixo) f += "#";
f += std::to_string(largura);
f += maiusculo ? "X}" : "x}";
return fmt::format(fmt::runtime(f), valor);
}
std::string formatCientifica(double valor) const {
return fmt::format("{:{}{}.{}e}", valor, alinhamento, largura, precisao);
}
};
int main() {
ConfigFormato cfg1 {10, 3, true, true, '>'};
ConfigFormato cfg2 {8, 6, false, false, '<'};
std::cout << "cfg1:\n";
std::cout << "int: " << cfg1.formatInt(42) << "\n";
std::cout << "hex: " << cfg1.formatHex(0xBEEF) << "\n";
std::cout << "cient: " << cfg1.formatCientifica(12345.6789) << "\n";
std::cout << "\ncfg2:\n";
std::cout << "int: " << cfg2.formatInt(-200) << "\n";
std::cout << "hex: " << cfg2.formatHex(0xABCD) << "\n";
std::cout << "cient: " << cfg2.formatCientifica(12345.6789) << "\n";
return 0;
}
Esses exemplos mostram como fmt::format oferece controle fino sobre a representação textual de dados numéricos e textuais, sendo amplamente utilizada em conjunto com spdlog e outras bibliotecas C++ modernas.