- •Ввод данных с клавиатуры
- •Вывод данных на экран. Форматированный вывод
- •Операторы цикла while, repeat, for Цикл while-do (цикл с предусловием - ред.)
- •Цикл repeat-until (цикл с постусловием - ред.)
- •Цикл for (цикл со счётчиком - ред.)
- •Рекуррентные последовательности
- •Процедуры и функции
- •Описание и вызов процедур и функций
- •Процедуры
- •Функции
- •Различие между процедурами и функциями
- •Модуль System
- •Модуль Crt
- •Модули Dos и WinDos
- •Модуль Graph
- •Описание модулей
- •Использование модулей
- •Операции над множествами
Использование модулей
Для использования в программе величин, описанных в интерфейсной части модуля, имя модуля указывается в разделе uses. Можно записать несколько имен модулей через запятую, например:
program example;
uses Average, Graph, Crt;
...
Поиск модулей выполняется сначала в библиотеке исполняющей системы, затем в текущем каталоге, а после этого - в каталогах, заданных в диалоговом окне Options/Directories.
Если в программе описана величина с тем же именем, что и в модуле, для обращения к величине из модуля требуется перед ее именем указать через точку имя модуля.
47.
Множества в Паскале - это наборы элементов перечислимого типа.
Определение множества очень похоже на определение массива, разве что для массива мы говорим о том, что он расположен в единой области памяти. Давайте разберемся, чем массивы отличаются от множеств.
-
Элементы массива могут иметь практически любой тип. Элементы множества обязаны относиться к перечислимому типу.
-
Каждый элемент занимает в массиве определенную позицию, которая обозначается его индексом. Причем индекс этот можно изменить в программе. Положение элемента в множестве зависит от реализации Паскаль-машины и во аремя выполнения программы меняться не может. Когда мы используем множество в программе, нас интересует только наличие или отсутствие в нем элемента с нужным значением.
-
В массиве может быть сколько угодно элементов с одинаковыми значениями. В множество каждый элемент входит строго один раз.
В выражениях на языке Паскаль значения элементов множества указываются в квадратных скобках: [1,2,3,4], ['а',‘b','с'], ['a'..'z'].
При задании множества мы объявляем, на каком типе оно базируется:
type {перечисляемый тип} VideoAdapterType = {MDA, Hercules, AGA, CGA, MCGA, EGA, VGA, Other, NotDetected}; {варианты множеств} SetOfChar = Set of Char; {множество из символов} SetOfByte = Set of Byte; {множество из чисел} SetOfVideo = Set of VideoAdapterType; {множество из названий видеоадаптеров} SetOfDigit = Set of 0..9; {множество из чисел от 0 до 9, задано диапазоном} SetOfDChar = Set of '0'..'9'; {множество символов - цифр, задано диапазоном} SetOfVA = Set of CGA..VGA; {подмножество названий видеоадаптеров} |
Базовый перечислимый тип можно вводить прямо в конструкции Set of...
SetOfVideo = Set of (MDA, Hercules, AGA, CGA, MCGA, EGA, VGA, Other, NotDetected}; |
В множестве может быть только до 256 элементов, поэтому типы ShortInt, Word, Integer, LongInt, хоть и перечислимые, базовыми для множеств быть не могут.
Операции над множествами
Объединением двух множеств A и B называется множество, состоящее из элементов, входящих хотя бы в одно из множеств A или B. Знак операции объединения в Паскале «+».
Примеры:
1) [1, 2, 3, 4] + [3, 4, 5, 6] => [1, 2, 3, 4, 5, 6]
2) []+[‘a’..’z’]+[‘A’..’E’, ‘k’] => [‘A’..’E’, ‘a’..’z’]
3) [5<4, true and false] + [true] => [false, true]
Пересечением двух множеств A и B называется множество, состоящее из элементов, одновременно входящих во множество A и во множество B.
Знак операции пересечения в Паскале «*»
Примеры:
1) [1, 2, 3, 4] * [3, 4, 5, 6] => [3, 4]
2) [‘a’..’z’]*[‘A’..’E’, ‘k’] => [‘k’]
3) [5<4, true and false] * [true] => []
Разностью двух множеств A и B называется множество, состоящее из элементов множества A, не входящих во множество B.
Примеры:
1a) [1, 2, 3, 4] - [3, 4, 5, 6] => [1, 2]
1b) [3, 4, 5, 6] - [1, 2, 3, 4] => [5, 6]
2a) [‘a’..’z’]-[‘A’..’E’, ‘k’] => [‘a’..’j’, ‘i’..’z’]
2b) [‘A’..’E’, ‘k’] - [‘a’..’z’] => [‘A’..’E’]
3a) [5<4, true and false] - [true] => [false]
3b) [true] - [5<4, true and false] => [true]
Операция вхождения. Это операция, устанавливающая связь между множеством и скалярной величиной, тип которой совпадает с базовым типом множества. Если x — такая скалярная величина, а M — множество, то операция вхождения записывается так: x in M.
Результат — логическая величина true, если значение x входит в множество M, и false — в противном случае.
Например, 4 in [3, 4, 7, 9] –– true, 5 in [3, 4, 7, 9] –– false.
Используя данную операцию, можно не только работать с элементами множества, но и, даже если в решении задачи явно не используются множества, некоторые логические выражения можно записать более лаконично.
1) Натуральное число n является двухзначным. Вместо выражения (n >= 10) and (n <=99) можно записать n in [10..99].
2) Символ c является русской буквой. Вместо выражения (c >= ‘А’) and (c <= ‘Я’) or (c>=‘а’) and (c<=‘п’) or (c>=‘р’) and (c<=‘я’) пишем c in [‘А’.. ‘Я’, ‘а’.. ‘п’, ‘р’.. ‘я’] и т.д.
48.
Рекурсия - это такой способ организации вычислительного процесса, при котором подпрограмма в ходе выполнения составляющих ее операторов обращается сама к себе. Рассмотрим классический пример - вычисление факториала. Программа вводит с клавиатуры целое число N и выводит на экран значение N.
примере 8.5 решение при N = 0 тривиально и используется для остановки рекурсии. Пример 8.5
Program Factorial; {$S+} {Включаем контроль переполнения стека} var n: Integer; Function Facfn: Integer): Real; {Рекурсивная функция, вычисляющая n ! } begin {Fac} if n < 0 then WriteLn ('Ошибка в задании N') else if n = 0 then Fac := 1 else Fac := n * Fac(n-l) end {Fac} ; {---------------} begin {main} repeat ReadLn (n) ; WriteLn ('n!= ',Fac(n)) until EOF end {main} . Рекурсивная форма организации алгоритма обычно выглядит изящнее итерационной и дает более компактный текст программы, но при выполнении, как правило, медленнее и может вызвать переполнение стека (при каждом входе в подпрограмму ее локальные переменные размещаются в особым образом организованной области памяти, называемой программным стеком). Переполнение стека особенно ощутимо сказывается при работе с сопроцессором: если программа использует арифметический сопроцессор, результат любой вещественной функции возвращается через аппаратный стек сопроцессора, рассчитанный всего на 8 уровней. Если, например, попытаться заменить тип REAL функции FAC (см. пример 8.5) на EXTENDED, программа перестанет работать уже при N = 8. Чтобы избежать переполнения стека сопроцессора, следует размещать промежуточные результаты во вспомогательной переменной. Вот правильный вариант примера 8.5 для работы с типом EXTENDED:
Program Factorial; {$S+,N+,E+} {Включаем контроль Стека и работу сопроцессора} var n: Integer; Function Fac(n: Integer): extended; var F: extended; {Буферная переменная для разгрузки стека сопроцессора} {Рекурсивная функция, вычисляющая п! } begin {Рас} if n < 0 then WriteLn ('Ошибка в задании N') else if n = 0 then Fac := 1 else begin F := Fac(n-l) ; Fac := F * n end end {Fac} ; {--------------} begin {main} repeat ReadLn (n) ; WriteLn ('n! = ',Fac(n)) until EOF end {main} . Рекурсивный вызов может быть косвенным. В этом случае подпрограмма обращается к себе опосредованно, путем вызова другой подпрограммы, в которой содержится обращение к первой, например:
Procedure A (i : Byte) ; begin ....... В (i); ....... end ; Procedure В (j : Byte) ; ....... begin ....... A(j); ....... end; Если строго следовать правилу, согласно которому каждый идентификатор перед употреблением должен быть описан, то такую программную конструкцию использовать нельзя. Для того, чтобы такого рода вызовы стали возможны, вводится опережающее описание:
Procedure В(j : Byte); forward; Procedure A(i : Byte); begin ....... В (i) ; ....... end ; Procedure В; begin ....... A(j); ....... end;
Как видим, опережающее описание заключается в том, что объявляется лишь заголовок процедуры В, а ее тело заменяется стандартной директивой FORWARD. Теперь в процедуре А можно использовать обращение к процедуре В - ведь она уже описана, точнее, известны ее формальные параметры, и компилятор может правильным образом организовать ее вызов. Обратите внимание: тело процедуры В начинается заголовком, в котором уже не указываются описанные ранее формальные параметры.