C: Ler linhas de um arquivo texto

Palavras-chave: C, arquivo texto, fgets, linhas de comprimento arbitrário

O método típico para se ler um arquivo texto linha a linha é usando a função fgets() com um buffer estático. O problema é que nem sempre sabemos qual será o comprimento máximo das linhas e, de acordo com a Lei de Murphy, chutar um tamanho “grande o suficiente” pode não ser o suficiente na prática. Além da possibilidade de abusos ou conteúdo malicioso quando o arquivo é fornecido pelo usuário.

A maneira “correta” de se fazer isso é um pouco trabalhosa, mas felizmente a glibc possui a pouca conhecida função getline(). Esta função toma um buffer dinâmico e irá redimensioná-lo se necessário. É uma função específica da glibc, então se seu programa irá rodar em outras plataformas, não a utilize.

Exemplo:

#define _GNU_SOURCE // necessário porque getline() é extensão GNU
#include <stdio.h>
#include <stdlib.h>
int main()
{
  FILE *f= fopen("teste.txt", "r");
  size_t len= 100; // valor arbitrário
  char *linha= malloc(len);

if (!f)
  {
    perror("teste.txt");
    exit(1);
  }
  while (getline(&linha, &len, f) > 0)
  {
    printf("%s", linha);
  }
  if (linha)
    free(linha);
  fclose(f);
  return 0;
}

É uma pena que não seja uma função portável, mas é algo que pode economizar algumas linhas de código e neurônios quando escrevemos xu^Wprograminhas descartáveis em C.

This entry was posted in C. Bookmark the permalink.

9 Responses to C: Ler linhas de um arquivo texto

  1. Eu says:

    Olá! :)

    Gostei da dica, mas gostaria de propor um outro post: se no caso eu não quiser usar a função getline() e quisesse o meu código mais portável possível, como seria “a maneira correta” de ler o arquivo?

    Agradeço a sua atenção e parabéns pela dica!

  2. R4F43L says:

    Tem algum jeito de fazer o getline funcionar em windows?
    Se nao, tambem tenho interesse em saber qual seria a “maneira correta trabalhosa” de se fazer isso .

    Obrigado.

  3. F. S. says:

    Preste atenção! Existe um memory leak feio no seu código. Verifique bem o fonte antes de postar algo.

  4. F.S.:

    Não vejo leak nenhum no código. Pode explicar onde você está vendo um?

  5. char *linha= malloc(len);

    if (!f)
    {
    perror(“teste.txt”);
    exit(1);
    }

    vc não liberou “linha”, mas sendo que é um “exit(1)”, não considero um leak também.

  6. F. S. says:

    Não basta você assumir que o vazamento não tem valor simplesmente porque tem um exit(), porque o primeiro descuidado que for utilizar este código trocará o exit() por um return.

    Outra coisa: é desnecessário a alocação manual feita com a variável linha, pois o getline() faz isto automaticamente. Simplesmente inicialize a variável com o valor NULL e tudo fica mais simples. KISS.

    • Daniel says:

      e ai F.S. .. jah faz um tempo q postaram isso aki neh!? .. rsrsr.. mas eu precisei do código e fui testar.. o fato é q eu fiz com a variável oq vc disse, mas não funcionou do seu jeito:
      char *linha = malloc(len); –> (deu certo)
      char *linha = NULL; –> (não deu)
      char *linha; –> (não deu)
      char linha; –> (não deu)
      char linha = NULL; –> (não deu)

      era soh pra informar .. :-b

      Abraço :D

      • Daniel says:

        soh uma correção .. a segunda linha (char *linha = NULL;) tambem deu certo.

        de qq forma, se vc criar uma variável comum não dá certo .. tem que ser um ponteiro :)

        :D

  7. Iury Salino says:

    estou precisando fazer um compilador em C até a analise sintática, você pode me ajudar?

Comments are closed.