Konstruktor mit Überprüfung
-
In wiefern inkonsestent? Die Funktion sollte laufen, habe die mal getestet.
-
Zeile 15 und 17 machen keinen Sinn irgendwie.
-
cooky451 schrieb:
Zeile 15 und 17 machen keinen Sinn irgendwie.
Inwiefern?
Edit: Ich würde die Reihenfolge umkehren, aber sonst...?(beziehe mich jetzt nur auf 15 u. 17)
-
Caligulaminus schrieb:
~Edit: Ich würde die Reihenfolge umkehren, aber sonst...? (beziehe mich jetzt nur auf 15 u. 17)~
Und ohne Umkehrung der Reihenfolge ist das ok? Insbesondere bei
Tyle schrieb:
Das Datum wird angelegt, obwohl es nicht angelegt werden dürfte.
Datum:Datum d3(29,2,2007);Wo habe ich den Fehler gemacht?
?
Bist du dir überhaupt sicher, dass eine Umkehrung der Reihenfolge ausreicht?
-
Wenn du die Reihenfolge umkehren würdest dann würde die Ausnahme das Jahre/400 nicht Anwendung finden.
Daher muss doch erst die Ausnahme abgefragt werden.
Alle durch 4 teilbaren Jahreszahlen sind Schaltjahre, aber nicht die durch 100 teilbaren, es sei denn sie sind sogar duch 400 teilbar.
Hier das Testprogramm:
#include <string> #include <iostream> using namespace std; bool checkdate(int m, int d, int y); int main(int argc, char* argv[]) { cout << checkdate( 1, 1, 2005) << endl; // 1=true cout << checkdate( 0, 1, 2005) << endl; // 0=false cout << checkdate(13, 1, 2005) << endl; // 0 cout << checkdate( 2,29, 1992) << endl; // 1 cout << checkdate( 2,29, 1996) << endl; // 1 cout << checkdate( 2,29, 2000) << endl; // 1 cout << checkdate( 2,29, 2001) << endl; // 0 cout << checkdate( 2,29, 2002) << endl; // 0 cout << checkdate( 2,29, 2003) << endl; // 0 cout << checkdate( 2,29, 2004) << endl; // 1 cout << checkdate( 2,29, 2100) << endl; // 0 cout << checkdate( 2,29, 2200) << endl; // 0 cout << checkdate( 2,29, 2300) << endl; // 0 cout << checkdate( 2,29, 2400) << endl; // 1 cout << checkdate( 2,29, 2500) << endl; // 0 system("pause"); return 0; } bool checkdate(int m, int d, int y) { //gregorian dates started in 1582 if (! (1582<= y ) )//comment these 2 lines out if it bothers you return false; if (! (1<= m && m<=12) ) return false; if (! (1<= d && d<=31) ) return false; if ( (d==31) && (m==2 || m==4 || m==6 || m==9 || m==11) ) return false; if ( (d==30) && (m==2) ) return false; if ( (m==2) && (d==29) && (y%4!=0) ) return false; if ( (m==2) && (d==29) && (y%400==0) ) return true; if ( (m==2) && (d==29) && (y%100==0) ) return false; if ( (m==2) && (d==29) && (y%4==0) ) return true; return true; }
-
@SeppJ:
Ich bezog mich auf cookies Aussage:cooky451 schrieb:
Zeile 15 und 17 machen keinen Sinn irgendwie.
Nicht auf die Korrektheit der Funktion insgesamt.
Abgesehen davon habe ich bis jetzt noch keinen echten Fehler gefunden.
(29,2,2007)wird bei mir jedenfalls zurückgewiesen.
-
@Tyle:
Hast recht.
-
Evt. ist etwas anderes im Programm falsch?
Ich verwende ne Methode in der Klasse um die Ausgabe für die Monate in Strings zu konvertieren:
//Zahlen in Monatsdaten konvertieren string Datum::getMonatString() const { switch (monat_) { case 1: return "Januar"; case 2: return "Februar"; case 3: return "Maerz"; case 4: return "April"; case 5: return "Mai"; case 6: return "Juni"; case 7: return "Juli"; case 8: return "August"; case 9: return "September"; case 10: return "Oktober"; case 11: return "November"; case 12: return "Dezember"; default: return "Undefined"; } }Sollte eigentlich nicht das Problem sein, da auch der normale getMonat nicht zurückgewiesen wird.
-
Wenn deine check-Funktion funktioniert und trotzdem (29,2,2007) [jetzt wohl (2,29,2007), da Du die Reihenfolge der Argumente im zweiten Beispiel geändert hast] akzeptiert wird, dann wirst Du sie wohl falsch benutzen.
-
Was macht den der Standardkonstruktor noch außer das Standard Datum anlegen?
Warum zum Beispiel Anstelle von:
if (! (1582<= y ) )nicht:
if ( 1582 > y )?
-
Ja das vermute ich auch.
Hier mal das Programm:
//#include "datum.hpp" //#include "zeit.hpp" //#include "termin.hpp" #include <iostream> #include <string> using namespace std; class Datum { private: //private Variablen Deklaration // unsigned int tag_; unsigned int monat_; unsigned int jahr_; public: // Methoden Deklaration // void setTag(const int); void setMonat(const int); void setJahr(const int); int getTag() const; int getMonat() const; string getMonatString() const; int getJahr() const; // Konstruktor Deklaration // // Standard Konstruktor Datum(const int x=1, const int y=1, const int z=1900); // Überprüfungs Konstruktor Datum(unsigned int, unsigned int, unsigned int); // Überladungs Deklarationen // // Operator << friend ostream &operator<<(ostream &, const Datum &); //Operator >> friend istream &operator>>(istream &, const Datum &); // Operator = Datum& operator=(const Datum &rh); // Operator == bool operator==(const Datum &r); // Operator += Datum &operator+=( int tage); // Methoden(Funktionen) Deklaration bool isValid(unsigned int, unsigned int, unsigned int); void makeValid(); }; // Set-Methoden Definitionen // void Datum::setTag(const int x) {tag_=x; return;} void Datum::setMonat(const int y) {monat_=y; return;} void Datum::setJahr(const int z) {jahr_=z; return;} // Get-Methoden Definitionen // // Tag int Datum::getTag() const { return tag_; } // Monat int Datum::getMonat() const { return monat_; } // Jahr int Datum::getJahr() const { return jahr_; } //Zahlen in Monatsdaten konvertieren string Datum::getMonatString() const { switch (monat_) { case 1: return "Januar"; case 2: return "Februar"; case 3: return "Maerz"; case 4: return "April"; case 5: return "Mai"; case 6: return "Juni"; case 7: return "Juli"; case 8: return "August"; case 9: return "September"; case 10: return "Oktober"; case 11: return "November"; case 12: return "Dezember"; default: return "Undefined"; } } // Konstruktor Definitionen // // Standardkonstruktor Definition Datum::Datum(const int x, const int y, const int z) : tag_(x), monat_(y), jahr_(z) { //... return; } // Konstruktor mit Überprüfung Datum::Datum(unsigned int x, unsigned int y, unsigned int z) { { if (!isValid(x,y,z)) { cout << "Datum ist ungueltig!"; tag_ = 1; monat_ = 1; jahr_ = 1900; } } } // Überladungs Deklarationen // Operator >> istream &operator>>(istream &is, Datum &z) { unsigned int t, m, j; scanf("%i %i %i", &t, &m, &j); z.setTag(t); z.setMonat(m); z.setJahr(j); return is; } // Operator << ostream& operator<<(ostream &os, const Datum &z) { os << z.getTag() << "." <<z.getMonatString() << "."<<z.getJahr(); return os; } // Operator = Datum& Datum::operator=(const Datum &rh) { this->tag_ = rh.tag_; this->monat_ = rh.monat_; this->jahr_ = rh.jahr_; return *this; } bool Datum::operator==(const Datum &r) { return this->getMonat() == r.getMonat() && this->getTag() == r.getTag(); //this->getJahr() == r.getJahr() && //Vergleiche auch Jahreszahlen } // Operator += Datum& Datum::operator+=( int tage) { tag_+= tage; /*if(!isValid()) makeValid();*/ return *this; } bool Datum::isValid(unsigned int tag_, unsigned int monat_, unsigned int jahr_) { if (! (1582<= jahr_ ) )//ab aktuelle jahresberechnung return false; if (! (1<= monat_ && monat_<=12) )// 12 monate checken return false; if (! (1<= tag_ && tag_<=31) ) // tage unter 31 liegen return false; if ( (tag_==31) && (monat_==2 || monat_==4 || monat_==6 || monat_==9 || monat_==11) ) // monate die keine 31 tage haben return false; if ( (tag_==30) && (monat_==2) ) // februar hat keine 31 tage return false; if ( (monat_==2) && (tag_==29) && (jahr_%4!=0) ) //februar auf schaltjahr prüfen - kein schaltjahr return false; if ( (monat_==2) && (tag_==29) && (jahr_%400==0) ) //februar auf schaltjahr prüfen - ist schaltjahr return true; if ( (monat_==2) && (tag_==29) && (jahr_%100==0) ) //februar auf schaltjahr prüfen - kein schaltjahr return false; if ( (monat_==2) && (tag_==29) && (jahr_%4==0) ) //februar auf schlatjahr prüfen - ist schaltjahr return true; return true; } void Datum::makeValid() { // TODO: Implement! } int main() { Datum d1; Datum d2(10,12,2012); cout << "Datum d1: " << d1 << endl; cout << "Datum d2: " << d2 << endl << endl; cout << "Versuche d3 mit Datum 29.02.2007 anzulegen" << endl; Datum d3(29,2,2007); cout << "Datum d3: " << d3 << endl << endl; cout << "Vergleiche d1 mit d2 und d3: " << endl; cout << "d1==d2: " << (d1==d2) << endl; cout << "d1==d3: " << (d1==d3) << endl << endl; cout << "Setze d1 auf Wert von d2" << endl; d1 = d2; cout << "Datum d1: " << d1 << endl << endl; cout << "Addiere 100 Tage zu d1" << endl; d1 += 100; cout << "Datum d1: " << d1 << endl; cout << "Addiere 60 Tage zu d2" << endl; d2 += 60; cout << "Datum d2: " << d2 << endl << endl; cout << "Datum im Format \"tt mm jjjj\" eingeben: "; cout.flush(); cin >> d1; cout << "Speichere eingegebenes Datum in d1" << endl; cout << "Datum d1: " << d1 << endl << endl; system("pause"); return 0; }
-
Warum zum Beispiel Anstelle von:
if (! (1582<= y ) )nicht:
if ( 1582 > y )?
Hat doch den gleichen Effekt

