MyTetra Share
Делитесь знаниями!
Решение
Время создания: 21.08.2017 16:52
Раздел: Computer - Programming - C++ - Coursera White_Belt - Final

/*

БД вида: дата - событие.

Дату определим как строку вида Год-Месяц-День.

Год может быть от 0 до 9999 включительно.

Месяц - от 1 до 12.

День - от 1 до 31.

Год-Месяц-День разделяются только символом дефиса и никаким другим.


Событие - строка из символов без пробелов. Событие не может быть пустым.

В одну и туже дату может быть множество событий. Одинаковые события,

произошедшие в один и тот же день, сохраняются один раз.


Commands:

- добавление события: Add Дата Событие

- удаление события: Del Дата Событие

- удаление всех событий за конкретную дату: Del Дата

- поиск событий за конкретную дату: Find Дата

- печать всех событий за все даты: Print


Все команды, даты и события при вводе разделены пробелами.

Команды считываются из стандартного ввода.

В одной строке может быть ровно одна команда,

но можно ввести несколько команд в несколько строк.

На вход также могут поступать пустые строки - их следует

игнорировать и продолжать обработку новых команд в последующих строках.


Добавление события

При добавлении события БД должна его запомнить и затем

показывать его при поиске (командой Find) или печати (командой Print).

В случае корректного ввода программа ничего не должна выводить на экран.


Удаление события

Удалить можно только ранее добавленные события.

Если событие найдено и удалено, то программа должна вывести строку

«Deleted successfully» (без кавычек).

Если событие в указанную дату не найдено,

то программа должна вывести строку «Event not found» (без кавычек).


Удаление нескольких событий

Команда удаляет все ранее добавленные события за указанную дату.

Программа всегда должна выводить строку вида «Deleted N events»,

где N — это количество всех найденных и удалённых событий.

N может быть равно нулю, если в указанную дату не было ни одного события.


Поиск событий

Ищем и печатаем ранее добавленные события в указанную дату.

Программа должна вывести на печать только сами события, по одному на строке.

События должны быть отсортированы по возрастанию

в порядке сравнения строк между собой (тип string).


Печать всех событий

С помощью этой команды можно показать полное содержимое нашей БД.

Программа должна вывести на печать все пары: Дата Событие по одной на строке.

Все пары должны быть отсортированы по дате,

а события в рамках одной даты должны быть отсортированы

по возрастанию в порядке сравнения строк между собой (тип string).

Даты должны быть отформатированы специальным образом:

ГГГГ-ММ-ДД, где Г, М, Д — это цифры чисел года, месяца и дня соответственно.

Если какое-то число имеет меньше разрядов, то оно должно дополняться нулями,

например, 0001-01-01 — первое января первого года.


Обработка ошибок ввода

Если пользователь ввёл неизвестную команду, то программа

должна об этом сообщить, выведя строку «Unknown command: COMMAND»,

где COMMAND — это та команда, которую ввёл пользователь.

Командой считается первое слово в строке (до пробела).


Если пользователь ввёл дату в неверном формате там, где она ожидалась,

то программа должна напечатать «Wrong date format: DATE»,

где DATE — это то, что пользователь ввёл вместо даты (до пробела).


Если формат даты верный, но сама дата неверна,

то программа должна напечатать более конкретную проблему:

«Month value is invalid: MONTH»,

где MONTH — это неверный номер месяца, например, 13 или 0.

«Day value is invalid: DAY»,

где DAY — это неверный номер дня в месяце, например, 39 или 0.

Значение года проверять отдельно не нужно.

Не нужно проверять календарную корректность даты:

количество дней в каждом месяце считается равным 31,

високосные года учитывать не нужно.

Если неверны как месяц, так и день, то нужно вывести

одно сообщение об ошибке в месяце.


После любой ошибки ввода и печати сообщения программа должна завершать своё выполнение.


*/


#include <iostream>

#include <sstream>

#include <iomanip>

#include <exception>

#include <string>

#include <set>

