C++ Saída com cout

Até agora o seu programa mostrou só frases prontas. Nesta aula, o std::cout passa a mostrar vários pedaços de uma vez: textos, números e até o resultado de contas, tudo numa instrução só. Você também vai conhecer o irmão dele, o std::cerr, que serve para mensagens de erro, e entender por que essa separação importa no terminal.

Você vai aprender
  • Encadear vários << numa instrução.
  • Misturar textos e números: "Ana tem " << 29 << " anos.".
  • Mostrar o resultado de contas: std::cout << 2 + 3.
  • Por que std::cout << 1 << 2 mostra 12.
  • Por que comparações precisam de parênteses: std::cout << (5 > 3).
  • O std::cerr, a saída de erros, e como separar as duas saídas no terminal com > e 2>.

Os programas foram compilados na máquina da Ana com g++ -std=c++23 -Wall -Wextra (g++ 15.2), na pasta ~/cpp.


A ideia: um tubo que leva até a tela

Imagine o std::cout como a boca de um tubo que termina na tela. O << é uma seta mostrando para onde as coisas vão: para dentro do tubo. Você pode jogar várias coisas, uma atrás da outra, e elas saem do outro lado na mesma ordem, coladinhas, sem nada no meio. O tubo não põe espaços, não pula linha e não pergunta nada: mostra exatamente o que você colocou.

O nome técnico desse tubo é fluxo (stream): o "stream" do iostream. O cout é o fluxo de saída; o cin, que você verá em Entrada com cin, é o fluxo de entrada, com a seta ao contrário (>>).


1. Encadear vários <<

Em vez de uma instrução para cada pedaço, você pode encadear vários << numa instrução só. As duas formas abaixo mostram exatamente a mesma coisa:

#include <iostream>

int main() {
    std::cout << "Ana" << " foi " << "à feira.\n";

    std::cout << "Ana";
    std::cout << " foi ";
    std::cout << "à feira.\n";

    std::cout << "Arroz: "
              << 2
              << " pacotes\n";
}
$ g++ -std=c++23 -Wall -Wextra encadeado.cpp -o encadeado && ./encadeado
Ana foi à feira.         « a linha 4, encadeada
Ana foi à feira.         « as linhas 6 a 8, separadas: mesmo resultado
Arroz: 2 pacotes         « uma instrução espalhada em três linhas do código
std::cout
A boca do tubo.
<< "Ana"
Primeiro pedaço.
<< " foi "
Segundo pedaço. Os espaços dentro das aspas é que separam as palavras na tela.
<< "à feira.\n"
Terceiro pedaço, com a quebra de linha no fim.
;
Um ; só, no fim da corrente inteira.

Como funciona por dentro: o computador faz std::cout << "Ana" primeiro, e o resultado dessa operação é o próprio std::cout, pronto para o próximo <<. É por isso que dá para encadear quantos você quiser.

Quando a corrente fica comprida, quebre-a em várias linhas, como no último exemplo. O costume é alinhar os << uns embaixo dos outros. Lembre (aula Sintaxe): para o compilador, a quebra de linha não importa; o que termina a instrução é o ;.


2. Textos e números juntos

O std::cout sabe mostrar números também. Números se escrevem sem aspas:

#include <iostream>

int main() {
    std::cout << "Ana tem " << 29 << " anos.\n";
    std::cout << 3.5 << "\n";
}
$ g++ -std=c++23 -Wall -Wextra numeros.cpp -o numeros && ./numeros
Ana tem 29 anos.
3.5

Três detalhes:

  • Os espaços ficam nos textos: "Ana tem " termina com espaço e " anos.\n" começa com espaço. Sem eles, sairia Ana tem29anos..
  • Números com vírgula usam ponto: 3.5, não 3,5. O C++ segue a escrita americana, e a saída também sai com ponto. Como mostrar 3,50 e controlar as casas decimais é assunto de Formatar com iomanip e std::format.
  • 29 e "29" são coisas diferentes. Na tela parecem iguais, mas 29 é um número (dá para fazer contas com ele) e "29" é um texto com os caracteres 2 e 9. A diferença aparece na próxima seção.

