ГЛАВА VII. Записи

 

                         7.1 Определение записей

 

Объекты, которые  нас  окружают,  имеют  различные характеристики. Обычно

таких характеристик  бывает  несколько.  В  Pascal  для описания реальных

объектов  используют   специальный   тип:   запись.  Записи  относятся  к

комбинированным  типам.  Это  означает,  что  записи  могут  состоять  из

элементов различных типов. Запись объединяет  все  эти  элементы в единое

целое. Каждый элемент записи называется полем {аналогия с таблицей}.

 

В простейшем случае формат определения типа запись имеет вид:

 

 type  <Имя типа> = record

           <имя поля1> : <тип поля1>;

           <имя поля2> : <тип поля2>;

                  ..........

           <имя поляN> : <тип поляN>;

       end

 

ПРИМЕР.

        type date = record

                       day  : 1..31;

                       month: 1..12;

                       year : word;

                    end;

        var d1, d2: date;

begin

     ...........

     d1.day:=16;

     d1.month:=12;

     d1.year:=1999;

     ...........

 

Если  обращение  к  элементам  массива  происходит посредством  индексов,

то обращение к полям записи -- по именам полей:

                    <имя переменной-записи>.<имя поля>

 

Такая комбинация называется составным именем.

 

Значение полей записей можно использовать в выражениях.

 

Две  переменные-записи   одного   типа  можно  использовать  в  операторе

присваивания:

                                  d2:=d1

 

На тип  поля записи не  накладывается ограничений: это может быть простой

или структурированный тип, например, массив, запись и т.д.

 

ПРИМЕР.  type Person = record

                 Name   : string[15];

                 SurName: string[20];

                 bd     : date;

              end;

 

         var x, y: Person;

 

Описан тир Person, содержащий поля: имя, фамилия и дата рождения.

Последнее  поле  также является записью (описание типа  date  см.  выше).

Тогда возможны следующие операторы:

                     --------------------------------------¬

                     ¦-------------------------------------¦ x

                     L--------------------------------------

                     ----------T------------T----T----T----¬

x.name:='Петр';      ¦---------¦            ¦    ¦    ¦    ¦ x.name

                     L---------+------------+----+----+-----

                     ----------T------------T----T----T----¬

x.Surname:='Петров'; ¦         ¦------------¦    ¦    ¦    ¦ x.Surname

                     L---------+------------+----+----+-----

                     ----------T------------T----T----T----¬

                     ¦         ¦            ¦----¦----¦----¦ x.bd

                     L---------+------------+----+----+-----

                     ----------T------------T----T----T----¬

x.bd.day:=24;        ¦         ¦            ¦----¦    ¦    ¦ x.bd.day

                     L---------+------------+----+----+-----

                     ----------T------------T----T----T----¬

x.bd.month:=5;       ¦         ¦            ¦    ¦----¦    ¦ x.bd.month

                     L---------+------------+----+----+-----

                     ----------T------------T----T----T----¬

x.bd.year:=1977;     ¦         ¦            ¦    ¦    ¦----¦ x.bd.year

                     L---------+------------+----+----+-----

 

 

Очень часто используются массивы из  записей  и  файлы записей. Например,

для описания класса из 30 человек можно использовать такой тип:

 

   type class = array[1..30] of person;

   var a9: class;

 

 

                        7.2 Ввод и вывод записей.

 

Объекты  типа  запись   не  могут  считываться  и  выводиться  на  печаль

процедурами read(ln) и write(ln). То есть если d: date, то  нельзя писать

read(d)  или   write(d).   Для  ввода/вывода  записей  следует  создавать

собственные процедуры.

 

ПРИМЕР.

Procedure InpDate(var d: date);

begin

  write('Введите день: '); readln(d.day);

  write('Введите месяц: '); readln(d.month);

  write('Введите год: '); readln(d.year);

end;

 

Procedure OutDate(d: date);

begin

  writeln('День: ', d.day);

  writeln('Месяц: ', d.month);

  writeln('Год: ', d.year);

end;

 

Procedure InpPerson(var p: person);

begin

  write('Введите имя: '); readln(p.name);

  write('Введите фамилию: '); readln(p.Surname);

  write('Введите дату рождения: ');

  InpDate(p.bd);

end;

 

Procedure OutPerson(p: person);

begin

  writeln('Имя: ', p.name);

  writeln('Фамилия: ', p.Surname);

  writeln('Дата рождения:');

  OutDate(p.bd);

end;

 

После описания таких процедур в главной программе можно ввести переменную

x типа person:

 

     InpPerson(x);

     if (x.bd.year mod 2 = 0) then writeln('Четный год рождения');

     OutPerson(x);

 

С помощью этих же процедур можно ввести и вывести данные об учениках 9"a"

класса (var a9: class):

  for i:=1 to 30 do InpPerson(a9[i]);

       ....................

  for i:=1 to 30 do OutPerson(a9[i]);

       ....................

 

 

                        7.3 Оператор присоединения

 

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

оператор присоединения WITH.

 

       Формат:      With <переменная типа запись> do <оператор>

 

ПРИМЕР.  var student: person;

         ....................

         with student do begin

         ¦ name:='Петр';

         ¦ Surname:='Петров';

         ¦ with bd do begin

         ¦ ¦ day:=1;

         ¦ ¦ month:=3

         ¦ ¦ year:=1977;

         ¦ end;

         end;

 

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

полей, без указания имени записи.

 

Уровень вложенности оператора with не должен превышать 9.

 

 

                         7.4 Записи с вариантами.

 

Рассмотренные  выше  записи  имели  строго  фиксированную структуру.  Это

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

процессе выполнения программы. Часто  это оказывается неудобным. Чтобы не

увеличивать числа разных типов данных, используемых в программе, в Pascal

