Примеры программ к Лабораторной работе N9. "Структуры данных и связный список"

/* films1.c - использование массива структур */
#include <stdio.h>

#define TSIZE 45 /* размер массива для хранения названия	*/
#define FMAX 5	/* максимальное количество названий фильмов */

struct film {
	char title[TSIZE];
	int rating;
};

int main(void){
	struct film movies[FMAX];
	int i = 0;
	int j;
	puts("Введите название первого фильма:");
	while (i < FMAX && gets(movies[i].title) != NULL &&	movies[i].title[0] != '\0')	{
		puts("Введите свое значение рейтинга <0-10>:");
		scanf("%d", &movies[i++].rating);
		while(getchar() != '\n')
			continue;
		puts("Введите название следующего фильма (или пустую строку для прекращения ввода):");
	}
	if (i == 0)
		printf("Данные не были введены. ");
	else
		printf ("Список фильмов:\n");
	for (j = 0; j < i; j++)
	printf("Фильм: %s Рейтинг: %d\n", movies[j].title,	movies[j].rating);
	printf("Программа завершена.\n");
	return 0;
}
/* films2.c - использование связного списка структур */
#include <stdio.h>
#include <stdlib.h> /* содержит прототип функции malloc() */
#include <string.h> /* содержит прототип функции strcpy() */
#define TSIZE 45	/* размер массива для хранения названия */

struct film {
	char title[TSIZE];
	int rating;
	struct film *next; /* указывает на следующую структуру в списке */
};

int main(void)
{
	struct film *head = NULL;
	struct film *prev, *current;
	char input[TSIZE];

	/* Сбор и сохранение информации */
	puts("Введите название первого фильма:");
	while (gets(input) != NULL && input[0] != '\0')	{
		current = (struct film *) malloc(sizeof(struct film));
		if (head == NULL) /* первая структура	*/
			head = current;
		else	/* последующие структуры */
			prev->next = current;
		current->next = NULL;
		strcpy(current->title, input);
		puts("Введите свое значение рейтинга <0-10>:");
		scanf("%d", &current->rating);
		while(getchar() != '\n')
			continue;
		puts("Введите название следующего фильма (или пустую строку для прекращения ввода информации):");
		prev = current;
	}

	/* Отображение списка фильмов */
	if (head == NULL)
		printf("Данные не были введены. ");
	else
		printf ("Список фильмов:\n");
	current = head;
	while (current != NULL)	{
		printf ("Фильм: %s Рейтинг: %d\n", current->title, current->rating);
		current = current->next;
	}

	/* Программа выполнена, поэтому можно освободить память */
	current = head;
	while (current != NULL){
		free(current);
		current = current->next;
	}

	printf ("Программа завершена.\n");

	return 0;
}
/* films3.c - использование связного списка в стиле ADT */
/* компилировать вместе с list.с */

#include <stdio.h>
#include <stdlib.h> /* прототип функции exit()	*/
#include "list.h" /* определение типов List, Item */

void showmovies(Item item);

int main(void) {

	List movies;
	Item temp;

	/* инициализация */
	InitializeList(&movies);

	if (ListIsFull(&movies))
	{
		fprintf (stderr, "Доступная память отсутствует! Программа завершена.\n");
		exit (1);
	}
	/* сбор и сохранение информации */
	puts("Введите название первого фильма:");
	while (gets(temp.title) != NULL && temp.title[0] != '\0') {
		puts ("Введите свое значение рейтинга <0-10>:");
		scanf("%d", &temp.rating);
		while (getchar() != '\n')
			continue;
		if (AddItem(temp, &movies)==false) {
			fprintf(stderr,"Проблема с резервированием памяти\n");
			break;
		}

		if (ListIsFull(&movies))
		{
			puts("Список полон.");
			break;
		}
		puts("Введите название следующего фильма (или пустую строку для прекращения ввода):");
	}

	/* отображение */
	if (ListIsEmpty(&movies))
		printf("Данные не были введены. ");
	else
	{
		printf ("Список фильмов:\n");
		Traverse(&movies, showmovies);
	}

	printf("Вы ввели %d фильмов.\n", ListItemCount(&movies));

	/* очистка */
	EmptyTheList(&movies);

	printf("Программа завершена.\n");

	return 0;
}

void showmovies(Item item)
{
	printf("Фильм: %s Рейтинг: %d\n", item.title, item.rating);
}
/* list.h - файл заголовка для простого типа list	*/
#ifndef LIST_H_
#define LIST_H_
#include <stdbool.h> /* функциональная возможность C99	*/

/* объявления, характерные для программы */
#define TSIZE 45 /* размер массива для хранения названия	*/
struct film
{
	char title[TSIZE];
	int rating;
};

