HOWTO · C++

Como Ler um Arquivo Linha por Linha em C++

Neste artigo, exploraremos quatro abordagens comuns para ler um arquivo linha por linha em C++: usando ifstream com getline(), a função getline() da biblioteca C, a função fgets() e istream_iterator.

Nesta página

Ler um arquivo linha por linha em C++ é uma operação fundamental em muitas tarefas de programação, como processamento de dados, análise de texto e análise de arquivos. Quer você esteja trabalhando com arquivos de texto pequenos ou com grandes conjuntos de dados, saber como realizar essa tarefa é importante.

Neste artigo, exploraremos quatro abordagens comuns para ler um arquivo linha por linha em C++: usando ifstream com getline(), a função getline() da biblioteca C, a função fgets() e istream_iterator.

Por Que Ler um Arquivo Linha por Linha

Ler um arquivo linha por linha costuma ser preferível a lê-lo inteiro de uma só vez, especialmente ao lidar com arquivos grandes. Ao processar uma linha por vez, você pode gerenciar o uso de memória de forma eficiente e lidar com arquivos de praticamente qualquer tamanho.

Essa abordagem é particularmente útil para tarefas em que você precisa processar cada linha de forma independente, como a análise de arquivos CSV, o processamento de logs ou a análise de texto.

Aqui está um exemplo de arquivo input.txt que contém um texto de exemplo:

This is a sample input file.
It contains multiple lines of text.
Each line demonstrates a different scenario.
For example, this line contains numbers: 12345.
And this line has special characters: !@#$%^&*().

Vamos usar esse arquivo como entrada para testar os exemplos de leitura de arquivos nas seções seguintes.

Como Ler um Arquivo Linha por Linha em C++ Usando ifstream Com a Função getline()

Quando se trata de ler um arquivo linha por linha em C++, um dos métodos mais simples e mais usados envolve utilizar a classe ifstream em conjunto com a função getline(). Essa abordagem oferece simplicidade e eficiência no tratamento da entrada de arquivos, tornando-se a escolha preferida de muitos desenvolvedores.

A função getline() faz parte da Biblioteca Padrão do C++ e é usada principalmente para ler linhas de fluxos de entrada, como arquivos ou a entrada padrão (cin).

Sua sintaxe é a seguinte:

istream& getline(istream& is, string& str, char delim);

Onde:

  • is: fluxo de entrada do qual os caracteres serão lidos.
  • str: variável string na qual os caracteres extraídos são armazenados.
  • delim: caractere delimitador que marca o fim de cada linha (o padrão é '\n').

A função getline() lê caracteres do fluxo de entrada até encontrar o delimitador especificado ou chegar ao fim do fluxo. Em seguida, ela armazena esses caracteres na variável string fornecida, excluindo o próprio delimitador.

É importante destacar que getline() retorna o fluxo de entrada (is), o que permite encadear várias operações de entrada.

Agora, vamos ver um exemplo que demonstra como ler um arquivo linha por linha usando ifstream com getline() em C++:

#include <fstream>
#include <iostream>
#include <string>

int main() {
  std::ifstream file("input.txt");

  if (!file.is_open()) {
    std::cerr << "Error: Unable to open the file." << std::endl;
    return 1;
  }

  std::string line;

  while (std::getline(file, line)) {
    std::cout << line << std::endl;
  }

  file.close();

  return 0;
}

Neste exemplo, começamos incluindo os arquivos de cabeçalho necessários: <iostream>, <fstream> e <string>. Eles fornecem funcionalidades para entrada/saída, fluxo de arquivos e manipulação de strings, respectivamente.

Em seguida, definimos a função main. Dentro da função main, é criada uma instância de std::ifstream chamada file, que representa o fluxo de arquivo de entrada.

Depois, tentamos abrir o arquivo chamado "input.txt" usando o construtor do arquivo. Se o arquivo não puder ser aberto, uma mensagem de erro é impressa no fluxo de erro padrão (cerr) e o programa termina com um status diferente de zero.

Em seguida, declaramos uma variável string line para armazenar cada linha lida do arquivo. Dentro do loop while, chamamos repetidamente std::getline() com o fluxo de arquivo (file) e a variável string (line) como argumentos.

Essa função lê uma linha do fluxo de arquivo até chegar ao fim da linha ou ao fim do arquivo. Cada linha lida é então impressa no fluxo de saída padrão (cout).

Por fim, depois de ler todas as linhas do arquivo, fechamos o fluxo de arquivo usando o método close() para liberar os recursos do sistema.

Saída:

Ler um arquivo linha por linha em C++ usando ifstream com getline()

Isso demonstra como ler um arquivo linha por linha em C++ de forma eficaz usando ifstream com getline(), fornecendo um método claro e conciso para lidar com operações de entrada de arquivos.

Como Ler um Arquivo Linha por Linha em C++ Usando a Função getline() da Biblioteca C

