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

Ключевой момент в решении задачи — выбор контейнера для хранения событий. Поскольку нам требуется быстрый поиск событий по дате, а также быстрое удаление конкретного события, используем словарь множеств — map<Date, set<string>>, для каждой даты хранящий множество соответствующих событий.

Кроме того, важно было аккуратно организовать обработку ошибок — тут очень помогает механизм исключений. Обратите внимание, например, на проверку корректности дня и месяца в дате: она вынесена в конструктор даты, что позволяет не заботиться об этом во всех остальных функциях, работающих с датами.


#include <cstdint>

#include <iomanip>

#include <iostream>

#include <map>

#include <set>

#include <sstream>

#include <stdexcept>

#include <string>

#include <vector>


using namespace std;


class Date {

public:

// конструктор выбрасывает исключение, если его аргументы некорректны

Date(int new_year, int new_month, int new_day) {

year = new_year;

if (new_month > 12 || new_month < 1) {

throw logic_error("Month value is invalid: " + to_string(new_month));

}

month = new_month;

if (new_day > 31 || new_day < 1) {

throw logic_error("Day value is invalid: " + to_string(new_day));

}

day = new_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) {

// воспользуемся тем фактом, что векторы уже можно сравнивать на <:

// создадим вектор из года, месяца и дня для каждой даты и сравним их

return vector<int>{lhs.GetYear(), lhs.GetMonth(), lhs.GetDay()} <

vector<int>{rhs.GetYear(), rhs.GetMonth(), rhs.GetDay()};

}


// даты будут по умолчанию выводиться в нужном формате

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;

}


class Database {

public:

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

storage[date].insert(event);

}

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

if (storage.count(date) > 0 && storage[date].count(event) > 0) {

storage[date].erase(event);

return true;

}

return false;

}

int DeleteDate(const Date& date) {

if (storage.count(date) == 0) {

return 0;

} else {

const int event_count = storage[date].size();

storage.erase(date);

return event_count;

}

}


set<string> Find(const Date& date) const {

if (storage.count(date) > 0) {

return storage.at(date);

} else {

return {};

}

}


void Print() const {

for (const auto& item : storage) {

for (const string& event : item.second) {

cout << item.first << " " << event << endl;

}

}

}


private:

map<Date, set<string>> storage;

};


Date ParseDate(const string& date) {

stringstream date_stream(date);

int year;

date_stream >> year;

if (date_stream.peek() != '-') {

throw logic_error("Wrong date format: " + date);

}

date_stream.ignore();

int month;

date_stream >> month;

if (date_stream.peek() != '-') {

throw logic_error("Wrong date format: " + date);

}

date_stream.ignore();

int day;

date_stream >> day;

if (!date_stream.eof()) {

throw logic_error("Wrong date format: " + date);

}

return Date(year, month, day);

}


int main() {

try {

Database db;


string command_line;

while (getline(cin, command_line)) {

stringstream ss(command_line);

string command;

ss >> command;

if (command == "Add") {

string date_str, event;

ss >> date_str >> event;

const Date date = ParseDate(date_str);

db.AddEvent(date, event);

} else if (command == "Del") {

string date_str;

ss >> date_str;

string event;

if (!ss.eof()) {

ss >> event;

}

const Date date = ParseDate(date_str);

if (event.empty()) {

const int count = db.DeleteDate(date);

cout << "Deleted " << count << " events" << endl;

} else {

if (db.DeleteEvent(date, event)) {

cout << "Deleted successfully" << endl;

} else {

cout << "Event not found" << endl;

}

}

} else if (command == "Find") {

string date_str;

ss >> date_str;

const Date date = ParseDate(date_str);

for (const string& event : db.Find(date)) {

cout << event << endl;

}

} else if (command == "Print") {

db.Print();

} else if (command.empty()) {

break;

} else {

throw logic_error("Unknown command: " + command);

}

}

} catch (const exception& e) {

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

}


return 0;

}













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