Ich schlachte meinen C-Compiler!! (kompilierfehler)



  • also erstmal:

    Header

    #ifndef _TERMINV_H
    #define _TERMINV_H
    #include <list>
    #include "termin.h"
    // using namespace std; - kein using im Header führt zu Abhängigkeiten von der Includereihenfolge
    
    class CTerminV {
      protected:
        std::list<CTermin> termine;
        std::string dateiName;
    
      public:
        std::list<CTermin>::iterator getTerminIterator(const unsigned long _id);
        CTermin *getTermin(const unsigned long _id);  
        void terminEinfuegen(CTermin &t);
        bool terminLoeschen(const unsigned long _id);
    }; // <-- hier kommt ein Strichpunkt hin
    
    #endif // _TERMINV_H
    

    Quelldatei (ist nicht abhängig von Klassen wie in Java)

    #include "terminv.h"
    
    using namespace std; // hier meinetwegen
    
    list<CTermin>::iterator CTerminV::getTerminIterator(const unsigned long _id) {
      list<CTermin>::iterator it = Termine.begin();
      while (it != this->Termine.end()) {
        if (it->getId() == _id) { // <-- da it ein iterator ist braucht man den indirekten Zugriffsoperator "->" und nicht "." it->getId() ist äquivalent zu (*it).getId(); 
          return it;
        }
        it++;
      }
      return NULL;
    } // <-- den ; brauchst du in C++  nicht (in Java auch nicht)
    
    CTermin* CTerminV::getTermin(const unsigned long _id) {
      list<CTermin>::iterator it = Termine.begin();
      while (it != this->Termine.end()) {
        if (it->getId() == _id) { // das gleiche wie vorhin
          return new CTermin(*it); //achtung jeder mit new angeforderte Speicher muss auch mit delete wieder freigegeben werden sonst hast du ein Speicherleck
        }
        else {
          return NULL; //<-- groß schreiben oder gleich einfach nur 0 nehmen
        }
      }
    }
    
    void CTerminV::terminEinfuegen(CTermin &t) {
      t.setNeueId();
      this->Termine.push_back(t);
      this->Termine.sort();
    }
    
    bool CTerminV::terminLoeschen(unsigned long _id) {
      list<CTermin>::iterator it = getTerminIterator(_id);
      if (it != NULL) { //<-- ein Iterator ist nicht zwangsläufig ein Zeiger
        this->Termine.erase(it);
        return true;
      } 
      else {
        return false;
      }
    }
    

    Das waren nur n paar Fehler die ich ausgebessert habe, du solltest dir die STL insbesondere den list<> Container und die ITeratoren nochmal anschauen.
    Und natürlich das ganze mit nem C++ Compiler compilieren und nicht mit nem C-Compiler 😉



  • Warte mal ... da hat dein Programm aber nen paar logische Schwachstellen ^^

    CTermin* CTerminV::getTermin(const unsigned long _id) {
      list<CTermin>::iterator it = Termine.begin();
      while (it != this->Termine.end()) {
        if (it->getId() == _id) { // das gleiche wie vorhin
          return new CTermin(*it); //achtung jeder mit new angeforderte Speicher muss auch mit delete wieder freigegeben werden sonst hast du ein Speicherleck
        }
        else {
          return NULL; //<-- groß schreiben oder gleich einfach nur 0 nehmen
        }
      }
    }
    

    ...
    entspricht:

    CTermin* CTerminV::getTermin(unsigned long id) 
    {
        if ((*(Termine.begin())).getId() == _id))
            return new CTermin(*(Termine.begin()));
        return NULL;
    }
    

    ... ich denke mal eher das du nach id suchen willst?

    bool CTerminV::getTermin(unsigned long id) 
    {
        for (std::list<CTermin>::iterator it = m_Termine.begin(); it != m_Termine.end(); ++it) if ((*it).GetId() == id) { termin = (*it); return true; }
        return false;
    }
    

    ...



  • Darum gefällt mir der indirekte ZUgriffsoperator besser als Klammern und ".":

    (D)Evil schrieb:

    CTermin* CTerminV::getTermin(unsigned long id) 
    {
        if ( (*(Termine.begin())).getId() == _id ) // <-- hier war ne Klammer zuviel
            return new CTermin(*(Termine.begin()));
        return NULL;
    }
    


  • #ifndef TERMIN_MANAGER_H__INCLUDED
    #define TERMIN_MANAGER_H__INCLUDED
    
    #include <list>
    #include "termin.h"
    
    class TerminManager 
    {
    public:
        Termin&		get_termin(unsigned long);  
    	Termin const &	get_termin(unsigned long) const;
        void		add_termin(const Termin&);
        void		delete_termin(unsigned long);
    
    private:
    	std::list<Termin>	m_items;
    	std::string			m_filename;
    };
    
    #endif // TERMIN_MANAGER_H__INCLUDED
    
    Termin& TerminManager::get_termin(unsigned long id)
    {
    	for (std::list<Termin>::iterator it = m_items.begin(); it != m_items.end(); ++it)
    		if ((*it).get_id() == id)
    			return (*it);
    	throw std::invalid_argument("Item does not exist");
    }
    
    Termin const& TerminManager::get_termin(unsigned long id) const
    {
    	for (std::list<Termin>::const_iterator it = m_items.begin(); it != m_items.end(); ++it)
    		if ((*it).get_id() == id)
    			return (*it);
    
    	throw std::invalid_argument("Item does not exist");
    }
    
    void TerminManager::add_termin(const Termin& termin)
    {	
    	m_items.push_back(termin);	
    }
    
    void TerminManager::delete_termin(unsigned long id)
    {
    	for (std::list<Termin>::iterator it = m_items.begin(); it != m_items.end(); ++it)
    		if ((*it).get_id() == id)
    		{
    			m_items.erase(it);
    			return;
    		}
    	throw std::invalid_argument("Item does not exist");
    }
    

    ...



  • klimmbimm schrieb:

    ...
    void CTerminV::terminEinfuegen(CTermin &t) {
    t.setNeueId();
    this->Termine.push_back(t);
    this->Termine.sort();
    };
    ...

    Also wenn die Teile beim Einfügen sortieren möchtest, solltest Du über std:.set bzw. std::multiset (oder map/multimap) nachdenken. Die macht das automatisch für Dich.

    Gruß,

    Simon2.



  • vielen dank für alle antworten!
    das gibt mir hoffnung zum weiterhacken :), werde morgen weitermachen und berichten!



  • @Checker&Murckser
    Danke nochmal und die std und list dinger kann ich mir leider nicht nochmal anschauen, dazu fehlt mir die motivation 😉
    Ich bin eingefleischter Java Programmierer und wir machen diese Terminverwaltung gerade an der fh.
    Ich mache ein berufsbegleitendes studium und arbeite seit jahren nur mit java, deswegen bin ich schon froh (und das reicht mir auch) wenn ich dann bald C++ code wenigstens lesen kann.
    Also wenn du hilfe in Java brauchst einfach pm schicken.

    @Evil
    Ja da hast du recht da war ich wohl etwas hektisch und wollte wohl nachhause 😉
    Habs ausgebessert, danke!
    Wenns nach mir ginge würde ich auch lieber in englisch hacken und das mit den exceptions sieht auch besser aus als mein code, aber unser dozent wollte uns wohl nicht überfordern da wir auch anfänger im kurs haben.

    @simon
    tjo sag das mal unserem dozent 😉
    der scheint wohl nicht ganz auf dem laufenden zu sein, ich werd bei der nächsten vorlesung mal klugscheißen und ihn fragen 😉

    So und nun *trommelwirbel* kommt meine komplette Terminverwaltung (inklusive kompilierfehlern natürlich)

    HEADER:

    #ifndef _TERMINV_H
    #define _TERMINV_H
    #include <list>
    #include "termin.h"
    
    class CTerminV {
    
    protected:
    	list<CTermin> termine;
    	string dateiName;
    
    public:
    	list<CTermin>::iterator getTerminIterator(const unsigned long _id);
    	CTermin *getTermin(const unsigned long _id);
    	void terminEinfuegen(CTermin &t);
    	bool terminLoeschen(const unsigned long _id);
    	bool terminBearbeiten(CTermin &t);
    	string terminAnzeigen(const unsigned long _id);
    	void getTermine(list<CTermin> &_terminList, CDatumUhrzeit _von, CDatumUhrzeit _bis);
    	string getDateiName();
    	void setDateiName(string _s);
    	bool terminListeSpeichern(string _dateiName);
    	bool terminListeLaden();
    };
    
    #endif // _TERMINV_H
    

    CLASS:

    #include "terminv.h"
    
    list<CTermin>::iterator CTerminV::getTerminIterator(const unsigned long _id) {
    	list<CTermin>::iterator it = termine.begin();
    	while (it != termine.end()) {
    		if (it->getId() == _id) {
    			return it;
    		}
    		it++;
    	}
    	return termine.end();
    }
    
    CTermin *CTerminV::getTermin(const unsigned long _id) {
    	list<CTermin>::iterator it = getTerminIterator(_id);
    	if (it != termine.end()) {
    		return new CTermin(*it);
    	} else {
    		return NULL;
    	}
    }
    
    void CTerminV::terminEinfuegen(CTermin &t) {
    	t.setNeueId();
    	termine.push_back(t);
    	termine.sort();
    }
    
    bool CTerminV::terminLoeschen(unsigned long _id) {
    	list<CTermin>::iterator it = getTerminIterator(_id);
    	if (it != termine.end()) {
    		termine.erase(it);
    		return true;
    	} else {
    		return false;
    	}
    }
    
    bool CTerminV::terminBearbeiten(CTermin &t) {
    	bool loeschenErfolgreich = terminLoeschen(t.getId());
    		if (loeschenErfolgreich) {
    			termine.push_back(t);
    			termine.sort();
    		} else {
    			return false;
    		}
    }
    
    string terminAnzeigen(const unsigned long _id) {
    	CTermin* t = getTermin(_id);
    	if (t != NULL) {
    		return t.toString();
    	} else {
    		return "Termin mit der ID: " << _id << " nicht gefunden!";
    	}
    }
    
    void getTermine(list<CTermin> &_terminList, CDatumUhrzeit _von, CDatumUhrzeit _bis) {
    	_terminList.clear();
    	list<CTermin>::iterator it = _terminList.begin();
    	while (it != termine.end()) {
    		if (_von <= it->getBeginn() && _bis >= it->getEnde()) {
    			_terminList.push_back(*it);
    		}
    		it++;
    	}
    }
    
    string getDateiName() {
    	return dateiName;
    }
    
    void setDateiName(string s) {
    	dateiName = s;
    }
    
    bool terminListeSpeichern(string _dateiName) {
    	ofstream *outputDatei;
    	outputDatei = new ofstream(_dateiName.c_str());
    	if (! outputDatei->is_open()) {
    		cout << "Fehler beim oeffnen der Datei!" << endl;
    		return false;
    	}
    	*outputDatei << CTermin::next_id << "|"
    				 << termine.size() << "|";
    
    	list<CTermin>::iterator it = termine.begin();
    	while (it != termine.end()) {
    		*outputDatei << *it;
    		*outputDatei << '\n';
    		*outputDatei << '|';
    		it++;
    	}
    
    	outputDatei->close();
    	return true;
    }
    
    bool terminListeLaden() {
    	ifstream *inputDatei;
    	inputDatei = new ifstream(dateiName.c_str());
    	char c;		
    	unsigned int terminCounter;
    	unsigned int i;
    	CTermin *t;
    
    	if (! inputDatei->is_open()) {
    		cout << "Fehler beim oeffnen der Datei!" << endl;
    		return false;
    	}
    
    	*inputDatei >> CTermin::next_id;
    	*inputDatei >> c;
    	*inputDatei >> terminCounter;
    	*inputDatei >> c;
    	for (i = 0; i < terminCounter; i++) {
    		t = new CTermin();
    		*inputDatei >> *t;
    		*inputDatei >> c;
    		while (c != '|') { // '\n' usw. bis einschl. '|' lesen
    			*inputDatei >> c; 
    		}
    		this->Termine.push_back(*t);
    	}
    	this->Termine.sort();
    }
    

    Er meckert bei Zeile 14 der class file,

    CTermin *CTerminV::getTermin(const unsigned long _id) {

    mit dieser Fehlermeldung:

    error C3861: 'getTermin': identifier not found



  • Hmm sry, entweder ich bin gerade auch mit Blindheit geschlagen oder zu doof den Fehler zu sehen.

    Auf jeden Fall, scheinen bei dir im Code einige viele "std::" (bzw. im Source ein using namespace std;) zu fehlen.
    Des weiteren frage ich mich, wieso du bei CTermin ein dynamisches Objekt zurückgibst und auch sonst alle möglichen dynamischen Objekte mit new anforderst, wo du acuh normale Stackobjekte nehmen könntest. Außerdem gibst du den angeforderten Speicher nicht wieder mit delete frei (das ist hier zwingend notwendig, C++ hat keinen Garbage Collector!).
    Wenn ich nachher was Zeit finde, füge ich das ganze mal bei mir ein und compiliere das - halt mit ner fiktiven Klasse termin, vllt. kann ich dir dann sagne, wie du den Fehler behebst.

    /Edit://

    Was mir sonst noch spontan ins Auge fällt:

    string terminAnzeigen(const unsigned long _id) {
        CTermin* t = getTermin(_id);
        if (t != NULL) {
          return t.toString();
        } else {
            return "Termin mit der ID: " << _id << " nicht gefunden!";
        }
    }
    

    Hier stimmt gleich mehreres nicht.
    Die Zuweisung passt noch:
    Aber dann musst du (a) über den indirekten Zugriffsoperator -> (oder (*t).toString()) auf die Funktion toString() zugreifen und (b) kann man hier das Speicherleck gut sehen.
    Du hast in getTermin Speicher auf dem Heap mittels "new" angefordert, gibst ihn aber nicht mehr frei, nach dem Verlassen von terminAnzeigen liegt also auf dem Heap ein Objekt, das nicht mehr benötigt wird und dessen Speicher "tot" ist. Bei einer häufigen Anzahl von Aufrufen der Funktion wird dein Heap also schnell mit toten Objekten zugemüllt.
    ➡ ➡ Und (c) du hast den Klassennamen vergessen anzufügen "CTerminV::" daher wohl auch er Compilerfehler

    So wäre es richtig:

    std::string CTerminV::terminAnzeigen(const unsigned long _id) {
        CTermin* t = getTermin(_id);
        if (t != NULL) {
          std::string s = t->toString();
          delete t;
          return s;
        } else {
            return "Termin mit der ID: " << _id << " nicht gefunden!";
        }
    }
    

    Am schönste wäre es natürlich, wenn getTermin von Anfang an ein Stackobjekt zurückliefern würde:

    CTermin CTerminV::getTermin(const unsigned long _id) {
        list<CTermin>::iterator it = getTerminIterator(_id);
        if (it != termine.end()) {
            return *it;
        } else {
            throw std::exception("invalid id");
        }
    } 
    
    std::string CTerminV::terminAnzeigen(const unsigned long _id) { 
        try {
          CTermin t = getTermin(_id); 
          return t.toString();
        } catch(...) {
            return "Termin mit der ID: " << _id << " nicht gefunden!";
        }
    }
    


  • Das Problem ist mein Dozent, er hat uns folgendes Vorgegeben und ich kenne ihn nicht und weiß nicht wie er darauf reagiert wenn ich das dann sauberer aber nicht nach seinen wunsch implementiere.
    Wahrscheinlich wollte er dass wir das Problem mit der Speicherverwaltung von C++ kennenlernen.

    e) Termin aus der Liste kopieren: Deklarieren und implementieren Sie eine weitere Methode, die mit Hilfe der Funktion in d) einen Termin als Kopie aus der Liste holt:
    // einzelnen Termin anhand der Id aus der Terminliste holen
    // (liefert Kopie, die wieder freigegeben werden muss)
    CTermin *getTermin(unsigned long id);

    Ohja ich habe bei den ganzen neuen Methode das CTerminV:: vergessen!

    Jetzt meckert er auch nicht mehr an dieser Stelle, sondern hier:

    return "Termin mit der ID: " << _id << " nicht gefunden!";
    

    error C2296: '<<' : illegal, left operand has type 'const char [20]'

    Nochmal alle meine anfängerfehler zusammengefasst:
    1. Bei nem Pointer mit . die methoden aufrufen und sonst mit ->
    2. Klasse:: vor jeden Methodennamen
    3. using namespace std nicht ins header sondern in die class file

    Bitte korrigier mich wenn ich da was falsch verstanden habe.



  • std::string CTerminV::terminAnzeigen(const unsigned long _id) 
    {
        CTermin* t = getTermin(_id);
        if (t != NULL) {
          std::string s = t->toString();
          delete t;
          return s;
        } else {
            std::stringstream s;
            s << "Termin mit der ID: " << _id << " nicht gefunden!";
            return s.str();
        }
    }
    


  • klimmbimmNoLogin schrieb:

    Nochmal alle meine anfängerfehler zusammengefasst:
    1. Bei nem Pointer mit . die methoden aufrufen und sonst mit ->
    2. Klasse:: vor jeden Methodennamen
    3. using namespace std nicht ins header sondern in die class file

    Bitte korrigier mich wenn ich da was falsch verstanden habe.

    nein 1.:
    Methodenaufrufe von Stackobjekten generell mit Objekt.Methode
    bei Pointern bzw. dynamischen Objekten (also alles was mit new angefordert wurde) mit objekt->Methode bzw. (*objekt).Methode()
    2.:
    wenn die Methode in einer KLasse ist, muss man das bei der Definition im Implementierungsfile (also deinem CLASS file) machen.
    3.: ja - also wenn dann in die Quelldatei, niemals in nen Header - da immer schön
    std:: vorschreiben.

    /Edit:
    Zu The-Kennys Code: #include <sstream> nicht vergessen - da ist std::stringstream drin untergebracht

    /Edit2:
    als Umsteighilfe von Java nach C++

    N Stackobjekt legst du so an:

    { // irgendein Block, Funktion, if-Prozedur, for-Schleife, ...
      TObjekttyp Bezeichner;
    } // Stackobjekt wird beim Verlassen des Blocks automatisch zerstört
    

    ein dynamisches so:

    { // irgendein Block, Funktion, if-Prozedur, for-Schleife, ...
      TObjekttyp * Bezeichner = new TObjekttyp ; // Pointer namens Bezeichnerbekommt ein neues Objekt vom Typ TObjekttyp zugewiesen
    } 
    /* ab hier kannst du nicht mehr mittels bezeichner darauf zugreifen, Objekt bleibt sofern nicht im Block schon per "delete Bezeichner" entfernt bestehen 
     :arrow_right: entweder Speicherleck, oder es gibt bereits einen anderen Pointer, der auf das Objekt zugreift und es auch zerstören kann 
    - wie oben in dem verbesserten Codesnippet mit getTermin und terminAnzeigen gezeigt - hier übernimmt die Methode, die das Objekt zurückgeliefert kriegt die Zerstörung per delete*/
    

    Anm.
    Du solltest die Speicherverwaltung in deinem Code komplett bereinigen, d.h. allen angeforderten Speicher wieder freigeben, sonst wird dein Lehrer das sicher negativ bewerten.



  • Ich denke ich habe jetzt alle Speicherlecks behoben, d.h. überall wo ich ein new gefunden habe nach der Verwendung das Objekt gelöscht.

    Im header habe ich brav vor jeden string ein std:: gemacht.

    Den stringstream habe ich auch eingebaut, danke kenny!

    Die komplette Terminverwaltung kommt jetzt ohne Kompilierfehler durch, aber stürzt hier und da ab 😉

    TerminVerwaltung:

    #include "terminv.h"
    #include <sstream>
    using namespace std;
    
    list<CTermin>::iterator CTerminV::getTerminIterator(const unsigned long _id) {
    	list<CTermin>::iterator it = termine.begin();
    	while (it != termine.end()) {
    		if (it->getId() == _id) {
    			return it;
    		}
    		it++;
    	}
    	return termine.end();
    }
    
    CTermin *CTerminV::getTermin(const unsigned long _id) {
    	list<CTermin>::iterator it = getTerminIterator(_id);
    	if (it != termine.end()) {
    		return new CTermin(*it);
    	} else {
    		return NULL;
    	}
    }
    
    void CTerminV::terminEinfuegen(CTermin &t) {
    	t.setNeueId();
    	termine.push_back(t);
    	termine.sort();
    }
    
    bool CTerminV::terminLoeschen(unsigned long _id) {
    	list<CTermin>::iterator it = getTerminIterator(_id);
    	if (it != termine.end()) {
    		termine.erase(it);
    		return true;
    	} else {
    		return false;
    	}
    }
    
    bool CTerminV::terminBearbeiten(CTermin &t) {
    	bool loeschenErfolgreich = terminLoeschen(t.getId());
    		if (loeschenErfolgreich) {
    			termine.push_back(t);
    			termine.sort();
    		} else {
    			return false;
    		}
    }
    
    string CTerminV::terminAnzeigen(const unsigned long _id) {
    	CTermin* t = getTermin(_id);
    	if (t != NULL) {
    		string s = t->toString();
    		delete t;
    		return s;
    	} else {
    		std::stringstream s;
    		s << "Termin mit der ID: " << _id << " nicht gefunden!";
    		return s.str();
    	}
    }
    
    void CTerminV::getTermine(list<CTermin> &_terminList, CDatumUhrzeit _von, CDatumUhrzeit _bis) {
    	_terminList.clear();
    	list<CTermin>::iterator it = _terminList.begin();
    	while (it != termine.end()) {
    		//konnte hier kein <= verwenden da der operator nicht implementiert ist
    		//z.b. beginn 3.7.07 ende 5.7.07, von 2.7.07 bis 6.7.07
    		if (_von < it->getBeginn() && it->getEnde() < _bis) {
    			_terminList.push_back(*it);
    		}
    		it++;
    	}
    }
    
    string CTerminV::getDateiName() {
    	return dateiName;
    }
    
    void CTerminV::setDateiName(string s) {
    	dateiName = s;
    }
    
    bool CTerminV::terminListeSpeichern(string _dateiName) {
    	ofstream *outputDatei;
    	outputDatei = new ofstream(_dateiName.c_str());
    	if (! outputDatei->is_open()) {
    		cout << "Fehler beim oeffnen der Datei!" << endl;
    		return false;
    	}
    	*outputDatei << CTermin::next_id << "|"
    				 << termine.size() << "|";
    
    	list<CTermin>::iterator it = termine.begin();
    	while (it != termine.end()) {
    		*outputDatei << *it;
    		//zeilenvorschub zur besseren lesbarkeit der datei
    		*outputDatei << '\n';
    		*outputDatei << '|';
    		it++;
    	}
    
    	outputDatei->close();
    	delete outputDatei;
    	return true;
    }
    
    bool CTerminV::terminListeLaden() {
    	ifstream *inputDatei;
    	inputDatei = new ifstream(dateiName.c_str());
    	char c;		
    	unsigned int terminCounter;
    	unsigned int i;
    	CTermin *t;
    
    	if (! inputDatei->is_open()) {
    		cout << "Fehler beim oeffnen der Datei!" << endl;
    		return false;
    	}
    
    	//next_id fülle damit nicht alle termine einfach überschrieben werden
    	*inputDatei >> CTermin::next_id;
    	*inputDatei >> c;
    	*inputDatei >> terminCounter;
    	*inputDatei >> c;
    	for (i = 0; i < terminCounter; i++) {
    		t = new CTermin();
    		*inputDatei >> *t;
    		*inputDatei >> c;
    		while (c != '|') { // '\n' usw. bis einschl. '|' lesen
    			*inputDatei >> c; 
    		}
    		termine.push_back(*t);
    		delete t;
    	}
    	termine.sort();
    	delete inputDatei;
    }
    

    Zum Beispiel in Zeile 67 stürzt er ab, was ich mir absolut nicht erklären kann denn da macht er doch nur nen vergleich.
    Aber jetzt muss ich erstmal pennen, jute nacht!



  • dein beispielfehler zeile 67:

    void CTerminV::getTermine(list<CTermin> &_terminList, CDatumUhrzeit _von, CDatumUhrzeit _bis) {
        _terminList.clear();
        list<CTermin>::iterator it = _terminList.begin();
        while (it != termine.end()) {
    

    schau mal, mit welcher liste du "it" initialisierst, und mit welcher liste du prüfst, ob "it" das Ende der Liste erreicht hat.



  • oO hab mich jetzt mal an die Funktionsrümpfe von dir zum großteil gehalten und es ein wenig angepasst:

    #include "terminv.h"
    #include <sstream>
    
    list<CTermin>::iterator CTerminV::getTerminIterator(unsigned long id) 
    {
    	for (std::list<CTermin>::iterator it = m_termine.begin(); it != m_termine.end(); ++it) 
    		if ((*it).getId() == id) return it;
    
    	return m_termine.end();
    }
    
    CTermin* CTerminV::getTermin(unsigned long id) const /* Da Kopie erstellt wird!*/
    {
    	std::list<CTermin>::iterator it = getTerminIterator(id);
    	return (it != m_termine.end() ? new CTermin(*it) : NULL);
    }
    
    void CTerminV::terminEinfuegen(const CTermin& termin) // hier muss mal zur abwechslung const hin ;)
    {
    	m_termine.push_back(termin);
    	m_termine[m_termine.size() - 1].setNeueId();
    	m_termine.sort();
    }
    
    bool CTerminV::terminLoeschen(unsigned long id) 
    {
        list<CTermin>::iterator it = getTerminIterator(id);
        if (it != termine.end()) 
    	{
            termine.erase(it);
            return true;
        }
    	return false;
    }
    
    bool CTerminV::terminBearbeiten(const CTermin& termin) 
    {
    	if (terminLoeschen(termin.getId()) != true) 
    		return false;
    
    	m_termine.push_back(termin);
    	m_termine.sort();
    
    	return true;
    }
    
    const std::string& CTerminV::terminAnzeigen(unsigned long id) const
    {
    	list<CTermin>::iterator it = getTerminIterator(id);
    
    	if (it != m_termine.end())
    		return (*it).toString();
    
    	std::ostringstream ss("Termin mit der ID: ");
    	ss << id << " nicht gefunden!";
    	return ss.str();
    }
    
    void CTerminV::getTermine(std::list<CTermin>& terminList, CDatumUhrzeit von, CDatumUhrzeit bis) 
    {
    	terminList.clear();
    	for (std::list<CTermin>::iterator it = m_termine.begin(); it != m_termine.end(); ++it)
    		if ((*it).getAnfang() >= von && (*it).getEnde() <= bis)
    			terminList.push_back(*it);
    }
    
    const std::string& CTerminV::getDateiName() const {	return m_dateiName;	}
    void CTerminV::setDateiName(const std::string& name) {	m_dateiName = name;	}
    
    bool CTerminV::terminListeSpeichern(const std::string& dateiName) 
    {
    	std::ofstream ausgabe(dateiName.c_str(), std::ios::out);
    	if (!ausgabe)
    	{
    		std::cout << "FEHLER: Die Datei \"" << dateiName << "\" konnte nicht geoeffnet werden!" << std::endl;
    		return false;
    	}
    
    	ausgabe << CTermin::next_id << "|" << m_termine.size() << "|";
    
    	for (std::list<CTermin>::iterator it = m_termine.begin(); it != m_termine.end(); ++it) 
    		ausgabe << *it << "\n|";
    
        return true;
    }
    
    bool CTerminV::terminListeLaden() 
    {
    	m_termine.clear();
    	std::ifstream einlesen(m_dateiName.c_str(), std::ios::in);
    	if (!einlesen)
    	{
    		std::cout << "FEHLER: Die Datei \"" << m_dateiName << "\" konnte nicht geoffnet werden!" << std::endl;
    		return false;
    	}
    
    	einlesen >> CTermin::next_id;
    	einlesen.seekg(sizeof(char), std::ios::cur);
    	std::size_t anzahlTermine;
    	einlesen >> anzahlTermine;
    	einlesen.seekg(sizeof(char), std::ios::cur);
    	for (std::size_t i = 0; i < anzahlTermine; ++i)
    	{
    		CTermin* tmp = new CTermin;
    		einlesen >> *tmp;
    		m_termine.push_back(*tmp);
    		delete tmp;
    		while (einlesen.get() != '|');
        }
        m_termine.sort();
    }
    

    ... guck dir die Veränderungen mal an ...



  • otze schrieb:

    dein beispielfehler zeile 67:

    void CTerminV::getTermine(list<CTermin> &_terminList, CDatumUhrzeit _von, CDatumUhrzeit _bis) {
        _terminList.clear();
        list<CTermin>::iterator it = _terminList.begin();
        while (it != termine.end()) {
    

    schau mal, mit welcher liste du "it" initialisierst, und mit welcher liste du prüfst, ob "it" das Ende der Liste erreicht hat.

    tja was soll ich dazu noch sagen, das ist ja einfach nur peinlich :D, danke!

    @Evil
    Ich habe ein paar Passagen übernommen, aber an die terminListeLaden und terminListeSpeichern Methoden habe ich mich nicht drangetraut.
    Ich könnte meinem Dozenten ja gar nicht erklären was diese seek methode macht und wieso ich die plötzlich verwende, wo er es uns doch ganz anders beigebracht hat.

    Das mit dem stringstream kann ich noch vertreten, ist ja wie ein stringbuffer in java glaube ich.

    Aber warum hast du die terminEinfuegen Methode geändert ?
    Es war doch vorher viel einfacher zu verstehen was da passiert.
    Wieso soll ich da const einfügen wenn ich doch an dem Objekt was ändere ?



  • Ich habe ein paar Passagen übernommen, aber an die terminListeLaden und terminListeSpeichern Methoden habe ich mich nicht drangetraut.

    Dann schieß los, wo du etwas noch nicht verstanden hast!

    einlesen >> CTermin::next_id;
    einlesen.seekg(sizeof(char), std::ios::cur);
    std::size_t anzahlTermine;
    einlesen >> anzahlTermine;
    einlesen.seekg(sizeof(char), std::ios::cur);
    

    Das ist eigentlich ganz einfach 🙂 zum einen hab ich die Variablen einlesen genannt, weil du auch sonnst rel. viel deutsche Variablennamen am wählen scheinst 😉
    Zu seekg ... seek steht ja für "suchen" und erklärt die Funktion nicht soo toll 😉 Der 1. Parameter heißt halt, um wie viele Byte du "seeken", d.h. dich in der Datei bewegen willst. sizeof(char) d.h., weil du ja sonnst für '|' eine Variable angelegt hattest und da immer reingelesen hattest ... deren Type war char. std::ios::cur gibt nur an von wo aus er sich fortbewegen soll. Wenn du bsw. std::ios::beg angegeben hättest, dann würde er wieder an den Anfang springen und von da aus sizeof(char) Bytes nach vorne gehen. Wenn ein negativer Wert da steht geht es rückwärts ... bei std::ios::beg natürlich nicht sooo sinnig 😉
    Zum nachlesen: http://www.cplusplus.com/reference/iostream/istream/seekg.html

    Aber warum hast du die terminEinfuegen Methode geändert ?
    Es war doch vorher viel einfacher zu verstehen was da passiert.
    Wieso soll ich da const einfügen wenn ich doch an dem Objekt was ändere ?

    Hmm ja ich hab die Funktion etwas im Sinn geändert fällt mir gerade auf. Aber mal zum Erklären:

    void CTerminV::terminEinfuegen(const CTermin& termin)
    {
        m_termine.push_back(termin); // eine KOPIE von termin wird in m_termine abgelegt
        m_termine[m_termine.size() - 1].setNeueId(); // m_termine.size() - 1, da der Index eines Arrays bei 0 und nicht bei 1 anfängt ;) m_termine.size() - 1 ist d.h. das letzte und neu hinzugefügte item ... da es aber eine Kopie des Orginals ist, ist const weg und wir können wieder setNeueId aufrufen!
        m_termine.sort();
    }
    

    ... So ... sinnlich ist die Veränderung, dass nun das Objekt termin nach und vor terminEinfügen die selbe ID von außen hat also

    CTermin termin;
    std::cout << termin.getId() << std::endl;
    verwaltung.terminEinfuegen(termin);
    std::cout << termin.getId() << std::endl;
    

    Wie du siehst ist die ID identisch ... in der Verwaltungsklasse hat dieser Termin jetzt aber eine andere id ...

    Solltest evt. noch nen const_iterator einbauen ... oftmals erstellst du Kopien deiner Objekte und d.h. brauchst nur const-Versionen ... kann der Compiler evt. was optimieren 🙂

    Wenn du noch Fragen hast ... immer her damit 😉



  • Hmm ok das mit dem Array leuchtet mir ein, also die fangen echt bei 0 an ? 😉
    Also ne das mit der terminEinfuegen methode von dir bringt mir nix außer verwirrung meines profs und ich will ihn ja nicht überlasten.
    Denn die Termine werden ja direkt nach dem einfügen sowieso gelöscht, da isses egal ob der eine jetzt ne andere id hat als der in der verwaltung.

    Aber den rest habe ich jetzt verstanden und sobald mein Programm ohne crash läuft, werde ich auch mal deine Lösung von termineLesen und Speichern verwenden.
    Achne eine sache habe ich noch nicht verstanden

    std::ifstream einlesen(m_dateiName.c_str(), std::ios::in);
        if (!einlesen)
    

    wieso öffnest du da den stream nicht mit open so wie in der referenz beschrieben ?

    Uuund das mit dem const_iterator, ehhhm ich bin java programmierer mir ist die performance sch* egal, das ding muss nur laufen 😃

    PS: Ich tue viele deutsche Variablennamen wählen weil unser Dozent uns 50% von dem Code vorgibt 🙂

    So damit du mal den kompletten Umfang des Programms siehst hier das Hauptprogramm (auch main genannt 😉 ) von unserem Dozenten.
    Aja und damit das ganze läuft gib ich dich noch die CDatumuhrzeit und CTermin Klasse dazu, dann siehste mal was man an ner deutschen FH heutzutage so lernen tut.

    MAIN:

    #include "stdafx.h"
    #include <string>
    #include <iostream>
    #include "..\libTerminV\termin.h"
    #include "..\libTerminV\terminv.h"
    
    using namespace std;
    
    int main(int argc, char* argv[])
    {
        char cmd;
        string cmdline;
        string str;
        string dateiName;
        CTerminV tv;    // Terminverwaltung instantiieren
        CTermin *t;
        list<CTermin> terminAnsicht;
        list<CTermin>::const_iterator itl;
        CDatumUhrzeit *von;
        CDatumUhrzeit *bis;
        unsigned long id;
        char c;
    	string DEFAULT_TERMINE_DATEI = "terminListe.txt";
    
        // Terminliste von Platte laden
        cout << "Termine-Datei laden, Dateiname ["
             << DEFAULT_TERMINE_DATEI << "]: ";
        getline(cin, dateiName);
        if (dateiName.length() <= 1) dateiName = DEFAULT_TERMINE_DATEI;
        tv.setDateiName(dateiName);
        tv.terminListeLaden();
    
        // Funktionsschleife mit Menü
        do {
    
           // Menü anzeigen falls Kommandozeile leer
           if (cmdline.length() <= 1) {
              cout << "Terminkalender: Funktionen" << endl;
              cout << "  e : Exit" << endl;
              cout << "  a : Terminliste anzeigen" << endl;
              cout << "  t : Termin anzeigen" << endl;
              cout << "  n : Termin neu anlegen" << endl;
              cout << "  b : Termin bearbeiten" << endl;
              cout << "  l : Termin loeschen" << endl;
              cout << "  s : Terminliste speichern" << endl;
           }
           cout << ">";
    
           // Kommando einlesen
           cin.clear();
           cmd = ' ';
           cmdline = "";
           getline(cin, cmdline);
           cmd = cmdline[0];
    
           // Kommando auswerten
           switch (cmd) {
              case 'e':
                 break;
              case 'a':
                 // Terminliste anzeigen
                 von = new CDatumUhrzeit();
                 *von -= WEEK;
                 cout << "Termine anzeigen, bitte Zeitraum eingeben!"
                      << endl;
                 cout << "Termine von [" << von->toString() << "]: ";
                 cin >> *von;
                 bis = new CDatumUhrzeit(*von + 31*DAY);
                 cout << "Termine bis [" << bis->toString() << "]: ";
                 cin >> *bis;
                 tv.getTermine(terminAnsicht, *von, *bis);
                 cout << "Termine von " << von->toString()
                      << " bis " << bis->toString() << ":" << endl;
                 if (terminAnsicht.empty()) {
                      cout << "Terminliste ist leer." << endl;
                 }
                 else {
                      cout << (unsigned long) terminAnsicht.size() 
                           << " Eintraege:" << endl;
                      for (itl = terminAnsicht.begin();
                           itl != terminAnsicht.end(); itl++) {
                         cout << "  " << itl->toString() << endl;
                      }
                 }
                 delete von;
                 delete bis;
                 break;
              case 't':
                 // Termin anzeigen
                 cout << "Bitte Termin Id eingeben: ";
                 cin >> id;
                 getline(cin, str);
                 str = tv.terminAnzeigen(id);
                 cout << str;
                 break;
              case 'n':
                 // Termin neu anlegen
                 t = new CTermin();
                 cin >> *t;
                 tv.terminEinfuegen(*t);
                 cout << "Neuer Termin: " << t->toStringAll() << endl;
                 delete t;
                 break;
              case 'b':
                 // Termin bearbeiten
                 cout << "Bitte Termin Id eingeben: ";
                 cin >> id;
                 getline(cin, str);
                 t = tv.getTermin(id);
                 if (t == 0) {
                     cout << "Termin mit id '" << int2string(id, "%i")
                          << "' nicht gefunden!" << endl;
                     break;
                 }
                 cin >> *t;
                 if ( ! tv.terminBearbeiten(*t)) {
                     cout << "Termin mit id '" << int2string(id, "%i")
                     << "' wurde inzwischen geloescht! Neu anlegen? [J/N]:";
                     getline(cin, str);
                     c = toupper(str.c_str()[0]);
                     if (c == 'J' || c == 'Y') {
                        tv.terminEinfuegen(*t);
                     }
                     else break;
                 };
                 cout << "Geaenderter Termin: " << t->toStringAll() << endl;
                 delete t;
                 break;
              case 'l':
                 // Termin löschen
                 cout << "Bitte Termin Id eingeben: ";
                 cin >> id;
                 getline(cin, str);
                 t = tv.getTermin(id);
                 if ( t == 0) {
                     cout << "Termin mit id '" << int2string(id, "%i")
                          << "' nicht gefunden!" << endl;
                     break;
                 }
                 cout << t->toStringAll() << endl;
                 cout << "Termin wirklich loeschen? [J/N]:";
                 getline(cin, str);
                 c = toupper(str.c_str()[0]);
                 if (c == 'J' || c == 'Y') {
                    if (tv.terminLoeschen(id)) {
                        cout << "Termin geloescht!" << endl;
                    }
                    else {
                        cout << "Fehler: Termin nicht geloescht!" << endl;
                    };
                 }
                 delete t;
                 break;
              case 's':
                 // Terminliste speichern
                 cout << "Bitte Dateinamen angeben ["
                      << tv.getDateiName() << "]: ";
                 getline(cin, dateiName);
                 if (dateiName.length() <= 1) dateiName = tv.getDateiName();
                 if (tv.terminListeSpeichern(dateiName)) {
                    cout << "Terminliste gespeichert unter: "
                         << dateiName << endl;
                    cout << "Gespeicherte Datei als Arbeitsdatei nehmen? [J/N]:";
                    getline(cin, str);
                    c = toupper(str.c_str()[0]);
                    if (c == 'J' || c == 'Y') {
                       tv.setDateiName(dateiName);
                    }
                 }             
                 break;
              default:
                 cout << "falsches Kommando (" << cmd << ")" <<endl;
                 cmdline = "";
                 break;
           }
        } while (cmd != 'e');
    
        // Terminliste auf Platte speichern
        tv.terminListeSpeichern(tv.getDateiName());
    
        return 0;
    }
    

    CTERMIN:

    #include "termin.h";
    
    unsigned long CTermin::next_id = 1;
    
    //*******************************************
    // Konstruktoren
    //*******************************************
    
    CTermin::CTermin() {
    	CDatumUhrzeit du;
    	setBeginn(du);
    	setEnde(du+=MINUTE*30);
    	setOrt("zuhuss");
    	setTitel("zuhuss");
    	setText("zuhuss");
    	this->id = 0;
    };
    
    //*******************************************
    // Setter
    //*******************************************
    void CTermin::setOrt(string _ort) {
    	this->Ort = _ort;
    };
    
    void CTermin::setTitel(string _titel) {
    	this->Titel = _titel;
    };
    
    void CTermin::setText(string _text) {
    	this->Text = _text;
    };
    
    void CTermin::setBeginn(CDatumUhrzeit _beginn) {
    	Zeitspanne alte_spanne = this->Ende - this->Beginn;
    	CDatumUhrzeit neues_ende = _beginn + alte_spanne;
    	this->Beginn = _beginn;
    	this->setEnde(neues_ende);
    };
    
    void CTermin::setEnde(CDatumUhrzeit ende) {
    	this->Ende = ende;
    };
    
    void CTermin::setNeueId() {
    	this->id = ++this->next_id;
    }
    //*******************************************
    // Getter
    //*******************************************
    string CTermin::getOrt() const {
    	return this->Ort;
    };
    
    string CTermin::getTitel() const {
    	return this->Titel;
    };
    
    string CTermin::getText() const {
    	return this->Text;
    };
    
    CDatumUhrzeit CTermin::getBeginn() const {
    	return this->Beginn;
    };
    
    CDatumUhrzeit CTermin::getEnde() const {
    	return this->Ende;
    };
    
    long CTermin::getId() const {
    	return this->id ;
    }
    //*******************************************
    // tostrings
    //*******************************************
    
    string CTermin::toString() const {
    	string str;
    	str = "\nTitel: " + this->getTitel() + "\n";
    	str += "Ort: " + this->getOrt() + "\n";
    	str += "Text: " + this->getText() + "\n";
    	str += "Beginn: " + this->getBeginn().toString() + "\n";
    	str += "Ende: " + this->getEnde().toString() + "\n";
        return str;
    };
    
    string CTermin::toStringAll() const {
    	string str;
    	str = toString();
    	str += "Id: " + this->getId();
        return str;
    };
    
    //*******************************************
    // Operatoren
    //*******************************************
    
    bool CTermin::operator==(const unsigned long _id) const
    {
    	return this->getId() == _id;
    };
    
    bool CTermin::operator<(const CTermin &_termin) const
    {
    	bool isLessThan = false;
    	if (this->getBeginn() < _termin.getBeginn()) {
    		isLessThan = true;
    	} else if (this->getEnde() < _termin.getEnde()) {
    		isLessThan = true;
    	} else if (this->getTitel() < _termin.getTitel()) {
    		isLessThan = true;
    	} else if (this->getId() < _termin.getId()) {
    		isLessThan = true;
    	}
        return isLessThan;
    };
    
    //*******************************************
    // friend Operatoren
    //*******************************************
    
    ostream& operator<<(ostream &_out, const CTermin &_termin)
    {
        _out << _termin.toString().c_str();
        return _out;
    };
    
    istream& operator>>(istream &_in, CTermin &_termin)
    {
    	string inputString;
    	CDatumUhrzeit inputDatumUhrzeit;
    
    	//Titel setzen
    	cout << "Bitte geben sie den Titel des Termins ein:" << endl;
    	_in >> inputString;
    	_termin.setTitel(inputString);
    
    	//Ort setzen
    	cout << "Bitte geben sie den Ort des Termins ein:" << endl;
    	_in >> inputString;
    	_termin.setOrt(inputString);
    
    	//Text setzen
    	cout << "Bitte geben sie den Text des Termins ein:" << endl;
    	_in >> inputString;
    	_termin.setText(inputString);
    
    	//Beginn setzen
    	cout << "Bitte geben sie den Beginn des Termins ein:" << endl;
    	_in >> inputDatumUhrzeit;
    	_termin.setBeginn(inputDatumUhrzeit);
    
    	//Ende setzen
    	cout << "Bitte geben sie das Ende des Termins ein:" << endl;
    	_in >> inputDatumUhrzeit;
    	_termin.setEnde(inputDatumUhrzeit);
    
    	_termin.setNeueId();
    	return _in;
    }
    
    //1|1181975400|1181986800|8|Raum D1015|Vorlesung PSE 136|Terminkalender fertig implementieren
    
    ofstream& operator<<(ofstream &fout, const CTermin &t) {
    	fout << t.id << "|"
    		<< t.Beginn << "|"
    		<< t.Ende << "|"
    		<< t.Ort.length() << "|" << t.Ort
    		<< t.Titel.length() << "|" << t.Titel
    		<< t.Text.length() << "|" << t.Text;
    	return fout;
    }
    
    ifstream& operator>>(ifstream &fin, CTermin &t) {
    	char c;
    	int len;
    	char ortBuf[1024];
    	char titelBuf[1024];
    	char textBuf[1024];
    
    	fin >> t.id >> c;
    	fin >> t.Beginn >> c;
    	fin >> t.Ende >> c;
    	//Ort
    	fin >> len >> c;
    	if (len != 0) {
    	    fin.get(ortBuf, len + 1);
    		t.Ort = ortBuf;
    	}
    	//Titel
    	fin >> len >> c;
    	if (len != 0) {
    	    fin.get(titelBuf, len + 1);
    		t.Titel = titelBuf;
    	}
    	//Text
    	fin >> len >> c;
    	if (len != 0) {
    	    fin.get(textBuf, len + 1);
    		t.Text = textBuf;
    	}
    	return fin;
    }
    

    CDatumUhrzeit:

    #include "datumuhrzeit.h"
    
    //*******************************************
    // Konstuktoren
    //*******************************************
    
    CDatumUhrzeit::CDatumUhrzeit() {
        this->Zeit = CDatumUhrzeit::now();
    };
    
    CDatumUhrzeit::CDatumUhrzeit(const CDatumUhrzeit &du) {
        this->Zeit = du.Zeit;
    };
    
    CDatumUhrzeit::CDatumUhrzeit(struct tm zeit) {
        this->Zeit = zeit;
    };
    
    //*******************************************
    // statische Element-Funktionen
    //*******************************************
    
    void CDatumUhrzeit::convertZeit2Tm(long jahr, int monat, int tag,
                               int std, int minute, int sec, struct tm& zeit)
    {
        zeit.tm_year = jahr - 1900;
        zeit.tm_mon = monat - 1;
        zeit.tm_mday = tag;
        zeit.tm_hour = std;
        zeit.tm_min = minute;
        zeit.tm_sec = sec;
    };
    
    void CDatumUhrzeit::convertTm2Zeit(struct tm zeit, long& jahr, int& monat, int& tag,
                                               int& std, int& minute, int& sec)
    {
        jahr = zeit.tm_year + 1900;
        monat = zeit.tm_mon + 1;
        tag = zeit.tm_mday;
        std = zeit.tm_hour;
        minute = zeit.tm_min;
        sec = zeit.tm_sec;
    };
    
    struct tm CDatumUhrzeit::now(){
        errno_t errnum;
        struct tm tm_time;
        time_t t = time(NULL);			// aktuelle Zeit in Sekunden seit 1970
        errnum = localtime_s(&tm_time, &t);	// time_t nach struct tm konvertieren
        return tm_time;				// Inhalt der Struktur zurückgeben
    };
    
    //*******************************************
    // Element-Funktionen
    //*******************************************
    
    void CDatumUhrzeit::setZeitpunkt(struct tm zeit) {
        this->Zeit = zeit;
    };
    
    struct tm CDatumUhrzeit::getZeitpunkt() const {
        return(this->Zeit);
    };
    
    void CDatumUhrzeit::getZeitpunkt(long& jahr, int& monat, int& tag,
                                    int& std, int& minute, int& sec) const
    {
        CDatumUhrzeit::convertTm2Zeit(this->Zeit, jahr, monat, tag, std, minute, sec);
    };
    
    string CDatumUhrzeit::toString() const {
        string str;
        long jahr;
        int monat, tag;
        int std, minute, sec;
        CDatumUhrzeit::convertTm2Zeit(this->Zeit, jahr, monat, tag, std, minute, sec);
        str = int2string(tag, "%02d");
        str += ".";
        str += int2string(monat, "%02d");;
        str += ".";
        str += int2string(jahr, "%04d");;
        str += " ";
        str += int2string(std, "%02d");;
        str += ":";
        str += int2string(minute, "%02d");;
        str += ":";
        str += int2string(sec, "%02d");;
        return str;
    };
    
    //*******************************************
    // Operatoren
    //*******************************************
    
    CDatumUhrzeit& CDatumUhrzeit::operator=(const CDatumUhrzeit &du)
    {
        this->Zeit = du.Zeit;
        return *this;
    };
    
    bool CDatumUhrzeit::operator<(const CDatumUhrzeit &du) const
    {
        time_t t1, t2;
        struct tm tmp_zeit, tmp_zeit_intern;
    	tmp_zeit_intern = this->Zeit;
        t1 = mktime(&tmp_zeit_intern);
        tmp_zeit = du.Zeit;
        t2 = mktime(&tmp_zeit);
        return t1 < t2;
    };
    
    bool CDatumUhrzeit::operator==(const CDatumUhrzeit &du) const
    {
        time_t t1, t2;
        struct tm tmp_zeit, tmp_zeit_intern;
    	tmp_zeit_intern = this->Zeit;
        t1 = mktime(&tmp_zeit_intern);
        tmp_zeit = du.Zeit;
        t2 = mktime(&tmp_zeit);
        return t1 == t2;
    };
    
    bool CDatumUhrzeit::operator!=(const CDatumUhrzeit &du) const
    {
        return (! (*this == du));
    };
    
    CDatumUhrzeit& CDatumUhrzeit::operator+=(Zeitspanne zsp)
    {
    	errno_t errnum;
        time_t t;
        t = mktime(&this->Zeit);
        time_t new_t;
        Zeitspanne zsp1;
        if (zsp < 0) zsp1 = -zsp; else zsp1 = zsp;
        new_t = t + (time_t) zsp1;
        errnum = localtime_s(&(this->Zeit), &new_t);
        return *this;
    };
    
    CDatumUhrzeit& CDatumUhrzeit::operator-=(Zeitspanne zsp)
    {
    	errno_t errnum;
        time_t t;
        t = mktime(&this->Zeit);
        time_t new_t;
        Zeitspanne zsp1;
        if (zsp < 0) zsp1 = -zsp; else zsp1 = zsp;
        new_t = t - (time_t) zsp1;
        errnum = localtime_s(&(this->Zeit), &new_t);
        return *this;
    };
    
    Zeitspanne CDatumUhrzeit::operator-(const CDatumUhrzeit& du)
    {
        Zeitspanne zsp;
        struct tm tmp_zeit;
        time_t t1;
        time_t t2;
        t1 = mktime(&this->Zeit);
        tmp_zeit = du.Zeit;
        t2 = mktime(&tmp_zeit);
        zsp = difftime (t1, t2);
        if (zsp < 0) zsp = -zsp;
        return zsp;
    
    };
    
    CDatumUhrzeit CDatumUhrzeit::operator-(Zeitspanne zsp)
    {
        CDatumUhrzeit du = *this;
        du -= zsp;
        return du;
    };
    
    CDatumUhrzeit CDatumUhrzeit::operator+(Zeitspanne zsp)
    {
        CDatumUhrzeit du = *this;
        du += zsp;
        return du;
    };
    
    //*******************************************
    // Friend-Operatoren
    //*******************************************
    
    ostream& operator<<(ostream& out, const CDatumUhrzeit& du)
    {
        out << du.toString().c_str();
        return out;
    };
    
    istream& operator>>(istream& in, CDatumUhrzeit& du)
    {
        string str;
        string tmp;
        long n;
        size_t i;
        struct tm zeit;
    
        zeit = du.Zeit;
        getline(in, str);
    
        // Tag
        n = atoi(str.c_str());
        if (n == 0) {
            du.Zeit = zeit;   // aktueller Zeitpunkt
            return in;
        }
        // init Uhrzeit
        zeit.tm_hour = 0;
        zeit.tm_min = 0;
        zeit.tm_sec = 0;
        if (n < 1 || n > 31) {
           du.Zeit = zeit;
           return in;
        }
        zeit.tm_mday = n;
    
        // Monat
        i = str.find_first_of(".");
        if (i == (size_t)-1 ) {
           du.Zeit = zeit;
           return in;
        }
        n = atoi(&str.c_str()[i+1]);
        if (n < 1 || n > 12) {
           du.Zeit = zeit;
           return in;
        }
        zeit.tm_mon = n - 1;
    
        // Jahr
        tmp = &str.c_str()[i+1];
        i = tmp.find_first_of(".");
        if (i == (size_t)-1 ) {
           du.Zeit = zeit;
           return in;
        }
        n = atoi(&tmp.c_str()[i+1]);
        if (n < 0 || n > 2038) {
            du.Zeit = zeit;
            return in;
        }
        if (n >= 50 && n < 100) {
            n += 1900;
        }
        if (n < 50) {
            n += 2000;
        }
        zeit.tm_year = n - 1900;
    
        // Stunde
        i = str.find_first_of(" ");
        if (i == (size_t)-1 ) {
           du.Zeit = zeit;
           return in;
        }
        n = atoi(&str.c_str()[i+1]);
        if (n < 0 || n > 23) {
           du.Zeit = zeit;
           return in;
        }
        zeit.tm_hour = n;
    
        // Minute
        i = str.find_first_of(":");
        if (i == (size_t)-1 ) {
           du.Zeit = zeit;
           return in;
        }
        n = atoi(&str.c_str()[i+1]);
        if (n < 0 || n > 59) {
           du.Zeit = zeit;
           return in;
        }
        zeit.tm_min = n;
    
        // Sekunde
        tmp = &str.c_str()[i+1];
        i = tmp.find_first_of(":");
        if (i == (size_t)-1 ) {
           du.Zeit = zeit;
           return in;
        }
        n = atoi(&tmp.c_str()[i+1]);
        if (n < 0 || n > 59) {
           du.Zeit = zeit;
           return in;
        }
        zeit.tm_sec = n;
    
        du.Zeit = zeit;
        return in;
    };
    
    ofstream& operator<<(ofstream& fout, const CDatumUhrzeit& du)
    {
        time_t t1;
        struct tm zeit = du.Zeit;
        t1 = mktime(&zeit);
        fout << (long) t1 << '|';
        return fout;
    };
    
    ifstream& operator>>(ifstream& fin, CDatumUhrzeit& du)
    {
    	errno_t errnum;
        char c;
        struct tm tm_time;
        time_t t;
        fin >> t >> c;
        errnum = localtime_s(&tm_time, &t);
        du.Zeit = tm_time;
        return fin;
    };
    
    //*******************************************
    // Funktionen außerhalb der Klasse
    //*******************************************
    
    string int2string(int i, char *format) {
        char temp[128];
        string str;
        sprintf_s(temp, format, i);
        str = temp;
        return str;
    };
    

    Ach und falls du das ding auch ans laufen bringen willst hier die header:

    #ifndef _TERMIN_H
    #define _TERMIN_H
    #include "../../datumuhrzeit.h"
    #include <string>
    #include <iostream>, <fstream>
    
    using namespace std;
    
    #define DEFAULT_DAUER (MINUTE*30)
    
    class CTermin {
    	protected:
    		unsigned long id;
    		CDatumUhrzeit Beginn;
    		CDatumUhrzeit Ende;
    		string Ort;
    		string Titel;
    		string Text;
    
    	public:
    		static unsigned long next_id;
    		//Konstruktoren
    		CTermin();
    
    		//setter
    		void setOrt (string _ort);
    		void setTitel (string _titel);
    		void setText (string _text);
    		void setBeginn(CDatumUhrzeit _beginn);
    		void setEnde(CDatumUhrzeit _ende);
    		void setNeueId();
    
    		//getter	
    		string getOrt() const;
    		string getTitel() const;
    		string getText() const;
    		CDatumUhrzeit getBeginn() const;
    		CDatumUhrzeit getEnde() const;
    		long getId() const;
    
    		//tostrings
    		string toString() const;
    		string toStringAll() const;
    
    		//operatoren
    		bool operator<(const CTermin &_termin) const;
    		bool operator==(const unsigned long _id) const;
    
    		//friend operatoren
    		friend ostream& operator<<(ostream&, const CTermin&);
    		friend istream& operator>>(istream&, CTermin&);
    		//friend ofstream& operator<<(ofstream&, const CTermin&);
    		//friend ifstream& operator>>(ifstream&, CTermin&);
    		friend ofstream& operator<<(ofstream &fout, const CTermin &t);
    		friend ifstream& operator>>(ifstream &fin, CTermin &t);
    
    };
    #endif // _TERMIN_H
    
    #ifndef _DATUMUHRZEIT_H
    #define _DATUMUHRZEIT_H
    #include <string>
    #include <iostream>
    #include <fstream>
    #include <time.h>
    #include <stdio.h>
    
    using namespace std;
    
    #define MINUTE 60
    #define HOUR (MINUTE*60)
    #define DAY (HOUR*24)
    #define WEEK (DAY*7)
    
    typedef long double Zeitspanne;  // Zeitspanne in Sekunden,
    
    // Hilfsfunktion, um Integer nach string zu verwandeln
    string int2string(int i, char *format = "%i");
    
    // ---------------------------------------------------
    // Diese Klasse speichert einen Zeitpunkt und 
    // bietet verschiedene Verarbeitungsmöglichkeiten.
    // ---------------------------------------------------
    // Datum und Uhrzeit mit Auflösung auf Sekundenebene,
    // die Klasse wird realisiert über die Struktur tm aus time.h
    
    class CDatumUhrzeit {
    
      protected:
        struct tm Zeit;
    
      public:
        //******** Konstruktoren ***************
        // erzeugt DatumUhrzeit mit aktuellem Zeitpunkt
        CDatumUhrzeit();
    
        // Kopierkonstruktor
        CDatumUhrzeit(const CDatumUhrzeit &du);
    
        // erzeugt DatumUhrzeit mit Zeitpunkt in struct tm
        CDatumUhrzeit(struct tm zeit);
    
        //******** statische Methoden ***************
        // Verwandle Zeit in struct tm nach
        // Jahr/Monat/Tag Stunde/Minute/Sekunde
        static void convertTm2Zeit(struct tm, long& jahr, int& monat,
                           int& tag, int& std, int& minute, int& sec);
    
        // Verwandle Zeit von Jahr/Monat/Tag Stunde/Minute/Sekunde
        // in struct tm
        static void convertZeit2Tm(long jahr, int monat, int tag,
                            int std, int minute, int sec, struct tm&);
        // Lade die aktuelle Zeit nach struct tm
        static struct tm now();
    
        //******** Set und Get Methoden ***************
        void setZeitpunkt(struct tm zeit);
        struct tm getZeitpunkt() const;
        void getZeitpunkt(long& jahr, int& monat, int& tag, int& std,
                                    int& minute, int& sec) const;
    
        //******** andere Methoden ***************
        // Zeitpunkt als string in der Form "01.01.2005 10:10:10"
        // zurückgeben
        string toString() const;
    
        //******** Operatoren ***************
        CDatumUhrzeit &operator=(const CDatumUhrzeit&);
        bool operator<(const CDatumUhrzeit&) const;
        bool operator==(const CDatumUhrzeit&) const;
        bool operator!=(const CDatumUhrzeit&) const;
    
        CDatumUhrzeit &operator+=(Zeitspanne);
        CDatumUhrzeit &operator-=(Zeitspanne);
        Zeitspanne operator-(const CDatumUhrzeit&);
        CDatumUhrzeit operator-(Zeitspanne);
        CDatumUhrzeit operator+(Zeitspanne);
    
        //******** Friend Operatoren ***************
        // Datum und Uhrzeit ausgeben in der Form "01.01.2005 10:10:10"
        friend ostream& operator<<(ostream&, const CDatumUhrzeit&);
    
        // Datum und Uhrzeit einlesen in der Form "01.01.2005 10:10:10"
        // Bei Eingabe von Return wird der Zeitpunkt in 'du' übernommen.
        // Fehlende oder fehlerhafte Zahlen setzen Datumszahlen auf
        // vorhandene Zahlen in 'du', Uhrzeitzahlen auf 0.
        // Die (alte) Zeit in 'du' ist der Default.
        friend istream& operator>>(istream&, CDatumUhrzeit& du);
    
        // Datum und Uhrzeit in eine Datei speichern
        // wird vorher in time_t verwandelt und mit '|' abgeschlossen
        friend ofstream& operator<<(ofstream&, const CDatumUhrzeit&);
    
        // Datum und Uhrzeit aus einer Datei lesen
        // Wert wird in time_t gelesen und nach struct tm verwandelt,
        // '|' wird gelesen und verworfen
        friend ifstream& operator>>(ifstream&, CDatumUhrzeit&);
    
    };
    
    #endif // _DATUMUHRZEIT_H
    
    #ifndef _TERMINV_H
    #define _TERMINV_H
    #include <list>
    #include "termin.h"
    
    class CTerminV {
    
    protected:
    	list<CTermin> termine;
    	string dateiName;
    
    public:
    	list<CTermin>::iterator getTerminIterator(const unsigned long _id);
    	CTermin *getTermin(const unsigned long _id);
    	void terminEinfuegen(CTermin &t);
    	bool terminLoeschen(const unsigned long _id);
    	bool terminBearbeiten(CTermin &t);
    	std::string terminAnzeigen(const unsigned long _id);
    	void getTermine(list<CTermin> &_terminList, CDatumUhrzeit _von, CDatumUhrzeit _bis);
    	std::string getDateiName();
    	void setDateiName(std::string _s);
    	bool terminListeSpeichern(std::string _dateiName);
    	bool terminListeLaden();
    };
    
    #endif // _TERMINV_H
    

    CDatumUhrzeit wurde uns komplett vom Dozenten vorgegeben wir mussten nur CTermin und CTerminV schreiben.

    Soo jetzt pennen und morgen kümmer ich mich darum das das ding ohne crash läuft.
    Ich glaube es liegt nur noch daran, dass die ifstream operatoren von CTermin nicht richtig implementiert sind, denn er speichert die Terminedatums nicht als Timestamp sondern als lesbares Datum.

    Du bist echt ne jute hilfe, ich muss aufpassen das ich nicht noch spaß an c++ bekomme, davor habe ich mich immer gefürchtet 😉



  • std::ifstream einlesen(m_dateiName.c_str(), std::ios::in);
    if (!einlesen)

    ... erstmal dazu:
    Warum noch eine extra Funktion aufrufen, wenn der Konstruktor das schon alles für dich regeln kann? Und if (!einlesen) solltest du auch if (einlese.is_open() == false) vorziehen. Der operator ! ist dafür extra da;) http://www.cplusplus.com/reference/iostream/ios/operatornot.html ...

    So werd die Klasse jetzt stückchenweise ausbessern und dir dann posten...



  • Hmm ... da mischt aber einer C und C++ ... ganz übel ... werd es mal korrigieren ...



  • So ... ist nicht getestet ...

    Termin.h

    #if !defined TERMIN_H__INCLUDED
    #define TERMIN_H__INCLUDED
    
    #if (_MSC_VER >= 1300)
    #pragma once
    #endif // (_MSC_VER >= 1300)
    
    class Termin
    {
    public:
    	Termin() :	m_Begin(), m_Ende(m_Begin + 60 * 30), 
    				m_Ort("Unbekannt"), m_Name("Unbekannt"), m_ID(0)
    	{}
    
    	operator std::string() const	{	return str(); }
    	bool operator==(std::size_t id) const { return m_ID == id; }
    	bool operator<(const Termin& obj) const { return (m_Anfang() < obj.get_anfang() || m_Ende < obj.get_ende() || m_Name < obj.get_name() || m_ID < obj.get_id());
    
    	friend std::ofstream& operator<<(std::ofstream&, const Termin&);
    	friend std::ifstream& operator>>(std::ifstream&, Termin&);
    	friend std::istream& operator>>(std::istream& stream, Termin&);
    
    public:
    	std::string const &	get_ort() const { return m_Ort;		}
    	std::string const & get_name() const { return m_Name;	}
    	std::string const & get_beschreibung() const { return m_Beschreibung;	}
    	DatumUhrzeit const & get_anfang() const { return m_Anfang; }
    	DatumUhrzeit const & get_ende() const { return m_Ende; }
    	std::size_t get_id() const { return m_ID; }
    
    public:
    	void set_ort(const std::string& ort)					{ m_Ort = ort;	}
    	void set_name(const std::string& name)					{ m_Name = name; }
    	void set_beschreibung(const std::string& beschreibung)	{ m_Beschreibung = beschreibung;	}
    	void set_anfang(const DatumUhrzeit& anfang)				{ DatumUhrzeit::zeitspanne tmp = m_ende - m_anfang; m_Anfang = anfang;	m_Ende = anfang + tmp; }
    	void set_ende(const DatumUhrzeit& ende)					{ m_Ende = ende;	}
    	void set_id()											{ m_ID = NEXT_ID; ++NEXT_ID;	}
    
    public:
    	std::string		data() const { std::ostringstream ss; ss << "ID: " << m_ID << "\n" << *this; return ss.str(); }
    	std::string		str() const 
    	{ 
    		std::ostringstream ss; 
    		ss	<< "Name: " << m_Name << "\nOrt: " << m_Ort << "\nBeschreibung: " << m_Beschreibung 
    			<< "\nVon " << m_Begin << " bis " << m_Ende;
    		return ss.str();
    	}
    
    public:
    	static std::size_t	NEXT_ID;
    
    private:
    	std::string		m_Ort;
    	std::string		m_Name;
    	std::string		m_Beschreibung;
    	DatumUhrzeit	m_Anfang;
    	DatumUhrzeit	m_Ende;
    	std::size_t		m_ID;
    };
    
    #endif // TERMIN_H__INCLUDED
    

    Termin.cpp

    std::size_t Termin::NEXT_ID = 1;
    
    istream& operator>>(std::istream& stream, Termin& termin)
    {
    	std::cout	<< ".Neuer Termin\n"
    				<< "-Name: " << std::flush;
    	std::string tmp;
    	std::getline(stream, tmp);
    	termin.set_name(tmp);
    
    	std::cout	<< "-Ort: " << std::flush;
    	std::getline(stream, tmp);
    	termin.set_ort(tmp);
    
      	std::cout	<< "-Beschreibung: " << std::flush;
    	std::getline(stream, tmp);
    	termin.set_beschreibung(tmp);
    
    	std::cout	<< "-Anfang: " << std::flush;
    	DatumUhrzeit tmpDatumUhrzeit;
    	stream >> tmpDatumUhrzeit;
    	termin.set_anfang(tmpDatumUhrzeit);
    
    	std::cout	<< "-Dauer: " << std::flush;
    	DatumUhrzeit::zeitspanne tmpZeitspanne;
    	while (!(stream >> tmpZeitspanne)) { stream.clear(); stream.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); }
    	termin.set_ende(tmpDatumUhrzeit + tmpZeitspanne);
    	termin.set_id();
    
        return stream;
    }
    
    std::ofstream& operator<<(std::ofstream& stream, const Termin& termin) 
    {
        stream	<< termin.get_id() << "|" << termin.get_anfang() << "|" << termin.get_ende() << "|"
    			<< termin.get_ort().length() + 1 << "|" << termin.get_ort() << termin.get_name().length() + 1 << "|" << termin.get_name()
    			<< termin.get_beschreibung().length() + 1 << "|" << termin.get_beschreibung();
        return stream;
    }
    
    std::ifstream& operator>>(std::ifstream& stream, Termin& termin) 
    {
    	stream >> termin.m_ID;
    	stream.seekg(sizeof(char), std::ios::cur);
    	stream >> termin.m_Anfang;
    	stream.seekg(sizeof(char), std::ios::cur);
    	stream >> termin.m_Ende;
    
    	/* Ort einlese */
    	std::size_t length = 0;
    	stream >> length;
    	stream.seekg(sizeof(char), std::ios::cur);
    	char* tmp = new char[length];
    	stream.get(tmp, length);
    	termin.m_Ort = tmp;
    	delete [] tmp;
    
    	stream >> length;
    	stream.seekg(sizeof(char), std::ios::cur);
    	tmp = new char[length];
    	stream.get(tmp, length);
    	termin.m_Name = tmp;
    	delete [] tmp;
    
        stream >> length;
    	stream.seekg(sizeof(char), std::ios::cur);
    	tmp = new char[length];
    	stream.get(tmp, length);
    	termin.m_Beschreibung = tmp;
    	delete [] tmp;
    
        return stream;
    }
    

    ...

    gleich kommt der Rest 😉


Anmelden zum Antworten