Простые и структурные типы данных
1. Перечисляемый и
ограниченный типы
Ранее рассматривались простые
стандартные типы данных (Integer, Boolean,Char ...) - порядковые
типы, то есть к переменным этих типов применимы Succ и Pred. Real -
не порядковый тип.
В Паскале разрешено введение новых
типов. Секция Type располагается между секцией констант и секцией
переменных. Введение своих типов повышает "читабельность" программ.
Например: Месяцы.
Type
Month = (Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec);
Var
M: Month;
Максимальная мощность перечисляемого
типа - 256 значений, поэтому перечисляемый тип фактически задаёт
подмножество типа Byte.
В Паскале отсутствуют средства,
которые бы позволяли осуществить непосредственный ввод - вывод переменных
перечисляемого типа, однако можно вывести код: Write(Ord(M)).
Кроме того применимы операции
сравнения:
If (M > FEB) And (M < JUN) Then
Write ('Весенний месяц');
Следует иметь ввиду, что
упорядоченность элементов перечисляемого типа определяется порядком их
следования. Самый левый элемент имеет минимальное значение, правый -
максимальное.
Пример:
процедура, в которой переменной перечисляемого типа присваивается
значение, в зависимости от введенного дня недели; если введённые символы
ошибочны, возвращается соответствующее сообщение.
Program DAY (Input, Output);
Type
DayOfWeek = (Sun, Mon, Tue, Wen, Thu, Fri, Sat);
Var
D: DayOfWeek;
Well: Boolean;
Procedure Read_WD (Var I:
DayOfWeek;Well: Boolean;);
Var
C: Char;
Begin
Read(C);
Well:= False;
Case C Of
"S": Begin
Readln(C);
Case C Of
"U": Begin
I:= Sun;
Well:= True;
End;
"A": Begin
I:= Sat;
Well:= True;
End;
End;{Of Case}
"M": Begin
Well:= True;
I:= Mon;
End;
"T": Begin Readln(C);
Case C Of
. . . . . . . . .
End;
"W": Begin
Well:= True;
I:= Wen;
End;
"F": Begin
Well:= True;
I:= Fri;
End;
End;
End;
Begin
Read_WD(D, Well);
If Not Well Then
Writeln ('Ошибка');
End.
Кроме перечисленного типа можно
вводить ограниченные или интервальные типы.
Пример:
Type
Year = 1900..2000;
Letter = "A".."Z";
Левая и правая константы задают
диапазон значений и их называют соответственно верхней и нижней границей
ограниченного типа.
Константы в определении ограниченного
типа должны относиться к одному и тому же базовому типу (целому,
символьному, порядковому). Базовый тип констант определяет допустимость
операций над данными ограниченного типа.
Пример:
Type
Days = (Mo, Tu, We, Th, Fr, Sa, Su);
WeekEnd = Sa..Su;
Var
W: WeekEnd;
. . . . . . . . . . . .
Begin
. . . . . . . . . . . .
W:= Sa;
. . . . . . . . . . . ,
Так как тип-диапазон наследует все
свойства базового типа, но с ограничениями, связанными с его меньшей
мощностью, то Ord(W) вернёт значения S , в то время как Pred(W) приведёт к
ошибке.
И перечисляемый и ограниченный типы
относят к простому типу.
Простой тип - это такой тип, который в некоторый момент времени
хранит только одно значение.
Структурированные типы данных - совокупность связанных данных и
множество правил, определяющих, как их организацию так и способ доступа к
элементам данных.
Массив - это упорядоченный набор переменных одного типа.
Массив содержит фиксированное число компонент, которое задаётся при
определении переменных типа массива. Тип компоненты массива может быть
любым. Каждый элемент масива имеет свой индекс. Тип индекса - простой,
поэтому все элементы массива могут быть перебраны при помощи операторов
цикла.
Описание массивов:
Var
Mas: Array [1..15] Of Real.
Work: Array [(Mon, Tue, Wed)] Of Integer.
B: Array ['A'..'Z'] Of Boolean.
C: Array [1..3, 1..5] Of Real.
D: Array [(Black, White)] Of 11..20.
В Паскале многомерный массив можно
описать как одномерный:
Type
Mas = Array [1..3] Of Array [1..5] Of Integer;
Var
A, B: Mas;
C: Array [1..3, 1..5] Of Integer;
{такая же структура но определена как двумерный массив}
Ссылка на элемент матрицы А, лежащий
на пересечении I-той строки и J-ого столбца выглядит следующим образом
A[I][J]; законно и такое обращение A[2]:= B[1], для массива такая
запись не верна. Все элементы структурированных типов допускают A:= B
(исключение - переменные файлового типа).
Можно использовать комформант -
массивы. Массивы с переменными границами в Турбо-Паскале использовать
нельзя. Нельзя, также и сравнивать массивы:
If A = B Then ...
В Турбо-Паскале предварительно определены два массива Mem и Port.

