Fehlerbehebung!?!
-
Mvstylez schrieb:
// ... double myPrice; // ...Yay! again

-
oh mein gott

dummheit kennt keine grenzen
danke!
-
ach ja Preis in ner double zahl
wenn ich noch zeit habe änder ich das am EEnde 
noch eine kleine frage und zwar gibt es ein problem das ich sobald ich mehr als eine Reise beim starten einlesen lasse gibt es ein crash mit der fehlermeldungterminate called after throwing an instance of 'std::out_of_range' what(): basic_string::substrdas heist ja quasi der versucht irgendwo reinzuschreiben wo der speicher dafür nicht reserviert wurde...
da es beim ersten mal aber klappt liegt es also nicht an dem string sondern dann warhscheinlich an der reisenlist[100] wo ich wahrscheinlich einen fehler gemacht habe aber mir fällt er nicht auf gebt mir mal einen schubs in die richtige richtung bitte
nvm der debugger bricht an der stelle in tokenizer.cpp ab: sagt es mir ja auch schon in der fehlermeldung basic_string::substr ...
aber keine ahnung ?!?std::string res = myString.substr(myPos, newpos-myPos);reisen.h
#ifndef REISEN_H #define REISEN_H #include <iostream> #include <string> class Reisen { private: int myId; double myPrice; int myLength; public: Reisen(); Reisen(int myId, double myPrice, int myLength); //getter int id() const {return myId;} double price() const{return myPrice;} int length() const{return myLength;} //setter void setId(int id){myId=id;} void setPrice(double price) {myPrice = price;} void setLength(int length) {myLength = length;} std::string serialize() const; }; std::ostream& operator<<(std::ostream& str, const Reisen& reisen); Reisen createReiseFromString(const std::string& s); #endif // REISEN_Hreisen.cpp
#include "reisen.h" #include <iostream> #include <sstream> #include "tokenizer.h" Reisen::Reisen() : myId(0), myPrice(0.0), myLength(0) {} Reisen::Reisen(int id, double price, int length) : myId(id), myPrice(price), myLength(length) {} std::string Reisen::serialize() const { std::ostringstream oss; oss<<myId<<"^"<<myPrice<<"^"<<myLength; return oss.str(); } std::ostream& operator<<(std::ostream& str, const Reisen& reisen) { str<<"[Reise]"<<reisen.id()<<" Preis: "<<reisen.price()<<"€ Länge: "<<reisen.length(); return str; } Reisen createReiseFromString(const std::string& s) { Tokenizer tok(s, '^'); std::istringstream iD(tok.next()); int id ; iD>>id; std::istringstream pricE(tok.next()); double price; pricE>>price; std::istringstream lengtH(tok.next()); int length; lengtH>>length; return Reisen(id,price,length); }reisenlist.h
#ifndef REISENLIST_H #define REISENLIST_H #include "reisen.h" #include <iostream> #include <string> const int MAXSIZE=100; class Reisenlist { private: Reisen myReiselist[MAXSIZE]; int mySize; public: Reisenlist(); void addReisen(const Reisen& reisen); void readFile(const std::string filename); void show(); void writeFile(const std::string filename); }; #endif // REISENLIST_Hreisenlist.cpp
#include "reisenlist.h" #include <fstream> #include <string> Reisenlist::Reisenlist(): mySize(0) { } void Reisenlist::addReisen(const Reisen& reisen){ myReiselist[mySize]= reisen; mySize++; } void Reisenlist::readFile(const std::string filename){ std::ifstream fi(filename.c_str()); if (!fi){ std::cout<<"Datei "<<filename<<" konnte nicht gelesen werden \n"; return; } std::string line; while (getline(fi, line)){ if (line.size() == 0 || line[0] == '#'){ continue; } Reisen reisen = createReiseFromString(line); myReiselist[mySize] = reisen; mySize++; } fi.close(); } void Reisenlist::show() { for (int i = 0; i<mySize; i++){ std::cout<<myReiselist[i]<<std::endl; } } void Reisenlist::writeFile(const std::string filename){ std::ofstream fo(filename.c_str()); if (!fo){ std::cout<<"Datei "<<filename<<" kann nicht beschrieben werden.\n"; return; } //nur zur erklärung fo<<"# Pro Zeile ein Objekt\n"; fo<<"# ID^Preis^Länge\n"; for (int i= 0; i< mySize; i++) { fo<<myReiselist[i].serialize()<<std::endl; } fo.close(); }tokenizer.h
#ifndef TOKENIZER_H #define TOKENIZER_H #include <iostream> #include <string> class Tokenizer { private: std::string myString; char myTrenner; std::string::size_type myPos; public: Tokenizer(const std::string& s, char trenner); std::string next(); bool hasMore() const; }; #endif // TOKENIZER_Htokenizer.cpp
#include "tokenizer.h" Tokenizer::Tokenizer(const std::string& s, char trenner): myString(s), myTrenner(trenner) { //leerstring if (myString.size() == 0) myPos = std::string::npos; } std::string Tokenizer::next(){ std::string::size_type newpos = myString.find(myTrenner,myPos); std::string res = myString.substr(myPos, newpos-myPos); myPos = (newpos == std::string::npos) ? newpos : newpos+1; return res; } bool Tokenizer::hasMore() const { return myPos != std::string::npos; }main
#include <iostream> #include "reisenlist.h" #include "reisen.h" #include "tokenizer.h" const std::string FILENAME= "Reisen.dat"; void newReise(Reisenlist& reisenlist) { int id; double price; int length; std::cout<<"\nID: "; std::cin>>id; std::cout<<"\nPreis: "; std::cin>>price; std::cout<<"\nLänge: "; std::cin>>length; Reisen reisen(id,price,length); reisenlist.addReisen(reisen); } void menu(Reisenlist& reisenlist){ char answ; do { std::cout<<"n - Neue Reise einfügen\n"; std::cout<<"l - Liste aller Reisen anzeigen\n"; std::cout<<"s - Neue Stadt einfügen\n"; std::cout<<"c - Stadt einer Reise zufügen\n"; std::cout<<"Eingabe: "; std::cin>>answ; switch(answ){ case 'n': newReise(reisenlist); break; case 'l': reisenlist.show(); break; case 'q': break; default: std::cout<<"Falsche Eingabe\n"; } }while(answ != 'q'); } int main() { Reisenlist reisenlist; reisenlist.readFile(FILENAME); menu(reisenlist); reisenlist.writeFile(FILENAME); }
-
Mvstylez schrieb:
einen schubs in die richtige richtung bitte

Wahrscheinlich benutzt Du irgendwo
string::substr()mit ungültigen Parametern.
Z.B. intokenizer::next().
-
ah ja hab grade gesehen das es darum ja auch in der fehlermeldung geht und wo der debugger genau den fehler anzeigt... aber ich verstehe trozdem nicht warum der das beim ersten string hinbekommt und beim zweiten mal dann nicht das dürfte doch eigentlich kein unterschied machen myPos usw wird doch neu belegt also dürfte er nicht darüber hinausspringen
-
also ich merk grade dem scheint nicht der fall zu sein so als ob der nach dem einlesen der Zeile nicht merkt das es eine neue Zeile ist und er wieder bei 0 anfangen muss.....
was logisch ist wenn man vergisst das oben hinzuschreiben
Danke!
bin ich eigentlich der einzige der so viele Schusselfehler macht wenn es darum geht ein programm zu schreiben bzw. wie kann man da entgegenwirken?
-
nein, das geht vielen am Anfang so. Die C++ Lernkurve ist sehr steil, und mit jeder durchwachten Nacht, die man auf der Suche nach der Ursache eines Schusselfehlers verbracht hat, sinkt die Schusselfehler-Rate, denn eine wegen Debuggings unter Zeitdruck durchwachte Nacht hat einen hervorragenden Lerneffekt (den Fehler macht man wahrscheinlich nicht ein zweites Mal :D)
-
haha ok gut zu wissen dass es hoffentlich irgendwann besser wird

