Студопедия

Главная страница Случайная страница

КАТЕГОРИИ:

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






Типы данных, определяемые пользователем






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

Переименование типов (typedef)

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

typedef тип новое_имя [ размерность ];

В данном случае квадратные скобки являются элементом синтаксиса. Размерность может отсутствовать. Примеры:

typedef unsigned int UINT;

typedef char Msg[100];

typedef struct{

char fio[30];

int date, code;

double salary; } Worker;

Введенное таким образом имя можно использовать таким же образом, как и имена стандартных типов:

UINT i, j; // две переменных типа unsigned int

Msg str[10]; // массив из 10 строк по 100 символов

Worker staff[100]; // массив из 100 структур

Кроме задания типам с длинными описаниями более коротких псевдонимов, typedef используется для облегчения переносимости программ: если машинно-зависимые типы объявить с помощью операторов typedef, при переносе программы потребуется внести изменения только в эти операторы.

Перечисления(enum)

При написании программ часто возникает потребность определить несколько именованных констант, для которых требуется, чтобы все они имели различные значения (при этом конкретные значения могут быть не важны). Для этого удоб­но воспользоваться перечисляемым типом данных, все возможные значения ко­торого задаются списком целочисленных констант. Формат:

enum [ имя_типа 3 { список_констант };

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

enum Err {ERR_READ, ERR_WRITE, ERR_CONVERT};

Err error;

switch (error){

case ERR_READ; /* операторы */ break;

case ERR_WRITE; /* операторы */ break;

case ERR_CONVERT: /* операторы */ break; }

Константам ERRREAD, ERR_WRITE, ERR_CONVERT присваиваются значения 0, 1 и 2 соответственно.

Другой пример:

enum {two = 2, three, four, ten = 10, eleven, fifty = ten + 40};

Константам three и four присваиваются значения 3 и 4, константе eleven — 11.

Имена перечисляемых констант должны быть уникальными, а значения могут совпадать. Преимущество применения перечисления перед описанием именованных констант и директивой #define (см. раздел «Директива #define») состоит в том, что связанные константы нагляднее; кроме того, компилятор при инициализации констант может выполнять проверку типов.

При выполнении арифметических операций перечисления преобразуются в целые. Поскольку перечисления являются типами, определяемыми пользователем, для них можно вводить собственные операции (см. «Перегрузка операций»).

ПРИМЕЧАНИЕ

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

Структуры (struct)

В отличие от массива, все элементы которого однотипны, структура может содержать элементы разных типов. В языке C++ структура является видом класса и обладает всеми его свойствами, но во многих случаях достаточно использовать структуры так, как они определены в языке С:

struct [ имя типа ] {

тип_1 элемент_1;

тип_2 элемент_2;

тип_n элемент_n;

} [ список_описателей ];

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

// Определение массива структур и указателя на структуру:

struct {

char fio[30];

int date, code;

double salary;

}staff[100], *ps;

Если список отсутствует, описание структуры определяет новый тип, имя которого можно использовать в дальнейшем наряду со стандартными типами, например:

struct Workerf // описание нового типа Worker

char fio[30]; int date, code;

double salary;

};

// описание заканчивается точкой с запятой

// определение массива типа Worker и указателя на тип Worker:

Worker staff[100], *ps;

Имя структуры можно использовать сразу после его объявления (определение можно дать позднее) в тех случаях, когда компилятору не требуется знать размер структуры, например:

struct List; // объявление структуры List

struct Link{

List *p; // указатель на структуру List

Link *prev, *succ; // указатели на структуру Link

};

struct List { /* определение структуры List */};

Это позволяет создавать связные списки структур.

Для инициализации структуры значения ее элементов перечисляют в фигурных скобках в порядке их описания:

struct{

char fio[30];

int date, code;

double salary;

}worker = {" Страусенко", 31, 215, 3400.55};

При инициализации массивов структур следует заключать в фигурные скобки каждый элемент массива (учитывая, что многомерный массив — это массив массивов):

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]

};

Для переменных одного и того же структурного тина определена операция присваивания, при этом происходит поэлементное копирование. Структуру можно передавать в функцию и возвращать в качестве значения функции. Другие операции со структурами могут быть определены пользователем (см. «Перегрузка операций»). Размер структуры не обязательно равен сумме размеров ее элементов, поскольку они могут быть выровнены по границам слова.

Доступ к полям структуры выполняется с помощью операций выбора. (точка) при обращении к полю через имя структуры и -> при обращении через указатель, например:

Worker worker, staff[100], *ps;

worker.fio = " Страусенко";

staff[8].code - 215;

ps-> salary = 0.12;

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

struct A {int a; double x; };

struct В {A a; double x; } х[2];

х[0].а.а = 1;

х[1].х = 0.1;

Как видно из примера, поля разных структур могут иметь одинаковые имена, поскольку у них разная область видимости. Более того, можно объявлять в одной области видимости структуру и другой объект (например, переменную или массив) с одинаковыми именами, если при определении структурной переменной использовать слово struct, но не советую это делать — запутать компилятор труднее, чем себя.


Поделиться с друзьями:

mylektsii.su - Мои Лекции - 2015-2024 год. (0.009 сек.)Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав Пожаловаться на материал