2. Символьные строки
Переменную типа Packed Array
[0..N] of Char принято называть символьной строкой.
Строка - это упакованный
массив, компоненты которого имеют тип Char и тип индекса имеет нижнюю
границу равную одному. К строкам применимы все 6 операций отношений, но
строки при этом должны иметь равную длину.
В Турбо-Паскале введён тип данных
String вместо описанного Packed Array of Char.
Операции с Char:
'5' < '25' {ошибка, так как разные длины строк}
'Var' = 'Var' {верно}
Var
Age: String [3];
Begin
Age:="тринадцать"; {Лишние символы после "и" усекаются}

3. Множества
Паскаль позволяет оперировать с
множествами как с типами данных.
Пример:
Type
Symbolset = Set Of ' ' .. '_';
Color = (White, Blue, Red);
Colorset = Set Of Color;
T1= Set Of 0..9;
Var
C: Color;
Colset: Colorset;
T: Integer;
Tset: T1;
Множества - наборы однотипных
объектов, каким-либо образом связанных между собой. Характер связей лишь
подразумевается программистом и никак не контролируется Турбо-Паскалем.
Максимальное количество элементов множества - 256.
Два множества считаются
эквивалентными тогда и только тогда, когда все элементы их одинаковы,
причём порядок следования элементов безразличен.
Описание:
<имя типа> = Set Of <базовый тип>, где
<базовый тип> есть любой порядковый тип кроме Word, Integer,
Longint. Для задания множества используется конструктор множества (((: :
=))). Список спецификаций элементов множества, отделяемых друг от друга
запятыми; список обрамляется [ ]. Спецификациями элементов могут быть
константы или выражения базового типа, а так же тип - диапазон того же
базового типа:
Type
Digitchar = Set Of '0'..'9';
Digit =Set Of 0..9;
Var
S1, S2, S3: Digitchar;
S4, S5, S6: Digit;
begin
. . . . . . . . . . . . . . . .
S1 : = ['1', '2', '3'];
S2 : = ['3', '2', '1'];
S3 : = ['2', '3'];
S4 : = [0..3, 6];
S5 : = [4, 5];
S6 : = [3..9];
Операции над множествами:
* |
пересечение (S4*S6 = [3,6]; S4*S5 = [4]) |
+ |
объединение (S4+S5 = [0, 1, 2, 3, 4, 5, 6]) |
- |
разность, содержит элементы из 1-го, которые не
принадлежат второму (S6-S5 = [3, 6, 7, 8, 9]) |
= |
проверка эквивалентности (S4=S4 = true; S5=S4 = false)
|
<> |
проверка неэквивалентности (S4<>S4 = false; S5<>S4
= true) |
<= |
проверка вхождения (True если 1-е содержится во втором).
|
>= |
(наоборот). |
in |
проверка принадлежности. |
Пример:
Алгоритм получение простых чисел.
Const
N = 100;
Type
Set_Of_Num = Set Of 1..N;
Var
N1, Next, I: Word;
Begset, Primerset: Set_Of_Num;
Begin
Begset:= [2..N];
Primerset:= [1];
Next:=2;
While Begset <> [ ] Do
Begin
N1:= Next;
While N1 <= N Do
Begin
Begset:= Begset - [N1];
N1:= N1 + Next;
End;
Primerset:= Primerset + [Next];
Repeat
Inc(Next);
Until (Next In Begset) Or (Next > N);
End;
For I:=1 To N Do
If I In Primerset Then
Write(I: 8);
Writeln;
End.
Итак, над множествами допустимы
четыре операции:
• объединение (+)
• пересечение (*)
• разность (-) (содержит элементы из 1-го, которых нет во 2-ом).
• операция in - позволяет определить, принадлежит элемент множеству или
нет.
В программе множество задаётся в виде
списка элементов, заключённого в квадратные скобки:
Colset:= [White, Red];
Colset:= [ ];
Tset:= [1, 7, 5];
Tset:= [0 ... 3, 6, 9];
Tset:= [8 Mod4, 15 Div 5];
Можно использовать операции сравнения.
Пример: из файла
вводится текст, содержащий символы от "+" до "[". Требуется рассчитать
символы текста в порядке кода ASCII (из повторно встречающихся выводить
только один):
Program Sort
Var
S: Char;
Sets: Set Of '+'..'[';
I: '+'..'[';
Begin
Sets:= [ ];
Read(S);
While Not Eof Do
Begin
While Not Eof Do
Begin
Sets: = Seets + [S];
Read(S);
End;
End;
Writeln;
For I: ='+' To '[' Do
If I In Sets Then
Write (I);
Writeln;
End.

