Двухсвязный список

 avatar
beq
c_cpp
a year ago
18 kB
2
Indexable
Never
#include <iostream>
#include <iomanip>
#include <string>
#include "Windows.h"
#include <fstream>
#include <conio.h>

using namespace std;

struct bibliya
{
	string fio;
	string name_knig;
	string godizd;
	string ins;
	int exemp;
	bibliya* next = nullptr;
	bibliya* prev = nullptr;
};


//Добавление в список
void add(bibliya** q)
{
	system("cls");
	bibliya* current = *q; //Указатель на текущий элемент
	string str;
	int temp;
	cout << "Каким образом внести новые данные? " << endl;
	cout << "1. В ручную" << endl;
	cout << "2. Загрузить список из файла" << endl;
	cout << "3. Главное меню" << endl;
	char select = '-';
	select = _getch();
	switch (select)
	{
	case '1':
	{
		system("cls");
		bibliya* new_product;
		new_product = new bibliya;

		cout << "Введите фамилию: ";
		cin >> str;
		new_product->fio = str;
		str = "";

		cout << "Введите инициалы: ";
		cin >> str;
		new_product->ins = str;

		getline(cin, str);
		cout << "\nВведите название книги: ";
		getline(cin, str);
		new_product->name_knig = str;
		str = "";

		cout << "\nУкажите год издания: ";
		cin >> str;
		new_product->godizd = str;
		str = "";

		cout << "\nКоличество экземпляров: ";
		cin >> temp;
		new_product->exemp = temp;

		if (!(*q))
		{
			*q = new_product;
			(*q)->next = nullptr;
			(*q)->prev = nullptr;
		}

		else
		{
			bibliya* current = (*q)->next;
			bibliya* previous = *q;
			while (current)
			{
				previous = current;
				current = current->next;
			}
			previous->next = new_product;
			new_product->prev = previous;
			new_product->next = current;
		}
		break;
	}


	case '2':      //ЗАГРУЗКА из правильно заполненного файла
	{
		system("cls");
		char FILE[256];
		cout << "Укажите путь к файлу (по умолчанию text.txt):";
		cin.getline(FILE, 256);
		if (strcmp(FILE, "") == 0) {
			strcpy_s(FILE, "text.txt");
		}
		ifstream fin;
		fin.open(FILE, fstream::in);
		if (fin.is_open())
		{
			string lineName;
			string lineins;
			string lineshop_name;
			string lineProdNumber;
			string lineProdPrice;
			int int_line = 0;
			int unsigned counter = 0;
			while (!fin.eof())
			{
				counter++;
				if (counter == 1)//фамилия
				{
					getline(fin, lineName);
				}
				else if (counter == 2) //инициалы
				{
					getline(fin, lineins);
				}
				else if (counter == 3)//Название книги
				{
					getline(fin, lineshop_name);
				}
				else if (counter == 4)//год издания
				{
					getline(fin, lineProdNumber);
				}
				else if (counter == 5)//экзмепляры
				{
					getline(fin, lineProdPrice);
				}
				else
				{
					if (lineName.length() == 0 || lineins.length() == 0 || lineshop_name.length() == 0 || lineProdNumber.length() == 0 || lineProdPrice.length() == 0) { cout << "Ошибка чтения файла. Файл пуст или неправильно заполнен!" << endl; break; }
					counter = 0;
					bibliya* new_node;
					new_node = new bibliya;
					if (!(*q))
					{
						*q = new_node;
						(*q)->next = nullptr;
						(*q)->prev = nullptr;
					}
					else {
						bibliya* current = (*q)->next;
						bibliya* previous = *q;
						while (current) {
							previous = current;
							current = current->next;
						}
						previous->next = new_node;
						new_node->prev = previous;
						new_node->next = current;
					}
					new_node->fio = lineName;
					new_node->ins = lineins;
					new_node->name_knig = lineshop_name;
					new_node->godizd = lineProdNumber;
					new_node->exemp = stoi(lineProdPrice);
					lineName = lineins = lineshop_name = lineProdNumber = lineProdPrice = "";

				}
			}
			fin.close();
		}
		else
		{
			cout << "Не удалось открыть файл" << endl;
		}
		break;
	}
	default:
	{
		system("cls");
		cout << "\n\nДобавление отменено! Возврат в главное меню.\n\nНажмите любую кнопку чтобы вернуться.";
		system("pause");
		break;
	}
	}
}

