Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ОИВТ_Ч1.doc
Скачиваний:
8
Добавлен:
07.11.2018
Размер:
1.27 Mб
Скачать

4.10.Структурированные типы данных

4.10.1.Перечисление

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

Пусть идентификатор времена года (seasons) может принимать одно из четырех значений: весна, лето, осень, зима (spring, summer, autumn, winter), тогда пример будет выглядеть так:

enum seasons{spring, summer, autumn, winter} p,w;

В примере переменные p,w могут принимать одно из четырех значений времени года. После введения типа seasons можно объявлять переменные (объекты) данного типа, например enum seasons a,b,c;

Введем еще одно объявление:

enum days {mon, tues, wed, thur, fri, sat,sun} my_week;

Имена, занесенные в days, представляют собой константы целого типа. Первая из них (mon) автоматически устанавливается в нуль, и каждая следующая имеет значение на единицу больше, чем предыдущая (tues=1, wed=2 и т.п.). Можно присвоить константам определенные значения целого типа (именам, не имеющим их, будут, как и раньше, назначены значения предыдущих констант, увеличенные на единицу). Например:

enum days {mon=5, tues=8, wed=10, thur, fri, sat} my_week;

После этого mon=5, tues=8, wed=10, thur=11, fri=12, sat=13, sun=14.

Тип enum можно использовать для задания констант true = 1 false = 0, например enum t_f {false true} a, b;

К сожалению, контроль за соответствием значений констант, присваемых переменным типа enum, не осуществляется.

void main (void)

{enum my_en {a, b=10, c,d};

my_en i1, i2,i3; //введенный тип my_en можно использовать для объявления переменных

enum vit {r, l, m=10} j1, j2;

// правильные действия

i1=a; i2=b; i3=a; j1=j2;

//некорректные действия, действия выполняются но вызывают выдачу сообщений

i1=0; i1=555; i1=r;

//ошибочные действия

// a=b; a=j1; a=i1; a=0; b=10;

}

4.10.2.Массивы

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

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

int a [100]; массив а из 100 элементов целого типа : а[0], a[1],.…, a[99] (индексация всегда начинается с нуля).

char b [30];

float c [42]; - элементы массива b имеют тип char, а с – float.

Двухмерный массив представляется как одномерный, элементы которого тоже массивы. Например, объявление char а[10][20]; задает двумерный массив символов. По аналогии можно установить и большее число измерений. Элементы двухмерного массива хранятся по строкам, т.е. если проходить по ним в порядке их расположения в памяти, то быстрее всего изменяется самый правый индекс. Например, обращение к девятому элементу пятой строки запишется так: а[5][9]. Пусть задано объявление: int a[2][3]; Тогда элементы массива а будут размещаться в памяти следующим образом: а[0][0], а[0][1] а[0][2], а[1][0], а[1][1], а[1][2]. Имя массива а – это указатель константы, которая содержит адрес его первого элемента ( для нашего примера – а[0][0] ). Предположим, что а=1000. Тогда адрес элемента а[0][1] будет равен 1002 (элемент типа int занимает в памяти 2 байта), адрес следующего элемента а[0] [2] – 1004 и т.п. Что же произойдет, если вы выберете элемент, для которого не выделена память. К сожалению, компилятор не следит за этим. В результате возникнет ошибка, и программа будет работать не верно.

В языке С существует сильная взаимосвязь между указателями и массивами. Любое действие, которое достигается индексированием массива, может быть выполнено и с помощью указателей, причем последний вариант будет быстрее. Объявление int а [5]; определяет массив из пяти элементов: а[0], а[1], а[2], а[3], а[4]. Если объект у объявлен как int *у; то оператор y=&a[0]; присваивает переменной у адрес элемента а[0]. Если переменная у указывает на текущий элемент массива а, то у+1 указывает на следующий элемент, причем здесь выполняется соответствующее масштабирование для приращения адреса с учетом длины объекта (для типа int – 2 байта, long – 4 байта, double – 8 байт и т.п.). Поскольку само имя массива есть адрес его нулевого элемента, то инструкцию у=&а[0]; можно записать и в другом виде: у=а;. Тогда элемент а[i] можно представить как *(а+i). С другой стороны, если у – указатель, то следующие две записи y[i] и *(y+i) эквивалентны. Между именем массива и соответствующим указателем есть одно важное различие. Указатель – это переменная и у=а; или у++; -допустимые операции. Имя же массива – константа, поэтому конструкции вида а=у; а++; использовать нельзя, так как значение константы постоянно и не может быть изменено.

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

Если указатели адресуют элементы одного массива, то их можно сравнивать (отношения вида: <, >, = =, ! = и др. работают правильно).

В то же время нельзя сравнивать либо использовать в арифметических операциях указатели на разные массивы (соответствующие выражения не приводят к ошибкам при компиляции, но в большинстве случаев не имеют смысла). Как и выше, любой адрес можно проверять на равенство или неравенство со значением NULL. Указатели на элементы одного массива можно также вычитать. Тогда результатом будет число элементов массива, расположенных между уменьшаемым и вычитаемым объектами.

Язык С позволяет инициализировать массив при объявлении. Для этого используется такая форма:

тип имя_массива [ ] [ ] = { список значений };

Рассмотрим примеры:

int a[5] = {0,1,2,3,4};

char с[7] = { 'a','b','c','d','e','f','g'};

int b [2] [3]= {1,2,3,4,5,6};

В последнем случае: b[0][0] = 1, b[0][1] = 2, b[0][2] = 3, b[1][0] = 4,

b[1][1] = 5, b[1][2] = 6.

В языке допускаются массивы указателей, которые объявляются, например, следующим образом: char *m[5]; . Здесь [m] – массив, содержащий адреса элементов типа char.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]