Os números vão ficar ainda mais úteis quando estiverem guardados em variáveis: std::cout << "Idade: " << idade funciona do mesmo jeito.


3. Contas direto na saída

Você pode colocar uma conta (uma expressão) no lugar do número. O C++ calcula primeiro e mostra o resultado:

#include <iostream>

int main() {
    std::cout << "2 + 3 = " << 2 + 3 << "\n";
    std::cout << "2 + 3" << "\n";
    std::cout << 10 * 4 << "\n";
    std::cout << 7 / 2 << "\n";
    std::cout << 7.0 / 2 << "\n";
}
$ g++ -std=c++23 -Wall -Wextra contas.cpp -o contas && ./contas
2 + 3 = 5                « o texto "2 + 3 = " e depois o resultado da conta
2 + 3                    « entre aspas é texto: nada é calculado
40                       « * é a multiplicação
3                        « 7 / 2 com números inteiros: a parte decimal é descartada!
3.5                      « com 7.0, a conta é feita com decimais

A linha 4 é a mais importante para entender: o mesmo 2 + 3 aparece duas vezes, uma entre aspas (texto, mostrado como está) e outra sem aspas (conta, mostrada como 5).

E o 7 / 2 dando 3? Não é erro: em C++, a divisão de dois números inteiros dá um resultado inteiro. Isso, o resto da divisão (%) e todas as outras contas estão em Operadores Aritméticos.

Missão: complete a segunda linha para mostrar Daqui a 10 anos ela terá 39 anos., mas sem escrever o número 39: deixe o C++ fazer a conta 29 + 10.

#include <iostream>

int main() {
    std::cout << "Ana tem " << 29 << " anos.\n";
    std::cout << "Daqui a 10 anos ela terá ";
}
#include <iostream>

int main() {
    std::cout << "Ana tem " << 29 << " anos.\n";
    std::cout << "Daqui a 10 anos ela terá " << 29 + 10 << " anos.\n";
}

4. Cuidado: o tubo não põe espaços

Lembra que o tubo cola tudo, sem nada no meio? Com textos, isso já atrapalha. Com números, engana:

#include <iostream>

int main() {
    std::cout << 1 << 2 << "\n";
    std::cout << 1 << " " << 2 << "\n";
    std::cout << "Arroz" << "Feijão" << "\n";
}
$ g++ -std=c++23 -Wall -Wextra colado.cpp -o colado && ./colado
12                       « parece o número doze, mas são o 1 e o 2 grudados
1 2
ArrozFeijão

Quem olha a primeira linha pensa "doze". Não há aviso nem erro: o programa fez exatamente o que foi pedido. Sempre que mostrar dois valores seguidos, coloque um separador entre eles: " ", ", ", " | " ou um "\n".


5. Comparações precisam de parênteses

Você pode querer mostrar o resultado de uma comparação, como "5 é maior que 3?". Sem parênteses, dá erro:

#include <iostream>

int main() {
    std::cout << 5 > 3;
}
$ g++ -std=c++23 -Wall -Wextra compara.cpp -o compara 2>&1 | head -n 8
compara.cpp: In function ‘int main()’:
compara.cpp:4:20: error: no match for ‘operator>’ (operand types are ‘std::basic_ostream<char>::__ostream_type’ {aka ‘std::basic_ostream<char>’} and ‘int’)
    4 |     std::cout << 5 > 3;
      |     ~~~~~~~~~~~~~~ ^ ~
      |               |      |
      |               |      int
      |               std::basic_ostream<char>::__ostream_type {aka std::basic_ostream<char>}
compara.cpp:4:20: note: there are 22 candidates
$ g++ -std=c++23 -Wall -Wextra compara.cpp -o compara 2>&1 | wc -l
178                      « a mensagem inteira tem 178 linhas!

(O 2>&1 | head -n 8 é um truque do terminal para ver só as 8 primeiras linhas da mensagem; o 2> é explicado na seção 6.)

