| B3 : Array [ 'a'..'z'] of Byte;

| S : String;

| {$R-} { выключаем режим проверки индексов массивов }

| FUNCTION Sum( VAR X; N : Word ) : LongInt;

| TYPE

| XType = Array [ 1..1 ] of Byte;

| VAR

| Summa : Longint; i : Word;

| BEGIN

| Summa := 0;

| for i:=1 to N do

| Summa := Summa* XType( X )[i];

| Sum := Summa

| END;

Рис. 6.16

- 121 -

| { $R+} { можно при необходимости восстановить режим }

| BEGIN

| { Заполнение каким-либо образом массивов B1, B2 и B3; }

| ...

| S := '123456789';

| { печать суммы всех значений элементов массива B1 : }

| WriteLn( Sum( B1, 201));

| { сумма элементов B2 с 100-го по 200-й включительно: }

| WriteLn( Sum( B2[100], 101));

| { сумма 10 элементов массива B3, начиная с 'b'-го : }

| WriteLn( Sum( B3['b'], 10));

| {печать суммы кодов символов строки S с '1'-го по '9'-й}

| WriteLn( Sum( S[1], 9));

| END.

Рис 6.16 (окончание)

Как видно, функция Sum не боится несовместимости типов. Но она будет корректно работать только с массивами, элементами которых являются значения типа Byte. Мы сами задали это ограничение, определив тип XType, к которому впоследствии приводим все, что передается процедуре через параметр X. Обращаем внимание на диапазон описания массива XType: 1..1. Если режим компиляции $R имеет знак минус (состояние по умолчанию), то можно обратиться к массиву с практически любым индексом i и будет получен i-й элемент, считая от первого. Мы задаем индексы 1..1 чисто в иллюстративных целях. Можно было записать

| TYPE

ХТуре = Array [ 0..65520 ] of Byte;

забронировав максимальное число элементов (описание типа без объявления переменной не влияет на потребление памяти программой). В таком случае состояние ключа компиляции $R не играет роли. Функция Sum может начать отсчитывать элементы с любого номера (см. рис. 6.16). Можно даже послать в нее строку, и ее содержимое будет принято за байты (а не символы) и тоже просуммировано. Несложно написать обратную процедуру для заполнения произвольной части различных массивов. Надо лишь, чтобы базовый тип этих массивов совпадал с тем, который вводится внутри процедуры для приведения бестипового параметра. И, конечно, вовсе не обязательно ограничиваться одними массивами. Рассмотренный пример можно распространить и на записи, и на ссылки, и на

- 122 -

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

6.9.6.4. Рекурсия. Использование рекурсии — традиционное преимущество языка Паскаль. Турбо Паскаль в полной мере позволяет строить рекурсивные алгоритмы. Под рекурсией понимается вызов функции (процедуры) из тела этой же самой функции (процедуры).

Рекурсивность часто используется в математике. Так, многие определения математических формул рекурсивны. В качестве примера можно привести формулу вычисления факториала:

и целой степени числа:

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

| FUNCTION Fact( n : Word ) : Longlnt;

| BEGIN

| if n=0

| then Fact := 1

| else Fact := n * Fact( n-1 );

| END;

и степени n числа x:

| FUNCTION IntPower( x : Real; n : Word ) : Real;

| BEGIN

| if n=0

| then IntPower := 1

| else IntPower := x * IntPower( x, n-1);

| END;

Если в функцию передаются n>0, то происходит следующее: запоминаются известные значения членов выражения в ветви ELSE (для факториала это n, для степени — x), а для вычисления неизвестных вызываются те же функции, но с «предшествующими»

- 123 -

аргументами. При этом вновь запоминаются (но в другом месте памяти!) известные значения членов и происходят вызовы. Так происходит до тех пор, пока выражение не станет полностью определенным (в наших примерах — это присваивание в ветви THEN), после чего алгоритм начинает «раскручиваться» в обратную сторону, изымая из памяти «отложенные» значения. Поскольку при этом на каждом очередном шаге все члены выражений уже будут известны, через n таких, «обратных» шагов мы получим конечный результат.

Перейти на страницу:

Поиск

Похожие книги