Шаг 86.
Переменные структуры

    На этом шаге мы покажем, как можно совместно использовать структуры и объединения.

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

    В языках, таких как Ada и Pascal, имеется тип данных, называемый записью с вариантами, поля которой содержат набор одних и тех же компонент плюс компоненты, не являющиеся общими для всех остальных объектов. В языке C++ также имеется тип данных, подобный записи с вариантами, называемый переменной структурой (variant structure), которая может быть реализована с использованием комбинации структуры и объединения.

    Рассмотрим для примера шаблон структуры figure:

   struct figure
   { 
     int area, perimeter; //Общие компоненты.
     int type; //Метка активной компоненты. 
     union
      { int radius; // Окружность. 
        int a[2]; // Прямоугольник. 
        int b[3]; // Треугольник. 
      } geom_fig;
   };

    В общем случае каждый объект типа figure будет состоять из трех компонентов: area, perimeter и type. Компонент type называется меткой активного компонента (active component tag), так как он используется для указания, какой из компонентов объединения geom_fig (например, radius, a или b) является активным в данный момент. Такая структура называется переменной структурой, потому что ее компоненты меняются в зависимости от значения метки активного компонента.

    В общем случае переменные структуры будут состоять из трех частей:

    Общая форма переменной структуры имеет следующий вид:

   struct
   {
     <общие компоненты>
     <метка активного компонента>
     union
     { <описание типа1> <компонента1> 
       <описание типа2> <компонента2>
          .        .         . 
       <описание типаN> <компонентаN>
     } <идентификатор>
   };

    Проиллюстрируем сказанное на примере. Предположим, что даны следующие определения констант[1]:

    #define CIRCLE 1
    #define RECT 2
    #define TRIANGLE 3

и что переменная fig определяется как: figure fig;. Тогда, по соглашению, перед присваиванием значения одному из компонентов соответствующее значение присваивается также переменной fig.type для указания активного компонента, например:

   fig.type = CIRCLE;
   fig.geom_fig.radius = 5;.

    Аналогично перед обращением к компоненту объединения необходимо проверить, является ли этот компонент активным, например:

    switch (fig.type)
    {
      case CIRCLE: Обработать окружность; break;
      case RECT: Обработать прямоугольник; break;
      case TRIANGLE: Обработать треугольник; break;
      default: Ошибка;
    }

    "Соберем" все сказанное в программу.

#include <iostream.h>
#define CIRCLE 1
#define RECT 2
#define TRIANGLE 3
struct figure
{ int area, perimeter; //Общие компоненты.
  int type; // Метка активного компонента.
  union 
  { int radius; // Окружность.
    int a[2]; //Прямоугольник.
    int b[3]; // Треугольник.
  } geom_fig;
};
figure fig;
void main ()
{
   cout << "Введите значение метки активного компонента... ";
   cin >> fig.type;
   switch (fig.type)
   { 
    case CIRCLE: 
       cout << "Введите радиус... "; 
       cin >> fig.geom_fig.radius;
       cout << "Радиус: " << fig.geom_fig.radius; 
       break;  
    case RECT: 
       cout << "Введите стороны прямоугольника... ";
       cin >> fig.geom_fig.a[0] >> fig.geom_fig.a[1];
       fig.area = fig.geom_fig.a[0]*fig.geom_fig.a[1];
       cout << "Площадь: " << fig.area;
       break;
    case TRIANGLE: 
       cout << "Введите стороны треугольника... ";
       cin >> fig.geom_fig.b[0] >> fig.geom_fig.b[1] >> fig.geom_fig.b[2];
       fig.perimeter=fig.geom_fig.b[0]+fig.geom_fig.b[1]+ 
                                               fig.geom_fig.b[2]; 
       cout << "Периметр: " << fig.perimeter;  
       break; 
    default: cout << "Ошибка!";
   }
}
Текст этой программы можно взять здесь.



(1)Джехани Н. Программирование на языке Си. - М.: Радио и связь, 1988. - 272с.


Предыдущий шаг Содержание