O que aconteceu: o C++ faz o << antes do > (cada operador tem uma prioridade, a precedência). Então ele leu (std::cout << 5) > 3: "o tubo é maior que 3?". Não faz sentido comparar o tubo com um número, e o g++ despeja uma lista enorme de tentativas que não serviram. O Clang, que é o compilador do editor do guia, explica melhor e já sugere os parênteses:

$ clang++ -std=c++23 -Wall -Wextra compara.cpp -o compara 2>&1 | head -n 12
compara.cpp:4:20: warning: overloaded operator << has higher precedence than comparison operator [-Woverloaded-shift-op-parentheses]
    4 |     std::cout << 5 > 3;
      |     ~~~~~~~~~~~~~~ ^ ~
compara.cpp:4:15: note: place parentheses around the '<<' expression to silence this warning
    4 |     std::cout << 5 > 3;
      |               ^
      |     (             )
compara.cpp:4:20: note: place parentheses around comparison expression to evaluate it first
    4 |     std::cout << 5 > 3;
      |                    ^
      |                  (    )
compara.cpp:4:20: error: invalid operands to binary expression ('__ostream_type' (aka 'basic_ostream<char, std::char_traits<char>>') and 'int')

"O operador << tem precedência maior que o de comparação"; "coloque parênteses em volta da comparação para calculá-la primeiro". Fazendo isso:

#include <iostream>

int main() {
    std::cout << (5 > 3) << "\n";
}
$ g++ -std=c++23 -Wall -Wextra compara2.cpp -o compara2 && ./compara2
1                        « 1 quer dizer "verdadeiro"

O 1 é o jeito do cout mostrar "verdadeiro" (e 0, "falso"). Como mostrar true e false por extenso está em Booleanos. A regra prática: na dúvida, ponha parênteses em volta de qualquer conta que não seja simples.


6. std::cerr: a saída de erros

Todo programa no terminal tem duas saídas, e as duas aparecem na tela:

SaídaNome no sistemaEm C++Para quê
Saída padrãostdout (número 1)std::coutO resultado do programa
Saída de errosstderr (número 2)std::cerr (character error)Erros, avisos, mensagens de andamento

O std::cerr se usa igual ao std::cout, com <<, e também vem do <iostream>:

#include <iostream>

int main() {
    std::cout << "Calculando o total...\n";
    std::cerr << "Aviso: preço do café não encontrado\n";
    std::cout << "Total: 25\n";
}
$ g++ -std=c++23 -Wall -Wextra cerr.cpp -o cerr && ./cerr
Calculando o total...
Aviso: preço do café não encontrado
Total: 25

Na tela, nenhuma diferença. Então para que duas saídas? Porque no terminal você pode mandar cada uma para um lugar. O > manda a saída padrão para um arquivo:

$ ./cerr > saida.txt
Aviso: preço do café não encontrado      « só o aviso apareceu na tela
$ cat saida.txt
Calculando o total...
Total: 25                                « o resultado foi para o arquivo

O resultado foi para o arquivo, limpinho, e o aviso continuou na tela, onde a Ana consegue vê-lo. Se o aviso tivesse sido escrito com std::cout, ele teria ido parar no meio do arquivo, e ela nem saberia do problema. O contrário também funciona: 2> (o número 2 é o stderr) manda só os erros para um arquivo:

$ ./cerr 2> erros.txt
Calculando o total...
Total: 25
$ cat erros.txt
Aviso: preço do café não encontrado
$ ./cerr > saida.txt 2> erros.txt        « cada saída no seu arquivo: a tela fica vazia
$ ./cerr 2> /dev/null                    « /dev/null é o "lixo" do sistema: os erros somem
Calculando o total...
Total: 25

Os redirecionamentos > e 2> são do terminal, não do C++ (o Guia Bash tem uma aula inteira sobre eles). Do lado do C++, a regra é: resultado no std::cout, mensagens de erro no std::cerr. Há ainda uma diferença de funcionamento: o std::cerr mostra cada mensagem na hora, sem esperar, o que é bom para erros; os detalhes estão em Novas Linhas.

