4.1.7. Перечислимые типы
Перечислимый тип — это такой тип данных, при котором количество всех возможных значений ограничено (конечно). Например, тип Word соответствует этому определению. В нем 65536 значений — от 0 до 65535. И уж точно перечислимыми являются типы: Byte — 256 значений от 0 до 255 и Char — в нем 256 символов с кодами от 0 до 255. Можно перечислить и все значения типов ShortInt, Integer и даже LongInt. Только перечисление начнется не с нуля, а с отрицательного целого значения.
Есть и еще один предопределенный перечислимый тип — Boolean. У него всего два значения — False и True. Принято, что номер False внутри языка равен 0, а номер True равен 1. Перечислимый тип можно расписать в ряд по значениям. Тип Char можно было расписать в синтаксисе Паскаля как
TYPE
Char = ( симв0, симв1..., симв64, 'A', 'B', 'C', ...симв255);
тип Byte выглядел бы так:
Byte = (0, 1, 2,...,254, 255);
- 66 -
а логический тип — как
Boolean = ( False, True );
Но такие определения проделаны еще во время написания самого компилятора языка, осталось только пользоваться ими. Зато мы можем вводить новые перечислимые типы, придумывая им имена и перечисляя через запятую в круглых скобках названия элементов-значений этого типа:
| TYPE
| Personages = ( NifNif, NufNuf, NafNaf );
| Test = ( Level0, Level1, Level2, Level4, Level5);
| MusicCard = ( IBM, Yamaha, ATARI, other, None);
| Boolean3 = (false_, Nolnfo_, true_);
Значения в скобках — это значения новых типов. Можно теперь объявлять переменные этих типов, а их значениями можно индексировать массивы или организовывать по ним циклы. Но всегда переменная такого типа сможет содержать только те значения, которые указаны в его перечислении.
Перечислимые данные (их можно называть атомами) должны иметь синтаксис идентификаторов, и поэтому не могут перечисляться цифры, символы, строки.
Идентификаторы не могут повторяться в одной программе. Заметьте, как введен тип Boolean3 для моделирования трехзначной логики: чтобы избежать использования уже задействованных имен True и False, они чуть-чуть видоизменены. Регистр написания идентификаторов по-прежнему не играет роли. Максимальное число элементов в одном вводимом перечислении равно 65535.
Применение вводимых перечислимых типов имеет ряд преимуществ:
1) улучшается смысловая читаемость программы;
2) более четко проводится контроль значений;
3) перечислимые типы имеют очень компактное машинное представление.
Недостатком применения перечислимых типов является то, что значения из перечислимого типа (атомы) не могут быть выведены на экран или принтер и не могут быть явно введены с клавиатуры. Бороться с этим недостатком можно, но посредством не очень красивых приемов. Обычно, чтобы все-таки иметь возможность вывода на экран, вводят массивы, проиндексированные атомами. Каждый их элемент есть строковое написание соответствующего атома (например, для атома NoInfo_ — строка 'Nolnfo_').
- 67 -
Для работы с перечислимыми типами в Турбо Паскале используются общепринятые функции Ord, Pred и Succ. Рассмотрим их действие.
Любой перечислимый тип имеет внутреннюю нумерацию. Первый элемент всегда имеет номер 0; второй — номер 1 и т.д. Порядок нумерации соответствует порядку перечисления. Номер каждого элемента можно получить функцией Ord(X) : LongInt, возвращающей целое число в формате длинного целого, где X — значение перечислимого типа или содержащая его переменная. Так, для введенного выше типа Test:
Ord(Level0) даст 0,
Ord(Level1) даст 1,
...
Ord(Level5) даст 5.
Применительно к целым типам функция Ord не имеет особого смысла и возвращает значение аргумента:
Ord(0) = 0
Ord(-100) =-100
но для значений Char она вернет их код:
Ord('0') = 48,
Ord(' ') = 32,
Ord('Б') = 129.
Для логических значений
Ord(False) = 0 и Ord( True ) = 1.
Обратной функции для извлечения значения по его порядковому номеру в языке нет, хотя выражение вида
X : = ИмяПеречислимогоТипа(ПорядковыйНомер)
запишет в X значение, соответствующее заданному порядковому номеру элемента перечисления. Кроме этого, имеются две функции последовательного перебора значений перечислимого типа:
Succ(X) — возвращает следующее за X значение в перечислимом типе;
Pred(X) — возвращает предыдущее значение в перечислимом типе.
Так, для нашего типа Boolеаn3
Succ(false_) = noinfo_ = Pred( true_).
Функции Succ и Pred применимы и к значениям целочисленных типов:
- 68 -
Succ(15) = 16, Succ(-15) = -14,
Pred(15) = 14, Pred(-15) = -16.
и очень эффективно работают в выражениях вида (N-1)*N*(N+1), которые могут быть переписаны как Pred(N)*N*Succ(N).
Не определены (запрещены) значения:
Succ(последний элемент перечисления)
и
Pred(первый элемент перечисления).
Поскольку перечислимые значения упорядочены, их можно сравнивать. Из двух значений большим является то, у которого больше порядковый номер (но это сравнение должно быть в пределах одного и того же типа!), т.е. выполняется:
True > False
в типе Boolean,
NoInfo_ < true_
в типе Boolean3,
'z' > 'a'
в типе Char.
Знаки сравнения могут быть и нестрогими.