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

ПР №5 Кольцевой односвязный список

.doc
Скачиваний:
1
Добавлен:
02.02.2025
Размер:
711.68 Кб
Скачать

ФЕДЕРАЛЬНОЕ АГЕНТСТВО СВЯЗИ

ФЕДЕРАЛЬНОЕ ГОСУДАРСТВЕННОЕ БЮДЖЕТНОЕ ОБРАЗОВАТЕЛЬНОЕ УЧРЕЖДЕНИЕ ВЫСШЕГО ОБРАЗОВАНИЯ

«САНКТ-ПЕТЕРБУРГСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ ТЕЛЕКОММУНИКАЦИЙ ИМ. ПРОФ. М.А. БОНЧ-БРУЕВИЧА»

(СПбГУТ)

Кафедра безопасности информационных систем

ОТЧЁТ

по итоговой работе №5 на тему: «Кольцевой односвязный список»

по дисциплине «Алгоритмы и структуры данных»

Выполнил: студент группы ИСТ-931, Гетманченко П.А.

«17» ноября 2020 г. ___________/П.А. Гетманченко /

Принял: к.ф.-м.н., доцент, Моисеев И. А.

«17» ноября 2020 г. __________/ И. А. Моисеев /

Основная часть

Цель работы: изучить понятие кольцевого односвязного списка, создав записную книжку на его основе.

Результаты выполнения работы

Шаг 1:

Первоначально нужно обязательно добавить к проекту файлы, а не просто открыть.

Результат:

List.cpp (файл с реализацией функций работы со списком)

#include "list.h"

int MainMenu()

{

system("cls");

cout << "Выберите действие" << endl;

cout << "1. Загрузка списка из файла" << endl;

cout << "2. Сохранение списка в файл" << endl;

cout << "3. Редактирование выбранной записи" << endl;

cout << "4. Добавление записи в список" << endl;

cout << "5. Удаление выбранной записи" << endl;

cout << "6. Поиск по списку" << endl;

cout << "7. Просмотреть весь список" << endl;

cout << "0. Выход" << endl;

int m = -1;

do {

cout << "> ";

cin >> m;

if (m < 0 || m > 7)

{

cout << "Некорректное значение, повторите ввод" << endl;

m = -1;

}

} while (m < 0);

return m;

}

int IndexMenu()

{

int d;

cout << "Введите номер записи: ";

cin >> d;

return d;

}

int FindMenu()

{

cout << "Выберите режим поиска" << endl;

cout << "1. по номеру записи" << endl;

cout << "2. по ФИО" << endl;

cout << "3. по году рождения" << endl;

cout << "4. по номеру телефона" << endl;

cout << "0. отмена" << endl;

int m = -1;

do {

cout << "> ";

cin >> m;

if (m < 0 || m > 4)

{

cout << "Некорректное значение, повторите ввод" << endl;

m = -1;

}

} while (m < 0);

return m;

}

Node* Load(Node* head, const char* fileName)

{

ifstream fin(fileName);

if (!fin.is_open())

{

cout << "ошибка открытия файла" << endl;

return head;

}

if (head != nullptr)

{

Clear(head);

head = nullptr;

}

Data val;

string str;

int index = 0;

while (!fin.eof())

{

// считываем из файла ФИО

getline(fin, str);

val.fullName = new char [str.size() + 1];

memset(val.fullName, 0, str.size() + 1);

memcpy_s(val.fullName, str.size() + 1, str.c_str(), str.size());

// считываем год рождения

fin >> val.year;

fin.get(); // забираем \n из конца строки

// считываем номер телефона

getline(fin, str);

val.phone = new char[str.size() + 1];

memset(val.phone, 0, str.size() + 1);

memcpy_s(val.phone, str.size() + 1, str.c_str(), str.size());

// добавляем элемент в список

if (!str.empty())

{

// вычисляем порядковый номер записи

val.index = ++index;

head = Insert(head, val);

}

}

fin.close();

cout << "Из файла прочитано " << index << " записей" << endl;

Show(head);

return head;

}

void Save(Node* head, const char* fileName)

{

if (head == nullptr)

{

cout << "Список пуст" << endl;

return;

}

ofstream fout(fileName);

if (!fout.is_open())

{

cout << "Ошибка открытия файла" << endl;

return;

}

Node* n = head;

int i = 0;

do

{

fout << n->value.fullName << endl;

fout << n->value.year << endl;

fout << n->value.phone << endl;

n = n->next;

i++;

} while (n != head);

fout.flush();

fout.close();

cout << "В файл записано " << i << " элементов списка" << endl;

}

Node* Insert(Node* head, Data val)

{

Node* newNode = new Node; // создаём новый узел списка

newNode->value = val; // запоминаем хранимое значение

if (head != nullptr) // если список не пуст

{

Node* n = head;

while (n->next != head) // находим последний узел списка

n = n->next;

n->next = newNode; // связываем последний узел с новым

}

else

head = newNode; // если список пуст, запоминаем новый узел как первый

newNode->next = head; // замыкаем список, последний элемент ссылается на первый

return head; // возвращаем указатель на первый элемент списка

}

void Edit(Node* head, int index)

{

if (head == nullptr)

{

cout << "Список пуст" << endl;

return;

}

Node* n = head;

while (n->next != head && n->value.index != index)

n = n->next;

if (n->value.index != index)

{

cout << "Элемент с заданным номером не найден" << endl;

return;

}

string str;

cout << "Введите ФИО (текущее значение: " << n->value.fullName << ")" << endl;

cin.ignore();

getline(cin, str);

delete[] n->value.fullName;

n->value.fullName = new char[str.size() + 1];

memset(n->value.fullName, 0, str.size() + 1);

memcpy_s(n->value.fullName, str.size() + 1, str.c_str(), str.size());

cout << "Введите год рождения (текущее значение: " << n->value.year << ")" << endl;

cin >> n->value.year;

cout << "Введите номер телефона (текущее значение: " << n->value.phone << ")" << endl;

cin.ignore();

getline(cin, str);

delete[] n->value.phone;

n->value.phone = new char[str.size() + 1];

memset(n->value.phone, 0, str.size() + 1);

memcpy_s(n->value.phone, str.size() + 1, str.c_str(), str.size());

cout << "Редактирование завершено" << endl;

}

Node* Add(Node* head)

{

Data val;

string str;

cout << "Добавление записи с список" << endl;

cout << "Введите ФИО: ";

cin.ignore();

getline(cin, str);

val.fullName = new char[str.size() + 1];

memset(val.fullName, 0, str.size() + 1);

memcpy_s(val.fullName, str.size() + 1, str.c_str(), str.size());

cout << "Введите год рождения: ";

cin >> val.year;

cout << "Введите номер телефона: ";

cin.ignore();

getline(cin, str);

val.phone = new char[str.size() + 1];

memset(val.phone, 0, str.size() + 1);

memcpy_s(val.phone, str.size() + 1, str.c_str(), str.size());

val.index = Size(head) + 1;

head = Insert(head, val);

cout << "Запись добавлена" << endl;

return head;

}

Node* Delete(Node* head, int index)

{

if (head == nullptr)

{

cout << "Список пуст" << endl;

return head;

}

Node* p = nullptr; // указатель на узел, предшествующий удаляемому

Node* n = head; // указатель на удаляемый узел

while (n->next != head && n->value.index != index)

{

p = n;

n = n->next;

}

if (n->value.index != index)

{

cout << "Элемент с заданным номером не найден" << endl;

return head;

}

// освобождаем память, занимаемую данными

delete[] n->value.fullName;

delete[] n->value.phone;

if (p == n) // если узел ссылается сам на себя, т.е. является единственным

{

delete n; // удаляем элемент

head = nullptr; // обнуляем указатель на начало списка

}

else if (n == head) // если удаляем не единственный, но первый элемент

{

head = head->next; // смещаем указатель на начало списка

p = head;

while (p->next != n) // ищем узел, предшествующий удаляемому

p = p->next;

}

p->next = n->next; // связываем элементы списка, исключая удаляемый

delete n; // удаляем узел

// корректируем номера оставшихся элементов списка

p = p->next;

do

{

p->value.index--;

p = p->next;

} while (p != head);

cout << "Запись удалена" << endl;

return head; // возвращаем указатель на начало списка

}

void Find(Node* head, int mode)