O próprio g++ faz isso

As mensagens de erro do compilador saem pelo stderr. É por isso que, na seção 5, foi preciso escrever 2>&1 ("mande o 2 para onde vai o 1") antes do | head: sem isso, o head só receberia a saída padrão, que estava vazia.


Outras formas de mostrar texto

O std::cout não é o único jeito. O mesmo resultado, de três formas:

#include <cstdio>
#include <iostream>
#include <print>

int main() {
    std::cout << "Ana tem " << 29 << " anos.\n";
    std::println("Ana tem {} anos.", 29);
    std::printf("Ana tem %d anos.\n", 29);
}
$ g++ -std=c++23 -Wall -Wextra formas.cpp -o formas && ./formas
Ana tem 29 anos.
Ana tem 29 anos.
Ana tem 29 anos.
FormaDe onde vemQuando usar
std::cout << …C++ desde sempre (<iostream>)Funciona em qualquer compilador; é o que você mais vai ver. O guia usa no Nível 1.
std::println("… {} …", valor) C++23<print>Mais curto, quebra a linha sozinho, e o {} marca onde entra cada valor. Aula std::format e std::print.
std::printf("… %d …", valor)Herança da linguagem C (<cstdio>)Código antigo. Errar o %d causa erros que o compilador nem sempre pega; prefira os outros dois.

Quando dá errado

expected ‘;’ before string constant: esqueceu o <<
$ g++ -std=c++23 -Wall -Wextra semseta.cpp -o semseta   « std::cout "Olá!\n";
semseta.cpp: In function ‘int main()’:
semseta.cpp:4:14: error: expected ‘;’ before string constant
    4 |     std::cout "Olá!\n";
      |              ^~~~~~~~~
      |              ;
semseta.cpp:4:10: warning: statement has no effect [-Wunused-value]
    4 |     std::cout "Olá!\n";
      |     ~~~~~^~~~

O que significa: sem o <<, o compilador vê std::cout sozinho e depois um texto solto (string constant). Ele acha que você esqueceu um ; entre os dois. A sugestão dele está errada, mas o lugar está certo.

Como consertar: ponha o << entre o std::cout e o texto.

no match for ‘operator>>’: a seta ao contrário
$ g++ -std=c++23 -Wall -Wextra setaerrada.cpp -o setaerrada 2>&1 | head -12
setaerrada.cpp: In function ‘int main()’:
setaerrada.cpp:4:15: error: no match for ‘operator>>’ (operand types are ‘std::ostream’ {aka ‘std::basic_ostream<char>’} and ‘const char [7]’)
    4 |     std::cout >> "Olá!\n";
      |     ~~~~~~~~~ ^~ ~~~~~~~~
      |          |       |
      |          |       const char [7]
      |          std::ostream {aka std::basic_ostream<char>}
setaerrada.cpp:4:15: note: there are 9 candidates
    4 |     std::cout >> "Olá!\n";
      |     ~~~~~~~~~~^~~~~~~~~~~
In file included from /usr/include/c++/15/string:57,
                 from /usr/include/c++/15/bits/locale_classes.h:42,

O que significa: >> é a seta do std::cin (entrada). Com o cout não existe >>: "nenhuma combinação para o operador >>". A mensagem completa tem 99 linhas listando tentativas; só as primeiras importam.

Como consertar: com cout (e cerr), a seta aponta para ele: <<. Pense: o texto vai para dentro do cout.

Vírgula em vez de <<: um pedaço some
#include <iostream>

int main() {
    std::cout << "Arroz", "Feijão";
    std::cout << "\n";
}
$ g++ -std=c++23 -Wall -Wextra virgula.cpp -o virgula && ./virgula
virgula.cpp: In function ‘int main()’:
virgula.cpp:4:35: warning: right operand of comma operator has no effect [-Wunused-value]
    4 |     std::cout << "Arroz", "Feijão";
      |                                   ^
Arroz                    « cadê o Feijão?