Der Zwang das nicht allzu oft zu wiederhohlen ist auf alle fälle da...
jetzt habe ich noch eine Frage zu einem Logik-Problem:
ich hab jetzt noch die Klasse: Orte und die Klasse Orteliste... jetzt muss ich jeder Reise ein paar Orte und die Aufenthaltsdauer dieser Orte hinzufügen... kann ich dass einfach als ein Feld von int's schreiben die die Position der Orte in Ortlist angeben...
quasi schnell runtergekrackselt so:class Reisen.... int myOrtID[10]; //sollen maximal 10 orte pro reise sein int myOrtlength[10]; int mySize; ... }; //woanders ;-) for (i=0;i<reise.mysize;i++){ cout<<ortliste[myOrtID[i]]<<" Aufenthaltsdauer"<<reise.myOrtLength; }hoffe das ist ungefähr verständlich wie ich das meine würde das so gehen oder gibt es bessere vorschläge

-
Du solltest deine Klasse besser "Reise" (d.h. in der Einzahl) nennen - und "Ort" (statt "Orte"). Eine gute sinnvolle Benennung ist das A und O.
Für deine Orte innerhalb der Reise-Klasse solltest du dann eine eigene Struktur anlegen:
struct ReiseOrt // oder Aufenthalt oder ... { int OrtIndex; // alternativ: const Ort* (bzw. const Ort&) int LengthOfStay; }Und statt des Arrays würde ich einen std::vector<ReiseOrt> vorschlagen.
-
danke für die Antwort. da wir vectors noch nich behandelt haben würde ich das lieber lassen als mich da jetzt kurzfristig reinzulesen

struct ist doch quasi das gleiche wie class oder hab ich da was falsch verstanden?
Die Orte habe ich schon in ner extra klasse das problem ist in deinem fall müsste ich ja für jeden Ort der ja bei unterschiedlichen reisen unterschiedliche Aufenthaltsdauern haben kann ein extra object anlegen oder?
-
ach ne nach nochmaligen drüberlesen du meinst das ich neben Ort und Reise noch eine Klasse aufmache "Stay"(was auch immer) und diese klasse dann in den Ort mit einfließen lasse oder?
also quasiclass Stay { int OrtID int LengthOfStay } // und in der class Reise class Reise {myId myLength myPrice //dann noch das hinzufügen: Stay myOrte[]; mySizedas ergibt Sinn dann vermisch ich die Funktionen/Methoden auch nicht so...
aber ich verstehe noch nicht ganz wie ich das dann wieder aufrufen kann
sagen wir mal ich hab in der Reiselist[] 15 reisen stehen und ich müsste ja pro Reise z.B. 10 Orte hinzufügen selbst wenn ich eine klasse StayList mache müsste die ja aus einem 2x2 "feld" bestehen oder damit ich für jede Reise die OrtID's hinbekomme?!?
bzw. was ich meine wenn ich dieses Stay myOrte[] dann aufrufe muss ich ja sowieso immer die Reise mit angeben erstellt der dann für jede Reise eine eigene Stay myOrte[] oder nur eins für alle?
-
Der Vorteil von der Struktur ist, daß du dann nur noch ein Array hast. In deiner Variante müßtest du ja immer schauen, daß die zugehörigen Werte je Array-Index zusammenpassen (und wenn du ein größeres Array haben möchtest, müßtest du alle Arrays anpassen - anstatt nur das eine).
Wenn du also
Stay myOrte[10];hast, dann kannst du einfach per
myOrte[index].OrtID // bzw. myOrte[index].LengthOfStayauf die Werte zugreifen.
myOrte ist also genau so eine Membervariable wie in deinem ursprünglichen Code die Variablen myOrtID[10] und myOrtlength[10] - die Verschachtelung ist nur etwas anders.
Wenn du jetzt noch einen weiteren Wert benötigst, so kannst du dann einfach diesen zu der Struktur Stay hinzufügen (anstatt wiederum ein neues Array davon anzulegen).
Dies ist generell der Gedanke hinter der objektorientierten Programmierung!
-
Vielen Dank! werde es so ausprobieren und hoffentlich hinbekommen

