Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

В2_7

.cpp
Скачиваний:
8
Добавлен:
01.02.2019
Размер:
11.89 Кб
Скачать
#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';
}
Соседние файлы в предмете Программирование на C++