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; }
pra que serve o
——
*ptr= ”;
——
na penúltima linha da pegalinha() ?
fim de string, é o mesmo que *ptr = ” ou *ptr = (char) 0.
Aspas simples vazias?
Não aparece caracter algum para mim dentro das aspas simples, apenas:
*ptr = ”;
que não compila.
Morreu o site ?
Ops, era para ser
*ptr = ”, o blog deve ter comido a barra invertida.
Uh, as aspas estão vazias de novo. :P
Talvez tenha que colocar duas barras invertidas:
*ptr = ‘\’;
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.
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).
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?
Eduardo, você pode lê-lo em bloco se quiser, e programar o reconhecimento de limite. A eficiência seria virtualmente a mesma.
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. :)
Pode ser assim também :D : http://geekrepublic.wordpress.com/2007/09/04/ler-linhas-de-um-arquivo-de-texto-de-maneira-portavel/