Jump to content

ler ficheiro e guardar linha a linha num array


goncalomsdias

Recommended Posts

Boa tarde!

Preciso de ler um ficheiro e conseguir guardar os valores de cada linha num array.

O problema é que o ficheiro vai ser bastante grande por isso não posso declarar o tamanho do array.

Já faz algum tempo que não programo em C, por isso estou meio perdido nisto...

#include <stdio.h>
#include <stdlib.h>
int main (void)
{
   FILE *fp;
   char filename[100];
   char* data;
   puts("Insert file name to open.");
   gets(filename);
   fp = fopen(filename,"r");
   fseek(fp, 0L, SEEK_END);
   int sz = ftell(fp);
   //You can then seek back to the beginning:
   fseek(fp, 0L, SEEK_SET);
   data = malloc(sz);
   if(fp==NULL)
   {
       printf("Cant open file! %s\n",filename);
       exit(1);
   }
   else
   {
       // calucate the size of the file.
       fseek(fp, 0L, SEEK_END);
       int sz = ftell(fp);
       //seek back to the beginning:
       fseek(fp, 0L, SEEK_SET);
       data = malloc(sz);
       //fread(data ,sz, 1, fp);
       size_string = strlen(data);
       //printf("%d",&size_string);
       while(fgets(data,sz,fp)!=NULL)
       {

       }
   }
}

Actualmente tenho este código, mas não sei o que fazer para guardar cada linha no array...

Se puderem dar umas dicas ficava muito agradecido.

Edited by pmg
LP adicionada ao GeSHi existente
Link to comment
Share on other sites

Podes ler o ficheiro todo e saber quantas linhas tem e alocar dinamicamente o array.

Ou tambem podes ter o numero de linhas no inicio do ficheiro.

Tambem podes ter um array com um tamanho predefinido e depois se tiver cheio crias outro e copias o valor do array

Por muito mais que que estude só aprendo uma coisa, que ainda tenho muita coisa para aprender.

A beleza de um código está em decompor problemas complexos em pequenos blocos simples.

"learn how to do it manually first, then use the wizzy tool to save time."

"Kill the baby, don't be afraid of starting all over again. Fail soon, learn fast."

Link to comment
Share on other sites

saber o tamanho do ficheiro nunca é indicativo do número de linhas, exemplo

linha 1 bem compridinha\n
linha 2\n
linha 3 ... ui que comprida que ela é ... até chega quase ao fundo aqui da caixa \n

consegues dizer quantas linhas tem este ficheiro só pelo número de bytes ??

se não sabes o número de linhas só tens duas opções:

- declaras um array demasiado grande sabendo que nunca será completamente preenchido

- usas memória dinâmica

IRC : sim, é algo que ainda existe >> #p@p
Link to comment
Share on other sites

declarar um array demasiado grande está fora de questão, porque os ficheiros podem ser mesmo grandes...

Como o pikax disse, não é possível usar o fgets para ler linha a linha, e ao mesmo tempo ter um contador a somar o número de linhas? Com esse número de linhas já é possível saber qual o tamanho que é necessário para o array

Link to comment
Share on other sites

declarar um array demasiado grande está fora de questão, porque os ficheiros podem ser mesmo grandes...

Como o pikax disse, não é possível usar o fgets para ler linha a linha, e ao mesmo tempo ter um contador a somar o número de linhas? Com esse número de linhas já é possível saber qual o tamanho que é necessário para o array

para isso terias de ler o ficheiro 2 vezes ... tu próprio disseste que os ficheiros seriam mesmo grandes ....

deixa-te de malandrices e toca a criar uma lista ligada ou algo do género ...

typedef struct ListaElem {
 char * line;
 struct ListaElem * next;
} ListaElem;

typedef struct Lista {
 size_t quantity;
 ListaElem * first;
 ListaElem * last;
} Lista;
IRC : sim, é algo que ainda existe >> #p@p
Link to comment
Share on other sites

declarar um array demasiado grande está fora de questão, porque os ficheiros podem ser mesmo grandes...

que tamanhos estas a falar??

Como o pikax disse, não é possível usar o fgets para ler linha a linha, e ao mesmo tempo ter um contador a somar o número de linhas? Com esse número de linhas já é possível saber qual o tamanho que é necessário para o array

sim podes fazer isso.

Ja' agora, porque que nao usas uma lista??

