Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Основы программирования на языке С. Учебное пособие
.pdf
mas[i]=m[i];
printf ("\nМассив дат сфорирован");
}
printf("\nИз введенных дат:\n");
for (int i=0; i<n; i++)
vivod(mas[i]);
printf("\наименьшая дата ");
vivod (min(mas,n));
break;
}
default: printf("Ошибка ввода ");
}
printf("\nДля продолжения нажмите Enter "); getch();
goto N;
}
Задание 20. Массив структур
Каждому студенту рекомендуется выполнить хотя бы одно из
упражнений 1-12 следующего задания.
Разработать демонстрационную программу, которая должна обеспечивать выбор с помощью меню и выполнение следующих функций:
– ввод полей структуры с клавиатуры;
– вывод полей структуры на экран;
– начальное формирование массива из N<20 структур объектов класса (ввод с клавиатуры или из заданного массива);
– вывод массива объектов на экран;
– дополнительные функции, указанные в варианте задания.
1. Описать структуру РАЦИОНАЛЬНОЕ ЧИСЛО (поля: ЧИСЛИ-
ТЕЛЬ, ЗНАМЕНАТЕЛЬ). Дополнительные функции демонстрационной
программы:
а) вычисление наибольшего из массива рациональных чисел;
b) проверка вхождения заданного числа в масив чисел.
2. Описать структуру ИСТОРИЧЕСКОЕ СОБЫТИЕ (поля: ЧИСЛО,
МЕСЯЦ, ГОД, СОБЫТИЕ). Дополнительные функции демонстрационной
программы:
a) сортировка массива исторических событий по полю СОБЫТИЕ;
b) поиск в массиве заданного события.
3. Описать структуру ДАТА (поля) ЧИСЛО, МЕСЯЦ, ГОД. Допол-
нительные функции демонстрационной программы:
а) поиск в массиве дат всех даты заданного года;
b) объединения двух массивов дат.
71

4. Описать структуру ДАТА (поля: ЧИСЛО, МЕСЯЦ, ГОД). Допол-
нительные функции демонстрационной программы:
а) сортировка массива дат;
b) поиск в массиве дат самой поздней.
5. Описать структуру АЛГЕБРАИЧЕСКИЙ ПОЛИНОМ (поля: СТЕ-
ПЕНЬ, КОЭФФИЦИЕНТЫ). Дополнительные функции демонстрационной
программы:
а) удаление заданного полинома из массива;
b) сложение двух заданных полиномов.
6. Описать структуру АВТОМАШИНА (поля: МАРКА, ГОД ВЫ-
ПУСКА, НОМЕР, ФАМИЛИЯ ВЛАДЕЛЬЦА). Дополнительные функции
демонстрационной программы:
а) сортировка массива машин по фамилии владельца;
b) поиск машин по марке.
7. Описать структуру СТУДЕНТ (поля ФИО, ЧИСЛО, МЕСЯЦ, ГОД
РОЖДЕНИЯ). Дополнительные функции демонстрационной программы:
а) поиск в массиве всех студентов заданного года рождения;
b) сортировка массива студентов по возрасту.
8. Описать структуру ИСТОРИЧЕСКОЕ СОБЫТИЕ (поля ГОД, СО-
БЫТИЕ). Дополнительные функции демонстрационной программы:
а) сортировка массива событий по году;
b) поиск всех событий в заданном году.
9. Описать структуру СТУДЕНТ (поля: ФИО, ГОД РОЖДЕНИЯ,
КОД ГРУППЫ). Дополнительные функции демонстрационной программы:
а) удаление из массива студента с определенной ФИО;
b) поиск в массиве всех студентов с заданным номером группы.
10. Описать структуру ЭКСПОРТИРУЕМЫЙ ТОВАР (поля:
НАИМЕНОВАНИЕ ТОВАРА, СТРАНА (импортирующая товар), ОБЪЕМ
ПАРТИИ (в штуках)). Дополнительные функции демонстрационной программы:
а) сортировка массива товаров по наименованию;
b) поиск всех товаров, импортируемых заданной страной.
11. Описать структуру УЧЕНИК (поля: ФИО, ГОД ОБУЧЕНИЯ,
НАЗВАНИЯ КЛАССА (БУКВА)). Дополнительные функции демонстрационной программы:
а) сортировка массива учеников по паре (год обучения, название
класса);
b) удаление ученика с заданной ФИО из массива.
12. Описать структуру УЧЕНИК (поля: ФИО, ГОД ОБУЧЕНИЯ,
НАЗВАНИЯ КЛАССА (БУКВА), ИТОГОВАЯ ОЦЕНКА.) Дополнительные функции демонстрационной программы:
а) сортировка массива учеников по фамилии;
b) поиск всех учеников с отличной итоговой оценкой.
72