//Вывод на экран
void output(bibliya** q, int a)
{
	int i = 1;
	bibliya* current = *q;
	int flag = 1;
	if (a == 1) //если выбрано с начала алфавита
	{
		cout << "Весь список книг отсортированный по алфавиту\n";
		while (current)
		{
			cout << " ФИО:                        " << current->fio << " " << current->ins << endl;
			cout << " Название книги:             " << current->name_knig << endl;
			cout << " Год издания:                " << current->godizd << endl;
			cout << " Количество экземпляров:     " << current->exemp << endl;
			current = current->next;
			i++;
			cout << "\n";
		}

		cout << "\nЗаписать всё в файл? y/n ";
		char yesno;
		yesno = _getch();
		if (yesno == 'y')
		{
			bibliya* sacc = *q;
			fstream fout;
			fout.open("rez.txt", ifstream::app);    //название файла в который запись пойдет
			if (fout.is_open())
			{
				while (sacc)
				{

					string txt = sacc->fio + '\n' + sacc->ins + '\n' + sacc->name_knig + '\n' + sacc->godizd + '\n' + to_string(sacc->exemp) + '\n';
					fout << txt;
					sacc = sacc->next;
				}
				cout << "\nЗапись произошла успешно!\n";
			}
			else
			{
				cout << "\nНет доступа к файлу. Запись прервана!" << endl;
			}
		}
	}
	else //если выбрано с конца алфавита
	{
		while (current->next)
		{
			current = current->next;
		}
		cout << "Весь список книг отсортированный с конца алфавита\n";
		while (current)
		{
			cout << " ФИО:                        " << current->fio << " " << current->ins << endl;
			cout << " Название книги:             " << current->name_knig << endl;
			cout << " Год издания:                " << current->godizd << endl;
			cout << " Количество экземпляров:     " << current->exemp << endl;
			current = current->prev;
			i++;
			cout << "\n";
		}
	}
}

void del(bibliya*& q)
{
	string candidat;
	bibliya* current = q;

	getline(cin, candidat);
	cout << "Укажите название книги, сведения о которой хотите стереть: ";
	getline(cin, candidat);
	cout << endl;
	while (current != nullptr)
	{
		if (current->name_knig == candidat)
		{
			cout << " ФИО:                        " << current->fio << " " << current->ins << endl;
			cout << " Название книги:             " << current->name_knig << endl;
			cout << " Год издания:                " << current->godizd << endl;
			cout << " Количество экземпляров:     " << current->exemp << endl;

			char answer = 'n';
			cout << "\nУдалить сведения об этой книге?   y/n ? ";
			cin >> answer;
			if (answer == 'y' || answer == 'Y')
			{
				if (current->prev == nullptr && current->next != nullptr)   //Если нет родителя, но есть потомок
				{
					current = current->next;
					q = current;
				}
				else if (current->prev != nullptr && current->next == nullptr)//Если есть родитель, но нет потомков
				{
					current->prev->next = nullptr;
				}
				else if (current->prev == nullptr && current->next == nullptr)//Нет ни родителя, ни потомка
				{
					current = nullptr;
				}
				else if (current->prev != nullptr && current->next != nullptr)//Есть и родитель, и потомок
				{
					current->fio = current->next->fio;
					current->ins = current->next->ins;
					current->name_knig = current->next->name_knig;
					current->godizd = current->next->godizd;
					current->exemp = current->next->exemp;

					current->prev->next = current->next;
					current->next->prev = current->prev;
				}
				cout << "\nСведения о книге были уcпешно удалены!" << endl;
			}
			else
			{
				cout << "Вы выбрали отмену удаления, данные были сохранены!" << endl;
			}
		}
		if (current != nullptr)current = current->next;
	}
}




