Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Программирование лекции.doc
Скачиваний:
50
Добавлен:
12.11.2019
Размер:
5.53 Mб
Скачать

4.1. Операции над множествами

Основная операция над множеством – проверка наличия в нем искомого значения. Для выполнения этой проверки программа проверяет значение бита с порядковым номером, равным искомому значению. Данная операция обозначается IN. Ее очень удобно использовать при обработке ввода с клавиатуры, чтобы не различать заглавные и строчные буквы:

VAR a:CHAR; … READ(a); IF a IN [‘y’,’Y’,’д’,’Д’] THEN …

Подобный подход гораздо логичнее и проще, чем написание сложного условия вида IF (a='Y') OR (a='Y')…

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

Объединение множеств A+B образует новое множество, в которое входят элементы и первого, и второго исходных множеств. Поскольку одинаковых элементов в множествах не бывает по определению (один элемент – один бит), то при объединении два одинаковых элемента превращаются в один. Обозначается операция объединения знаком "+". Схематически операция объединения показана на Рис. 5 .7.

Рис. 5.7. Объединение множеств.

Рассмотрим пример:

TYPE ts=SET OF CHAR; VAR a,b,c:ts; … a:=[’a’..’c’]; b:=[’d’..’f’]; c:=a+b;

Объединение множеств [’a’,’b’,’c’] и [’d’,’e’,’f’] приведет к результату ['a','b','c','d','e','f'].

Пересечение множеств A*B заключается в нахождении тех элементов, которые есть и в первом множестве, и во втором. Операция пересечения обозначатся знаком "*". Ее схема показана на Рис. 5 .8

Рис. 5.8. Пересечение множеств.

В нашем примере:

TYPE ts=SET OF CHAR; VAR a,b,c:ts; … a:=[’a’..’d’]; b:=[’d’..’f’]; c:=a*b;

Пересечение множеств [’a’,’b’,’c’, ’d’] и [’d’,’e’,’f’] приведет к результату ['d'] – этот элемент присутствовал в обоих множествах сразу. Если общих элементов нет, результатом пересечения будет пустое множество [].

Вычитание множеств A-B образует множество, в котором присутствуют только те элементы множества А, которых нет в множестве В (Рис. 5 .9).

Рис. 5.9. Вычитание множеств.

Вычитание множеств [’a’,’b’,’c’, ’d’] и [’d’,’e’,’f’] приведет к результату [’a’,’b’,’c’] – эти элементы не присутствовали во втором множестве.

4.2. Массивы

Массив (array) – самый распространенный сложный тип данных. Массив однороден: все его элементы имеют один и тот же базовый тип. Массив в памяти – структура данных с прямым доступом к каждому элементу (в отличие от файла на диске). Это означает, что для считывания содержимого элемента массива с номером 25 не нужно просматривать предыдущие 24 элемента (сравните CD и кассету). Нужный элемент в массиве находится по его индексу. В описании массива тип индекса также надо указывать. Таким образом, в описании массива присутствуют два типа данных:

  1. тип данных каждого элемента массива;

  2. тип данных индекса массива.

4.3. Утверждения о массивах

Массив описывается в программе так, как показано на Рис. 5 .10.

Рис. 5.10. Описание массива.

Например, в описании TA=ARRAY[1..10] OF REAL явно присутствуют два типа данных: REAL – тип элементов массив и тип диапазон 1..10, задающий число этих элементов.

Элементы массива располагаются в памяти непрерывно, один за другим (Рис. 5 .11).

Рис. 5.11. Размещение массива в памяти.

Это сделано для того, чтобы быстро и просто вычислять адрес элемента с заданным индексом. На суммарный размер всех элементов массива наложено ограничение – он не может превышать 64Кб. Дело в том, что память компьютеров типа IBM PC делится на сегменты размером по 64Кб. Программа одновременно работает с одним из многих сегментов памяти, поэтому все переменные должны занимать не более 65Кб. При попытке объявить слишком большой массив мы получим сообщение об ошибке:

TYPE TA=ARRAY[1..50000] OF REAL;

Structure too large

Как убедиться, что наш массив вылез из 64Кб? Давайте посчитаем. Из документации известно, что переменная типа REAL занимает 6 байт. 650000= 300000 байт или 300000/1024=292Кб. Кстати, определить размер в байтах любого типа данных поможет функция SizeOf. Например, SizeOf(REAL) вернет шесть.

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

TYPE TA=ARRAY[1..10] OF REAL; VAR A:TA; … A:=0;

Так делать нельзя! Переменной A как таковой нет – есть только переменные A[1], A[2], .. A[10].

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

TYPE TA:ARRAY[1..1000] OF REAL; VAR a:TA; … FILLCHAR(a,1000,0);

Малоизвестная процедура Паскаля FillChar(adr,n,v) заносит в память один за другим n штук значений v, начиная с адреса adr. Для массива это как раз подходит. Но так можно делать именно обнуление. При размере элемента массива, превышающем один байт, занесение ненулевых значений в несколько последовательных байт приведет к неожиданному результату. Так, переменная типа WORD занимает два байта. Если в оба из них занести значение 1, то значение всей переменной станет вовсе не 1, а 00000001000000012=257. Если во все элементы нужно занести ненулевое значение, придется писать цикл.

Как отмечалось выше, обращение к отдельному элементу массива происходит по его индексу (порядковому номеру). При этом индексы можно вычислять. Фактически рассчитывается адрес ячейки памяти, начиная с которой лежит элемент массива с затребованным индексом. В массиве адрес к-го элемента=адрес 1 элемента+(к  размер элемента в байтах).

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

TYPE TA1=ARRAY[1..20] OF REAL;

TA2=ARRAY[1..10] OF TA1;

В памяти все ячейки многомерного массива все равно хранятся последовательно, никаких строк и столбцов при этом не образуется. Поэтому вопрос "а какой индекс – это строки, а какой – столбцы?" – не имеет смысла. Размерностей может быть и более двух (теоретически – аж до 255).

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

VAR a:WORD; TYPE ta:ARRAY[1..a] OF REAL;

Однако вполне допустим вариант

CONST Nmax=20; TYPE ta:ARRAY[1..Nmax] OF REAL;

Константу Nmax будет удобно использовать при организации циклов по массиву:

FOR I:=1 TO Nmax DO

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