[Risolto] Legge da file
Ciao a tutti.. è molto urgente quindi se sapete come aiutarmi ve ne sarei grato
devo leggere da un file di testo (.txt) in questa forma:
Nome Cognome : interesse1, interesse2, interesse3, ecc ecc
non so perchè ma mi sono bloccato nella lettura da file.
la struttura l'ho impostata così:
typedef char interesse[20];
typedef struct{
char nome[15];
char cognome[15];
interesse interes[18];
}persone;
while(fscanf(fp,"%s %s :",persone.nome,persone.cognome)!=EOF){ ...
con questo ciclo leggo il nome ed il cognome..cosa devo inserire dentro per caricare correttamente i vari interessi (separati da spazio/virgola) ??
Grazie mille a chiunque mi aiuti ^^
devo leggere da un file di testo (.txt) in questa forma:
Nome Cognome : interesse1, interesse2, interesse3, ecc ecc
non so perchè ma mi sono bloccato nella lettura da file.
la struttura l'ho impostata così:
typedef char interesse[20];
typedef struct{
char nome[15];
char cognome[15];
interesse interes[18];
}persone;
while(fscanf(fp,"%s %s :",persone.nome,persone.cognome)!=EOF){ ...
con questo ciclo leggo il nome ed il cognome..cosa devo inserire dentro per caricare correttamente i vari interessi (separati da spazio/virgola) ??
Grazie mille a chiunque mi aiuti ^^
Risposte
Per prima cosa elimina la parola urgente dal titolo.
Dopo di che puoi chiedere il numero di interessi e chiederne uno per volta oppure decidere un modo per segnalare al programma che non ci sono più altri interessi.
Dopo di che puoi chiedere il numero di interessi e chiederne uno per volta oppure decidere un modo per segnalare al programma che non ci sono più altri interessi.
Devo leggere da file quindi non posso far immettere da tastiera a priori il numero di interessi..
come faccio a leggere (con fscanf/fgets/ecc) fino a quando ci sono valori?
Grazie ^^
come faccio a leggere (con fscanf/fgets/ecc) fino a quando ci sono valori?
Grazie ^^
Gli interessi possono contenere spazi? Normalmente si legge una riga per volta e poi si estraggono i valori dalla stringa cercando i separatori con funzioni come strchr..
strchr? ma è una funzione del c o c++?
sapresti spiegarmi come si implementa e a cosa serve? Grazie mille!
sapresti spiegarmi come si implementa e a cosa serve? Grazie mille!
È una funzione che si trova sia nel C, che nel C++. Trova la successiva ricorrenza di un particolare carattere in una stringa. Ma forse soluzioni più semplici o alternative sono possibili.. Non hai risposto alla mia domanda sulla possibilità di avere spazi all'interno delle stringhe degli interessi..
Ah non avevo capito fosse una domanda..
comunque no, non ci possono essere spazi, cioè ogni interesse è definito da un'unica parola!
Quindi utilizzo una semplice fgets per leggere le righe in un vettore qualsiasi e poi le spezzetto con quella funzione? Come dovrei implementarla?
Grazie ancora!
comunque no, non ci possono essere spazi, cioè ogni interesse è definito da un'unica parola!
Quindi utilizzo una semplice fgets per leggere le righe in un vettore qualsiasi e poi le spezzetto con quella funzione? Come dovrei implementarla?
Grazie ancora!
Ho studiato la funzione strchr ma onestamente mi sembra una soluzione troppo complicata..
come potrei fare sennò? Ho esaurito le forze mentali..
come potrei fare sennò? Ho esaurito le forze mentali..
To, ti ho fatto una versione che legge una sola riga. Ci metti due secondi ad adattarlo a leggere tutto
#include <stdio.h> #include <stdlib.h> typedef char interesse[20]; typedef struct{ char nome[15]; char cognome[15]; interesse interes[18]; } persone; #define die(...) exit(fprintf(stderr,##__VA_ARGS__)); int main(int argc, char *argv[]) { FILE *fp = fopen(argv[1],"r"); int c, interestsCount = 0, interestLenght = 0; persone persona; if(!fp) die("Errore nell'apertura di file.txt"); //Leggo una sola riga, per leggerle tutte cicla per ogni \n if(2 != fscanf(fp,"%s %s :",&persona.nome,&persona.cognome)) die("Formato file non corretto"); //il puntatore ora è avanti, leggo fino al termine della riga ed estraggo gli interessi do { c = fgetc(fp); if(c == ' ') { persona.interes[interestsCount][interestLenght-1] = '\0'; ++interestsCount; interestLenght = 0; continue; } persona.interes[interestsCount][interestLenght++] = c; } while(c != '\n'); //se sei nel ciclo, controlla anche che non arrivi a EOF fclose(fp); printf("Nome: %s\nCognome: %s\n",persona.nome,persona.cognome); printf("Interessi: "); for(c=0;c<interestsCount;++c) puts(persona.interes[c]); return 0; }
Credo che la soluzione più semplice sia quella di leggere una riga per volta con fgets (immagino che ogni riga sia formattata come hai scritto) e quindi usare sscanf per leggere i valori che ti interessano.. Ci sono alcuni dettagli tecnici un po' delicati per usare questo sistema per cui provo a scriverti un codice di esempio..
Okk grazie!
Grazie nobody, credo di aver capito quella funzione.
Grazie nobody, credo di aver capito quella funzione.
Ok, il codice di esempio è il seguente.. Legge da console ma la lettura da file è uguale (uso infatti fgets che è uguale in entrambi i casi). Unico difetto è che è necessario avere uno spazio tra gli interessi e la virgola o non funziona.. Per farlo funzionare è necessario cambiare la stringa di formato nello sscanf. %n è quello che fa funzionare il tutto e restituisce il numero di caratteri letti dalla funzione.
#include <stdio.h> int main(int argc, char *argv[]) { char riga[1024] = ""; char nome[64] = ""; char cognome[64] = ""; char interesse[64] = ""; int n = 0, d = 0; while(fgets(riga, sizeof(riga), stdin)) { sscanf(riga, "%63s %63s :%n", nome, cognome, &n); printf("Nome: %s\nCognome: %s\n", nome, cognome); while (sscanf(riga+n, " %63s ,%n", interesse, &d) > 0) { printf("%s\n", interesse); n += d; } } return 0; }
Ho provato ad adattarla ma penso di aver dimenticato qualcosa (sono sui libri da 8 ore e non capisco più nulla..)
sscanf legge da "riga" una parola (fino allo spazio) e copia il valore su "nome", giusto? E' questo il funzionamento?
sscanf legge da "riga" una parola (fino allo spazio) e copia il valore su "nome", giusto? E' questo il funzionamento?
sscanf è esattamente come scanf ma invece di leggere da console, legge i caratteri da una stringa. Stringa che nel mio caso ho letto da fgets ma può venire da qualsiasi fonte. Siccome sscanf non memorizza l'ultima posizione letta dalla chiamata precedente è necessario leggere tale posizione con %n e quindi spostare la posizione iniziale di lettura del numero corretto di posizioni. Questo è più o meno quello che fa quel codice usando le variabili n e d. Quando devi consegnare questo esercizio? Forse dovresti prenderti una pausa..
Okk perfetto, credo di aver capito..
cmq si, hai ragione, una pausa ci vorrebbe..
grazie mille!
cmq si, hai ragione, una pausa ci vorrebbe..
grazie mille!
Rieccomi...
Avevo abbandonato questo "esercizio" per dedicarmi ad altro, ma poco fa ho deciso di riprenderlo per risolverlo una volta per tutte!
Ho preso come esempio un file di testo costituito da:
nome : interesse
(solo un interesse per adesso, poi la lettura di altri interessi penso di farla mediante una lista di liste..ma ci lavoro dopo, intanto risolvo la lettura di un interesse).
string è la stringa su cui copio ogni singola riga. Poi ho pensato di copiare il contenuto delle due parti in altre due stringhe ed infine le copio sui campi degli elementi della lista.
La lista ha la seguente struttura:
typedef struct{
char nome[15];
char interesse[15];
}element;
typedef struct list_element{
element value;
struct list_element *next;
}item;
typedef item* list;
nella funzione di caricamento da file ho quindi inserito questo ciclo:
while(fgets(string,100,fp)!=NULL){
for(k=0;k<30&&string[k]!=':';k++){
nom[k]=string[k];
}
for(j=0,k=k+2;k<30&&string[k]!='\n';k++,j++){
interes[j]=string[k];
}
strcpy(e.nome,nom);
strcpy(e.interesse,interes);
e.nome[strlen(e.nome)-2]='\0';
e.interesse[strlen(e.interesse)-1]='\0';
l=insord(e,l);
}
però ancora non funziona bene. Sono sicuro che il problema sia dato dal fatto che leggendo 100 caratteri ho una stringa "sporca" e piena di simboli, quindi quando provo ad estrasse la seconda parola mi da qualche problema (ho provato un sacco di condizioni, con risultati differenti ma senza risolvere il problema).
Sono anche sicuro che sto commettendo un errore banale, per questo chiedo a voi che la vedete da fuori di dirmi cosa sbaglio..
Grazie mille!
Avevo abbandonato questo "esercizio" per dedicarmi ad altro, ma poco fa ho deciso di riprenderlo per risolverlo una volta per tutte!
Ho preso come esempio un file di testo costituito da:
nome : interesse
(solo un interesse per adesso, poi la lettura di altri interessi penso di farla mediante una lista di liste..ma ci lavoro dopo, intanto risolvo la lettura di un interesse).
string è la stringa su cui copio ogni singola riga. Poi ho pensato di copiare il contenuto delle due parti in altre due stringhe ed infine le copio sui campi degli elementi della lista.
La lista ha la seguente struttura:
typedef struct{
char nome[15];
char interesse[15];
}element;
typedef struct list_element{
element value;
struct list_element *next;
}item;
typedef item* list;
nella funzione di caricamento da file ho quindi inserito questo ciclo:
while(fgets(string,100,fp)!=NULL){
for(k=0;k<30&&string[k]!=':';k++){
nom[k]=string[k];
}
for(j=0,k=k+2;k<30&&string[k]!='\n';k++,j++){
interes[j]=string[k];
}
strcpy(e.nome,nom);
strcpy(e.interesse,interes);
e.nome[strlen(e.nome)-2]='\0';
e.interesse[strlen(e.interesse)-1]='\0';
l=insord(e,l);
}
però ancora non funziona bene. Sono sicuro che il problema sia dato dal fatto che leggendo 100 caratteri ho una stringa "sporca" e piena di simboli, quindi quando provo ad estrasse la seconda parola mi da qualche problema (ho provato un sacco di condizioni, con risultati differenti ma senza risolvere il problema).
Sono anche sicuro che sto commettendo un errore banale, per questo chiedo a voi che la vedete da fuori di dirmi cosa sbaglio..
Grazie mille!
Inizializza le stringhe che usi a '\0'.
In maniera che anche se le riempi di caratteri validi non per la totaltà della lunghezza - 1 , sei sicuro che questa sarà terminata correttamente dal nullbyte.
Puoi usare la funzione memset per inizializzare la stringa a 0.
Poi vabbè ci sono altre cosette che non dovresti usare, come la strcpy che anche lei è il male in quanto non fa controlli sulla lunghezza dei dati, e dovresti usare quindi al suo posto la strncpy, ma per ora sorvola.
Prima occupati di far funzionare le cose inizializzando tutto.
Comunque, nel sorgente che ti ho pubblicato qualche risposta fa, c'è il modo funzionante per estrarre il nome e tutti gli interessi da una sola riga.
Puoi adattare quello ed hai vinto
In maniera che anche se le riempi di caratteri validi non per la totaltà della lunghezza - 1 , sei sicuro che questa sarà terminata correttamente dal nullbyte.
Puoi usare la funzione memset per inizializzare la stringa a 0.
Poi vabbè ci sono altre cosette che non dovresti usare, come la strcpy che anche lei è il male in quanto non fa controlli sulla lunghezza dei dati, e dovresti usare quindi al suo posto la strncpy, ma per ora sorvola.
Prima occupati di far funzionare le cose inizializzando tutto.
Comunque, nel sorgente che ti ho pubblicato qualche risposta fa, c'è il modo funzionante per estrarre il nome e tutti gli interessi da una sola riga.
Puoi adattare quello ed hai vinto
Edit: risolto..
Andavano riazzerati i contatori, inizializzati a '\0' il resto dei campi non utilizzati ed il gioco è fatto
Grazie a tutti, in particolare a nobody
Andavano riazzerati i contatori, inizializzati a '\0' il resto dei campi non utilizzati ed il gioco è fatto
Grazie a tutti, in particolare a nobody
