Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Tekhnologia_programmirovania.pdf
Скачиваний:
182
Добавлен:
08.04.2015
Размер:
1.76 Mб
Скачать

176

Глава 14. Структуры, перечисления, объединения

14.1. Объявление структур

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

Для моделирования точек на плоскости, рис.59, можно использовать следующую структуру:

struct point{

// Структура для моделирования точек на плоскости

int x;

 

 

 

 

 

 

int y;

 

 

 

 

 

 

};

 

 

 

 

 

 

 

y

 

 

 

 

 

 

 

 

 

 

 

3

 

 

 

(4, 3)

 

 

 

 

 

 

 

 

(0, 0)

4

x

 

 

 

 

Рис.60. Точки на плоскости

Здесь struct – это ключевое слово, с которого начинается описание структуры. Идентификатор point – это имя структуры. В фигурных скобках помещается список объявлений членов или полей структуры x и y. Имена членов структуры должны различаться, но могут совпадать с именами других переменных программы.

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

point pt1, pt2, pt3; // Определение трех точек на плоскости

Эта запись аналогична объявлению переменных встроенных типов:

Структуры, перечисления, объединения 177

int a, b, c;

Переменные структурного типа могут копироваться, над ними можно выполнять операции присваивания, их можно передавать в функции в качестве аргумента и возвращать из функции в качестве результата.

Структурные переменные можно инициализировать при определении, например,

point nachkoord = {0, 0}, p1 = {1, 1};

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

Доступ к члену структуры осуществляется конструкцией:

ИМЯ_СТРУКТУРЫ.ЧЛЕН

Например, чтобы напечатать координаты точки p1, можно использовать инструкцию:

cout << p1.x <<”, ” << p1.y;

y

pt2

pt1

(0

, 0)

 

x

 

Рис.61. Прямоугольник как совокупность двух точек

Структуры могут быть вложенными друг в друга, например, прямоугольник, рис.62, можно рассматривать как совокупность двух точек, объединенных в одну структуру:

struct rect{

// Прямоугольник

point pt1;

// Первая вершина

point pt2;

// Вторая вершина

};

 

Структура rect имеет своими членами две структуры point. Пусть объявлена структурная переменная:

178 14

rect screen;

Выражение screen.pt1.x ссылается на координату x точки pt1 из структуры screen.

14.2. Структуры и функции

Рассмотрим несколько функций, манипулирующих точками и прямоугольниками.

// make_point: создание точки point make_point(int x, int y)

{

point tmp;

tmp.x = x; tmp.y = y; return tmp;

}

Здесь внутри функции создается локальная структура tmp, ее членам присваиваются значения. Затем с помощью return значение структуры возвращается из функции, после чего работа функции завершается, и локальная структура tmp уничтожается. Значение структуры, возвращенное из функции, может быть присвоено какой-то структурной переменной в вызывающей программе.

Следующая функция создает прямоугольник по двум точкам p и q:

// make_rect: создание прямоугольника rect make_rect(point p, point q)

{

rect tmp;

tmp.pt1 = p; tmp.pt2 = q; return tmp;

}

Здесь внутри функции создается локальная структура tmp, полям которой присваиваются значения структур p и q. При присваивании структур производится почленное копирование.

Возможно, что точка pt1 не лежит ниже и левее, чем pt2. Следующая функция преобразует прямоугольник к каноническому виду.

#define max(a, b) (a)>(b)?(a):(b)

// Макрос для выбора максимума

#define min(a, b) (a)<(b)?(a):(b)

// Макрос для выбора минимума

// canon_rect: канонизация координат прямоугольника rect canon_rect(rect r)

{

rect tmp;

Структуры, перечисления, объединения 179

tmp.pt1.x = min(r.pt1.x, r.pt2.x); tmp.pt1.y = min(r.pt1.y, r.pt2.y); tmp.pt2.x = max(r.pt1.x, r.pt2.x); tmp.pt2.y = max(r.pt1.y, r.pt2.y); return tmp;

}

14.3. Указатели на структуры

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

Объявление point* pp;

сообщает, что pp есть указатель на структуру point. Если pp ссылается на структуру, то выражение

*pp

есть сама структура, а выражения

(*pp).x, (*pp).y

являются членами структуры. Скобки в выражении (*pp).x необходимы, так как приоритет оператора точка (.) выше, чем приоритет оператора звездочка (*) и выражение *pp.x будет проинтерпретировано как *(pp.x), что неверно, так как pp не структура, а pp.x не является указателем.

Пусть имеем фрагмент программы:

point origin, *pp;

// Структура и указатель на структуру

pp = &origin;

// Указателю pp присвоен адрес структуры origin

Напечатать координаты точки origin можно следующим образом: cout << ”origin: (” << (*pp).x << ”, ” << (*pp).y << ”)”;

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

->

Если p – указатель на структуру, то выражение p->ЧЛЕН_СТРУКТУРЫ

180 14

есть ее отдельный член, поэтому напечатать координаты точки origin можно инструкцией:

cout <<”origin: (” << pp->x << ”, ” << pp->y << ”)”;

Операторы точка (.) и стрелка (->) имеют одинаковый приоритет и выполняются слева направо. Пусть, например, сделаны объявления:

rect r, *pr = &r;

Следующие выражения эквивалентны:

r.pt1.x, pr->pt1.x, (r.pt1).x

