Palavras-chave: C, arquivo texto, linhas, leitura, getline
Como dito num post anterior, a glibc possui uma função para ler linhas de comprimento arbitrário de um arquivo texto. Mas como esta função é especifica a glibc, alguns leitores pediram uma versão que faça o mesmo em qualquer sistema. Uma das muitas formas de fazer isto é:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *pegalinha(FILE *f, char **buffer, size_t *buflen)
{
char *ptr;
char *tmp;
int c;
if (!*buffer || !*buflen)
{
*buflen= 32;
*buffer= (char*)malloc(*buflen);
if (!*buffer)
return NULL;
}
ptr= *buffer;
while ((c= fgetc(f)) != EOF) {
*ptr++= c;
if (c == '\\n') break;
if (ptr - *buffer >= *buflen-1)
{
// aumenta o buffer um pouco mais
tmp= (char*)realloc(*buffer, *buflen+32);
if (!tmp)
return NULL;
// atualiza ptr para o caso do novo buffer estar em outro lugar
ptr= tmp + (ptr - *buffer);
*buflen+= 32;
*buffer= tmp;
}
}
*ptr= 0;
return c==EOF ? NULL : *buffer;
}
int main(int argc, char **argv)
{
FILE *file;
char *linha= NULL;
size_t tamlinha= 0;
if (argc != 2) { printf("%s \\n", argv[0]); exit(1); }
if (!(file= fopen(argv[1], "r"))) { perror(argv[1]); exit(1); }
while (pegalinha(file, &linha, &tamlinha))
{
printf("%i:%s", tamlinha, linha);
}
if (linha)
free(linha);
fclose(file);
return 0;
}







13 comments
Comments feed for this article
15 abril 2007 às 16:55
eljunior
pra que serve o
——
*ptr= ”;
——
na penúltima linha da pegalinha() ?
24 abril 2007 às 13:26
Alexandre
fim de string, é o mesmo que *ptr = ” ou *ptr = (char) 0.
24 abril 2007 às 13:42
Eduardo Habkost
Aspas simples vazias?
Não aparece caracter algum para mim dentro das aspas simples, apenas:
*ptr = ”;
que não compila.
30 abril 2007 às 11:24
cezeiro
Morreu o site ?
9 maio 2007 às 0:54
Alfredo Kojima
Ops, era para ser
*ptr = ”, o blog deve ter comido a barra invertida.
9 maio 2007 às 13:10
Eduardo Habkost
Uh, as aspas estão vazias de novo. :P
Talvez tenha que colocar duas barras invertidas:
*ptr = ‘\’;
20 maio 2007 às 14:45
Anonymous
Hum, parece meio óbvio mas é possível chamar o fgets() várias vezes. Se uma nova linha não foi encontrada, chama realloc no buffer antes de cada chamada nova do fgets(). Dependendo do tipo de uso, pode até manter em buffers separados mesmo.
6 agosto 2007 às 13:46
Reign of Erebus
Se a intenção é ler o arquivo inteiro, separando linha por linha, porque simplesmente não copiá-lo para uma string e repartí-lo com strtok()? Seria mais eficiente que com realloc() (teoricamente).
6 agosto 2007 às 16:07
Eduardo Habkost
Reign of Erebus: você não vai querer ler todo o conteúdo do arquivo pra memória. E se seu arquivo tiver vários gigabytes?
21 agosto 2007 às 11:54
Reign of Erebus
Eduardo, você pode lê-lo em bloco se quiser, e programar o reconhecimento de limite. A eficiência seria virtualmente a mesma.
21 agosto 2007 às 12:29
Eduardo Habkost
E se a linha for maior que o tamanho de bloco que você escolheu? :)
A idéia da função apresentada é facilitar a leitura de linha de tamanho arbitrário sem maiores complicações e sem limites arbitrários.
Sempre há espaço para otimização, claro. Mas “otimização prematura é a raiz de todo o mal”, como costumam dizer. :)
4 setembro 2007 às 15:15
Ler linhas de um arquivo de texto de maneira portável « Geek Republic
[...] Arquivado em: C ANSI, Programação, Geek stuff, C — Reign of Erebus @ 15h15m Inspirado neste post, resolvi fazer minha própria função para ler linhas de um arquivo de maneira portável em C [...]
4 setembro 2007 às 15:34
Reign of Erebus
Pode ser assim também :D : http://geekrepublic.wordpress.com/2007/09/04/ler-linhas-de-um-arquivo-de-texto-de-maneira-portavel/