9. ДИНАМИЧЕСКИЕ СТРУКТУРЫ ДАННЫХ
Большинство задач, рассмотренных в предыдущих главах, требовали
работы со статическими переменными – переменными, которые создаются
в момент определения и уничтожаются автоматически при выходе программы из области их действия. Статические переменные и структуры
данных характеризуются фиксированным размером выделенной для них
памяти. Например, если описан массив int a[100] под него будет
выдела
sizeof(int)*100 байт, хотя в самой программе может реально использовать-
ся лишь несколько первых элементов массива. Существуют задачи, которые исключают использование структур данных фиксированного размера
и требуют введения динамических структур данных, способных увеличиваться в размерах в процессе работы программы. Если до начала работы
с данными невозможно определить, сколько памяти
потребуется для их
хранения, то память должна выделять по мере необходимости отельными
блоками, связанными друг с другом указателями. Динамическая структура может занимать несмежные участки оперативной памяти. Память под
элементы динамической структуры выделяется с помощью функции malloc
и освобождается с помощью функции free (см. главу 6).
Динамические структуры широко применяют и для более
эффективной работы с данными, размер которых известен, особенно для решения
задач сортировки, поскольку упорядочивание динамических структур не
требует перестановки элементов, а сводится к изменению указателей на
эти элементы. Например, если в процессе выполнения программы требуется многократно упорядочивать большой массив данных, имеет смысл организовать его в виде динамической структуры
.
Элемент динамической структуры данных в языке С представляет
собой тип данных struct, содержащий по крайней мере два поля: для хранения данных и для указателя на эту же структуру. Полей данных и указателей может быть несколько. Например, элемент динамического списка
целых чисел имеет вид:
struct el
{
int a;
el *b;
}
Каждая динамическая структура характеризуется, во-первых, взаимосвязью элементов, и, во-вторых, набором типовых операций над этой
структурой. В случае динамической структуры важно решить следующие
вопросы:
– каким образом может расти и сокращаться данная структура;
– каким образом можно включить в структуру новый и удалить существующий элемент;
73

– как можно обратиться к конкретному элементу структуры для вы-
полнения над ним определенной операции.
Доступ по индексу к элементу динамической структуры, очевидно,
менее удобен, чем это было в случае массивов, так как любой элемент при
изменении размеров структуры может изменить свою позицию. Поэтому,
обычно доступ к элементам динамической структуры осуществляют
последовательно по следующему принципу: имеется один или несколько
указателей, позволяющих войти в структуру (например, указатель на первый элемент), а далее поиск требуемого элемента выполняется следованием по цепочке указателей от элемента к элементу.
Достоинства динамических структур данных – в возможности обес-
печения значительной изменчивости структур, а именно:
– размер структуры
ограничивается только доступным объемом ма-
шинной памяти;
– при изменении логической последовательности элементов структуры
требуется не перемещение данных в памяти, а только коррекция указателей;
– большая гибкость структуры (произвольная вставка и удаление
элементов).
Вместе с тем динамические структуры данных имеют и недостатки,
основные из которых следующие:
– на поля указателей (связок) расходуется
дополнительная память;
– доступ к элементам связной структуры может быть менее эффек-
тивным по времени.
Из динамических структур в программах чаще всего используют линейные списки, их частные случае – стеки и очереди, а также бинарные
деревья.
Самый простой способ связать множество элементов – сделать так,
чтобы каждый элемент ссылался на следующей. Такую
динамическую
структуру называют однонаправленным (односвязным) линейным
списком. Если каждый элемент структуры содержит ссылку как на следующий, так и не предыдущий, то говорят о двунаправленном (двусвяз-
ном) линейном списке. Создадим однонаправленный список студентов
и их оценок. Каждый элемент списка будет иметь следующий вид:
struct student
{
char *fio;
int mark;
student *next;
};
Для формирования списка требуется описать, по крайней мере, один
указатель – на начало списка (голова списка).
student * begin=NULL;
и один вспомогательный указатель
student *adr;.
74

