Pascal. Простые типы данных

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

{раздел выполнения основной программы} 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;

На занятии будет объяснен алгоритм создания типов данных пользователя в Паскаль (Type). Будут разобраны примеры.

Типы данных в Pascal делятся на простые и сложные.

К простым типам относятся стандартные, перечисляемые и ограниченные.

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

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

Новые (пользовательские) типы данных нужны в первую очередь для наглядности и удобства:

Пример: Задана матрица размерностью 10 x 50. Выполнить описание матрицы, используя пользовательский тип данных

procedure p(a: array of Integer);

Зато следует создать тип данных и записать так:

1 2 type vector = array [ 1 .. 10 ] of integer ; var procedure p(a: vector) ;

type vector = array of integer; var procedure p(a: vector);

Примеры описания массивов при помощи новых типов

type vector = array of integer; matritsa = array of vector;

  • 1 type matritsa = array [ 1 .. 8 ] of array [ 1 .. 10 ] of integer ;

    type matritsa = array of array of integer;

  • 1 type matritsa = array [ 1 .. 8 , 1 .. 10 ] of integer ;

    type matritsa = array of integer;

  • В следующем примере переменные c и d описаны одинаково:

    1 2 3 4 5 6 type vector = array [ 1 .. 10 ] of integer ; matritsa = array [ 1 .. 8 ] of vector; var a, b: vector; c: matritsa; d: array [ 1 .. 8 ] of vector;

    type vector = array of integer; matritsa = array of vector; var a,b: vector; c:matritsa; d:array of vector;

    Type 1 : Заданы массивы а, b и c. Найти среднее арифметическое минимальных элементов массива (использовать формирования массива и ).
    При описании процедур использовать пользовательские типы данных

    Перечисляемый тип и интервальный тип в Паскаль

    Перечисляемый тип

    В программе можно использовать переменные такого типа, который не совпадает ни с одним из стандартных типов.

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

    Эти значения не могут являться строками, их нельзя вывести на печать и нельзя ввести в компьютер при помощи операторов Read и Write .

    Рассмотрим пример создания перечисляемого типа в Паскаль:

    type pt= (word1, word2, ... wordN ) ; var w: pt;

    type pt=(word1,word2, ... wordN); var w: pt;

  • pt – идентификатор типа (произвольный),
  • word1 , word2 … — конкретные значения, которые может принимать переменная w , принадлежащая типу pt
  • значения данного типа считаются упорядоченными, т.е. описание типа одновременно вводит упорядочение word1 .
  • Интервальный тип

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

    Рассмотрим пример объявления интервального типа:

    a: min.. max ;
  • a – интервальная переменная
  • min – нижняя граница
  • max – верхняя граница подмножества
  • границы диапазона разделяются двумя точками
  • граница min всегда должна быть меньше max
  • константы min и max должны принадлежать одному и тому же типу. Они определяют базовый тип переменной a .
  • Совместное использование перечисляемого и интервального типов

    Переменную интервального типа можно задать с основой на базовый перечисляемый тип . Рассмотрим пример:

    Пример: Если переменная b может принимать одно из значений red , yellow , green , то эту переменную можно описать так: b: red..green; базовым типом для b является тип color :

    type color= (red, yellow, green, blue) ; var b: red.. green ; begin b: = red; writeln (b) ; b: = yellow; writeln (b) ; b: = green; writeln (b) ; readln end .

    type color=(red,yellow,green,blue); var b:red..green; begin b:=red; writeln(b); b:=yellow; writeln(b); b:=green; writeln(b); readln end.

    В данном примере тип color — является базовым. Переменная b интервального типа определена при помощи базового перечисляемого типа.

    Пример: Известно, сколько дней в каждом месяце года. Сколько дней летом?
    31,28,31,30,31,30,31,31,30,31,30,31

    Один из вариантов решения данной задачи выглядит так:

      Показать решение:

      1 2 3 4 5 6 7 8 const dni: array [ 1 .. 12 ] of byte = (31 , 28 , 31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 , 30 , 31 ) ; var s, i: integer ; begin s: = 0 ; for i: = 6 to 8 do s: = s+ dni[ i] ; {летние месяцы - 6, 7, 8} writeln (s) end .

      const dni: array of byte = (31,28,31,30,31,30,31,31,30,31,30,31); var s,i: integer; begin s:=0; for i:=6 to 8 do s:=s+dni[i]; {летние месяцы - 6, 7, 8} writeln(s) end.

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

      Показать решение:

      1 2 3 4 5 6 7 8 9 TYPE mes = (january, february, march, april, may, june, july, august, september, october, november, december) ; CONST dni: array [ january.. december ] of Byte = (31 , 28 , 31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 , 30 , 31 ) ; VAR s: Integer ; i: mes; {переменная счетчика цикла i задана типом mes, а не Integer} BEGIN s: = 0 ; for i: = june to august do s: = s+ dni[ i] ; WriteLn (s) END .

      TYPE mes = (january, february, march, april, may, june, july, august, september, october, november, december); CONST dni:array of Byte = (31,28,31,30,31,30,31,31,30,31,30,31); VAR s:Integer; i:mes; {переменная счетчика цикла i задана типом mes, а не Integer} BEGIN s:=0; for i:=june to august do s:=s+dni[i]; WriteLn(s) END.

    Type 2: Определить по названию дня недели выходной ли это или рабочий день.

  • Определить перечислимый тип со значениями дней недели (mon , tue , wed , thu , fri , sat , sun ).
  • В программе присвоить значение переменной (из значений типа, например, mon ).
  • Проверять переменную: если значение суббота или воскресенье – выдавать сообщение «Выходной!» , иначе «Работаем!» .
  • Type 3: В зависимости от месяца года, выдавать сообщение «холодно» — если зимний месяц, и «тепло» — если летний.

  • Определить перечисляемый тип со значениями названий месяцев года.
  • Объявить переменную, относящуюся к этому типу.
  • В программе присвоить значение переменной (из значений типа).
  • Проверять переменную: если значение относится к зимнему месяцу, — выдавать сообщение «холодно» иначе, — «тепло» .
  • Реализовать несколькими способами.
  • Writeln (pribitie) end .

    var otpravlenie,pribitie:byte; begin otpravlenie:=22; pribitie:=otpravlenie+10; writeln(pribitie) end.

    программа вместо ответа «8» напечатает ответ «32».
    Введение ограниченного диапазонного типа позволит избежать неправильного результата, однако компилятор все равно выдаст ошибку:

    1 2 3 4 5 6 var otpravlenie, pribitie: 0 .. 24 ; begin otpravlenie: = 22 ; pribitie: = otpravlenie+ 10 ; writeln (pribitiedeva) ; var a: znak; begin a: = lev; if a<= strelets then writeln ("огонь" ) ; if (a>= vesi) and (a<= bliznetsi) then writeln ("воздух" ) ; if (a>= rak) and (a<= ribi) then writeln ("вода" ) ; if (a>= kozerog) and (a<= deva) then writeln ("земля" ) ; end .

    type znak=(oven,lev,strelets,vesi,vodoley, bliznetsi,rak,skorpion,ribi,kozerog,telets,deva); var a:znak; begin a:=lev; if a<=strelets then writeln("огонь"); if (a>=vesi) and (a<=bliznetsi) then writeln ("воздух"); if (a>=rak) and (a<=ribi) then writeln ("вода"); if (a>=kozerog) and (a<=deva) then writeln ("земля"); end.

    Type 5: В зависимости от названия цветка, выдавать к какому сезону года он относится:

  • Весна: подснежник, ирис, нарциссы
  • Лето: ромашка, одуван, мак
  • Осень: астра, хризантема, флокс
  • Конструкция, задающая альтернативы для простого типа выглядит так:

    <простой тип> ::= <перечисляемый тип>

    <предопределенный тип>

    <ограниченный тип>

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

    Перечисляемый тип

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

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

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

    при условии, что кардинальное число типа меньше или равно 256, разместить эти данные в одном байте, т.е. экономить память.

    Конструкция, определяющая правило описания перечисляемого типа имеет вид:

    <перечисляемый тип> ::= (<список значений>)

    <список значений> ::= <значение>

    <список значений>,<значение>

    <значение> ::= <идентификатор>

    <целое >

    Таким образом, в соответствии с правилом, описание перечисляемого типа сводится к перечислению в скобках и через запятую значений, принадлежащих специфицируемому типу.

    Пример раздела типов с такими описаниями:

    Day = (mo, tu, we, th, fr, sa, su); {card(day)=7}

    Notation= (do_, re, mi, fa, sol, la, si); {card(notation)=7}

    Тогда, при описании переменных MyDday и MyNota в разделе переменных:

    MyNota: Notation;

    можно, например, использовать такие операторы присваивания:

    Поскольку предопределенный тип является скалярным, для него полезно определить функции, которые возвращают предшествующее и последующее значения для своего аргумента. В языке Паскаль такими функциями являются соответственно Pred(x) и Succ(x). Так, в результате выполнения оператора MyDay:=Pred(sa) переменной MyDay будет присвоено значение fr, а выполнение оператора MyNota:=Succ(do_) присвоит переменной MyNota значение re. Очевидно, что эти функции не определены на соответственно "первом" и "последнем" значениях, т.е. обращения вида Pred(do_) или Succ(si) вызовут сообщение об ошибке. Кроме того, существенным недостатком перечисляемого типа является отсутствие поддержки вывода его значений в подавляющем большинстве существующих систем программирования, что заставляет использовать для вывода, например, такой фрагмент текста программы.

    Перечисляемые типы

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

    Синтаксис

    type имя = (идентификатор, идентификатор, ..., идентификатор);

    Замечания

    Идентификаторы в определении типа становятся константами перечисляемого типа.

    Первая константа имеет порядковый номер 0, вторая - 1, и так далее.

    Перечисляемые типы являются подклассом порядковых типов.

    Пример

    type Suit = (Clubs, Diamonds, Hearts, Spades);

    При таком объявлении Hearts является константой типа Suit.

    Стандартная функция Ord возвращает порядковый номер перечисляемой константы. В этом примере,

    Ord(Clubs) = 0
    Ord(Diamonds) = 1
    Ord(Hearts) = 2

    Ада

    type Day is (Mon, Tue, Wed, Thu, Fri, Sat, Sun);
    type Suit is (Clubs, Diamonds, Hearts, Spades);
    type Color is (White, Red, Yellow, Green, Blue, Brown, Black);
    type Light is (Red, Amber, Green); -- Red и Green перегружены

    В отличие от Borland Pascal, идентификаторы в определении типа становятся функциями, а не константами. Это позволяет перегружать их. А в остальном, поведение этих функций полностью аналогично константам.

    Описание и использование

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

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

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

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

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

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

    Реализация

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

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

    Критика

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

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

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

    Ada

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

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

    C++

    C#

    Enum Cardsuit { Clubs, Diamonds, Spades, Hearts } ;

    Java

    Enum Cardsuit { Clubs, Diamonds, Spades, Hearts }

    Haskell

    В некоторых языках программирования (например, в языке Haskell) при помощи Алгебраических типов можно эмулировать перечисления. Например, так кодируется булевский тип, содержащий два идентификатора для представления значений истинности:

    Data Bool = False | True

    Примечания


    Wikimedia Foundation . 2010 .

    Википедия

    По техническим причинам Bool перенаправляется сюда. О Bool можно прочитать здесь: stdbool.h. Логический, булев (англ. Boolean или logical data type) тип данных примитивный тип данных в информатике, которые могут принимать два возможных … Википедия

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

    Целое, целочисленный тип данных (англ. Integer), в информатике один из простейших и самых распространённых типов данных в языках программирования. Служит для представления целых чисел. Множество чисел этого типа представляет собой… … Википедия

    Примитивный (встроенный, базовый) тип тип данных, предоставляемый языком программирования как базовая встроенная единица языка. В зависимости от языка и его реализации, набор таких типов может сильно различаться. Он определяется… … Википедия

    У этого термина существуют и другие значения, см. Множество (значения). Множество тип и структура данных в информатике, является реализацией математического объекта множество. Данные типа множество позволяют хранить ограниченное число значений… … Википедия

    Некоторые языки программирования предоставляют специальный тип данных для комплексных чисел. Наличие встроенного типа упрощает хранение комплексных величин и вычисления над ними. Содержание 1 Арифметика над комплексными 2 Поддержка в языках … Википедия

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