Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Методическое пособие 555

.pdf
Скачиваний:
4
Добавлен:
30.04.2022
Размер:
2.33 Mб
Скачать

при этом их типы должны быть совместимы по присваиванию с типами соответствующих формальных параметров.

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

Рассмотрим следующую программу:

program lab; var

a1,b1,c1,d1: Integer; //глобальные переменные

procedure proc(a,b: Integer; var c,d: Integer); begin

writeln(a,' ',b,' ',c, ' ', d); a := 2; b := 2;

c := 2; d := 2;

writeln(a,' ',b,' ',c, ' ', d); end;

begin

a1 := 1; b1 := 1;

c1 := 1; d1 := 1;

proc(a1, b1, c1, d1); //вызов процедуры

writeln(a1,' ',b1,' ',c1, ' ', d1); end.

В этой программе процедура proc имеет четыре формальных параметра типа Real, при этом a и b – параметрызначения, а c и d – параметры-переменные. В основном блоке программы глобальным переменным a1, b1, c1 и d1 присваивается значение 1, после чего вызывается процедура proc c фактическими параметрами a1, b1, c1 и d1.

При вызове процедуры создаются локальные переменные a и b типа Real, которым присваиваются значения фактических параметров a1 и b1 (передача по значению). Для

111

параметров c и d новые локальные переменные не создаются: их адрес в оперативной памяти совпадает с адресом соответствующих глобальных переменных с1 и d1. В результате выполнения процедуры proc, значения глобальных переменных a1 и b1 останутся без изменения, а значения переменных c1 и d1 изменятся. Из вышеизложенного следует, что в процессе работы данной программы операторы writeln (два из которых расположены в теле процедуры, а один в основном блоке программы) выведут на экран следующие строки:

1 1 1 1

2 2 2 2

1 1 2 2

1.5. Опережающее описание подпрограммы

Подпрограммы могут быть вызваны не только из основной программы, но и из других подпрограмм. Здесь может возникнуть проблема, связанная с тем, что в языке Pascal нельзя использовать процедуру, не объявленную ранее (выше по тексту программы). Например, имеется две процедуры proc1 и proc2, при этом из процедуры proc1 вызывается процедура proc2, а из процедуры proc2 вызывается процедура proc1. Трудность связана с тем, что та из процедур, которая описана выше, «ничего не знает» о процедуре, описанной ниже, и не может ее вызвать.

Решить данную проблему можно при помощи директивы forward, которая позволяет объявить заголовок подпрограммы, не описывая при этом ее тело (оно должно быть описано позднее). Для рассмотренного примера это будет выглядеть следующим образом:

//Опережающее описание первой процедуры procedure proc1(список параметров); forward;

//Описание второй процедуры procedure proc2(список параметров); begin

112

...

Вызов процедуры proc1;

...

end;

//описание процедуры proc1 procedure proc1(список параметров); begin

...

Вызов процедуры proc2;

...

end;

1.6.Использование массивов в качестве параметров

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

procedure proc(a: array [1..5] of Integer);

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

type

MyArr = array[1..5] of Integer;

procedure proc (a: MyArr);

1.7. Рекурсия

Если подпрограмма вызывает сама себя, то такой вызов называют рекурсивным. В качестве примера рассмотрим рекурсивную функцию, вычисляющую результат возведения переменной x в целую неотрицательную степень n :

113

function pow(x: real; n: Integer): Real; begin

if (n = 0) then begin pow := 1;

end

else begin

pow := pow(x,n-1)*x; end;

end;

Рассмотрим работу функции pow. Предположим, функция была вызвана из основной программы оператором pow(2,3), т.е. мы вычисляем значение 23. Параметры этой процедуры сразу после первого вызова примут значения x = 2, n = 3. При выполнении оператора присваивания

pow := pow(x,n-1)*x;

будет выполнен рекурсивный вызов функции pow – эта вторично вызванная функция выполняет тот же программный код, но с другими начальными параметрами: x = 2, n = 2. Эта функция вызовет функцию pow еще раз. Рекурсивные вызовы будут продолжаться до тех пор, пока в очередной вызванной функции не выполнится условие n = 0: эта функция вернет значение 1 в функцию, вызванную предпоследней. Та в свою очередь вернет значение 1*2 в функцию, вызванную перед ней и т.д. В итоге функция pow, вызванная в первый раз из основной программы, вернет значение 23 = 8.

