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.
- 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 << 2mostra12. - 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>e2>.
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, sairiaAna tem29anos.. - Números com vírgula usam ponto:
3.5, não3,5. O C++ segue a escrita americana, e a saída também sai com ponto. Como mostrar3,50e controlar as casas decimais é assunto de Formatar com iomanip e std::format. 29e"29"são coisas diferentes. Na tela parecem iguais, mas29é 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ída | Nome no sistema | Em C++ | Para quê |
|---|---|---|---|
| Saída padrão | stdout (número 1) | std::cout | O resultado do programa |
| Saída de erros | stderr (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.
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.
| Forma | De onde vem | Quando 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.
<<: 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.
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
| Escrita | Mostra |
|---|---|
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 / 2 | 3 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:
2. A saída de erros
Complete para mostrar a mensagem pela saída de erros:
3. Qual é a saída?
O que aparece na tela com std::cout << 4 << 5 + 1 << "\n";?
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 + 3mostra5;"2 + 3"mostra2 + 3. - Os espaços entre palavras e números são responsabilidade sua:
1 << 2vira12. - Comparações e contas complicadas vão entre parênteses:
(5 > 3). std::cerré a saída de erros. No terminal,>redireciona ocoute2>redireciona ocerr.