Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология
Образование Политология Производство Психология Стандартизация Технологии


ГЛАВА 13. Структуры, объединения, перечисления



В реальных задачах информация, которую требуется обрабатывать, может иметь достаточно сложную структуру. Для ее адекватного представления используются типы данных, построенные на основе базовых типов данных, массивов и указателей. Языки высокого уровня позволяют программисту определять свои типы данных и правила работы с ними, т.е. типы, определяемые пользователем. В языке Си к ним относятся структуры, объединения и перечисления. Рассмотрим их более подробно.

 

Структуры

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

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

– структура – это обозначение участка оперативной памяти, где располагаются конкретные значения данных; в дальнейшем – это структурная переменная, поля которой располагаются в смежных областях ОП;

– структура – это правила формирования структурной переменной, которыми руководствуется компилятор при выделении ей места в ОП и организации доступа к ее полям.

Определение объектов типа структуры производится за два шага:

– декларация структурного типа данных, не приводящая к выделению участка памяти;

– определение структурных переменных объявленного структурного типа с выделением для них памяти.

 

Декларация структурного типа данных

Структурный тип данных задается в виде шаблона, общий формат описания которого следующий:

struct ID структурного типа {

описание полей

};

Атрибут «ID структурного типа» является необязательным и может отсутствовать. Описание полей производится обычным способом: указываются типы переменных и их идентификаторы.

Пример определения структурного типа

Необходимо создать шаблон, описывающий информацию о студенте: номер группы, Ф.И.О. и средний балл. Один из возможных вариантов:

struct Stud_type {

char Number[10];

char Fio[40];

double S_b;

};

Поля одного типа при описании можно объединять в одну группу:

struct Stud_type {

char Number[10], Fio[40];

double S_b;

};

Размещение данного объекта типа Stud_type в ОП схематически будет выглядеть следующим образом:

 

Number Fio S_b
10 байт 40 байт 8 байт

 

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

Примеры групповых операций:

– захват и освобождение памяти для объекта;

– запись и чтение данных, хранящихся на внешних носителях как физические и/или логические записи с известной структурой (при работе с файлами).

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

struct Stud_type {

char *Number, *fio;

double S_b;

};

В данном случае, вводя строки Number и fio различной длины, размеры объектов будут также различны.

 

Создание структурных переменных

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

Способ 1. В любом месте программы для декларации структурных переменных, массивов, функций и т.д. используется объявленный в шаблоне структурный тип, например:

struct Stud_type student; – структурная переменная;

Stud_type Stud[100]; – массив структур

Stud_type *p_stud; – указатель на структуру

Stud_type* Fun(Stud_type); – прототип функции с параметром структурного типа, возвращающей указатель на объект структурного типа.

Способ 2. В шаблоне структуры между закрывающейся фигурной скобкой и символом «;» указывают через запятые идентификаторы структурных данных.

Для нашего примера можно записать:

struct Stud_type {

char Number[10], Fio[40];

double S_b;

} student, Stud[100], *p_stud;

Если дальше в программе не понадобится вводить новые данные объявленного структурного типа, идентификатор Stud_type можно не указывать.

При декларации структурных переменных возможна их одновременная инициализация, например:

struct Stud_type {

char Number[10], Fio[40];

double S_b;

} student = {"123456", "Иванов И.И.", 6.53 };

или:

Stud_Type stud1 = {"123456", "Иванов И.И." };

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

Некоторые особенности:

1) поля не могут иметь атрибут, указывающий «класс памяти», данный атрибут можно определить только для всей структуры;

2) идентификаторы полей могут совпадать с идентификаторами других объектов программы, т.к. шаблон структуры обладает собственным пространством имен;

3) при наличии в программе функций пользователя шаблон структуры рекомендуется поместить глобально перед определениями всех функций и в этом случае он будет доступен всем функциям.

Обращение к полям структур

Обращение к полям структур производится путем создания составных имен, которые образуются двумя способами:

1) при помощи операции принадлежности (.) общий вид которой

ID_структуры . ID_поля

или

(*указатель_структуры) . ID_поля

2) при помощи операции косвенной адресации (–>) в виде

указатель_структуры –> ID_поля

или

(&ID_структуры) –> ID_поля

Если в программе созданы объекты объявленного ранее шаблона:

Stud_Type s1, *s2;

то к полям объекта s1 можно обратиться следующим образом:

s1. Number, s1. Fio, s1. S_b;

или

(&s1) –> Number, (&s1) –> Fio, (&s1) –> S_b;

а к полям объекта, адрес которого s2:

s2 –> Number, s2 –> Fio, s2 –> S_b;

или

(*s2) . Number, (*s2) . Fio, (*s2) . S_b;

 

Вложенные структуры

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

Например, в структуре Person, содержащей сведения – ФИО, дата рождения, сделать дату рождения внутренней структурой date по отношению к структуре Person. Тогда шаблон такой конструкции будет выглядеть так:

struct date {

int day, month, year;

};

struct Person {

char fio[40];

struct date f1;

};

Объявляем переменную и указатель на переменные такой структуры:

struct Person a, *p;

Инициализируем указатель p адресом переменной а:

p = &a;

Тогда обращение к полям структурной переменной a будет выглядеть следующим образом:

a . fio a. f1 . day a . f1 . month a . f1 . year

или

p–>fio p–>f1.day p–>f1.month p–>f1.year

Можно в качестве связи с вложенной структурой использовать указатель на нее:

struct date {

int day, month, year;

};

struct Person {

char fio[40];

struct date *f1;

};

Тогда обращение к полям будет следующим:

a .fio a.f1–>day a.f1–>month a.f1–>year

или

p–>fio p–>f1–>day p–>f1–>month p–>f1–>year

 

Массивы структур

Структурный тип «struct ID_структуры», как правило, используют для декларации массивов, элементами которых являются структурные переменные. Это позволяет создавать программы, оперирующие с простейшими базами данных.

Например, массив структур, объявленного ранее типа:

struct Person spisok[100];

причем ключевое слово struct можно не писать. Декларацию массива можно выполнить и в описании шаблона следующим образом:

struct Рerson {

char fio[40];

int day, month, year;

} spisok[100];

В данном случае обращение к полю, например, day элемента массива с индексом i может быть выполнено одним из следующих способов:

spisok[i].day=22; *(spisok+i).day=22; (spisok+i)–>day=22;

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

struct Spisok {

char Fio[20];

double S_Bal;

};

// Описание прототипов функций пользователя

void Out(int, Spisok);

void In(int, Spisok *);

void main(void)

{

Spisok Stud[50], *sved;

. . .

for(i=0;i<N;i++)

Vvod(i, &Stud[i]);

puts("\n Spisok Students");

for(i=0;i<N;i++)

Out(i+1, Stud[i]);

. . .

}

// Функция вывода на экран данных одного элемента структуры

void Out(int nom, Spisok dan) {

printf("\n %3d – %20s %4.2lf ",nom, dan.Fio, dan.S_Bal);

}

// Функция ввода данных одного элемента структуры

void In (int nom, Spisok *sved) {

printf("\n Введите сведения %d : ", nom+1);

fflush(stdin);

puts("\n ФИО – ");

gets(sved–>Fio);

puts("\n Средний балл – ");

scanf(“%lf”, &sved–>S_Bal);

}

 






Читайте также:

Последнее изменение этой страницы: 2016-03-16; Просмотров: 113; Нарушение авторского права страницы


lektsia.com 2007 - 2017 год. Все права принадлежат их авторам! (0.092 с.) Главная | Обратная связь