§ 5.13. Ошибки при написании подпрограмм

 

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

 

Тип ошибки

Неверное написание

Несоответствие типов формального и фактического параметров

 

Здесь фактический параметр типа real, а формальный –типа integer

Function f1(x: integer): real;

   begin

   if x>0 then f1:=1/x else f1:=0.0;

   end;

begin

   writeln(f1(0.5));

end.

Несоответствие числа формальных и фактических параметров

 

Здесь фактических параметров - два, а формальный -один

Function f1(x: integer): real;

   begin

   if x>0 then f1:=1/x else f1:=0.0;

   end;

   var a,b:real;

begin

   read(a,b);

   writeln(f1(a,b));

end.

Невозвращение значения функцией при одном из условий

 

На самом деле программа может выдать неожиданный результат в виде 1.38Е-308 - случайное значение в ячейке памяти

Function f1(x: integer): real;

   begin

   if x>0 then f1:=1/x;

   end; // при x<=0 функция непредсказуема

begin

   writeln(f1(0)); // будет ошибка

end.

Неприсваивание значения для имени подпрограммы-функции

 

Значение функции при выходе из подпрограммы равно нулю

Function f1(x: real): real;

   begin

   if x>0 then writeln(1/x) else writeln(0.0);

   end;

   var a:real;

begin

   read(a);

   writeln('** ',f1(a));

end.

Присваивание значения имени подпрограммы-процедуры

 

Компилятор сообщает об ошибке

procedure f1(x: real);

   begin

   if x>0 then f1:= 1/x else f1:=0.0;

   end;

   var a:real;

begin

   read(a);

   f1(a);

end.

Описание локальной переменной цикла, используемого в процедуре, как глобальной переменной

 

Значение переменной i в основной программе испорчено. Параметр-переменная цикла i должна быть описана в теле процедуры отдельно

var i: integer; // глобальная переменная

procedure w1(x: integer);

   begin

   for i:=1 to 10 do

   write(x);

   end;

begin

   i:=7;

   w1(5); // будет выведено 10 цифр 5

end.

Передача выходных параметров по значению

 

В вызывающую программу параметры-значения не возвращаются, т.к в процедуре меняется лишь копия переменной i, а не сама переменная i. Для корректного возвращения в основную программу нового значения i, ее необходимо описывать в заголовке процедуры как параметр-переменная через var

procedure BadInc(i: integer);

   begin

   i:=i+1; writeln(i);

   end;

var i: integer;

begin

   i:=5;

   writeln(i); // выдаст 5

   badinc(i); //выдаст 6

   writeln(i); // опять выдаст 5

end.

{ верное описание процедуры}

{ procedure BadInc(var i: integer);}

 

Можно предложить несколько полезных советом по работе с подпрограммами:

·     выделяйте в процедуру (функцию) небольшой логически завершенный фрагмент алгоритма;

·     не смешивайте в одной процедуре (функции) ввод-вывод данных и вычислительные алгоритмы;

·     называйте свои процедуры (функции) мнемоническими именами;

·    если алгоритм, который вы решили выделить в процедуру (функцию), все еще слишком сложен, оформите фрагмент этого алгоритма в другой процедуре (функции);

·     если алгоритм должен вычислить одно скалярное значение это должна быть функция, а не процедура;

·     если в вашей программе встречаются многократно вложенные циклы или "многоэтажные" условные операторы, это верный признак, что вам нужны процедуры (функции);

·      для выхода из подпрограммы используйте в процедурах и функциях процедуру Exit.