Menu

getline em C++: ler a linha inteira, corrigir a entrada pulada, ler arquivos

Como o std::getline lê uma linha inteira para uma std::string: uso com cin, por que ele retorna uma string vazia depois de cin >>, as correções com cin.ignore e std::ws, delimitadores personalizados e leitura de um arquivo linha por linha até o fim.

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

Lendo uma linha inteira

cin >> text lê uma única palavra: para no primeiro espaço. Para ler tudo o que o usuário digitou até o Enter, espaços incluídos, use std::getline, do header <string>:

#include <iostream>
#include <string>

int main() {
    std::string name;
    std::cout << "Full name: ";
    std::getline(std::cin, name);
    std::cout << "Hello, " << name << "!\n";
}

Digitar Ada Lovelace imprime Hello, Ada Lovelace!. Com std::cin >> name ele imprimiria Hello, Ada! e deixaria Lovelace esperando na entrada.

A assinatura é:

std::istream& std::getline(std::istream& input, std::string& text);
std::istream& std::getline(std::istream& input, std::string& text, char delim);
  • input é qualquer stream de entrada: std::cin, um arquivo aberto com std::ifstream ou um std::istringstream montado a partir de uma string.
  • text é substituído (não recebe texto no final) pelos caracteres lidos.
  • delim é o caractere que encerra a leitura. O padrão é '\n'. O delimitador é removido do stream e não é guardado em text.
  • O valor de retorno é o próprio stream, e é isso que permite testá-lo numa condição.

Como o getline funciona igual em qualquer stream de entrada, os exemplos executáveis desta página leem de um std::istringstream com texto fixo. Assim a saída é previsível sem você digitar nada. Para ler do teclado, troque a variável do stream por std::cin.

Saída:

[Ada Lovelace]
[Alan Turing]

Os colchetes mostram que a quebra de linha não faz parte de nenhuma das strings.

getline depois de cin >> retorna uma string vazia

Este é o problema mais comum com o getline. Você lê um número com >>, depois uma linha com getline, e o getline parece ser pulado:

Saída:

age: 30
city: []

input >> age lê os caracteres 30 e para no primeiro caractere que não pode fazer parte de um número, a quebra de linha. Essa quebra de linha fica no stream. O getline então lê até a próxima quebra de linha, encontra uma imediatamente e retorna uma string vazia. Com std::cin, o efeito é que o programa nunca espera pela segunda resposta.

Há duas correções padrão. As duas vão entre o >> e o getline.

Correção 1: descartar o resto da linha com ignore.

Saída:

age: 30
city: [Paris]

ignore(n, '\n') joga fora caracteres até ter removido uma quebra de linha ou n caracteres, o que vier primeiro. Passar o maior std::streamsize possível significa "até a quebra de linha, esteja ela onde estiver". Isso também remove qualquer coisa que o usuário tenha digitado depois do número na mesma linha, como espaços no final. Com o teclado, a linha é std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');, e ela precisa de #include <limits>.

Um std::cin.ignore() sem argumentos descarta exatamente um caractere. Funciona quando a quebra de linha vem logo depois do número, e falha assim que há um espaço antes dela.

Correção 2: pular os espaços em branco iniciais com std::ws.

Saída:

age: 30
city: [Paris]

std::ws é um manipulador que consome todo o espaço em branco (espaços, tabs, quebras de linha) na posição atual. input >> std::ws retorna o stream, então pode ir direto para o getline. Ele também pula linhas em branco e espaços no início, o que é prático para nomes e cidades, mas errado quando espaços iniciais ou uma linha vazia são entradas com significado. Nesse caso, use ignore.

Lendo até o fim da entrada

getline retorna o stream, e um stream se converte em false quando uma leitura falha. Quando não há mais linhas, o getline falha, então um laço while em volta dele lê todas as linhas e para no fim:

Saída:

1: [apples 3]
2: [bread 1]
3: []
4: [milk 2]
read 4 lines

Dois detalhes dessa saída:

  • Uma linha vazia continua sendo uma leitura bem-sucedida. Ela dá uma string vazia e o laço continua. Só chegar ao fim da entrada o interrompe.
  • A última linha não precisa de uma quebra de linha no final. Se o texto terminasse em milk 2 sem \n, o getline ainda a retornaria, e a chamada seguinte falharia.

Com std::cin, o mesmo laço lê até a entrada acabar. Isso acontece quando a entrada vem de um arquivo por redirecionamento (./program < data.txt), ou quando o usuário aperta Ctrl+D no macOS e no Linux, ou Ctrl+Z e depois Enter no Windows.

Evite o padrão while (!input.eof()) { std::getline(input, line); ... }. eof() só fica verdadeiro depois que uma leitura já bateu no fim, então o corpo roda uma vez a mais com uma leitura que falhou e um line desatualizado. Coloque a chamada de getline na condição.

