Pers.narod.ru. Обучение. Учебник по Паскалю. Глава 19

19. Множества и перечислимые типы

 

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

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

Для объявления множества достаточно записать оператор

set of тип;

где тип -- один из определенных программистом или предустановленных типов данных:

type charset: set of char;

var symbols: charset;

Вопреки этому примеру, стандартные типы данных мало применимы для множеств -- ведь исходный тип набора должен быть порядковым (см. п. 2.3) и не иметь более чем 256 различных значений с нижним и верхним пределом от 0 до 255 соответственно. Это связано с тем, что для хранения количества элементов множества выделяется только один байт оперативной памяти. Приведем другой пример для множества:

type charset= set of char;

var symbols:charset;

    c1:char;

begin

 symbols:=['A'..'Z','a'..'z'];

 write ('Put one symbol:');

 readln (c1);

 if c1 in symbols then writeln ('OK')

 else writeln ('Error');

end.

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

if c1 in symbols then writeln ('OK')

Слева от оператора in может быть указано выражение любого перечислимого типа T, а справа -- набор с типом, совместимым с типом T.

Любые совместимые по типам данных множества можно объединять операций "+", вычитать операцией "-" и пересекать операцией "*". При этом результаты операций с множествами  соответствуют правилам логики множеств:

·       порядковое значение c находится в множестве A+B только в том случае, если c находится в A или B;

·       порядковое значение c находится в множестве A-B только в том случае, если c находится в A и не находится в B;

·       порядковое значение c находится в множестве A*B только в том случае, если c находится и в A, и в B.

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

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

type Latin = set of 'A'..'z';

const SmallLatin : Latin = ['A'..'Z'];

      BigLatin : Latin = ['a'..'z'];

var LatinLetters : Latin;

 c:char;

begin

 LatinLetters := BigLatin + smallLatin;

 repeat

  write ('Введите символ или ',

         'пробел для выхода:');

  reset (input);

  readln (c);

  if c in LatinLetters then

   writeln (c,' - латинская буква');

 until c=' ';

end.

Как в примере выше, полезно бывает создавать из множеств подмножества при указании конструктора, содержащего выражения диапазонов в квадратных скобках [ ... ]:

type Digits = set of 0..9; {Множество цифр}

     Letters = set of 'A'..'Z';

      {Множество латинских букв}

const EvenDigits : Digits =

 [0, 2, 4, 6, 8];

 {Подмножество четных цифр}

      Vowels : Letters =

 ['A', 'E', 'I', 'O', 'U', 'y'];

 {Подмножество гласных букв}

      HexDigits : set of '0'..'z' =

 ['0'..'9', 'A'..'F', 'a'..'f'];

 {Символы 16-ричных чисел}

type shortWeekDays =

 (Pn,Vt,sr,ch,Pt,sb,Vs);

 {Перечислимый тип "дни недели"}

const Holidays : set of shortWeekDays

 = [sb, Vs];

 {Подмножество "Выходные" дней недели}

var wd:shortWeekDays;

 {Переменная типа "Дни недели"}

    i:integer;

begin

 wd:=Pn;

 for i:=1 to 7 do begin

  if wd in Holidays then

   writeln (ord(wd), ' - Выходной день')

  else writeln (ord(wd), ' - Будний день');

  Inc(wd);

 end;

end.

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

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

 идентификатор,..., идентификатор);

Возможные значения перечисления, заданные оператором type, должны быть идентификаторами Паскаля, поэтому назвать дни недели по-русски в последнем описании type было бы невозможно.

Идентификаторы, указанные в определении типа, становятся константами перечислимого типа, первая константа имеет порядковый номер 0, вторая -- номер 1, и так далее:

type suit = (Club, Diamond, Heart, Spade);

При этом объявлении Heart является константой типа suit. Стандартная функция ord возвращает порядковый номер перечислимой константы, в нашем примере

ord(Club)     = 0

ord(Diamond)  = 1

ord(Heart)    = 2

Как показано в листинге, переменным перечислимого типа можно присваивать константы, входящие в описание типа и увеличивать их значения как любые порядковые числа оператором Inc(wd), но эти значения нельзя читать или записывать "напрямую" операторами семейства read/write. В качестве альтернативы их можно приводить к целочисленным значениям стандартной функцией ord, при этом всегда первая константа списка имеет значение 0 (в нашем случае -- константа Pn). Оператор in в листинге позволяет проверить, попадает ли величина в подмножество, созданное для элементов исходного типа множества. Таким образом, основное назначение множеств и перечислимых типов -- удобная для человека запись выражений с "понятными" названиями констант вместо чисел. С точки зрения компилятора данные типа множества и перечисления являются целочисленными величинами.

Для ограничения диапазона исходных данных можно также непосредственно объявить тип-диапазон:

type Hour=0..23; minute=0..59;

Здесь объявлены переменные типов "час" и "минута", для переменных этих типов будут проверяться ограничения на попадание в указанные при описании диапазоны значений. Если переменной типа-диапазона присвоено недопустимое значение, программа отреагирует на это сообщением "Constant out of range".

Рейтинг@Mail.ru
вверх гостевая; E-mail
Hosted by uCoz