Массивы структур
Использование typedef
Вложенные структуры
Обращение к полям структур
Обращение к элементам структур производится посредством:
а) операции принадлежности (.) в виде:
имя_структуры_или_объединения.имя_элемента
или
(*указатель_структуры_или_объединения).имя_элемента
б) операции косвенной адресации (->) в виде:
указатель_структуры_или_объединения -> имя_элемента
Например:
Объявляем переменную и указатель на переменные структуры
Stud_Type s1, *s2;
обращаемся к полям структуры:
s1. Number;
s1. Fio;
s1. 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
Использование typedef упрощает определение структурных переменных, например:
typedef struct person
{
char fio[40];
int day, month, year;
} W;
здесь W - созданный пользователем тип данных - структура с указанными полями, и для нашего примера:
W t1, t2; - декларация двух переменных t1, t2 типа W.
Структурный тип может быть использован для декларации массивов, элементами которых являются структурные переменные, например:
struct person spisok[100]; - spisok - массив структур;
или
struct person
{
char fio[40];
int day, month, year;
} spisok[100];
В данном случае обращение к полю, например, day i -й записи может быть выполнено одним из следующих способов:
spisok[i].day *(spisok+i).day (spisok+i) -> day.
При анализе размеров структурных переменных иногда число байт, выделенных компилятором под структурную переменную, оказывается больше, чем сумма байт ее полей. Это связано с тем, что компилятор выделяет участок памяти для структурных переменных с учетом выравнивания, добавляя между полями пустые байты по следующим правилам:
структурные переменные, являющиеся элементами массива, начинаются на границе слова, т.е. с четного адреса;
любое поле структурной переменной начинается на границе слова, т.е. с четного адреса и имеет четное смещение по отношению к началу переменной;
при необходимости в конец переменной добавляется пустой байт, чтобы общее число байт было четное.
Некоторые особенности:
1. поля структуры, как правило, имеют разный тип, кроме функций, файлов и самой этой структуры;
2. поля не могут иметь атрибут класс памяти, данный атрибут можно определить только для всей структуры;
3. идентификаторы как самой структуры, так и ее полей могут совпадать с идентификатарами других объектов программы, т.к. шаблон структуры обладает собственным пространством имен;
4. при наличии в программе функций пользователя шаблон структуры рекомендуется поместить глобально перед определениями всех функций, в этом случае он будет доступен всем функциям.
5. Элементы структур в общем случае размещаются в памяти последовательно с учетом выравнивания начальных адресов. Выравнивание - установка значения адреса, кратного некоторой величине, определяемой собенностями адресации данных на аппаратном уровне.
Пример на использование структур
Вести сведения о студентах учебной группы (не более 50):
а) фамилию и имя;
в) итоги сдачи экзаменов – три оценки.
В программе расчитать средний балл для каждого студента, выполнить поиск по первой букве фамилии, поиск нужной записи.
Текст программы может иметь вид:
#include <iostream.h>
#include <stdio.h>
#include <string.h>
#include <conio.h>
struct Spisok {
char Fio[20];
int Ot[3];
float S_Bal;
} *sved;
void Vvod(int nom,struct Spisok *sved)
{ cout << "\n Vvedi svedenia " << (nom+1);
cout << "\n FIO - "; gets(sved->Fio);
float s=0;
for(int i=0;i<3;i++) {
cout << "\n Otcenki - "; cin >> sved->Ot[i];
s+=sved->Ot[i];
}
sved->S_Bal=s/3.;
return; }
void main(void)
{ struct Spisok Stud[50]; int i,N; char Bukva;
clrscr();
cout << "\n Vvedi kol-vo < 50 "; cin >> N;
for(i=0;i<N;i++) Vvod(i,&Stud[i]);
cout << "\n Spisok Students";
for(i=0;i<N;i++)
printf("\n %20s %4.2f",Stud[i].Fio,Stud[i].S_Bal);
cout << "\n Poisk FIO (bukva) "; cin >> Bukva;
cout << "\n Sveden Students";
int kod_p=0;
for(i=0;i<N;i++)
if(Stud[i].Fio[0]==Bukva){ kod_p=1;
printf("\n %20s %4.2f",Stud[i].Fio,Stud[i].S_Bal); }
if(kod_p==0) cout << " Takix HET!";
cout << "\n Poisk zapisi";
Vvod(-1,sved);
kod_p=0;
for(i=0;i<N;i++)
if(memcmp(sved,&Stud[i],sizeof(sved))==0)
{ kod_p=1;
printf("\n %20s %4.2f",Stud[i].Fio,Stud[i].S_Bal);
}
if(kod_p==0) cout << " Takix HET!";
getch();
}