Se for usar std::cout, use std::format junto!

cout com std::format em C++

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.

Nao use COUT em C++ antes de ver isso: std::format!

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;
}

Hi, I’m John! I’m 25 years old.


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.

referencias de livros em C++
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;
}

O preco do produto eh: 1300.00


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 🙂

Foto de perfil de Emanoel

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.

Leave a Reply

Your email address will not be published. Required fields are marked *