Добавил:
oih07968
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:lab1 / student
.cpp//-- В задании необходимо разработать программу, в которой выполняется ввод списка записей определенного типа.
//-- Записи вводятся построчно в определенном формате, признак завершения ввода – ввод пустой строки.
//-- Список – двунаправленный. При написании программы реализовать функции:
//--добавление элемента в конец списка,
//вставка элемента перед текущим элементом списка,
//--удаление элемента из списка.
//-- При вводе данных записи упорядочиваются по определенному полю (согласно варианту задания).
//-- Направление упорядочивания на выбор разработчика.
//-- Полученный список вывести на экран.
// Фамилия, имя, отчество (строки по 15 символов);
// номер зачетной книжки (целое шестизначное число);
// дата рождения (в формате дд.мм.гггг).
// Формат ввода: Фамилия Имя Отчество [No зачетной книжки], Дата рождения
/*
Сидоров Сидр Сидрович [131955], 14.07.1993
Иванов Иван Иванович [453465], 01.02.1996
Петров Петр Петрович [156556], 22.12.1998
Лапин Гавриил Васильевич [793907], 24.01.1980
Соболев Геннадий Леонидович [531426], 11.02.1983
Фомичев Владислав Николаевич [567018], 15.02.1983
Горшков Даниил Тимурович [686569], 18.04.1985
Доронин Богдан Семенович [151241], 17.07.1989
Анисимов Леонид Николаевич [105593], 11.11.1992
Лихачев Юрий Витальевич [420839], 09.10.1997
Вставка Перед Элементом [777777], 07.07.1997
*/
#include <iostream>
#include <sstream>
#include <string>
#include <regex>
#include <iomanip>
#include <Windows.h>
using namespace std;
#if defined(max)
#undef max
#endif
struct Student
{
string lastname;
string firstname;
string middlename;
int number = 0;
string date;
Student* next = nullptr;
Student* prev = nullptr;
};
template <typename T>
bool get_value(stringstream& ss, T& value);
Student* push(string lastname, string firstname, string middlename, int number, string date, Student* last);
Student* insert(string lastname, string firstname, string middlename, int number, string date, Student* stk);
Student* pop(Student* stk);
void output(Student* stk);
string useless_symbol(string str);
Student* student_sort(Student* first);
int main()
{
SetConsoleCP(1251);
SetConsoleOutputCP(1251);
Student* first = nullptr;
Student* last = nullptr;
string str;
regex rg_format("[А-Я]{1}[а-я]{1,14} [А-Я]{1}[а-я]{1,14} [А-Я]{1}[а-я]{1,14} \\[[1-9]{1}[0-9]{5}\\], "
"(0[1-9]|[12][0-9]|3[01]).(0[1-9]|1[012]).(19|20)[0-9]{2}");//регулярное выражение для проверки ввода
cout << "Вводите данные студентов в формате 'Фамилия Имя Отчество [№ зачетной книжки], Дата рождения':" << endl;
cout << "По завершении ввода введите пустую строку." << endl;
while (1)
{
getline(cin, str);//читаем строку из потока ввода
if (str.empty()) break;//если строка пустая завершаем ввод
if (!regex_match(str, rg_format))
{
cout << "Введенная строка не соответствует формату!" << endl;
continue;
}
str = useless_symbol(str);//очищает строку от всех символов кроме букв, цифр и пробелов
stringstream ss(str);//записываем строку в поток
string lastname;
string firstname;
string middlename;
int number;
string date;
if (get_value(ss, lastname) &&
get_value(ss, firstname) &&
get_value(ss, middlename) &&
get_value(ss, number) &&
get_value(ss, date))//если данные прочитаны успешно
{
last = push(lastname, firstname, middlename, number, date, last);
if (first == nullptr) first = last;//если указатель на первый элемент не задан - задаем
}
}
str.clear();
cout << "Введите дату (студенты, родившиеся позже указанной даты, будут удалены):" << endl;
tm t = {};
cin >> get_time(&t, "%d.%m.%Y");
while (cin.fail())
{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Некорректный ввод! Попробуйте снова: ";
cin >> get_time(&t, "%d.%m.%Y");
}
cin.ignore(numeric_limits<streamsize>::max(), '\n');
Student* stk = first;
while (stk != nullptr)//удаляем из списка студентов с датой позже указаной
{
tm d = {};
istringstream ss(stk->date);
ss >> get_time(&d, "%d.%m.%Y");
if (!ss.fail() && mktime(&d) > mktime(&t))
{
if (first == stk) first = first->next;
if (last == stk) last = last->prev;
stk = pop(stk);
}
else stk = stk->next;
}
first = student_sort(first);//сортируем список
output(first);//выводим результат
system("pause");
return 0;
}
template <typename T>
bool get_value(stringstream& ss, T& value)
{//ввод значений
ss >> value;
if (ss.fail())
{
ss.clear();
ss.ignore(1, '\n');
cout << "Некорректный ввод! Попробуйте снова: ";
return false;
}
return true;
}
Student* push(string lastname, string firstname, string middlename, int number, string date, Student* last)
{//добавление элемента в конец списка
Student* item = new Student;
item->lastname = lastname;
item->firstname = firstname;
item->middlename = middlename;
item->number = number;
item->date = date;
item->next = nullptr;
item->prev = last;
if (last != nullptr) last->next = item;
return item;
}
Student* insert(string lastname, string firstname, string middlename, int number, string date, Student* stk)
{//вставка элмента в указанное место
Student* item = new Student;
item->lastname = lastname;
item->firstname = firstname;
item->middlename = middlename;
item->number = number;
item->date = date;
item->next = stk;
item->prev = stk->prev;
if (stk->prev != nullptr) (stk->prev)->next = item;
stk->prev = item;
return item;
}
Student* pop(Student* stk)
{//удаление элемента
if (stk == nullptr) return nullptr;
Student* next = stk->next;
Student* prev = stk->prev;
if (next != nullptr) next->prev = prev;
if (prev != nullptr) prev->next = next;
delete stk;//удалили элемент
return next;
}
void output(Student* stk)
{//вывод списка
if (stk == nullptr) cout << "Список пуст!";
while (stk != nullptr)
{
cout << stk->lastname << " " << stk->firstname << " " << stk->middlename << " " << stk->number << " " << stk->date << endl;
stk = stk->next;
}
cout << endl;
}
string useless_symbol(string str)
{//удаление всех символов из строки кроме 'А-я', '0-9', ' ', '.'
int i = 0;
while (str[i])
{
if ((str[i] < 'А' || str[i] > 'Я') &&
(str[i] < 'а' || str[i] > 'я') &&
(str[i] < '0' || str[i] > '9') &&
str[i] != ' ' && str[i] != '.')
str.erase(i, 1);
else i++;
}
return str;
}
Student* student_sort(Student* first)
{//сортировка списка
if (first == nullptr || first->next == nullptr) return first;
Student* i = first;
while (i != nullptr)
{
string min_str = i->lastname + i->firstname + i->middlename;
Student* min_value = i;
Student* j = i->next;
while (j != nullptr)
{
string cur_str = j->lastname + j->firstname + j->middlename;
if (cur_str < min_str)
{
min_str = cur_str;
min_value = j;
}
j = j->next;
}
if (min_value != i)
{
Student* flip_next = i->next;
Student* flip_prev = i->prev;
if (i->next == min_value)
{//если у текущего элемента следующий тот, с кем обмен (соседи)
flip_next = i;
min_value->prev = min_value;
}
i->next = min_value->next;
i->prev = min_value->prev;
if (i->next != nullptr) (i->next)->prev = i;
if (i->prev != nullptr) (i->prev)->next = i;
//если предыдущий элемент существует, то устанавливаем значение указателя next у предыдущего элемента на текущий
min_value->next = flip_next;
min_value->prev = flip_prev;
if (min_value->next != nullptr) (min_value->next)->prev = min_value;
if (min_value->prev != nullptr) (min_value->prev)->next = min_value;
if (min_value->prev == nullptr) first = min_value;
}
i = min_value->next;
}
return first;
}