Работа со структурами. Вложенные структуры. Массивы структур

Цель работы

Освоить правила объявления шаблона структуры, определения по заданному шаблону структурной переменной или массива структурных переменных. Изучить способы доступа к полям структурной переменной, в том числе через указатель на эту переменную. Освоить способы обработки массивов структурных переменных.

Задание 1

Предложить структуру для описания указанных в вариантах данных. Организовать заполнение полей структурной переменной введенными с клавиатуры значениями. Использовать два способа доступа к полям структуры: через ссылку, содержащую имя структурной переменной и имя поля, и через указатель.

Варианты структур для выполнения работы:

1. ''Человек'': ФИО; пол; домашний адрес (город, улица, дом, квартира); номер телефона.

2. ''Студент'': ФИО; группа; дата рождения (год, месяц, число); домашний адрес (строкой).

3. ''Владелец автомобиля'': ФИО; автомобиль (марка, цвет, гос. номер); номер авт. прав; отделение регистрации ГИБДД.

4. ''Пациент'': ФИО; год рождения; домашний адрес (почтовый индекс, страна, город, улица, дом, квартира); номер телефона.

5. ''Спортивная команда'': название; город команды; количество игроков; результаты игр (выиграно, проиграно, вничью).

6. ''Покупатель'': ФИО; пол; адрес: (город, улица, номер дома, номер квартиры); номер кредитной карточки.

7. ''Автомобиль'': марка; цвет; номера (номер двигателя; гос. регистрационный номер); год выпуска.

8. ''Фильм'': название; режиссер (фамилия, имя, национальность); год выпуска; жанр.

9. ''Музыкальный товар'': порядковый номер в каталоге; название; исполнитель; количество на складе (mp3, CD, DVD).

10. ''Музыкальный альбом'': название альбома; название группы; количество песен на носителе; выпуск (год выпуска, фирма-производитель, тираж).

Задание 2

Используя выполненное задание 1, сформировать в программе одномерный динамический массив структур, организовать заполнение элементов массива с клавиатуры, при этом вести диалог с пользователем о необходимости продолжать ввод. После заполнения массива структур упорядочить его по заданному полю. Например, упорядочить государства по численности населения или в алфавитном порядке.

Методические указания к выполнению заданий

Структурные переменные, или просто структуры, - это объединение одной или более переменных, возможно разных типов, в одну область памяти, имеющую для простоты одно имя. Отдельные составные части одной переменной называются полями.

Термин структура в языке С\C++ соответствует двум разным по смыслу понятиям:

1. обозначение места в памяти, где располагается информация; далее это место называется структурной переменной;

2. правила формирования структурной переменной, используемые компилятором для выделения ей места памяти и организации доступа к полям; далее такие правила называются шаблоном (pattern) структуры.

Как и любая переменная, структурная переменная должна быть описана. Описание состоит из 2 шагов:

1. задание шаблона структуры;

2. собственно описание структурной переменной.

Каждый шаблон имеет собственное имя для того, чтобы компилятор мог различать различные шаблоны. В том случае, если в функции исполняется единственный шаблон, он может иметь имя «нет_имени», что задается пропуском pattern_name при описании шаблона. Имена шаблонов должны быть уникальными в пределах их области определения.

Синтаксис задания шаблонов:

struct pattern_name {

type1 field_name1;

type2 field_name2;

...

typen field_namen;

};

где pattern_name - имя шаблона, удовлетворяющее правилам задания идентификаторов языка С\C++; type1, type2, typen - любые типы, например: int, char, float; field-name1, field-name2, field_namen - имена полей, удовлетворяющие правилам задания идентификаторов языка С\C++.

Например:

struct BOOK {

char name[20];

char title[44];

int year;

float price;

};

Имена полей в одном шаблоне должны быть уникальными. Однако в разных шаблонах можно использовать совпадающие имена полей. Кроме того, имена шаблонов проверяются на уникальность друг с другом, а не с метками или именами переменных.

Как и простая переменная, шаблон имеет область определения (видимости). Если шаблон описан внутри блока { } - это локальный шаблон, видимый только из пределов данного блока, в частности из пределов конкретной функции. Если описание шаблона помещено вне блоков, такой шаблон видим во всех функциях ниже точки описания шаблона до границы файла. Нельзя описать шаблон с реквизитами extern.

Когда задан шаблон, может быть описана структурная переменная. Описание структурной переменной состоит из задания типа и имени структурной переменной.

Например:

struct BOOK first_book;// здесь описывается структурная переменная по приведенному ранее шаблону BOOK.

Компилятор выделит под переменную число байтов памяти, достаточное для хранения всех ее полей. В данном случае это 70 байт. Число байтов, выделенное под структурную переменную, не всегда равно сумме длин отдельных полей из-за влияния дополнительного фактора внутреннего представления структурных переменных, называемого выравниванием. Точно выделенное число байтов всегда возвращает операция sizeof(struct pattern_name).

Например: sizeof (struct BOOK)

Синтаксис языка С\C++ разрешает совмещать описание шаблона и структурной переменной.

Например:

struct BOOK {

char name [20];

char title [44];

int year;

float price;

} first_book, child_book;

Для доступа к отдельным полям структурной переменной исполняют операцию ’.’ , формируя ссылку на нужное поле из имени структурной переменной и имени нужного поля. Такая ссылка может располагаться в любом месте выражений, где допустимы ссылки на простые переменные.

Например:

first_book.year = 1992;

strcopy ( child_book.title, "Белый Бим Черное ухо");

scanf ( "%f ", &first_book.price);

Ссылка на поле структурной переменной обладает всеми свойствами обычных переменных. Если поле - массив символов, как, например child_book.title, - это указатель-константа на первый элемент массива.

Можно определить адрес первого байта поля структурной переменной обычной операцией взятия адреса. Например: &first_book.price - адрес первого байта поля. Если структура переменных соответствует одному шаблону, допускаются операции присваивания таких структур переменных.

Например: first_book = child_book;

Эта операция приводит к физической пересылке в памяти числа байтов, равного размеру шаблона структурной переменной.

При описании структурной переменной разрешается выполнять инициализацию полей переменной.

Например:

struct BOOK first_book={"Митчелл М.","Унесенные ветром",1991,5.25},

child_book={"Троепольский Г.Н.","Белый Бим Черное Ухо",1980,2.78};

Разрешается объединять задание шаблона, описание структурных переменных и их инициализацию в одном предложении.

Для упрощения описания структурных переменных можно исполнять оператор typedef описания собственного типа данных. Это упрощает текст программы и экономит силы на повторный набор слова struct при описании структурных переменных. Общая форма конструирования собственного типа данных:

typedef описание_типа имя_нового_типа;

Например:

typedef struct BOOK {

char name [20];

char title [44];

int year;

float price;

} MY_BOOKS;

Затем можно использовать созданный тип для описания необходимых данных, например: MY_BOOKS dog_book, child_book;

Поле структурной переменной может иметь любой тип, в том числе и быть другой структурой. В этом случае его называют вложенной структурой. Шаблон вкладываемой структуры должен быть уже известен компилятору.

Например:

struct UDC {

char class_, subclass;

int number;

};

struct BOOK {

char name [20];

char title [44];

struct UDC udk_class;

int year;

float price;

} first_book, child_book;

Ссылка на поле вложенной структуры формируется из имени структурной переменной, имени структурного поля и имени поля вложенной структуры. Перечисленные имена разделяются символом ‘.’ (операция точка).

Например:

first_book.udc_class='A';

child_book.udc_class.number=681;

Структура не может вкладываться сама в себя. Разрешается использовать описываемый шаблон, если одно из полей является указателем на описываемую структуру.

Например:

struct BOOK {

struct BOOK *my_own;

char name[20];

char title[40];

int year;

float price;

};

Описание шаблона структуры вводит по существу новый тип. Раз так, то ничего не мешает использовать указатель на введенный тип. Для доступа к полям структурной переменной через указатель используется операция ®. Пример описания указателя на структурную переменную, инициализации указателя и его исполнения для ссылки на отдельные поля структурной переменной:

struct UDC {

char subclass;

int number;

};

struct BOOK {

struct UDC udc_class;

char name[20];

char title[44];

int year;

float price;

};

struct BOOK *ptr_book, first_book;

ptr_book=&first_book;

ptr_book->year = 1992;

ptr_book->udc_class.subclass='A';

ptr_book->udc_class.number=681;

scanf ("%d", &ptr_book->price);

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

Для доступа к полям вложенной структуры используют сначала ®, а затем ссылку на поле вложенной структуры операции.

Например: ptr_book->udc_class.subclass='A';

Используя указатель на структурную переменную можно сделать ссылку на поле любого типа, в том числе, например, на указатель. Пример доступа к полям структуры с исполнением указателя на структуру UDC, являющегося полем структуры BOOK:

struct UDC {

char subclass;

int number;

} my_class;

struct BOOK {

struct UDC *udc_class;

char name [20];

char title[44];

int year;

float price;

};

struct BOOK *ptr_book, first_book;

ptr_book=&first_book;

ptr_book->udc_class=&my_class;

ptr_book->year=1992;

ptr_book->udc_class->subclass='A';

ptr_book->udc_class->number=681;

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

По заданному шаблону структуры можно описывать массивы структурных переменных.

Например:

typedef struct {

char name[20];

char title[44];

int year;

float price;

} BOOKS;

BOOKS library[25];

Доступ к элементам массива может осуществляться с использованием индекса или через указатель-константу, которым является имя массива.

Например:

library[i].year = 28;

(*(library + i)).year = 28;

(library + i)-> year = 28;

Если описать рабочий указатель и инициализировать его адресом первого элемента массива:

BOOKS library[25], *ptr = library;

то для доступа к i-му элементу массива используем указатель ptr:

(ptr + i) ® year = 28;

Продвижение указателя ptr операцией ++ или -- соответственно увеличивает или уменьшает его на размер типа BOOKS, то есть устанавливает на следующий элемент массива структурных переменных вперед или назад.

Наши рекомендации