Опишем функцию создания списка. Предполагается, что данная
функция работает с глобальной переменной begin и, таким образом, не
имеет параметров и возвращаемого значения. Если же в программе требуется работать с несколькими списками, то необходимо написать функцию,
возвращающую, указатель на начало списка. Пример такой функции описан в задании 22.
void vvod ()
{
int n;
printf ("Введите количество студентов ");
scanf("%d",&n);
const int dlin=20;
char f[dlin]; // вспомогательный массив для хранения
введенной фамилии студента
for (int i=1;i<=n; i++)
{
if (begin==NULL) // выделение памяти под первый
элемент списка
{
begin=(student *) malloc(sizeof(student));
adr=begin;
}
else // выделение памяти под очередной элемент списка
{
adr->next=(student *) malloc(sizeof(student));
adr=adr->next;
}
//заполнение элементов списка
printf (" Введите фамилию ");
gets(f); gets(f);
adr->fio=(char *)malloc (strlen(f)+1);
strcpy(adr->fio,f);
printf("Введите оценку ");
scanf("%d",&adr->mark);
adr->next=NULL;
}
}
В данном случае мы создали список студентов как очередь. Очередь – это частный случай списка, добавление элементов в который вы-
полняется в один конец, а выборка – из другого конца. Другие операции
с очередью не определены. При выборке элемент исключается из очереди. Очередь реализует принцип FIFO (firs in – first out, первым пришел –
первым вышел). В
нашем примере указатель begin указывает на начало
списка, и не изменяется при добавлении новых элементов. Добавление
элементов происходит в конец списка. Очевидно, что обработка элементов для списка, сформированного таким образом, может происходить
только с первого введенного.
75

Функцию формирования очереди vvod() можно написать следующем
образом.
1. Определить отдельную функцию создания первого элемента оче-
реди first().
2. Определить отдельную функцию добавление очередного элемента
в очередь add().
3. В функции vvod() вызвать функцию first() и в цикле функцию
add().
Другим частным случаем однонаправленного списка является стек,
добавление в который и выборка из которого выполняется с одного конца
Другие операции со стеком не определены. При выборке элемент исключается из стека. Стек реализует принцип LIFO (last in – first out, последним пришел – первым вышел). Создадим список студентов как стек, постоянно передвигая указатель begin и делая последний созданный элемент
головой списка.
void vvod ()
{
int n;
printf ("Введите количество студентов ");
scanf("%d",&n);
const int dlin=20;
char f[dlin]; // вспомогательный массив для хранения
введенной фамилии студента
for (int i=1;i<=n; i++)
{
adr=(student *) malloc(sizeof(student));
printf (" Введите фамилию ");
gets(f); gets(f);
adr->fio=(char *)malloc (strlen(f)+1);
strcpy(adr->fio,f);
printf("Введите оценку ");
scanf("%d",&adr->mark);
adr->next=begin;
begin=adr;
}
}
Чтобы вывести на экран элементы списка, созданного любым из
предложных способов, можно использовать следующую процедуру:
void vivod()
{
adr=begin;
while (adr!=NULL)
{
printf("\n%20s%s%d",(adr->fio)," ",adr->mark);
adr=adr->next;
}
}
.
76

