PDA

View Full Version : [C] ho bisogno di un consiglio


welfi
06-10-2007, 16:23
salve a tutti, dovrei, dato un file di testo con tot parole (prese da un articolo di giornale, o da un libro, non importa), fare in modo da prendere tutte le parole, e poi ordinarle in ordine alfabetico..tutto questo in C.

Mi sono bloccato sulla funzione per dividete tutto il testo in parole, per poi prendere le singole parole ed ordinarle in ordine alfabetico, oppure in ordine di ehm...come si dice quando una parola compare più volte..vabbè avete capito :D!!!. Considero una parola separata dall'altra dallo spazio (gli altri caratteri tipo !?< . ecc non li considero per ora).

io pensavo di metterli in un array, ma ce ne vorrebbe uno per ogni parola...oppure pensavo alle liste, ma non sò bene come implementare il tutto.

Potreste darmi una mano??? Non voglio il codice scritto in C, perchè voglio farlo da solo, ma vorrei un piccolo aiuto su come poter procedere!

grazie

andbin
06-10-2007, 16:32
salve a tutti, dovrei, dato un file di testo con tot parole (prese da un articolo di giornale, o da un libro, non importa), fare in modo da prendere tutte le parole, e poi ordinarle in ordine alfabetico..tutto questo in C.Per la lettura delle parole potresti usare fscanf, ad esempio. Per memorizzarle potresti usare un array espandibile (lo riallochi dinamicamente). Per l'ordinamento ... dipende, potresti implementare il classico bubble sort o usare la qsort().

welfi
06-10-2007, 16:42
Per la lettura delle parole potresti usare fscanf, ad esempio. Per memorizzarle potresti usare un array espandibile (lo riallochi dinamicamente). Per l'ordinamento ... dipende, potresti implementare il classico bubble sort o usare la qsort().

sbagliavo sempre, usando un array di char, infatti qui ogni carattere va in un indice, e non posso associare ad ogni indice dell'array una stringa...invece devo fare un array di int:

a[0]"casa"
a[1] = "mare"..