#include <map>


using namespace std;


class Date

{

public:

Date()

{

year = 0;

month = 1;

day = 1;

}

Date(const int& y, const int& m, const int& d)

{

year = y;

month = m;

day = d;

}

void PrintDate() const

{

cout << setw(4) << setfill('0') << year << "-";

cout << setw(2) << setfill('0') << month << "-";

cout << setw(2) << setfill('0') << day;

}

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())

return true;

else if(lhs.GetYear() == rhs.GetYear())

{

if(lhs.GetMonth() < rhs.GetMonth())

return true;

else if(lhs.GetMonth() == rhs.GetMonth())

{

if(lhs.GetDay() < rhs.GetDay())

return true;

else return false;

}

else return false;

}

else return false;

}


class Database

{

public:

void AddEvent(const Date& date, const string& event)

{

eve[date].insert(event);

}

bool DeleteEvent(const Date& date, const string& event)

{

if(eve.count(date))

{

if(eve.at(date).count(event))

{

eve[date].erase(event);

return true;

}

}

return false;

}

int DeleteDate(const Date& date)

{

int size = eve[date].size();

eve.erase(date);

return size;

}

void Find(const Date& date) const

{

if(eve.count(date))

{

set<string> dateEvents = eve.at(date);

for(const string& s : dateEvents)

cout << s << endl;

}

}

void Print() const

{

for(const auto& i : eve)

{

for(const auto& j : i.second)

{

i.first.PrintDate();

cout << " " << j << endl;

}

}

}


private:

map<Date, set<string>> eve;

};


void WrongDateFormat(const string& msg)

{

string errmsg = "Wrong date format: " + msg;

throw runtime_error(errmsg);

}


int DateValueFromStream(stringstream& stream, const string& s)

{

if(stream.peek() == '-')

{

int value;

stream.ignore(1);

stream >> value;

return value;

/* if(isdigit(value))

return value;

else

WrongDateFormat(s);*/

}

else

{

WrongDateFormat(s);

}

}


Date DateFromString(const string& str)

{

if(str.empty())

{

WrongDateFormat(str);

}

stringstream ss(str);

int year;

int month;

int day;

ss >> year;

if(year < 0 || year > 9999)

{

WrongDateFormat(str);

}

month = DateValueFromStream(ss, str);

day = DateValueFromStream(ss, str);

if(ss.peek() != EOF)

{

WrongDateFormat(str);

}

if(month < 1 || month > 12)

{

stringstream errmsg;

errmsg << "Month value is invalid: " << month;

throw runtime_error(errmsg.str());

}

if(day < 1 || day > 31)

{

stringstream errmsg;

errmsg << "Day value is invalid: " << day;

throw runtime_error(errmsg.str());

}

Date date(year, month, day);

return date;

}


int main()

{

Database db;

string command;

try

{

while(getline(cin, command))

{

if(!command.empty())

{

string request;

stringstream stream(command);

stream >> request;

if(request == "Print")

{

db.Print();

}

else if(request == "Add" || request == "Del" || request == "Find")

{

Date date;

string event;

string dateStr;

stream >> dateStr;

date = DateFromString(dateStr);

stream >> event;

if(request == "Find")

{

db.Find(date);

}

else

{

if(request == "Add")

{

if(event.empty())

{

WrongDateFormat(dateStr);

}

else db.AddEvent(date, event);

}

else if(request == "Del" && !event.empty())

{

if(db.DeleteEvent(date, event))

cout << "Deleted successfully";

else cout << "Event not found";

cout << endl;

}

else //DEL without any EVENT

{

cout << "Deleted " << db.DeleteDate(date) << " events" << endl;

}

}

}

else

{

string errmsg = "Unknown command: " + request;

throw runtime_error(errmsg);

}

}

}

}

catch(exception& ex)

{

cout << ex.what() << endl;

}

getchar();

return 0;

}

Так же в этом разделе:
 
MyTetra Share v.0.53
Яндекс индекс цитирования