С помощью функции make_point можно динамически инициализировать структуры. Например, следующая функция получает в качестве аргумента указатель на структуру rect, внутри функции создается точка, динамически инициализируемая вызовом функции.

// cetner_rect: возвращает точку - центр прямоугольника point center_rect(rect* pr)

{

point tmp =

make_point((pr->pt1.x + pr->pt2.x) / 2, (pr->pt1.y + pr->pt2.y) / 2); return tmp;

}

Программа 36. Точки и прямоугольники на экране

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

На экране при его работе в текстовом режиме начало системы координат находится в левом верхнем углу, ось xs направлена вправо, ось ys вниз, то есть координата ys отсчитывается от верхнего края экрана. Левый верхний угол экрана имеет координаты (1, 1). Высота экрана составляет обычно 25 строк, ширина – 80 столбцов. Кроме того, если на экране создано окно, то в нем действует своя локальная система координат, с началом в левом верхнем углу окна.

Будем считать, что первый квадрант математической плоскости совпадает с физической плоскостью экрана, то есть ось x совпадает с нижним краем экрана, ось y – с левым, единица длины на математической плоскости численно равна единице длины на экране. Отсюда следует связь математических координат x, y и экранных координат xs, ys:

Структуры, перечисления, объединения 181

xs = x, ys = 25 − y.

Данные соображения учитываются в функции void show_rect(rect* pr, int color);

которая изображает на экране прямоугольник и переводит курсор в его центр. В программе использованы такие же обозначения, как на рис. 64.

Рис.65. Отображение математической плоскости на плоскость экрана

В текст программы следует вставить сделанные выше объявления структур point и rect и определения функций.

// Файл PointRct.cpp

 

struct point{

// Cтруктура точка

int x, y;

 

};

 

// make_point: создание точки

 

point make_point(int x, int y)

 

{

 

point tmp;

 

tmp.x = x; tmp.y =y;

 

return tmp;

 

}

 

struct rect{

// Структура прямоугольник

point pt1, pt2;

 

};

 

// make_rect: создание прямоугольника rect make_rect(point p, point q)

{

// color - цвет прямоугольника point LU = make_point(pr->pt1.x, HIGHT - pr->pt2.y);

182 14

rect tmp;

tmp.pt1 = p; tmp.pt2 = q; return tmp;

}

#include <conio.h>

// cetner_rect: возвращает точку - центр прямоугольника point center_rect(rect* pr)

{

point tmp =

make_point((pr->pt1.x + pr->pt2.x) / 2, (pr->pt1.y + pr->pt2.y) / 2); return tmp;

}

#define max(a, b) (a)>(b)?(a):(b) #define min(a, b) (a)<(b)?(a):(b)

//canon_rect: канонизация координат прямоугольника rect canon_rect(rect r)

{

rect tmp;

tmp.pt1.x = min(r.pt1.x, r.pt2.x); tmp.pt1.y = min(r.pt1.y, r.pt2.y); tmp.pt2.x = max(r.pt1.x, r.pt2.x); tmp.pt2.y = max(r.pt1.y, r.pt2.y); return tmp;

}

//show_rect: изображает прямоугольник на экране и

//помещает курсор в его центр

const int HIGHT = 25;

// Высота экрана в строках

void show_rect(rect* pr, int color)

{

//LU – Левый верхний угол прямоугольника на экране point RD = make_point(pr->pt2.x, HIGHT - pr->pt1.y);

//RD – Правый нижний угол прямоугольника на экране

window(LU.x, LU.y, RD.x, RD.y);

// Создание окна,

 

 

// соответствующего прямоугольнику

textbackground(color);

// Выделение прямоугольника

 

clrscr();

// цветом

 

point M = center_rect(pr);

// Центр прямоугольника в

 

 

//

математической

системе

координат

 

 

int xM = M.x, yM = M.y;

// Координаты центра в

 

Структуры, перечисления, объединения

183

 

 

//

математической

системе

 

координат

 

 

int xsM = xM, ysM = HIGHT - yM;

// Координаты центра

 

 

 

// прямоугольника на экране

 

int xwM = xsM - LU.x, ywM = ysM - LU.y;

// xwM, ywM – координаты

 

 

// центра прямоугольника в окне

M = make_point(xwM, ywM);

// Преобразование координат центра

 

 

// прямоугольника в оконные

 

gotoxy(M.x, M.y);

// Перевод курсора в центр прямоугольника

}

 

 

 

 

# include <iostream.h>

 

 

 

 

void main()

 

 

 

 

{

 

 

 

 

point a, b;

// Две точки

 

rect ab;

// Прямоугольник

 

int x, y;

 

 

 

 

textbackground(BLACK);

 

 

 

 

clrscr();

// Очистка экрана

 

cout << "Введите координаты первой точки\n";

 

cin >> x >> y;

 

 

 

 

a = make_point(x, y);

// Первая вершина прямоугольника

cout << "Введите координаты второй точки \n";

 

cin >> x >> y;

 

 

 

 

b = make_point(x, y);

// Вторая вершина прямоугольника

ab = make_rect(a, b);

// Создание прямоугольника

 

ab = canon_rect(ab);

// Приведение к каноническому виду

 

show_rect(&ab, RED);

// Изображение на экране

 

getch();

 

 

 

 

}

 

 

 

 

На рис. 66 приведено изображение экрана при работе с программой.