ТИПЫ ДАННЫХ
4.1 Типы данных
4.2 Преобразование типов и
действия над ними
4.3
Простые типы
4.3.1
Порядковые типы
4.3.2
Вещественные типы
4.4 Структурированные типы
4.4.1 Массивы
4.4.2 Сортировка массивов
4.4.3 Записи
4.4.4
Множества
4.5
Строки
4.6
Совместимость и преобразование типов
Тесты на закрепление материала
Любые данные, т.е. константы, переменные, значения функций или выражения, в Турбо Паскале характеризуются своими типами. Тип определяет множество допустимых значений, которые может иметь тот или иной объект, а также множество допустимых операций, которые применимы к нему. Кроме того, тип определяет также и формат внутреннего представления данных в памяти ПК.
Турбо Паскаль характеризуется разветвленной структурой типов данных (рис.6).
4.1. ТИПЫ ДАННЫХ
Структура рассмотренной
программы имеет следующий вид:
PROGRAM MyFlrstProgram;
{ Раздел описаний )
BEGIN
{ Раздел операторов }
END.
Слова PROGRAM, BEGIN и END выделяют две
части программы - раздел описаний и
раздел операторов (именно по этому эти
слова всюду в текстах программ и примерах
в книге выделены прописными буквами).
Такая структура обязательна для
любой программы, что следствием жесткого
требования языка: любой нестандартный
для языка Турбо Паскаль идентификатор,
используемый в исполняемых операторах,
должен быть предварительно описан в
разделе описаний. (Стандартные
идентификаторы связаны с предварительно
объявленными объектами и входят в
стандартную библиотеку Турбо Паскаля.
Таким, является идентификатор WR1TELN.
Стандартные идентификаторы, если они
используются в программе, описывать не
нужно).
По сравнению с языком Фортран
требование предварительного описания
идентификаторов кажется чрезмерно
строгим и делающим менее свободным. На
самом деле в нем проявляется тенденция
развил языков программирования в сторону
повышения надежности создаваемой
программы. Кто программировал на языке
Фортран, знает, как бывает трудно
обнаружить в большой программе ошибочно
введенный или пропущенный символ в
идентификаторе. Если, например, всюду в
программе используется переменная с
именем EPSILON, а в одном месте ошибочно
написано EPSLON, то программа может
благополучно откомпилироваться и даже
давать почти правдоподобный результат
для некоторых наборов данных, но в какой-то
момент начнет вести себя стран.
Обязательное предварительное описание
идентификаторов в Турбо Паскале защищает
программы от такого рода ошибок и
повышает их надёжность.
Описать идентификатор - это значит
указать тип связанного с ним объекта
программы (константы или переменной).
Понятие типа - одно фундаментальных
понятий Турбо Паскаля. В гл.4 подробно
рассмотрены различные типы, а здесь лишь
укажем, что тип определяет, во-первых,
способ внутреннего представления
объекта и, во-вторых, действия, которые
разрешается над ним выполнять.
На первых порах понадобятся
следующие простые типы:
INTEGER - целочисленные данные, во внутреннем
представлен занимают 2 байта; диапазон
возможных значений - от -32768 до +32767 данные
представляются точно;
REAL - вещественные данные, занимают б байт;
диапазон возможных значений модуля - от 2.9Е-39
до 1.7Е+38; точность представления данных -
11... 12 значащих цифр;
CHAR - символ, занимает 1 байт;
STRING - строка символов, занимает МАХ+1 байт,
где МАХ - максимальное число символов в
строке;
BOOLEAN - логический тип, занимает 1 байт и
имеет два значения: FALSE (ложь) и TRUE (истина).
Тип константы определяется
способом записи ее значения. Например:
const
С1=17;
C2=3.14;
CЗ='А';
C5=false;
При анализе этого фрагмента
программы компилятор отнесет первую
константу к типу INTEGER, вторую - к типу REAL,
третью - к CHAR, четвертую - к STRING и последнюю
– к BOOLEAN. Признаком, позволяющим отнести
константу к REAL или к INTEGER, является
наличие или отсутствие десятичной точки
в ее значении. Разумеется, константы С2 и С4
относятся к разным типам: С2 - к REAL (в
константе есть десятичная точка), а С4 - к
STRING (константа обрамлена апострофами).
Константу C3 компилятор будет считать
относящейся к типу CHAR: одиночный символ в
апострофах относится к CHAR, в то время как
несколько символов к STRING.
В отличие от константы переменная
именует объект программы, который может
изменять свое значение в ходе счета. При
описании переменных за идентификатором
ставятся двоеточие и имя типа. Несколько
однотипных переменных можно объединять в
список, разделяя их запятыми. В начале
раздела описания переменных должно
стоять зарезервированное слово VAR (VARiables -
переменные). Например:
Var
Sigma: real;
a, b, c, d: char;
textl: string (15);
text2: string;
flag: Boolean;.
Как уже говорилось, тип данных
определяет длину внутреннего
представления соответствующих
переменных. В частности, длина
внутреннего представления переменных
типа STRING (строка символов) зависит от
максимального числа символов, которые
могут составлять строку. В приведенном
выше примере переменная TEXTI описана с
указанием ее максимальной длины (15
символов), а в описании переменной ТЕХТ2
максимальная длина не указана и
компилятор установит для нее предельно
допустимую в Турбо Паскале длину - 255
символов.
Рассмотрим еще одну несложную
программу (пример 2). Ее назначение: ввести
с клавиатуры два целых числа, найти
отношение первого числа ко второму и
вывести полученный результат на экран.
Пример 2.
{Программа вводит два целых числа и
выводит частное от деления 1-го на 2-е }
var
N1, n2: Integer; {n1 и n2 - вводимые целые)
х : real; { х - результат }
BEGIN
wrlte('n1='); {Сообщить о вводе п1}
readln(nl); {Ввести л1}
wrlte(‘n2=‘); {Сообщить о вводе п2}
readln(n2); {Ввести п2 }
x:=n1/n2; {Найти результат }
wrlteln('n1/n2=’,x); {Вывести его }
END.
Прежде всего бросается в глаза появление
в программе поясняющих комментариев.
Комментарий в Турбо Паскале - это
произвольная после любых символов,
обрамленная фигурными скобками.
Комментарий разрешается вставлять в
любое место программы, где по смысл может
стоять пробел. В качестве ограничителей
комментария допускаете использование
фигурных скобок «{» и «}», а также пары
символов: «(*» слева от комментария и «*)» -
справа от него:
{ Это - комментарий }
(* Это - тоже комментарий *)
Комментарии с однотипными
ограничителями нельзя вкладывать друг в
друга, т.е. недопустимы
последовательности вида
{ ... { ... } ... }или (* ... (* ... *) ... *)
Однако можно вкладывать
комментарии с ограничителями разны типов
(не более одной глубины вложения):
{ ... (* ... *) ... }или (* ... { ... } … *)
Последнее обстоятельство
проясняет кажущуюся странной
избыточность ограничителей: если всюду в
программе будут использоваться
ограничители одного типа, то для того,
чтобы временно исключить из программы
какой-либо фрагмент текста, достаточно
заключить его в ограничите ли другого
типа.
Наличие комментариев в программе
избавляет меня от необходимости пояснять
назначение отдельных строк программы.
Несколько слов о вводе данных. Пары
операторов
write (..);
readln(..);
работают следующим образом. Вначале
оператор WRITE выводит на экран и оставляет
курсор в конце только что выведенной
текста. Заметим, что оператор
wrlteln(text);
в примере 1 после вывода текста
осуществлял перевод строки и
устанавливал курсор в начало следующей
строки, экрана. Именно в этом простом
действии (переводе строки) заключается
единственное отличие в процедуры WRITELN от
процедуры WRITE.
Затем по оператору READLN вызывается
встроенная процедура да данных и
программа останавливается в ожидании
ввода. В этот момент необходимо набрать
на клавиатуре нужное число и нажать
клавишу «Ввод». Сразу после этого
программа продолжит работу:
проанализировав введенное число и
перейдет к вводу следующего числа или
вычислению результата. Таким образом,
сигналом окончания подготовки
очередного числа является нажатие на
клавишу «Ввод», до этого момента можно
стирать любой ошибочно введенный символ
клавишей «Забой».
Для вычисления отношения
введенных чисел используется один из
основных операторов Турбо Паскаля -
оператор присваивания. В его левой части
указывается имя переменной, правая часть
представляет собой выражение того же
типа, что и переменная. Пара символов «:=»,
связывающая левую и правую части
оператора присваивания, означает «присвоить
значение». Запомним: в операторах
присваивания Турбо Паскаль всегда
используются символы<:=>, в то время как
при описании констант -одиночный символ «-».
С точки зрения синтаксиса языка, два
символа<:=> рассматриваются как один
специальный символ и обязательно пишутся
слитно.
Оператор присваивания
используются практически во всех языках
программирования. В некоторых языках,
например в Фортране или Бейсике , символ
присваивания является знак равенства,
однако новичка, привыкшего к строгости
математических формул, может озадачить
типичная форма записи Фортран- оператора
присваивания, например, такая:
X=x+1
Вариант записи на Турбо Паскале
X:=x+1
в этом смысле кажется более логичным.
Разумеется, вряд ли кому-нибудь придет в
голову видеть уравнения там, где их нет.
Конечно же, и в том, и в том, и другом
случае реализуется одно и то же
алгоритмическое действие: к содержимому X
прибавляется 1 и полученный результат
вновь присваивается переменной X.
Обратите внимание на оператор вывода
результатов
writeln (‘n1/n2=’,x);
В нём в качестве одного из
параметров явно указывается константа
типа строка символов ' П 1 / П 2. 'Конечно же,
константы (в отличие от временных) вовсе
не обязательно описывать в разделе
описаний, так как тип легко определяется
компилятором по форме записи константы. С
отчетом этого можно было бы записать
программу из примера 1 предельно конечно:
BEGIN
writeln('Я программирую на Турбо Паскале');
END.
4.2. ПРЕОБРАЗОВАНИЯ ТИПОВ И ДЕЙСТВИЯ НАД НИМИ
Как уже говорилось, тип переменной
позволяет не только устанавливать длину
ее внутреннего представления, но и
контролировать те действия, которые
выполняются над ней в программе. Контроль
за использованием переменных еще на
этапе компиляции программы - важное
преимущество Турбо Паскаля перед другими
языками программирования, в которых
допускается автоматическое
преобразование типов. В Турбо Паскале
почти невозможны неявные (автоматические)
преобразования типов. Исключение сделано
только в отношении констант и переменных
типа INTEGER (целые), которые разрешается
использовать в выражениях типа REAL (вещественные).
Если, например, переменные X и У описаны
следующим образом:
var
х : Integer;
у : real:
то оператор
у :=х . 2:
будет синтаксически правильным, хотя
справа от знака присваивания стоит
целочисленное выражение, а слева -
вещественная переменная компилятор
сделает необходимые преобразования
автоматически. В то время оператор
х:= 2.0;
будет неверным, так как автоматическое
преобразование типа REAL (константа 2.0
содержит десятичную точку и,
следовательно, принадлежит к типу REAL) в
тип INTEGER в Турбо Паскале запрещено.
Разумеется, запрет на
автоматическое преобразование типов еще
и означает, что в Турбо Паскале нет
средств преобразования данных. Они
конечно же, есть, но их нужно использовать
явно (подробнее об этом cм гл.4). Для
преобразования данных в языке существуют
встроенные функции, которые получают в
качестве параметра значение одного типа,
возвращают результат в виде значения
другого типа. В частности, для
преобразования REAL в INTEGER имеются даже две
встроенные функции такого рода: ROUND
округляет REAL до ближайшего целого, TRUNC
усекает REAL путем отбрасывания дробной
части.
Например, ошибочным будет
оператор
х := у/х;
но правильным
х :=round(y/x): (объявления переменных см. выше).
Понятие функции в Турбо Паскале
близко к понятию процедур) Как и
процедура, функция вызывается своим
именем и может содержа: произвольное
число операторов Турбо Паскаля и даже
внутренних процедур и функций.
Существенным отличием функции от
процедуры является то обстоятельство,
что функция имеет собственное значение и,
следовательно, может использоваться
наравне с переменными в выражений
соответствующего типа.
Для преобразования данных типа CHAR
(символ) в целое число предназначена
функция ORD, обратное преобразование INTEGER
CHAR осуществляет функция CHR.
С помощью несложной программы (пример
3) Вы сможете узнать внутренний код
произвольного символа. Пример:.
{ Программа читает символ с клавиатуры и
выводит на экран этот символ и
соответствующий ему внутренний код }
var
clt : char; { В эту переменную читается
символ }
BEGIN
wrlte('Введите любой символ: ');
readln(ch); { Читать один символ );
writeln(ch, '=' .ord(ch); { Преобразовать его к
целому и вывести на экран }
END.
Обратите внимание: при вызове
writeln(ch, '=', ord(ch));
третьим параметром обращения указан
вызов функции ORD(CH), что с гонки зрения
языка является выражением; как мы увидим
дальше (см. гл.8), во многих случаях при
вызове процедур и функций в качестве
параметров вызова можно указывать не
только переменные или константы, но и
выражения с их участием.
По мере надобности мы будем
знакомиться с другими функциями
преобразования типов данных, а сейчас - о
тех операциях, которые разрешены над
различными типами.
Конечно же, в Турбо Паскале есть
все четыре арифметические операции над
переменными REAL и INTEGER: + - сложение; -
вычитание; * - умножение; / - деление
вещественное; div - деление целочисленное.
Наличие двух операций деления
есть еще одно проявление
основополагающего принципа Турбо
Паскаля: программист должен явно
подтверждать компилятору, что он готов к
возможным последствиям преобразования
типов. Если, например, в языке Фортран
используется выражение 1/2 , то результат
этого выражения будет зависеть от того,
переменной какого типа он будет присвоен:
если N есть переменная целого типа, а X -
вещественного, то в программе на Фортране
присваивания
N = Ѕ
X = 1/2
дадут значения 0 для N и 0.5 для X. В Турбо
Паскале такой двусмысленности нет:
выражение 1/2 всегда имеет значение 0.5 и
поэтому оператор
var
N : Integer:
N := 1/2;
просто недопустим. В то же время
допустимый в Турбо Паскале оператор
var
X : real;
X := 1 dlv 2;
самим фактом использования операции
целочисленного деления D1V
свидетельствует о том, что программист
сознательно отбрасывает дробную часть
результата. (Надеюсь, что читатель
извинит явную искусственность этих
примеров, которая вызвана лишь
стремлением проиллюстрировать
обсуждаемые особенности языка).
Для данных типа INTEGER в Турбо
Паскале есть еще одна операция деления -
MOD, т.е. получение остатка от
целочисленного деления. Например:
5mod 2=1
31 mod 16=15
18 mod 3=0
В Турбо Паскале отсутствует
операция возведения в степень, что
очевидно, будет вызывать определенные
неудобства при реализации м числительных
алгоритмов. Некоторым утешением может
служить шип чие встроенной функции SQR,
возвращающей квадрат от значения
параметра, причем тип результата
определяется типом параметра. (Читателям,
имеющим опыт программирования на Бейсике,
следует учесть, 41 функция SQR(X) в Турбо
Паскале имеет прямо противоположный
математический смысл по сравнению с
одноименной функцией в Бейсике, которая
извлекает корень квадратный из параметра
X).
И еще об одном существенном
недостатке Турбо Паскаля: в отсутствуют
комплексный тип и соответствующие
операции над ними. Вообще, в отношении
реализации разнообразных вычислительных
процедур Турбо Паскаль значительно
уступает Фортрану ОС ЕС. В частности, в
нем намного беднее набор встроенных
математических функций (см. гл. 4).
При работе с целыми числами могут
оказаться полезными две процедуры (здесь
и далее в квадратных скобках указываются
необязательны параметры):
DEC(X [,N]) - уменьшает содержимое переменной X
на значение выражения N (если N не задано,
то на 1); тип переменной X и выражение N -
INTEGER (точнее, любой целый, см. гл. 4);
INC(X [,N]) - увеличивает значение X на N (если N
не задано, то на 1).
Над символами и строками символов
определена единственная опeрация -
сцепление двух строк. Операция
обозначается символом «+» Например,
программа
var
st:string;
BEGIN
st:='Турбо' + '-‘ + 'Паскаль ':
writeIn(11):
END.
напечатает строку
Турбо-Паскаль
Все остальные действия над строками и
символами реализуются c помощью
встроенных процедур и функций (см. гл.4).
И, наконец, об операциях отношения
и логических операциях.
Над данными типа REAL, INTEGER, CHAR, STRING
определены
следующие операции отношения (сравнения):
= - равно;
<> - не равно;
< - меньше;
> -больше;
<= - меньше или равно,
>= - больше или равно.
В операциях сравнения должны
участвовать однотипные операнды.
Исключение сделано опять-таки в
отношении REAL и INTEGER, которые могут
сравниваться друг с другом. Результат
применения операции отношения к любым
операндам имеет тип BOOLEAN.
Сравнение двух строк осуществляется
следующим образом. Символы строк
сравниваются попарно друг с другом так,
что первый символ первой строки
сравнивается с первым символом второй
строки, второй символ первой строки - со
вторым символом второй и т.д. Символы
сравниваются путем сравнения их кодов во
внутреннем представлении (см. гл. 4 и прил.
2). Если одна строка короче другой,
недостающие символы заменяются нулем.
Отношение первой несовпадающей друг с
другом пары символов и принимается за
отношение двух строк.
При сравнении данных типа BOOLEAN
учитывается внутреннее соглашение Турбо
Паскаля, в соответствии с которым FALSE есть
нулевой байт, a TRUE- байт с единицей в
младшем разряде. Заметим, что функция ORD
преобразует к целому не только символы,
но и логические величины, поэтому
ord(false)-0, ord(true) -1.
В Турбо Паскале определены
следующие логические операции:
not - логическое НЕ; or - логическое ИЛИ;
and - логическое И; хоr - исключительное ИЛИ.
Логические операции применимы к
операндам целого и логического типов.
Если операнды - целые числа, то результат
логической операции есть тоже целое
число (подробнее об этом сказано в гл.4).
Логические операции над логическими
данными дают результат логического типа.
При вычислении выражений любого
типа приоритет вычислений определяется
расставленными скобками, а при их
отсутствии - по табл. 1 (в порядке убывания
приоритета).
Таблица 1.
Приоритет операций |
|
Приоритет |
Операция |
1 | Not, @ |
2 | *, /, div, mod, and, shl, shr |
3 | +, -, or, xor |
4 | =, <>, <, >, <=, >=, in |
Примечание. Операции @ (получение
адреса объекта), in (принадлежность к
множеству), shl и shr (сдвиги операндов)
описаны в гл.4.
Следует учесть, что в отличие от
многих других языков программирования в
Турбо Паскале логические операции имеют
более высокий приоритет, чем операции
отношения. В связи с этим, в сложных
логических выражениях обычно необходимо
расставлять скобки. Если, например, бис
имеют тип INTEGER , то выражение
(a = b) and ( c < d )
4.3. ПРОСТЫЕ ТИПЫ
4.3.1. Порядковые типы
К порядковым типам относятся (см.
рис.6) целые, логический, символьный,
перечисляемый и тип-диапазон. К любому из
них применима функция ORD(X), которая
возвращает порядковый номер значения
выражения X. Для целых типов функция ORD(X)
возвращает само значение X, т.е. ОRD(Х)-Х или
Х, принадлежащего любому целому типу.
Применение ORD(X) к логическому,
символьному и перечисляемому типам дает
положительное целое число в диапазоне от
0 до 1 (логический тип), от 0до 255 (символьный),
от 0до 65535 (перечисляемый). Тип-диапазон
сохраняет все свойства базового
порядкового типа, поэтому результат
применения к нему функции ORD(X) зависит от
свойств этого типа.
К порядковым типам можно также
применять функций:
PRED(X) - возвращает предыдущее значение
порядкового типа (значение, которое
соответствует порядковому номеру ORD(X)-1), т.е.
ORD(PRED(X)) - ORD(X) - I;
SUCC(X) - возвращает следующее значение
порядкового типа, которое соответствует
порядковому номеру ORD(X)+1, т.е. ORD(SUCC(X)) - ORD(X)
+1.
Например, если в программе определена
переменная
var с : char;
"с":= ‘5’:,
то функция PRED(C) вернет значение '4', а
функция SUCC(C) - значение '6'.
Если представить себе любой
порядковый тип как упорядоченное
множество значений, возрастающих слева
направо и занимающих на числовой оси
некоторый отрезок, то функция PRED(X) не
определена для левого, a SUCC(X) - для правого
конца этого отрезка.
Целые типы. Диапазон возможных значений
целых типов зависит от их внутреннего
представления, которое может занимать
один, два или четыре байта. В табл. 4
приводится название целых типов, длина их
внутреннего представления в байтах и
диапазон возможных значений.
Таблица 4
Длина, байт | Название типа | Диапазон значений |
1 | byte | 0....255 |
1 | shortint | -128...127 |
2 | word | 0..65535 |
2 | integer | -32768...32767 |
4 | longint | -21747483648..2147483647 |
Обращение | Тип результата | Действие |
abs(x) | x | Возвращает модуль X |
chr(b) | Char | Возвращает символ по его коду |
dec(vx[,i]) | Процедура | Уменьшает значение vx на i, при отсутствии i- на 1. |
Inc(vx[,i]) | Процедура | Увеличивает значение vx на i, при отсутствии i- на 1. |
hi(i) | Byte | Возвращает старший байт аргумента |
hi(w) | То же | То же |
lo(i) | '' | Возвращает младший байт аргумента |
lo(w) | '' | То же |
odd(i) | boolean | Возвращает True, если аргумент - не чётное число, false если чётное |
random(w) | Как у параметра | Возвращает псевдослучайное число, равномерно распределённое на интервале 0<=x<w |
sqr (x) | То же | Возвращает квадрат аргумента |
swap(i) | integer | Меняет местами байты в слове |
swap(w) | word | То же |
Код | Символ | Код | Символ | Код | Символ | Код | Символ |
0 | NULL | 32 | BL | 64 | @ | 96 | ' |
1 | SOH | 33 | ! | 65 | A | 97 | a |
2 | STX | 34 | '' | 66 | B | 98 | b |
3 | ETX | 35 | # | 67 | C | 99 | c |
4 | EOT | 36 | $ | 68 | D | 100 | d |
5 | ENQ | 37 | % | 69 | E | 101 | e |
6 | ACK | 38 | & | 70 | F | 102 | f |
7 | BEL | 39 | ' | 71 | G | 103 | g |
8 | BS | 40 | ( | 72 | H | 104 | h |
9 | HT | 41 | ) | 73 | I | 105 | i |
10 | LF | 42 | * | 74 | J | 106 | j |
11 | VT | 43 | + | 75 | K | 107 | k |
12 | FF | 44 | , | 76 | L | 108 | l |
13 | CR | 45 | - | 77 | M | 109 | m |
14 | SO | 46 | . | 78 | N | 110 | n |
15 | SI | 47 | / | 79 | O | 111 | o |
16 | DEL | 48 | 0 | 80 | P | 112 | p |
17 | DC1 | 49 | 1 | 81 | Q | 113 | q |
18 | DC2 | 50 | 2 | 82 | R | 114 | r |
19 | DC3 | 51 | 3 | 83 | S | 115 | s |
20 | DC4 | 52 | 4 | 84 | T | 116 | t |
21 | NAK | 53 | 5 | 85 | U | 117 | u |
22 | SYN | 54 | 6 | 86 | V | 118 | v |
23 | ETB | 55 | 7 | 87 | W | 119 | w |
24 | CAN | 56 | 8 | 88 | X | 120 | x |
25 | EM | 57 | 9 | 89 | Y | 121 | y |
26 | SUB | 58 | : | 90 | Z | 122 | z |
27 | ESC | 59 | ; | 91 | [ | 123 | { |
28 | FS | 60 | < | 92 | \ | 124 | | |
29 | GS | 61 | = | 93 | ] | 125 | } |
30 | RS | 62 | > | 94 | ^ | 126 | ~ |
31 | US | 63 | ? | 95 | _ | 127 | ^ |
Символы с кодами 0...31 относятся к
служебным кодам. Если эти коды
используются в символьном тексте
программы, они считаются пробелами. При
использовании их в операциях ввода-вывода
они могут иметь следующее
самостоятельное значение:
Символ Код Значение
BEL 7 Звонок;
вывод на экран этого символа
сопровождается звуковым сигналом
НТ 9 Горизонтальная табуляция;
при выводе на экран смещает курсор в
позицию, кратную 8, плюс 1 (9,17, 25 и т.д.)
LF 10 Перевод строки;
при выводе его на экран все последующие
символы будут выводиться, начиная с той
же позиции, но на следующей строке
VT 11 Вертикальная табуляция;
при выводе на экран заменяется
специальным знаком
FF 12 Прогон страницы;
при выводе на принтер формирует страницу,
при выводе на экран заменяется
специальным знаком
CR 13 Возврат каретки;
вводится нажатием на клавишу Enter (при
вводе с помощью READ или READLN означает
команду «Ввод» и в буфер ввода не
помещается; при выводе означает команду «Продолжить
вывод с начала текущей строки»)
SUB 26 Конец файла;
вводится с клавиатуры нажатием Ctrl-Z; при
выводе заменяется специальным знаком
ESC 27 Конец работы;
вводится с клавиатуры нажатием на
клавишу ESC; при
выводе заменяется специальным знаком
К типу CHAR применимы операции отношения, а
также встроенные функции:
CHR(B) - функция типа CHAR; преобразует
выражение В типа БУГЕ в символ и
возвращает его своим значением;
UPCASE(CH) - функция типа CHAR; возвращает символ
в верхнем регистре, если он определен для
аргумента СН типа CHAR; в противном случае
возвращает сам символ СН, например:
var
с1,с2 : char;
begin
c1:=UpCase('s’);
c2:=UpCase('ф'};
writeln(d, ' ' ,c2);
end.
В результате прогона этой программы на
экран будет выдано
S ф
так как функция UPCASE не обрабатывает
кириллицу.
Перечисляемый тип. "Перечисляемый
тип задается перечислением тех значений,
которые он может получать. Каждое
значение именуется некоторым
идентификатором и располагается в списке,
обрамленном круглыми скобками, например:
type
colors = (red, white, blue);
Применение перечисляемых типов
делает программы нагляднее. Если,
например, в программе используются
данные, связанные с месяцами года, то
такой фрагмент программы:
type
ТипМесяц=(янв,фев,мар,апр,май,июн,июл,aвг,сен,окт,ноя,дек);
var
месяц : ТипМесяц;
if месяц-авг then writetn('Хорошо бы поехать
к морю!');
был бы, согласитесь, очень наглядным. Увы!
В Турбо Паскале нельзя использовать
кириллицу в идентификаторах, поэтому мы
вынуждены писать так:
type .
TypeMonth=(Jan.feb.mar.may,Jun,jul,aug,sep,oct,nov,dec);
var
month: TypeMonth;
if'month=aug then writeIn('Хорошо бы поехать к
морю!'):
Соответствие между значениями
перечисляемого типа и порядковыми
номерами этих значений устанавливается
порядком перечисления: первое значение в
списке получает порядковый номер 0,
второе - 1 и т.д. Максимальная мощность
перечисляемого типа составляет 65535
значений, поэтому фактически
перечисляемый тип задает некоторое
подмножество целого типа WORD и может
рассматриваться как компактное
объявление сразу группы целочисленных
констант со значениями 0, 1 и т.д.
Использование перечисляемых
типов повышает надежность программ
благодаря возможности контроля тех
значений, которые получают
соответствующие переменные. Пусть,
например, заданы такие перечисляемые
типы:
type
colors = (black, red, white);
ordenal= one, two, three);
days = (tnonday, tuesday, Wednesday);
С точки зрения мощности и внутреннего
представления все три типа эквивалентны:
ord(black)-0, .... ord(white)-2,
ord(one)-0, ... , ord(three)-2,
ord(monday)-0, ... , ord(wednesday)-2.
Однако, если определены переменные
var
col : colors;
num : ordenal;
day : days; то допустимы операторы
col := black;
num := succ(two);
day := pred(tuesday); но недопустимы
col := one;
day := black: и т.д:
Как уже упоминалось, между
значениями перечисляемого типа и
множеством целых чисел существует
однозначное соответствие, задаваемое
функцией ORD(X). В Турбо Паскале допускается
и обратное преобразование: любое
выражение типа WORD можно преобразовать в
значение перечисляемого типа, если
только значение целочисленного
выражения не превышает мощности
перечисляемого типа. Такое
преобразование достигается применением
автоматически объявляемой функции с
именем перечисляемого типа (см. п. 4.4).
Например, для рассмотренного выше
объявления типов эквивалентны следующие
присваивания:
col := one;
col := colors(O); Разумеется, присваивание
col := 0; будет недопустимым.
Переменные любого перечисляемого
типа можно объявлять без
предварительного описания этого типа,
например:
var
col : (black, white, green);
Тип-диапазон. Тип-диапазон есть
подмножество своего базового типа, в
качестве которого может выступать любой
порядковый тип, кроме типа-диапазона.
Тип-диапазон задается границами своих
значений внутри базового типа:
< мин. знач. >.. <макс.знач. >
Здесь <мин.знач.> - минимальное
значение типа-диапазона; <макс.знач-> -
максимальное его значение. Например:
type
digit - '0'..'9'; dig2 - 18 .. 57:
Тип-диапазон необязательно
описывать в разделе TYPE, а можно указывать
непосредственно при объявлении
переменной, например:
var
date 1..31: month 1..12: Ichr 'A'..'Z':.
При определении типа-диапазона
нужно руководствоваться следующими
правилами:
• два символа «..» рассматриваются как
один символ, поэтому между ними
недопустимы пробелы;
• левая граница диапазона не должна
превышать его правую граничу.
Тип-диапазон наследует все
свойства своего базового типа, но с
ограничениями, связанными с его меньшей
мощностью. В частности, если определена
переменная
Type
days = (mo.tu.we,th.fr.sa.su);
WeekEnd = sa .. su;
var
w : WeekEnd:
w := sa;
то ORD{W} вернет значение 5 , в то время как PRED(W)
приведет к ошибке.
4.3.2. Вещественные типы
В отличие от порядковых типов,
значения которых всегда сопоставляются с
рядом целых чисел и, следовательно,
представляются в ПК абсолютно точно,
значения вещественных типов определяют
произвольное число лишь с некоторой
конечной точностью, зависящей от
внутреннего формата вещественного числа.
Таблица 7.
Вещественные типы
Длина,
байты |
Название типа | Мантисса, значащие цифры | Диапазон десятичного порядка |
4 | single | 7...8 | -45...+38 |
6 | real | 11..12 | -39...+38 |
8 | double | 15...16 | -324...+308 |
10 | extended | 19..20 | -4951..+4932 |
8 | comp | 19..20 | -2(63)+1...+2(63)-1 |
s | e | m |
Здесь s - знаковый разряд числа; е -
экспоненциальная часть; содержит
двоичный порядок; т - мантисса числа.
Мантисса т имеет длину от 23 (для SINGLE) до 63 (для
EXTENDED) двоичных разрядов, что и
обеспечивает точность 7...8 для SINGLE и 19...20
для EXTENDED десятичных цифр. Десятичная
точка (запятая) подразумевается перед
левым (старшим) разрядом мантиссы, но при
действиях с числом ее положение
сдвигается влево или вправо в
соответствии с двоичным порядком числа,
хранящимся в экспоненциальной части,
поэтому действия над вещественными
числами называют арифметикой с плавающей
точкой (запятой).
Как видим, Турбо Паскаль
характеризуется богатой гаммой веществ
венных типов, однако доступ к типам SINGLE,
DOUBLE и EXTENDED возможен только при особых
режимах компиляции. Дело в том, что эти
типы рассчитаны на аппаратную поддержку
арифметики с плавающей точкой и для их
эффективного использования в состав ПК
должен входить арифметический
сопроцессор 8087, 80287 или их отечественный
аналог К181ОВМ87.
Компилятор Турбо Паскаля позволяет
создавать программы, работающие на любых
ПК (с сопроцессором или без него) и
использующие любые вещественные типы.
Необходимая для этого настройка
компилятора описана в прил. 1. В процессе
запуска Турбо Паскаль проверяет состав
аппаратных средств и выявляет наличие
или отсутствие сопроцессора.
В некоторых случаях бывает необходимо
отключить автоконтроль. Для этого перед
запуском Турбо Паскаля следует дать
такую команду ДОС:
set 87-N Команда
set 87-Y напротив, включает автоконтроль -
эта команда активна по умолчанию.
Отметим, что арифметический
сопроцессор всегда обрабатывает числа в
формате EXTENDED, а три других вещественных
типа в этом случае получаются простым
усечением результатов до нужных размеров
и применяются в основном для экономии
памяти.
Например, если «машинное эпсилон»
(см. пример б в гл.2) вычисляется с помощью
такой программы:
{SN+.E+}
type
RealType = real;
Обращение | Тип параметра | Тип результата | Примечание |
abs(x) | real, integer | Тип аргумента | Модуль аргумента |
ArcTan(x) | real | real | Арктангенс(радианы) |
cos(x) | То же | То же | Косинус, угол в радианах |
exp(x) | '' | '' | Экспонента |
frac(x) | '' | '' | Дробная часть числа |
int(x) | '' | '' | Целая часть числа |
in(x) | '' | '' | Логарифм натуральный |
pi | - | real | П=3.141592653 |
Random | - | real | Равномерное псевдослучайное число 0<=x<1 |
Random(x) | integer | integer | Равномерное псевдослучайное целое число 0<=i<x |
Randomize | - | - | Инициация датчика псевдослучайных чисел |
sin(x) | real | real | Синус, угол в радианах |
sqr(x) | real, integer | тип аргумента | Квадрат аргумента |
sqrt(x) | real | real | Корень квадратный |
При решении задачи сортировки обычно выдвигается требование минимального использования дополнительной памяти, из которой вытекает недопустимость применения дополнительных массивов.
Для оценки быстродействия алгоритмов различных методов сортировки, как правило, используют два показателя:
Количество присваивания;
Количество сравнений;
Все методы сортировки можно разделить на две большие группы:
Прямые методы сортировки;
Улучшенные методы сортировки;
Прямые методы сортировки по принципу, лежащему в основе метода, в свою очередь разделяются на три группы:
1) сортировка вставкой (включением)
2) сортировка выбором (выделением)
3) сортировка обменом (‘пузырьковая’ сортировка )
Улучшенные методы сортировки основываются на тех же принципах, что и прямые, но используют некоторые оригинальные идеи для ускорения процесса сортировки. Прямые методы на практике используются довольно редко, так как имеют относительно низкое быстродействие. Однако они хорошо показывают суть основанных на них улучшенных методов. Кроме того, в некоторых случаях (как правило, при небольшой длине массива или особом расположении элементов массива) некоторые из прямых методов могут даже превзойти улучшенные методы.
Сортировка вставкой
Принцип метода:
Массив разделяется на две части: отсортированную и не отсортированную. Элементы из не отсортированной части поочерёдно выбираются и вставляются в отсортированную часть так, чтобы не нарушить в ней упорядоченность элементов. В начале работы алгоритма в качестве отсортированной части массива принимают только один первый элемент, а в качестве не отсортированной части – все остальные элементы.
Таким образом, алгоритм будет состоять из n-1-го прохода (n- размерность массива), каждый из которых будет включать четыре действия:
Взятие очередного i- го не отсортированного элемента и сохранение его в дополнительной переменной;
Поиск позиции j в отсортированной части массива, в которой присутствие взятого элемента не нарушит упорядоченности элементов;
Сдвиг элементов массива от i- 1- го до j- 1- го вправо, чтобы освободить найденную позицию вставки;
Вставки взятого элемента в найденную j- ю позицию.
Для реализации данного метода можно предложить несколько алгоритмов, которые будут отличатся способом поиска позиции вставки.
Рассмотрим схему реализации одного из возможных алгоритмов.
Схематично описанные действия одного прохода можно представить следующим образом
Схема сортировки методом вставки. Слева в кружке указан номер прохода
Программа, реализующая рассмотренный алгоритм, будет иметь следующий вид:
Демонстрация
Program InsertionSort;
Uses Crt;
Const
N= 20; {длина массива}
Type
Tvector= array [1..n] of real;
Var
Vector : Tvector;
B : Real;
I, j, k : integer;
Begin
ClrScr;
Writeln (‘Введите элементы массива:’);
For i:=1 to n do Read (Vector[i]); Readln;
{-----------------------------------------------------------------}
for i:= 2 to n do
begin
B:= Vector[i]; {Взятие не отсортированного элемента}
{Цикл поиска позиции всиавки}
j:= 1;
while (B> Vector[j]) do
j:= j+1; {После окончания цикла индекс j фиксирует позиции вставки}
{Цикл сдвига элементов для освобождения позиции вставки}
for k:= i-1 downto j do
Vector[k+1] := Vector [k];
{Вставка взятого элемента на найденную позицию }
Vector[j] := B;
End;
{--------------------------------------------------------------------------}
writeln(‘Отсортированный массив:’);
for i := 1 to n do write (Vector[i]:8:2);
writeln;
end.
Сортировка выбором
Принцип метода:
Находим (выбираем) в массиве элемент с минимальным значением на интервале от 1- го элемента до n- го (последнего) элемента и меняем его местами с первым элементом. На втором шаге находим элемент с минимальным значением на интервале от 2- го до n –го элемента и меняем местами со вторым элементом.
И так далее для всех элементов до n-1- го.
Рассмотрим схему алгоритма прямого выбора.
Программа, реализующая метод выбора, будет иметь следующий вид:
Демонстрация
Program SelectionSort;
Uses Crt;
Const
N= 20 ; {длина массива}
Type
Tvector = array [1..n] of real;
Var
Vector : Tvector;
Min : Real;
Imin, S : Integer;
I: Integer;
Begin
ClrScr;
Writeln (‘Введите элементы массива:’);
For i:= 1 to n do Read (Vector[i]); Readln;
{----------------------------------------------------------------------}
for S:=1 to n-1 do
begin
{Поиск минимального элемента в диапазоне}
{от S- го элемента до n- го}
min := vector[S];
Imin := S;
For i := S+1 to n do
If vector[i] < min then
Begin
Min:= vector[i];
Imin := i;
End;
{Обмен местами минимального и S –го элементов}
vector[imin] := vector[S];
vector[S] := Min;
end;
{--------------------------------------------------------------------------}
writeln(‘Отсортированный массив:’);
for i:= 1 to n do write (vector[i] :8:2);
writeln;
end.
Сортировка обменом (‘пузырьковая’ сортировка)
Принцип метода:
Слева направо поочерёдно сравниваются два соседних элемента, и если их взаиморасположение не соответствует заданному условию упорядоченности, то они меняются местами. Далее берутся два следующих соседних элемента и так далее до конца массива.
После одного такого прохода на последней n- ой позиции массива будет стоять максимальный элемент(‘всплыл’ первый ‘пузырёк’). Поскольку максимальный элемент уже стоит на своей последней позиции, то второй проход обменов выполняется до n-1- го элемента. И так далее. Всего требуется n-1 проход.
Рассмотрим схему алгоритма сортировки методом прямого обмена по не убыванию.
Программа, реализующая метод обмена(‘пузырька’ ), будет иметь следующий вид:
Program BubleSort;
Uses Crt;
Const
N= 20; {Длина массива}
Type
Tvector = array [1..n] of real;
Var
Vector : Tvector ;
B : Real;
I, k: integer;
Begin
ClrScr;
Writeln {‘Введите элемент массива:’};
For i:= 1 to n do Read (Vector[i]); Readln;
{-------------------------------------------------------------}
for k:= n downto 2 do
{‘Всплывание ’ очередного максимального элемента на k- ю позицию }
for i:= 1 to k-1 do
if Vector[i] > Vector[i+1] then
begin
B:= Vector[i];
Vector[i+1] :=B
End;
{------------------------------------------------------------------}
writeln {‘Отсортированный массив:’};
for i:= 1 to n do write (Vector[i]:8 :2);
writeln;
end.
Сравнение прямых методов сортировки
Теоретическиеи практические исследования алгоритмов прямых методов сортировки показали, что как по числу присваивания они имеют квадратичную зависимость от длины массива n. Исключение составляет метод выбора, который имеет число присваиваний порядка n*ln(n). Это свойство алгоритма выбора полезно использовать в задачах сортировки в сложных структурах данных, когда на одно сравнение выполняется большое число присваиваний. В таких задачах метод выбора успешно конкурирует с самыми быстрыми улучшенными методами сортировки.
Принцип двоичного поиска:
Исходный массив делится пополам и для сравнения выбирается средний элемент. Если он совпадает с искомым, то поиск заканчивается . Если же средний элемент меньше искомого, т овсе элементы левее его также будет меньше искомого. Следовательно, их можно исключить из зоны дальнейшего поиска, оставив только правую часть массива. Аналогично, если средний элемент больше искомого, то отбрасывается правая часть, а остаётся левая.
На втором этапе выполняется аналогичные действия над оставшейся половине массива.
И так далее, пока элемент не будет найден, или длина зоны поиска станет равной нулю. В последнем случае искомый элемент найден не будет.
Рассмотрим схему алгоритма двоичного поиска.
Одно из возможных вариантов программы, реализующей метод двоичного поиска, имеет следующий вид:
Program BinSearch;
Uses Crt;
Const
N= 20; {Длина массива}
Type
Tvector = array [1..n] of real;
Var
Vector : Tvector; {Исходный массив}
X : Real; { Искомый элемент}
L, R: Integer; {Текущие границы зоны поиска}
I : Integer;
Begin
ClrScr;
Writeln {‘Введите элементы массива:’};
For i:= 1 to n do Read (Vector[i]); Readln;
Write(‘Введите искомый элемент:’);
Readln(x);
{---------------------------------------------------------------------}
L:= 1; R:= n;
While(L<=R) do (Покане пересекутся границы )
Begin
I:=(L+R) div 2;{Индекс среднего элемента}
If Vector[i] = X then
Break{Выход из цикла поиска т.к элемент найден}
Else
If Vector[i]< X thenL :=i+1
Else R:=i- 1;
End;{while}
If Vector[i]= X then
Writeln (‘Искомый элемент найден на позиции’, i:3)
Else
Writeln (‘Искомый элемент не найден’);
{-----------------------------------------------------------------------}
end.
Запись - это структура данных,
состоящая из фиксированного числа
компонентов, называемых полями
записи. В отличие от массива,
компоненты (поля) записи могут быть
различного типа. Чтобы можно было
ссылаться на тот или иной компонент
записи, поля именуются.
Структура объявления типа записи
такова:
<имя типа» - RECORD <сп.полей> END
Здесь <имя типа> - правильный
идентификатор;
RECORD, END - зарезервированные слова (запись,конец);
<сп.полей> - список полей;
представляет собой
последовательность разделов записи,
между которыми ставится точка с
запятой.
Каждый раздел записи состоит из
одного или нескольких
идентификаторов полей, отделяемых
друг от друга запятыми. За
идентификатором (идентификаторами)
ставится двоеточие и описание типа
поля (полей), например:
type
Birthday - record day,month : byte; year : word end; var
a,b : Birthday;
В этом примере тип BIRTHDAY (день
рождения) содержит три поля с именами
DAY, MONTH и YEAR (день, месяц и год);
переменные А и В содержат записи типа
BirthDay.
Как и в массиве, значения переменных
типа записи можно присваивать другим
переменным того же типа, например
а := b; К каждому из компонентов записи
можно получить доступ, если
использовать составное имя, т.е.
указать имя переменной, затем точное
имя поля:
a.day := 27;
b.year := 1939; Для вложенных полей
приходится продолжать уточнения:
var
с : record
name : string;
bd : Birthday
end;
if c.bd.year - 1939 then ...
Чтобы упростить доступ к полям
записи, используется опеатор
присоединения WITH:
WITH <переменная> DO <оператор>
Здесь WITH, DO - ключевые слова (с, делать);
<переменная> - имя переменной типа
запись, за которым, возможно следует
список вложенных полей;
<оператор> - любой оператор Турбо
Паскаля.
Например:
with c.bd do month := 9;
Это эквивалентно
with с do with bd do month := 9;
или
with c, bd do month := 9;
или
c.bd.month := 9;
Турбо Паскаль разрешает
использовать записи с так называем
вариантными полями, например:
type
forma = record
name : string;
case byte of
0 : (BirthPlace : string[40] );
1 : (country : string[20];
EntryPort : string[20];
EntryDate : 1..31;
end;
В этом примере тип FORMA определяет
запись с одним фиксированным полем NAME и вариантной частью,
которая задается предложением
CASE...OF. Вариантная часть состоит из
нескольких вариантов (в примере - из двух вариантов: 0 и 1). Каждый
вариант определяется конец
выбора, за которой следует двоеточие
и список полей, заключенный в
круглые скобки. В любой записи может
быть только одна вариантная
часть, и, если она есть, она должна
располагаться за всеми
фиксированными полями.
Замечательной особенностью
вариантной части является то обстоятельство, что все заданные в ней
варианты как бы "накладываются"
друг
на друга, т.е. каждому из них
выделяется одна и та же область
памяти. Это
открывает дополнительные
возможности преобразования типов,
например:
var
mem4:record
case byte of
0 : (by array [0..3] of byte);
1 : (wo array (0..1] of word);
2: (lo : longint);
end;
var
mem4:record
case byte of
0 : (by array [0..3] of byte);
1 : (wo array (0..1] of word);
2: (lo : longint); end;
В этом примере запись МЕМ4 имеет три
варианта, каждый из которых занимает
в памяти один и тот же участок из 4
байт. В зависимости от того, к какому
полю записи мы обращаемся в
программе, этот участок может
рассматриваться как массив из 4 байт (поле
ВУ), массив из двух целых типа WORD (поле
WO) или, наконец, как одно целое число
типа LONGINT (поле LO). Например, этой
записи можно сначала присвоить
значение как длинному целому, а затем
проанализировать результат по
байтам или словам:
var
x : word;
xb: byte;
хi: longInt;
with m do begin
lo := trunc(2*pi*x); If wo[1]=0 then
If by[1]=0 then xb := x[0] else x := wo[0] else xi := lo
end;
Предложение CASE...OF, открывающее
вариантную часть, внешне похоже на
соответствующий оператор выбора, но
на самом деле лишь играет роль
своеобразного служебного слова,
обозначающего начало вариантной
части. Именно поэтому в конце
вариантной части не следует ставить
END как пару к СA SE... OF. (Поскольку
вариантная часть - всегда последняя в
записи, за ней все же стоит END, но лишь
как пара к RECORD). Ключ выбора в
предложении CASE... OF фактически
игнорируется компилятором:
единственное требование,
предъявляемое к нему Турбо Паскалем,
состоит в том, чтобы ключ определял
некоторый стандартный или
предварительно объявленный
порядковый тип. Причем сам этот тип
никак не влияет ни на количество
следующих ниже вариантных полей, ни
даже на характер констант выбора. В
стандартном Паскале в качестве ключа
выбора необходимо указывать
некоторую переменную порядкового
типа, причем в исполняемой части
программы можно присваивать
значение этой переменной и таким
образом влиять на выбор лей. В Турбо
Паскале также можно в поле ключа
выбора указывать переменную
порядкового типа и даже присваивать
ей в программе значение, что однако
не влияет на выбор поля: значения
констант выбора в Турбо Паскале
могут быть произвольными, в том числе
повторяющимися,
rec=record
a: byte;b: word;
end;rec2 = record
с : longint;
case x : byte of
1 : (d : word);
2 : (e : record
case Boolean of
3 :(f: reс1);
3 :(g: single);
'3':( с: word)
end)
end;
var
r : rec2;
BEGIN
r.x :=255:
if r.e..g=0 then wrIteln('O.K.')
else writeln(r.e.g)
END.
В этом примере предложение
case Boolean of
в записи, определяемой в поле Е,
объявляет ключом выбора логический
тип, который, как известно, имеет лишь
два значения - TRUE и FALSL Константы же
выбора следующих далее вариантов не
только содержат совершенно не
свойственные этому типу значения, но
и две из них повторяются, а общее
количество вариантов - три, а не два,
как следовало бы ожидать.
Имена полей должны быть уникальными
в пределах той записи, где они
объявлены, однако, если записи
содержат поля-записи, т.е. вложи. одна
в другую, имена могут повторяться на
разных уровнях вложенной (см. поле С в
последнем примере).
4.4.4. Множества
Множества - это наборы
однотипных логически связанных
друг с другом объектов. Характер
связей между объектами лишь
подразумевается программистом и
никак не контролируется Турбо
Паскалем. Количество элементов,
входящих в множество, может
меняться в пределах от 0 до 256 (множество,
не содержащее элементов,
называется пустыми. Именно
непостоянством количества своих
элементов множества отличаются
от массивов и записей.
Два множества считаются
эквивалентными тогда и только то
когда все их элементы одинаковы,
причем порядок следования
элемента в множестве
безразличен. Если все элементы
одного множества входят также и
в другое, говорят о включении
первого множества во второе
пустое множество включается в
любое другое.
Пример определения и задания
множеств:
Type
DigitChar= set of ‘0’..’9’;
Digit = set of 0..9;
Var
S1,s2,s3: digitChar;
S4,S5,S6:digit;
S1:=[‘1’,’2’,’3’];
S2:=[‘3’,’2’,’1’];
S3:=[‘2’,’3’];
S4:=[0..3,6];
S5:=[4,5];
S6:=[3..9];
В этом примере множества
SI и S2 эквивалентны, а множество S3
включено в 52 , но не эквивалентно
ему. Описание типа множества
имеет вид:
<имя типа> - SET OF <баз.тип>
Здесь <имя типа> - правильный
идентификатор;
SET, OF - зарезервированные слова (множество,
из);
<баз..тип> - базовый тип
элементов множества, в качестве
которого может использоваться
любой порядковый тип, кроме WORD,
INTEGER, WNGINT.
Для задания множества
используется так называемый
конструктор множества: список
спецификаций элементов
множества, отделяемых друг от
друга запятыми; список
обрамляется квадратными
скобками (см. предыдущий пример).
Спецификациями элементов могут
быть константы или выражения
базового типа, а также - тип-диапазон
того же базового типа.
Над множествами
определены следующие операции:
- - пересечение множеств;
результат содержит элементы,
общие для обоих множеств;
например, S4*S6 содержит [3], S4*S5 -
пустое множество (см. выше);
+ - объединение множеств;
результат содержит элементы
первого множества, дополненные
недостающими элементами из
второго множества:
S 4+S5 содержит [0, 1, 2, 3, 4, 5, 6];
S5=S6 содержит [3, 4, 5, 6, 7, 8, 9];
n разность множеств ; результат
содержит элементы из первого
множества, которые не
принадлежат второму:
S6-S5 содержит [3, 6, 7, 8, 9];
S4-S5содержит [0, 1, 2, 3, 6];
= - проверка эквивалентности;
возвращает TRUE, если оба
множества эквивалентны;
<> - проверка
неэквивалентности; возвращает
TRUE, если оба множества
неэквивалентны;
<= - проверка вхождения;
возвращает TRUE, если первое
множество включено во второе;
>= - проверка вхождения;
возвращает TRUE, если второе
множество помещено в первое;
In - проверка принадлежности; в
этой бинарной операции первый
элемент - выражение, а второй -
множество одного и того же типа;
возвращает TRUE, если выражение
имеет значение, принадлежащее
множеству:
3 in S6 возвращает True
2*2 in S1 возвращает False
МуTуре = (а, b, c, d);
MуТуре (2)
Integer ( 'D')
pointer ( longint(a) + $FF)
char (127 mod с)
byte (k)
При автоопределенном
преобразовании типа выражения
может произойти изменение
длины его внутреннего
представления (длина может
увеличиться или уменьшиться).
В Турбо Паскале определен еще
один явный способ
преобразования данных: в ту
область памяти, которую
занимает переменная
некоторого типа, можно
поместить значение выражения
другого типа, если только
длина внутреннего
представления вновь
размещаемого значения в
точности равна длине
внутреннего представления
переменной. С этой целью вновь
используется
автоопределенная функция
преобразования типов, но уже в
левой части оператора
присваивания:
type
by1 = array [ 1. . 2 ] of byte;
int = array [ 1. .2 ] of integer;
RЕС = record
x, у : Integer
end;
var
vbyt : byt;
vlnt : int;
vrec :rec;
begin
byt (vin1[1]) [2] := 0;
int (vrec) [1] := 256
end.