Pascal перечисляемый тип. Pascal. Простые типы данных. Описание и использование

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

Пример. Type Colour = (Red , Orange , Green) ;

Перечисляемый тип задается списком значений (объектов), которые могут принимать переменные этого типа. При этом каждый объект есть имя. Перечислимый тип задается самим программистом, в зависимости от того, какую задачу он решает.

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

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

Описание перечисляемого типа имеет вид:

Type Имя типа = (Список констант);

Var: Имя переменной: имя типа;

Здесь под константой понимается особый вид констант - констант, задаваемых пользователем. Под списком понимается перечень констант, разделенных запятыми. Сам список заключается в круглые скобки.

В общем виде:

Type T = (A1, A2,...,An);

Пример. Type Year = (Winter , Spring , Summer , Autumn);

Здесь Year - имя перечисляемого типа:

Зима, Весна, Лето, Осень - константы;

A - переменная, которая может принимать значение любой из констант.

Объект, указанный в списке,может присутствовать только в одном описании.

Пример. Type T1 = (One , two , three);

T2 = (Tree , four , five);

Эти два задания типов несовместимы.

Имена объектов, указанных в описании перечисленного типа, являются константами этого типа. В языке Паскаль допускается указывать константы перечислимого типа непосредственно в разделе переменных без использования раздела Type.

Пример. Var A: (Winter , Sprihg , Summer , Autumn);

Но лучше использовать описание данных с использованием раздела Type.

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

Пример.

Type Name =(Jon , Tom , Nick) ;

Color =(Red , Blue , Black);

Var X , Y , Z: Name ;

C1 , C2: Color ;

Каждая из констант имеет порядковый номер, счет начинается с нуля. Упорядоченность констант позволяет применять к ним операции отношения (сравнения): < ,<= ,= , <>, >, >=. Результат операции будет логического типа (Type , False). Winter < Spring < Summer < Autumn (Зима < Весна< Лето< Осень)

Свойства перечисляемого типа:

1) A i <> A j , если i >

2) A i < A j , если i < j (упорядоченность).

3) Значениями типа Т могут быть только А 1 , А 2 , ... А n .

Упорядоченность определяется той последовательностью, в которой перечислены константные идентификаторы. Наличие упорядоченности позволяет применить стандартные функции:

Ord (x) - нахождение порядкового номера,

Pred (x) - нахождение предыдущего элемента,

Succ (x) - нахождение последующего элемента.

Succ (A i) = A i +1 для i= 1,2,...n-1 - последующий член.

Pred (A i) = A i - 1 для i = 1,2,3...n - предыдущий член.

Ord (Ai) = i -1 - функция определения порядкового номера А i . Нумерация условно начинается с нуля.

Пример.

Имеется перечень зверей: лиса, волк, заяц, зубр, тигр, лев, медведь, косуля, олень, барс. Определить порядковый номер тигра (N1) и порядковый № зверя после косули (N2)

Type Zver = (lisa,volk,zaiac,zubr,tigr,lev,medved,kosulia,olen,bars);

Var P1,P2: Zver;

P2: = Succ (kosulia);

N1: = Ord(P1)+1;

N2: = Ord(P2)+1;

Writeln (‘N1 = ‘, N1:2);

writeln (‘N2 = ‘, N2: 2);

Так как счет перечислимых начинается с нуля, а не с единицы, для вычисления порядкового номера необходимо прибавить единицу.

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

Type Week = (Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday);

For Day: = Monday To Sunday Do

