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.
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!
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.
Preste atenção! Existe um memory leak feio no seu código. Verifique bem o fonte antes de postar algo.
F.S.:
Não vejo leak nenhum no código. Pode explicar onde você está vendo um?
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.
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.
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
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
estou precisando fazer um compilador em C até a analise sintática, você pode me ajudar?