Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
все ответы.docx
Скачиваний:
8
Добавлен:
26.09.2019
Размер:
2.71 Mб
Скачать

10. Структурированные типы данных. Записи. Обращение к полям записей. Оператор with. Тип "запись" (record)

Тип Запись (Record) используется для компактного представления данных разного типа.

  • ОПИСАНИЕ

TYPE

<Имя_типа>=Record

<Поле1>:<ТипПоля1>;

<Поле2>:<ТипПоля2>;

...

<ПолеN>:<ТипПоляN>;

End;

  • Каждая запись состоит из заданного числа полей.

  • <ТипПоляi> - любой простой или структурированный тип.

  • Размещение значений полей записи в памяти определяется порядком их описания (первое поле - в младших адресах, последнее - в старших).

  • При совпадении типов нескольких полей записи имена полей могут быть перечислены через запятую.

  • ПРИМЕР 1. Описать тип данных со структурой:

Студент

Имя

Дата рождения

Телефон,

где

Дата рождения -

День

Месяц

Год

  • ПРИМЕР 2. Комплексное число (Re,Im)

Type

Complex=Record

Re,Im:Real;

End;

Var

C1,C2,C3:Complex;

А)

Type

Student = record

Name:String[20];

Birthday:record

Day:1..31;

Month:1..12;

Year:1900..2000;

End;

Phone:String[10];

End;

или B)

Type

MyDate = record

Day:1..31;

Month:1..12;

Year:1900..2000;

End;

Student = record

Name:String[20];

Birthday:MyDate;

Phone:String[15];

End;

  • ПРИМЕР 3. Описать тип данных «Сотрудник», содержащий поля Имя, Возраст, Стаж

Type

Empl=Record

Name:String;

Age, Standing: Integer;

End;

Var

E:Empl;

Var

GrK1_281:Array[1..30] of Student;

  • ОБРАЩЕНИЕ К ПОЛЯМ ЗАПИСИ

<Переменная_запись>.<ИмяПоля>

для вложенной записи (см. пример 1, поле-запись Birthday)

<Переменная_запись>.<ИмяПоля>.<ПолеПоляЗаписи>

  • ПРИМЕР 4. Обращение к полям записи

A) Тип Complex (см.пример2)

Var

C1,C2: Complex;

Begin

c1.re:=1; c1.im:=-4.5

c2.re:=c1.re;

c2.im:=(c1.im-5)*2;

End

B) Тип Empl (см.пример3)

Var E:Empl;

Begin

E.Name:=’Иванов Петр’;

E.Age:=45;

E.Standing:=20;

End.

C) Тип MyDate (см. пример 1B) - для среды Delphi !!!

Uses SysUtils;

Var

YY, MM, Day: Word;

Today:MyDate;

Begin

DecodeDate(Date(),YY, MM, Day)

Today.Year:= YY;

Today.Month:=MM;

Today.Day:= Day;

End.

  • Подпрограммы модуля SysUtils

  • Функция Date() возвращает значение текущей даты в вещественном формате (тип TDateTime)

  • Процедура DecodeDate() преобразует значение TDateTime в числовые значения года, месяца и дня.

  • ДОПУСТИМЫЕ ОПЕРАЦИИ

  1. Для переменных-записей допустима только операция присваивания.

  2. Поля записи могут участвовать во всех операциях, применимых к типу этих полей.

  3. Ввод/вывод содержимого записи на экран допустим только для полей простого типа.

  • ПРИМЕР 5. Ввод/вывод записи типа Student (см. пример 1).

PROCEDURE ReadStud(Var S:Student);

Begin

Readln(S.Name);

Readln(S.BirthDay.Year);

Readln(S.BirthDay.Month);

Readln(S.BirthDay.Day);

Readln(S.Phone);

End;

PROCEDURE WriteStud(S:Student);

Begin

Writeln(S.Name);

Writeln(S.BirthDay.Year);

