Newsgroup: it.comp.os.linux.development
Titolo: Leggere un file di stringhe

Salve,
scusate se sono magari ot, dovrei sviluppare un piccolo programmino in C 
che mi consenta di leggere file di stringhe, una stringa su ogni riga, e 
memorizzare le stringhe in un array, ma a priori non so quante stringhe 
ci sono nel file. Ma anche sapendolo come faccio a dimensionare un array 
dinamico ? Con i puntatori ?  Mi date una idea da dove e come iniziare ?
Francesco
-- 
http://www.itp-news.com

 dinamico ? Con i puntatori ?  Mi date una idea da dove e come iniziare ?
1 - fai una lista 
2 - un char ** che reallochi in caso di bisogno
3 - decidi che a priori il numero di stringhe non potrà mai essere >
NMAX e dichiari un vettore lungo NMAX
(3) puo' essere conveniente solo per NMAX piccoli,
 dopo io scelglierei (2).
 (1) scomoda strutture  e algoritmi inutilmente complicati per un
problema di questo tipo

 problema di questo tipo
Il metodo 1 ed il metodo 3 li avevo pensato anche io, e sono quelli che 
saprei già implementare e che ho già implementato varie volte, ma non so 
come partire con il metodo 2. In effetti mi servirebbe un piccolo 
esempio. In rete ho trovato poco e molto poco chiaro. 
Avevo pensato a delle liste concatenate, ma poi mi serve accedere in 
maniera diretta alle stringhe, la cui posizione viene scelta da un numero 
pseudo-casuale.
Francesco
-- 
http://www.itp-news.com

 Francesco
affrontare il problema implica comunque la capacita' di acquisire in
memoria tutto il file, quindi i controlli preliminare su tale
possibilita' sono da sottintendersi.
1) scegli un linguaggio interpretato ad alto livello con memory-manager
  che faccia tutto per te (come ad esempio Perl)
 
  open $filehandler, "<fileditesto.txt";
  @linee = <$filehandler>;
  # ora nell' array @linee c' e' una entry per ogni linea
  # nel file fileditesto.txt
2) senza riscrivere tutto un memorimanager in C, fai uno stat
   del file da acquisire per saperne le dimensioni in bytes:
 
   man 2 stat
   il campo st_size e' quello che ti serve.
   con la funzione malloc delle libc allochi dinamicamente tutta la
   memoria che ti serve per contenerlo
   man 3 malloc
   e con letture raw con read
   man 2 read
   lo bevi tutto in tale memoria allocata.
   ora ti manca di dividerlo logicamente il linee.
   puoi allocare dinamicamente con malloc un array di puntatori a char
   ma per allocarlo una sola volta devi prima sapere quanti '/n' ci sono
   nel file (inoltre puoi decidere che l' ultima linea, quella prima di
   EOF possa non essere terminata da '/n' quindi con 2 passate.
   con la prima conti le linee, poi allochi un array di
   nlinee * sizeof(char*) e con la seconda passata ad ogni posizione
   metti l' indirizzo che char di inizio linea (ricercando ancora i 'n')
   a quel punto l' accesso random alle linee lo fai attraverso l' array
   di puntatori a char allocato dinamicamente.
   se non vuoi fare le due passate, o allochi gia' un array capace di
   contenere tutte le possibili linee per quel file ( in un file di
   1000000 di bytes possono esserci 1000000 di 'n' quindi, occhio )
   o riallochi periodicamente, ad esempio con realloc, ma questo puo'
   dare altri problemi, in quanto implica un memory manager di sistema
   evoluto, che comunque potrebbe dar luogo a frammentazione dello heap
   (ma chi se ne frega? :) )
Se proprio lo devi fare in C e senza librerie aggiuntive consiglio
le 2 passate.
ciao
Roberto.
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 Roberto.
Si, devo svilupparlo in C. Ti ringrazio per i tuoi consigli.
Francesco
-- 
http://www.itp-news.com

 Si, devo svilupparlo in C. Ti ringrazio per i tuoi consigli.
Ti consiglio una cosa tipo (con raddoppio delle dimensioni del container 
tipo STL):
	int size = 2; // falso ma forziamo un'allocazione al primo giro
	int lines = 0;
	char buffer[1024];
	char **arr = NULL;
	while (!feof(file)) {
		if (fgets(file, buffer, sizeof(buffer))) {
			if (lines == 0 || lines == size) {
				size *= 2;
				arr = realloc(arr, size * sizeof(char *));
			}
	// da aggiungere codice che strippa \n \r e simili se necessario
			arr[lines] = strdup(buffer);
			lines++;
		}
	}
 

 	while (!feof(file)) {
classico errore da principiante.  dalla FAQ list di comp.lang.c, Q/A
12.2:
Q: Why does the simple line-copying loop
   while(!feof(infp)) {
     fgets(buf, MAXLINE, infp);
     fputs(buf, outfp);
   }
copy the last line twice?
A: In C, end-of-file is only indicated AFTER an input routine has
tried to read, and failed. (In other words, C's I/O is not like
Pascal's.) Usually, you should just check the return value of the
input routine:
	while(fgets(buf, MAXLINE, infp) != NULL)
		fputs(buf, outfp);
In virtually all cases, there's no need to use feof at all. (feof, or
more likely ferror, may be useful after a stdio call has returned EOF
or NULL, to distinguish between an end-of-file condition and a read
error.)
References: K&R2 Sec. 7.6 p. 164
            ISO Sec. 7.9.3, Sec. 7.9.7.1, Sec. 7.9.10.2
            H&S Sec. 15.14 p. 382 
-- 
Maurizio Loreti                         
http://www.pd.infn.it/~loreti/mlo.html
Dept. of Physics, Univ. of Padova, Italy              ROT13: 
ybe...@cq.vasa.vg

 classico errore da principiante.  dalla FAQ list di comp.lang.c, Q/A
Leggi il resto del codice prima di commentare una linea :) Quel codice 
non era testato, quindi poteva avere errori, ma sicuramente non aveva 
quel problema e sicuramente non sono principiante :)
Bye,
  Gabry

Ho provato ad applicare il tuo consiglio, modificando nel modo seguente 
il tuo codice
while ((scanf("%s",&verbo)!=EOF))
{
printf("\n Verbo: %s",verbo);
lines++;
verbi = realloc(verbi, strlen(verbo)*lines*sizeof(char *));
verbi[lines] = verbo;
printf("\n Verbo: %s %s ",verbi[lines-1],verbi[lines]);
printf("\n Riga %d",lines);
printf("\n i=%d",i);
n++;
}
printf("\n Linee :%d\n",lines);
printf("\n Verbi caricati :\n");
for (i=1;i<=lines;i++)
printf("\n i=%d Verbo:%s",i, verbi[i]);
}
Ma l'ultimo ciclo mi stampa solo l'ultima riga dell'array
-- 
http://www.itp-news.com