Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <string>
- #include <vector>
- #include <map>
- #include <set>
- #include <exception>
- #include <fstream>
- #include <iomanip>
- #include <sstream>
- #include <cctype> // для функции isdigit
- //#include <ctype>
- using namespace std;
- // дата
- class Date {
- public:
- Date() {
- Year = -1; Month = -1; Day = -1;
- };
- Date(int y, int m, int d)
- {
- if ((m > 12 || m < 1) && (d > 31 || d < 1))
- {
- string string_err = "Month value is invalid: " + to_string(m);
- throw invalid_argument(string_err);
- }
- else if (m > 12 || m < 1)
- { //Month value is invalid: MONTH
- string string_err = "Month value is invalid: " + to_string(m);
- throw invalid_argument(string_err);
- }
- else if (d < 1 || d>31)
- {
- string string_err = "Day value is invalid: " + to_string(d);
- throw invalid_argument(string_err);
- }
- else
- {
- Year = y;
- Month = m;
- Day = d;
- }
- }
- public:
- int GetYear() const
- {
- return Year;
- };
- int GetMonth() const
- {
- return Month;
- };
- int GetDay() const
- {
- return Day;
- };
- private:
- int Year;
- int Month;
- int Day;
- };
- bool operator<(const Date& lhs, const Date& rhs)
- {
- if (lhs.GetYear() == rhs.GetYear())
- {
- if (lhs.GetMonth() == rhs.GetMonth())
- {
- return lhs.GetDay() < rhs.GetDay();
- }
- else return lhs.GetMonth() < rhs.GetMonth();
- }
- else return lhs.GetYear() < rhs.GetYear();
- };
- bool operator==(const Date& lhs, const Date& rhs)
- {
- if (lhs.GetYear() == rhs.GetYear())
- {
- if (lhs.GetMonth() == rhs.GetMonth())
- {
- return lhs.GetDay() == rhs.GetDay();
- }
- else return false;
- }
- else return false;
- };
- // вывод даты в нужном формате
- ostream& operator << (ostream& stream, const Date& date)
- {
- stream << setw(4)<< setfill('0')<< date.GetYear() << "-" << setw(2) << setfill('0') << date.GetMonth()<<"-" << setw(2) << setfill('0') <<date.GetDay();
- return stream;
- }
- /// преобразователь строки в вектор с датой, всё посимвольно
- vector<int> ParseDate(const string& date_str)
- {
- vector<int> date_vec;
- string part, year, month, day;
- int def_count = 0; // счетчик тире
- for (int i = 0; i < date_str.size(); ++i)
- {
- if (date_str[i] != '-')
- {
- // если не тире, проверяем, цифра ли это
- if ((date_str[i] >= '0' && date_str[i] <= '9') && def_count == 0) {
- year += date_str[i];
- }
- else if ((date_str[i] >= '0' && date_str[i] <= '9') && def_count == 1) {
- month += date_str[i];
- }
- else if ((date_str[i] >= '0' && date_str[i] <= '9') && def_count == 2) {
- day += date_str[i];
- }
- else {
- throw runtime_error("Wrong date format: " + date_str);
- }
- }
- else
- {
- def_count++;
- }
- if (def_count > 2) throw runtime_error("Wrong date format: " + date_str);
- }
- if(year !="" && month != "" && day != "")
- {
- if (year.size() <= 4 && month.size() <= 2 && day.size() <= 2)
- {
- date_vec.push_back(stoi(year));
- date_vec.push_back(stoi(month));
- date_vec.push_back(stoi(day));
- }
- else
- throw runtime_error("Wrong date format: " + date_str);
- }
- else
- throw runtime_error("Wrong date format: " + date_str);
- return date_vec;
- }
- // попытка считать дату из потока
- vector<int> ParseDateFlow(const string& date_str)
- {
- vector<int> date_vec;
- stringstream sstr(date_str);
- string year, month, day;
- string year_itog, month_itog, day_itog;
- int flag_y = 1;
- int flag_m = 1;
- int flag_d = 1;
- int i_year, i_month, i_day;
- int def_count = 0; // счетчик тире
- // если в строке не только тире и цифры, надо вылететь
- for (int i = 0; i < date_str.size(); ++i)
- {
- if((date_str[i]< '0' || date_str[i]> '9') && date_str[i] != '-') throw runtime_error("Wrong date format: " + date_str);
- }
- sstr >> i_year;
- if(!(i_year >= 0 && i_year <= 9999)) throw runtime_error("Wrong date format: " + date_str);
- sstr.ignore(1);
- sstr >> i_month;
- sstr.ignore(1);
- sstr >> i_day;
- if(!sstr.eof()) throw runtime_error("Wrong date format: " + date_str);
- date_vec.push_back(i_year);
- date_vec.push_back(i_month);
- date_vec.push_back(i_day);
- return date_vec;
- }
- // структура для ввода команды
- struct command_struct
- {
- string command = "";
- Date date;
- string event = "";
- };
- // заполняем структуру
- command_struct struct_from_command(const string& com)
- {
- command_struct cs;
- stringstream in;
- in.str(com);
- in >> cs.command;
- in.ignore(1);
- string date;
- in >> date;
- if (date != "")
- {
- vector<int> dv = ParseDateFlow(date);
- cs.date = Date(dv.at(0), dv.at(1), dv.at(2));
- }
- in.ignore(1);
- in >> cs.event;
- return cs;
- }
- // класс базы данных
- class Database {
- public:
- void AddEvent(const Date& date, const string& event);
- bool DeleteEvent(const Date& date, const string& event);
- int DeleteDate(const Date& date);
- set<string> Find(const Date& date) const;
- void Print() const;
- private:
- map<Date, set<string> > database;
- };
- void Database::AddEvent(const Date& date, const string& event)
- {
- // ещё раз проверим дату
- if (date.GetYear() >= 0 && date.GetMonth() > 0 && date.GetDay() > 0)
- {
- if (event != "") // и если событие ненулевое
- {
- database[date].insert(event);
- }
- }
- //else throw runtime_error("Wrong date format: ");
- }
- //1. Удалить можно только ранее добавленные события.Если событие найдено и удалено, то программа должна вывести
- //строку «Deleted successfully»(без кавычек).Если событие в указанную дату не найдено, то программа должна
- //вывести строку «Event not found»(без кавычек).
- bool Database::DeleteEvent(const Date& date, const string& event)
- {
- set<string> found_events;
- if (database.size() > 0)
- {
- if(database.find(date)!= database.end())
- {
- found_events = database.at(date);
- if (found_events.size() > 0) {
- for (const auto& item : found_events)
- {
- if (item == event)
- {
- database[date].erase(event);
- // если мы удалили последнее событие, удалим всю дату
- if (database[date].size() == 0)
- {
- database.erase(date);
- }
- return true;
- }
- }
- }
- else return false;
- }
- else return false;
- }
- else return false;
- }
- // 2. Команда удаляет все ранее добавленные события за указанную дату. Программа всегда должна выводить строку
- // вида «Deleted N events», где N — это количество всех найденных и удалённых событий. N может быть равно нулю,
- // если в указанную дату не было ни одного события.
- int Database::DeleteDate(const Date& date)
- {
- if (database.size() > 0)
- {
- if (database.find(date)!=database.end())
- {
- int k = database.at(date).size();
- database.erase(date);
- return k;
- }
- }
- return 0;
- };
- set<string> Database::Find(const Date& date) const
- {
- set<string> date_events = {""};
- date_events.clear();
- if(database.find(date)!=database.end())
- {
- date_events = database.at(date);
- }
- return date_events;
- };
- //С помощью этой команды можно показать полное содержимое нашей БД.Программа должна вывести на печать
- void Database::Print() const
- {
- for (const auto& item1 : database)
- {
- for (const auto& item2 : item1.second)
- {
- cout << item1.first<< " "<< item2 << endl;
- }
- }
- };
- ////////////////////////////////////////////////////////////////////////////
- int main() {
- Database db;
- //-добавление события : Add Дата Событие
- // - удаление события : Del Дата Событие
- // - удаление всех событий за конкретную дату : Del Дата
- // - поиск событий за конкретную дату : Find Дата
- // - печать всех событий за все даты : Print
- string command;
- string event_str;
- Date event_date;
- while (getline(cin, command)) {
- // Считайте команды с потока ввода и обработайте каждую
- // написать функцию, которая разбирает команду
- if (command == "") continue;
- else
- {
- stringstream cs0(command);
- string com, ev;
- string cs0date;
- cs0 >> com;
- cs0.ignore(1);
- cs0 >> cs0date;
- cs0.ignore(1);
- cs0 >> ev;
- // проверим, правильные ли все команды
- try {
- if (com == "Add" || com == "Find" || com == "Del" || com == "Print")
- {
- // для 3го теста
- if (com == "Add" && ev == "") throw runtime_error("Wrong date format: " + cs0date);
- else
- {
- try
- {
- command_struct cs1;
- cs1 = struct_from_command(command);
- if (cs1.command == "Add") // добавить событие в базу
- {
- if (cs0date == "") { throw runtime_error("Wrong date format: " + cs0date); }
- else {
- if (ev != "")
- {
- db.AddEvent(cs1.date, cs1.event);
- }
- }
- //}
- }
- else if (cs1.command == "Del")
- {
- if (cs0date == "") { throw runtime_error("Wrong date format: " + cs0date); }
- else
- {
- if (cs1.event == "")
- {
- int N = db.DeleteDate(cs1.date);
- cout << "Deleted " << N << " events" << endl;
- }
- else
- {
- if (db.DeleteEvent(cs1.date, cs1.event) == true)
- {
- cout << "Deleted successfully" << endl;
- }
- else cout << "Event not found" << endl;
- }
- }
- }
- else if (cs1.command == "Find")
- {
- //Ищем и печатаем ранее добавленные события в указанную дату.Программа должна вывести на печать только сами события,
- //по одному на строке.События должны быть отсортированы по возрастанию в порядке сравнения строк между собой(тип string).
- if (cs0date == "") { throw runtime_error("Wrong date format: " + cs0date); }
- else
- {
- set<string> found_events = db.Find(cs1.date);
- if (found_events.size() > 0)
- {
- for (auto item : found_events)
- {
- cout << item << endl;
- }
- }
- }
- }
- else if (cs1.command == "Print")
- {
- db.Print();
- }
- }
- catch (exception& ex) {
- throw ex;
- }
- }
- }
- else // неизвестная команда
- {
- throw runtime_error( "Unknown command: " + com );
- }
- }
- catch (invalid_argument& ia)
- {
- cout << ia.what() << endl;
- return 0;
- }
- catch (runtime_error& re)
- {
- cout << re.what() << endl;
- return 0;
- }
- catch (exception& ex)
- {
- cout << ex.what() << endl;
- return 0;
- }
- } // else if command != ""
- } // while
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement