View Full Version : [C++] Aiuto a fare il parsing di una linea
MacLinuxWinUser
24-11-2008, 15:51
Ciao a tutti,
in un programma che uso,
leggo un file di testo in cui per ogni riga vi sono dei parametri non
separati ma inseriti nella stringa che di volta in volta leggo.
Il file di testo è composto da file che dovrei aprire, ma prima dovrei
ricavarne i parametri fondamentali dal loro stesso nome.
Mi è venuto in mente di leggere la riga con fscanf, conoscete metodi migliori ???
Esempio di uso:
lista file:
p_a1_b2.5_c3.txt
q_a2_b1.5_c4.txt
r_a3_b0.3_c5.txt
s_a4_b3.5_c6.txt
e pensavo di leggerla così:
char par0[1];
int par1=0,par3=0;
float par2=0.0;
fscanf(file,"%c_a%d_b_%f_c%d.txt",par0,&par1,&par2,&par3)
avete consigli migliori ???
DanieleC88
24-11-2008, 17:50
char par0[1];
Non bastava "char par0;"?
avete consigli migliori ???
Se il testo è formattato così rigorosamente direi che può anche andare bene, ma non ho mai provato a farlo. Solo, dovresti controllare il valore di ritorno di fscanf() dopo ogni chiamata per verificare che la lettura sia stata (probabilmente) corretta.
Altrimenti, puoi fare un piccolo parser manuale, non è difficilissimo. Ci vuole solo una maggiore dose di pazienza... :D
sottovento
25-11-2008, 08:09
Probabilmente ti conviene leggere una riga alla volta (cosi' hai gia' il nome del file completo) e poi estrarre da questa i parametri che ti interessano usando la strtok.
MacLinuxWinUser
25-11-2008, 08:31
strtok ?????
e sarebbe ?
strtok ?????
e sarebbe ?
strtok è il migliore amico del memory leak :p
Visto che sei in C++ leggi una stringa alla volta dal fstream con getline (http://www.cplusplus.com/reference/string/getline.html).
Poi usi un istringstream (http://www.cplusplus.com/reference/iostream/istringstream/) e fai il parsing come più ti aggrada, ad esempio usando getline (http://www.cplusplus.com/reference/iostream/istream/getline.html) con il delimitatore e scartando i caratteri che non servono con ignore (http://www.cplusplus.com/reference/iostream/istream/ignore.html).
MacLinuxWinUser
25-11-2008, 09:28
In effetti volevo capire bene come fare il parsing....
apprezzo il tuo aiuto cionci, ma se ti fosse possibile,
potresti indicarmi un link o libro dove sia spiegato più in dettaglio
come fare parsing?
Grazie mille a tutti comunque...
Non è che ci sia un libro, si tratta semplicemente di usare le funzionalità che ti mette a disposizione la libreria standard. Anche definire questo parsing significa solo ingigantire il problema.
Per ogni metodo o classe ti ho linkato la spiegazione e c'è anche un esempio.
MacLinuxWinUser
25-11-2008, 10:01
Grazie !!!!
sottovento
25-11-2008, 11:03
strtok è il migliore amico del memory leak :p
Non mi risulti alllochi memoria. Il problema e' che usa variabili statiche, quindi non e' thread safe.
Non mi risulti alllochi memoria. Il problema e' che usa variabili statiche, quindi non e' thread safe.
Certo che non la alloca, ma se prendo un puntatore ritornato da strtok, poi me lo porto avanti nel mio programma e poi decido di fare una delete sul puntatore...puff :D
sottovento
25-11-2008, 12:00
Certo che non la alloca, ma se prendo un puntatore ritornato da strtok, poi me lo porto avanti nel mio programma e poi decido di fare una delete sul puntatore...puff :D
Non ottengo un leak comunque, e lo stesso discorso varrebbe nel caso si decidesse di fare un delete su puntatori dello stesso tipo (es: ctime()).
Cmq il suggerimento migliore e' quello che hai dato, riguardo all'uso degli stream. Sicuramente!
MacLinuxWinUser
26-11-2008, 11:32
Ciao !!!
piccolo problema, la situazione è la seguente:
Esempio di uso:
lista file:
p_a1.0_b2.5_c3.5.txt
q_a2.0_b1.5_c4.2.txt
r_a3.0_b0.3_c5.4.txt
s_a4.0_b3.5_c6.txt
e pensavo di leggerla così:
char par0[1];
float par1=0,par3=0;
float par2=0.0;
fscanf(file,"%c_a%f_b_%f_c%f.txt",par0,&par1,&par2,&par3)
ma il programma si pianta a leggere l'ultima linea del file di esempio
in quanto non riconosce il 6.txt ed invece vorrebbe un 6.0.txt
come posso ovviare il problema ?
ho 3000 file, non posso rinominarli per ora....
a meno di non usare qualche script o regular expression che però non son capace ad usare...
DanieleC88
26-11-2008, 12:20
ma il programma si pianta a leggere l'ultima linea del file di esempio
in quanto non riconosce il 6.txt ed invece vorrebbe un 6.0.txt
come posso ovviare il problema ?
Per ovviare al problema secondo me fai molto prima a scrivere un po' di codice a mano. Ragiona attentamente sul formato che ti aspetti, fai un po' di controlli durante la lettura e in poco tempo ne verrai fuori con un parsing corretto. Il tutto IMHO, chiaramente. ;)
MacLinuxWinUser
26-11-2008, 13:37
Dici di usare getchar?
Ho poca fantasia su cosa fare
sottovento
26-11-2008, 13:48
Ciao !!!
piccolo problema, la situazione è la seguente:
Esempio di uso:
lista file:
p_a1.0_b2.5_c3.5.txt
q_a2.0_b1.5_c4.2.txt
r_a3.0_b0.3_c5.4.txt
s_a4.0_b3.5_c6.txt
e pensavo di leggerla così:
char par0[1];
float par1=0,par3=0;
float par2=0.0;
fscanf(file,"%c_a%f_b_%f_c%f.txt",par0,&par1,&par2,&par3)
ma il programma si pianta a leggere l'ultima linea del file di esempio
in quanto non riconosce il 6.txt ed invece vorrebbe un 6.0.txt
come posso ovviare il problema ?
ho 3000 file, non posso rinominarli per ora....
a meno di non usare qualche script o regular expression che però non son capace ad usare...
Volendo cercare di cambiare il meno possibile: la fscanf() ritorna il numero di parametri che e' riuscita correttamente a leggere e ad assegnare alle tue variabili. Pertanto la fscanf() che hai scritto, nel caso non ci siano errori, dovrebbe sempre ritornare quattro.
A questo punto, potresti fare una fscanf() leggendo dei %d invece di %f, qualcosa del tipo
int result = fscanf(file,"%c_a%d.%d_b_%d.%d_c%d.%d.txt",
par0,&par1,&par2,&par3,&par4,&par5,&par6);
In tal caso:
- se il nome e' del tipo r_a3.0_b0.3_c5.4.txt, otterrai result = 7
- se il nome e' del tipo s_a4.0_b3.5_c6.txt, otterrai result = 6 e non utilizzerai par6 perche' non contiene nulla di significativo.
NOTA: non l'ho provato, ho solo letto il manuale della fscanf()!
Vincenzo1968
26-11-2008, 15:13
Per ovviare al problema secondo me fai molto prima a scrivere un po' di codice a mano. Ragiona attentamente sul formato che ti aspetti, fai un po' di controlli durante la lettura e in poco tempo ne verrai fuori con un parsing corretto. Il tutto IMHO, chiaramente. ;)
Quoto. Io consiglio un bell'automa a stati finiti.
:bimbo:
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.