Так как память под элементы списка выделяется с помощью функции malloc, то ее необходимо освобождать с помощью функции free. Таким образом, после окончания работы со списком его необходимо удалить
из памяти во избежание проблем «динамического мусора», например,
с помощью следующей функции.
void del()
{
while (begin)
{
adr=begin->next;
free (begin);
begin=adr;
}
}
Кроме процедур создания, вывода на экран, удаления списка обычно
определяют следующие процедуры:
– добавления элемента (в начало или в конец списка);
– поиска заданного элемента;
– вставка элемента (до или после заданного элемента);
– сортировка списка;
– удаления заданного элемента.
Задание21.Динамическийсписок
Каждому студенту рекомендуется выполнить хотя бы одно из
упражнений 1-12 следующего задания.
Разработать демонстрационную программу, в которой используется динамическая структура списка (однонаправленного или двунаправленного)
и обеспечивается выбор с помощью меню и выполнение следующих функций:
– создания списка на основе данных из файла,
– записи данных из списка в файл,
– добавления элемента в начало (конец) списка,
– удаления всего списка,
– сортировки списка по
одному из полей,
– вывода всего списка данных на экран в виде таблицы,
– функций, описанных в варианте задания.
1. Ввести структуру АВТОМАШИНА с полями МАРКА, ГОД ВЫ-
ПУСКА, НОМЕР, ФАМИЛИЯ ВЛАДЕЛЬЦА. Составить функцию поиска
машины по любой из комбинации признаков.
2. Ввести структуру АВТОМАШИНА с полями МАРКА, ГОД ВЫ-
ПУСКА, НОМЕР, ФАМИЛИЯ
ВЛАДЕЛЬЦА. Составить функцию,
а. поиска всех владельцев машин, имеющих более одной машины;
b. формирования нового списка машин заданного владельца.
77

3. Ввести структуру ИСТОРИЧЕСКОЕ СОБЫТИЕ с полями ЧИСЛО,
МЕСЯЦ, ГОД, СОБЫТИЕ. Составить и протестировать функцию,
а. сортирующую список исторических событий по дате (год, месяц,
число);
b. добавляющую новое событие в отсортированный по датам собы-
тия список в нужное место.
4. Ввести структуру ИСТОРИЧЕСКОЕ СОБЫТИЕ с полями ГОД,
СОБЫТИЕ. Составить функцию,
а. вычисляющую
в каком году произошло больше всего событий;
b. формирующую новый список из событий, произошедших в этом
году.
5. Ввести структуру ИСТОРИЧЕСКОЕ СОБЫТИЕ с полями ГОД,
СОБЫТИЕ. Составить функцию,
а. подсчитывающую средний интервал между датами;
b. удаляющую все события заданного года.
6. Ввести структуру СТУДЕНТ с полями ФИО, ЧИСЛО, МЕСЯЦ,
ГОД РОЖДЕНИЯ, НОМЕР ГРУППЫ
. Составить функцию,
а. удаляющую всех студентов из заданной группы,
b. сортирующую список студентов по возрасту (год, месяц, дата
рождения).
7. Ввести структуру ТОВАР с полями НАИМЕНОВАНИЕ ТОВА-
РА, СТРАНА-производитель, ОБЪЕМ ПАРТИИ (в штуках). Составить
функцию,
а. поиска всех стран, производящих более k наименований товара
(предполагается, что для каждой страны наименование одно
товара встре-
чается в списке один раз);
b. формирующую новый список товаров заданной страны.
8. Ввести структуру ТОВАР с полями НАИМЕНОВАНИЕ ТОВАРА,
ОБЪЕМ ПАРТИИ (в штуках), ГОД, МЕСЯЦ, ДЕНЬ поставки. Составить
функцию,
а. поиска всех товаров, поставленных в заданный месяц заданного
года;
b. удаления всех товаров с заданным наименованием.
9. Ввести структуру
УЧЕНИК с полями ФИО, ГОД РОЖДЕНИЯ,
НОМЕР КЛАССА. Составить функцию,
а. удаляющую всех студентов заданного класса;
b. добавляющего нового студента в отсортированный по ФИО спи-
сок студентов.
10. Ввести структуру СТУДЕНТ с полями ФИО, НОМЕР ГРУППЫ.
Составить функцию,
а. подсчитывающую среднее количество учеников в группе;
b. формирующую новый список из учеников заданной
группы.
78