void sort(bibliya*& Head)                 //Сортировка пузырьком 
{
	bibliya* left = Head;                 //Первый элемент — это пусть будет голова
	bibliya* right = Head->next;          //Второй элемент — это пусть будет следующий за головой элемент

	bibliya* temp = new bibliya;          //Временное звено для хранения переставляемого всех значений переставляемого звена

	while (left->next)  //Обходим по всем звеньям, за исключением крайнего правого
	{
		while (right) //Обходим по всем звеньям, включая крайний правый (по всем относительно первого левого на текущий момент)
		{
			if ((left->fio) > (right->fio)) //Проверяем необходимость перестановки
			{
				temp->name_knig = left->name_knig;
				left->name_knig = right->name_knig;
				right->name_knig = temp->name_knig;


				temp->fio = left->fio;
				left->fio = right->fio;
				right->fio = temp->fio;

				temp->ins = left->ins;
				left->ins = right->ins;
				right->ins = temp->ins;

				temp->godizd = left->godizd;
				left->godizd = right->godizd;
				right->godizd = temp->godizd;

				temp->exemp = left->exemp;
				left->exemp = right->exemp;
				right->exemp = temp->exemp;

			}
			right = right->next;                    //не забываем направлять указатель на следующий элемент (по подобию инкремента), иначе цикл зависнет
		}
		left = left->next;                          //не забываем направлять указатель на следующий элемент (по подобию инкремента), иначе цикл зависнет
		right = left->next;                         //Поскольку второй указатель убежал немного вперёд, обязательно возвращаем его назад, это следующий элемент относительно текущего первого
	}
}



//Поиск
void TryToFind(bibliya** q)
{
	int flag = false;
	string knig1;
	bibliya* current = *q;
	bibliya* previous = nullptr;
	getline(cin, knig1);
	cout << "Укажите название книги: ";
	getline(cin, knig1);

	while (current != nullptr)
	{
		if (current->name_knig == knig1)
		{
			cout << " ФИО:                        " << current->fio << " " << current->ins << endl;
			cout << " Название книги:             " << current->name_knig << endl;
			cout << " Год издания:                " << current->godizd << endl;
			cout << " Количество экземпляров:     " << current->exemp << endl;
			cout << "\n";
			flag = true;
		}
		previous = current;
		current = current->next;
	}
	if (flag == false)
	{
		cout << "\nНе найдено книг с данным условием!";
	}
}

void help()
{
	system("cls");
	cout << "Вариант 16" << endl;
	cout << "1. Составить программу, которая содержит текущую информацию о книгах в библиотеке." << endl;
	cout << "Сведения о книгах включают:" << endl;
	cout << "•	фамилию и инициалы автора;" << endl;
	cout << "•	название;" << endl;
	cout << "•	год издания;" << endl;
	cout << "•	количество экземпляров данной книги в библиотеке;\n" << endl;
	cout << "2. Программа должна обеспечивать:\n" << endl;
	cout << "•	хранение всех данных обо всех книгах в библиотеке в виде односвязного списка (очередь);" << endl;
	cout << "•	добавление данных о книгах вновь поступивших в библиотеку;" << endl;
	cout << "•	удаление данных о списываемой книге, название которой введено с клавиатуры;" << endl;
	cout << "•	вывод информации обо всех книгах в библиотеке;" << endl;
	cout << "•	по запросу выводится информация о книге, название которой введено с клавиатуры." << endl;
	cout << "3.Программа должна обеспечивать диалог с помощью меню." << endl;
	system("pause");
}

void info()
{
	system("cls");
	cout << "Динамические структуры данных" << endl;
	cout << "(Очереди)" << endl;
	cout << "Версия 2.0" << endl;
	cout << "Год 2022" << endl;
	cout << "Разработчик ---" << endl;
	cout << "Студент группы ---" << endl;
	system("pause");
}

void take_out(bibliya** q)
{
	bibliya* old_header = *q;
	while (*q)
	{
		(*q) = (*q)->next;
		free(old_header);
		old_header = *q;
	}
}

int main()
{
	SetConsoleCP(1251);
	SetConsoleOutputCP(1251);
	bool flag = false;
	bool flag1 = false;
	bool flag2 = false;
	bibliya* q = nullptr;
	int vibor;
	int choice;

	do {
		system("cls");
		cout << "1. Добавить книгу.\n";
		cout << "2. Удалить книгу.\n";
		cout << "3. Показать полный список библиотеки.\n";
		cout << "4. Поиск книги по названию.\n";
		cout << "5. О программе.\n";
		cout << "6. Помощь.\n";
		cout << "7. Выход\n";
		do
		{
			cout << "\nВведите номер пункта меню: ";
			cin >> vibor;
			if (vibor < 1 || vibor > 8)
			{
				cout << "Введено неверное значение. Повторите ввод: ";
				cin.clear();
				cin.sync();
			}

		} while (vibor < 1 || vibor > 8);
		system("cls");
		switch (vibor)
		{
		case 1: {
			do
			{
				cin.ignore();
				add(&q);
				flag = true;
				cout << "\nЕсли хотите ещё добавить книги введите 1, иначе 2\n";
				do
				{
					cin >> choice;
					if (choice < 1 || choice > 2)
					{
						cout << "Введено неверное значение. Повторите ввод: ";
						cin.clear();
						cin.sync();
					}
				} while (choice < 1 || choice > 2);
			} while (choice == 1);
			cout << "Чтобы вернуться в меню, нажмите любую клавишу" << endl;
			_getch();
			break;
		}
		case 2:
		{
			if (q)
			{
				do
				{
					del(q);
					cout << "\nЕсли хотите продолжить введите 1, иначе 2" << endl;
					do
					{
						cin >> choice;
						if (choice < 1 || choice > 2)
						{
							cout << "Введено неверное значение. Повторите ввод: ";
							cin.clear();
							cin.sync();
						}
					} while (choice < 1 || choice > 2);
					cout << "\n";
				} while (choice == 1);
			}
			else
			{
				cout << "\nИнформационная система пуста!\n";
			}
			cout << "Чтобы вернуться в меню, нажмите любую клавишу" << endl;
			_getch();
			break;
		}
		case 3:
		{
			if (q)
			{
				sort(q);
				do
				{
					system("cls");
					cout << "1. Вывести библиографический список с начала алфавита.\n";
					cout << "2. Вывести библиографический список с конца алфавита.\n";
					cout << "3. Вернуться в главное меню.\n";
					do
					{
						cin >> choice;
						if (choice < 1 || choice > 3)
						{
							cout << "\nВведено неверное значение. Повторите ввод: ";
							cin.clear();
							cin.sync();
						}
					} while (choice < 1 || choice > 3);
					system("cls");
					switch (choice)
					{
					case 1:
					{
						output(&q, 1);
						cout << "\nЧтобы продолжить, нажмите любую клавишу" << endl;
						_getch();
						break;
					}
					case 2:
					{
						output(&q, 2);
						cout << "\nЧтобы продолжить, нажмите любую клавишу" << endl;
						_getch();
						break;
					}
					}
				} while (choice != 3);
			}
			else
			{
				cout << "\nИнформационная система пуста.\n";
				cout << "\nДля продолжения нажмите любую клавишу..." << endl;
				_getch();
			}
			break;
		}
		case 4:
		{
			if (q)
			{
				do
				{
					TryToFind(&q);
					cout << "\nЕсли хотите продолжить введите 1, иначе 2" << endl;
					do
					{
						cin >> choice;
						if (choice < 1 || choice > 2)
						{
							cout << "\nВведено неверное значение. Повторите ввод: ";
							cin.clear();
							cin.sync();
						}
					} while (choice < 1 || choice > 2);
				} while (choice == 1);
			}
			else
			{
				cout << "\nСписок библиотеки пуст.\n";
			}
			break;
		}
		case 5:
		{
			info();
			break;
		}
		case 6:
		{
			help();
			break;
		}
		case 7:
		{
			take_out(&q);
			break;
		}
		}
	} while (vibor != 7);
	return 0;
}