4. Записи
Запись - наиболее общий и
гибкий структурированный тип в Паскале.
Запись состоит из фиксированного
числа компонентов, называемых полями, которые могут быть различных типов.
Этим запись существенно отличается от массива, все компоненты которого
должны быть одного и того же типа и доступ к компонентам осуществляется не
по индексам (номерам), а по именам.
Пример:
Type
Date = Record
Year: Integer;
Month: 1..12;
Day: 1..31;
End;
Book = Record
Title: String [40];
Author: String [50];
Entry: Date;
End;
Var
D1: Date;
B: Book;
В Паскале разрешено использовать
массивы записей. Записи также можно использовать в качестве компонент
файлов. Однако поля записи не могут быть файлового типа. Чтобы обратиться
к отдельной компоненте записи необходимо задать имя записи, за ним точку и
сразу за точкой написать название нужного поля.
Пример1:
D1.Day:=25;
B.Author:= "Levy";
B.Entry.Year:= 1980;
а можно и
B. Entry: = 1980; так как Year первое
поле Date.
Пример2: В памяти
находится массив из 1000 элементов, каждый из которых имеет тип записи
Book. Определить количество книг, год издания которых меньше или равен
1600 году. Для каждого из таких элементов массива распечатать название
книги, имя автора, год издания:
Program Rarity;
Type
Date = Record
. . . . . . . . . . .
End;
Book = Record
. . . . . . . . . . .
End;
Var
S, I: Integer;
Mas: Array[1..1000] Of Book;
Begin
S:= 0;
For I:= 1 To 1000 Do
If Mas[I].Entry.Year <= 1600 Then
Begin
Write (Mas[I].Title,}' , ',Mas[I].Author,',' , ',Mas[I].Entry.Year:
6);
S:= S+1;
End;
Writeln ('Число Книг' , S: 4);
End.
Оператор присоединения With.
Можно сократить длинные обозначения элементов записи:
With имя
записи Do оператор.
Оператор With открывает область
действия, содержащую имена полей указанной переменной типа записи так, что
эти имена фигурируют в качестве имён переменных. Кроме экономии места при
написании программ, оператор With экономит так же время при выполнении
программы, так как ссылка на запись подготавливается только один раз.
Пример:
With B Do
Begin
Title: = ' ... ';
Author:= ' ... ';
End;
эквивалентно
B.Title: = ' ... ';
B.Author:= ' ... ';

5. Запись с
вариантами
Вариантная часть начинается со слова
Case. Это означает, что в записях можно задавать тип, содержащий
определения нескольких вариантов структуры. Различие может касаться как
числа компонент, так и их типов. Запись может содержать только одну
вариантную часть (экономия памяти). Вариантная часть сама может содержать
варианты (вложения).
Пример:
Type
N = String [20];
Status = (Женат, Вдов, Разведён, Холост);
Date = Record
Mo: 1..12;
Day: 1..31;
Year: Integer;
End;
Person = Record
Name: N;
Sex: (Муж, Жена);
Birth: Date;
Case Ms: Status Of
Женат, Вдов: (MDate: Date);
Разведён: (Date: Date; First: Boolean);
Холост: (Indept: Boolean);
End.
Замечательная особенность - наложение
в памяти вариантных полей, то есть дополнительная возможность
преобразования типов:
Var
M = Record
Case Byte Of
0: (By: Array[0..3] Of Byte);
1: (Wo: Array[0..3] Of Word);
2: (Lo: Longint);
End;
. . . . . . . . . . . . . .
With M Do
Begin
Lo: . . . . . .;
If By [3] = 2 Then ... ;
Case Of, открывающее вариантную часть
не имеет ничего общего с ветвлением Case Of; в данном случае это директива
компилятору, сигнализирующая о том, что последующие поля нужно разместить
начиная с одной и той же ячейки памяти, поэтому, если изменяется одно из
полей - вариантов, изменяются и все остальные. Поле выбора должно быть
порядкового типа.
В Турбо-Паскале, в отличие от
классики, переменной, описанной в поле ключа выбора, можно присваивать
значения, но это ни как не влияет на выбор поля. Значения констант выбора
могут быть произвольными и даже повторяющимися. Вместо поля выбора можно
иставить лишь идентификатор какого - либо типа, но в таком случае в
программе невозможно будет узнать, каким из альтернативных полей
используется память, а значит и то, значение какого типа там лежит, но это
не всегда и нужно.
Пример:
Type
Rec1 = Record
A: Byte;
B: Word;
End;
Rec2 = Record
C: Longint;
Case X: Byte Of
1: (D: Word);
2: (E: Record);
Case Boolean Of
3: (F: Rec1);
3: (G: Single);
'3': (C: Word);
End;
End;
Var
2: Rec2
. . . . . . . . . .
R.X: = 255;
If R.E.G = 0 Then
Writeln (0K)
Else
Writeln (R.E.G);
Имена полей должны быть уникальными в пределах той записи, где они
объявлены, однако если записи содержат поля-записи то есть вложены одна в
другую, имена могут повторяться на разных условиях вложенности.