2. Практическая часть

Задание 1. Написать программу, содержащую процедуру расчета двух сторон треугольника, если известны (заданы пользователем) длина его третьей стороны и два прилежащих к ней угла.

114

Решение. Найти две неизвестные стороны можно при помощи теоремы синусов (cм. рисунок):

 

a

b

 

c

 

2R ,

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

sin

sin

 

sin

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

где R – радиус окружности, описанной около треуголь-

ника. Пусть известна сторона c и углы

и , тогда

180

 

, a

 

sin

c

,

b

 

sin

c

.

 

 

sin

 

sin

 

 

 

 

 

 

 

 

 

 

 

 

 

Код программы представлен ниже.

program lab_6_p1;

var //глобальные переменные

a,b,c: Real; //длины сторон треугольника

alfa, beta: Real; //углы, прилежащие к стороне c

//описание процедуры proc

procedure proc(c,alfa,beta: Real; var a,b : Real); var

gamma: Real; //локальная переменная begin

gamma := 180 - alfa - beta;

a := (sin(alfa*Pi/180)/sin(gamma*Pi/180))*c; b := (sin(beta*Pi/180)/sin(gamma*Pi/180))*c; end;

begin

//получаем исходные данные от пользователя writeln('Введите длину стороны треугольника:'); readln(c);

writeln('Введите первый прилежащий угол:'); readln(alfa);

writeln('Введите второй прилежащий угол:'); readln(beta);

//Вызываем процедуру

115

proc(c,alfa,beta,a,b);

//Выводим результат

writeln('Длины двух других сторон: '); writeln(a, ' ', b);

end.

Список формальных параметров процедуры proc содержит 5 переменных, из которых три – c, alfa и beta – па- раметры-значения, а два – a и b – параметры-переменные. Также объявлена локальная переменная gamma. Тело процедуры содержит операции присваивания, обеспечивающие вычисление длин сторон треугольника по указанным выше формулам. При вычислении синусов углы умножаются на коэффициент Pi/180 для перевода из градусов в радианы.

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

В основном блоке программы сначала обеспечивается получение от пользователя исходных данных – значений глобальных переменных c, alfa и beta. Затем вызывается процедура proc с пятью фактическими параметрами – глобальными переменными c, alfa, beta, a, b. Поскольку два последних параметра передаются по ссылке (на это указывает ключевое слово var в списке формальных параметров процедуры), в результате выполнения процедуры значения глобальных переменных a и b изменятся. Далее остается только вывести результат расчета на экран оператором writeln.

Нажимая клавишу F8, выполните пошаговое выполнение программы, при этом на шаге вызова процедуры proc используйте клавишу F7 – «шаг со входом в подпрограмму». Можно также использовать «точку остановки», расположенную в теле процедуры. Проследите за изменениями значений всех переменных.

116

Задание 2. Длина одной стороны треугольника и два прилежащих к ней угла задаются пользователем. Программа должна вывести на экран радиус описанной около треугольника окружности и ее площадь. Для расчета радиуса описанной окружности используйте подпрограмму-функцию.

Задание 3. Дан двумерный массив из 3 × 3 элементов (вещественных чисел). Вычислить определитель соответствующей квадратной матрицы. Элементы массива должны вводиться пользователем, для вычисления определителя используйте функцию.

Задание 4. Массивы a и b, содержащие 5 целочисленных элементов, вводятся пользователем. Необходимо вычислить сумму массивов a и b (по правилу сложения матриц) и результат поместить в массив b. Итоговый массив b должен быть выведен на экран. Напишите текст соответствующей программы, которая должна содержать три подпрограммы: для ввода одного массива, для вывода массива на экран и для вычисления суммы массивов.

Задание 5. Напишите программу, вычисляющую факториал числа n, задаваемого пользователем, при помощи рекурсивной функции.

3.Контрольные вопросы и задания

1.Какие преимущества дает использование подпрограмм?

2.Какие виды подпрограмм имеются в языке Pascal? Чем они отличаются друг от друга?

