Добавил:
farel
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:В2_7
.cpp#include <iostream>
#include <Windows.h>
#include <conio.h>
using namespace std;
#define KEY_DOWN 80
#define KEY_UP 72
#define KEY_LEFT 75
#define KEY_RIGHT 77
#define KEY_BACKSPACE 8
#define KEY_ENTER 13
#define MAX_ITEMS_MENU 4 // Максимальное количество пунктов меню
#define MAX_LENGTH_ITEM 48 // Максимальная длина названия пункта меню
#define MAX_ITEMS_SUBMENU 8 // Максимальное количество пунктов подменю
template <class T> class list {
struct item {
item() : data(NULL), next(NULL), prev(NULL) {}
item * next; // Указатель на следующий элемент
item * prev; // Указатель на предыдующий элемент
T data; // Значение элемента
};
item * head; // Начало списка (голова)
item * tail; // Конец списка (хвост)
public:
list(); // Конструктор
~list(); // Деструктор
void push_front(); // Добавление элемента в начало списка
void push_back(); // Добавление элемента в конец списка
void init(T value); // Инициализация списка при добавлении первого элемента
void amount_of_different_elems(); // Вывод различных элементов списка
bool erase(item * _ptr);
bool pop_front();
bool pop_back();
int pop_select();
void print(); // Вывод всего списка
};
const char items_menu[MAX_ITEMS_MENU][MAX_LENGTH_ITEM] = {
"Целочисленный список",
"Вещественный список",
"Символьный список",
"Выход"
};
const char items_submenu[MAX_ITEMS_SUBMENU][MAX_LENGTH_ITEM] = { // Названия пунктов меню
"Добавить элемент в начало",
"Добавить элемент в конец",
"Удалить элемент из начала",
"Удалить элемент с конца",
"Выбрать элемент для удаления",
"Вывести список",
"Вывести количество различных элементов",
"Назад"
};
HANDLE hStdOut; // Дескриптор потока вывода
list <int> lInt;
list <char> lChar;
list <float> lFloat;
void menu();
void show_menu(short);
void show_submenu(short);
template <class T>
void submenu(list <T> * ptr);
int main() {
setlocale(0, "");
hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); // Получаем ID обработчика потока вывода
// Скрываем курсор
CONSOLE_CURSOR_INFO cInfo = { 1, false };
SetConsoleCursorInfo(hStdOut, &cInfo);
//------------------------------
menu();
return 0;
}
void menu() {
unsigned short select_id = 0;
show_menu(select_id);
char press_key = 0;
while (1) {
press_key = _getch();
if (press_key == -32) press_key = _getch();
switch (press_key)
{
case KEY_UP: {
select_id = (select_id ? --select_id : MAX_ITEMS_MENU - 1);
show_menu(select_id);
break;
}
case KEY_DOWN: {
select_id = (select_id < MAX_ITEMS_MENU - 1 ? ++select_id : 0);
show_menu(select_id);
break;
}
case KEY_ENTER: {
switch (select_id) {
case 0:
submenu(&lInt);
show_menu(select_id);
break;
case 1:
submenu(&lFloat);
show_menu(select_id);
break;
case 2:
submenu(&lChar);
show_menu(select_id);
break;
case 3:
return;
}
}
}
}
}
template <class T>
void submenu(list <T> * ptr) {
unsigned short select_id = 0;
show_submenu(select_id);
char press_key = 0;
while (1) {
press_key = _getch();
if (press_key == -32) press_key = _getch();
switch (press_key)
{
case KEY_UP: {
select_id = (select_id ? --select_id : MAX_ITEMS_SUBMENU - 1);
show_submenu(select_id);
break;
}
case KEY_DOWN: {
select_id = (select_id < MAX_ITEMS_SUBMENU - 1 ? ++select_id : 0);
show_submenu(select_id);
break;
}
case KEY_ENTER: {
switch (select_id) {
case 0: {
system("cls");
ptr->push_front();
system("pause");
show_submenu(select_id);
break;
}
case 1: {
system("cls");
ptr->push_back();
system("pause");
show_submenu(select_id);
break;
}
case 2: {
system("cls");
if (ptr->pop_front())
cout << "Удален элемент с начала списка!" << endl;
system("pause");
show_submenu(select_id);
break;
}
case 3: {
system("cls");
if (ptr->pop_back())
cout << "Удален элемент с конца списка!" << endl;
system("pause");
show_submenu(select_id);
break;
}
case 4: {
system("cls");
int return_value = ptr->pop_select();
if (return_value == 1) {
system("cls");
cout << "Выбранный элемент был успешно удален!" << endl;
}
else if (return_value == -1) {
show_submenu(select_id);
break;
}
system("pause");
show_submenu(select_id);
break;
}
case 5: {
system("cls");
ptr->print();
system("pause");
show_submenu(select_id);
break;
}
case 6: {
system("cls");
ptr->amount_of_different_elems();
system("pause");
show_submenu(select_id);
break;
}
case 7:
return;
}
break;
}
}
}
}
void show_menu(short _select_id) {
system("cls");
cout << "\tДвусвязный список" << endl;
cout << endl;
for (int i = 0; i < MAX_ITEMS_MENU; i++) {
if (i == _select_id) {
SetConsoleTextAttribute(hStdOut, (WORD)((15 << 4) | 0)); // Изменение цвета текста и фона за текстом который будет выведен далее
cout << ' ' << items_menu[i];
for (int j = 0; j < MAX_LENGTH_ITEM - strlen(items_menu[i]); j++) cout << ' ';
cout << endl;
SetConsoleTextAttribute(hStdOut, (WORD)((0 << 4) | 15));
}
else cout << ' ' << items_menu[i] << endl;
}
}
void show_submenu(short _select_id) {
system("cls");
cout << "\tДвусвязный список" << endl;
cout << endl;
for (int i = 0; i < MAX_ITEMS_SUBMENU; i++) {
if (i == _select_id) {
SetConsoleTextAttribute(hStdOut, (WORD)((15 << 4) | 0)); // Изменение цвета текста и фона за текстом который будет выведен далее
cout << ' ' << items_submenu[i];
for (int j = 0; j < MAX_LENGTH_ITEM - strlen(items_submenu[i]); j++) cout << ' ';
cout << endl;
SetConsoleTextAttribute(hStdOut, (WORD)((0 << 4) | 15));
}
else cout << ' ' << items_submenu[i] << endl;
}
}
template <class T>
list<T>::list() : head(NULL), tail(NULL) {}
template <class T>
list<T>::~list() {
if (head == tail) delete head;
else {
delete head;
delete tail;
}
}
template <class T>
void list<T>::push_front() {
T value;
cout << "Добавление нового элемента в начало списка\nВведите значение элемента: ";
cin >> value;
while (getchar() != '\n');
if (head == NULL)
{
init(value);
return;
}
item * elem;
elem = new item;
elem->data = value;
elem->prev = NULL;
elem->next = head;
head->prev = elem;
head = elem;
cout << "Элемент успешно добавлен!" << endl;
}
template <class T>
void list<T>::push_back() {
T value;
cout << "Добавление нового элемента в конец списка\nВведите значение элемента: ";
cin >> value;
while (getchar() != '\n');
if (head == NULL)
{
init(value);
return;
}
item * elem;
elem = new item;
elem->data = value;
elem->next = NULL;
elem->prev = tail;
tail->next = elem;
tail = elem;
cout << "Элемент успешно добавлен!" << endl;
}
template <class T>
void list<T>::init(T value) {
item * elem;
elem = new item;
elem->data = value;
elem->next = NULL;
elem->prev = NULL;
head = elem;
tail = elem;
}
template <class T>
void list<T>::amount_of_different_elems() {
if (head == NULL)
{
cout << "Список пуст!" << endl;
return;
}
int size = 0, count = 0, i, j;
item * ptr = head;
bool item_exist = false;
for (ptr = head; ptr != NULL; ptr = ptr->next, size++); // Подсчет количества элементов в списке
cout << "Количество элементов в списке: " << size << endl;
T * temp = new T[size]; // Выделение временной памяти для элементов списка которые нужно сравнить
for (ptr = head, i = 0; ptr != NULL; ptr = ptr->next, i++) {
item_exist = false;
for (j = 0; j < i; j++)
// Если индекс элемента не 0 и значение элемента уже встречалось, то элемент не оригинальный
if (i && ptr->data == temp[j]) item_exist = true;
if (!item_exist) {
count++;
temp[i] = ptr->data;
}
}
cout << "Количество различных элементов в списке: " << count << endl;
}
template <class T>
bool list<T>::erase(item * _ptr) {
if (_ptr == head && _ptr == tail) {
head = tail = NULL;
delete _ptr;
return 1;
}
else if (_ptr == head) {
head->next->prev = NULL;
head = head->next;
delete _ptr;
return 1;
}
else if (_ptr == tail) {
tail->prev->next = NULL;
tail = tail->prev;
delete _ptr;
return 1;
}
else {
_ptr->prev->next = _ptr->next;
_ptr->next->prev = _ptr->prev;
delete _ptr;
return 1;
}
return 0;
}
template <class T>
bool list<T>::pop_front() {
if (head == NULL) {
cout << "Список пуст!" << endl;
return 0;
}
return erase(head);
}
template <class T>
bool list<T>::pop_back() {
if (head == NULL) {
cout << "Список пуст!" << endl;
return 0;
}
return erase(tail);
}
template <class T>
int list<T>::pop_select() {
if (head == NULL)
{
cout << "Список пуст!" << endl;
return 0;
}
item * ptr_select = head;
char press_key = 0;
while (1) {
system("cls");
cout << "Чтобы удалить элемент выберите его с помощью клавиш ВЛЕВО и ВПРАВО и нажмите ENTER\n";
cout << "Для перехода в предыдущее меню нажмите клавишу BACKSPACE\n\n";
cout << ' ';
for (item * ptr = head; ptr != NULL; ptr = ptr->next) {
if (ptr_select == ptr) {
SetConsoleTextAttribute(hStdOut, (WORD)((15 << 4) | 0)); // Изменение цвета текста и фона за текстом который будет выведен далее
cout << ptr->data;
SetConsoleTextAttribute(hStdOut, (WORD)((0 << 4) | 15));
cout << ' ';
}
else cout << ptr->data << ' ';
}
press_key = _getch();
if (press_key == -32) press_key = _getch();
switch (press_key) {
case KEY_LEFT: {
ptr_select = (ptr_select == head ? tail : ptr_select->prev);
break;
}
case KEY_RIGHT: {
ptr_select = (ptr_select == tail ? head : ptr_select->next);
break;
}
case KEY_ENTER:
return erase(ptr_select);
case KEY_BACKSPACE:
return -1;
default:
break;
}
}
}
template <class T>
void list<T>::print() {
if (head == NULL)
{
cout << "Список пуст!" << endl;
return;
}
for (item * ptr = head; ptr != NULL; ptr = ptr->next)
{
cout << ptr->data << ' ';
}
cout << '\n';
}