Клас за работа с дати

Да се създаде клас за работа с дати, съдържащ методи за:

  1. Въвеждане на дата от клавиатурата
  2. Извеждане на дата на екрана в различен формат (европейски, американски)
  3. Проверка дали датата е първия ден от месеца
  4. Проверка в кой сезон е датата
  5. Проверка дали датата съвпада с друга дата
  6. * Пресмятане кой е последния ден от текущия месец
  7. * Проверка дали датата е последния ден от месеца
  8. * Преминаване към следващ ден
  9. * Преминаване към предишен ден
  10. * Проверка дали датата е валидна дата

Да се направи програма, демонстрираща тези методи.

Публикувано в 12а с етикети . Постоянна връзка.

6 Responses to Клас за работа с дати

  1. dreanor каза:
    #include <cstdlib>
    #include <iostream>
    
    using namespace std;
    
    class Data
    {
    public:
        int den, mesec, godina;
        Data();
        Data(int d, int m, int g);
        Data(const Data &d);
        void Vhod();
        void Izwejdane(char format) const;
        bool NachaloMesec() const;
        int Sezon() const;
        bool Suwpadenie(int d, int m, int g) const;
        bool Suwpadenie(const Data &d) const;
        int DniMesec() const;
        bool PosledenDen() const;
        void SledwashtDen();
        void PredishenDen();
        bool ValidnaData() const;
    
    };
    
    Data::Data()
    {
       den=mesec=godina=1;
    }
    
    Data::Data (const Data &d)
    {
        den=d.den;
        mesec=d.mesec;
        godina=d.godina;
    }
    
    Data::Data(int d, int m, int g)
    {
        den=d;
        mesec=m;
        godina=g;
    }
    
    void Data::Vhod()
    {
        cout<<"Wuwedete den, mesec, godina: ";
        cin>>den>>mesec>>godina;
    }
    
    void Data::Izwejdane(char format) const
    {
        switch(format)
        {
        case('a'): cout<<mesec<<'/'<<den<<'/'<<godina; break;
        case('e'): cout<<den<<'.'<<mesec<<'.'<<godina; break;
        default: cout<<"Newaliden izbor\n";
        };
    }
    
    bool Data::NachaloMesec() const
    {
        return den==1;
    }
    
    int Data::Sezon() const
    {
        switch (mesec)
        {
        //зима
        case(12):
        case(1):
        case(2): return 4;
    
        //пролет
        case(3):
        case(4):
        case(5): return 1;
    
        //лято
        case(6):
        case(7):
        case(8): return 2;
    
        //есен
        case(9):
        case(10):
        case(11): return 3;
    
        default: return 0;
        }
    }
    
    bool Data::Suwpadenie(int d, int m, int g) const
    {
        return ((den==d) && (mesec==m) && (godina==g));
    }
    
    bool Data::Suwpadenie(const Data &d) const
    {
        return ((den==d.den) && (mesec==d.mesec) && (godina==d.godina));
    }
    
    
    int Data::DniMesec() const
    {
        if(mesec == 1 || mesec == 3 || mesec == 5 || mesec == 7 || mesec == 8 || mesec == 10 || mesec == 12)
            return 31;
        else if(mesec == 4 || mesec == 6 || mesec == 9 || mesec == 11)
            return 30;
        else
        {
            if(godina % 4 == 0)
            {
                if(godina % 100 == 0)
                {
                    if(godina % 400 == 0)
                        return 29;
                    return 28;
                }
                return 29;
            }
            return 28;
        }
    }
    
    bool Data::PosledenDen() const
    {
        return den==DniMesec();
    }
    
    void Data::SledwashtDen()
    {
        if(ValidnaData())
        {
            if (den<DniMesec())
                den++;
            else
            {
                den=1;
                if(mesec<12)
                    mesec++;
                else
                {
                    mesec=1;
                    godina++;
                }
            }
        }
    }
    
    void Data::PredishenDen()
    {
        if(ValidnaData())
        {
            if(den>1)
                den--;
            else
            {
                if(mesec>1)
                {
                    mesec--;
                    den=DniMesec();
                }
                else
                {
                    mesec=12;
                    godina--;
                    den=31;
                }
            }
        }
    }
    
    bool Data::ValidnaData() const
    {
        if ((mesec>=1)&&(mesec<=12)&&(godina>0))
        {
            if ((den>=1)&&(den<=DniMesec()))
                    return true;
            else return false;
        }
        else return false;
    }
    
    
    
    
    int main(int argc, char *argv[])
    {
        Data dnes(28, 2, 2014);
        dnes.Izwejdane('e');
        cout<<"\nProwerka za walidna data: "<<dnes.ValidnaData();
    
        cout<<"\nDali dnes e nachaloto na meseca? "<<dnes.NachaloMesec()<<endl;
    
        cout<<"Sezonut w koito e meseca ( prolet, lqto, esen, zima): "<<dnes.Sezon()<<endl;
    
        cout<<"Suzdawane na now obekt i wuwejdane na danni ot klaviaturata: \n";
        Data* DataPtr= new Data();
        DataPtr->Vhod();
    
        cout<<"Demonstraciq na funkciite sledwasht i predishen den: \n";
        DataPtr->SledwashtDen();
        DataPtr->Izwejdane('e');
        cout<<endl<<endl;
    
        dnes.SledwashtDen();
        dnes.Izwejdane('e');
        cout<<endl<<endl;
    
        DataPtr->PredishenDen();
        DataPtr->Izwejdane('e');
        cout<<endl<<endl;
    
        dnes.PredishenDen();
        dnes.Izwejdane('e');
        cout<<endl<<endl;
    
        delete DataPtr;
        return 0;
    }
    
    • Данаил каза:

      Много добро решение! И добре обмислено (например липсата на break в Sezon)! Демонстрираш и познания извън преподаденото – например еднаквите имена на методите. Хареса ми и дето си демонстрирал и статична променлива и динамична. Радва и това, че преди да успея да пусна кода, който направихме в часа, ти ме изпревари и с тази част, и с останалото :-)

      Ако се налага да намеря какво да коментирам по решението въобще (макар всичките му съвършенства), бих подал следните теми за размисъл и дискусия:
      1. „Wuwedete den, mesec, godina: “ може да подлъже потребителя, че може да постави запетая между въвежданите данни
      2. Първата част на DniMesec може да се реализира със switch, а втората – само с един if или дори без нито един (като се използва преобразуването между типовете – return 28 + проверка–за-високосна). Но така, както си го направил, е по-прегледно.
      3. DniMesec (и всички свързани с него фунции) няма да работи коректно при невалиден месец (да кажем 0 или > 12). Добре е да сложиш и проверка дали месеца е февруари.

  2. dreanor каза:

    Проверката за февруари се извършва при 2-рия else в DniMesec, където връща резултат в зависимост дали е високосна година или не, ако допуснем, че месеца е валиден (1; 12) и не се открие съвпадение при предходните проверки.
    Целият метод може да се вложи в друга условна команда, която използва вече съществуващата функция за проверка на валиден месец и да върне някакво число (да речем отрицателно) при наличие на грешка.

    • Данаил каза:

      Да, но този код ще се изпълнява и при февруари, и при невалиден месец. А щом имаме данни, въвеждани от потребителя, програмистът трябва винаги да е нащрек :-) Мисълта ми е че може да стане

      else if(mesec == 2)
        // кода за проверка за високосна година
      else return 0;
      

      и с цената на само още един if функцията DniMesec (и всички ползващи я) ще отличава грешни данни от валидни. Но и така както си го направил е напълно коректно – програмистът, който ползва този клас така или иначе трябва да се подсигури първо, че има валидни данни, преди да ги ползва за каквото и да е.

      Това просто са два различни подхода при програмирането – единият е класовете да са с по-малко код и по-ефективни и бързи, но да не пазят програмистите, които ги ползват от грешки. Другият подход е класове, които включват проверки на най-критичните места, на цената на известно количество допълнителен код и породеното от него леко забавяне. И двата подхода си имат и предимства и недостатъци и изборът на единия или другия е въпрос на лично предпочитание или конкретна специфика на проекта. Затова писах, че бележките ми са „за размисъл и дискусия“ – за да покажа, че може и така, и онака. Но и както си го направил си е перфектно.

    • Данаил каза:

      P.S. А ValidnaData в DniMesec не може да ползваш, защото ще имаш непряка рекурсия :-)

Вашият коментар