/* определения обобщенного типа	*/
typedef struct film Item;
typedef struct node
{
	Item item;
	struct node * next;
} Node;

typedef Node * List;

/* прототипы функций	*/
/* операция:	инициализация списка	*/
/* начальные условия: plist указывает на список */
/* конечные условия: список инициализирован пустым значением	*/
void InitializeList(List * plist);

/* операция:	определение того, является ли список пустым */
/*	plist указывает на инициализированный список */
/* конечные условия: функция возвращает значение True, если список	*/
/*	пуст, и False - в противном случае	*/
bool ListIsEmpty(const List *plist);

/* операция:	определение того, является ли список полным	*/
/*	plist указывает на инициализированный список	*/
/* конечные условия: функция возвращает значение True, если список */
/* полон, и False - в противном случае */
bool ListIsFull(const List *plist) ;

/* операция: определение количества элементов в списке */
/* plist указывает на инициализированный список */
/* конечные условия: функция возвращает число элементов в списке */
unsigned int ListItemCount(const List *plist);

/* операция: добавление элемента в конец списка */
/* начальные условия: item - элемент, добавляемый в список */
/* plist указывает на инициализированный список */
/* конечные условия: если возможно, функция добавляет элемент в */
/* конец списка и возвращает значение True; */
/* в противном случае она возвращает значение */
/* False */
bool AddItem(Item item, List * plist);

/* операция: применение функции к каждому элементу списка */
/* plist указывает на инициализированный список */
/* pfun указывает на функцию, которая принимает */
/* аргумент Item и не имеет возвращаемого */
/* значения */
/* конечное условие: функция, указанная pfun, выполняется один */
/* раз для каждого элемента в списке */
void Traverse(const List *plist, void (* pfun)(Item item) );

/* операция: освобождение зарезервированной памяти, если */
/* таковая существует */
/* plist указывает на инициализированный список */
/* конечные условия: любая память, зарезервированная для списка, */
/* освобождается, и список устанавливается в */ /* пустое состояние */
void EmptyTheList(List * plist);

#endif
/* list.c - функции, поддерживающие операции со списком */
#include <stdio.h>
#include <stdlib.h>
#include "list.h"

/* прототип локальной функции */
static void CopyToNode(Item item, Node * pnode);

/* функции интерфейса */
/* устанавливает список в пустое состояние */
void InitializeList(List * plist) {
	* plist = NULL;
}

/* возвращает значение true, если список пуст */
bool ListIsEmpty(const List * plist) {
	if (*plist == NULL)
		return true;
	else
		return false;
}

/* возвращает значение true, если список полон */
bool ListIsFull(const List * plist) {
	Node * pt;
	bool full;
	pt = (Node *) malloc(sizeof(Node));
	if (pt == NULL)
		full = true;
	else
		full = false;
	free (pt);
	return full;
}

/* возвращает количество узлов */
unsigned int ListItemCount(const List * plist) {
	unsigned int count =0;
	Node * pnode = *plist; /* установка на начало списка */
	while (pnode != NULL) {
		++count;
		pnode = pnode->next; /* установка на следукщий узел */
	}
	return count;
}

/* создает узел для хранения элемента и добавляет его в конец */
/* списка, указанного переменной plist (медленная реализация) */
bool AddItem(Item item, List * plist) {
	Node * pnew;
	Node * scan = *plist;
	pnew = (Node *) malloc(sizeof(Node));
	if (pnew == NULL)
		return false; /* выход из функции в случае ошибки */
	CopyToNode(item, pnew);
	pnew->next = NULL;
	if (scan == NULL) /* список пуст, поэтому помещает */
		*plist = pnew; /* pnew в начало списка */
	else
	{
		while (scan->next != NULL)
			scan = scan->next; /* ищет конец списка */
		scan->next = pnew; /* добавляет pnew в конец */ 
	}
	return true;
}

/* посещает каждый узел и выполняет функцию, указанную pfun */
void Traverse (const List * plist, void (* pfun)(Item item) ) {
	Node * pnode = *plist; /* устанавливает указатель на начало списка */
	while (pnode != NULL) {
		(*pfun)(pnode->item); /* применяет функцию к элементу */
		pnode = pnode->next; /* переход к следующему элементу */
	}
}

/* освобождает память, зарезервированную функцией malloc() */
/* устанавливает указатель списка в значение NULL */
void EmptyTheList(List * plist){
	Node * psave;
	while (*plist != NULL){
		psave = (*plist)->next; /* сохранение адреса следуюцего узла */
		free(*plist);			/* освобождение текущего узла	*/
		*plist = psave;			/* переход к следующему узлу	*/
	}
}

/* определение локальной функции */
/* копирует элемент в узел */
static void CopyToNode(Item item, Node * pnode) {
	pnode->item = item; /* копирование структуры */
}