Por muito mais que que estude só aprendo uma coisa, que ainda tenho muita coisa para aprender.

A beleza de um código está em decompor problemas complexos em pequenos blocos simples.

"learn how to do it manually first, then use the wizzy tool to save time."

"Kill the baby, don't be afraid of starting all over again. Fail soon, learn fast."

Link to comment
Share on other sites

O código que postaste já faz isso (duas vezes): obtém o tamanho do ficheiro com fseek/ftell, aloca um bloco de memória desse tamanho + 1, preenche-o com um fread do ficheiro todo e mete um 0 no final do bloco, usa a função strtok para partir o bloco em linhas (usando os caracteres \r e \n como separadores) e guarda os ponteiros para cada linha (devolvidos pela strtok, se o comprimentto dessa string não fôr 0) num outro bloco de memória (array de ponteiros), que podes aumentar com o realloc quando estiver cheio (aumenta-o em blocos, não ponteiro a ponteiro).

Neste caso irás gastar apenas um ponteiro por cada linha (4 bytes), para além da memória necessária para as linhas em si.

  • Vote 1
Link to comment
Share on other sites

neste momento tenho 1 ficheiro com mais de 10000 linhas. Mas o objectivo é ficar preparado para lidar com ficheiros maiores que isso, e com mais que 1 ficheiro desses.

O código que postaste já faz isso (duas vezes): obtém o tamanho do ficheiro com fseek/ftell, aloca um bloco de memória desse tamanho + 1, preenche-o com um fread do ficheiro todo e mete um 0 no final do bloco, usa a função strtok para partir o bloco em linhas (usando os caracteres \r e \n como separadores) e guarda os ponteiros para cada linha (devolvidos pela strtok, se o comprimentto dessa string não fôr 0) num outro bloco de memória (array de ponteiros), que podes aumentar com o realloc quando estiver cheio (aumenta-o em blocos, não ponteiro a ponteiro).

Neste caso irás gastar apenas um ponteiro por cada linha (4 bytes), para além da memória necessária para as linhas em si.

Quando chegar a casa ja vou tentar isso e depois digo algo.

Link to comment
Share on other sites

falame em Bytes, KB, MB e GB, o numero de linhas cheja a ser um pouco relativo, se tiveres um caracter por linha seria um ficheiro de 10000Bytes que e' um pouco menos de 10~9KB, achas isso grande??

Por muito mais que que estude só aprendo uma coisa, que ainda tenho muita coisa para aprender.

A beleza de um código está em decompor problemas complexos em pequenos blocos simples.

"learn how to do it manually first, then use the wizzy tool to save time."

"Kill the baby, don't be afraid of starting all over again. Fail soon, learn fast."

Link to comment
Share on other sites

nao concegues encaixar 10MB na memoria???

se tu declares um array gigante!

char *array[9999999];

este array vazio ira' ocupar 9999999*sizeof(char*)

Por muito mais que que estude só aprendo uma coisa, que ainda tenho muita coisa para aprender.

A beleza de um código está em decompor problemas complexos em pequenos blocos simples.

"learn how to do it manually first, then use the wizzy tool to save time."

"Kill the baby, don't be afraid of starting all over again. Fail soon, learn fast."

Link to comment
Share on other sites

Eu tenho outra sugestao, se for possivel:

em vez de leres o ficheiro todo para um array e tratares os dados como um todo, les e tratas cada linha isoladamente num ciclo.

ou seja, em vez de

// pseudo codigo
while (fgets(linha)) { strcpy(array[nlinhas++], linha); }
for (i = 0; i < nlinhas; i++) { tratalinha(array[i]); }

experimenta assim

// pseudo codigo
while (fgets(linha)) { tratalinha(linha); }
Edited by pmg

What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Link to comment
Share on other sites

Eu tenho outra sugestao, se for possivel:

em vez de leres o ficheiro todo para um array e tratares os dados como um todo, les e tratas cada linha isoladamente num ciclo.

ou seja, em vez de

// pseudo codigo
while (fgets(linha)) { strcpy(array[nlinhas++], linha); }
for (i = 0; i < nlinhas; i++) { tratalinha(array[i]); }

experimenta assim

// pseudo codigo
while (fgets(linha)) { tratalinha(linha); }

Isso acho que não vai dar, porque depois vou precisar de manipular uma das colunas dentro da linha, para todas as linhas...

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.