Основы программирования (947332), страница 28
Текст из файла (страница 28)
7] ofinteger=((], J, /, 7,1),(2X2X2).(3X3,3,3));Var i:integer;Beginfor i:=Low(a) to Higlt(a) do WriteLn(sum(a[i]));end.Примечание. Обратите внимание, что допустимо лередавать в подпрограмму строку матрицы как одномерный массив, указав ее номер - a[i].В том случае, если необходимо разработать универсальную подпрограмму с параметрами - многомерными массивами, следует применять нетипизированные параметры (см. параграф 5.5).Проблема разработки универсальных подпрограмм существует и длястрок.По правилам Borland Pascal, если строка передается в подпрограмму какпараметр-значение, то длина ее не контролируется. Контроль длины осуществляется только для строк, передаваемых в подпрограмму как параметр-переменная. Поэтому при написании универсальных подпрограмм, работающих со строками произвольного размера, необходимо включать режим открытых строк {$Р+} или объявлять параметры-строки как openstring.Пример 5.7.
Разработать программу, которая формирует строку, содержащую буквы латинского алфавита.Для решения задачи будем использовать процедуру, которая добавляет кстроке символ, номер которого на единицу превышает номер последнегосимвола:Unit Stroka;InterfaceProcedure Add(var s: openstring);161Часть L Основы алгоритмизации и процедурное программированиеImplementationProcedure Add;begins:=^s+chr(succ(Ord(s[length(s)J)));end;EndПараметр s должен передаваться как открытая строка, так как в противном случае при попытке использовать процедуру в программе мы получимсообщение о том, что типы формального и фактического параметров не совпадают (Error 26: Туре mismatch).Program ex;Uses Stroka;Var S:string[26]; i:integer;Begins:^'A\for i: =2 to 26 do Add(s);WriteLn(s);EndУвеличить область применения подпрограмм позволяет также использование нетипизированных параметров и параметров процедурного типа.Задания для самопроверкиЗадание 1.
Разработайте универсальную подпрограмму, удаляющую из массива элемент, номер которого передается в списке параметров. Поместите подпрофамму в модуль. Разработайте тестирующую программу.Задание 2. Разработайте универсальную подпрофамму, которая сортирует слова строки по алфавиту. Слова в строке разделены одним пробелом. Поместите подпрограмму в модуль. Разработайте тестирующую программу.5.5.
Нетипизированные параметрыВ Borland Pascal допускается использовать параметры, тип которых неуказан. Такие параметры могут передаваться в подпрограмму только поссылке (как параметры-переменные), так как в этом случае в подпрограммуреально передается адрес параметра.Безусловно, для того чтобы подпрограмма могла выполнять какие-либодействия с этим параметром, она должна как-то назначить ему тип.Для приведения нетипизированного параметра к определенному типуможно использовать:1625. Модульное программирование• автоопределенное преобразование типов;• наложенное описание переменной определенного типа.При автоопределенном преобразовании типов тип выражения указывают явно (см.
параграф 2.5), например:Procedure Proc(Var:a);......b:=Integer(a)-^IO;,..Для наложения переменной определенного типа используют описание сabsolute (см. параграф 2.3), например:Procedure Proc(Var:a);...Var r:real absolute a;...При этом переменная г оказывается в памяти размещенной в том же месте, что и нетипизированный параметр а, и, соответственно, любое изменение г приведет к изменению а.Пример 5.8.
Разработать подпрограмму, которая может суммировать какэлементы массива целых чисел, так и элементы массива вещественных чисел.Тип массива подпрограмма будет определять по значению третьего параметра, для которого объявим специальный перечисляемый тип. В разделеописаний подпрограммы определим шаблоны для каждого случая. Шаблонпредставляет собой описание массива соответствующего типа максимальновозможного размера 64 Кб/<размер элемента>. Оба шаблону наложены поадресу нетипизированного параметра. Если значение третьего параметраподпрограммы treal, то используется шаблон mr, а если tinteger - шаблон mi.Unit Summa4;InterfaceType ttype=(treal, tinteger); {описание типа третьего параметра}Function sumfvar x;n:integer;t:ttype).real;ImplementationFunction sum;Var mr:array[L.maxint*2 div sizeof(real)] of real absolute x;mi: array[L.maxint^l div sizeof(integer)] of integer absolute x;s:real;i:integer;begin s:=0;if t=treal thenfor i:-I to n do s:=s+mr[ijelse for i:=I to n do s:-s+mifij;sum:=s;end;End163Часть I.
Основы алгоритмизации и процедурное программированиеТестирующая программа вызывает одну и ту же функцию для суммирования массивов с разным типом элементов.Program ex;Uses Summa4;Var a:array[L.10] of integer;b:array[L.15] of real;i,n; integer;Beginfor i;=l to 10 do Read(a[iJ); ReadLn;WriteLnCCyMMa= \stim(a,10,tintegerJ:8:J);for i:=l to J 5 do Read(b[i]); ReadLn;WriteLn('CyMMa= \sum(b, 15jreal):8:l);end.Примечание. Вместо описания массива максимально возможного размера в подпрограмме можно описать массив длиной 1 элемент, но при работе с таким шаблоном необходимо отключать контроль индексов {$R-}.Нетипизированные параметры можно применить для написания универсальных подпрограмм, использующих в качестве параметров многомерныемассивы.
Поскольку невозможно в подпрограмме определить универсальный шаблон многомерного массива, приходится обрабатывать многомерныймассив как одномерный, учитывая то, что элементы многомерных массивовв памяти располагаются так, что чем правее индекс, тем быстрее он возрастает. Так, элементы трехмерного массива В(2,3,2) будут расположены впамяти в следующем порядке:bl,l,l' ^^1,1,2' bi,2,i, b | 2,2^ b] 3,1, b] 3 2, b 2 | j , ^2,\,b ^2,2,1' ^2,2,2^ Ь2Д1, Ь2зд.Пример 5.9.
Разработать универсальную подпрограмму транспонирования матрицы.На рис. 5.9 показано, как в матрице А(Р,Р) расположены элементы реальной матрицы размером пхп, где п<Р, и, соответственно, как те же элементырасположены в памяти.Таким образом, в одномерном массиве элемент с индексами i и j имеетиндекс (i-l)*P+j, т.е. индекс этого элемента зависит от размера строки зарезервированной матрицы. В подпрограмму это значение передается через параметр Р.Чтобы транспонировать матрицу, меняем местами элементы, расположенные ниже и выше главной диагонали.Примечание.
При разработке алгоритма процедуры учтено, что при транспонированииматрицы по аналогии с переворотом строки количество перестановок равно п*п div 2. Есливыполнить п*п перестановок, то матрица примет исходный вид, так как будет транспонирована дважды.1645. Модульное программирование1-я строкаи т.д.пНеопределенныеэлементыНеопределенныеэлементыРис. 5.9. Матрица А(Р,Р) {а) и ее внутреннее представление {б)Unit Matrica;InterfaceProcedure tran(Var x;n,P:integer);ImplementationProcedure tran;Var a:array[1..2*maxint div sizeof(real)] of real absolute x;ij: integer;t.real;beginfor i:=2 to n doforj:=l to i-I dobegin t: =a[(i-l) ''P+jJ;af(i-l) *P+jJ: =afO'l) *P+i];a[0'l)''P+i]:=t;end;end;End.Тестирующая программа выглядит следующим образом:Program ex;Uses Matrica;Var a:array[L .10J,.
10] of real;ij.'integer;BeginWriteLnCВведите матрицу a(5 *5);');for i:=l to 5 dobeginfor j:=l to 5 do Read(a[i,j]);ReadLn;end;165Часть I. Основы алгоритмизации и процедурное программированиеtran(a,5,10);WriteLn('Результат: *);for i:-l to 5 dobeginforj:=l to 5 do Write(a[iJ]:6:2);WriteLn;end;EndЗадания для самопроверкиЗадание 1. Разработайте универсальную подпрограмму, определяющую среднее арифметическое элементов матрицы размером nxm элементов.
Поместите подпрофамму в модуль. Разработайте тестирующую программуЗадание 2. Разработайте универсальную подпрограмму, удаляющую из матрицы размером nxm заданную строку и столбец. Поместите подпрограмму в модуль.Разработайте тестирующую программу.5.6. Параметры процедурного типаПараметры процедурного типа используют тогда, когда нужно передатьв подпрограмму имена процедур и функций.Для объявления процедурного типа используют заголовок подпрограммы, в котором отсутствует имя, например:Туре proc=procedure (a,b,c:real;Var d:real):func=function(x: real): real;Значениями переменных процедурных типов являются идентификаторыпроцедур и функций с соответствующими заголовками:Var f:func;/:фп1;...Процедуры или функции, идентификаторы которых будут передаватьсяв качестве параметров процедурного типа, по правилам языка необходимокомпилировать в режиме дальнего вызова (с указанием директивы компилятора {$Р+}или служебного слова far).
В этом режиме при вызове подпрограмм используются длинные 4-байтовые адреса (см. параграф 7.1) в отличие от коротких 2-байтовых адресов, которые применяются для адресацииподпрограмм, объявленных в основной программе или ее подпрограммах.1665. МодульноепрограммированиеПримечания: 1. Если процедуры или функции описываются в интерфейсной части модуля (см. параграф 5.2), то по умолчанию они вызываются в режиме дальнего вызова, поэтомуспециально это оговаривать не надо.2. Стандартные процедуры и функции, описанные в модуле System, по умолчанию являются функциями ближнего вызова.