#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
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.
> Grazie per la risposta, ma ci sono cose che non capisco
> [...] 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
Dal tuo esempio sembrava che ti servisse solo sapere la dimensione del
file. Per caricarlo in memoria puoi usare uno degli altri sistemi a cui
ho accennato:
- leggi un carattere per volta ed allochi la memoria con realloc()
(ti serviranno due "contatori", uno per la dimensione corrente dell'area
che hai allocato ed uno per il numero di caratteri che hai letto).
- usi fseek() per andare in fondo al file ed ftell() per sapere
quanto è lungo. Non ci sono garanzie di correttezza!
- usi stat() per ottenere le informazioni che ti servono. Non portabile.
- leggi il file un carattere alla volta con fgetc() per ottenere la
lunghezza dei file (attenzione a "rb") allochi la memoria che ti serve
con malloc() e leggi tutto il file in una volta sola con fread()
> Per quale motivo non posso scrivere main()? E' solo una questione di stile?
Non solo. In C è buona norma rispettare i prototipi delle funzioni. Nel
tuo caso sono sicuro che non ci sarebbe nessun problema ma perchè
andarseli a cercare?
> int argc, char *argv[] ho letto serve per i tipi derivati
> dei puntatori, giusto?
argc e argv servono per accedere ai parametri che passerai sulla linea
di comando. Supponendo che il tuo programma si chiami "leggifile" potrai
passargli il nome del file da leggere in questo modo:
leggifile miofile.txt
argv[1] punterà a "miofile.txt".
> Per quanto riguarda i commenti: //commento//
> /*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.
> 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?
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
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.
>In realtà credo che molte implementazioni di malloc/realloc facciano già
>da sole questo.
Credo proprio di sì.