Problem bei Datum-Klasse



  • Hallo! 🙂

    ich soll eine datum-klasse mit folgenden memberfunktionen schreiben:
    • set_date(int y, int m, int d): Setzt das Datum auf das gegebene Jahr, Monat und Tag.
    • add_days(int d), add_months(int m), add_years(int y): Za ̈hlen zum Datum die angege- benen Tage bzw. Monate oder Jahre hinzu. Beachten Sie, daß die Argumente d, m, y sowohl negativ als auch beliebig gross sein ko ̈nnen (z.B.: add_days(-3400)).
    Wenn im Konstruktor der Klasse ein ungültiges Datum angegeben wird, dann soll eine Fehlermeldung ausgegeben werden und das Datum auf den 1.1.1900 gesetzt werden

    ich denke das habe ich soweit auch hinbekommen, jedoch folgender Zusatz bereitet mir Kopfzerbrechen:
    Es gilt für add_months und add_years folgende Spezialregel: Der Monatsletzte soll immer auf einen anderen Monatsletzten verschoben werden.

    Ich habe keinen Plan, wie ich diesen letzten Punkt in mein Programm integrieren kann, ohne weitere memberfunktionen hinzuzufügen.
    Vielleicht könnt ihr mir da helfen.

    //  Date.hpp
    //
    
    #ifndef __Date2__Date__
    #define __Date2__Date__
    
    class Date {
    public:
    	//! Construct a date
        Date(int y, int m, int d);
        Date();
    	void set_date(int y, int m, int d);
        //! return year
        int year();
        //! return month
        int month();
        //! return date
        int day();
        //! add d days to the date
        void add_days(int d);
        //! add m months to the date
        void add_months(int m);
        //! add y years to the date
        void add_years(int y);
    private:
        //! store year
        int y_;
        //! store year
        int m_;
        //! store year
        int d_;
    };
    
    #endif /* defined(__Date2__Date__) */
    
    //  Date.cpp
    //
    
    #include <iostream>
    #include "Date.hpp"
    
    using namespace std;
    
    //@@ You should, in general, try to avoid code duplication when
    //@@ implementing the date class. If you need something more often
    //@@ than once, this something should go in its own function.
    
    //@@ You can add the definitions ofsuch helper functions here at
    //@@ the beginning of Date.cpp. Please DO NOT DEFINE THEM IN SEPARATE
    //@@ .hpp/.cpp FILES !!!. The unit test cannot find those additional
    //@@ functions and will not compile your code.
    
    //@@ Example: you could define a function that checks whether year y
    //@@ is a leap year here...
    
    // helper functions
    
    bool is_leap_year(int y) {
    	return ((y%4==0) && !((y%100==0) && (y%400!=0)));
    }
    
    int days_in_month(int uyear, int umonth){ 
    	int arrdays_in_month[13] = {  31, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; // 0=Dec, 1=Jan,..., 12=Dec
    
    	if (umonth == 2)
    	{
    		// Februar: Schaltjahr unterscheiden
    		if (is_leap_year(uyear))
    			return 29;
    		else
    			return 28;
    	}
    	return arrdays_in_month[umonth];
    
    }                
    
    Date::Date(int y, int m, int d) {
    	set_date(y, m, d);
    }
    
    Date::Date() : y_(1900), m_(1), d_(1) {}
    
    void Date::set_date (int y, int m, int d) {
    	if (d<=days_in_month(y, m) && (m<=12)) {
    		y_ = y;
    		m_ = m;
    		d_ = d;
    	}
    	else {
    		cout << "Die Datumseingabe ist nicht korrekt!" << endl;
    		y_ = 1900;
    		m_ = 1;
    		d_ = 1;
    	}
    }
    
    //@@ Definitions of Date's member functions should go below here.
    //@@ I am putting the definitions of year(), month() and day() as
    //@@ an example ...
    
    int Date::year() {			//WOZU BENÖTIGE ICH DIESE FUNKTIONEN??
        return y_;
    }
    
    int Date::month() {
        return m_;
    }
    
    int Date::day() {
        return d_;
    }
    
    void Date::add_days(int d){
    	if (d>=0){
    		while (days_in_month(y_, m_)<(d_+d)) {
    			d -= days_in_month(y_, m_);
    			add_months(1);
    			cout << d << endl;
    		}
    		d_ += d;
    	}
    	else {
    		while (d_<=-d) {
    			d += d_;
    			d_ = days_in_month(y_, (m_-1));
    			add_months(-1);
    			cout << d << " " << m_ << endl;
    		}
    		d_ += d;
    	}
    }
    
    void Date::add_months(int m)
    {
    	if (m>=0) {
    		while (m_+m>12) {
    			m -= 12;
    			add_years(1);
    		}
    		m_ += m;
    	}
    	else {
    		while (m_<=-m) {
    			m += m_;
    			m_ = 12;
    			add_years(-1);
    		}
    		m_ += m;
    	}
    }
    
    void Date::add_years(int y){
    	y_ += y;
    }
    

  • Mod

    chiral schrieb:

    Wenn im Konstruktor der Klasse ein ungültiges Datum angegeben wird, dann soll eine Fehlermeldung ausgegeben werden und das Datum auf den 1.1.1900 gesetzt werden

    Schrecklich. 👎

    Ich habe keinen Plan, wie ich diesen letzten Punkt in mein Programm integrieren kann, ohne weitere memberfunktionen hinzuzufügen.
    Vielleicht könnt ihr mir da helfen.

    -Du darfst sicherlich weitere Funktionen hinzufügen, wenn dir das hilft
    -Könntest du es denn mit diesen Zusatzfunktionen?
    -Falls ja: Wenn du trotzdem unbedingt weitere Funktionen vermeiden möchtest, dann bau doch einfach das, was du in diesen Funktionen gemacht hättest, in add_months ein.

    P.S.: Ich kann dein Programm durch geschickte Angabe eines ungültigen Datums zum Absturz bringen. Denk mal noch einmal genau über den Programmverlauf nach. Vielleicht hilft dir zur Korrektur des Problems folgendes (kann man aber auch anders machen, ist bloß gut zu wissen):
    http://en.wikipedia.org/wiki/Short-circuit_evaluation



  • chiral schrieb:

    Ich habe keinen Plan, wie ich diesen letzten Punkt in mein Programm integrieren kann, ohne weitere memberfunktionen hinzuzufügen.

    private Memberfunktionen füge ruhig zu.



  • Vielen Dank für die Antworen!!

    ich hab nun noch einige punkte verändert und eine zusätzliche private member function hinzugefügt.

    hier hab ich die if bedingung erweitert. (war das der fehler, der mein programm zum absturz brachte??)

    void Date::set_date (int y, int m, int d) {
    	if (d<=days_in_month(y, m) && (d>0) && (m>0) && (m<=12)) {
    		y_ = y;
    		m_ = m;
    		d_ = d;
    	}
    	else {
    		cout << "Die Datumseingabe ist nicht korrekt!" << endl;
    		y_ = 1900;
    		m_ = 1;
    		d_ = 1;
    	}
    }
    
    void Date::add_days(int d){
    	if (d>=0){
    		while (days_in_month(y_, m_)<(d_+d)) {
    			d -= days_in_month(y_, m_);
    			inc_months(1);
    			cout << d << endl;
    		}
    		d_ += d;
    	}
    	else {
    		while (d_<=-d) {
    			d += d_;
    			d_ = days_in_month(y_, (m_-1));
    			inc_months(-1);
    			cout << d << " " << m_ << endl;
    		}
    		d_ += d;
    	}
    }
    
    void Date::inc_months(int m)
    {
    	if (m>=0) {
    		while (m_+m>12) {
    			m -= 12;
    			++y_;
    		}
    		m_ += m;
    	}
    	else {
    		while (m_<=-m) {
    			m += m_;
    			m_ = 12;
    			--y_;
    		}
    		m_ += m;
    	}
    }
    
    void Date::add_months(int m)
    {
    	if (m>0) {
    		if (d_ = days_in_month(y_, m_)) {
    			while (m_+m>12) {
    			m -= 12;
    			++y_;
    			}
    			d_ = days_in_month(y_, (m_+m));
    		}
    		else {
    			while (m_+m>12) {
    				m -= 12;
    				++y_;
    			}
    		}
    			m_ += m;
    	}		
    	else {
    		if (m<0) {
    			if (d_ >= days_in_month(y_, m_)) {
    				while (m_<=-m) {
    					m += m_;
    					m_ = 12;
    					--y_;
    				}
    				m_ += m;
    				d_ = days_in_month(y_, (m_));
    			}
    			else {
    				while (m_<=-m) {
    					m += m_;
    					m_ = 12;
    					--y_;
    				}
    				m_ += m;
    				if (d_>days_in_month(y_, m_))
    					d_=days_in_month(y_, m_);
    			}
    		}
    		else {}
    	}
    }
    
    void Date::add_years(int y){
    	if ((m_=2) && (d_=days_in_month(y_, m_))) {
    		y_ += y;
    		d_ = days_in_month(y_, m_);
    	}
    	else
    		y_ = y;
    }
    

    dieser teil ist nun ziemlich umständlich, aber das programm läuft und macht auch meistens was es soll... 😉

    nur bei einem punkt geschehen dubiose dinge. wenn ich in der main folgendes eingebe...

    int main(int argc, const char * argv[])
    {    
        Date date(2013, 3, 31);
    	date.add_days(-365);
    	date.add_months(0);
    	date.add_years(0);
        cout << date.day() << "." << date.month() << "." << date.year() << endl;
        return 0;
    }
    

    ...dann erhalte ich, wenn ich date.add_years(0) lösche, den 31.3.2012.
    So jedoch wird der 29.2.2012 ausgegeben.
    Warum nur?


  • Mod

    chiral schrieb:

    hier hab ich die if bedingung erweitert. (war das der fehler, der mein programm zum absturz brachte??)

    Nein.

    ...dann erhalte ich, wenn ich date.add_years(0) lösche, den 31.3.2012.
    So jedoch wird der 29.2.2012 ausgegeben.
    Warum nur?

    Ziemlich wahrscheinlich der gleiche Fehler (habe das Programm nur überflogen).

    Du wendest ständig days_in_month auf ungeprüfte Nutzereingaben an. Dadurch kann ein böswilliger oder unbedarfter Nutzer 0, negative oder Monate > 12 angeben. Das führt zu einem unsinnigen Fehlerwert bei 0 und zu undefiniertem Verhalten (Absturz oder Datenmüll) sonst.

    edit: Nein, der Fehler nach dem du fragtest ist ein anderer:

    if ((m_=2) && (d_=days_in_month(y_, m_)))
    

    Lass mich raten: Da stand

    if (m_=2 && d_=days_in_month(y_, m_))
    

    und der Compiler hat dich gewarnt, dass du da Klammern um die Zuweisung machen solltest? Da hast du dich selbst angeschmiert, denn das wichtige Stichwort, dass dir der Compiler nennen wollte war "Zuweisung".



  • Habs nun halbwegs hinbekommen. Danke für die Hilfe!!


Anmelden zum Antworten