Оператор вызова процедуры
В статье “Подпрограммы” 2 подробно рассказывается о таком виде подпрограмм, как процедуры. Стандартные подпрограммы языка программирования, которые входят в одну из библиотек подпрограмм, а также пользовательские подпрограммы, описанные внутри данного блока, вызываются с помощью оператора вызова процедуры:
<имя процедуры>(E1,E2,…,En)
Здесь E1,E2,…,En — переменные или выражения, представляющие собой фактические параметры обращения к процедуре. Наиболее часто используемыми стандартными процедурами являются процедуры ввода и вывода данных (read и write в Pascal).
Вызов процедуры семантически эквивалентен выполнению блока, описанного в качестве тела процедуры, после передачи в него начальных значений некоторых переменных (параметров-значений) или замены имен некоторых переменных (параметров-переменных) на имена фактических переменных, указанных при вызове процедуры.
39. При передаче и преобразовании информации в программе должны соблюдаться некоторые требования, блокирующие некорректные действия программиста. Эти требования могут быть разделены на три группы, соответствующие следующим случаям:
1. передача фактического параметра-переменной;
2. вычисление выражения;
3. выполнение оператора присваивания и передача фактического параметра-значения.
В первом случае должны быть выполнены требования тождественности типов, во втором – совместимости типов, в третьем – совместимости по присваиванию. Тождественность типов. Рассмотрим процедуру, в списке формальных параметров которой заданы лишь параметры-переменные (перед именем формального параметра записано слово Var). Пример 1.
Type Ar1 = array[1..100] of real;
Ar2 = array[1..100] of real;
Ar3 = Ar1;
Ar4 = Ar3;
Var X : Ar1; Y : Ar2; Z : Ar3; W : Ar4;
a,b : real;
m,n : integer;
Procedure Proc1(Var D:Ar1; Var k:integer);
Begin
..........................
End { Proc1 };
Ранее было указано, что формальный и соответствующий ему фактический параметр должны иметь одно и то же имя типа. Это не совсем точно. Обозначим через Type1 имя типа формального параметра, через Type2 - имя типа соответствующего ему фактического параметра. Как известно, при обращении к процедуре фиктивный адрес формального параметра-переменной замещается реальным адресом фактического параметра. В этом случае формальная и фактическая переменные соответствуют одному и тому же полю памяти. Следовательно, имена типов Type1 и Type2 этих переменных должны определять переменные одинакового размера и структуры, с одинаковым множеством допустимых значений и операций по их обработке. Последнее возможно, если типы Type1 и Type2 тождественны. Два типа считаются тождественными, если они представляют собой одно и то же имя типа или один из них описан как эквивалентный другому типу. В примере 1 типы Ar1, Ar3 и Ar4 тождественны, Ar1 и Ar2 - не тождественны, хотя они и имеют одинаковое описание типа. Поэтому обращения к процедуре Proc1(X,m), Proc1(Z,m) и Proc1(W,m) считаются правильными, а при обращении Proc1(Y,m) будет выведено сообщение "Type mismatch" ("Несоответствие типов"). Совместимость типов. Рассмотрим пример 2. Пример 2.
Var x,y : real;
m,n : integer;
ch : char;
b : boolean;
Begin ...............
y:=x+2*ch;
b:=(x<ch) and n;
Вполне очевидно, что выражения в правой части операторов присваивания не могут быть вычислены, поскольку лишены смысла арифметические операции по отношению к символьным переменным, сравнение числовых и символьных переменных и т.п. В этих выражениях нарушены требования совместимости типов. Основные правила совместимости типов: - операнды выражения имеют численные типы (вещественный, целочисленный, диапазонный); - операнды определены логическим типом; - операнды имеют строковый, символьный или диапазонный символьный типы. Если операнды выражения имеют различные численные типы, то при выполнении арифметических операций производится преобразование их значений к более старшему типу в соответствии со следующими приоритетами: - real; - longint; - integer, word; - shortint, byte.
Совместимость типов по присваиванию. Рассмотрим пример 3. Пример 3.
Var x,y : real;
m,n : integer;
ch : char;
b : boolean;
Begin ...............
{ 1 } y:=(m<n) and b;
{ 2 } ch:=x+m;
{ 3 } m:=2*x+y;
{ 4 } y:=3*m-n;
Числовой переменной нельзя присвоить булевское значение, символьной переменной - численное значение. Поэтому операторы 1 и 2 не могут быть выполнены, здесь нарушается требование совместимости по присваиванию. В правой части оператора 3 - вещественное значение, в левой части - целочисленная переменная. Если допустить выполнение такого оператора, то дробная часть вещественного значения должна быть отброшена, т.е. произошла бы потеря точности. В связи с этим считается, что в операторе 3 также нарушаются требования совместимости по присваиванию. В операторе 4 потеря точности не наблюдается. При его выполнении производится лишь преобразование целочисленного значения, полученного при вычислении выражения в правой части оператора, к типу real. Обозначим тип переменной в левой части Type1, тип значения выражения - Type2. Основные требования совместимости по присваиванию: - Type1 и Type2 имеют тождественные типы и ни один из них не является файловым типом; - Type1 и Type2 - целочисленные типы; - Type1 - вещественный тип, Type2 - вещественный или целочисленный тип; - Type1 и Type2 - строковые типы; - Type1 - строковый тип, Type2 - символьный тип. Более жесткие требования должны соблюдаться, когда в левой и правой частях оператора присваивания записаны составные переменные, в частности, массивы. Пример 4.
Type Ar1 = array[1..100] of real;
Ar2 = array[1..100] of real;
Ar3 = Ar1;
Var X,Y : Ar1; Z : Ar2; W : Ar3;
Здесь типы Type1 и Type2 должны быть тождественными. Следовательно, в этом случае операторы Y:=X и Y:=W являются допустимыми, в то время как для оператора Y:=Z будет определено несоответствие типов. Рассмотрим теперь процедуру, в списке формальных параметров которой имеются параметры-значения. Пример 5.
Var x,y : real;
m,n : integer;
Procedure Proc2(k:integer; r,t:real);
Begin
End { Proc2 };
Begin
{ 1 } Proc2(m,n-1,x+m);
{ 2 } Proc2(y,x+y,x);
Для параметра-значения в теле процедуры выделяется поле памяти в соответствии с его типом. При обращении к процедуре в это поле пересылается значение фактического параметра; другими словами, формальному параметру присваивается значение фактического параметра. Следовательно, по отношению к параметру-значению должны соблюдаться изложенные выше требования совместимости по присваиванию. В частности, в примере 5 для оператора 1 эти требования соблюдаются, для оператора 2 - не соблюдаются.
41.Процедуры ввода-вывода в языке Pascal
Процедуры вывода
Write( Зн1 [,Зн2,..., Знn] )– записывает одно или более значений из одной или более переменных в текстовый файл.
Каждые параметры Зн являются выражениями, значения которых должны быть выведены на экран. Каждое выводимое выражение должно быть символьного, целого, вещественного, строкового, или булевского типа.
Writeln( Зн1, [,Зн2,..., Знn])– данная процедура является расширением процедуры Write. После выполнения процедуры Write процедура Writeln переводит курсор на следующую строку.
Пример использования процедур вывода:
Рассмотрим выполнение процедур вывода следующей программы:
program Wrt;
Var
r:real; i:integer;
s:string[10];
Begin
i:=12;
r:=100;
s:= 'r=';
write(s,r);
writeln('i=',i);
write(i+1,r+i);
writeln();
write(i,', ',i);
End.
При выполнении программы на экране будут появляться выводимые процедурами вывода значения (таблица 4).
Таблица 4 – Пошаговое выполнение процедур вывода
Выполняемый оператор
| Экран программы
| | | write(s,r);
| r=1.0000000000E+02
| | writeln('i=',i);
| r=1.0000000000E+02i=12
| | write(i+1,r+i);
| r=1.0000000000E+02i=12
13 1.1200000000 E+02
| | writeln();
| r=1.0000000000E+02i=12
13 1.1200000000 E+02
| | write(i,', ',i);
| r=1.0000000000E+02i=12
13 1.1200000000 E+02
12, 12
| |
Процедуры ввода
Read( Пр1, [,Пр2,..., Прn ] ) – считывает одно или более значений из текстового файла в одну или более переменных.
Каждый параметр Пр№ является переменной символьного, строкового, целого или вещественного типа.
Процедура останавливает выполнение программы до тех пор, пока пользователь не введёт с клавиатуры требуемое количество значений и нажмёт <Enter>. Числовые значения при вводе должны разделяться пробелом (<Space>) или окончанием строки (клавиша <Enter>). При считывании строковых и символьных значений символ пробел считается частью вводимой строки, а не разделительным символом.
Readln( Пр1, [,Пр2,..., Прn] ) – данная процедура является расширением процедуры Rеаd. После выполнения процедуры Rеаd процедура Rеаdln делает пропуск всех введённых с клавиатуры символов до начала следующей строки.
Пример использования процедур ввода:
Рассмотрим по шагам выполнение следующей программы:
program Rd;
var
r:real; i,i2:integer; c: char; s:string[3];
begin
read(c,r,i,i2);
read(i);
readln(s,r);
read(i);
end.
При выполнении программы пользователь должен будет вводить определённые значения, которые будут сохраняться в соответствующие переменные (таблица 5).
Таблица 5 – Пошаговое выполнение процедур ввода
Выполняемый оператор
| Вводимое пользователем с клавиатуры
| Состояние переменных
| r
| i
| i2
| c
| s
| read(c,r,i,i2);
| 234.5 3 22<Enter>
| 34.5
|
|
| ’2’
| ’’
| 33 101<Enter>
| 34.5
|
|
| ’2’
| ’’
| read(i);
| программа не останавливается для ввода данных
| 34.5
|
|
| ’2’
| ’’
| readln(s,r);
| st2.25 2.3 13<Enter>
| 0.25
|
|
| ’2’
| ’st2’
|
Таблица 5 (окончание) – Пошаговое выполнение процедур ввода
Выполняемый оператор
| Вводимое пользователем с клавиатуры
| Состояние переменных
| read(i);
| 2.5<Enter>
| Ошибка: invalid numeric format (попытка записать вещественное число в переменную целого типа)
|
42. Структурные операторы
К их числу относятся:
· составной оператор,
· условный оператор If,
· оператор варианта Case,
· оператор цикла For – Do,
· оператор цикла While – Do,
· оператор цикла Repeat – Until,
· оператор записи With,
· оператор Try – Except – End,
· оператор Try – Finally – End,
· оператор On – Do,
· оператор Try – Finally – End.
13.1. Составной оператор
Это простая структура следующих друг за другом операторов, заключенных в операторные скобки begin … end.
Синтаксис составного оператора:
Begin
Оператор1
Оператор2
…
ОператорN
End;
Составной оператор применяется в тех случаях, когда какое-либо действие необходимо применить не к одному, а сразу к нескольким операторам.
Пример:
Begin
R:= X;
X:= Y;
Y:= R;
End;
13.2. Условный оператор If
Синтаксис допускает два вида оператора:
if логическое выражение then оператор1 else оператор2;
и его усеченный вариант:
if логическое выражение then оператор1;
Оператор работает следующим образом. Сначала вычисляется логичес-кое выражение. Если оно истинно, то выполняется оператор1, иначе – оператор2. Усеченный оператор выполняет оператор1 только в случае истинного значения логического выражения и не производит никаких действий в случае его ложности.
Примеры:
if (x < 10.7) then a[4]:= 5 else a[4]:= 6;
if (x < 10.7) then a[4]:= 5;
Допустима вложенность условных операторов внутри составного условного оператора. Например, оператору
if L1 then if L2 then St1 else St2 else St3;
эквивалентен оператор
if L1 then
begin
if L2 then St1 else St2;
end
else St3;
В этом операторе для повышения структурированности использованы операторные скобки begin … end. При конструировании сложного условного оператора во избежание логических ошибок следует отдавать предпочтение структурному способу записи такого оператора.
13.3. Оператор варианта Case
Синтаксис оператора:
Case Selector of
Const1: Оператор1;
Const2: Оператор2;
…
ConstN: ОператорN
[else Оператор];
End;
Selector может быть любой простой тип кроме Real. Каждая из Const1 … ConstN может быть значение, несколько перечисленных через запятую значений или отрезок типа. Оператор Else, как видно из описания, может отсутствовать. В том случае, если он присутствует, то действует общее правило: перед словом Else не должно быть символа ";" (точка с запятой). Поясним работу оператора Case на примере:
Case i of
0 : x := 0;
1,3 : x := 1;
10 .. 15: x := 2
else x := 3;
End;
При выполнении оператора Case управление будет передано тому оператору, который помечен константой, являющейся значением переменной i. Например, если к моменту выполнения Case-оператора i = 0, то будет выполнен оператор x := 0. Иначе, если i = 1 или i = 3, то будет выполнен оператор x := 1; иначе, если значение i в диапазоне 10 .. 15, то будет выполнен оператор x := 2; наконец, если i не равно ни одной из вышеперечисленных констант, то будет выполнен оператор x := 3, следующий за словом else (иначе).
13.4. Оператор цикла For – Do
Синтаксис оператора имеет две разновидности:
For счетчик цикла:=нач.знач. To конеч.знач. Do оператор
For счетчик цикла:=нач.знач. Downto конеч.знач. Do оператор
Здесь конструкция For .. Do называется заголовком цикла, оператор – телом цикла.
Для циклов должны соблюдаться следующие правила и ограничения:
начальное и конечное значения счетчика цикла должны быть одинаковых простых типов, кроме Real;
в теле цикла счетчик не должен менять значение;
вход в цикл минуя заголовок запрещен;
для первой разновидности начальное значение не должно быть больше конечного;
для второй разновидности начальное значение не должно быть меньше конечного.
Первая разновидность оператора цикла For работает следующим образом. Сначала счетчик цикла принимает нач.знач. и выполняется оператор, расположенный вслед за словом Do. Затем значение счетчика будет увеличено на шаг счетчика 1 и вновь будет выполнен оператор и т. д., пока счетчик не переберет все значения от нач.знач. до конеч.знач.
Пример.
s:= 0;
For i:=1 to 44 do s:= s + z[i];
В результате в переменной s будет накоплена сумма первых 44 элементов массива z.
Другая разновидность оператора For отличается лишь отрицательным шагом –1 счетчика.
Пример.
s:= 0;
For i:=44 Downto 1 do s:= s + z[i];
Будет получен тот же результат.
13.5. Оператор цикла While – Do
Синтаксис оператора:
While логическое выражение Do оператор;
Цикл выполняет оператор, расположенный вслед за словом Do до тех пор, пока истинно логическое выражение, расположенное за словом While ("выполняй, пока истинно").
Пример.
x:= 0;
i:=0;
While (x < 101.667) do
Begin
Inc (i);
X:= X + 5.617;
Y[i]:= Func (i + 6, 9 * i, X);
End;
В этом примере цикл будет выполняться до тех пор, пока не выполнится условие x < 101.667. В теле цикла переменная X с каждым шагом цикла увеличивает свое значение на 5.617 так, что на определенном шаге условие x < 101.667 впервые не будет выполнено. В этот момент без входа в тело цикл закончит работу.
13.6. Оператор цикла Repeat – Until
Синтаксис оператора:
Repeat
Оператор1;
Оператор2;
…
ОператорN;
Until логическое выражение;
Цикл работает, пока логическое выражение ложно ("повторяй, пока не выполнится").
Пример.
s:= 0;
i:=0;
Repeat
Inc (i);
s:= s + z[i];
Until (i = 44);
В этом примере цикл будет выполняться до тех пор, пока не выполнится условие i = 44. Результат будет тот же, что в примере для For-цикла.
13.7. Операторы Break и Continue
Оператор Break может быть размещен в теле цикла. При его выполнении цикл прекращает работу и считается выполненным.
Пример.
s:= 0;
i:=0;
Repeat
Inc (i);
s:= s + z[i];
if (s > 14) then Break;
Until (i = 44);
В этом примере цикл будет выполняться до тех пор, пока не выполнится условие i = 44 или если в операторе if переменная s превысит значение 14.
Оператор Continue также может быть размещен в теле цикла. При его выполнении управление независимо от того, где он расположен, сразу передается в начало цикла для выполнения следующего шага.
Пример.
s:= 0;
i:=0;
Repeat
Inc (i);
s:= s + z[i];
if (s > 20) then Continue;
if (s > 14) then Break;
Until (i = 44);
В этом примере если в первом операторе if выполнится условие s > 20, то сработает оператор Continue. Он сразу передаст управление на первый оператор в теле цикла – Inc (i), предотвратив тем самым выполнение ниже-следующих операторов – второго if и Until.
13.8. Вложенные циклы
В теле оператора цикла могут быть размещены другие операторы цикла. Такие структуры называются вложенными циклами. Язык допускает любую глубину вложенности циклов. При использовании вложенных циклов необходимо иметь в виду следующее:
все вложенные циклы For – Do должны иметь различные счетчики (иначе это противоречило бы требованию на запрет изменения значения счетчика внутри цикла);
нет никаких ограничений на досрочный выход из внутреннего цикла наружу;
недопустим вход во внутренний цикл For – Do, минуя его заголовок, что соответствует общему требованию о корректном входе в цикл.
Вложенные циклы используются в ситуациях, когда на каждом шаге наружного цикла необходимо полностью выполнить внутренний цикл.
Пример.
Const
n = 15;
m = 24;
Var
i,j: Byte;
R,Tau,s: Real;
z: array[1..n, 1..m] of Real;
…
{заполнение массива z с использованием вложенных циклов}
Tau:= Pi/m;
For i:=1 to n do begin
R:=4.0*Pi*Sin(i*Tau); {первый оператор в теле цикла по i}
For j:=1 to m do z[i, j] := R+j; {второй оператор в теле цикла по i}
end {i};
{вычисление суммы положительных элементов массива z с использованием вложенных циклов }
s:=0;
For i:=1 to n do
For j:=1 to m do
if ( z[i, j] > 0) then s:= s + z [i, j];
Приведенный пример содержит две структуры вложенных циклов. Первая структура предназначена для заполнения элементов двумерного массива z с помощью математической формулы
Наружный цикл со счетчиком i в теле цикла содержит два оператора – оператор присваивания (вычисление значения вспомогательной переменной R с целью сокращения времени вычислений) и оператор внутреннего цикла со счетчиком j. Поскольку наружный цикл в своем теле содержит несколько операторов, то они заключены в операторные скобки begin … end.
Эта структура работает следующим образом. После входа в наружный цикл переменная i (счетчик этого цикла) примет значение 1. Далее будет вычислено значение переменной R при i = 1. После этого будет выполнен внутренний цикл со счетчиком j, где j на каждом шаге будет последовательно принимать значения 1, 2, 3, … m (i при этом остается неизменным и равным 1). В результате будут вычислены элементы z11 , z12 , … ,z1m первой строки массива. Затем будет выполнен возврат к заголовку наружного цикла, где значение счетчика i будет увеличено на 1 (т. е. i станет равно 2) и вновь будет выполнены операторы, расположенные в его теле. В результате будут определены элементы z21 ,z22 , … ,z2m второй строки массива и т.д.
Вторая структура вложенных циклов предназначена для вычисления суммы положительных элементов массива z. Для этого сначала переменной s будет присвоено значение 0, а затем во вложенных циклах будет накоплена требуемая сумма в ячейку s.
13.9. Оператор записи With
В ранних версиях языка оператор использовался для более удобного доступа к полям записи.
Пример:
Var
Student : Record
Fam: String[30];
Name: String[20];
Age: Word;
End;
…
Student.Fam:= 'Колокольников';
Student.Name:= 'Павел';
S:=Student.Fam + ' '+Student.Name;
{предыдущих три оператора эквивалентны следующим}
With Student do
Begin
Fam:= 'Колокольников';
Name:= 'Павел';
S:= Fam + ' '+ Name;
End;
13.10. Оператор Try – Except – End
Это новейшее средство языка. Блок Try – Except – End используется для предотвращения исключительных ситуаций (ИС), которые могут возникнуть при выполнении программы. К их числу относятся сбои в работе аппаратуры, ошибки вычислений (например деление на нуль), попытки присвоить значение, выходящее за пределы типа и т. д.
Синтаксис:
Try
{операторы, способные генерировать ИС}
Except
{операторы, обрабатывающие генерированные ИС}
end ;
Блок Try – Except – End работает следующим образом. Выполнение начинается с операторов, расположенных в блоке Try – Except. Если в каком-либо операторе возникает ИС, то она подавляется и затем выполняются все операторы, расположенные в блоке Except – End. В результате предотвращается аварийное прерывание программы. Использование блока Try – Except – End открывает возможность программного контроля за ИС.
Пример.
i:= 0;
n:= 8;
Try
i:= n div i; {Деление на нуль. Оператор генерирует ИС}
n:= i + 9;
Except
ShowMessage('Ошибка. Деление на нуль в операторе i := n / i');
End;
Результатом выполнения блока операторов будет появление на экране формы с сообщением "Ошибка. Деление на нуль в операторе i := n / i", после чего программа продолжит работу с оператора, следующего за словом End, а не с оператора n := i + 9.
Если бы оператор i := n div i не был защищен блоком Try – Except – End, то возникшая при его выполнении ИС привела бы к нежелательному аварийному завершению программы.
13.11. Оператор On – End
При возникновении ИС язык позволяет не только предотвратить прерывание программы, но и определить, какого именно вида была ИС. Для этого в блоке Except – End можно использовать оператор On –Do.
Пример
i:= 0; n:= 8;
Try
i:= n div i; {Деление на нуль. Оператор генерирует ИС}
n:= i + 9;
Except
On Ex: EdivByZero do ShowMessage('Деление на нуль');
End;
В этом примере сообщение о возникновении ИС будет выдано только в случае, когда ИС будет только деление на нуль (EdivByZero). Во всех остальных случаях ИС будет предотвращена, однако никакого сообщения о ее возникновении выдано не будет. Объявленная в блоке Except – End переменная Ex может быть любым именем (здесь Ex используется только для примера).
13.12. Оператор Try – Finally – End
Блок Try – Finally – End также используется для предотвращения ИС, которые могут возникнуть при выполнении программы. В отличие от блока Try – Except – End блок Try – Finally – End используется для освобождения ресурсов памяти, закрытия файлов и пр. в случае возникновения ИС.
Синтаксис:
Try
{операторы, способные генерировать ИС}
Finally
{операторы освобождения ресурсов памяти }
end ;
Блок Try – Finally – End работает следующим образом. Выполнение начинается с операторов блока Try – Finally, которые в правильно написанной программе должны содержать операторы выделения ресурсов памяти. Если в каком-либо операторе возникает ИС, то управление сразу передается к операторам блока Finally – End, где производится освобождение памяти, закрытие файлов и пр. В результате, с одной стороны, предотвращается аварийное прерывание программы и, во вторых, корректно освобождается ранее зарезервированная память, выполняется ряд других необходимых операций.
Отметим, что блок Finally – End выполняется всегда вне зависимости от того, была или не была сгенерирована ИС.
Пример.
i:= 0;
n:= 8;
Try
GetMem (p, 8000); {выделение памяти}
i:= n div i; {Деление на нуль. Оператор генерирует ИС}
n:= i + 9;
Finally
FreeMem (p, 8000); {освобождение памяти}
End;
Не нашли, что искали? Воспользуйтесь поиском по сайту:
©2015 - 2024 stydopedia.ru Все материалы защищены законодательством РФ.
|