Тип «Запись» (Record) и оператор присоединения With

 

Запись - это структурированный тип данных, состоящий из фиксированного числа компонентов одного или нескольких типов. Определение типа записи начинается идентификатором record и заканчивается зарезервированным словом end. Между ними располагается список компонентов, называемых полями, с указанием идентификаторов полей и типа каждого поля. Тип «запись» определяется конструкцией

 

RECORD

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

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

ПолеМ : ТипПоляМ

END;

 

Если тип нескольких полей совпадает, то имена полей могут быть просто перечислены, например:

 

Type

PointRecType = record x, y: Integer end;

Пример.

Type

Car=Record

Number: integer; {Номер}
Marka: string[20]; {Марка автомобиля}
FIO: string[40]; {Фамилия, инициалы владельца}
Address: string[60]; {Адрес владельца}

end;

Var

M, V: Car;

В данном примере запись Car содержит четыре компонента: номер, название марки машины, фамилию владельца и его адрес. Доступ к полям записи осуществляется через переменную типа «запись». В нашем случае это переменные М и V типа Car.

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

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

Например, чтобы получить доступ к полям записи Car надо написать:

 

M.Number, M.Marka, M.FIO, M.Address.

 

Составное имя можно использовать везде, где допустимо применение типа поля. Для присваивания полям значений используется оператор присваивания.

Пример.

 

M.Number:=1678;

M.Marka:= ‘Газ_24’;

M.FIO:=’Иванов И. И.’

M.Address:=’ул. Пушкина 12-31’;

Составные имена можно использовать, в частности, в операторах ввода-вывода:

 

Read(M.Number, M.Marka, M.FIO, M.Address);

Write(M.Number:4, M.Marka:7, M.FIO:12, M.Address:25);

 

Допускается применение оператора присваивания, и к записям в целом, если они имеют одинаковый тип. Например, V := М;

После выполнения этого оператора значения полей записи V станут равными значениям соответствующих полей записи М.

В ряде задач удобно пользоваться массивами из записей. Их можно описать следующим образом:

 

Type

Person= record

FIO: string[20];

Age : 1..99;

Prof: string[30];

End;

Var

List: array[1..50] of Person;

 

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

 

with ИмяПеременной_Записи DO Оператор;

 

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

Пример: Присвоить значения полям записи Саг с помощью оператора with

 

with M do

begin

Number:=1678;

Marka:= ‘Газ_24’;

FIO:=’Петров В. И.’

Address:=’ул. Остужева 2-31’;

end;

 

Внутри области действия оператора with могут указываться и переменные, не имеющие отношения к записи. Но в этом случае надо следить, чтобы они не совпадали по написанию с полями записи.

 

PROGRAM MAIN;

var

X, Y: Integer;

RecXY: record X, Y: Integer end;

Begin

X: =10; Y: =20; { значения переменных X и Y }
with RecXY do begin { работаем с записью RecXY }
X: = 3.14 * X; {Где какой X и Y? }
Y: = 3.14 * Y  

end; {with}

End.

Действия внутри оператора with проводятся только над полями записи RecXY. Чтобы сохранить оператор with и «развязать» имена X и Y, надо к переменным X и Y приписать так называемый квалификатор - имя программы или модуля (UNIT), в которой они объявлены (для этого программа должна иметь заголовок). Так, оператор присоединения можно исправить следующим образом:

 

with RecXY do begin

X: = 3.14 * Main.X;

Y: = 3.14 * Main.Y

end;

 

и проблема исчезнет.

В Pascal допускает вложение записей (т.е. поле записи само является записью), соответственно оператор with тоже может быть вложенным.

 

with RV1 do

with RV2 do

with RVn do…

 

что эквивалентно конструкции

 

with RV1, RV2, …, RVn do...

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

 

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

Использование фиксированной части аналогично описанному ранее. Вариантная часть формируется с помощью оператора case . Он задает особое поле записи поле признака, которое определяет, какой из вариантов в данный момент будет активизирован. Значением признака в каждый текущий момент выполнения программы должна быть одна из расположенных следом констант. Константа, служащая признаком, задает вариант записи и называется константой выбора. Формат:

 

