Anfänger: XML Parsen und Objekte in einer Liste speichern klappt nicht ;-(
-
Hallo zusammen,
bin recht neu im C++, hoffe aber bald ein Mitglied der Gemeinde zu werden:-)
Meine Aufgabe derzeit ein XML File einzulesen und zu speichern.
Leider klappt nicht alles so wie ich es mir vorgestellt habe.
Anzahl der zu speichernden Objekte weißt man vor dem Parsen nicht.
Daher hab ich ein Paar Fragen:
Wie muss ich richtig dynamisch mehrere Objekte in einer Schleife erzeugen?
mit new? mach ich das richtig?
Ist die Liste der richtige Container um meine Objekte zu speichern?
(ich muss später diese Liste nur komplett durchlaufen)
Auf die privaten Elemente der Objekte (Junction) aus der Liste kann ich nicht zugreifen, aus dem Array schon, wo liegt das Problem?
warum wird die Größe des Arrays mit 20 angegeben obwohl ich 5 eingegeben habe?
Wofür steht eine "8" im "8Junction" als Ausgabe für "typeid ((*Iter)).name()" oder typeid ((* array[ti])).name() ?
was kann ich noch alles verbessern?
Vielen Dank im voraus.main.cpp
#ifdef HAVE_CONFIG_H #endif #include <libxml++-2.6/libxml++/libxml++.h> #include <libxml++-2.6/libxml++/parsers/textreader.h> #include <iostream> #include <list> #include <typeinfo> // << typeid(reader.get_value()).name() << #include <boost/lexical_cast.hpp> #include "Junction.h" using namespace std; //ostream & operator<<(ostream &output, const Junction & junc) { // output << "ID " << (int) junc.getID() << endl; // << ' ' << junc.getX << ' ' << junc.getY; // return output; //} int main(int argc, char* argv[]) { list <Junction> JunctionList; list <Junction>::iterator Iter; Junction * array[5]; int ai = 0; cout << "sizeof(array): " << sizeof (array) << endl; try { xmlpp::TextReader reader("/home/sugarray21/sumo-0.11.1/maps/map_very_small.net"); while (reader.read()) { if (reader.get_name() == "junction") { int id; float x, y; cout << "--- junction ---" << endl; if (reader.has_attributes()) { reader.move_to_first_attribute(); do { if (reader.get_name() == "id") { id = boost::lexical_cast<int>(reader.get_value()); cout << " ID:: " << id << endl; } else if (reader.get_name() == "x") { x = boost::lexical_cast<float>(reader.get_value()); cout << " X :: " << x << endl; } else if (reader.get_name() == "y") { y = boost::lexical_cast<float>(reader.get_value()); cout << " Y :: " << y << endl; } } while (reader.move_to_next_attribute()); cout << "Junction: " << id << ": " << x << ": " << y << endl; Junction *t_Junction = new Junction(id, x, y); cout << "Junction: " << t_Junction->getID() << ": " << t_Junction->getX() << ": " << t_Junction->getY() << endl; JunctionList.push_back(*t_Junction); array[ai++] = t_Junction; // Junction t_Junction(id, x, y); // cout << "Junction: " << t_Junction.getID() << ": " << t_Junction.getX() << ": " << t_Junction.getY() << endl; reader.move_to_element(); } else { } } } } catch (const exception& e) { cout << "Exception caught: " << e.what() << endl; } cout << "JunctionList.size: " << JunctionList.size() << endl; for (Iter = JunctionList.begin(); Iter != JunctionList.end(); ++Iter) cout << typeid ((*Iter)).name() << " " << (*Iter).getID() << " "; // print all cout << endl; int ti; cout << "sizeof(array): " << sizeof (array) << endl; for (ti = 0; ti<sizeof (array); ti++) { cout << typeid ((* array[ti])).name() << " ID: " << (* array[ti]).getID(); cout << " X: " << (* array[ti]).getX() << " Y: " << (* array[ti]).getY() << endl; } }junction.h
/* * File: Junction.h * Author: sugarray21 * * Created on 12. Januar 2010, 15:40 */ #ifndef _JUNCTION_H #define _JUNCTION_H class Junction { // friend ostream & operator<<(ostream &, const Junction &); public: Junction(); Junction(const Junction& orig); Junction(int id, float x, float y); int getID(); float getX(); float getY(); void setID(int id); void setX(float x); void setY(float y); virtual ~Junction(); private: unsigned int id; float x, y; }; #endif /* _JUNCTION_H */junction.cpp
/* * File: Junction.cpp * Author: sugarray21 * * Created on 12. Januar 2010, 15:40 */ #include "Junction.h" Junction::Junction() { } Junction::Junction(const Junction& orig) { } Junction::Junction(int t_id, float t_x, float t_y) { id = t_id; x = t_x; y = t_y; } Junction::~Junction() { } int Junction::getID() { return id; }; float Junction::getX() { return x; }; float Junction::getY() { return y; };Ausgabe:
sizeof(array): 20 --- junction --- ID:: 317557901 X :: 630.25 Y :: 1697 Junction: 317557901: 630.25: 1697 Junction: 317557901: 630.25: 1697 --- junction --- ID:: 317558017 X :: 644.22 Y :: 952 Junction: 317558017: 644.22: 952 Junction: 317558017: 644.22: 952 --- junction --- ID:: 317558232 X :: 414.62 Y :: 0 Junction: 317558232: 414.62: 0 Junction: 317558232: 414.62: 0 --- junction --- ID:: 6350306 X :: 0 Y :: 1124.5 Junction: 6350306: 0: 1124.5 Junction: 6350306: 0: 1124.5 JunctionList.size: 4 8Junction 112 8Junction 112 8Junction 112 8Junction 112 sizeof(array): 20 8Junction ID: 317557901 X: 630.25 Y: 1697 8Junction ID: 317558017 X: 644.22 Y: 952 8Junction ID: 317558232 X: 414.62 Y: 0 8Junction ID: 6350306 X: 0 Y: 1124.5 Segmentation fault Press [Enter] to close the terminal ...
-
sugarray21 schrieb:
Wie muss ich richtig dynamisch mehrere Objekte in einer Schleife erzeugen?
mit new? mach ich das richtig?Nein, benutz einfach direkt die Einfügeoperationen des Containers.
Ist die Liste der richtige Container um meine Objekte zu speichern?
(ich muss später diese Liste nur komplett durchlaufen)Für den Zweck ist der Containertyp relativ egal. vector dürfte deiner Beschreibung nach aber ein wenig besser geeignet sein.
Auf die privaten Elemente der Objekte (Junction) aus der Liste kann ich nicht zugreifen, aus dem Array schon, wo liegt das Problem?
Naja, das ist halt der Zweck von private
. Wo bitte greifst du über das Array auf private Elemente zu? Ich kann die Stelle nicht finden. Das dürfte eigentlich nicht gehen.warum wird die Größe des Arrays mit 20 angegeben obwohl ich 5 eingegeben habe?
Wein sizeof die Größe in char-Größen angibt.
Wofür steht eine "8" im "8Junction" als Ausgabe für "typeid ((*Iter)).name()" oder typeid ((* array[ti])).name() ?
Keine Ahnung, die Ausgabe von typeid ist nicht standardisiert. Vielleicht stehen im Handbuch deines Compilers Details.
was kann ich noch alles verbessern?
Vor allem erstmal die Art und Weise wie du Elemente in die Liste einfügst, siehe oben. Der Rest des quelltextes ist mir zu lang um mir alles anzugucken.
-
SeppJ auf jeden Fall danke dir!
"benutz einfach direkt die Einfügeoperationen des Containers. "
gern, wie geht n das nur?
JunctionList.push_back(Junction(id, x, y));so?
wird zwar kompiliert aber die Ausgabe von der Liste ist nicht richtig.
Von dem Array dagegen schon. Kein Plan woran es liegt!
Ausgabe:JunctionList.size: 4 8Junction ID 112 X:1.41531e-43 Y:0 8Junction ID 112 X:1.41531e-43 Y:0 8Junction ID 112 X:1.41531e-43 Y:0 8Junction ID 112 X:1.41531e-43 Y:0 sizeof(array): 20 8Junction ID: 317557901 X: 630.25 Y: 1697 8Junction ID: 317558017 X: 644.22 Y: 952 8Junction ID: 317558232 X: 414.62 Y: 0 8Junction ID: 6350306 X: 0 Y: 1124.5 Segmentation faultwarum wird ein Fehler "Segmentation fault" ausgegeben?
Ausgabe von der Liste
ostream & operator<<(ostream &output, const Junction & junc) { output << "ID " << junc.id << " X:" << junc.x << " Y:" << junc.y << endl; return output; } .... cout << "JunctionList.size: " << JunctionList.size() << endl; for (Iter = JunctionList.begin(); Iter != JunctionList.end(); ++Iter) cout << typeid ((*Iter)).name() << " " << *Iter; // print all cout << endl;Auf private Elemente greife ich über GET Methode oder frend Funktion zu.
(steht doch da
)
-
sugarray21 schrieb:
SeppJ auf jeden Fall danke dir!
"benutz einfach direkt die Einfügeoperationen des Containers. "
gern, wie geht n das nur?
JunctionList.push_back(Junction(id, x, y));so?
Ja.
wird zwar kompiliert aber die Ausgabe von der Liste ist nicht richtig.
Von dem Array dagegen schon. Kein Plan woran es liegt!
Zeig mal den Code wie er jetzt ist.
warum wird ein Fehler "Segmentation fault" ausgegeben?
Weil das Array 5 Elemente hat, du aber versuchst, auf 20 zuzugreifen.
Auf private Elemente greife ich über GET Methode oder frend Funktion zu.
(steht doch da
)Das ist ja auch völlig in Ordnung. Inwiefern klappt das denn bei der Liste nicht?
-
main.cpp
#ifdef HAVE_CONFIG_H #endif #include <libxml++-2.6/libxml++/libxml++.h> #include <libxml++-2.6/libxml++/parsers/textreader.h> #include <iostream> #include <list> #include <typeinfo> // << typeid(reader.get_value()).name() << #include <boost/lexical_cast.hpp> #include "Junction.h" using namespace std; ostream & operator<<(ostream &output, const Junction & junc) { output << "ID " << junc.id << " X:" << junc.x << " Y:" << junc.y << endl; return output; } int main(int argc, char* argv[]) { list <Junction> JunctionList; list <Junction>::iterator Iter; Junction * array[4]; int ai = 0; try { xmlpp::TextReader reader("/home/sugarray21/sumo-0.11.1/maps/map_very_small.net"); while (reader.read()) { if (reader.get_name() == "junction") { int id; float x, y; cout << "--- junction ---" << endl; if (reader.has_attributes()) { reader.move_to_first_attribute(); do { if (reader.get_name() == "id") { id = boost::lexical_cast<int>(reader.get_value()); cout << " ID:: " << id << endl; } else if (reader.get_name() == "x") { x = boost::lexical_cast<float>(reader.get_value()); cout << " X :: " << x << endl; } else if (reader.get_name() == "y") { y = boost::lexical_cast<float>(reader.get_value()); cout << " Y :: " << y << endl; } } while (reader.move_to_next_attribute()); cout << "Junction: " << id << ": " << x << ": " << y << endl; Junction *t_Junction = new Junction(id, x, y); cout << "Junction: " << t_Junction->getID() << ": " << t_Junction->getX() << ": " << t_Junction->getY() << endl; array[ai++] = t_Junction; JunctionList.push_back(Junction(id, x, y)); reader.move_to_element(); } else { } } } } catch (const exception& e) { cout << "Exception caught: " << e.what() << endl; } cout << endl << "JunctionList.size: " << JunctionList.size() << endl; for (Iter = JunctionList.begin(); Iter != JunctionList.end(); ++Iter) cout << typeid ((*Iter)).name() << " " << *Iter; // print all cout << endl << "sizeof(array): " << sizeof (array) / sizeof (array[0]) << endl; for (int ti = 0; ti < sizeof (array) / sizeof (array[0]); ti++) { cout << typeid ((* array[ti])).name() << " " << *array[ti]; } }Ausgabe von der Liste ist Bullshit:
--- junction --- ID:: 317557901 X :: 630.25 Y :: 1697 Junction: 317557901: 630.25: 1697 Junction: 317557901: 630.25: 1697 --- junction --- ID:: 317558017 X :: 644.22 Y :: 952 Junction: 317558017: 644.22: 952 Junction: 317558017: 644.22: 952 --- junction --- ID:: 317558232 X :: 414.62 Y :: 0 Junction: 317558232: 414.62: 0 Junction: 317558232: 414.62: 0 --- junction --- ID:: 6350306 X :: 0 Y :: 1124.5 Junction: 6350306: 0: 1124.5 Junction: 6350306: 0: 1124.5 JunctionList.size: 4 8Junction ID 112 X:1.41531e-43 Y:0 8Junction ID 112 X:1.41531e-43 Y:0 8Junction ID 112 X:1.41531e-43 Y:0 8Junction ID 112 X:1.41531e-43 Y:0 sizeof(array): 4 8Junction ID 317557901 X:630.25 Y:1697 8Junction ID 317558017 X:644.22 Y:952 8Junction ID 317558232 X:414.62 Y:0 8Junction ID 6350306 X:0 Y:1124.5 Press [Enter] to close the terminal ...
-
Die falsche Übergabe an die Liste liegt daran, dass du einen Copykonstruktor definiert hast, dieser aber nichts tut. Deshalb wird, wenn push_back das Objekt in die Liste kopiert, ein uninitialisiertes Objekt erzeugt. Du brauchst für deine Klasse weder einen Copykonstruktor noch einen Destruktor.
-
YESSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS!
JunctionList.size: 4 8Junction ID 317557901 X:630.25 Y:1697 8Junction ID 317558017 X:644.22 Y:952 8Junction ID 317558232 X:414.62 Y:0 8Junction ID 6350306 X:0 Y:1124.5 sizeof(array): 4 P8Junction ID 317557901 X:630.25 Y:1697 P8Junction ID 317558017 X:644.22 Y:952 P8Junction ID 317558232 X:414.62 Y:0 P8Junction ID 6350306 X:0 Y:1124.5 Press [Enter] to close the terminal ...sieht doch schon mal besser aus.
DANKE DIR 1000 MAL !!!
Du hast dir aber echt viel Zeit für mich genommen! Respekt!
Was ich noch nicht verstehe ist,
warum ich gar keinen Konstruktor und einen Destruktor brauche?
Hättest du jetzt gesagt, das ich einen selber definieren soll, hätte ich noch verstanden. Wird einer (Kopierkonstruktor) impliziert erstellt und aufgerufen?
Was ist mir dem Standartkonstruktor und dem Destruktor?
Danke Dir vielmals!
-
Ja, wenn man keinen Konstruktor, Destruktor, Kopierkonstruktor oder Zuweisungsoperator definiert und es wird trotzdem einer gebraucht, dann wird vom Compiler automatisch eine triviale Version erstellt. Diese erzeugt/vernchtet/kopiert (je nachdem) einfach stumpf alle Datenelemente. das ist in vielen Fällen völlig ausreichend, so auch hier.
Die wichtigste Ausnahme, wann man diese Funktionen selber schreiben sollte, ist, wenn man in der Klasse Zeiger auf andere Objekte hat.
-
ah stimmt habe ich doch vor kurzem gelesen, dann muss man den Kopierkonstruktor selber
schreiben und neuen Zeiger auf kopierte Daten erstellen. Danke dir !