-
Eben. Wenn du eine Fehlermeldung haben möchtest, wenn das Jahr kleiner als 1582 ist, warum prüfst du dann erst ob es größer gleich ist und negierst dann das Ergebnis.
-
Gut die Schreibweise kompliziert das natürlich ändert aber nichts am Verhalten der Funktion.
Ist aber noch die Frage wo ich den Fehler bei der Abfrage gemacht habe

-
Dein Konstruktor
Datum::Datum(unsigned int x, unsigned int y, unsigned int z)wird nicht gerufen, weil 2007, 2 oder 29 alesints sind. Tu den weg, und pack die Überprüfung in deinen StandardkonstruktorDatum(const int x=1, const int y=1, const int z=1900).
Außerdem schreien die vollkommen unsinnigen Bezeichnerx, y, zfür Tag, Monat, Jahr (oder war's jetzt Monat, Tag, Jahr???) nach Verwechslungen. In deinen beiden vorhergehenden Beispielen hattest Du auch zwei verschiedene Reihenfolgen der Argumente.~edit: Typo.~
-
Ok ich werde drauf achten in Zukunft den Code lesbarer zu halten. Da hast du Recht, dass das sinnvoller ist.
Wenn ich die Abfrage in den Standardkonstruktor lege funktioniert die Abfrage.
Gibt es eine Möglichkeit die Abfrage in einen zweiten Konstruktor zu legen? Ich würde gerne einen Standardkonstruktor haben und einen modifizierten.
Zudem gibt es eine Möglichkeit MS-Visio so zu nutzen das ich das Programm Schritt für Schritt durchlaufe um besser Fehler zu finden?
Vielen Dank!
-
Tyle schrieb:
Gibt es eine Möglichkeit die Abfrage in einen zweiten Konstruktor zu legen? Ich würde gerne einen Standardkonstruktor haben und einen modifizierten.
Welchen Zweck hätte es, ungültige Daten zuzulassen?
Tyle schrieb:
Zudem gibt es eine Möglichkeit MS-Visio so zu nutzen das ich das Programm Schritt für Schritt durchlaufe um besser Fehler zu finden?
-> Debugger
-
Mach eben einen Konstruktor ganz ohne Argumente, anstatt einem mit Defaultargumenten:
Datum::Datum(): year(1900), day(1), month(1) { } Datum::Datum(int year, int month, int day) { /* was auch immer */}
-
Für das Programm ist es vollkommen ausreichend nur einen Konstruktor zu haben, das stimmt schon.
Nur soll das Programm 2 Konstruktor beinhalten, ich denke damit wir die Übleradung auch nutzen.
Anforderung:
- Einen Standardkonstruktor der Objekte mit dem Datum 1.1.1900 initialisiert.- Einen Konstruktor mit drei unsigned int-Parameter für Tag, Monat und Jahr
und der überprüft ob das übergebene Datum valid ist, mit Fehlerausgabe und falls ein Fehler vorliegt das Datum mit 1.1.1900 anlegt.Bisher habe ich (wenn ich den Standardkonstruktor entwerne nur den zweiten Konstruktor angelegt bis auf das der keine unsigned int Werte enthält.
-
Mach's doch einfach so:
SeppJ schrieb:
Datum::Datum(): year(1900), day(1), month(1) { } Datum::Datum(int year, int month, int day) { /* was auch immer */}Nimm aus dem Konstruktor mit Überprüfung einfach die Defaultwerte raus und Du bist fertig.