Writeln(S.BirthDay.Month);

Writeln(S.BirthDay.Day);

Writeln(S.Phone);

End;

Var

Gr281:Array[1..N] of Student;

Begin

For i:=1 to N do ReadStud(Gr281[i]);

End.

  • ПРИМЕР 6. Сложение двух комплексных чисел (см. пример 2).

Type

Complex=Record

Re:Real;

Im:Real;

End;

Var

C1,C2,C3:Complex;

Procedure CSum(C1,C2:Complex; Var C3:Complex);

Begin

C3.Re:=C1.Re+C2.Re;

C3.Im:=C1.Im+C2.Im;

end;

Begin

C1.Re:=2;

C1.Im:=2;

Readln(C2.Re,C2.Im);

CSum(C1,C2,C3);

Writeln(C3.Re:1,'+',C3.Im:1,'*I');

End.

  • ОПЕРАТОР ПРИСОЕДИНЕНИЯ (WITH)

WITH <Переменная-Запись> DO <оператор> (см. пример 7)

  • Упрощает работу с записью. Внутри оператора WITH отсутствует ссылка на переменную-запись, при обращении указывается только идентификатор поля.

  • Если поле записи само является записью, то к полям этого поля можно обращаться по схеме

WITH <Перем-запись>,<Поле-запись> DO <оператор>

или

WITH <Перем-запись>.<Поле-запись> DO <оператор> (см. пример 7B)

  • ПРИМЕР 7. Чтение элемента массива Gr281 - записи типа Student (см. пример 5)

A)

With Gr281[i] do

Begin

Readln(Name);

Readln(BirthDay.Year)

Readln(BirthDay.Month)

Readln(BirthDay.Day)

Readln(Phone)

End

B)

With Gr281[33], BirthDay do

Begin

Readln(Name);

Readln(Year)

Readln(Month)

Readln(Day)

Phone:='323-93-65';

End

  • ТИПИЗИРОВАННЫЕ КОНСТАНТЫ-ЗАПИСИ

Поля константы указываются в том же порядке, как они следуют в описании типа; значения задаются в виде:

Const

<Имя>:<Тип>=(<имя_поля1>: <значение_поля1>;... <имя_поляN>: <значение_поляN>)

  • ПРИМЕР 8. ОБЪЯВЛЕНИЕ ТИПИЗИРОВАННЫХ КОНСТАНТ-ЗАПИСЕЙ

TYPE

Point = record

x,y: real;

end;

Vector = array[0..1] of Point;

Month = (Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Decb);

MyDate = record

d:1..31; m:Month;

y:1900..1999; end;

CONST

ZeroPoint : Point = (x:0.0; y:0.0);

Line : Vector = ((x:-3.1; y:1.5),(x:5.8; y:3.0));

SomeDay : MyDate = (d:11; m:Jan; y:1970);

ВАРИАНТНАЯ ЧАСТЬ ЗАПИСИ

Используется для описания различных структур в пределах одного типа-записи. Позволяет экономить память, выделяемую для хранения переменной данного типа.

  • ОПИСАНИЕ

TYPE

<Имя_типа>=Record

<Поле1>:<ТипПоля1>;

<ПолеK>:<ТипПоляK>;

Case [<поле-признак>:] <тип поля-признака> of

{Список фиксированных полей}

<набор значений1>: (<список полей1>);

<набор значенийL>: (<список полейL>);

End;

{Список вариантных полей (вариантная часть)}

  • Фиксированные поля (в т.ч. и поле-признак)

Поля, присутствующие во всех вариантах.

  • Поле - признак (селектор, тэг, ярлык)

Используется для выбора одного из L вариантов структуры оставшейся части записи (<список полей1>,…, <список полейL>).

Для определения поля-признака должен использоваться один из порядковых типов (<тип поля-признака>).

