9.2 Оператор WITH
При работе с записями, при обращении к различным полям каждый раз приходится писать сначала имя самой записи, что не всегда удобно, если полей много. Поэтому в Паскале применяется оператор WITH:
with NEKTO do
begin
NAME:= 'MANUELA'; AGE:= 20;
MALADI:= 'GRIP';
MARIE:= true;
end.
Другими словами, в рамках оператора, помещенного внутри оператора WITH, к полям определенной переменной можно обращаться просто по имени (префикация имен опускается).
Особенно эффективно использовать WITH, когда речь идет о вложенных записях, т.е. таких, где поля есть тоже записи. Например, запись типа PATIENT можно расширить добавлением поля DATE, которое снова есть запись с 3-мя полями:
type PATIENT = record
NAME: string [10];
MALADI: string [30];
DATE: record
DEN: integer;
MESJATS: string [10];
GOD: integer;
end;
MARIE: boolean;
end;
var NEKTO: PATIENT.
При таком вложении доступ, например, к полю GOD уже должен сопровождаться указанием двух префиксных имен, например:
read (NEKTO.DATE.GOD).
Здесь уже WITH может значительно упростить работу с полями:
with NEKTO, DATE do
begin
NAME:= 'MANUELA'; AGE:= 20;
MALADI:= 'GRIP';
DEN:= 18;
MESJATS:= 'MART';
GOD:= 1944;
MARIE:= TRUE;
end.
Оператор WITH принято называть оператором присоединения. В общем случае он выглядит так: WITH R1, R2,..., Rn do S, что эквивалентно WITH R1 do WITH R2, R3,..., Rn do S.
Имя поля в операторе присоединения обозначает компоненту комбинированной переменной из ближайшего объединяющего оператора присоединения, в котором указана переменная с таким полем. Следовательно, если две переменные из списка комбинированных переменных оператора присоединения имеют поля, обозначенные одним и тем же именем, то внутри оператора WITH это имя обозначает поле той переменной, которая указана в списке позже.
С другой стороны, при определении некоторого комбинированного типа имена отдельных полей могут совпадать с именами обычных, простых переменных, не входящих в комбинированную переменную. Как здесь происходит отличие?
Пусть, например, имеется простая переменная AGE и поле AGE некоторой комбинированной переменной NEKTO. В этом случае их можно отличить, т.к. простая переменная имеет имя AGE, а переменная-поле имеет полное имя NEKTO.AGE. А что будет в операторе WITH, где префикс NEKTO опускается?
В этом случае в операторе предпочтение отдается именам полей записи, т.е. считается, что внутри оператора WITH соответствующее имя обозначает имя поля, а не имя переменной.
Проиллюстрируем этот тезис на примере. Пусть даны типы:
const N_STUD =...;
N_SOTR =...;
n =...;
type SEX = (M,F);
STUD = RECORD
FAM,IM,OTH: array [1..N_STUD] of string[n];
POL: SEX;
GR: 111..154;
STIP: boolean;
end;
SOTR = record
FAM,IM,OTH: array [1..N_SOTR] of string[n];
POL: SEX;
DOLGN: (LAB, ASS, STPR, DOZ, PROF);
ZARPL: integer;
end;
var X: STUD; Y: SOTR;
STIP: integer;
Тогда можно дать такой фрагмент программы:
with X, Y do
begin
IM[5]:= 'ALEXANDR ';
POL:= M;
STIP:= true;
GR:= 122;
end;
STIP:= 160.
Здесь поля IM, POL относятся к переменной Y типа SOTR, т.к. эта переменная в списке переменных-записей заголовка WITH фигурирует после переменной X типа STUD. Кроме того, в этом фрагменте имя STIP в теле оператора WITH есть имя поля переменной Х.
9.3 Записи с вариантами
Записи, описанные ранее - это записи с фиксированными частями. Они имеют в различных ситуациях строго определенную структуру. Однако бывают ситуации, когда нужно отказаться от этой строгой определенности. Поэтому появляются записи с вариантами.
Рассмотрим пример создания программ для введения списка библиографических ссылок. Например, научные работы могут быть оформлены в виде монографий, т.е. книг, а могут быть и журнальные публикации. Если известно, что все публикации есть книги, то это можно задать в виде следующего описания:
const MAXNOMBRE =...
type ENTRY = record
AUTOR, TITLE, PUBLISHER, SITY: STRING [100];
YEAR: 1...9999;
end;
var REFLIST: array [1...MAXNOMBRE] of ENTRY;
Здесь ENTRY - вход, т.е. данные о какой-либо научной работе. Если же некоторые работы входят в журналы, то нужно создавать новый массив данных только для журналов и работать с этими двумя массивами, что не очень удобно. В Паскале есть возможность образовать структуру с вариантами, каждый вход которой соответствует содержанию записи. Это достигается путем введения в описание записи специального оператора CASE- переключателя, который в чем-то похож на ранее введенный, но имеет свои синтаксические и семантические отличия.
В нашем примере, помимо описанного уже типа ENTRY, вводим еще один переменный тип:
ENTRYTYPE = (BOOK,MAGAZINE);
Теперь можно скорректировать раннюю запись:
type ENTRY = record
AUTOR, TITLE: string [100];
YEAR: 1..9999;
case TAG: ENTRYTYPE of
BOOK: (PUBLISHER, SITY: STRING [100]);
MAGAZINE: (MAGNAME: STRING; VOLUME, ISSUE: integer)
END;
Это описание делится на две части: фиксированную и вариантную. Поля: AUTOR, TITLE и YEAR - фиксированная часть. Остальная часть - вариантная, структура которой может меняться в пределах двух вариантов. Вариантная часть записи начинается со строки CASE, где в качестве селектора выступает не выражение, а идентификатор некоторого перечислимого типа. Элементы (компоненты) этого перечислимого типа (в нашем случае ENTRYTYPE) используются в качестве альтернативного определения записи: BOOK и MAGAZINE. В каждой альтернативе имеется свой набор полей:
BOOK: MAGAZINE:
AUTOR AUTOR
TITLE TITLE
YEAR YEAR
PUBLISHER MAGNAME
CITY VOLUME
ISSUE
Для того, чтобы различать, какую из ветвей нужно выбрать для работы, в такую запись вводится так называемое поле ТЕГА (tag fild) или узловое поле. Это дополнительное поле с именем TAG имеет тип ENTRYTYPE и помещается в качестве селектора в оператор CASE - OF:
ENTRY = record
AUT, TIT: string[100];
YEAR: 1..9999;
case TAG: ENTRYTYPE of
BOOK: (PUB,CYTY: string[100]);
MAGAZINE: (MAGNAME: string[100]; VOL,ISSU: integer);
end;
Здесь поле с именем TAG имеет тип ENTRYTYPE и принимает два значения. Если это поле имеет значение BOOK, то это ссылка на книгу, в противном случае - на журнал. Для определения составления записи с вариантами достаточно проверить значение поля TAG.
ПРИМЕР: Процедура печати значений записей типа ENTRY
procedure PRINTREF (CITATION: ENTRY);
begin
with CITATION do begin
writeln (AUTOR); writeln (TITLE); writeln (YEAR);
if TAG = BOOK then
writeln (PUB,',',CITY)
else
begin writeln (MAGNAME);
writeln (VOL,',',ISSUE)
end;
end;
end;
ЗАМЕЧАНИЯ:
1. Вариантная часть может содержать произвольное число аргументов, которые задействуются или перечислимыми типами, или произвольными порядковыми типами (интервалами).
2. Любая запись имеет только одну вариантную часть, которая должна всегда располагаться в конце описания, поэтому END оператора CASE совпадает с END всего описания.
3. Имя поля не может встречаться в двух вариантах одной записи.
4. В вариантной части могут встречаться другие новые вариантные части.
10. ФАЙЛОВЫЙ ТИП
До сих пор все рассмотренные типы переменных отличались тем, что в них заранее известно число компонент и тип этих компонент. Например, массив ARRAY[1..N] OF REAL состоит из N вещественных чисел, а запись:
record
POL1: string[M];
POLN: real;
end;
состоит из N полей, каждое из которых имеет свой тип. Кроме того, характерной особенностью всех рассмотренных ранее типов данных является то обстоятельство, что все эти данные неразрывно связаны с самим текстом программы и "живут" вместе с ней. Это означает, что все данные, присущие некоторой программе, не могут быть отделены от нее и использоваться в другой программе.
Но существует класс задач, когда количество компонент (пусть одного и того же типа) заранее определить невозможно. Оно выясняется только в процессе решения задачи, т.е. во время работы программы. Поэтому возникает необходимость в таком типе значений, которые представляют собой произвольные последовательности элементов одного и того же типа, но длина этих последовательностей заранее не ограничена. Такие типы называют файловыми.
Итак, файл (FILE) представляет собой совокупность данных одинакового типа. В этом файл напоминает массив. Однако у массива с помощью индекса можно указать любой его элемент, например, A[7] - седьмой элемент. У файла же вызывать данные таким образом нельзя.
Условно файлы можно изобразить как некоторую ленту, у которой есть начало, а конец не фиксируется. Элементы файла записываются на эту ленту последовательно, друг за другом:
Файл напоминает магнитную ленту для записи мелодий, начало которой заполнено, а конец пока свободен. Новые записи помещаются в конец ленты. Прокрутить какую-то мелодию на ленте означает сделать протяжку ленты. Существует несколько разновидностей файлов, отличающихся методом доступа к ним. По способу доступа к элементам файла они бывают ПОСЛЕДОВАТЕЛЬНОГО и ПРЯМОГО доступа.
Файлы - это единственный тип данных, посредством которого данные получаются извне (входной файл) и передаются из ЭВМ во внешний мир (выходной файл). Файлы - средство связи с внешним миром.
... .....-46.780 Program Prim24; Var r1,r2:real; BEGIN r1:=-46.78; r2:=-46.78; writeln('r1=',r1:12:3,' r2=',r2:9:4); writeln('_______________________________'); readln; END. 6. Массивы 6. 1. Описание массивов В языке Паскаль можно обрабатывать не только отдельные переменные, но и их совокупности. Одной из таких совокупностей (структурированных) данных является массив. ...
... . Объясните, для чего служат разрешения и привилегии в Windows NT. Зав. кафедрой -------------------------------------------------- Экзаменационный билет по предмету СИСТЕМНОЕ ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ Билет № 22 Перечислите возможности и инструменты системы программирования Microsoft Developer Studio. Укажите для чего предназначается буфер в системах ввода-вывода, ...
... с внешнего устройства (из входного файла) в основную память ЭВМ, операция вывода - это пересылка данных из основной памяти на внешнее устройство (в выходной файл). Файлы на внешних устройствах часто называют физическими файлами. Их имена определяются операционной системой. В программах на языке Паскаль имена файлов задаются с помощью строк. Например, имя файла на диске может иметь вид: ...
0 комментариев