6 Совместимость и
преобразования типов
Турбо-Паскаль - типизированный язык,
следовательно, все применяемые операции определены только над операндами
совместимых типов.
Два типа считаются совместимыми, если
• оба они есть один и тотже тип.
• один тип есть тип-диапазон второго типа.
• оба они являются типами-диапазонами одного и того же базового типа.
• один тип есть строка, а другой - строка или символ.
• оба они есть процедурные типы с одинаковым типом результата (для
типа-функции), одинаковым количеством параметров и одинаковым типом
взаимно соответствующих параметров.
В Турбо-Паскалевской программе данные
одного типа могут преобразовываться в данные другого, явным или неявным
образом.
При явном преобразовании используются
специальные функции Ord, Trunc, Round, Chr,
Ptr (преобразует четырёхбайтный
целочисленный аргумент к типу-указателю).
Преобразование может достигаться
применением идентификатора (имени) стандартного типа, или определённого
пользователем типа, в качестве идентификатора функции преобразования к
выражению преобразуемого типа (так называемое автоопределённое
преобразование типов). Например, допустимы следующие вызовы
функций:
Type Mytype = (A, B, C, D);
. . . . . . . . . . . . . . . . .
Mytype (2);
Integer (D);
Pointer (Longint (A) + $FF);
Char (127 Mod C);
Byte (K);
При автоопределённом преобразовании
типа выражения может произойти изменение длины его внутреннего
представления (уменьшение или увеличение).
В Турбо-Паскале есть ещё один явный
способ: в ту область памяти, которую занимает переменная некоторого типа,
можно поместить значение выражения другого типа, если только длина
внутреннего представления вновь размещаемого значения в точности равна
длине внутреннего представления переменной. С этой целью вновь
используется автоопределённая функция преобразования типов, но уже в левой
части оператора присваивания:
Type
Byt = Array [1..2] Of Byte;
Int = Array [1..2] Of Integer;
Rec = Record
X: Integer;
Y: Integer;
End;
Var
VByt: Byt;
VInt: Int;
VRec: Rec;
Begin
Byt (VInt[1])[2]:= 0;
Int (VRec)[1]:= 256;
End.
Неявное преобразование типов возможно
только в двух случаях:
• выражение из целых и вещественных приводится к вещественным
• одна и та же область памяти трактуется попеременно как содержащая данные
то одного, то другого типа.
Совмещение данных может произойти при
использовании записей с вариантами, типизированных указателей, содержащих
одинаковый адрес, а также при явном размещении данных разного типа в одной
области памяти (используется Absolute
- за ним помещается либо абсолютный адрес, либо идентификатор ранее
определённой переменной).
Абсолютный адрес - пара чисел,
разделённых двоеточием - первое - сегмент, второе - смещение.
Пример:
B: Byte Absolute $0000:$0055;
W: Longint Absolute 128:0;
Если за Absolute указан идентификатор переменной, то происходит совмещение
в памяти данных разного типа, причём первые байты внутреннего
представления данных будут располагаться по одному и тому же абсолютному
адресу:
Var
X: Real;
Y: Array [1..3] Of Integer Absolute X;