Значение поля указывает на активный в текущий момент вариант. Каждый вариант определяется одной или несколькими константами (<набор значений i>), которые должны отличаться друг от друга и иметь тип, совместимый с типом селектора.

  • ПРИМЕР 9. Описать тип, который мог бы содержать сведения о фигурах: точка (x,y), окружность (координаты центра, радиус), прямоугольник (координаты вершины, длины сторон)

TYPE

Figure=(Point, Circle, Rectangle);

Figure_Rec=record

x,y : Double;

Case kind : Figure of {поле-признак}

Фиксированная часть

Circle : (radius: Double); {прямоугольник}

Rectangle : (height,width: Double); {круг}

Вариантная часть

End;

  • Размер записи для любого варианта равен длине записи с максимальным вариантом (SizeOf(Figure_Rec)=8+8+1+8+8=33)

  • Каждый вариант начинается с одного и того же адреса памяти.

Возможные варианты записи типа Figure_Rec

Выбор структуры - по значению поля Kind

Фиксированная

Вариантная часть

Kind=Point{точка}

X

Y

Kind

Kind=Rectangle{прямоугольник}

X

Y

Kind

Height

Width

Kind=Circle{круг}

X

Y

Kind

Radius

  • Доступ к вариантным полям записи - как к фиксированным, но в любое время возможно обращение к полям только одного из вариантов (иначе - логическая несогласованность).

  • В типизированных константах значение поля-признака варианта (если задано) должно быть определено; указываются только поля выбранного варианта.

  • ПРИМЕР 10. Считывание значений записи типа Figure_Rec (см. пример 9)

Var F:figure_rec;

Procedure InputFigure(var FR:Figure_rec);

var Fig_Kind:Byte;

begin

repeat

Writeln('Выберите фигуру: 0-точка, 1-окружность, ');

Writeln(' 2-прямоугольник.');

Readln(Fig_kind);

until Fig_Kind in [0..2];

Case Fig_Kind of

0 : Write('Введите координаты точки:');

1 : Write('Введите координаты центра:');

2 : Write('Введите координаты вершины:');

end;

With FR do

Begin

Readln(x,y);

kind:=Figure(Fig_kind); // используем приведение типа

Case kind of

Circle: begin

Write('Радиус (R):');

Readln(Radius);

end;

Rectangle: begin

Write('Длины сторон прямоугольника (S1 и S2):');

readln(Height,Width);

end;

end; {case}

end; {with}

end; {proc}

begin

InputFigure(F);...

end.

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

  • ПРИМЕР 11. ОПИСАНИЕ ВАРИАНТНОЙ ЧАСТИ ЗАПИСИ БЕЗ ПОЛЯ-ПРИЗНАКА.

В запись CB4 заносятся коды первых четырех цифровых символов (поля B1-B4, значения 48-51), а при обращении к ним как к символам (вариант с массивом C) на экран выведутся символы ’0’-’3’.

Var

CB4:Record

Case Boolean of

True: (C:Array[1..4]of Char);

False: (B1,B2,B3,B4:Byte);

End;

I:Integer;

Begin

CB4.B1:=48; CB4.B2:=49;

CB4.B3:=50; CB4.B4:=51;

For I:=1 to 4 do

With CB4 do

Write(C[i]);{вывод символов '0' '1' '2' '3'}

End

  • При совпадении имен полей записи с именами внешних переменных или полей других записей нужно указывать квалификатор (имена программ, модулей, записей) там, где это необходимо.

  • ПРИМЕР 12. СОВПАДЕНИЕ ИМЕН ПОЛЕЙ ЗАПИСИ С ДРУГИМИ ИМЕНАМИ

Program Main;

Type

Complex= Record

Re,Im: Real

End;

Var

Re,Im:Integer; // Имена переменных совпадают с именами полей записи CX

CX: Complex;

Begin

...

Re:=1; Im:=0;

With CX Do

Begin

Re:=Main.Re; // В правой части упомянуты глобальные переменные – указано имя программы (Main)

Im:=Main.Im;

End;

End.