Além da Biblioteca Padrão do C++, os desenvolvedores de C++ também podem utilizar a função getline() fornecida pela biblioteca C para ler um arquivo linha por linha. Embora essa função funcione de forma ligeiramente diferente, ela oferece uma alternativa viável para lidar com operações de entrada de arquivos.

A função getline() da biblioteca C é usada principalmente para ler linhas de fluxos de entrada, de forma semelhante à sua equivalente na Biblioteca Padrão do C++. Sua sintaxe é a seguinte:

ssize_t getline(char** lineptr, size_t* n, FILE* stream);

Aqui,

  • lineptr: um ponteiro para o buffer no qual a linha será armazenada.
  • n: um ponteiro para a variável que contém o tamanho do buffer (que será redimensionado se necessário).
  • stream: o fluxo de arquivo do qual a linha será lida.

Diferentemente da função getline() da Biblioteca Padrão do C++, a versão da biblioteca C retorna um valor ssize_t que indica o número de caracteres lidos, ou -1 se ocorrer um erro ou se o fim do arquivo for alcançado.

Vamos ver um exemplo que demonstra como ler um arquivo linha por linha usando getline() da biblioteca C em C++:

#include <cstdio>
#include <cstdlib>
#include <iostream>

int main() {
  FILE* file = fopen("input.txt", "r");

  if (!file) {
    std::cerr << "Error: Unable to open the file." << std::endl;
    return 1;
  }

  char* line = nullptr;
  size_t len = 0;

  ssize_t read;
  while ((read = getline(&line, &len, file)) != -1) {
    std::cout << line;
  }

  free(line);

  fclose(file);

  return 0;
}

Começando pelos arquivos de cabeçalho necessários incluídos: <iostream> para operações de entrada/saída, <cstdio> para entrada/saída no estilo C e <cstdlib> para funções de alocação de memória.

Na função main, declaramos um ponteiro FILE* chamado file e tentamos abrir o arquivo "input.txt" no modo de leitura usando a função fopen(). Se o arquivo não puder ser aberto, uma mensagem de erro é impressa e o programa termina com um status diferente de zero.

Em seguida, declaramos um ponteiro de caractere line e uma variável size_t chamada len para armazenar, respectivamente, cada linha lida do arquivo e seu comprimento. Dentro do loop while, chamamos repetidamente getline() com o fluxo de arquivo (file), o endereço do ponteiro line e o endereço da variável len.

Essa função lê uma linha do fluxo de arquivo, aloca memória dinamicamente conforme necessário e armazena a linha no buffer apontado por line. Cada linha lida é então impressa no fluxo de saída padrão (cout).

Depois de ler todas as linhas do arquivo, liberamos a memória alocada dinamicamente para o buffer line usando a função free() e fechamos o fluxo de arquivo usando a função fclose() para liberar os recursos do sistema.

Saída:

Ler um arquivo linha por linha em C++ usando getline() da biblioteca C

Isso demonstra um método alternativo para ler um arquivo linha por linha em C++, aproveitando a função getline() da biblioteca C.

Como Ler um Arquivo Linha por Linha em C++ Usando a Função fgets()

Outro método para ler um arquivo linha por linha em C++ envolve o uso da função fgets(), que faz parte da biblioteca padrão C. Embora fgets() possa parecer menos intuitiva em comparação com as abordagens baseadas em fluxos do C++, ela oferece simplicidade e compatibilidade com bases de código legadas ou cenários em que a entrada/saída no estilo C é preferida.

A sintaxe de fgets() é a seguinte:

char *fgets(char *str, int size, FILE *stream);

Aqui,

  • str: um ponteiro para o array de caracteres (buffer) no qual a linha será armazenada.
  • size: o número máximo de caracteres a serem lidos (incluindo o terminador nulo).
  • stream: o fluxo de arquivo do qual a linha será lida.

A função retorna str em caso de sucesso, ou NULL se ocorrer um erro ou se o fim do arquivo for alcançado.

Vamos prosseguir com um exemplo que ilustra como ler um arquivo linha por linha usando fgets() em C++:

#include <cstdio>
#include <iostream>

int main() {
  FILE* file = fopen("input.txt", "r");

  if (!file) {
    std::cerr << "Error: Unable to open the file." << std::endl;
    return 1;
  }

  char line[256];

  while (fgets(line, sizeof(line), file) != NULL) {
    std::cout << line;
  }

  fclose(file);

  return 0;
}

Neste exemplo, começamos incluindo os arquivos de cabeçalho necessários: <iostream> para operações de entrada/saída e <cstdio> para entrada/saída no estilo C.

Dentro da função main, declaramos um ponteiro FILE* chamado file e tentamos abrir o arquivo "input.txt" no modo de leitura usando a função fopen(). Se o arquivo não puder ser aberto, uma mensagem de erro é impressa e o programa termina com um status diferente de zero.

Em seguida, definimos um array de caracteres line com tamanho de 256 caracteres para armazenar cada linha lida do arquivo. Dentro do loop while, chamamos repetidamente fgets() com o fluxo de arquivo (file), o endereço do array line e o tamanho do array.