Type

Rec = record

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

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

<константа выбораn > : (поле. . . . :тип)

end;

 

Компоненты каждого варианта (идентификаторы полей и их типы) заключаются в круглые скобки. У части case нет отдельного end, как этого следовало бы ожидать по аналогии с оператором case. Одно слово end заканчивает всю конструкцию записи с вариантами. Необходимо отметить, что количество полей каждого из вариантов не ограничено.

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

При использовании записей с вариантами необходимо придерживаться следующих правил:

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

• запись может иметь только одну вариантную часть, причем она должна размещаться в конце записи;

• если поле, соответствующее какой - либо метке, является пустым, то оно записывается следующим образом: <метка>: ().

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

Программа выглядит следующим образом:

 

Program SF;

Uses Crt;

Type TF=(rect,circle);

figure=record

case art : TF of

rect :(L1,L2:real);

circle:(R:real);

end;

Var x:figure;

p:string[6];

pr:char;

Begin

ClrScr;

repeat

write('Введите вид фигуры (rect, circle) '); readln(p);

with x do begin

if p='rect' then art:=rect;

if p='circle' then art:=circle;

case art of

rect: begin

write('Введите длину прямоугольника= '); readln(L1);

write('Введите ширину прямоугольника= '); readln(L2);

writeln('Площадь равна=', L1*L2:8:3);

end;

circle: begin

write('Введите радиус окружности= ');readln(R);

writeln('Площадь равна=', Pi*R*R:8:3);

end;

end; {case}

end;

write('Продолжить расчет? (Y-Да,N- Нет) ');readln(pr);

until pr='N';

readln;

End.

Множества в Паскале.

 

Множество представляет собой набор различных объектов одинакового типа, называемого базовым типом. Базовый тип может быть перечисляемым или интервальным. Если C есть множество объектов типа T, то о каждом объекте типа T можно сказать, что он либо является элементом множества C, либо нет. Таким образом, тип множества C определяет подмножество объектов базового типа T. Тип множества определяется в разделе определения типов.

<Имя типа множества> = SET OF <базовый тип>

Ключевые слова SET OF означают - набор из.

Определим перечисляемый тип:

TYPE SCHOOL = (PUPILS, TEACHERS, ZAVUCH, ZAVHOZ, DIRECTOR)

Тип множества может быть таким:

TYPE ADMINISTRAZIA = SET OF SCHOOL;

Переменные типа ADMINISTRAZIA описываются в разделе описания переменных обычным образом.

Тип ADMINISTRAZIA - это производный множественный тип для типа SCHOOL. А тип SCHOOL - это базовый тип для типа ADMINISTRAZIA. Множества представляются списком элементов, заключенным в квадратные скобки. Конструкции [PUPILS, TEACHERS], [ZAVUCH, ZAVHOZ, DIRECTOR] будут константами типа SCHOOL. Множество может не иметь элементов. В этом случае оно называется пустым множеством и обозначается так: [ ].

Для объектов, имеющих структуру множества, определены специальные операции:

объединение, пересечение и вычитание двух множеств;

проверка на равенство или неравенство множеств;

проверка принадлежности элемента к множеству, (т.е. входит ли указанный элемент во множество или нет).

Объединением двух множеств называется множество всех элементов, принадлежащих обоим множествам. Знаком операции объединения множеств служит знак “+”.

Например:

[1, 2] + [3, 4, 5] = [1, 2, 3, 4, 5];

[PUPILS, TEACHERS] + [ZAVUCH, ZAVHOZ, DIRECTOR] =

[PUPILS, TEACHERS, ZAVUCH, ZAVHOZ, DIRECTOR];

Пересечением двух множеств называется множество элементов, которые принадлежат одновременно обоим множествам. Знаком операции пересечения множеств служит знак “*”.

Например:

[1..10] * [5..20] = [5..10];

[PUPILS, TEACHERS] * [TEAHERS, ZAVUCH] = [TEAHERS];

