Да се създаде клас за работа с дати, съдържащ методи за:
- Въвеждане на дата от клавиатурата
- Извеждане на дата на екрана в различен формат (европейски, американски)
- Проверка дали датата е първия ден от месеца
- Проверка в кой сезон е датата
- Проверка дали датата съвпада с друга дата
- * Пресмятане кой е последния ден от текущия месец
- * Проверка дали датата е последния ден от месеца
- * Преминаване към следващ ден
- * Преминаване към предишен ден
- * Проверка дали датата е валидна дата
Да се направи програма, демонстрираща тези методи.


#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-рия else в DniMesec, където връща резултат в зависимост дали е високосна година или не, ако допуснем, че месеца е валиден (1; 12) и не се открие съвпадение при предходните проверки.
Целият метод може да се вложи в друга условна команда, която използва вече съществуващата функция за проверка на валиден месец и да върне някакво число (да речем отрицателно) при наличие на грешка.
Да, но този код ще се изпълнява и при февруари, и при невалиден месец. А щом имаме данни, въвеждани от потребителя, програмистът трябва винаги да е нащрек :-) Мисълта ми е че може да стане
и с цената на само още един if функцията DniMesec (и всички ползващи я) ще отличава грешни данни от валидни. Но и така както си го направил е напълно коректно – програмистът, който ползва този клас така или иначе трябва да се подсигури първо, че има валидни данни, преди да ги ползва за каквото и да е.
Това просто са два различни подхода при програмирането – единият е класовете да са с по-малко код и по-ефективни и бързи, но да не пазят програмистите, които ги ползват от грешки. Другият подход е класове, които включват проверки на най-критичните места, на цената на известно количество допълнителен код и породеното от него леко забавяне. И двата подхода си имат и предимства и недостатъци и изборът на единия или другия е въпрос на лично предпочитание или конкретна специфика на проекта. Затова писах, че бележките ми са „за размисъл и дискусия“ – за да покажа, че може и така, и онака. Но и както си го направил си е перфектно.
P.S. А ValidnaData в DniMesec не може да ползваш, защото ще имаш непряка рекурсия :-)
Да, това го има :) Забравих как е направен метода. Ами остава вече споменатият вариант.