Essa função lê uma linha do fluxo de arquivo e a armazena no buffer line. Cada linha lida é então impressa no fluxo de saída padrão (cout).

Depois de ler todas as linhas do arquivo, fechamos o fluxo de arquivo usando a função fclose() para liberar os recursos do sistema.

Saída:

Ler um arquivo linha por linha em C++ usando fgets()

Isso mostra uma abordagem alternativa para ler um arquivo linha por linha em C++. Embora ligeiramente diferente em sintaxe e uso, fgets() oferece uma opção viável para lidar com operações de entrada de arquivos, proporcionando compatibilidade e familiaridade com os paradigmas de programação no estilo C.

Como Ler um Arquivo Linha por Linha em C++ Usando istream_iterator

O istream_iterator oferece uma maneira elegante e moderna de ler dados de fluxos de entrada, incluindo arquivos, tratando o fluxo como uma sequência de elementos. Embora normalmente seja usado para ler dados formatados, como inteiros ou strings, ele também pode ser empregado para ler linhas de um arquivo, tratando cada linha como um elemento string.

Essa abordagem oferece concisão e legibilidade no código, tornando-se uma escolha conveniente para muitos desenvolvedores.

A sintaxe de istream_iterator é a seguinte:

istream_iterator<T> it(istream& is);

Aqui,

  • T: o tipo de dado a ser lido.
  • is: o fluxo de entrada do qual os dados serão lidos.

O construtor de istream_iterator inicializa um iterador (it) para iterar sobre os elementos extraídos do fluxo de entrada (is). Ele é normalmente usado em combinação com os operadores de desreferenciação e incremento de istream_iterator (*it e ++it, respectivamente) para acessar os elementos do fluxo e avançar por eles.

Considere o seguinte exemplo de código, que demonstra como ler um arquivo linha por linha usando istream_iterator em C++:

#include <fstream>
#include <iostream>
#include <iterator>
#include <string>

int main() {
  std::ifstream file("input.txt");

  if (!file.is_open()) {
    std::cerr << "Error: Unable to open the file." << std::endl;
    return 1;
  }

  std::istream_iterator<std::string> it(file);
  std::istream_iterator<std::string> end;

  if (it == end) {
    std::cerr << "Error: Empty file." << std::endl;
    return 1;
  }

  std::cout << *it++;

  while (it != end) {
    std::cout << " " << *it++;
  }
  std::cout << std::endl;

  file.close();

  return 0;
}

Começando pelos arquivos de cabeçalho necessários incluídos: <iostream> para operações de entrada/saída, <fstream> para fluxo de arquivos, <iterator> para operações com iteradores e <string> para manipulação de strings.

Na função main, declaramos um objeto ifstream chamado file e tentamos abrir o arquivo "input.txt". Se o arquivo não puder ser aberto, uma mensagem de erro é impressa e o programa termina com um status diferente de zero.

Em seguida, criamos um istream_iterator chamado it, inicializado com o fluxo de arquivo file, para ler strings do arquivo. Além disso, criamos um iterador de fim de fluxo chamado end para indicar o fim do arquivo.

Dentro do loop while, iteramos sobre o conteúdo do arquivo usando o iterador it até que ele alcance o iterador de fim de fluxo end. Em cada iteração, desreferenciamos o iterador (*it) para obter a linha atual, a exibimos no console e então avançamos o iterador (++it).

Depois de processar todas as linhas do arquivo, fechamos o fluxo de arquivo usando o método close() para liberar os recursos do sistema.

Saída:

Ler um arquivo linha por linha em C++ usando istream_iterator

Isso demonstra um método alternativo para ler um arquivo linha por linha em C++, aproveitando o istream_iterator para tratar o conteúdo do arquivo como uma sequência de strings. Essa abordagem oferece uma solução moderna e concisa para lidar com operações de entrada de arquivos, melhorando a legibilidade e a manutenibilidade do código.

Conclusão

Exploramos vários métodos para ler um arquivo linha por linha em C++, cada um com suas vantagens e adequação dependendo dos requisitos específicos e das preferências do programador. Seja usando a função getline() da Biblioteca Padrão do C++, getline() da biblioteca C, fgets() ou istream_iterator, os desenvolvedores têm uma variedade de opções à disposição.

A função getline() nas bibliotecas C++ e C oferece uma abordagem simples, enquanto fgets() proporciona compatibilidade com a programação no estilo C. Por outro lado, istream_iterator apresenta uma solução moderna e concisa para iterar sobre o conteúdo do arquivo como uma sequência de strings.

Independentemente do método escolhido, o objetivo principal continua o mesmo: ler o conteúdo de um arquivo linha por linha de forma eficiente e precisa. Ao compreender a sintaxe e o funcionamento de cada método, podemos selecionar a abordagem mais adequada para nossos projetos, garantindo um tratamento eficiente de arquivos e uma legibilidade ideal do código.