Тема 6. Определяемые пользователем типы: структуры, объединения и поля
Перечисления
Перечисления – это набор именованных целочисленных констант. Перечисление задает конечное множество возможных значений, которые могут получать объекты перечисления. Вот формальное определение синтаксиса перечислений:
Как имя_типа_перечисления, так и список_переменных необязательны, но один из них обязательно должен присутствовать. Список_перечислений – это разделенный запятыми список идентификаторов. Имя_типа_перечисления используется для объявления переменных данного типа. В перечислениях каждому элементу ставится в соответствие целочисленное значение и поэтому перечисления можно использовать в любых выражениях. Например:
Если явно не проводить инициализацию, значение первого символа перечисления будет 0, второго – 1 и так далее.
Можно определить значения одного или нескольких символов, используя инициализатор. Это делается путем помещения за символом знака равенства целочисленного значения. При использовании инициализатора, символы, следующие за инициализационным значением, получают значение большее, чем указанное перед этим.
if (day==1) cout << Rus("Сегодня вторник") << endl;
tomorrow=++day;
if (tomorrow==wedday) cout << Rus("Завтра среда") << endl;
system("pause");
}
Использование элементов перечисления должно подчиняться следующим правилам:
1. Переменная может содержать повторяющиеся значения.
2. Идентификаторы в списке перечисления должны быть отличны от всех других идентификаторов в той же области видимости, включая имена обычных переменных и идентификаторы из других списков перечислений.
3. Имена типов перечислений должны быть отличны от других имен типов перечислений и структур в этой же области видимости.
4. Невозможен прямой ввод или вывод символов перечислений.
Структуры
Структура - определенный тип, представляющий собой поименованную совокупность компонент (элементов, полей структуры). В отличие от массива, все элементы которого однотипны, структура может содержать элементы разных типов.
Дополнительно, элементы структуры могут быть битовыми полями, которые другим способом недоступны.
В C++ структуры рассматриваются как класс. Это означает, что для компонент структуры могут быть определены спецификации доступа: public (по умолчанию), private и protected.
Структуры описываются с помощью ключевого слова struct:
struct [ имя_типа ]
{тип_1 элемент_1;
тип_2 элемент_2;
...
тип_n элемент_n;}
[ список_описателей ];
Элементы структуры называются полями структурыи могут иметь любой тип, кроме типа этой же структуры. Если отсутствует имя типа, должен быть указан список описателей переменных, указателей или массивов.В этом случае описание структуры служит определением элементов этого списка:
Struct
{
char Surname [25]:
илиchar* Surname;
int date, code;
double money;
} mas[200], *ps;
Если список отсутствует, описание структуры определяет новый тип, имя которого можно использовать в дальнейшем наряду со стандартными типами, например:
Struct Man
{ //описание нового типа Man
char Surname [25];
илиchar* Surname;
int date, code;
double money;
}; //описание заканчивается точкой с запятой
//определение массива типа Man и указателя на тип Man:
. . .
Man mas[200], *ps;
Для инициализации структуры значения ее элементов перечисляют в фигурных скобках в порядке их описания:
Struct
{
char Surname [25];
int date, code;
double money;
} Man = {"Иванов", 26, 119, 195000.5};
При инициализации массивов структур следует заключать в фигурные скобки каждый элемент массива (учитывая, что многомерный массив - это массив массивов):
Struct complex
{float Real, Im;}
compl [2][3] = {
{{1, 1}, {1, 1}, {1, 1}}, //строка 1, то есть массив compl[0]
{{2, 2}, {2, 2}, {2, 2}} //строка 2, то есть массив compl[1]
};
Доступ к полям структурывыполняется с помощью операций выбора “.” (точка) при обращении к полю через имя структуры и -> при обращении через указатель, например:
Man men, mas[200], *ps;
men.Surname = "Иванов";
mas[8].code = 119;
ps->money = 9500.55;
strcpy(men.Surname, "Иванов");
Пример:
#include <iostream.h>
#include <conio.h>
#include <windows.h>
char bufRus[256];
char* Rus(const char* text){
CharToOem(text, bufRus);
return bufRus;}
Struct date
{ int day;
int month;
int year;
char mon_name[8];
};
date d = { 4,10,2011,"окт"};
Void main ()
{ struct date *p;
cout << Rus("\nДоступ к структуре по имени: \n");
cout << d.day << "."<< d.month <<"." << d.year;
p = &d;
d.day=14;
p->year=2010;
strcpy(p->mon_name, "янв");
cout << Rus("\nДоступ к структуре по указателю: \n");
Если элементом структуры является другая структура, то доступ к ее элементам выполняется через две операции выбора:
struct A {int a; double x;};
struct B {A a; double x;} x[2], n, *pB;
...
x[0].a.a = 1; x[0].a.x = 13.54; x[0].x = 0.1;
pB=&n;
pB->a.a=4; pB->a.x=25.454; pB->x=0.35;
Как видно из примера, поля разных структур могут иметь одинаковые имена, поскольку у них разная область видимости. Более того, можно объявлять в одной области видимости структуру и другой объект (например, переменную или массив) с одинаковыми именами, если при определении структурной переменной использовать слово struct.
Перечислим операции, которые допустимы над структурами:
- доступ к элементу структуры с помощью операции "." (точка).
- доступ к элементу структуры по указателю с помощью операции "->" в виде: <указатель на структуру> -> <элемент_структуры>. Так, обращения pd->year и (*pd).year эквивалентны. Круглые скобки (*pd) необходимы, поскольку операция "." доступа к элементу структуры старше, чем "*";
- определение адреса структуры с помощью операции "&";
- инициализация структур внешнего и статического класса памяти;
- присваивание структуры как единого целого;
- передача структуры в качестве параметра функции и возвращение структуры в результате работы функции;
- передача отдельных компонент структуры в качестве аргументов функции;