Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
л_18_Структуры_объед.doc
Скачиваний:
0
Добавлен:
01.04.2025
Размер:
265.73 Кб
Скачать

Инициализация структурных переменных

Разрешается выполнять инициализацию полей структурной переменной при её определении. Например:

struct Book {char name[20]; //определение шаблона структуры

char title[44];

int year;

float price;

};

Book // инициализация структурных переменных при их определении first_book =

{“Mitchel M.”,

“Unesennie vetrom”,

2007,

20000 },

child_book =

{“Troepolskij G.”,

“Belij Bim Chernoe Ucho”,

2006,

10000},

dog_book =

{…..};

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

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

Как мы видели, поле структурной переменной может иметь любой тип, в том числе и быть другой структурой. В качестве членов структуры можно объявлять массивы других структур.

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

struct UDC {char class, subclass; int number;};

struct Book { struct UDK udc_class;

char name [20];

chat title[44];

int year;

float price;

} first_book, child_book, dog_book;

Ссылка на поле вложенной структуры формируется из имени структурной переменной, имени структурного поля и имени вложенной структуры. Перечисленные имена разделяются символом «точка». Например:

first_book.udc_class.class = ‘A’; // (first_book.udc_class).class.

dog_book.udc_class.number =681;

Теоретически не существует ограничения на величину уровня вложенности структур.

В отношении полей структурного типа существует только одно существенное ограничение – поле не может иметь тот же тип, что и определяемый структурный тип, однако оно может иметь тип указателя на этот тип.

Например:

struct Book { Book my_s; //это ошибка !!!!!

char name[20];

char title[44];

int year;

float price;

};

struct Book { Book* my_s; //OK!!!!!

char name[20];

char title[44];

int year;

float price;

};

Пусть имеем вложенные структуры:

struct Distance //длина в километрах и метрах

{ int km, m;

};

struct Pole //размеры прямоугольного поля

{ Distance length;

Distance width,

};

Тогда инициализация структурной переменной типа Pole выглядит так:

Pole pole = { {2, 20}, {1, 5}};

Операции над структурными переменными

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

if (strcmp(first_book.name, “Mitchel M.”) == 0)…….

if(first_book.year%4==0)…

first_book.name[0] = lower(first_book.name[0]);

strcpy (first_book. name, “Mitchel M.”); //поле-строка получает значение !!!!!

strcpy (first_book. title, “Unesennie vetrom”);

cin >> child_book.title; //поле- строка получает значение !!!!!

first_book. year = 2007;

cin >> first_book. price;

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

Непосредственно сравнивать две структурные переменные (даже одного типа) нельзя. Сравнивать можно только члены структур. Например:

struct { int a;

int b;

} v1, v2;

if ((v1.a == v2.a) && (v1.b == v2.b)) cout << “переменные равны”;

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

first_book = child_book;

first_book = child_book = dog_book;

!!! Для определения прямоугольных областей можно использовать предопределенную в заголовочном файле windows.h структуру RECT, соответствующую приведенной выше структуре Rectangle:

#include <windows.h>

RECT r1, r2 = { 2, 6, 4, 2 }, r3;

r1.left = 1;

r1.top = 5;

r1.right = 3;

r1.bottom = 1;

r3 = r1;

cout<< r3.left << endl;

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

НО!!! Поверхностное копирование полей-указателей может стать источником ошибок в дальнейшей работе. Если в структуре есть поля-указатели, то после присваивания будет существовать больше одной структурной переменной, поля которой указывают на одну и ту же область памяти.!!!

Если два структурных типа «закольцованы» (поля одного структурного типа объявляются через другой структурный тип и наоборот):

struct A { B *pb;};

struct B { A *pa;};

то допустимо использовать предварительное неполное определение любого из типов:

struct B; // предварительное неполное определение типа B;

struct A { B *pb;};

struct B { A *pa;};

В данном случае предварительное неполное определение структурного типа B допустимо использовать в определении структурного типа A, так как определение указателя pb на структуру типа B не требует сведений о размере структуры типа B.

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

Выражение (*ptr_date).year представляет собой обращение к элементу year структуры, связанной с указателем ptr_date. Нельзя опускать скобки в этом выражении, так как приоритет операции точка (.) выше, чем операции доступ по указателю (*).

Для вложенных структур доступ к полям структурной переменной через указатель реализуется следующим образом: p->q->mem, что равносильно (p->q) -> mem (поскольку операции -> и . выполняются слева направо). Аналогично, выражение stud. birthdate. month означает (stud. birthdate). month.