11. Ввести структуру СТУДЕНТ с полями ФИО, НОМЕР ГУППЫ,
ИТОГОВАЯ ОЦЕНКА. Составить функцию,
а. подсчитывающую среднюю оценку для каждой группы;
b. удаляющую всех студентов заданной группы.
12. Ввести структуру СТУДЕНТ с полями ФИО, НОМЕР ГУППЫ.
Составить функцию,
а. подсчитывающего количество студентов в каждой группе.
b. удаляющую студента с заданной фамилией (предполагается, что
в
списке фамилии студентов уникальны).
13. Ввести структуру КНИГА с полями НАЗВАНИЕ, ФИО АВТОРА,
ГОД ИЗДАНИЯ, КОЛИЧЕСТВО ЭКЗЕМПЛЯРОВ. Составить функцию,
а. подсчитывающую общее количество экземпляров книг,
b. вычисляющее в какой год было издано больше всего книг (по
наименованию, а не по количеству экземпляров. Предполагается, что одна
книга издается в одном году один
раз).
14. Ввести структуру КНИГА с полями НАЗВАНИЕ, ФИО АВТОРА,
ГОД ИЗДАНИЯ. Составить функцию,
а. удаляющую все книги, изданные ранее заданного года;
b. формирующую новый список из книг заданного автора.
Задание 22. Использование стеков и очередей
Пример. По введенной формуле необходимо построить ее постфиксную (польскую инверсную) запись (ПОЛИЗ). При вычислении выражений
записанных в ПОЛИЗе, операции выполняются в том порядке, в котором
они встречаются при просмотре выражения слева направо, поэтому отпадает необходимость использования скобок и многократного сканирования выражения из-за различного приоритета операций. Например, выражению
2+3*4 соответствует ПОЛИЗ 234*+, а выражению (a+(b^c)^d*(c+f/d ) – ПОЛИЗ abc^d^+cfd/+* . Будем считать, что во введенной формуле встречаются
только операции
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#define ZNAK (c=='*' || c=='/')
struct STACK
{
int info;
STACK *next;
};
//-------Функция добавления элемента в вершину стека------
-
+, -,*, / и буквы операнды.
,
79

void push (STACK ** s, int i)
{
STACK * new_el;
new_el= (STACK* ) malloc (sizeof(STACK));
new_el->info=i;
new_el->next=*s;
*s=new_el;
}
//-----Функция удаления верхнего элемента из стека-------int pop (STACK ** s, int * error)
{
STACK * old=*s;
int info=0;
if (*s) //если стек не пуст
{
info=old->info;
*s=(*s)->next;
free (old);
*error=0; //элемент успешно удален
}
else *error=1;
return info;
}
//--Функция получение значения из стека (без удаления эле-
мента)--
int peek (STACK ** s, int *error)
{
if (*s)
{
*error=0;
return (*s)->info;
}
else {*error=1; return 0;}
}
void main ()
{
char s[80], s1[80];//массив для считывания формулы и
для записи ПОЛИЗа
char c; //вспомогательный символ
STACK *st=NULL;// вершина стека
printf("Enter formula ");
gets(s);
int l= strlen (s);
push(&st,'(');//заносим '(' в стек
int k=0, er;
for (int i=0; i<l; i++) //просматриваев выражение
//cлева направо
80
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