введена возможность  определения  типа-записи  с произвольным (но заранее

определенным) числом вариантов структуры.

 

Например, пусть нужно определить тип Person2, добавив к  Person поле Pol,

и  в  зависимости от того, мужчина  это  или женщина, определить

    (а) для мужчин:

         (1) рост;

         (2) курит или нет;

    (б) для женщин:

         (1) цвет глаз;

         (2) любимые цветы.

 

type PersonPol = (M, F);

     Person2 = record

               ¦  p: person;

               ¦  case Pol: PersonPol of

               ¦    M: (r: word;

               ¦        Smoking: boolean);

               ¦    F: (EyesColor: (blue, brown, gray, green);

               ¦        Flower: string[20])

               end;

 

Теперь в типе Person2 определены те  же самые поля, что и в Person (name,

Surname и  bd). Кроме того, добавлено  поле Pol, которое  может принимать

значение  M  (мужчина)  и F (женщина).  В  случае,  если  Pol=M, в запись

дополнительно  включаются  поля  "r" и "Smoking", а если Pol=F,  то  поля

"EyesColor" и "Flower".  Важно  понимать, что при всем  при  том мы здесь

имеем  дело  с  одним и тем же типом Person2. Если бы не было возможности

создавать вариативную часть записи, то пришлось  бы  заводить  два  типа:

отдельно для мужчин и для женщин.

 

Полный формат определения записи с вариантами:

 

 type  <Имя типа> = record

           <имя поля1> : <тип поля1>;

                  ..........

           <имя поляN> : <тип поляN>;

           case <поле признака>: <имя типа признака> of

              <константа выбора 1>: ( <поле 11> : <тип 11>;

                                      <поле 12> : <тип 12>;

                                      .....................

              <константа выбора 2>: ( <поле 21> : <тип 21>;

                                      <поле 22> : <тип 22>;

                                      .....................

                                      <поле N2> : <тип N2>;

               ............................................

       end

 

Отметим следующие моменты:

    (1) Начало вариантной  части  отмечается служебным словом CASE; после

        определения  поля  признака  записывается  служебное  слово   OF.

        Вариантная часть  завершается  вместе  с окончанием описания всей

        записи  служебным  словом  END.  При  этом  CASE,  в  отличие  от

        оператора выбора, своего END не имеет.

    (2) В описании записи может быть единственная вариантная  часть и она

        всегда задается в конце записи.

    (3) Альтернативы  вариантной  части      нас  M  и  F)  помечаются

        допустимыми  значениями  поля  выбора.

    (4) Определение  поля выбора помещено в заголовке вариантной  части.

        Таким образом, поле выбора -- это полноправное поле записи.

    (5) Тип поля выбора должен  быть  задан именем, т.е. это должен  быть

        или стандартный тип Pascal,  или  заранее определенный тип (у нас

        PersonPol).

    (6) Имена  полей во всех  вариантах должны быть различны и отличаться

        от имен фиксированной части.

    (7) Для некоторых значений поля выбора  варианты могут отсутствовать.

        Тогда после двоеточия ставится пустой список: пара скобок ().

 

ПРИМЕР. Найти  на  плоскости  расстояние  между  двумя точками, заданными

        полярными или декартовыми координатами.

 

   PROGRAM Coord;

   uses crt;

    type Point = record

                    case s: 0..1 of

                         0: (x,y: Real);

                         1: (r,fi: Real);

                 end;

     var  t1, t2: point;

           rast: Real;

 

  Procedure InpPoint (var t: point);

  BEGIN

  ¦ Writeln('Координаты точки: ');

  ¦ Writeln('Декартовы - 0, полярные - 1');

  ¦ With t do begin

  ¦ ¦    Readln(s);

  ¦ ¦    if s in [0,1] then

  ¦ ¦        case s of

  ¦ ¦        ¦    0: begin

  ¦ ¦        ¦       ¦ Write ('Введите координаты x,y: ');

  ¦ ¦        ¦       ¦ Readln (x,y);

  ¦ ¦        ¦       end;

  ¦ ¦        ¦    1: begin

  ¦ ¦        ¦       ¦ Write ('Введите полярный радиус r и угол fi: ');

  ¦ ¦        ¦       ¦ Readln(r,fi);

  ¦ ¦        ¦       end;

  ¦ ¦        end

  ¦ end

  END;

 

   BEGIN

   ¦  ClrScr;

   ¦  writeln ('Программа вычисляет расстояние между двумя точками');

   ¦  writeln('Введите координаты 1 точки'); InpPoint(t1);

   ¦  writeln('Введите координаты 2 точки'); InpPoint(t2);

   ¦  Case t1.s of

   ¦  ¦  0: Case t2.s of

   ¦  ¦     ¦ 0: rast:= sqrt(sqr(t1.x-t2.x)+sqr(t1.y-t2.y));

   ¦  ¦     ¦ 1: rast:= sqrt(sqr(t1.x-t2.r*cos(t2.fi))+sqr(t1.y-t2.r*

   ¦  ¦     ¦           sin(t2.fi)));

   ¦  ¦     end;

   ¦  ¦  1: case t2.s of

   ¦  ¦     ¦ 0: rast:=sqrt(sqr(t1.r*cos(t1.fi)-t2.x)+

   ¦  ¦     ¦             sqr(t1.r*sin(t1.fi)-t2.y));

   ¦  ¦     ¦ 1: rast:=sqrt(sqr(t1.r*cos(t1.fi)-t2.r*cos(t2.fi))+

   ¦  ¦     ¦               sqr(t1.r*sin(t1.fi)-t2.r*sin(t2.fi)));

   ¦  ¦     end;

   ¦  end;

   ¦  writeln('Расстояние = ',rast:12:3);

   END.

 

Hosted by uCoz