7 Типизированные константы
Описываются в разделе констант:
<идентификатор> : <тип> = < значение >
В ходе выполнения программы можно присваивать другие значения.
При повторном входе в блок (процедуру или функцию), в котором объявлена
типизированная константа, переинициализации не происходит и она сохраняет
то значение, которое имела при выходе из блока. Могут быть любого типа,
кроме файлов. Нельзя так же объявить типизированную константу-запись, если
хотя бы одно её поле файлового типа. Нельзя использовать в качестве
значения при объявлении других констант или границ типа-диапазона.
Примеры:
1. Типизированные константы простых типов и типа String:
Type
Colors = (White, Red, Black);
Const
{Правильные объявления}
Cyrrcol: Colrs = Red;
Name: String = 'Ку-Ку';
Year: Word = 1989;
X: Real = 0.1;
Min: Integer = 0;
Max: Integer = 10;
Days: 1..31 = 1;
Answer: Char = 'Y';
{Неправильные объявления}
Mars: Arrray [Min..Max] Of Real;
A,B,C: Byte = 0;
X: Real = Pi;
Var
Namef: String [22] = 'Prog.Pas';
2. Типизированные
константы-массивы
В качестве начального значения используется список констант,
отделённых друг от друга запятыми, список заключается в круглые скобки:
Type
Colors = (White, Red, Black);
Const
Colstr: Arrray [Colors] Of String [5] = ('White', 'Red', 'Black');
Vector: Array [1..5] Of Byte = (0, 0, 0, 0, 0);
При объявлении массива символов можно
использовать то обстоятельство, что все символьные массивы и строки в
Турбо- Паскале хранятся в упакованном формате,.поэтому в качестве значения
массива-константы типа Char допускается указывать символьную строку:
Const
Digit: Array [0..9] Of Char = ('0','1','2','3','4','5','6','7','8','9');
Digchr: Aray [0..9] Of Char = ('0123456789');
При объявлении многомерных -
множество констант, соответствующее каждому измерению заключается в
дополнительные круглые скобки и отделяется от соседей множества запятыми.
Множество констант с максимальной
глубиной вложения связывается с изменением самого правого индекса массива.
Пример - вывести на
экран три строки с монотонно увеличивающимися целыми числами:
Var
I, J, K, L: Integer;
Const
Matr: Array [1..3, 1..5] Of Byte = ((0, 1, 2, 3, 4), (5, 6, 7, 8, 9),
(10, 11, 12, 13, 14));
Cube: Array [0..1, 0..1. 0..2] Of Integer = (((0, 1, 2),(3, 4, 5)), ((6,
7, 8),(9, 10, 11)));
Mas4: Array [0..1, 0..1, 0..1, 0..1] Of Word = ((((0, 1), (2, 3)), ((4,
5), (6, 7))), (((8, 9),
(10, 11)), ((12, 13), (14, 15))));
Begin
{Циклы и Writeln}
End.
Количество переменных в списке
констант должно строго соответствовать объявленной длине массива по
каждому измерению.
3. Типизированные константы-записи.
<идентификатор>:<тип> = (<список значений
полей>)
<тип> - предварительно объявленный тип записи.
<список значений полей > - список из последовательностей следующего
вида: имя поля, двоеточие и константа; элементы списка отделятся друг от
друга точкой с запятой.
Пример:
Type
Point = Record
X,Y: Real;
End;
Vect = Array [0..1] Of Point;
Month = (Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec);
Date = Record
D: 1..31;
M: Month;
Y: 1900..1999;
End;
Const
Orign: Point = (X: 0; Y: -1);
Line: Vector = ((X: -3.1; Y: 1.5), (X: 5.9; Y: 3.0));
Someday: Date = (D: 16; M: Mar; Y: 1989);
Для записей с вариантными полями
указывается только один из возможных вариантов констант:
Type
Forma = Record
Case Boolean Of
True:
(Place: String [40]);
False:
(Country: String [20];
Port: String [20];
Date: Array[1..3] Of Word;
Count: Word)
End;
Const
Con1: Forma = (Country: 'Россия';
Port: 'Москва';
Date: (16,3,89);
Count: 10);
Con2: Forma = (Place: 'Петрозаводск');
4. Типизированные константы
множества.
Значение типизированной константы множества задаётся в виде
правильного конструктора множества:
Type
Days = Set Of 1..31;
Dige = Set Of '0'..'9';
Error = Set Of 1..24;
Const
Workdays: Days = [1..5, 8..12, 15..19, 22..26, 29, 30];
Evendigits: Dige = ['0', '2', '4', '6', '8'];
Errorflag: Error = [ ];
5. Типизированные константы
указатели.
Единственным значением типизированной константы указателя может быть
только Nil:
Const
Pr: ^Real = Nil;
P: POINTER = Nil;

|