If (Day: = (Wednesday) Or (Day = Friday)

Then Writeln (‘Study’)

Else If (Day: = (Saturday) Or (Day = Sunday)

Then Writeln (‘Nothing’)

else Writeln (‘Work’)

Результат будет такой: Work

В языке Paskal нельзя вводить и выводить данные перечислимого типа с помощью операторов Read и Write.

{косвенная рекурсия

{раздел выполнения основной программы} PR_2

Здесь процедура Pr_1 при первом вызове инициирует случайное трехзначное число "n1" - выигрышный номер. При каждом вызове процедура Pr_1 запрашивает ввод трехзначного номера билета "n". Если номер билета не совпал (n<>n1) и остались еще билеты (i<>0), то снова вызывается процедура Pr_1, иначе вызывается процедура Pr_2 (окончание рекурсивного вызова). Если номера совпали (n1=n), то выводится сообщение: "Вы угадали, получите выигрыш в банке!". Процедура Pr_2 либо вызывает процедуру Pr_1, либо программа заканчивается (оператор Halt). В процедуре Pr_2 заголовок не имеет параметров, а в процедуре Pr_1 параметры указываются при первом описании. В данном случае приводится управляемая на каждом шаге рекурсия (процедура запрашивает номер билета). Включив тело процедуры Pr_2 в Pr_1 и введя операторы цикла, нетрудно избавиться от рекурсивного вызова процедур.

Структурированные типы данных

Любой из структуированных типов данных характеризуется множественностью образующих этот тип элементов. Переменная или константа структуированного типа всегда имеет несколько компонент. Каждая из этих компонент, в свою очередь, может принадлежать структуированному типу, что позволяет говорить о возможной вложенности типов.

В Турбо Паскале пять структуированных типов:

массивы;

строки;

множества;

записи;

файлы;

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

Перечисляемый тип данных

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

перечисляемый тип, заключается в круглые скобки.

Программист объединяет в одну группу в соответствии с каким-либо признаком всю совокупность значений, составляющих перечисляемый тип. Например, перечисляемый тип Rainbow (РАДУГА) объединяет скалярные значе-

ния RED, ORANGE, YELLOW, GREEN, LIGHT_BLUE, BLUE, VIOLET (КРАСНЫЙ, ОРАНЖЕВЫЙ, ЖЕЛТЫЙ, ЗЕЛЕНЫЙ, ГОЛУБОЙ, СИНИЙ, ФИОЛЕТОВЫЙ). Перечисляемый тип Traffic_Light (СВЕТОФОР) объединяет скалярные значения RED, YELLOW, GREEN (КРАСНЫЙ, ЖЕЛТЫЙ, ЗЕЛЕНЫЙ).

Перечисляемый тип описывается в разделе описания типов, например: Type

Rainbow = (RED, ORANGE, YELLOW,

GREEN, LIGHT_BLUE, BLUE, VIOLET);

Каждое значение является константой своего типа и может принадлежать только одному из перечисляемых типов, заданных в программе. Например, перечисляемый тип Traffic_Light не может быть определен в одной программе с типом Rainbow, так как оба типа содержат одинаковые константы.

Описание переменных, принадлежащих к скалярным типам, которые объявлены в разделе описания типов, производится с помощью имен типов.

Например:

type Traffic_Light= (RED, YELLOW, GREEN); var Section: Traffic_Light;

Это означает, что переменная Section может принимать значения RED, YELLOW или GREEN.

Переменные перечисляемого типа могут быть описаны в разделе описания переменных, например:

var Section: (RED, YELLOW, GREEN);

При этом имена типов отсутствуют, а переменные определяются совокупностью значений, составляющих данный перечисляемый тип.

К переменным перечисляемого типа может быть применим оператор присваивания:

Section:= YELLOW;

Упорядоченная последовательность значений, составляющих перечисляемый тип, автоматически нумеруется, начиная с нуля и далее через единицу. Отсюда следует, что к перечисляемым переменным и константам могут быть применены операции отношения и стандартные функции Pred, Succ, Ord.

Интервальный тип данных

Отрезок (диапазон значений) любого порядкового типа может быть определен как интервальный (ограниченный) тип. Отрезок задается диапазоном от

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

Примеры отрезков: 1..10 -15..25

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

Над переменными, относящимися к интервальному типу, могут выполняться все операции и применяться все стандартные функции, которые допустимы для соответствующего базового типа.

Массивы

Массивы – это совокупности однотипных элементов. Характеризуются они следующим:

каждый компонент массива может быть явно обозначен и к нему имеется прямой доступ;

число компонент массива определяется при его описании и в дальнейшем не меняется.

Для обозначения компонент массива используется имя переменной-массива

и так называемые индексы, которые обычно указывают желаемый элемент. Тип индекса может быть только порядковым (кроме longint). Чаще всего используется интервальный тип (диапазон).

Описание типа массива задается следующим образом:

имя типа = array[ список индексов ] of тип

Здесь имя типа – правильный идентификатор; список индексов - список одного или нескольких индексных типов, разделенных запятыми; тип - любой тип данных.

Вводить и выводить массивы можно только поэлементно.

Пример 1. Ввод и вывод одномерного массива. const

mas = array of integer;

a: mas; i: byte;

writeln("введите элементы массива"); for i:=1 to n do readln(a[i]); writeln("вывод элементов массива:");

for i:=1 to n do write(a[i]:5); end.

Определить переменную как массив можно и непосредственно при ее описании, без предварительного описания типа массива, например:

var a,b,c: array of integer;

Если массивы a и b описаны как: var

a = array of integer;

b = array of integer;

то переменные a и b считаются разных типов. Для обеспечения совместимости применяйте описание переменных через предварительное описание типа.

Если типы массивов идентичны, то в программе один массив может быть присвоен другому. В этом случае значения всех переменных одного массива будет присвоены соответствующим элементам второго массива. Вместе с тем, над массивами не определены операции отношения. Сравнивать два массива можно только поэлементно.

Так как тип, идущий за ключевым словом of в описании массива, – любой тип Турбо Паскаль, то он может быть и другим массивом.

Например: type

mas = array of array of integer;

Такую запись можно заменить более компактной: type

mas = array of integer;

Таким образом возникает понятие многомерного массива. Глубина вложенности массивов произвольная, поэтому количество элементов в списке индексных типов (размерность массива) не ограничена, однако не может быть более 65520 байт.

Работа с многомерными массивами почти всегда связана с организацией вложенных циклов. Так, чтобы заполнить двумерный массив (матрицу) случайными числами, используют конструкцию вида:

for i:=1 to m do

for j:=1 to n do a:=random(10);

Для "красивого" вывода матрицы на экран используйте такой цикл: for i:=1 to m do begin

for j:=1 to n do write(a:5); writeln;

Пример. Найти длину n-мерного вектора a (n <= 50): x = (a12+a22+...+an2)

const maxSize = 50;

x: double; i, n: byte;

write(‘n = ’) ; read (n) ;

{ вычисление суммы }

x := 0 ;

for i:= 1 to n do

x := x + sqr (a [i]) ;

{ вычисление длины вектора }

x := sqrt (x) ;

write (‘длина вектора a =‘, x: 8:2) ;

Пример. Найти количество положительных, отрицательных и нулевых элементов массива a (количество элементов <= 50).

const maxSize = 50;

type vector = array of double; var a: vector;

i, n, kplus, kminus, kzero: byte;

write(‘n = ’) ; read (n) ;

{ ввод массива } for i:= 1 to n do

write (‘a[‘, i, ‘]=‘) ; read (a[i]) ;

{ инициализация счетчиков } kplus:= 0 ; kminus:= 0 ; kzero:= 0 ; for i:= 1 to n do

then inc (kminus) else if a [i] > 0

then inc (kplus) else inc (kzero) ;

write (‘k+ =‘, kplus , ‘ k- =‘, kminus, ‘ k0 =‘, kzero) ;

Пример. Проверить, является ли числовой массив a упорядоченным по возрастанию (количество элементов <= 50).

const maxSize = 50;

type vector = array of double; var a: vector;

write(‘n = ’) ; read (n) ;

{ ввод массива } for i:= 1 to n do begin

write (‘a[‘, i, ‘]=‘) ; read (a[i]) ;

p:= 0 ; { установка флажка} for i:= 1 to n - 1 do

if a <= a [i] then p:= 1;

{ если нарушилось возрастание, то смена флажка } if p = 1

then write (‘нет’) else write (‘да’) ;

Нахождение максимального элемента массива - подход к алгоритму. n = 1 тогда nMax:= 1 ;

n = 2 тогда nMax:= 1 ;

if a > a then nMax:= 2 ;

n = 3 тогда …… if a > a then nMax:= 3 ;

Пример. Найти значение и номер максимального элемента числового массива a (количество элементов <= 50).

const maxSize = 50;

type vector = array of double; var a: vector;

i, n, nMax: byte;

write(‘n = ’) ; read (n) ;

write (‘a[‘, i, ‘]=‘) ; read (a[i]) ;

for i:= 1 to n do

if a [i] > a then nMax:= i;

{ если встретился больший элемент, то запомнили его номер }

write (‘номер =’, nMax , ‘ max значение =‘, a :8: 2) ;

Сортировка числового массива - подход к алгоритму пузырьковой сортировки.

Для определенности - по возрастанию:

n = 2 тогда if a < a

then { если элементы стоят неправильно, то меняем их местами} begin t:= a ;

a := a ; a := t ; end;

n = 3 тогда if a < a

then begin t:= a ; a := a ;

then begin t:= a ; a := a ;

{ максимальный элемент на месте}

Пример. Упорядочить по возрастанию числовой массив a (количество элементов <= 50).

const maxSize = 50;

type vector = array of double; var a, b: vector;

i, n, k: byte; t: double;

write(‘n = ’) ; read (n) ;

{ ввод массива } for i:= 1 to n do begin

write (‘a[‘, i, ‘]=‘) ; read (a[i]) ;

b:= a ; { присваивание массива} for k:= 1 to n-1 do

for i:= 1 to n - k do if b < b[i]

then begin t:= b[i] ;

b [i] := b ; b := t ;

end; writeln (‘упорядоченный массив:’) ; for i:= 1 to n do

writeln (‘b[‘, i, ‘]=‘, b[i] :8:2) ;

Пример. Найти сумму элементов матрицы a, состоящей из n строк и m

столбцов (n <= 5, m <= 4). uses wincrt;

const RSize = 5; CSize = 4;

sum: double; i, j, n, m: byte;

{ ввод массива } for i:= 1 to n do

for j:= 1 to m do begin

{ вычисление суммы }

for i:= 1 to n do

for j:= 1 to m do sum:= sum + a ;

write (‘сумма =‘, sum: 8:2) ;

Пример. Найти количество нулевых элементов в каждом столбце массива a. uses wincrt;

const RSize = 5; CSize = 4;

type matr = array of double; var a: matr;

i, j, n, m, kzero: byte;

for i:= 1 to n do

for j:= 1 to m do begin

write (‘a[‘, i, ‘,’, j, ‘]=‘) ; read (a) ;

for j:= 1 to m do{ цикл по столбцам } begin

{ инициализация счетчика } kzero:= 0 ;

for i:= 1 to n do if a [i] = 0

then inc (kzero) ;

writeln (j, ‘-й столбец:k0 =‘, kzero) ;

Пример. Найти номера строк массива a, в которых есть хоть один 0. uses wincrt;

const RSize = 5; CSize = 4;

type matr = array of double; var a: matr;

i, j, n, m, p: byte;

write(‘n = ’) ; read (n) ; write(‘m = ’) ; read (m) ; { ввод массива }

for i:= 1 to n do

for j:= 1 to m do begin

write (‘a[‘, i, ‘,’, j, ‘]=‘) ; read (a) ;

end ; for i:= 1 to n do

p:= 0 ; { установка флажка} for j:= 1 to m do

then p:= 1;{смена флажка } if p = 1

then writeln (‘номер строки=’, i);

Пример. Найти значение и номера максимального элемента числового массива a

const RSize = 5; CSize = 4;

type matr = array of double; var a: matr;

i, j, n, m, Rmax, Cmax: byte;

write(‘n = ’) ; read (n) ; write(‘m = ’) ; read (m) ; { ввод массива }

for i:= 1 to n do

for j:= 1 to m do begin

write (‘a[‘, i, ‘,’, j, ‘]=‘) ; read (a) ;

end ; Rmax:=1 ; Cmax:= 1 ; for i:= 1 to n do

for j:= 1 to m do

if a > a then

Rmax:= i; Cmax:= j ; end;

write (‘max = a[‘ , Rmax, ‘,’ , Cmax,‘ ]= ‘ , a :8: 2)

Пример. Переставить строки матрицы a в порядке возрастания элементов первого столбца.

const RSize = 5; CSize = 4;

type matr = array of double; var a , b: matr;

i, j, k, n, m: byte; t: double;

write(‘n = ’) ; read (n) ; write(‘m = ’) ; read (m) ; { ввод массива }

for i:= 1 to n do

for j:= 1 to m do begin

write (‘a[‘, i, ‘,’, j, ‘]=‘) ; read (a) ;

for k:= 1 to n-1 do

for i:= 1 to n - k do

if b < b

then { перестановка строк } for j:= 1 to m do

b := b ; b := t ; end;

writeln (‘упорядоченный массив:’) ; for i:= 1 to n do

for j:= 1 to m do

write (b :8:2) ;

writeln; { переход к новой строке }

Пример. Выполнить умножение матрицы a на вектор x. uses wincrt;

const RSize = 5; CSize = 4; VSize = 5 ;

type matr = array of double; vector = array of double;

i, j, k, n, m: byte;

write(‘n = ’) ; read (n) ; write(‘m = ’) ; read (m) ;

{ ввод матрицы } for i:= 1 to n do

for j:= 1 to m do begin

write (‘a[‘, i, ‘,’, j, ‘]=‘) ; read (a) ;

{ ввод вектора }

for j:= 1 to m do begin

write (‘x[‘, j, ‘]=‘) ; read (x[j]) ;

for i:= 1 to n do begin

for j:= 1 to m do

y[ i ] := y[ i ] + a * x[j] ;

{ вывод результата }

for i:= 1 to n do

writeln (‘y[‘, i, ‘]=‘, y[i] :8:2) ;

Пример. Выполнить умножение матрицы a на матрицу b. uses wincrt;

const RSize = 5; CSize = 5;

type matr = array of double; var a, b, c: matr;

i, j, k, n, m, L: byte;

write(‘n = ’) ; read (n) ; write(‘m = ’) ; read (m) ; { ввод матрицы a} for i:= 1 to n do

for j:= 1 to m do begin

write (‘a[‘, i, ‘,’, j, ‘]=‘) ; read (a) ;

end ; write(‘L = ’) ; read (L) ;

{ ввод матрицы b} for i:= 1 to m do

for j:= 1 to L do begin

write (‘b[‘, i, ‘,’, j, ‘]=‘) ; read (b) ;

{ количество строк матрицы b равно количеству столбцов матрицы a} for i:= 1 to n do

for j:= 1 to L do begin

c[ i , j] := 0 ;

for k:= 1 to m do

c[ i , j] := c[ i , j] + a * b ;

{ вывод результата }

for i:= 1 to n do begin

for j:= 1 to L do

write (c :8:2) ; writeln;


Алгоритм языка Pascal построен таким образом,что для того чтобы оперировать с переменными,нужно обычно указать их тип. Причем описание типа для каждой переменной необходимо производить до выполнения программы (в разделе var). То есть запуске компилятора программа сначала получает сведения,касательно того с какими типами данных будет работать и только потом выполняет какие-либо действия.
Итак в Паскале 3 основных типа: простой,структурированный и указатель. Однако каждый тип имеет свои подтипы. Для удобства все типы данных приведены в виде списка.

Для каждого типа характерен свой диапазон значений. Ниже приведены диапазоны значений для простого типа

Чаще всего используют типы integer ,real ,longint ,byte ,string ,boolean и char так как обычно в задачах не указывается какие конкретно типы должны быть использованы для решения. Будьте внимательны при использовании типов и внимательно следите за допустимыми диапазонами для каждого типа. Например дробным числам нельзя присваивать тип integer ,а типом сhar может быть только один символ (например переменная f:=gfgfgf не может быть char)
Теперь о том как описать тип. Как уже было сказано выше операторам присваивается тип в самом начале программы (можно даже сказать что до начала программы). Итак описываются типы в разделе var, который находится до начала программы (то есть до begin). Рассмотрим простой пример
var x,u,yu,i:integer;
s,f:real;
g:string;
begin
....
end. Как видно из примера шаблон описания типа выглядит так
оператор1,оператор 2: тип; Как вы уже заметили нет необходимости описывать каждый оператор, если тип общий,достаточно перечислить их через запятую. Также нет необходимости после каждого типа переходить на новую строку,здесь это сделано просто для более удобного чтения кода. Вообще код должен быть читабельным и хорошо воспринимаемым, поэтому советуется операторы общего типа объединять,а каждый тип писать с новой строки.

Перечисляемый тип определяется как набор идентификаторов, с точки зрения языка играющих ту же роль, что и обычные именованные константы, но связанные с этим типом. Классическое описание типа-перечисления в языке Паскаль выглядит следующим образом:

type Cardsuit = (clubs , diamonds , hearts , spades ) ;

Здесь производится объявление типа данных Cardsuit (карточная масть), значениями которого может быть любая из четырёх перечисленных констант. Переменная типа Cardsuit может принимать одно из значений clubs, diamonds, hearts, spades , допускается сравнение значений типа перечисление на равенство или неравенство, а также использование их в операторах выбора (в Паскале - case) в качестве значений, идентифицирующих варианты.

Использование перечислений позволяет сделать исходные коды программ более читаемыми, так как позволяют заменить «магические числа» , кодирующие определённые значения, на читаемые имена.

На базе перечислений в некоторых языках могут создаваться типы-множества . В таких случаях множество понимается (и описывается) как неупорядоченный набор уникальных значений типа-перечисления.

Перечисляемый тип может использоваться в объявлениях переменных и формальных параметров функций (процедур, методов). Значения перечислимого типа могут присваиваться соответствующим переменным и передаваться через параметры соответствующих типов в функции. Кроме того, всегда поддерживается сравнение значений перечислимого типа на равенство и неравенство. Некоторые языки поддерживают также другие операции сравнения для значений перечислимых типов. Результат сравнения двух перечислимых значений в таких случаях определяется, как правило, порядком следования этих значений в объявлении типов - значение, которое в объявлении типа встречается раньше, считается «меньше» значения, встречающегося позже. Иногда перечислимый тип или некоторый диапазон значений перечислимого типа также может быть использован в качестве типа индекса для массива. В этом случае для каждого значения выбранного диапазона в массиве имеется один элемент, а реальный порядок следования элементов соответствует порядку следования значений в объявлении типа.

Реализация

Обычно в процессе компиляции значения перечислений представляются при помощи целых чисел. В зависимости от конкретного языка программирования такое представление может быть либо полностью скрыто от программиста, либо доступно ему с помощью тех или иных «обходных манёвров» (например, принудительного преобразования значения типа перечисление к значению типа «целое число»), либо даже управляемо программистом (в таких случаях программист имеет возможность явно указать, какими числами будут кодироваться все или некоторые значения типа-перечисления). У всех вариантов есть свои положительные и отрицательные стороны. С одной стороны, возможность использования числовых значений констант, составляющих тип-перечисление, особенно при злоупотреблении ею, лишает смысла использование этих типов и создаёт опасность появления ошибок (когда используются числовые значения, для которых в типе нет соответствующих констант). С другой стороны, явное управление значениями даёт некоторые дополнительные возможности. Например, позволяет использовать типы-перечисления при организации интерфейса с модулями, написанными на других языках, если они используют или возвращают кодированные целыми числами значения из некоторого предопределённого набора.

Ещё одна возможность, которую дают перечислимые типы на уровне реализации языка - экономия памяти. При небольшом объёме типа-перечисления для хранения значения этого типа достаточно нескольких битов (вышеприведённый тип Cardsuit требует всего два бита на значение, в то время как стандартное целое число на большинстве используемых архитектур занимает 32 бита - в 16 раз больше), и компилятор может использовать этот факт для уплотнения хранения данных в памяти. Это может быть особенно важно, если несколько значений типов-перечислений хранятся в одной записи - уплотнение записей при обработке больших их количеств может освободить много памяти. Правда, необходимо отметить, что компиляторы обычно не реализуют эту возможность, по крайней мере, в последнее время, когда компьютерная память существенно подешевела.

Критика

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

С другой стороны, например, в Java , первоначально не содержащей перечислимого типа, этот тип был впоследствии введён из соображений не только удобства, но и надёжности: проблема использования вместо перечислений групп именованных констант в том, что отсутствует контроль со стороны компилятора как за уникальностью значений констант, так и за возможностью случайного присваивания переменным значений, не соответствующих ни одной из этих констант.

Описание перечислений в различных языках

Enum cardsuit { CLUBS , DIAMONDS , HEARTS , SPADES };

Динамические языки слабой типизации с C-подобным синтаксисом (например perl или JavaScript), как правило, не имеют перечислений.

C++

Перечисления в языке C++ прямо наследуют поведение перечислений языка C, за исключением того, что перечисляемый тип в C++ - настоящий тип, и ключевое слово enum используется только при объявлении такого типа. Если при обработке параметра являющегося перечислением, какое-либо значение из перечисления не обрабатывается (например один из элементов перечисления забыли обработать в конструкции switch), то компилятор может выдать предупреждение о забытом значении.

enum Cardsuit { Clubs , Diamonds , Spades , Hearts }

Java

В первоначальной Java перечислений не было, вместо них предлагалось использовать классы со статическими константами. Начиная с версии 5 (1.5) перечисления были введены в язык, они представляют собой полноценный класс, в который можно добавлять произвольное количество полей и методов. Перечисления были введены для улучшенного контроля за типобезопасностью.

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

Type Colors = (red, white, blue); Days = (Mon, Tue, Wed, Thu, Fri, Sat, Sun);

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

Переменные любого перечисляемого типа можно объявлять без предварительного описания этого типа, например:

Var TextColor: (black, white, green);

Значения, входящие в перечисляемый тип, являются константами. Действия над ними подчиняются правилам, применимым к константам. Они пронумерованы начиная от 0 в порядке следования в описании. Ко всем перечисляемым типам применимы операции отношения (если оба операнда одного типа). Порядок устанавливается последовательностью перечисления констант.

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

  • succ(X) – следующее за X
  • pred(X) – предшествующее X
  • ord(X) – ординальный номер X

Допускается и обратное преобразование: любое выражение типа WORD можно преобразовать в значение перечисляемого типа, если только значение целочисленного выражения не превышает мощности перечисляемого типа. Такое преобразование достигается применением автоматически объявляемой функции с именем перечисляемого типа.