bmstu_iu6_Cpp1 (823967), страница 12
Текст из файла (страница 12)
Так членамиструктуры могут быть массивы данных скалярных типов, массивы массивов. Кроме того,элементами структуры могут быть другие структуры, получившие названия вложенных.Глубина вложения компилятором не ограничивается. Обращение к таким членам тоже осуществляется с помощью точечной нотации, после чего идет обращение к элементу по правилам обращения, определяемому типом элемента.Пример 3.7. Написать программу определения среднего балла каждого студента игруппы в целом после сдачи трех экзаменов.Оглавление73Структуры данных:1) test – данные об экзамене: название экзамена и отметка (см. рисунок 3.13, а);2) student – фамилия студента и массив результатов 3 экзаменов (см.
рисунок 3.13,б).studenttestname ballfamily name name nameballballballбaРисунок 3.13 – Структуры test (a) и student (б)#include <locale.h>#include <stdio.h>#include <conio.h>#include <string.h>typedef struct// данные об экзамене{char name[10];int ball;} test;typedef struct// данные о студенте{char family[22];test results[3];}student;int main(int argc, char* argv[]){setlocale(0,"russian");student stud[10]; // массив данных о студентахint i,n=0; float avarstud,avarage=0;while (puts("Введите фамилию, предметы и оценки или end"),scanf("\n%s",stud[n].family),strcmp(stud[n].family,"end")!=0){for (avarstud=0,i=0; i<3; i++){scanf("\n%s %d",stud[n].results[i].name,&stud[n].results[i].ball);avarstud+=stud[n].results[i].ball;}Оглавление74printf("Среднее:%s=%5.2f\n",stud[n].family,avarstud/3);avarage+=avarstud;n++;}printf("Средняя оценка в группе=%5.2f\n",avarage/n/3);puts("Нажмите любую клавишу для завершения...");_getch();return 0;}3.7 * ОбъединенияОбъединение – это средство описания области памяти, используемой для храненияпеременных разных типов.
Объединения позволяют хранить в разное время различныеданные или интерпретировать один и тот же набор битов по-разному.Объявление объединения напоминает объявление структуры:union <Имя объединения> {<Список элементов объединения>}[<Список переменных [и значений]>];Например:union mem// наложение полей (см. рисунок 3.14){double d;long l;int k[2];};k[0]k[1]ldРисунок 3.14 – Наложение описаний переменных в объединенииЭто объявление фактически объявляет новый тип – объединение под названием mem.После объявления можно объявлять переменные указанного типа, массив таких переменных и указатели на переменные данного типа. Чтобы объявить переменную, нужно либоуказать ее имя в конце объявления типа, либо применить отдельный оператор объявления,например:Оглавление75union mem comp,vfsun[10],*ptrun;В языке С++ не запрещается указывать перед этим объявлением ключевое словоunion, но это излишне, так как имя объединения полностью определяет его тип, например: Например:mem comp,vfsun[10],*ptrun;При объявлении переменной типа объединения компилятор автоматически выделяетпамять, достаточную для хранения наибольшего члена объединения.Для доступа к членам объединения используются те же синтаксические конструкции, что и для доступа к членам структуры.Объединения можно использовать для специального преобразования типов, поскольку к хранящимся в объединении данным можно обращаться разными способами.
Например, объединение можно использовать для манипуляции байтами, образующими значениевещественного числа, изменять его точность или выполнять необычное округление. Крометого, объединения, например, могут использоваться для выделения отдельных полей из одного длинного.3.8 Динамические структуры данных. СпискиДинамическими принято называть структуры данных, которые создаются в процессевыполнения программы. Понятие «создаются» можно интерпретировать по-разному:• создаются – в смысле «получают память и начинают реально существовать»;• создаются – в смысле «организуются, строятся из некоторых элементов».К первому типу относятся динамические массивы, строки и структуры, память подкоторые выделяется во время выполнения программы.
К структурам второго типа относятся списки.Список – структура, при организации которой использованы указатели, содержащиеадреса следующих элементов. Элемент списка состоит из двух частей: информационной иадресной. Информационная часть содержит поля данных. Адресная – включает от одногодо n указателей, содержащих адреса других элементов. Количество связей, между соседними элементами списка определяет его связность: односвязные, двусвязные, n-связные.По структуре списки бывают линейными, древовидными и сетевыми. На линейныхсписках обычно реализуют разные дисциплины обслуживания:• очередь – дисциплина обработки элементов данных, в которой добавление элементов выполняется в конец, а удаление – из начала;Оглавление76• стек – дисциплина обработки элементов данных, в которой добавление и удаление элементов осуществляется с одной стороны;• дек – дисциплина обработки элементов данных, в которой добавление и удалениеэлементов может выполняться с двух сторон.3.8.1 Описание элементов списковых структурДля описания элемента списковой структуры используют структуры, одно илинесколько полей которых – указатели на саму эту структуру.
Ниже приведены примерыописания элементов односвязного и двусвязного списков.Элемент односвязного списка:struct element // тип элемента{char name[16];// информационное поле 1char telefon[7]; // информационное поле 2element *p;// адрес следующего элемента};Элемент двусвязного списка:// тип элементаstruct element{char name[16];// информационное поле 1char telefon[7];// информационное поле 2element *prev;// адресное поле «предыдущий»element *next;// адресное поле «следующий»};3.8.2 Основные приемы работыСоздание списковой структуры предполагает:• описание элемента списка;• объявление указателей для работы со списком;• создание пустого списка;• добавление элементов к списковой структуре и удаление их из нее в процессе работы.Оглавление77Рассмотрим эти операции на конкретном примере.1. Описание элемента списка:struct element// тип на элемента{int num;// целое числоelement *p;// указатель на следующий элемент};2.
Описание переменной – указателя списка и нескольких переменных-указателей встатической памяти:element * first,*n,*f,*q;// адрес первого элемента// вспомогательные указатели3. Исходное состояние – «список пуст»:first=NULL;Добавление элементов в список. Возможно несколько вариантов добавления элементов к списку:• добавление элемента к пустому списку;• перед первым, например, при построении списка по типу стека;• после последнего, например, при построении списка по типу очереди;• после/перед заданным элементом, например при построении сортированногосписка.1 Добавление элемента к пустому списку:first=new element;// запросили память под элементfirst->num=5;// занесли данные в информационное полеfirst->p=NULL;// записали признак конца списка NULL2 Добавление элемента перед первым (по типу стека):q=new element;// запросили память под элементq->num=4;// занесли данные в информационное полеq->p=first;// записали в новый элемент адрес первогоfirst=q;// записали в качестве первого адрес нового элемента3 Добавление элемента после первого (по типу очереди):q=new element;// запросили память под элементq->num=4;// занесли данные в информационное полеq->p=NULL;// записали признак конца списка NULLfirst->p=q;// записали признак конца списка NULLОглавление78Удаление элемента из списка.
При удалении элемента из списка также возможныварианты:• удаление первого элемента;• удаление элемента с адресом q;• удаление последнего элемента.1. Удаление первого элементаq=first;// скопировали адрес первого элементаfirs=first->p;// запомнили адрес нового первого элементаdelete q;// удалили бывший первый элемент2. Удаление элемента с адресом q// скопировали адрес первого элементаf=first;while(f->p!=q) f=f->p; // нашли предыдущий элементq=q->p;// перешли к следующему элементуdelete f->p;// удалили элемент с адресом qf->p=q;// сменили адрес в предыдущем элементе3. Удаление последнего элементаf=q=first;// скопировали адрес первого элементаwhile(q->p!=NULL)// нашли последний и предыдущий элементы{f=q;q=q->p;}f->p=NULL;// объявили предыдущий элемент последнимdelete q;// удалили последний элементПример 3.8.
Написать программу, которая формирует список деталей, содержащийнаименование и диаметр детали. Удалить из списка все детали с диаметром, меньшим 1.#include <locale.h>#include <stdio.h>#include <conio.h>#include <string.h>struct zap// тип элемента{char det[10];float diam;zap *p;};Оглавление79int main(int argc, char* argv[]){setlocale(0,"russian");zap a,*r,*q,*f;r=new zap;r->p=NULL;puts("Вводите названия деталей и их диаметр:");scanf("%s %f\n",r->det,&r->diam);while( (scanf_s("\n%s",a.det,sizeof(a.det)-1 )),strcmp(a.det,"end")!=0 ){scanf("%f",&a.diam);q=r;r=new zap;strcpy(r->det,a.det);r->diam=a.diam;r->p=q;}// удаление записейq=r;do{if (q->diam<1){if( q==r){r=r->p;delete(q);q=q->p;delete(f->p);q=r;}else{}}else{f=q; q=q->p;Оглавлениеf->p=q;80}} while(q!=NULL);q=r;puts("Результаты:");if(q==NULL) puts("Данные отсутствуют.");elsedo{printf("%s %5.1f\n",q->det,q->diam);q=q->p;} while (q!=NULL);puts("Нажмите любую клавишу для завершения...");_getch();return 0;}Контрольные вопросы к главе 31.