Menu

Entrada e saída em C++: cin, cout, getline e streams

Como funciona a E/S de console em C++: imprimir com cout, ler com cin, o clássico bug da quebra de linha do getline depois do cin e como se recuperar quando a entrada falha.

Esta página tem editores executáveis - edite, execute e veja a saída na hora.

Como o C++ conversa com o console

O C++ faz a E/S de console por meio de streams do cabeçalho <iostream>. Você escreve para o mundo com cout (saída de caracteres) e lê do usuário com cin (entrada de caracteres). Eles usam dois operadores que você já viu como deslocamentos de bits, reaproveitados aqui:

  • << é o operador de inserção: envia dados para dentro do cout.
  • >> é o operador de extração: puxa dados de dentro do cin para uma variável.

Um jeito fácil de lembrar a direção: as setas apontam para o sentido em que os dados fluem. Agora que você consegue guardar texto em strings, vamos mover esse texto para dentro e para fora do seu programa.

Imprimindo com cout

O cout envia para a saída padrão tudo o que você inserir. Você pode encadear vários << em uma única instrução, misturando texto, números e variáveis à vontade.

Cada << acrescenta à mesma linha até você inserir uma quebra de linha. Há duas maneiras de fazer isso: '\n' insere um caractere de quebra de linha, enquanto endl insere uma quebra de linha e descarrega o buffer para a tela. O flush tem um custo real, então dentro de um laço que imprime milhares de linhas, prefira '\n': o stream se descarrega sozinho quando preciso (e sempre ao encerrar o programa).

// Tudo bem para uma mensagem isolada:
cout << "Done" << endl;

// Em um laço pesado, prefira isto: sem flush forçado a cada iteração:
for (int i = 0; i < 1000000; ++i)
    cout << i << '\n';

Lendo com cin e >>

cin >> variable lê um token delimitado por espaços em branco e o converte para o tipo da variável. Ele pula quaisquer espaços ou quebras de linha iniciais e então para no próximo espaço em branco.

Como >> para no espaço em branco, ele é ótimo para números individuais e palavras isoladas, mas inútil para uma frase inteira: cin >> word com a entrada hello world lê apenas hello e deixa world no buffer para a próxima leitura.

Lendo uma linha inteira com getline

Para capturar uma linha inteira — espaços e tudo — use getline(cin, line), que lê tudo até a tecla Enter para dentro de uma std::string.

Esta é a ferramenta certa sempre que a entrada puder conter espaços: nomes, endereços, frases. Só existe uma armadilha esperando por você no momento em que misturar getline com >>.

A armadilha da quebra de linha entre cin e getline

Este é o bug de E/S mais comum em C++. Quando você faz cin >> n, a extração lê o número, mas deixa a quebra de linha (a tecla Enter que você pressionou) no buffer de entrada. O getline seguinte vê essa quebra de linha que sobrou na hora, trata a linha como já encerrada e te entrega uma string vazia — sem nunca pausar para esperar entrada.

int age;
string city;

cin >> age;            // você digita 30 e pressiona Enter; '\n' fica no buffer
getline(cin, city);    // lê o '\n' que sobrou -> city fica "" (vazia!)

A correção é descartar essa quebra de linha que sobrou com cin.ignore depois do >> e antes do getline:

cin.ignore(numeric_limits<streamsize>::max(), '\n') pula caracteres até ter consumido uma quebra de linha (ou ter chegado ao fim da entrada). É a versão robusta: a mais curta cin.ignore() descarta apenas um único caractere, o que quebra se o usuário tiver digitado espaços extras depois do número. Pegue a forma completa por hábito.

Quando a entrada falha

Se o usuário digitar letras onde você esperava um número, a extração falha: cin entra em um estado de erro e a variável de destino fica inalterada (definida como 0 desde o C++11). Pior ainda, uma vez que cin está em estado de falha, toda leitura posterior também é silenciosamente pulada, então você pode acabar em um laço infinito.

A recuperação tem sempre dois passos: cin.clear() reseta as flags de erro para o stream ficar utilizável de novo, e cin.ignore(...) descarta os caracteres problemáticos que ainda estão presos no buffer. Pule o ignore e a entrada inválida permanece, então o próximo >> falha de novo — o clássico laço infinito. Testar cin >> n diretamente na condição funciona porque o stream se converte em false quando está em estado de falha.

Erros comuns a evitar

  • Usar cin >> s para uma frase. Ele para no primeiro espaço. Use getline para qualquer coisa com espaços.
  • Esquecer o cin.ignore entre >> e getline. A quebra de linha que sobra te dá uma linha vazia. Limpe o buffer primeiro.
  • Recorrer ao endl em todo lugar. Cada um força um flush. Use '\n' por padrão e guarde o endl para quando a saída realmente precisar aparecer agora.
  • Ignorar um cin com falha. Letras em uma leitura numérica deixam o cin quebrado; sempre faça clear() e depois ignore() antes de ler de novo.

Próximo: String streams

A E/S de console e a manipulação de strings se unem nas string streams. Uma stringstream te dá os mesmos operadores << e >>, mas apontados para uma string em memória em vez do console — perfeito para fazer o parsing de uma linha em números, montar texto formatado e converter entre strings e outros tipos sem nunca tocar no teclado.

Perguntas frequentes

Por que o getline pula a entrada logo depois de usar cin em C++?

cin >> x lê o número, mas deixa no buffer a quebra de linha que você pressionou. O getline seguinte lê até essa quebra de linha que sobrou e retorna uma string vazia na hora. Limpe-a primeiro com cin.ignore(numeric_limits<streamsize>::max(), '\n'); depois do >> e antes do getline.

Qual é a diferença entre endl e \n em C++?

Ambos terminam a linha, mas o endl também descarrega (flush) o buffer de saída para a tela, enquanto '\n' apenas insere uma quebra de linha. O flush tem um custo: em um laço apertado, prefira '\n' e deixe o stream descarregar sozinho. Use endl apenas quando realmente precisar que a saída apareça agora.

Como leio uma linha inteira de texto incluindo espaços em C++?

Use getline(cin, line), não cin >> line. O operador >> para no primeiro espaço em branco, então captura apenas uma palavra. O getline lê tudo até a tecla Enter para dentro de uma std::string, espaços incluídos.

Coddy programming languages illustration

Aprenda a programar com o Coddy

COMEÇAR