ecc...non avevo capito nulla sugli array di stringhe allora :(

e nel caso volessi implementarlo con lista?

andbin
06-10-2007, 16:49
sbagliavo sempre, usando un array di char, infatti qui ogni carattere va in un indice, e non posso associare ad ogni indice dell'array una stringa...invece devo fare un array di int:No no alt.

Se intendi usare un array di stringhe (e non altre strutture dati come le liste), dovresti fare "un array di puntatori a char", in cui ogni puntatore punta ad una stringa, il cui spazio di memoria va allocato appositamente.

Bisogna vedere poi se vuoi realizzare un array di una dimensione massima prefissata (più semplice) o un array "espandibile" da (ri)allocare a runtime (meno facile).

Se fisso, si può fare:

char *stringhe[500]; /* 500 stringhe */

Se riallocabile:

char **stringhe;

ma va (ri)allocato a runtime.

stringhe = (char**) malloc (500 * sizeof (char*));

se non basta, a runtime si fa:

stringhe = (char**) realloc (stringhe, 1000 * sizeof (char*));

Tutto questo è solo per allocare lo spazio per i puntatori, non per i caratteri delle stringhe. Per ogni stringa che leggi, allocherai memoria sufficiente, ci copierai la stringa e assegnerai il puntatore ad un elemento dell'array.

welfi
06-10-2007, 17:01
allora mi metto a ripetere un po gli array di puntatori....ma per le liste anche dovrei usare gli array? tipo ogni elemento della lista dovrebbe avere una parola. ora questa parola o viene memorizzata in un array di int (come pensavo di fare) oppure in un array di puntatori..sbaglio?

welfi
06-10-2007, 17:07
nel frattempo ti posto quello che ho fatto fin'ora, con gli array di int, che sembra più semplice (poi lo implementerò anche con gli altri casi);

Nella funzione, dove c'è l'if, mi manca un metodo per inserire caratteri di vlta in volta, esempio se c non è uno spazio, mette il carattere in a, se il succ. carattere non è uno spazio, vuol dire che la parola non è finita e lo deve aggiungere ancora ad a con lo stesso indice del carattere precedente, finchè nn trova lo spazio e la parola risulta finita.

void dividi_in_parole(FILE *fp, int a[] ){
int *stringa;
int c, i = 0;

do{
c = getc(fp);
if (c != 32)
{
;
}
else
{i++;}

}while (c != EOF);


}


int main(int argc, char *argv[])
{
FILE *fp;
int array_parole[500] ={'0'};

fp = fopen("/home/peppe/Desktop/file.txt", "r");

dividi_in_parole(fp, array_parole);


fclose(fp);
return EXIT_SUCCESS;
}

andbin
06-10-2007, 17:12
allora mi metto a ripetere un po gli array di puntatori....ma per le liste anche dovrei usare gli array? tipo ogni elemento della lista dovrebbe avere una parola. ora questa parola o viene memorizzata in un array di int (come pensavo di fare) oppure in un array di puntatori..sbaglio?array di int?? Non vedo a cosa ti possa servire....

Qui hai diverse soluzioni: o usi un array di puntatori a char o usi una qualche altra struttura dati come una lista linkata.

Per la lista linkata dovresti fare una piccola struttura (struct) che contiene il tuo dato (e qui puoi/devi decidere come gestire lo spazio per i caratteri) e un puntatore all'elemento successivo.

Però nota che se devi poi ordinare il tutto, una lista linkata è meno semplice da ordinare rispetto ad un array.

Un esempio basilare di gestione di una lista linkata l'ho fatto di recente in <questa> (http://www.hwupgrade.it/forum/showthread.php?t=1526774) discussione.

andbin
06-10-2007, 17:14
void dividi_in_parole(FILE *fp, int a[] ){
int *stringa;
......No no no. Lascia perdere gli int perché sei sulla strada completamente sbagliata.

welfi
06-10-2007, 17:17
ti ringrazio molto per i consigli!!! inizio a studiarmi gli array di puntatori e inizio a implementare qualcosa...poi passo allo studio delle liste link

nel caso posto di nuovo :D

welfi
06-10-2007, 17:40
ehm, posso fare un altra domandina??? io ho questo file di testo, ma come faccio a caricare, ad esempio in una variabile "stringa", una parola letta dal file e non un singolo carattere?(per poi metterla nell'array di puntatori)???

oppure sapendo come caricare un singolo carattere alla volta(usando getc) come li metto tutti insieme finchè non trovo lo spazio (carattere 32)??

andbin
06-10-2007, 19:36
ehm, posso fare un altra domandina???Certo, il forum è fatto per questo.

io ho questo file di testo, ma come faccio a caricare, ad esempio in una variabile "stringa", una parola letta dal file e non un singolo carattere?(per poi metterla nell'array di puntatori)???Prova questo semplice programmino:
#include <stdio.h>

int main (void)
{
FILE *f;
char buf[101];

if ((f = fopen ("un_file_di_testo.txt", "r")) != NULL)
{
while (fscanf (f, "%100s", buf) == 1)
printf ("[%s]\n", buf);

fclose (f);
}

return 0;
}Legge dal file e stampa ogni singola parola mettendola tra [ ]. Le parole devono essere al massimo di 100 caratteri, la lunghezza massima è determinata dallo specificatore di formato nella fscanf.

Nota che 'buf' è uno solo e contiene di volta in volta l'ultima parola letta. Per tale motivo non si dovrebbe mettere nell'array l'indirizzo di buf. Per ogni parola, devi determinarne la lunghezza, allocare dinamicamente della memoria (e nota bene, va allocato 1 carattere in più per il nullo finale), poi copiare in questa area la stringa e a quel punto puoi assegnare nell'array l'indirizzo di questa area.

welfi
07-10-2007, 10:02
conosco fscanf, ma credevo che leggesse dal file, come hai scritto tu, 100 CARATTERI, invece legge un massimo di 100 caratteri, ma restituisce ogni volta una stringa delimitata dallo spazio!!!! cavolo, non l'ho trovata scritta da nessuna parte questa ottima utilità di fscanf!!!

andbin
07-10-2007, 10:48
non l'ho trovata scritta da nessuna parte questa ottima utilità di fscanf!!!A dire il vero dovrebbe essere ben stampata e documentata su tutte le reference serie (che non siano il manuale delle giovani marmotte...)

La documentazione del VC++ dice:

scanf Width Specification
width is a positive decimal integer controlling the maximum number of characters to be read from stdin. No more than width characters are converted and stored at the corresponding argument. Fewer than width characters may be read if a white-space character (space, tab, or newline) or a character that cannot be converted according to the given format occurs before width is reached.

welfi
07-10-2007, 10:59
nel mio in italiano non c'è..lo devo cambiare! visto che siamo in tema, mi puoi consigliare un buon libro (se proprio non c'è in italiano va bene anche inglese) di C fatto bene però :D

cmq credo di essere arrivato a buon punto, ho fatto in modo di dividere le parole da un testo qualunque, togliendo eventuali punteggiature dopo la parola (virgole, punti) ed ogni parola va nell'array di puntatori. tutto funziona bene, ma dopo 6 parole esce con un errore. no sò perchè, ma anche cambiando le parole dopo 6 parole lette da errore.!!!!

ti posto il codice, se potreseti dargli un'occhiata quando vuoi cosi mi aiuti a capire cosa c'è che nn va...grazie


//elimina tutta la punteggiatura! e restituisce la lunghezza della parola
int elimina_schifezze(char temp[])
{
int i =0;
while(temp[i]>48)
i++;
temp[i] = '\0';
return i;
}

//divide in parole il testo
void dividi_in_parole(FILE *fp, char *a[] ){
char temp[30];
int lunghezza, indice;

indice = -1;
while (fscanf (fp, "%30s", temp) == 1){
indice++; //conta le parole
lunghezza = elimina_schifezze(temp); //lunghezza effettiva della parola
a[indice] = calloc(lunghezza+1,sizeof(char));
strcpy(a[indice], temp);
printf("%s\n", a[indice]);//controllo che parole ha inserito e come le ha inserite
}

}

int main(int argc, char *argv[])
{
FILE *fp;
char *array_parole[500];
int lunghezza;

//apro il file
fp = fopen("/home/peppe/Desktop/file2.txt", "r");

//divido in parole il testo
dividi_in_parole(fp, *array_parole);

//chiudo il file
fclose(fp);

return EXIT_SUCCESS;
}

andbin
07-10-2007, 11:10
dividi_in_parole(fp, *array_parole);L'asterisco * non ci vuole, perché passi un tipo di dato incompatibile (e il compilatore dovrebbe pure segnalartelo).

welfi
07-10-2007, 11:21
ora va bene, ti ringrazio!

ps, per caso puoi consigliarmi un buon libro e completo di C, fatto bene, in italiano oppure(se proprio in italiano nn c'è) in inglese??

gepeppe
09-10-2007, 19:54
ma se si volesse realizzare il comportamento di fscanf con un altra funzione, come si dovrebbe fare?? cioè se nel codice seguente:

if ((f = fopen ("un_file_di_testo.txt", "r")) != NULL)
{
while (fscanf (f, "%100s", buf) == 1)
printf ("[%s]\n", buf);

fclose (f);
}

al posto di scanf (o magari in un posto diverso, ma cmq senza usare scanf) cosa potrei mettere per leggere da un file di testo di volta in volta una stringa delimitata dallo spazio??

Imrahil
09-10-2007, 19:57
ora va bene, ti ringrazio!

ps, per caso puoi consigliarmi un buon libro e completo di C, fatto bene, in italiano oppure(se proprio in italiano nn c'è) in inglese??

Deitel & Deitel, C: Corso Completo di Programmazione, edito da Apogeo.

gepeppe
11-10-2007, 14:33
ma se si volesse realizzare il comportamento di fscanf con un altra funzione, come si dovrebbe fare?? cioè se nel codice seguente:

if ((f = fopen ("un_file_di_testo.txt", "r")) != NULL)
{
while (fscanf (f, "%100s", buf) == 1)
printf ("[%s]\n", buf);

fclose (f);
}

al posto di scanf (o magari in un posto diverso, ma cmq senza usare scanf) cosa potrei mettere per leggere da un file di testo di volta in volta una stringa delimitata dallo spazio??

grazie---e per questo invece??

andbin
11-10-2007, 15:21
grazie---e per questo invece??Un'altra soluzione potrebbe essere quella di leggere "a righe" con fgets() e poi spezzare la riga in parole tramite strtok() (specificando come delimitatori lo spazio, magari anche il tab o altro che vuoi).