Danke!
-
Hab noch ein paar Probleme

Hab wahrscheinlich irgendwas übersehen..
Damit will ich quasi die Aufenthalte der Reise hinzufügen aber irgendwie funktioniert das nicht richtig
1. bei einem gefunden Ort funktioniert es zumindest bis zum speichern der Datei dann hab ich da einen fehler aber da schau ich später mal rein.. aber wieso funktioniert es dann nicht wenn ich den Ort erst neu erstellen muss?
der Ort wird erstellt und den kann ich mir anzeigen lassen aber die Position des ortes in der Ortliste wird nicht gespeichert?!?Reisenlist::Reisenlist(): mySize(0) { } void Reisenlist::addStay(int id, Ortelist &ortelist){ bool added=false; for(int i=0; i<mySize;i++){ if (myReiselist.id()==id){ std::string name; int length; bool foundOrt=1; std::cout<<"\nBitte geben Sie den Namen des Ortes ein: \n"; std::cin>>std::ws; getline(std::cin, name); for (int j=0; j<ortelist.getMySize();j++){ if(name==ortelist.getMyOrt(j)){ std::cout<<"Geben sie die Aufenthaltsdauer an: "; std::cin>>length; myReiselist[i].setStayId(j,length,myReiselist[i].staySize()); myReiselist[i].plusStaySize(); foundOrt=true; added = true; break; }else{foundOrt=false; } } if (!foundOrt){ std::cout<<"Geben sie die Aufenthaltsdauer an: "; std::cin>>length; Orte orte(name); ortelist.addOrte(orte); myReiselist[i].setStayId(ortelist.getMySize(),length,myReiselist[i].staySize()); myReiselist[i].plusStaySize(); added=true; } } } if (!added)std::cout<<"\nUngültige Reise eingegeben\n"; }die methoden dazu:
#ifndef STAYS_H #define STAYS_H #include <string> class Stays { private: int myStayId; int myStayLength; public: Stays(); Stays(int myStayId,int myStayLength); //getter int getStayId()const{return myStayId;} int getStayLength()const{return myStayLength;} //setter void setStayId(int stayId){myStayId = stayId;} void setStayLength(int stayLength){myStayLength = stayLength;} std::string serialize() const; }; #endif // STAYS_Hund
void plusStaySize(){myStaySize+=1;}in der Reisen Klasse
2.Problem bei der Ausgabe gibt der anstelle der korrekten Stays immer irgendeine leere Stay klasse aus also kommt bei
[i] int stayLength(int pos) const{return myStays[pos].getStayLength();}
int getStayId(int pos) const{return myStays[pos].getStayId();}*
immer return 0; aber da sollte eigentlich ja die id/aufenthaltsdauer der Reise stehen wenn ich im debugger Die reise selber anschaue steht da auch alles richtig drin und der übergibt die korrekten Werte aber greift irgendwie auf ein anderes myStays zu
Bei der Ausgabe
#ifndef REISEN_H #define REISEN_H #include <iostream> #include <string> #include "stays.h" const int MAXORT=10; class Reisen { private: int myId; double myPrice; int myLength; Stays myStays[MAXORT]; int myStaySize; public: Reisen(); Reisen(int myId, double myPrice, int myLength, Stays myStays[MAXORT], int staySize); //getter int id() const {return myId;} double price() const{return myPrice;} int length() const{return myLength;} int staySize() const{return myStaySize;} int stayLength(int pos) const{return myStays[pos].getStayLength();} int getStayId(int pos) const{return myStays[pos].getStayId();} //setter void setId(int id){myId=id;} void setStayId(int stayId,int stayLength, int s){myStays[s].setStayLength(stayLength); myStays[s].setStayId(stayId); } void setPrice(double price) {myPrice = price;} void setLength(int length) {myLength = length;} void setStaySize(int staySize){myStaySize = staySize;} //andere Methoden void createStay(int stayId, int stayLength); void plusStaySize(){myStaySize+=1;} std::string serialize() const; }; std::ostream& operator<<(std::ostream& str, const Reisen& reisen); Reisen createReiseFromString(const std::string& s); #endif // REISEN_H#ifndef REISENLIST_H #define REISENLIST_H #include "reisen.h" #include <iostream> #include <string> #include <ortelist.h> const int MAXSIZE2=100; class Reisenlist { private: Reisen myReiselist[MAXSIZE2]; int mySize; public: Reisenlist(); void addReisen(const Reisen& reisen); void readFile(const std::string filename); void show( Ortelist ortelist); void writeFile(const std::string filename); void searchMax(); void searchMin(); void preisProTag(); void addStay(int id,Ortelist &ortelist); }; #endif // REISENLIST_Hvoid Reisenlist::writeFile(const std::string filename){ std::ofstream fo(filename.c_str()); if (!fo){ std::cout<<"Datei "<<filename<<" kann nicht beschrieben werden.\n"; return; } //nur zur erklärung fo<<"# ID^Preis^Reisenlänge^AnzahlBesuchterOrte\n"; fo<<"# 2. Zeile: DazugehörendeOrte^Aufenthaltsdauer\n"; for (int i= 0; i< mySize; i++) { fo<<myReiselist[i].serialize()<<std::endl; fo<<myReiselist[i].staySize()<<"^"; for(int j=0;j<myReiselist[i].staySize();j++){ fo<<myReiselist[i].getStayId(j)<<"^"<<myReiselist[i].stayLength(j)<<"^"; } if (myReiselist[i].staySize()==0){ fo<<"0^0^0"; } fo<<std::endl; } fo.close(); }falls ich was vergessen habe zu posten kommt das gerne noch mit hin..
-
So ganz durchschaue ich deinen Code nicht (die Methode addStay macht m.E. zu viel und sollte auf mehrere kleinere Funktionen aufgeteilt werden).
Aber besser ist es sowieso, wenn du selber den Fehler findest.
Was für eine IDE (Editor) verwendest du denn? Am besten, du lernst den Umgang mit dem Debugger (Stichworte: Breakpoint, Watch, CallStack).
-
Ich kann dir leider keine Lösung sagen, aber:
Stichwort ist hierminimales Beispiel. Manchmal entdeckt man auch selber leicht den Fehler, wenn man versucht das Problem aufs Wesentliche zu beschränken.
-
Verwende QT creator und mit dem Debugger arbeite ich schon aber von watch und Callstacks noch nié was gehört (es sei denn watch bezeichnet einfach die Möglichkeit variableninhalte anzuschauen). Meines erachtens schickt der alles richtig hin und her hab mein beitrag davor nochmal editiert, kann ich dir irgendwas verständlicher machen an dem Code?
quasi sobald die Id gefunden wurde schaut er ob es den Ort schon gibt oder nicht
und wenn es ihn gibt sucht er nach der Position in die der Ort gespeichert ist übergibt das an myStayId,
wenn es ihn nicht gibt legt er einen Neuen Ort an und übergibt die position wo er den neuen Ort gespeichert hat an myStayIdkönnte es daran liegen das ich die ortelist auf eine bestimmte Art übergebe?
wobei den Ort erstellt es ja
-
f (!foundOrt){ std::cout<<"Geben sie die Aufenthaltsdauer an: "; std::cin>>length; Orte orte(name); ortelist.addOrte(orte); myReiselist[i].setStayId(ortelist.getMySize(),length,myReiselist[i].staySize()); myReiselist[i].plusStaySize(); added=true;hab den Fehler gefunden das muss heißen
ortelist.getMySize()-1da bei addOrte ja auch die ortelist.mySize schon +1 gemacht wird hab ich quasi immer eine postition zu viel angegeben was aber ja nicht auffällt da die ja alle initialisiert werden
