Você provavelmente conhece o std::cout
em C++, mas você também – provavelmente – não o está usando com todo o seu potencial porque não conhece o std::format
. Acertei, não é mesmo? Pois bem, vamos ao assunto.
std::format – um aliado poderoso
Você deve estar acostumado a imprimir valores na saída do seu programa usando instruções como aquela mostrada a seguir. O problema com esse código é que o texto que está sendo imprimido na tela é difícil de se entender: você precisa traduzir na sua mente a variável world
no seu conteúdo, e depois juntar todos os pedaços de string soltos você tem seu texto final! Com uma saída simples, isso pode ser fácil, mas quando você quer imprimir algo maior e mais complexo, esse trabalho mental pode ser bastante cansativo.
std::string world{"world"}; std::cout << "Hello, " << world << "!" << std::endl;
Para resolver esse problema foi introduzido o std::format em C++, na biblioteca <format>, que permite formatar os strings de modo semelhante à formatação usada pelo printf – mas ainda melhor! Veja um exemplo a seguir do uso do std::format junto com o cout.
Exemplo 1 – std::format usado junto com o std::cout
#include <iostream> #include <format> #include <string> int main() { std::string name{"John"}; const int age{25}; std::cout << std::format("Hi, I'm {0}! I'm {1} years old.\n", name, age); return 0; }
Note que no exemplo acima eu usei os índices 0 e 1 dentro das chaves no primeiro argumento do format: "Hi, I'm {0}! I'm {1} years old.\n"
, porque eu quis. Eu poderia simplesmente ter deixado as chaves vazias e o código teria funcionado do mesmo jeito. A vantagens de usar os índices é que eu poderia controlar a ordem na qual minhas variáveis são inseridas no string que será formatado. Os valores 0 e 1 correspondem aos índices dos argumentos que vêm depois da string de formatação. Se eu quisesse inverter a ordem de inserção dos meus argumentos para gerar na saída o texto “Hi, I’m 25! I’m John years old.”, bastaria escrever o seguinte na string de formatação (primeiro argumento do std::format
): Hi, I'm {1}! I'm {0} years old.\n
. Note o 1 invertido de posição com o 0.
Referências
Tomei como base para escrever esse artigo o Capítulo 2 do livro C++ Profissional, de Marc Gregoire (que recomendo bastante).
Campos de substituição
Os campos de substituição são as chaves que usamos dentro da string de formatação (primeiro argumento do std::format), e eles servem para indicar a posição na qual os argumentos que vêm depois da string serão inseridos dentro dela. Eles possuem o seguinte formato: {arg-id: format-spec} (segundo o CppReference). Aqui está o que cada uma dessas coisas significa:
- O arg-id é o índice do argumento que será inserido na string no lugar do campo de formatação (como vimos no exemplo 1).
- O format-spec é um especificador de formatação do valor que será inserido no string (por exemplo, .5 serve para limitar o número de digitos de um valor
double
em 5) - Os dois-pontos (:) serve para separar o índice do argumento (arg-id) do especificador de formatação do argumento que será inserido (format-spec)
Vejamos um exemplo do uso do format-spec para formatar um double usado como argumento do std::format.
Exemplo 2 – Uso dos especificadores de formatação com o std::format
#include <iostream> #include <format> #include <string> int main() { double price{1299.99999}; std::cout << std::format("O preco do produto eh: {:.2f}", price); return 0; }
Resumindo
Neste artigo vimos como funciona o std::format em conjunto com o std::cout, e falei para você porque você deve usá-lo sempre que possível. Ainda assim, para te ajudar a reter essas informações, resumi a seguir as principais vantagens de se usar o std::format em C++ junto com o cout.
- Maior legibilidade do string que será formatado: ao invés de ter de decifrar na mente a saída de uma expressão como
cout << "Eu me chamo " << nome << ", sou " << nacionalidade << " e tenho " << idade << " anos."
, o std::format simplifica sua vida e permite que você entenda o string de saída com maior facilidade:cout << std::format("Eu me chamo {}, sou {} e tenho {} anos.", nome, nacionalidade, idade)
. Melhor, não? - Controle sobre a ordem de inserção dos argumento no string de saída: como vimos no exemplo 1, é possível indicar o índice de cada argumento dentro das chaves { } na string de formatação do std::format, permitindo ao usuário controlar melhor e com maior liberdade a string que será construida sem fazer malabarismos para obter o resultado que deseja.
- Segurança de tipos: Ao contrário do printf, com o qual é preciso ter cuidado com os argumentos que você está inserindo na string resultante, o std::format te deixa tranquilo: por usar os mecanismos de dedução de tipos dos templates (assim como o cout), você não precisa se preocupar com nada e basta passar os argumentos que quiser na sequência do string de formatação.
Gostou do artigo? Então inscreva-se na nossa newsletter para não perder nenhum dos nossos artigos 🙂
Para que serve o ENDL em C++? 2 exemplos comentados >>
Sou apaixonado por tecnologia, literatura e também filosofia. O cultivo dessas paixões ao longo da minha trajetória me inspiraram a compartilhar aquilo que aprendo com os outros da maneira mais clara que eu possa. Sou formado em Engenharia Elétrica no Brasil, e também sou engenheiro formado na França. Trabalho atualmente como programador C++ em uma multinacional francesa, uma das maiores empresas de TI do mundo.