diff --git a/Application/Application.cpp b/Application/Application.cpp new file mode 100644 index 0000000..9b3159f --- /dev/null +++ b/Application/Application.cpp @@ -0,0 +1,272 @@ +#include "Line.h" + +#include +#include +#include +#include + +using namespace Library; +using namespace std; + +string msgs[] = { "Exit", "Print menu", "Print", "Set line name", "Add station","Add transfer", "Find station", "Delete station", "Find transfer", + "Get type of station", "Delete transfer", "Change station name", "Save file", "Read file", "Check stations"}; + +const int amount = 15; + +Line CreateNew(); //создание нового + +bool Exit(Line&); //функция выхода +bool Menu(Line&); //меню +bool Print(Line&); //вывод всей информации +bool SetName(Line&); //изменить имя линии +bool AddStation(Line&); //добавить станцию +bool AddTransfer(Line&); //добавить пересадку +bool FindStation(Line&); //поиск станции на линии +bool DeleteStation(Line&); //удаление станиции +bool FindTransfer(Line&); //поиск станции, с которой есть переход на данную станцию +bool GetType(Line&); //вывод типа станций +bool DeleteTransfer(Line&); //удаление пересадок +bool ChangeStationName(Line&); //изменение имени станции +bool SaveFile(Line&); //запись в файл +bool ReadFile(Line&); //чтение из файла +bool CheckStations(Line&); //проверить корректность описания станций (конкретно - проверка правильности кол-ва пересадок) + +// ввод числа из входного потока i +template +void getNum(T &a) +{ + cin >> a; + while (!cin.good()) + { + getchar(); + cin.clear(); + cin >> a; + } +} + +string getStr(); //чтение строки с пробелами + +int main() +{ + Line L = CreateNew(); + bool ex = false; + size_t choice = 0; + Menu(L); + bool(*func[amount]) (Line&) = { Exit, Menu, Print, SetName, AddStation, AddTransfer, FindStation, DeleteStation, FindTransfer, + GetType, DeleteTransfer, ChangeStationName, SaveFile, ReadFile, CheckStations}; //массив функций + + while (!ex) + { //цикл выбора пукнта + cout << "Make your choice: "; + getNum(choice); + while (choice >= amount) //пока не ввели корректный номер пункта + getNum(choice); + try + { + ex = (*func[choice])(L); + } + catch (const exception& e) + { + cout << "Error: " << e.what() << endl; + } + catch (...) + { + cout << "Unknown error" << endl; + } + } + + return 0; +} + +//создание новой линии +Line CreateNew() +{ + cout << "Enter name of line: "; + string name = getStr(); + return Line(name); +} + +//завершение программы +bool Exit(Line& L) +{ + return true; +} + +//вывод меню +bool Menu(Line&) +{ + for (size_t i = 0; i < amount; ++i) + cout << i << " " << msgs[i] << endl; + return false; +} + +//вывод плана +bool Print(Line& L) +{ + cout << L; + return false; +} + +//изменение имени +bool SetName(Line& L) +{ + cout << "Enter new name of line: "; + string name = getStr(); + L.setName(name); + cout << "Name changed successfull" << endl; + return false; +} + +//добавление станции +bool AddStation(Line& L) +{ + cout << "Enter position of new station: "; + size_t position; + getNum(position); + cout << "Enter name of station: "; + string name = getStr(); + L.addStation(name, position); + cout << "Station added successfull " << endl; + return false; +} + +//добавление пересадки +bool AddTransfer(Line& L) +{ + cout << "Enter position of station: "; + size_t position; //ввод позиции станции + getNum(position); + cout << "Enter name of station: "; + string station = getStr(); //ввод имени станции + cout << "Enter name of line: "; + string line = getStr(); //ввод имени линии, куда будет происходить персадка + L.addTransfer(position, station, line); + cout << "Station added successfull" << endl; + return false; +} + +//поиск станции +bool FindStation(Line& L) +{ + cout << "Enter name of station: "; + string station = getStr(); + const Station* S = L.find(station); + if (S) + cout << *S; + else + cout << "Station not found" << endl; + return false; +} + +//удаление станции +bool DeleteStation(Line& L) +{ + cout << "Enter name of station: "; + string station = getStr(); //удаление станции + L.deleteStation(station); + cout << "Station deleted" << endl; + return false; +} + +//поиск пересадки на даннцю станцию +bool FindTransfer(Line& L) +{ + cout << "Enter name of station: "; + string station = getStr(); + const Station* S = L.findTransfer(station); + if (S) + cout << *S; + else + cout << "Station not found" << endl; + return false; +} + +//получение имени типа данной станции +bool GetType(Line& L) +{ + cout << "Enter name of station: "; + string station = getStr(); + cout << "Type is: " << L.getType(station) << endl; + return false; +} + +//удалить заданную пересадку с заданной номером станции +bool DeleteTransfer(Line& L) +{ + cout << "Enter position of station: "; + size_t stationPosition; + getNum(stationPosition); + cout << "Enter position of transfer: "; + size_t transferPosition; + getNum(transferPosition); + L.deleteTransfer(stationPosition, transferPosition); + cout << "Transfer deleted" << endl; + return false; +} + +//изменение имени станции +bool ChangeStationName(Line& L) +{ + cout << "Enter position of station: "; + size_t position; + getNum(position); + cout << "Enter name of station: "; + string name = getStr(); + L.changeStationName(position, name); + cout << "Name changed" << endl; + return false; +} + +//сохранить в файл +bool SaveFile(Line& L) +{ + cout << "Enter file name: "; + string file = getStr(); + ofstream o; + o.open(file); + L.save(o); + cout << "File wrote successfull" << endl; + return false; +} + +//считать из файла +bool ReadFile(Line& L) +{ + cout << "Enter file name: "; + string file = getStr(); + ifstream i; + i.open(file); + if (i) + { + L.read(i); + cout << "File read" << endl; + } + else + { + cout << "File not found" << endl; + } + return false; +} + +//проверка корректности количествапересадок на станции с помощью итератора +bool CheckStations(Line& L) +{ + for (Line::const_iterator it = L.begin(); it != L.end(); it++) + if ((*it)->correct()) + cout << (*it)->name() << " is correct." << endl; + else + cout << (*it)->name() << " is incorrect." << endl; + return false; +} + +string getStr() //чтение строки +{ + string s = ""; + getline(cin, s); + if (s.length() == 0) + { + cin.clear(); + getline(cin, s); + } + return s; +} diff --git a/Library/Line.cpp b/Library/Line.cpp new file mode 100644 index 0000000..a911df4 --- /dev/null +++ b/Library/Line.cpp @@ -0,0 +1,227 @@ +#include "Line.h" + +#include + +using namespace Library; +using namespace std; + +Line::Line(string name) +{ + m_name = name; +} + +Line::Line(const Line& L) +{ + m_name = L.m_name; + try + { + for (auto s : L.m_stations) //клонируем каждый элемент из контейнера другой линии + m_stations.push_back(s->clone()); + } + catch (const exception& e) //если при копировании возникло исключение + { + for (auto s : m_stations) //s имеет тип Station* + delete s; //очищаем что накопировали + throw e; //и выкидываем исключение дальше + } +} + +Line::Line(Line&& L) +{ + m_name = L.m_name; + m_stations = L.m_stations; + L.m_stations.clear(); +} + +Line::~Line() +{ + for(auto s : m_stations) + delete s; //удаляем все станции в контейнере +} + +Line& Line::operator= (const Line& L) +{ + if (this != &L) + { + m_name = L.m_name; + deque stations; + try + { + for (auto s : L.m_stations) //клонируем каждый элемент из контейнера другой линии + stations.push_back(s->clone()); + for (auto s : m_stations) + delete s; //удаляем все станции, которые хранились + m_stations.clear(); + m_stations = stations; + } + catch (const exception& e) //если при копировании возникло исключение + { + for (auto s : stations) //s - имеет тип Station* + delete s; //очищаем что накопировали + throw e; //и выкидываем исключение дальше + } + } + return *this; +} + +Line& Line::operator= (Line&& L) +{ + if (this != &L) + { + m_name = L.m_name; + m_stations = L.m_stations; + L.m_stations.clear(); + } + return *this; +} + + +std::ostream& Library::operator<< (std::ostream& o, const Line& L) +{ + o << "Line: " << L.m_name << endl << endl; + size_t i = 0; + for (auto s : L.m_stations) //выводим все станции в линии (s имеет тип Station*) + o << i++ << " " << *s << endl; + return o; +} + +//назначить имя линии - необходимо проверить, что новое имя не совпадает с именем линии +//на которую делаем пересадку +void Line::setName(std::string name) +{ + for (auto s : m_stations) + if (!s->check(name)) + throw runtime_error("incorrect line name (name used as other line name)"); + m_name = name; +} + +//добавить станцию +void Line::addStation(std::string name, size_t position) +{ + if (find(name)) + throw runtime_error("station exists"); + if (position < 0 || position > m_stations.size()) + throw out_of_range("incorrect position of station"); + m_stations.insert(m_stations.begin() + position, new Station(name)); + //вставляем новый элемент на нужную позицию со сдвигом остальных +} + +//поиск линии +const Station* Line::find(std::string name) const +{ + for(auto s : m_stations) + if (s->name() == name) + return s; + return nullptr; +} + +//добавить пересадку +void Line::addTransfer(size_t position, std::string station, std::string line) +{ + if (line == m_name) + throw runtime_error("incorrect line name"); + if (position < 0 || position >= m_stations.size()) + throw out_of_range("incorrect station position"); + Station* s = m_stations[position]; + m_stations[position] = s->addTransfer(station, line); //перезаписываем новой станцией + delete s; +} + +//удалить станцию +void Line::deleteStation(std::string name) +{ + for (auto it = m_stations.begin(); it != m_stations.end(); ++it) + if ((*it)->name() == name) + { + delete *it; + m_stations.erase(it); + return; + } + throw runtime_error("station not found"); +} + +//поиск станции с пересадкой на заданную +const Station* Line::findTransfer(std::string name) const +{ + for(auto s : m_stations) + if (s->consistTransfer(name)) + return s; + return nullptr; +} + +//возвращение типа станции +std::string Line::getType(std::string station) const +{ + if (find(station)) + return find(station)->getType(); + else + throw runtime_error("station not found"); +} + +//удаление пересадки +void Line::deleteTransfer(size_t positionStation, size_t positionTransfer) +{ + if (positionStation >= m_stations.size()) + throw out_of_range("incorrect position"); + Station* s = m_stations[positionStation]; + m_stations[positionStation] = s->deleteTransfer(positionTransfer); + delete s; +} + +//изменить имя станции +void Line::changeStationName(size_t position, std::string name) +{ + if (position >= length()) + throw out_of_range("incorrect position"); + for(auto s : m_stations) + if (s->name() == name) + throw runtime_error("name exist"); + Station* s = m_stations[position]; + m_stations[position] = s->setName(name); + delete s; +} + +//сохранить в файл +void Line::save(ofstream& o) const +{ + o << m_name << endl; + o << m_stations.size() << endl; + for(auto s : m_stations) + s->save(o); +} + +//чтение из файла +void Line::read(ifstream& i) +{ + for(auto s : m_stations) + delete s; + m_stations.clear(); + m_name = getStr(i); + size_t count; + i >> count; + for (size_t j = 0; j < count; ++j) + { + string name = getStr(i); + addStation(name, j); + size_t transfers; + i >> transfers; + for (size_t k = 0; k < transfers; ++k) + { + string station = getStr(i); + string line = getStr(i); + addTransfer(j, station, line); + } + } +} + +string Library::getStr(ifstream& i) +{ + string s = ""; + getline(i, s); + if (s.length() == 0) + { + i.clear(); + getline(i, s); + } + return s; +} \ No newline at end of file diff --git a/Library/Line.h b/Library/Line.h new file mode 100644 index 0000000..d90fba1 --- /dev/null +++ b/Library/Line.h @@ -0,0 +1,82 @@ +#pragma once + +#include "Station.h" + +#include + +#include + +//пространтсво имён библиотеки +namespace Library +{ + class Line //класс линии, состоит из имени линии и deque - + //контейнер на базе массива с быстрой вставкой в конец и начало + //(поскольку станции строят либо в конце, либо в начале линии) + { + std::string m_name; //имя + std::deque m_stations; //дек станция + public: + class const_iterator; //вложенный класс итератора + friend const_iterator; //он дружествен + + Line(std::string name); //конструктор по имени + Line(const Line& L); //копирующий конструктор + Line(Line&& L); //перемещающий конструктор + ~Line(); //деструктор + + Line& operator= (Line&& L); //операторы = + Line& operator= (const Line& L); + friend std::ostream& operator<< (std::ostream&, const Line&); //вывод + + void setName(std::string name); //изменить имя линии (проверяет корректность всех пересадок) + std::string name() const { return m_name; } //получить имя линии + size_t length() const { return m_stations.size(); } //получить длину линии (количество станций) + void addStation(std::string name, size_t position); //добавить станцию (имя станции и позиция на линии) + const Station* find(std::string name) const; //поиск станции по имени + const Station* findTransfer(std::string name) const; //поиск пересадки по имени станции, на котрую происходит пересадка + void addTransfer(size_t position, std::string station, std::string line); //добавить пересадку + //со станции на position, на station на линии line + void deleteStation(std::string name); //удалить станцию по имени + std::string getType(std::string) const; //получить тип станции по её имени + void deleteTransfer(size_t station, size_t transfer);//удалить transfer пересадку со станции на заданной позиции + void changeStationName(size_t position, std::string name); //изменить имя на заданное + void save(std::ofstream& file) const; //сохранение в файл + void read(std::ifstream& file); //чтение из файла + + const_iterator begin() const { return const_iterator(*this, 0); } //получить итератор, указывающий на начало + const_iterator end() const { return const_iterator(*this, m_stations.size()); } //итератор, указывающий на конец + + //вложенный класс итератора + class const_iterator + { + private: + const Line& L; //ссылка на линию + size_t cur; //текущее положение + public: + const_iterator(const Line& L, size_t cur) : L(L), cur(cur) {} + const_iterator& operator++() //оператор ++ + { + ++cur; + return *this; + } + const_iterator operator++(int) + { + const_iterator it(*this); + ++cur; + return it; + } + bool operator!= (const const_iterator& I) const //неравенство + { + return cur != I.cur; + } + + const Station* operator*() //получение значения по итератору + { + return L.m_stations[cur]; + } + + }; + }; + + std::string getStr(std::ifstream& i); //получение строки из файла +} \ No newline at end of file diff --git a/Library/Station.cpp b/Library/Station.cpp new file mode 100644 index 0000000..3dba726 --- /dev/null +++ b/Library/Station.cpp @@ -0,0 +1,58 @@ +#include "Station.h" +#include "StationUT.h" +#include "StationNT.h" + +#include + +using namespace Library; +using namespace std; + +ostream& Library::operator<< (ostream& o, const Station& S) +{ + return S.print(o); +} + +ostream& Station::print(ostream& o) const +{ + o.width(20); + o << left << m_name << "Type is: Station" << endl; + return o; +} + +Station* Station::addTransfer(string station, string line) const +{ + if (m_name == station) + return new StationUT(m_name, 1, &line); + else + return new StationNT(m_name, 1, &line, &station); +} + +bool Station::consistTransfer(string name) const +{ + return false; +} + +string Station::getType() const +{ + return "Station"; +} + +Station* Station::deleteTransfer(size_t position) const +{ + throw runtime_error("no transfers."); +} + +Station* Station::setName(std::string name) const +{ + return new Station(name); +} + +void Station::save(ofstream& o) const +{ + o << m_name << endl << 0 << endl; +} + +bool Station::correct() const +{ + return true; +} \ No newline at end of file diff --git a/Library/Station.h b/Library/Station.h new file mode 100644 index 0000000..e8afcbd --- /dev/null +++ b/Library/Station.h @@ -0,0 +1,34 @@ +#pragma once + +#include +#include + +namespace Library +{ + //базовый класс обычной станции + class Station + { + protected: + std::string m_name; //имя станции + + virtual std::ostream& print(std::ostream&) const; //перегружаемая функция для вывода + public: + Station(std::string name) : m_name(name) {} //конструктор по имени + std::string name() const { return m_name; } //получение имени станции + virtual Station* clone() const { return new Station(*this); } //метод получения копии объекта + + friend std::ostream& operator<< (std::ostream&, const Station&); //оператор вывода + + virtual bool check(std::string name) const { return true; } //проверяет отсутствие пересадок на линию с именем name + + //добавить пересадку, возвращает указатель на новую станцию другого типа, которой нужно заменить старую + virtual Station* addTransfer(std::string station, std::string line) const; + virtual bool consistTransfer(std::string name) const; //проверяет наличии пересадки на станцию с заданным именем + virtual std::string getType() const; //возвращает строку типа станции + virtual Station* deleteTransfer(size_t position) const; //удаляет пересадку (генерирует исключение для простой станции) + virtual Station* setName(std::string name) const; //изменить имя станции - возвращает указатель на новую станцию + //(т.к. может измениться тип станции) + virtual void save(std::ofstream& o) const; //сохранение в файл + virtual bool correct() const; //функция проверки корректности количества пересадок (для простой станции всегда вернёт true) + }; +} \ No newline at end of file diff --git a/Library/StationNT.cpp b/Library/StationNT.cpp new file mode 100644 index 0000000..3a8d330 --- /dev/null +++ b/Library/StationNT.cpp @@ -0,0 +1,108 @@ +#include "StationNT.h" + +#include + +using namespace Library; +using namespace std; + +StationNT::StationNT(std::string name, size_t count, const std::string* lines, const std::string* stations) + : StationUT(name, count, lines) +{ + for (size_t i = 0; i < count; ++i) + m_stations[i] = stations[i]; +} + +std::ostream& StationNT::print(std::ostream& o) const +{ + o.width(20); + o << left << m_name << "Type is: StationNT" << endl; + o << " " << m_count << " transfers: " << endl; + for (size_t i = 0; i < m_count; ++i) + o << " Line: " << m_lines[i] << ", station: " << m_stations[i] << "." << endl; + return o; +} + +//добавление пересадки +Station* StationNT::addTransfer(std::string station, std::string line) const +{ + if (m_count == 3) + throw overflow_error("too much transfers"); + string lines[MAX_COUNT]; + string stations[MAX_COUNT]; + for (size_t i = 0; i < m_count; ++i) + { + lines[i] = m_lines[i]; + stations[i] = m_stations[i]; + } + lines[m_count] = line; + stations[m_count] = station; + return new StationNT(m_name, m_count + 1, m_lines, m_stations); +} + +bool StationNT::consistTransfer(std::string name) const +{ + for (size_t i = 0; i < m_count; ++i) + if (m_stations[i] == name) + return true; + return false; +} + +std::string StationNT::getType() const +{ + return "StationNT"; +} + +//удаление пересадки, возможны возвраты разных типов обеъектов +Station* StationNT::deleteTransfer(size_t position) const +{ + if (position >= m_count) + throw out_of_range("incorrect transfer"); + if (m_count == 1) //если это была последняя пересадка + { + return new Station(m_name); //то возвращаем обычную станцию + } + else + { + string stations[MAX_COUNT]; + string lines[MAX_COUNT]; + //копируем начало спсика пересадок + for (size_t i = 0; i < position; ++i) + { + stations[i] = m_stations[i]; + lines[i] = m_lines[i]; + } + //копируем со сдвигом часть после удалённой станции + for (size_t i = position; i < m_count - 1; ++i) + { + stations[i] = m_stations[i + 1]; + lines[i] = m_lines[i + 1]; + } + //теперь надо проверить, осталась ли станция пересадочным узлом + //(когда есть пересадки на станции с другими именами), или же теперь + //это просто станция с пересадками на одноимённые станции + for (size_t i = 0; i < m_count - 1; ++i) + if (stations[i] != m_name) //если есть хотя бы одна станция с отличным именем - то это пересадочный узел + return new StationNT(m_name, m_count - 1, lines, stations); + //если все пересадки на одноимённые, то вернули станцию с пересадками на одноимённые + return new StationUT(m_name, m_count - 1, lines); + } +} + +Station* StationNT::setName(string name) const +{ + //если есть хотя бы одна станция с отличным именем пересадки, + //то объект останется пересадочным узлом + for (size_t i = 0; i < m_count; ++i) + if (m_stations[i] != name) + return new StationNT(name, m_count, m_lines, m_stations); + //иначе вернём станцию с одноимёнными пересадками, т.к. все имена теперь совпадают с новым + //именем станции + return new StationUT(name, m_count, m_lines); +} + +void StationNT::save(ofstream& o) const +{ + o << m_name << endl << m_count << endl; + for (size_t i = 0; i < m_count; ++i) + o << m_stations[i] << endl << m_lines[i] << endl; +} \ No newline at end of file diff --git a/Library/StationNT.h b/Library/StationNT.h new file mode 100644 index 0000000..ef189f2 --- /dev/null +++ b/Library/StationNT.h @@ -0,0 +1,27 @@ +#pragma once + +#include "StationUT.h" + + +namespace Library +{ + //класс станций с пересадкой на станции с другим названием + class StationNT : public StationUT + { + std::string m_stations[3]; //массив названий станций пересадок (массив линий наследуется от родителя) + + virtual std::ostream& print(std::ostream&) const; //перегружаемая функция для вывода + public: + StationNT(std::string name, size_t count, const std::string* lines, const std::string* stations); //конструктор с аргументами + virtual Station* clone() const { return new StationNT(*this); } //копирование + + //добавить пересадку, возвращает указатель на новую станцию другого типа, которой нужно заменить старую + virtual Station* addTransfer(std::string station, std::string line) const; + virtual bool consistTransfer(std::string name) const; //проверяет наличии пересадки на станцию с заданным именем + virtual std::string getType() const; //возвращает строку типа станции + virtual Station* deleteTransfer(size_t position) const; //удаляет пересадку (возвращает указатель на новый объект) + virtual Station* setName(std::string name) const; //изменить имя станции - возвращает указатель на новую станцию + //(т.к. может измениться тип станции) + virtual void save(std::ofstream& o) const; //сохранение в файл + }; +} \ No newline at end of file diff --git a/Library/StationUT.cpp b/Library/StationUT.cpp new file mode 100644 index 0000000..998336c --- /dev/null +++ b/Library/StationUT.cpp @@ -0,0 +1,112 @@ +#include "StationUT.h" +#include "StationNT.h" + +#include + +using namespace Library; +using namespace std; + +StationUT::StationUT(string name, size_t count, const string* lines) + : Station(name) +{ + if (count > 3) + throw overflow_error("too much transfers"); + m_count = count; + for (size_t i = 0; i < count; i++) + m_lines[i] = lines[i]; +} + +std::ostream& StationUT::print(std::ostream& o) const +{ + o.width(20); + o << left << m_name << "Type is: StationUT" << endl; + o << " " << m_count << " transfers: " << endl; + for (size_t i = 0; i < m_count; i++) + o << " Line: " << m_lines[i] << ", station: " << m_name << "." << endl; + return o; +} + +//проверяем наличие пересадок на линию с заданным именем +bool StationUT::check(string name) const +{ + for (size_t i = 0; i < m_count; i++) + if (m_lines[i] == name) + return false; + return true; +} + +//добавить пересадку, вернёт указатель на объект, в котором будет добалена пересадка +Station* StationUT::addTransfer(std::string station, std::string line) const +{ + //при попытке добавить 4 пересадку - ошибка + if (m_count == 3) + throw overflow_error("too much transfers"); + //если добавление на одноименную станцию, то возвращем объект этого же класса, + //но с большим числом пересадок + //копируем массив линий, его передадим в конструктор + string lines[MAX_COUNT]; + for (size_t i = 0; i < m_count; ++i) + lines[i] = m_lines[i]; + lines[m_count] = line; + if (m_name == station) + { + return new StationUT(m_name, m_count + 1, lines); + } + else //если же имя другое, то формируем пересадочный узел + { + string stations[MAX_COUNT]; + for (size_t i = 0; i < m_count; ++i) + stations[i] = m_name; + stations[m_count] = station; + StationNT* s = new StationNT(m_name, m_count + 1, m_lines, stations); + return s; + } +} + +string StationUT::getType() const +{ + return "StationUT"; +} + +//удалить пересадку +Station* StationUT::deleteTransfer(size_t position) const +{ + if (position >= m_count) + throw out_of_range("incorrect transfer position"); + if (m_count == 1) //если это последняя пересадка, то вернём обыкновенную станцию + { + return new Station(m_name); + } + else //иначе - сдвигаем все линии и возвращаем станцию с пересадками + { + string lines[MAX_COUNT]; //формируем массив названий линий + for (size_t i = 0; i < position; ++i) + lines[i] = m_lines[i]; + for (size_t i = position; i < m_count - 1; ++i) + lines[i] = m_lines[i + 1]; + return new StationUT(m_name, m_count - 1, lines); + } +} + +//изменить имя - в результате вернём пересадочный узел, т.к. имя станций, на которые осуществляем +//пересадки остались старые, а имя этой станции изменилось +Station* StationUT::setName(std::string name) const +{ + string stations[MAX_COUNT]; + for (size_t i = 0; i < m_count; i++) + stations[i] = m_name; + return new StationNT(name, m_count, m_lines, stations); +} + +//сохранение в файл +void StationUT::save(ofstream& o) const +{ + o << m_name << endl << m_count << endl; + for (size_t i = 0; i < m_count; i++) + o << m_name << endl << m_lines[i] << endl; +} + +bool StationUT::correct() const +{ + return m_count >= 1 && m_count <= 3; +} \ No newline at end of file diff --git a/Library/StationUT.h b/Library/StationUT.h new file mode 100644 index 0000000..dad27a6 --- /dev/null +++ b/Library/StationUT.h @@ -0,0 +1,32 @@ +#pragma once + +#include "Station.h" + +namespace Library +{ + //класс станций с пересадкой на одноимённую + class StationUT : public Station + { + protected: + static const size_t MAX_COUNT = 3; //максимальное число пересадок + size_t m_count; //число пересадок + std::string m_lines[MAX_COUNT]; //массив из трёх названий линии + + virtual std::ostream& print(std::ostream&) const; //перегружаемая функция для вывода + public: + //StationUT() :Station("") , count (0) {} //пустой конструктор + StationUT(std::string name, size_t count, const std::string* lines); //конструктор по имени и массиву линий + virtual Station* clone() const { return new StationUT(*this); } //функция клонирования + + virtual bool check(std::string name) const; //проверка отсутствия пересадок на линии с таким именем + + //добавить пересадку, возвращает указатель на новую станцию другого типа, которой нужно заменить старую + virtual Station* addTransfer(std::string station, std::string line) const; + virtual std::string getType() const; //возвращает строку типа станции + virtual Station* deleteTransfer(size_t position) const; //удаляет пересадку (генерирует исключение для простой станции) + virtual Station* setName(std::string name) const; //изменить имя станции - возвращает указатель на новую станцию + //(т.к. может измениться тип станции) + virtual void save(std::ofstream& o) const; //сохранение в файл + virtual bool correct() const; //проверяет корректность количества пересадок + }; +} \ No newline at end of file diff --git a/Testing/Testing.cpp b/Testing/Testing.cpp new file mode 100644 index 0000000..a41b482 --- /dev/null +++ b/Testing/Testing.cpp @@ -0,0 +1,202 @@ +#include "stdafx.h" +#include "gtest\gtest.h" +#include "Line.h" +#include "Station.h" +#include "StationUT.h" +#include "StationNT.h" + +using namespace std; +using namespace Library; + +#undef deque + +TEST(StationTesting, Constructor) +{ + Station S2("station"); + ASSERT_STREQ("station", S2.name().c_str()); + Station* S3 = S2.clone(); + ASSERT_EQ("station", S3->name()); + ASSERT_EQ("Station", S3->getType()); + delete S3; +} + +TEST(StationTesting, Print) +{ + Station S("name"); + ostringstream o; + o << S; + ASSERT_STREQ("name Type is: Station", o.str().c_str()); +} + +TEST(StationTesting, Check) +{ + Station S("station"); + ASSERT_TRUE(S.check("name")); +} + +TEST(StationTesting, AddTransfer) +{ + Station S = Station("station"); + Station* S2 = S.addTransfer("station 2", "line"); + ASSERT_EQ(typeid(*S2), typeid(StationNT)); + delete S2; + S2 = S.addTransfer("station", "line"); + ASSERT_EQ(typeid(*S2), typeid(StationUT)); + delete S2; +} + +TEST(Testing, CheckAddTransfer) +{ + Station S = Station("S"); + Station* S2 = S.addTransfer("S2", "L1"); + ASSERT_EQ(typeid(*S2), typeid(StationNT)); + S = Station("S"); + S2 = S.addTransfer("S", "L2"); + ASSERT_EQ(typeid(*S2), typeid(StationUT)); + S2 = S2->addTransfer("S2", "L3"); + ASSERT_EQ(typeid(*S2), typeid(StationNT)); +} + +TEST(Testing, ChechDeleteTransfer) +{ + Station S = Station("S"); + Station* S1 = S.addTransfer("S", "L"); + Station* S2 = S1->deleteTransfer(0); + ASSERT_EQ(typeid(*S2), typeid(Station)); + S = Station("S"); + S1 = S.addTransfer("S", "L"); + S1 = S1->addTransfer("S2", "L"); + ASSERT_EQ(typeid(*S1), typeid(StationNT)); + S1 = S1->deleteTransfer(1); + ASSERT_EQ(typeid(*S1), typeid(StationUT)); + S1 = S1->deleteTransfer(0); + ASSERT_EQ(typeid(*S1), typeid(Station)); +} + +TEST(Testing, ChangeName) +{ + Station* S = new Station("S"); + S = S->addTransfer("S2", "L"); + ASSERT_EQ(typeid(*S), typeid(StationNT)); + S = S->setName("S2"); + ASSERT_EQ(typeid(*S), typeid(StationUT)); +} + +TEST(LineTesting, Constructor) +{ + Line L("line"); + ASSERT_STREQ("line", L.name().c_str()); +} + +TEST(DequeTesting, CheckConstructor) //тест конструкторов +{ + Deque D = Deque (); + ASSERT_EQ(D.size(), 0); +} + +TEST(DequeTesting, CheckGet) +{ + deque d = deque (); + Deque D = Deque (); + for (int i = 0; i < 20; i++) + { + d.push_back(i); + D.push_back(i); + ASSERT_EQ(d.size(), D.size()); + } +} + +TEST(DequeTesting, CheckIndex) +{ + Deque D = Deque (); + for (int i = 0; i < 20; i++) + { + D.push_back(i); + ASSERT_EQ(D[i], i); + } + for (int i = 0; i < 20; i++) + D[i] = i * 2; + for (int i = 0; i < 20; i++) + { + ASSERT_EQ(D[i], i * 2); + } + ASSERT_ANY_THROW(D[-1]); + ASSERT_ANY_THROW(D[D.size()]); +} + +TEST(DequeTesting, CheckIterator) +{ + deque d = deque (); + Deque D = Deque (); + for (int i = 0; i < 20; i++) + { + d.push_back(i); + D.push_back(i); + } + + int i = 0; + for (Deque::iterator it = D.begin(); it != D.end(); it++, i++) + ASSERT_EQ(*it, i); +} + +TEST(DequeTesting, CheckInsertErase) +{ + Deque D = Deque (); + ASSERT_EQ(D.size(), 0); + for (int i = 0; i < 20; i++) + D.push_back(i); + D.clear(); + ASSERT_EQ(D.size(), 0); + for (int i = 0; i < 20; i++) + D.push_back(i); + Deque::iterator it = D.end() + -1; + for (int i = 19; i >= 0; i--) + { + it = D.erase(it); + it = it + -1; + ASSERT_EQ(D.size(), i); + if (i) + { + ASSERT_EQ(*it, i - 1); + } + } + for (int i = 0; i < 20; i++) + D.push_back(i); + it = D.begin(); + for (int i = 0; i < 20; i++) + { + it = D.erase(it); + ASSERT_EQ(D.size(), 19 - i); + if (i != 19) + { + ASSERT_EQ(*it, i + 1); + } + } + D.clear(); + for (int i = 0; i < 20; i++) + { + D.push_front(i); + ASSERT_EQ(D.size(), i + 1); + ASSERT_EQ(*(D.begin()), i); + ASSERT_EQ(*(D.end() + -1), 0); + } + for (unsigned int i = 0; i < 20; i++) + { + it = D.insert(D.begin() + 2 * i, 20 + i); + ASSERT_EQ(D.size(), 21 + i); + ASSERT_EQ(*it, 20 + i); + } + for (unsigned int i = 0; i < 20; i++) + { + ASSERT_EQ(D[2 * i], 20 + i); + ASSERT_EQ(D[2 * i + 1], 19 - i); + } +} + + +int _tmain(int argc, _TCHAR* argv[]) +{ + ::testing::InitGoogleTest(&argc, argv); + + return RUN_ALL_TESTS(); +} \ No newline at end of file