{

if (head == nullptr)

{

cout << "Список пуст" << endl;

return;

}

string str;

int x;

switch (mode)

{

case 1: //по номеру записи

cout << "Введите номер записи: ";

cin >> x;

break;

case 2: //по ФИО

cin.ignore();

cout << "Введите ФИО: ";

getline(cin, str);

break;

case 3: //по году рождения

cout << "Введите год рождения: ";

cin >> x;

break;

case 4: //по номеру телефона

cin.ignore();

cout << "Введите номер телефона: ";

getline(cin, str);

break;

default:

return;

}

cout << "Результаты поиска:" << endl;

Node* n = head;

int i = 0;

bool f;

do

{

switch (mode)

{

case 1: //по номеру записи

f = (x == n->value.index);

break;

case 2: //по ФИО

f = (strstr(n->value.fullName, str.c_str()) != nullptr);

break;

case 3: //по году рождения

f = (x == n->value.year);

break;

case 4: //по номеру телефона

f = (strstr(n->value.phone, str.c_str()) != nullptr);

break;

default:

break;

}

if (f == true)

{

cout << setw(2) << n->value.index << ") "

<< setw(20) << n->value.fullName << " "

<< n->value.year << "г.р., тел.: "

<< n->value.phone << endl;

i++;

}

n = n->next;

} while (n != head);

if (i == 0)

cout << "Ничего не найдено" << endl;

else

cout << "Найдено " << i << " записей" << endl;

}

void Show(Node* head)

{

if (head == nullptr)

{

cout << "Список пуст" << endl;

return;

}

Node* n = head;

do

{

cout << setw(2) << n->value.index << ") "

<< setw(20) << n->value.fullName << " "

<< n->value.year << "г.р., тел.: "

<< n->value.phone << endl;

n = n->next;

} while (n != head);

}

void Clear(Node* head)

{

Node* p = head;

Node* n = p->next;

Node* r = nullptr;

while (n != p)

{

r = n;

n = n->next;

// освобождаем память

delete[] r->value.fullName;

delete[] r->value.phone;

delete r;

}

// удаляем последний узел

delete[] n->value.fullName;

delete[] n->value.phone;

delete n;

}

int Size(Node* head)

{

if (head == nullptr)

return 0;

Node* n = head;

while (n->next != head)

n = n->next;

return n->value.index;

}

main.cpp (главный файл программы, где с функции main начинается выполнение программы)

#include "list.h"

#include <Windows.h>

int main()

{

setlocale(LC_ALL, "Russian");

SetConsoleOutputCP(1251);

SetConsoleCP(1251);

const char* fileName = "test.txt";

Node* head = nullptr;

int d = 0;

do {

d = MainMenu();

// Исполним выбранную команду

switch (d)

{

case 1: // Загрузка списка из файла

head = Load(head, fileName);

break;

case 2: // Сохранение списка в файл

Save(head, fileName);

break;

case 3: // Редактирование выбранной записи

Edit(head, IndexMenu());

break;

case 4: // Добавление записи в список

head = Add(head);

break;

case 5: // Удаление выбранной записи

head = Delete(head, IndexMenu());

break;

case 6: // Поиск по списку

Find(head, FindMenu());

break;

case 7: // Просмотреть весь список

Show(head);

break;

case 0: // Выход

Clear(head);

break;

}

system("pause");

} while (d != 0);

return 0;

}

List.h (заголовочный файл, с описанием всех функций работы со списком)

#pragma once

#include <iostream>

#include <fstream>

#include <string>

#include <iomanip>

using namespace std;

struct Data

{

int index; // порядковый номер записи

char* fullName; // фамилия и инициалы

int year; // год рождения

char* phone; // номер телефона

};

struct Node

{

Data value; // хранимое значение

Node* next; // указатель на следующий узел списка

};

int MainMenu(); // меню программы управления данными

int IndexMenu(); // меню ввода номера редактируемой или удаляемой записи

int FindMenu(); // меню выбора режима поиска

Node* Load(Node* head, const char *fileName); // загрузка файла данных с диска и вывод на экран

void Save(Node* head, const char* fileName); // запись файла на диск

Node* Insert(Node* head, Data val); // добавление записи в список

void Edit(Node* head, int index); // редактирование выбранной записи

Node* Add(Node* head); // добавление записи в список

Node* Delete(Node* head, int index); // удаление выбранной записи

void Find(Node* head, int mode); // поиск записи в файле

void Show(Node* head); // просмотр списка

void Clear(Node* head); // очистка памяти от списка

int Size(Node* head); // вычисление размера списка

Шаг 2:

Вид программы:

Шаг 3:

Действия программы:

  1. Загрузка списка из файла

  1. Сохранение списка из файла

  1. Редактирование выбранной записи

  1. Добавление записи в список

  1. Удаление выбранной записи

  1. Поиск по списку

По номеру записи:

По ФИО:

По году рождения:

По номеру телефона:

Отмена действия:

  1. Просмотреть весь список

  1. Выход

Выводы:

Была создана записная книжка на основе кольцевого односвязного списка с различными действиями, изменяющими информацию в ней.

Содержание

Основная часть 2

Результаты выполнения работы 2

Выводы 23

Содержание 23

САНКТ-ПЕТЕРБУРГ 2020