Frage zu Headerdateien



  • Danke SeppJ.

    Nein, ich habe C++ von A bis Z nicht gelesen. Diese Codebeispiele bzw. Code von mir stammt übrigens großteils von unserem Lehrer da ich die Musterlösung durcharbeiten will... Ich kann also nichts dafür, wenn uns der Lehrer solch (anscheinend) schlechten Code "beibringt".

    Da es "nur" zu Übungszwecken ist, würde ich mich freuen, wenn du über diese, ich nenn es jetzt mal Schwachstellen, drüber wegschaust. Ich hab jetzt meinen Code noch weiter geschrieben und hab nun ein Problem in der Zeile 11 der Verwaltung.cpp. Wenn aus der main.cpp der neue Mitarbeiter "p2" hinzugefügt werden soll, bekomm ich einen "Debug Assertion Fail". Außerdem sagt mir der Compiler, dass in Zeile 125 der Datei xfunctional eine int-Variable auf booleschen Wert gesetzt wird. Ich hab allerdings nirgends eine int-Variable mit booleschen Inhalt verwendet. Ich weiß nicht wo der Fehler steckt. Könnt ihr mir helfen?

    Hier nun der Code:

    #include<iostream>
    #include"verwaltung.h"
    using namespace std;
    
    int main()
    {
    	person p1, p2, p3;
    	verwaltung neueVerw;
    
    	//Mitarbeiter-Daten
    	p1.wohnort = "aaa";
    	p1.nachName = "xxx";
    
    	p2.wohnort = "bbb";
    	p2.nachName = "yyy";
    
    	p3.wohnort = "ccc";
    	p3.nachName = "zzz";
    
    	//Mitarbeiter in der Verwaltung anlegen
    	neueVerw.addMitarbeiter(p1);
    	neueVerw.addMitarbeiter(p2);
    	neueVerw.addMitarbeiter(p3);
    
    	//bestimmten Mitarbeiter entlassen
    	neueVerw.druckeMitarbeiterListe();
    	neueVerw.entlasseMitarbeiter("Mehrl");
    	neueVerw.druckeMitarbeiterListe();
    
    return 0;
    }
    
    #ifndef VERWALTUNG__H
    #define VERWALTUNG__H
    
    #include<set>
    #include<string.h>
    using namespace std;
    
    #include"Person.h"
    
    class verwaltung
    {
    private:
    	char* faName;
    	set<person> mitarbeiter;
    
    public:
    	void addMitarbeiter(person);		//Neuen Mitarbeiter hinzufügen
    	void entlasseMitarbeiter(char*);		//Mitarbeiter mit dem angegebenen Namen entfernen
    	void gehaltMitarbeiter(char*, int);	//Einem Mitarbeiter ein Gehalt hinzufügen
    	void druckeMitarbeiterListe();	//Alle Mitarbeiter ausgeben
    	int berechneKosten();	//Gehälter aller Mitarbeiter aufaddieren und ausgeben
    	int anzahlMitarbeiter();	//Gibt die Anzahl der Mitarbeiter aus
    };
    
    #endif
    
    #include<iostream>
    #include<set>
    using namespace std;
    
    #include"Verwaltung.h"
    
    void verwaltung::addMitarbeiter(person p)
    {
    	mitarbeiter.insert(p);
    }
    
    void verwaltung::entlasseMitarbeiter(char* name)
    {
    	set<person>::iterator iter = mitarbeiter.begin();
    
    	while(iter != mitarbeiter.end())
    	{
    		if(!strcmp(name, (*iter).nachName))
    		{
    			mitarbeiter.erase(iter);
    			return;
    		}
    
    		iter++;
    	}
    }
    
    void verwaltung::druckeMitarbeiterListe()
    {
    	set<person>::iterator iter = mitarbeiter.begin();
    
    	while(iter != mitarbeiter.end())
    	{
    		cout << *iter;
    		iter++;
    	}
    }
    
    #ifndef PERSON__H
    #define PERSON__H
    
    #include<iostream>
    using namespace std;
    
    class person
    {
    public:
    	char* nachName;
    	char* wohnort;
    	int gehalt;
    
    	friend ostream& operator << (ostream&, const person);
    	friend int operator < (const person, const person);
    	person& operator = (person&);
    
    	person()
    	{
    
    	}
    
    	~person()
    	{
    
    	}
    };
    
    #endif
    
    #include<string.h>
    #include"Person.h"
    
    ostream& operator << (ostream& o, const person p)	//Überladung des Ausgabeoperators "<<"
    {
    	return o << p.nachName << " " << p.wohnort << " " << p.gehalt << " " << endl;
    }
    
    int operator < (const person p1, const person p2)
    {
    	return strcmp(p1.nachName, p2.nachName);
    }
    
    person& person::operator = (person &prs)	//Überladung des Zuweisungsoperators "="
    {
    	nachName = prs.nachName;
    	gehalt = prs.gehalt;
    	wohnort = prs.wohnort;
    
    return *this;
    }
    

    PS: Kann man hier im Board eigentlich irgendwie Dateien hochladen? Ich finde, dass viel Code irgendwann unübersichtlich wird...; besonders hier im Board.


  • Mod

    Mit deinem Code kann ich keinen konkreten Fehler erzeugen. Er ist zwar kriminell schlecht und enthält viele fragwürdige Konstrukte die bei der kleinsten Belastungsprobe explodieren werden, aber das einzige was derzeit wirklich tatsächlich falsch ist, ist die Ausgabe des undefinierten Gehaltsfeldes. Das sollte hier aber nicht abstürzen.

    Sobald du aber nur kleinste Änderungen vornimmst kann das ganz anders aussehen. Der Code ist wohl das wackeligste Kartenhaus aller Zeiten. Potentielle Fehler: Überall. Kann ich nicht alle auflisten. Aber noch hält es.

    Hast du die Chance den Kurs abzubrechen oder brauchst du die Note?

    PS: Kann man hier im Board eigentlich irgendwie Dateien hochladen? Ich finde, dass viel Code irgendwann unübersichtlich wird...; besonders hier im Board.

    Nein und das ist auch gut so. Die beste Methode Fehler selber zu finden, ist Code soweit zusammenzukürzen, bis der Fehler gerade eben noch auftritt. Dann wäre er auch kurz genug für's Forum, aber dann hat man den Fehler meistens schon alleine gefunden. Merke: Das Forum ist die Anlaufstelle, wenn man selber nicht mehr weiter weiß. 2000 Zeilen Code zu posten und zu sagen, dass irgendwo ein Fehler drin ist kommt nicht in Frage. Solche Vorarbeit muss man selber leisten.



  • Sofern vertretbar (wenn Du vom Lehrer dann keinen auf den Deckel bekommst), verwende std::string statt char*. Und sonst mach bitte all die using namepsace std; Direktiven aus den Headerdateien raus. Das gehört sich nämlich nicht, da du damit über all dort den globalen Namensraum verpestest, wo eine solche Headerdatei inkludiert wird...

    Der selbstdefinierte Konstruktor, Destruktor und Zuweisungsoperator für person ist überflüssig! Und hier und da fehlt ein "const" was sonst noch üblich gewesen wäre...


  • Mod

    krümelkacker schrieb:

    Der selbstdefinierte Konstruktor, Destruktor und Zuweisungsoperator für person ist überflüssig!

    Kommt drauf an. Bei char* als Member sollte da eigentlich schon was hin, aber es sollte komplett anders aussehen als hier.



  • Ich hab mir jetzt nochmals meinen Code genau angesehen und dabei festgestellt, dass der Fehler immer dann kommt, wenn das Programm die weitere Person in die set speichern will. Dabei ist mir aufgefallen, dass er versucht die weitere Person auf die gleiche Stelle zu speichern, wo schon eine Person ist.

    Ich hab mir nun ein kleines Programm geschrieben indem ich feststellen konnte, wie diese insert() Methode arbeitet. Dabei hab ich entdeckt, dass man bei insert() den iterator nicht weiterzählen lassen muss, sonder das macht insert() selber.

    Ich weiß leider jetzt aber noch immer nicht was da faul sein könnte.


  • Mod

    vip@r schrieb:

    Ich weiß leider jetzt aber noch immer nicht was da faul sein könnte.

    Tja. Hast du mal an die revolutionäre Idee gedacht. den Code zeigen, der den Fehler verursacht? Das was du oben gezeigt hast, ist nur gefährlich, nicht falsch. Und da wird auch nix weitergezählt oder so, daher ist wohl anzunehmen, dass du mit ganz anderem Code arbeitest.



  • @SeppJ:

    Auch wenn das jetzt etwas spät ist, aber hier ist der Code:

    Diese Methode,...

    void verwaltung::addMitarbeiter(person p)
    {
    	set<person>::iterator iter = mitarbeiter.end();
    
    	mitarbeiter.insert(p);
    }
    

    ..., wird von diesem Aufruf aus der main aufgerufen:

    neueVerw.addMitarbeiter(p1);
    neueVerw.addMitarbeiter(p2);
    neueVerw.addMitarbeiter(p3);
    

    p1 funktioniert tadellos; erst bei p2 hakts dann und das Programm bricht mir mit einem Fenster mit diesem Inhalt ab: http://s14.directupload.net/file/d/2882/u79psxp8_jpg.htm

    Edit: Eigentlich brauch ich doch diesen Iterator gar nicht, das müsste doch auch ohne gehen...; das Problem besteht aber dann dennoch weiterhin!



  • Dein operator< ist fehlerhaft, er berechnet nicht wirklich <. Vermutung: es kann gleichzeitg p1<p2 und p2<p1 wahr sein.



  • Wenn ich p2 in der Verwaltung ablegen will, dann liefert strcmp() eine 1 zurück. Laut der C++Referenz heißt das dann Folgendes: A value greater than zero indicates that the first character that does not match has a greater value in str1 than in str2.

    Wie wirke ich dem nun entgegen? Besser gefragt: Was ist daran nun falsch?



  • vip@r schrieb:

    Was ist daran nun falsch?

    Warum sollte etwas daran falsch sein?



  • Nein, natürlich nicht an meiner Erklärung sondern an meinem Code...



  • Operator < muss bool zurückgeben. Dabei bedeutet true dass das erste Argument kleiner als das zweite ist, false bedeutet dass das erste Argument größer oder gleich dem Zweiten ist. strcmp gibt aber int zurück (-1: str1 < str2, 0:str1=str2, 1:str1>str2)
    Das heißt, dein operator< muss so aussehen:

    bool operator<(const person& p1, const person& p2) {
      if(strcmp(p1.nachName,p2.nachName) < 0) return true;
      return false;
    }
    


  • pyhax schrieb:

    Das heißt, dein operator< muss so aussehen:

    bool operator<(const person& p1, const person& p2) {
      if(strcmp(p1.nachName,p2.nachName) < 0) return true;
      return false;
    }
    

    Nein, er muss so aussehen:

    bool operator<(const person& p1, const person& p2) {
      return strcmp(p1.nachName, p2.nachName) < 0;
    }
    


  • vip@r schrieb:

    Da es "nur" zu Übungszwecken ist, würde ich mich freuen, wenn du über diese, ich nenn es jetzt mal Schwachstellen, drüber wegschaust.

    Ganz falscher Ansatz. Grade wenn du noch am Üben bist, sollten die schlechten Details alle angemerkt werden, damit du es richtig übst und dir nicht den gleichen fehleranfälligen Stil angewöhnst, den dein Lehrer offenbar intus hat. Den später wieder loszuwerden ist nämlich nicht gerade einfach.


Anmelden zum Antworten