Разностью двух множеств называется множество, содержащее те элементы, которые не являются элементами второго множества. Знаком операции разности двух множеств служит знак “-”.

Например:

[1..10] - [5..20] = [1..4];

[PUPILS, TEACHERS, DIRECTOR] - [ZAVUCH, ZAVHOZ] = [DIRECTOR];

Для множеств определены операции отношения:

= обозначает тождественность множеств;

<> обозначает нетождественность множеств;

<= обозначает “содержится в”;

>= обозначает “содержит”.

Операции проверки на равенство или неравенство множеств вырабатывают значения true или false, например:

[3, 4, 5] = [4, 5] - false

[3, 4, 5] <> [4, 5] - true

[1, 2, 3] <= [1..10] - true

Для проверки принадлежности элемента к множеству служит отношение IN, зарезервированное слово в языке Турбо-Паскаль. Слева от слова IN пишется выражение перечисляемого типа. Справа пишется выражение типа множеств, производимого от типа левого операнда. Результат будет true, если первый операнд является элементом второго операнда, т.е. элементом этого множества. В противном случае результат будет false.

Например,

5 in [1, 2, 3, 4, 5, 6, 7] - true

10 in [1, 2, 3, 4, 5, 6, 7] - false

выражение ZAVUCH IN [PUPILS, TEACHERS, ZAVUCH, ZAVHOZ]

будет истинным, а выражение

DIRECTOR IN [PUPILS, TEACHERS, ZAVUCH, ZAVHOZ] – ложное

 

31,

Д И Н А М И Ч Е С К И Е П Е Р Е М Е Н Н Ы Е Статической переменной (статически размещенной) называется описан-ная явным образом в программе переменная, обращение к ней осуществля-ется по имени. Место в памяти для размещения статических переменныхопределяется при компиляции программы. В отличие от таких статических переменных в программах, написанныхна языке ПАСКАЛЬ, могут быть созданы динамические переменные. Основ-ное свойство динамических переменных заключается в том, что они соз-даются и память для них выделяется во время выполнения программы.Размещаются динамические переменные в динамической области памяти(heap - области). Динамическая переменная не указывается явно в описаниях переменныхи к ней нельзя обратиться по имени. Доступ к таким переменным осу-ществляется с помощью указателей и ссылок. Работа с динамической областью памяти в TURBO PASCAL реализуется спомощью процедур и функций New, Dispose, GetMem, FreeMem, Mark,Release, MaxAvail, MemAvail, SizeOf. Процедура New( var p: Pointer ) выделяет место в динамической об-ласти памяти для размещения динамической переменной p^ и ее адресприсваивает указателю p. Процедура Dispose( var p: Pointer ) освобождает участок памяти,выделенный для размещения динамической переменной процедурой New, изначение указателя p становится неопределенным. Проуедура GetMem( var p: Pointer; size: Word ) выделяет участокпамяти в heap - области, присваивает адрес его начала указателю p,размер участка в байтах задается параметром size. Процедура FreeMem( var p: Pointer; size: Word ) освобождает учас-ток памяти, адрес начала которого определен указателем p, а размер -параметром size. Значение указателя p становится неопределенным. Процедура Mark( var p: Pointer ) записывает в указатель p адресначала участка свободной динамической памяти на момент ее вызова. Процедура Release( var p: Pointer ) освобождает участок динамичес-кой памяти, начиная с адреса, записанного в указатель p процедуройMark, то-есть, очищает ту динамическую память, которая была занятапосле вызова процедуры Mark. Функция MaxAvail: Longint возвращает длину в байтах самого длинно-го свободного участка динамической памяти. Функция MemAvail: Longint полный объем свободной динамической па-мяти в байтах. Вспомогательная функция SizeOf( X ): Word возвращает объем в бай-тах, занимаемый X, причем X может быть либо именем переменной любоготипа, либо именем типа. Рассмотрим некоторые примеры работы с указателями. var p1, p2: ^Integer; Здесь p1 и p2 - указатели или пременные ссылочного типа. p1:=NIL; p2:=NIL; После выполнения этих операторов присваивания указатели p1 и p2 небудут ссылаться ни на какой конкретный объект. New(p1); New(p2); Процедура New(p1) выполняет следующие действия: -в памяти ЭВМ выделяется участок для размещения величины целоготипа; -адрес этого участка присваивается переменной p1: г===== г===== ¦ *--¦--------->¦ ¦ L=====- L=====- p1 p1^ Аналогично, процедура New(p2) обеспечит выделение участка памяти,адрес которого будет записан в p2: г===== г===== ¦ *--¦--------->¦ ¦ L=====- L=====- p2 p2^ После выполнения операторов присваивания p1^:=2; p2^:=4; в выделенные участки памяти будут записаны значения 2 и 4 соответ-ственно: г===== г===== ¦ *--¦--------->¦ 2 ¦ L=====- L=====- p1 p1^ г===== г===== ¦ *--¦--------->¦ 4 ¦ L=====- L=====- p2 p2^ В результате выполнения оператора присваивания p1^:=p2^; в участок памяти, на который ссылается указатель p1, будет записанозначение 4: г===== г===== ¦ *--¦--------->¦ 4 ¦ L=====- L=====- p1 p1^ г===== г===== ¦ *--¦--------->¦ 4 ¦ L=====- L=====- p2 p2^ После выполнения оператора присваивания p2:=p1; оба указателя будут содержать адрес первого участка памяти: г===== г===== ¦ *--¦--------->¦ 4 ¦ L=====- --->L=====- p1 ¦ p1^ p2^ ¦ г===== ¦ ¦ *--¦------- L=====- p2 Переменные p1^, p2^ являются динамическими, так как память для нихвыделяется в процессе выполнения программы с помощью процедуры New. Динамические переменные могут входить в состав выражений, напри-мер: p1^:=p1^+8; Write('p1^=',p1^:3); Пример. В результате выполнения программы: Program DemoPointer; var p1,p2,p3:^Integer; begin p1:=NIL; p2:=NIL; p3:=NIL; New(p1); New(p2); New(p3); p1^:=2; p2^:=4; p3^:=p1^+Sqr(p2^); writeln('p1^=',p1^:3,' p2^=',p2^:3,' p3^=',p3^:3); p1:=p2; writeln('p1^=',p1^:3,' p2^=',p2^:3) end. на экран дисплея будут выведены результаты: p1^= 2 p2^= 4 p3^= 18p1^= 4 p2^= 4

