|
|
|
![]() |
|
Strumenti |
![]() |
#1 |
Senior Member
Iscritto dal: Jul 2007
Città: Sicilia
Messaggi: 6263
|
[C++] Carico una riga fantasma
Salve a tutti.
Ho il seguente problema: ho un file di testo contenente, in ogni riga, tre numeri, ad esempio la seguente lista: Codice:
-0.01975 0.185617 -0.0153931 -0.01925 0.185622 -0.0159337 -0.01875 0.185626 -0.0164744 -0.01825 0.185633 -0.0172854 -0.01775 0.185639 -0.0179612 -0.01725 0.185647 -0.0189073 -0.01675 0.185653 -0.0195831 Codice:
#include <iostream> #include <fstream> int main (int argc, char** argv) { struct coordinates { double x; /**< Coordinata x */ double y; /**< Coordinata y */ double z; /**< Coordinata z */ }; /** \struct point * La struttura contiene informazioni generali su un punto, ovvero le sue * coordinate, un identificativo numerico e la lista dei suoi descrittori. */ struct point { long int id; /**< ID del punto */ struct coordinates coords; /**< Coordinate del punto */ struct point *next; /**< Puntatore al prossimo elemento */ }; struct point *plist, *plist_temp; std::ifstream infile; long int count = 0; plist = NULL; plist_temp = NULL; // Apertura file infile.open(argv[1], std::ios::in); // Lettura dei dati nel caso il file sia aperto con successo if (infile) { while (!infile.fail()) { // Incremento del contatore count++; // Creazione del nuovo elemento in testa plist_temp = plist; plist = new struct point; // Memorizzazione dei valori infile >> plist->coords.x; infile >> plist->coords.y; infile >> plist->coords.z; // Memorizzazione del contatore plist->id = count; // inserimento dell'elemento della lista plist->next = plist_temp; // Scrittura a schermo dei valori std::cout << "punto n. " << count << ": " << plist->coords.x << " " << plist->coords.y << " " <<plist->coords.z << std::endl; } std::cout << "Il numero di numeri letti e' " << count << std::endl; plist_temp = plist; plist = plist->next; delete plist_temp; } else { std::cout << "Errore nella lettura deil file\n"; } infile.close(); return 0; } Lo compilo con g++ -Wall test.c. Tuttavia, se lo eseguo, ottengo il seguente output: Codice:
./a.out file_con_punti punto n. 1: -0.01975 0.185617 -0.0153931 punto n. 2: -0.01925 0.185622 -0.0159337 punto n. 3: -0.01875 0.185626 -0.0164744 punto n. 4: -0.01825 0.185633 -0.0172854 punto n. 5: -0.01775 0.185639 -0.0179612 punto n. 6: -0.01725 0.185647 -0.0189073 punto n. 7: -0.01675 0.185653 -0.0195831 punto n. 8: 0 0 0 Per sicurezza, ho provato a modificare il file contenente i punti, aggiungendo delle righe vuote, oppure senza nessuna riga vuota alla fine ma con spazi dopo l'ultima cifra dell'ultimo numero, ed infine terminando il file esattamente subito dopo l'ultima cifra dell'ultimo numero, ma il risultato non cambia, ho sempre la presenza del punto 'fantasma' che non ci dovrebbe essere. Come posso modificare il programmino in maniera tale che non legga l'ultimo punto inesistente? Daniele PS: Utilizzo g++ (GCC) versione 4.2.3.
__________________
Non abbiamo ereditato il mondo dai nostri padri L'abbiamo preso in prestito dai nostri figli |
![]() |
![]() |
![]() |
#2 |
Senior Member
Iscritto dal: Feb 2006
Messaggi: 1304
|
Sicuramente il while viene eseguito una volta di troppo.
Nella condizione io metterei ( !infile.fail() && !infile.eof() ), dato che eof() è la funzione più adatta a trovare la fine del file... magari fail() viene chiamato se si effettua una lettura dopo eof()... e in questa maniera hai comunque una lettura vuota a eof(). E poi io sarei partito da 0 nella numerazione, mettendo count++ alla fine. Però è questione di gusti ![]() |
![]() |
![]() |
![]() |
#3 |
Senior Member
Iscritto dal: Jul 2007
Città: Sicilia
Messaggi: 6263
|
Provato, ma non funge. Legge sempre la riga vuota. Anch'io pensavo al ciclo while di troppo, ma ancora non ho trovato soluzione...
Daniele PS: Anch'io partirei da 0 per il conteggio, ma poi devo elaborare e salvare in un formato dove l'ID parte da 1, quindi mi adeguo.
__________________
Non abbiamo ereditato il mondo dai nostri padri L'abbiamo preso in prestito dai nostri figli |
![]() |
![]() |
![]() |
#4 |
Senior Member
Iscritto dal: Dec 2005
Città: Istanbul
Messaggi: 1817
|
il problema e' che finche' il test iniziale ti da il risultato dell'ultima lettura, non quella di quella che stai per fare. Questo e' in particolare vero se hai un linea vuota alla fine: finche' non provi a leggere un nuovo valore il codice non si accorge che sei arrivato alla fine.
La soluzione corretta e' provare a leggere i tre valori, e _dopo_ verificare se c'e' stato un errore in lettura e in tal caso interrompere il loop, senza ovviamente salvare l'ultima lettura. potresti sostituire il seguente codice Codice:
while (!infile.fail()) { // Incremento del contatore count++; // Creazione del nuovo elemento in testa plist_temp = plist; plist = new struct point; // Memorizzazione dei valori infile >> plist->coords.x; infile >> plist->coords.y; infile >> plist->coords.z; Codice:
double x,y,z; while ( infile >> x >> y >> z ) { count++; plist_temp = plist; plist = new struct point; // Memorizzazione dei valori plist->coords.x = x; plist->coords.y = y; plist->coords.z = z; /* ... */
__________________
One of the conclusions that we reached was that the "object" need not be a primitive notion in a programming language; one can build objects and their behaviour from little more than assignable value cells and good old lambda expressions. —Guy Steele |
![]() |
![]() |
![]() |
#5 |
Senior Member
Iscritto dal: Jul 2007
Città: Sicilia
Messaggi: 6263
|
Grazie, hai risolto il mio problema... Ti devo una birrozza...
Daniele
__________________
Non abbiamo ereditato il mondo dai nostri padri L'abbiamo preso in prestito dai nostri figli |
![]() |
![]() |
![]() |
#6 |
Senior Member
Iscritto dal: Dec 2005
Città: Istanbul
Messaggi: 1817
|
Suggerimento 2, togli tutti quei commenti inutili
![]() Penso sia abbastanza chiaro che "double x" e' la coordinata x e che count++ incrementa il contatore. Se a qualcuno non risultasse chiaro, spero cambi mestiere in breve tempo ![]() Suggerimento 3. Utilizza un contenitore standard per salvare i tuoi punti. A seconda dell'uso, un vector<> o una list<> dovrebbero fare al caso tuo. Anche perche' nel caso sopra mescoli informazioni relative al contenitore in se(il puntatore a next) con informazioni relative al punto (il suo id) Meglio ancora se aggiungi i costruttori alle strutture Ritengo piu' sensato qualcosa del genere: Codice:
struct coordinates { coordinates( double _x, double _y, double _z):x(_x),y(_y),z(_z){} double x; /**< Coordinata x */ double y; /**< Coordinata y */ double z; /**< Coordinata z */ }; struct point { point( double x, double y, double x,long _id):id(_id),coords(x,y,z){} long int id; /**< ID del punto */ struct coordinates coords; /**< Coordinate del punto */ }; std::list<point> pointList; /* ... */ if (infile) { double x,y,z; while ( infile >> x >> y >> z ) { pointList.push_back( point(x,y,z, pointList.size() + 1) ); const point& p = pointList.back(); std::cout << "punto n. " << pointList.size() << ": " << p.coords.x << " " << p.coords.y << " " <<p.coords.z << std::endl; } std::cout << "Il numero di numeri letti e' " << pointList.size() << std::endl; }
__________________
One of the conclusions that we reached was that the "object" need not be a primitive notion in a programming language; one can build objects and their behaviour from little more than assignable value cells and good old lambda expressions. —Guy Steele |
![]() |
![]() |
![]() |
#7 |
Senior Member
Iscritto dal: Jul 2007
Città: Sicilia
Messaggi: 6263
|
Ok, farò tesoro dei tuoi consigli.
Daniele
__________________
Non abbiamo ereditato il mondo dai nostri padri L'abbiamo preso in prestito dai nostri figli |
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 07:07.