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

Основы программирования на языке С. Учебное пособие

.pdf
Скачиваний:
1
Добавлен:
07.09.2026
Размер:
2 Мб
Скачать
☆
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
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]