33,

Выражения

 

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

Математические операции

В таблице приведены основные математические операции Турбо Паскаль.

Символ операции Название операции Пример
* умножение 2*3 (результат: 6)
/ деление 30/2 (результат: 1.5E+01)
+ сложение 2+3 (результат: 5)
- вычитание 5-3 (результат: 2)
div целочисленное деление 5 div 2 (результат: 2)
mod остаток от деления 5 mod 2 (результат: 1)

Логические операции

Над логическими аргументами в Турбо Паскаль определены следующие операции:

  • NOT - логическое отрицание ("НЕ")
  • AND - логическое умножение ("И")
  • OR - логическое сложение ("ИЛИ")
  • XOR - логическое "Исключающее ИЛИ"

Результаты выполнения этих операций над переменными А и В логического типа приведены в таблице истинности.

A B not A A and B A or B A xor B
true true false true true false
true false   false true true
false true true false true true
false false   false false false

Операции отношения

К операциям отношения в Турбо Паскаль относятся такие операции, как:

  • > - больше
  • < - меньше
  • = - равно
  • <> - не равно
  • >= - больше или равно
  • <= - меньше или равно

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

Приоритет операций

Порядок вычисления выражения определяется старшинством (приоритетом) содержащихся в нем операций. В языке Паскаль принят следующий приоритет операций:

  • унарная операция not, унарный минус -, взятие адреса @
  • операции типа умножения: * / div mod and
  • операции типа сложения: + - or xor
  • операции отношения: = <> < > <= >= in

Порядок выполнения операций переопределить можно с помощью скобок. Например 2*5+10 равно 20, но 2*(5+10) равно 30.