O que significa: compila (é C++ válido, embora inútil), mas o "Feijão" depois da vírgula é ignorado: "o operando da direita do operador vírgula não tem efeito". Só o -Wall avisa. O Clang diz expression result unused.

Como consertar: no cout, os pedaços se separam com <<, nunca com vírgula. (No std::println, é ao contrário: os valores vêm separados por vírgula.)

expected primary-expression before ‘;’ token: << sobrando no fim
$ g++ -std=c++23 -Wall -Wextra setafim.cpp -o setafim   « std::cout << "Olá!\n" <<;
setafim.cpp: In function ‘int main()’:
setafim.cpp:4:29: error: expected primary-expression before ‘;’ token
    4 |     std::cout << "Olá!\n" <<;
      |                             ^

O que significa: depois de um << precisa vir alguma coisa para mostrar (uma "expressão"), e veio o ;. Acontece muito quando você apaga o último pedaço da corrente e esquece a seta.

Como consertar: apague o << que sobrou ou complete com o que faltava.

Números grudados: 12 em vez de 1 2

O que significa: o cout não põe nada entre os pedaços.

Como consertar: coloque separadores: std::cout << 1 << " " << 2.


Referência rápida

EscritaMostra
std::cout << "Oi";Oi
std::cout << "a" << "b" << "\n";ab e quebra a linha
std::cout << "Idade: " << 29;Idade: 29
std::cout << 2 + 3;5
std::cout << "2 + 3";2 + 3
std::cout << 7 / 2; e 7.0 / 23 e 3.5
std::cout << 1 << 2;12
std::cout << (5 > 3);1 (verdadeiro)
std::cerr << "Erro!\n";Erro!, pela saída de erros
./prog > arq / ./prog 2> arq(terminal) manda o cout / o cerr para o arquivo

Exercícios

1. O operador

Complete com o operador que leva o número para o cout:

std::cout << "Total: " 25 << "\n";

2. A saída de erros

Complete para mostrar a mensagem pela saída de erros:

std:: << "Arquivo não encontrado\n";

3. Qual é a saída?

O que aparece na tela com std::cout << 4 << 5 + 1 << "\n";?

Saída:

4. O que mostra std::cout << "10 + 5" << "\n";?

5. A Ana rodou ./relatorio > resultado.txt e uma mensagem ainda apareceu na tela. Por quê?

6. Por que std::cout << 5 > 3; não compila?

Missão final: o cupom da lojinha

Missão: um caderno custa 12 reais e uma caneta custa 2.5. Mostre o cupom abaixo, deixando o C++ fazer as contas: 3 * 12 para os cadernos, 2 * 2.5 para as canetas e a soma das duas para o total (não escreva 36, 5 nem 41 direto). Cuidado com os espaços.

Cupom da Lojinha da Ana
Caderno x 3 = 36
Caneta x 2 = 5
Total: 41
#include <iostream>

int main() {
    std::cout << "Cupom da Lojinha da Ana\n";
    std::cout << "Caderno x 3 = " << 3 * 12 << "\n";
    // complete as outras linhas
}
#include <iostream>

int main() {
    std::cout << "Cupom da Lojinha da Ana\n";
    std::cout << "Caderno x 3 = " << 3 * 12 << "\n";
    std::cout << "Caneta x 2 = " << 2 * 2.5 << "\n";
    std::cout << "Total: " << 3 * 12 + 2 * 2.5 << "\n";
}

Resumo

  • std::cout é o tubo até a tela; << põe coisas nele, na ordem, sem nada no meio.
  • Vários << podem ser encadeados numa instrução, com um ; no fim.
  • Textos vão entre aspas; números e contas, sem aspas. 2 + 3 mostra 5; "2 + 3" mostra 2 + 3.
  • Os espaços entre palavras e números são responsabilidade sua: 1 << 2 vira 12.
  • Comparações e contas complicadas vão entre parênteses: (5 > 3).
  • std::cerr é a saída de erros. No terminal, > redireciona o cout e 2> redireciona o cerr.