204 lines
4.7 KiB
C++
204 lines
4.7 KiB
C++
/*
|
||
* lesson_1.cpp
|
||
*
|
||
* Created on: 16 окт. 2021 г.
|
||
* Author: alexander
|
||
*/
|
||
|
||
#include "lesson_1.hpp"
|
||
|
||
#include <sstream>
|
||
#include <algorithm>
|
||
#include <iomanip>
|
||
|
||
/****************************
|
||
* Person *
|
||
****************************/
|
||
|
||
std::optional<std::string> getOptStr(std::string &s)
|
||
{
|
||
if (s == "")
|
||
{
|
||
return std::nullopt;
|
||
}
|
||
|
||
return s;
|
||
}
|
||
|
||
std::ostream& operator<<(std::ostream &out, const Person &p)
|
||
{
|
||
out << std::setw(15) << p.firstname << std::setw(12) << p.lastname;
|
||
|
||
if (p.patronymic.has_value())
|
||
{
|
||
out << std::setw(17) << p.patronymic.value();
|
||
}
|
||
else
|
||
{
|
||
out << std::setw(18);
|
||
}
|
||
|
||
return out;
|
||
}
|
||
|
||
bool operator<(const Person &p1, const Person &p2)
|
||
{
|
||
return tie(p1.firstname, p1.lastname, p1.patronymic) < tie(p2.firstname, p2.lastname, p2.patronymic);
|
||
}
|
||
|
||
bool operator==(const Person &p1, const Person &p2)
|
||
{
|
||
return tie(p1.firstname, p1.lastname, p1.patronymic) == tie(p2.firstname, p2.lastname, p2.patronymic);
|
||
}
|
||
|
||
/*********************************
|
||
* PhoneNumber *
|
||
*********************************/
|
||
|
||
bool operator<(const PhoneNumber &p1, const PhoneNumber &p2)
|
||
{
|
||
return tie(p1.country_code, p1.city_code, p1.number, p1.additional_number) < tie(p2.country_code, p2.city_code, p2.number, p2.additional_number);
|
||
}
|
||
|
||
std::optional<int> getOptInt(std::string &s)
|
||
{
|
||
if (s == "")
|
||
{
|
||
return std::nullopt;
|
||
}
|
||
|
||
return std::stoi(s);
|
||
}
|
||
|
||
std::ostream& operator<<(std::ostream &out, const PhoneNumber &p)
|
||
{
|
||
out << std::setw(3) << '+' << p.country_code << '(' << p.city_code << ')' << p.number;
|
||
|
||
if (p.additional_number.has_value())
|
||
{
|
||
out << ' ' << p.additional_number.value();
|
||
}
|
||
|
||
return out;
|
||
}
|
||
|
||
/*******************************
|
||
* PhoneBook *
|
||
*******************************/
|
||
|
||
PhoneBook::PhoneBook(std::istream &file)
|
||
{
|
||
if (!file)
|
||
{
|
||
std::cout << "Не удаётся открыть файл!" << std::endl;
|
||
exit(1);
|
||
}
|
||
|
||
for (std::string line; std::getline(file, line);)
|
||
{
|
||
std::stringstream str(line);
|
||
std::vector<std::string> rowData;
|
||
|
||
for (std::string s; getline(str, s, ';');)
|
||
{
|
||
rowData.push_back(s);
|
||
}
|
||
|
||
std::pair<Person, PhoneNumber> entry;
|
||
|
||
for (size_t i = 0; i < rowData.size(); ++i)
|
||
{
|
||
switch (i)
|
||
{
|
||
case 0:
|
||
entry.first.firstname = rowData[i];
|
||
break;
|
||
case 1:
|
||
entry.first.lastname = rowData[i];
|
||
break;
|
||
case 2:
|
||
entry.first.patronymic = getOptStr(rowData[i]);
|
||
break;
|
||
case 3:
|
||
entry.second.country_code = stoi(rowData[i]);
|
||
break;
|
||
case 4:
|
||
entry.second.city_code = stoi(rowData[i]);
|
||
break;
|
||
case 5:
|
||
entry.second.number = rowData[i];
|
||
break;
|
||
case 6:
|
||
entry.second.additional_number = getOptInt(rowData[i]);
|
||
break;
|
||
}
|
||
}
|
||
|
||
m_data.push_back(entry);
|
||
}
|
||
}
|
||
|
||
std::ostream& operator<<(std::ostream &out, const PhoneBook &pb)
|
||
{
|
||
for (const auto& [first, second] : pb.m_data)
|
||
{
|
||
out << first << ' ' << second << std::endl;
|
||
}
|
||
|
||
return out;
|
||
}
|
||
|
||
void PhoneBook::SortByName()
|
||
{
|
||
sort(m_data.begin(), m_data.end(), [](const std::pair<Person, PhoneNumber> &lhs, const std::pair<Person, PhoneNumber> &rhs)
|
||
{
|
||
return lhs.first < rhs.first;
|
||
});
|
||
}
|
||
|
||
void PhoneBook::SortByPhone()
|
||
{
|
||
sort(m_data.begin(), m_data.end(), [](const std::pair<Person, PhoneNumber> &lhs, const std::pair<Person, PhoneNumber> &rhs)
|
||
{
|
||
return lhs.second < rhs.second;
|
||
});
|
||
}
|
||
|
||
std::pair<std::string, std::vector<PhoneNumber>> PhoneBook::GetPhoneNumber(const std::string &firstname)
|
||
{
|
||
std::vector<PhoneNumber> phoneNumbers;
|
||
int count = 0;
|
||
|
||
for_each(m_data.begin(), m_data.end(), [&](const auto &entry)
|
||
{
|
||
if (entry.first.firstname == firstname)
|
||
{
|
||
phoneNumbers.push_back(entry.second);
|
||
++count;
|
||
}
|
||
});
|
||
|
||
switch (count)
|
||
{
|
||
case 0:
|
||
return { "not found", phoneNumbers };
|
||
case 1:
|
||
return { "", phoneNumbers };
|
||
default:
|
||
return { "found more than 1", phoneNumbers };
|
||
}
|
||
}
|
||
|
||
void PhoneBook::ChangePhoneNumber(const Person &p, const PhoneNumber &pn)
|
||
{
|
||
auto entry = find_if(m_data.begin(), m_data.end(), [&](const auto &entry)
|
||
{
|
||
return entry.first == p;
|
||
});
|
||
|
||
if (entry != m_data.end())
|
||
{
|
||
entry->second = pn;
|
||
}
|
||
}
|