3.Как выглядит описание процедуры и функции? Какой оператор обязательно должен содержаться в теле функции?

4.Какие параметры называют формальными, а какие фактическими?

5.Чем отличаются механизмы передачи в подпрограмму параметров-значений и параметров-переменных? В каких

117

случаях следует использовать параметры-переменные, а в каких – параметры-значения?

6.Как вызвать подпрограмму, что происходит при вызове?

7.Можно ли использовать в качестве фактического пара- метра-переменной арифметическое выражение? Поясните почему.

8.В каких случаях может потребоваться опережающее описание подпрограммы? Как оно осуществляется?

9.Как использовать в качестве параметра процедуры или функции статический массив?

10.Что такое рекурсия? Поясните алгоритм работы рекурсивной функции для вычисления факториала (задание 5).

Лабораторная работа № 7

МОДУЛЬ GRAPHABC И ПРОГРАММИРОВАНИЕ ГРАФИКИ

1.Теоретические сведения

1.1.Модуль GraphABC. Графическое окно

Модуль GraphABC представляет собой библиотеку подпрограмм для учебного программирования графики. Этот модуль подключается к программе стандартным способом в разделе подключения модулей uses:

uses graphABC;

В модуле GraphABC определено множество констант, типов, процедур, функций и классов для рисования в графическом окне. Экран представляет собой матрицу точек (пикселей), причем имеется возможность высветить любой пиксель любым цветом. Любой объект, высвечиваемый на экране, является совокупностью отдельных пикселей. Координаты каж-

118

дого пикселя определяются парой целых чисел (x, y). По умолчанию, пиксель с координатами (0, 0) (начало координат) расположен в левом верхнем углу графического окна. При этом координата x увеличивается слева направо, а координата y сверху вниз.

Для работы с графическим окном предусмотрен ряд подпрограмм, некоторые из которых представлены в табл. 7.1.

Таблица 7.1 Подпрограммы для работы с графическим окном

Имя процедуры (функции)

Действие

 

 

 

 

Возвращает ширину клиентской

WindowWidth: Integer

части графического окна в пик-

 

селях

 

 

Возвращает высоту клиентской

WindowHeight: Integer

части графического окна в пик-

 

селях

 

SetWindowWidth(w:

Устанавливает ширину клиент-

ской части графического окна в

Integer)

пикселях

 

 

 

SetWindowHeight(h:

Устанавливает высоту

клиент-

ской части графического окна в

Integer)

пикселях

 

 

 

SetWindowSize(w,h:

Устанавливает размеры клиент-

ской части графического окна в

Integer)

пикселях

 

 

 

ClearWindow

Очищает графическое окно бе-

лым цветом

 

 

 

ClearWindow(c:

Очищает графическое

окно

Color)

цветом c

 

119

1.2. Цвет

Для задания цвета в модуле GraphABC предусмотрен тип Color. Для работы с цветом предусмотрен ряд подпрограмм, например функция

function RGB(r,g,b: byte): Color;

возвращает цвет, который содержит красную (r), зеленую (g) и синюю (b) составляющие (r, g и b – в диапазоне от 0 до 255).

Кроме того, задавать различные цвета можно с использованием множества цветовых констант: clBlack (черный), clWhite (белый), clRed (красный), clGreen (зеленый), clBlue (синий), clCyan (голубой), clMagenta (пурпур-

ный), clYellow (желтый) и др. (cм. справочную систему

PascalABC.Net).

1.3. Свойства пера и кисти

Рисование линий осуществляется текущим пером (Pen), заливка замкнутых областей – текущей кистью (Brush), а вывод строк – текущим шрифтом (Font).

Процедуры и функции для доступа к свойствам пера и кисти, некоторые из которых представлены в табл. 7.2, сгруппированы парами. Так, если Prop – имя свойства пера, то функция PenProp возвращает значение этого свойства, а процедура SetPenProp(p) устанавливает это свойство.

Таблица 7.2 Подпрограммы для работы с пером, кистью и шрифтом

Имя процедуры (функции)

Действие

 

 

SetPenColor(c:

Устанавливает цвет текущего

Color)

пера

PenColor: Color

Возвращает цвет текущего пера

SetPenWidth(Width:

Устанавливает ширину текуще-

Integer)

го пера

120