Newsgroup: it.comp.lang.c
Titolo: lettura files e array dinamici

Ciao a tutti, Sto studiando la gestione dei files e ho scritto questo 
piccolo programma:
#include<stdio.h>
#include<stdlib.h>
main()
{
  char lettura[10000]; //questo array serve per contenere i caratteri 
letti dal file
  FILE *puntatore; //puntatore a file: verra' passato come parametro 
alle funzioni che operano sui file
  int conta_caratteri;
  int i;
  puntatore=fopen("passare array a funzione.txt","r"); //apro un file di 
testo esistente in sola lettura
  //dopo aver copiato i caratteri del file letto
//la funzione fread aggiunge \0 e trasforma l'array in stringa
do
{
  conta_caratteri=fread(lettura,1,10000,puntatore);
  if(conta_caratteri!=0)
  {i=conta_caratteri;} //traferisco il valore del numero di caratteri in 
una variabile d'appoggio//
                       //fino a che non diventa zero (fine file)
}while(conta_caratteri!=0);
  fclose(puntatore); //chiudo il file
  system("cls");
  printf("\n\nil file contiene %d caratteri",i);
  printf("\n\n");
  puts(lettura);
  getchar();
}
Però mi chiedevo: dato che non posso sapere a priori qual è la 
dimensione del file che voglio leggere, e quindi non so quanto debba 
essere grande l'array per contenerlo, è possibile in C creare un array 
dinamico?  Grazie.

 è possibile in C creare un array dinamico?
La risposta "breve" è NO! La risposta più lunga prevede l'uso di 
realloc() per allocare un blocco di memoria di dimensione sempre 
maggiore da usare come array.
Comunque, nel tuo caso (contare quanti caratteri ci sono in un file) ti 
serve un array: usa fgetc() e leggi il file un carattere alla volta.
Altrimenti puoi usare fseek() per spostarti alla fine del file e ftell() 
per ottenere la posizione (ma il risultato non è garantito) oppure usare 
la stat() (ma non è C standard).
Qalche osservazione:
  - Se ti interessa la lunghezza del file devi aprire il file con "rb" e 
non con "r" altrimenti potresti avere problemi con gli "a capo" dei file 
in formato DOS (se invece vuoi solo sapere il numero di "caratteri" puoi 
usare anche "r").
  - Dopo la fopen() controlla di aver aperto veramente il file. Il fatto 
il file esista non vuol dire che la fopen() non possa fallire
  - Usare la fread va anche bene ma se il tuo file è piu' lungo 
dell'array dovresti mettere i += conta_caratteri altrimenti memorizzi 
solo la dimensione dell'ultimo blocco letto. (ovviamente devi 
inizializzare "i" prima).
  - Dopo la fread() dovresti usare la feof() (o la ferror()) per capire 
se hai veramente raggiunto la fine del file o se c'e' stato un errore in 
lettura.
  - main puo' essere:
       int main(void);
    oppure
       int main(int argc, char *argv[]);
    ma non:
       main();
  - I commenti con // sono solo C99 (ed ho un'avversione speciale per i 
commenti "alla C++", ma de gustibus ...)
Se ridai un'occhiata al tuo programma sono sicuro che troverai altri 
spunti per migliorarlo.
R.D.

 
Ops! Intendevo:
    nel tuo caso [...] NON ti serve un array:
R.D

Remo D. ha scritto:

Grazie per la risposta, ma ci sono cose che non capisco (premetto che 
sono alle prime armi): perchè dici di leggerlo un carattere alla volta? 
Io voglio che il contenuto del file venga salvato in un contenitore 
(come un array appunto) per poter poi essere manipolato (non so ancora 
per quale scopo, è solo un'idea per adesso). Per quale motivo non posso 
scrivere main()? E' solo una questione di stile? Mi sembra che debba 
essere obbligatoriamente (void) solo in C++ (linguaggio che ancora non 
ho studiato). int argc, char *argv[] ho letto serve per i tipi derivati 
dei puntatori, giusto? Per quanto riguarda i commenti: //commento// 
/*commento*/ come dici tu è solo questione di preferenze :-)

 dinamico?  Grazie.
Se il file è un file regolare, puoi saperne la dimensione. Un metodo un 
po' brutale è quello di usare "fseek", "ftell" (cercane la 
documentazione). Una volta che sai quanto spazio ti serve, puoi allocare 
dinamicamente l'array. Il comando che ti serve è "malloc".
ciao,
	E.

 /*commento*/ come dici tu è solo questione di preferenze :-)
Ed anche di compilatore. // vale solo per i compilatori C99 (o per 
quelli C89 che che lo avevano già implementato come estensione non 
standard). Comunque sì, è solo l'attaccamento di un vecchietto alle 
properie abitudini :)
R.D.

 dinamico?
Sě, devi usare l'allocazione dinamica. Ovviamente trattandosi di una
lettura e quindi di una crescita progressiva dell'array, puoi allocare
memoria a blocchi sempre piů grandi. Una tecnica usata spesso (anche con
certe implementazioni di std::vector in C++) č quella di far crescere
l'array in maniera ammortizzata, diminuendo il numero di realloc()
successive. Per esempio: preallochi 5 caratteri, quando esaurisci il
riempimento ne allochi 5*2 = 10, quindi 10*2 = 20, ecc... ecc...
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 riempimento ne allochi 5*2 = 10, quindi 10*2 = 20, ecc... ecc...
In realtà credo che molte implementazioni di malloc/realloc facciano già 
da sole questo. Cioè malloc ti riserva sempre uno spazio che è una 
potenza di 2, e quindi il realloc non deve far niente finchè lo spazio 
richiesto non raddoppia.
E.

da sole questo.
Credo proprio di sì.