Lendo um arquivo linha por linha

Arquivos usam o mesmo laço. Abra o arquivo com std::ifstream, de <fstream>, confira se ele abriu e leia:

Saída:

1. Ada 92
2. Grace 88
3. Alan 95

if (!file) pega um arquivo inexistente ou um caminho errado antes do laço. Sem isso, o laço simplesmente lê zero linhas, o que parece um arquivo vazio e não um erro. O arquivo fecha automaticamente quando file sai de escopo no fim do main.

Arquivos salvos no Windows terminam cada linha com \r\n. Quando um arquivo assim é lido no Linux ou no macOS, o getline remove o \n mas mantém o \r, e toda linha termina com um retorno de carro invisível que quebra comparações como line == "done". Remova-o depois de ler:

if (!line.empty() && line.back() == '\r') {
    line.pop_back();
}

Usando um delimitador personalizado

O terceiro argumento muda o caractere que encerra cada leitura. Um uso comum é dividir uma linha nas vírgulas. Leia a linha primeiro e depois divida-a com um std::istringstream:

Saída:

fields: 3
[Ada Lovelace]
[36]
[London]

A vírgula é removida do stream e não é guardada, do mesmo jeito que a quebra de linha na forma padrão. Repare que, com um delimitador personalizado, a quebra de linha é um caractere comum. Se você chamar std::getline(file, field, ',') direto num arquivo de várias linhas, o último campo de uma linha e o primeiro campo da seguinte voltam grudados, como em "London\nGrace Hopper". Ler uma linha por vez e dividir cada linha separadamente evita isso. A página de string streams aprofunda o std::istringstream, incluindo a conversão de campos como "36" em números.

std::getline vs cin.getline

Também existe uma função membro com nome parecido:

char buffer[20];
std::cin.getline(buffer, 20);        // função membro, array de char de tamanho fixo

std::string text;
std::getline(std::cin, text);        // função livre, std::string

cin.getline escreve num array de char e guarda no máximo size - 1 caracteres mais o '\0' final. Uma linha mais longa coloca o stream em estado de falha, e toda leitura posterior é pulada até você chamar std::cin.clear(). std::getline com uma std::string não tem limite de tamanho para você controlar. Use-o, a menos que esteja trabalhando com uma API que exige um array de char.

Erros comuns

  • Misturar >> e getline sem limpar a quebra de linha. Adicione ignore(...) ou use std::ws entre os dois. A página de entrada e saída mostra o mesmo problema com std::cin e como se recuperar quando uma leitura numérica falha.
  • Chamar getline(std::cin, number) com um int. getline só lê para uma std::string. Leia a linha e depois converta com std::stoi ou um std::istringstream.
  • Fazer o laço com eof(). Teste a própria chamada de getline: while (std::getline(input, line)).
  • Esquecer #include <string>. O std::getline para strings é declarado em <string>. Alguns compiladores deixam passar via <iostream>, e o código falha em outro compilador.
  • Não verificar se o arquivo abriu. Um caminho errado faz o std::ifstream falhar em silêncio e o laço de leitura rodar zero vezes.

Perguntas frequentes

O que o getline faz em C++?

std::getline(stream, text) lê caracteres de stream para a std::string text até encontrar uma quebra de linha, e então remove essa quebra de linha do stream sem guardá-la. Ao contrário de cin >> text, ele mantém os espaços, então lê uma linha inteira, como um nome completo ou uma frase.

Por que o getline é pulado depois de cin >> em C++?

cin >> number para de ler na quebra de linha que você digitou depois do número e deixa essa quebra de linha no buffer de entrada. O getline seguinte a encontra imediatamente e retorna uma string vazia. Descarte-a antes com std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');, ou chame std::getline(std::cin >> std::ws, text) para pular os espaços em branco iniciais.

Como usar getline com um delimitador diferente da quebra de linha?

Passe o delimitador como terceiro argumento: std::getline(stream, field, ','). Ele lê até a próxima vírgula, guarda o texto antes dela e descarta a vírgula. As quebras de linha passam a ser caracteres comuns, então isso costuma ser combinado com um std::stringstream montado a partir de uma única linha.

Como ler um arquivo linha por linha em C++?

Abra com std::ifstream file("data.txt"); e faça um laço com while (std::getline(file, line)) { ... }. getline retorna o stream, que se converte em false quando não há mais linhas, então o laço para no fim do arquivo.

Qual a diferença entre cin.getline e getline?

std::getline(std::cin, text) é uma função livre que lê para uma std::string, que cresce para caber qualquer linha. std::cin.getline(buffer, size) é uma função membro que lê para um array fixo de char e falha se a linha tiver mais de size - 1 caracteres. Use std::getline com std::string, a menos que você tenha um motivo para usar arrays crus.

Ilustração das linguagens de programação do Coddy

Aprenda a programar com o Coddy

COMEÇAR