Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
000voprosy_k_ehkzamenu_po_oaipr_rakovcy.doc
Скачиваний:
4
Добавлен:
24.12.2018
Размер:
381.44 Кб
Скачать

Использование модулей

Для использования в программе величин, описанных в интерфейсной части модуля, имя модуля указывается в разделе 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. Теперь в процедуре А можно использовать обращение к процедуре В - ведь она уже описана, точнее, известны ее формальные параметры, и компилятор может правильным образом организовать ее вызов. Обратите внимание: тело процедуры В начинается заголовком, в котором уже не указываются описанные ранее формальные параметры.