Ошибка фактический параметр должен быть переменной

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
program lalala; const      n=5; Type     mas = array[1..n,1..n] of real;     vek = array[1..n] of real; const       a:mas =( (1,2,0,0,0), (3,4,5,0,0), (0,6,7,8,0), (0,0,9,10,11), (0,0,0,12,13) );       b:vek = (6,13,19,25,31); Var    x,k,m,t,p,q:vek;    tmp,ev:real;     Procedure InitMas(Var a:mas; Var b:vek); Var i,j:integer; begin     write('b(',i,')=');     readln(b[i]);  end;     Procedure Prog(Var a:mas; Var k,m,t:vek); Var i,j:integer; Begin for i:=1 to n do     begin     if i=1 then        k[i]:=0     else         k[i]:=a[i,i-1];         m[i]:=-a[i,i];     if i=n then         t[i]:=0     else         t[i]:=a[i,i+1];     end;  end;   Procedure Vec(Var a:mas; Var q,p,k,m,x:vek); Var i,j:integer; Begin p[1]:=t[1]/m[1]; q[1]:=-b[1]/m[1]; for i:=2 to n do     begin     p[i]:=-t[i]/(k[i]*p[i-1]-m[i]);     q[i]:=(b[i]-k[i]*q[i-1])/(k[i]*p[i-1]-m[i]);     end; x[n]:=(b[n]-k[n]*q[n-1])/(k[n]*p[n-1]-m[n]); for i:=n-1 downto 1 do    x[i]:=p[i]*x[i+1]+q[i]; end;   Procedure PrintB(Var a:mas; Var x:vek); Var i,j:integer; begin for i:=1 to n do     writeln('x(',i,')=',x[i]); end;   Procedure Evklid(Var a:mas); Var i,j:integer; Var ev:real; begin ev:=0;  for i:=0 to n do         begin             for j:=0 to n do              begin              ev:=ev + sqrt(sqr(a[i,j]));              end;         end;          writeln('ev=',ev);  end;   Procedure Proverka(Var a:mas); Var i,j:integer; f1:boolean; Begin      for i:=2 to n do     Begin         for j:=0 to  i-1 do         Begin             if ((a[i,j] <> 0) or (a[j,i] <> 0)) then             Begin             f1:= false;             end;         end;     end;   if (f1) then     Begin         writeln('Matrix nn');         Prog(a,k,m,t);      end      else       Begin       writeln('Error');      end;  end;   begin      InitMas(a,b);      Prog(a,k,m,t);      Vec(a,p,q,k,b,x);      PrintB(a,x);      Evklid(a);  readln(); end.

Параметры-переменные

При
передаче параметров-переменных в
подпрограмму фактически через стек
передаются их адреса в порядке, объявленном
в заголовке подпрограммы. Следовательно,
подпрограмма имеет доступ к этим
параметрам и может их изменять.

Параметры-переменные
указываются в заголовке подпрограммы
аналогично параметру-значению, но только
перед именем параметра пишется
зарезервированное слово var.
Его действие распространяется на все
переменные, указанные до ближайшей
точки с запятой, то есть в пределах одной
группы.

Пример

procedure
maxmin(a:tArr; var max, min :real; n :word);

Тип
параметров-переменных может быть любым,
включая файловый.

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

Пример
Функция вычисления максимального
элемента в массиве.

type tarr =
array [1..100] of integer;

{фактический
параметр должен быть переменной или
типизированной
константой
типа
tarr}

function
max (var mas:tarr; n:byte):integer;

var

ma:integer;

i:byte;

begin

ma:=mas[1];

for
i:=2 to n do

if
ma<mas[i] then ma:=mas[i];

max:=ma;

end;

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

Однако,
при такой передаче параметра возможно
его нежелательное
изменение
.

Подпрограмма
по-прежнему может работать с одним типом
массивов.

Параметры-константы

Условие – параметр
передается в подпрограмму, но изменять
его подпрограмма не должна. Нежелательно
передавать параметр как

параметр-переменную.
Можно передать как параметр-значение,
но если этот параметр имеет большой
размер (массив, запись и т.д.), то копии
могут занять большую часть стека или
даже переполнить его. Это ведет к
уменьшению быстродействия программы.
В этой ситуации параметр лучше передать
как параметр-константу. Такой параметр,
если он структурного типа, передается
своим
адресом
,
но предусмотрена его защита от изменений
(версия 7.0).

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

Пример

function
NewString (const s :string) :string;

Тип
параметра-значения
может быть любым, кроме файлового.

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

Параметр-константу
нельзя передавать в другую подпрограмму
в качестве фактического параметра.

Пример
Функция вычисления максимального
элемента в массиве.

function
max(const mas: tarr;n: byte): integer;

var

ma:integer;

i:byte;

begin

ma:=mas[1];

for i:=1
to n do

if
ma<mas[i] then ma:=mas[i];

max :=ma;

end;

Пример

const

a:
integer = 5;

b:
integer = 7;

procedure
inc(var c: integer; b: integer)

begin

c:=
c+c;

b:=
b+b;

writeln(‘удвоенные
: ’,c:
5, b:
5);

end;

begin

writeln(‘исходные
: ’,a: 5, b: 5);

inc(a,b);

writeln(‘результат
: ’,a: 5,b: 5);

end.

исходные
:

5

7

удвоенные
:

10

14

результат
:

10

7

b
– параметр-значение

При
вызове вычисляется значение, полученный
результат копируется во временную
память и передается подпрограмме.

Любые
возможные изменения в подпрограмме
параметра-значения никак
не воспринимаются вызывающей программой,
т.к. в этом случае изменяется копия
фактического параметра.

а
– параметр-переменная

При
вызове подпрограмме передается сама
переменная (адрес переменной). Изменение
параметра-переменной приводит к изменению
фактического параметра в вызывающей
программе.

В
случае параметра-константы
в подпрограмму также передается адрес
области памяти, в которой располагается
переменная или вычисленное значение.
Компилятор блокирует любые присваивания
параметру-константе нового значения в
теле подпрограммы.

Пример
может служить иллюстрацией механизма
«закрывания» глобальной переменной
одноименной локальной: хотя b
объявлена как глобальная, в теле процедуры
её «закрывает» локальная, объявленная
как параметр-значение.

Параметры-переменные используются как
средство связи с внешним миром: с помощью
этих параметров подпрограмма может
передавать своей работы вызывающей
программе.

Всегда возможна
передача результатов и через глобальные
переменные.

Оценка
вариантов передачи результатов работы
подпрограммы вызывающей программе

  • злоупотребление
    глобальными связями делает программу
    запутанной, трудной в понимании и
    сложной в отладке;

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

  • с
    другой стороны, описание всех формальных
    параметров, как параметров-переменных
    нежелательно по двум причинам: во-первых,
    это исключает возможность вызова
    подпрограммы с фактическими параметрами
    в виде выражений,
    что делает программу менее компактной,
    во-вторых, в подпрограмме возможно
    случайное использование формального
    параметра.

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

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

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]

  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #

На занятии будет объяснен алгоритм работы с процедурами на Паскале. Будут разобраны примеры использования процедуры с параметрами и без параметров. Познакомитесь с понятиями: формальные и фактические параметры, параметр по значению и параметр по ссылкее

Содержание:

  • Процедуры в Паскале
    • Процедуры с параметрами. Фактические и формальные параметры
    • Процедуры с параметрами. Параметр по ссылке (передача параметра по ссылке)
    • Передача аргументов по значению и по ссылке
    • Самостоятельная работа

Процедуры в Паскале

Подпрограмма — это фрагмент кода, который имеет свое имя и создается в случае необходимости выполнять этот код несколько (много) раз. Подпрограмма описывается единожды перед началом основной программы (до begin). Компилятор пропускает данный фрагмент кода, пока в основной программе не встретит «вызов» подпрограммы, который выглядит как обращение к ней по имени (возможно, имени с аргументами, указанными в скобках).

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

Итак, рассмотрим синтаксис объявления и описания процедуры в Паскале

var;{область объявления глобальных переменных}   procedure название (параметры); {начало процедуры} var;{объявление локальных переменных} begin{тело процедуры} end;{конец процедуры}   begin{основная программа} end.

Пример: Процедура без параметров, которая печатает 60 звездочек, каждую с новой строки

1 2 3 4 5 6 7 8 9 10 11 
procedure pr; var i:integer; begin for i:=1 to 60 do begin {тело подпрограммы} write('*'); writeln; end; end; {конец подпрограммы} begin pr; {вызов процедуры} end.

В данном примере работы с процедурой в Паскале очевидно, что компилятор пропустит блок описания процедуры и дойдет до основной программы (9 строка кода). И только после того, как встретится вызов процедуры (10 строка), компилятор перейдет к ее выполнению, вернувшись к строке 1.

Процедуры с параметрами. Фактические и формальные параметры

Рассмотрим пример необходимости использования процедуры.

Пример:
Построить фигуру
построение треугольников в процедуре

Особенность: Три похожие фигуры.

  • общее: размеры, угол поворота
  • отличия: координаты, цвет
  • Алгоритм решения:

    • выделить одинаковые или похожие действия (три фигуры);
    • найти в них общее (размеры, форма, угол поворота) и отличия (координаты, цвет);
    • отличия записать в виде неизвестных переменных, они будут параметрами процедуры.

    1_1

    Решение на паскале:
    Процедура:
    пример процедуры в Паскале

    Программа:
    1_1

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 
    uses GraphABC; procedure Tr( x, y: integer; color:system.Drawing.Color); begin MoveTo(x, y); LineTo(x, y-60); LineTo(x+100, y); LineTo(x, y); FloodFill(x+20, y-20,color); end; begin SetPenColor(clBlack); Tr(100, 100, clBlue); Tr(200, 100, clGreen); Tr(200, 160, clRed); end.

    Рассмотрим синтаксис объявления и описания процедуры с параметрами в Паскале.

    var;{область объявления глобальных переменных}   procedure pr(параметр1, параметр2: integer; параметр3:char); {начало процедуры} var;{объявление локальных переменных} begin{тело процедуры} end;{конец процедуры}   begin{основная программа} pr (параметр1, параметр2, параметр3); {вызов процедуры} end.

    Задание procedure 1: Написать процедуру рисования N вертикальных линий. N задается параметром процедуры.

    Задание procedure 2: Написать процедуру рисования N окружностей, сдвинутых по горизонтали. N, радиус R и отступ O задаются параметрами процедуры (всего 3 параметра).

    Пример: Написать процедуру, которая печатает 60 раз указанный символ (введенный с клавиатуры), каждый с новой строки

    Параметры процедуры (в некоторых языках они называются аргументами) указываются в скобках после ее имени (в объявлении).

    В данном примере в качестве введенного символа будем использовать параметр процедуры. Формальный параметр процедуры указывается в скобках при ее описании. Обязательно необходимо указать тип формального параметра через двоеточие.

    Фактический параметр — это то значение, которое указывается в скобках при вызове процедуры. Фактическим параметром может быть конкретное значение (литерал: число, символ, строка…) либо переменная, которые компилятор подставит вместо формального параметра. Поэтому тип данных у формального и фактического параметра процедуры должен быть одинаковым.

    Pascal PascalABC.NET
    1 2 3 4 5 6 7 8 9 10 11 12 13 14 
    var s:char; procedure pr(a:char); {a - формальный параметр} var i:integer; begin for i:=1 to 60 do begin write(a); writeln; end; end; begin writeln('введите символ'); readln(s); pr(s); {s - фактический параметр} end.
    1 2 3 4 5 6 7 8 9 10 11 
    procedure pr(a:char); {a - формальный параметр} begin loop 60 do begin println(a); end; end; begin writeln('введите символ:'); var s:= readchar; pr(s); {s - фактический параметр} end.

    В данном примере при вызове процедуры компилятор заменит формальный параметр a фактическим параметром s, т.е. тем символом, который будет введен с клавиатуры. Оба параметра имеют тип данных char.

    • число фактических параметров должно быть равно числу формальных параметров;
    • соответствующие фактические и формальные параметры должны совпадать по порядку следования и по типу данных.

    Задача procedure 3. Написать процедуру, которая складывает два любых числа (два параметра).

    Процедуры с параметрами. Параметр по ссылке
    (передача параметра по ссылке)

    Пример: Программа поиска максимума из двух целых чисел при помощи процедуры

    1. способ:
    2. Pascal PascalABC.NET
      1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 
      var x,y,m,n:integer; {a и b - параметры по значению, max - параметр по ссылке} procedure MaxNumber(a,b:integer;var max:integer); begin if a>b then max:=a else max:=b; end; begin write('vvedite x,y'); readln(x,y); MaxNumber(x,y,m); {фактические параметры} writeln('max=',m) end.
      1 2 3 4 5 6 7 8 9 10 11 
      {a и b - параметры по значению, max - параметр по ссылке} procedure MaxNumber(a,b:integer;var maximum:integer); begin maximum:=max(a,b); end; begin var (x,y):=readInteger2('введите x,y'); var m:integer; MaxNumber(x,y,m); {фактические параметры} writeln('max=',m) end.

      В примере параметры a и b служат для хранения в них сравниваемых чисел, а параметр по ссылке max — для сохранения в ней максимального из двух чисел. Параметр по значению — параметр, принимаемый по значению, или выходной параметр передает свое значение в основную программу (фактическому параметру m), т.е. возвращает значение. Тогда как параметры по ссылке — параметры, принимаемые по ссылке, (входные параметры), наоборот, принимают значения из основной программы (из фактических параметров x и y). Для параметра по ссылке (max) используются те ячейки памяти, которые отведены под соответствующий параметр при вызове процедуры (ячейка m), именно поэтому такой параметр называется параметром, передаваемым по ссылке.

      Таким образом, сформулируем понятия:

      Если в качестве формального параметра указана обычная переменная с указанием ее типа, то такой параметр есть параметр, передаваемый по значению, или входной параметр (a и b в примере). Тип данных формального параметра-значения должен соответствовать типу данных его фактического параметра (a и b должны попарно соответствовать типу данных x и y).

      Если перед именем формального параметра в объявлении процедуры стоит служебное слово var, то такой параметр называется параметром, передаваемым по ссылке, или выходным параметром (max в примере). Для него используются те ячейки памяти, которые отведены под соответствующий параметр при вызове процедуры (m). А передача такого параметра называется передачей по ссылке (ссылка на ту же ячейку в памяти). Фактический параметр, соответствующий параметру-переменной, может быть только переменной (не константой, не литералом и не выражением).

    3. способ:
    4. Использование параметров-переменных позволяет тратить меньше памяти

      Pascal PascalABC.NET
      1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 
      var x,y:integer; {b - параметр по ссылке или выходной параметр} procedure exchange(a: integer;var b:integer); var c:integer; begin if a>b then begin c:=a; a:=b; b:=c; {второй параметр процедуры - b - всегда будет максимальным} end; end; begin writeln('введите два числа'); readln(x,y); exchange (x,y); writeln('max=',y) end.
      1 2 3 4 5 6 7 8 9 10 11 
      {b - параметр по сслыке или выходной параметр} procedure exchange(a: integer;var b:integer); begin b:=max(a,b); end; begin var (x,y):=readInteger2('введите x,y'); var m:integer; exchange (x,y); writeln('max=',y) end.

      Используя данный способ решения задачи, мы обошлись без третьего параметра. Для этого в процедуре мы использовали еще одну локальную переменную c. Процедура меняет значения переменных a и b таким образом, чтобы b всегда была максимальной. Поэтому в 15 строке программы в качестве максимальной выводится второй параметр (y), соответствующий формальному параметру b.

    Задача procedure 4.

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

    Поиск наибольшего общего делителя на паскале
    Словесный алгоритм:

    • Вводятся a и b (например, 18 и 24)
    • В цикле повторяем действия:
    • Если а < b, то меняем переменные местами (1 шаг: a=24, b=18; 2 шаг: a=18, b=6)
    • Переменной a присваиваем остаток от деления a на b (1 шаг: a=6, b=18; 2 шаг: a=0, b=6)
    • Когда остаток равен 0, выводится результат (значения переменной b) (b=6)

    Алгоритм решения поиска НОД:

    числа a  и  b  остаток  результат
    1 a=18, b=24
    24>18
    если b>a → swap(a,b)
    a=24, b=18
    24/18  = 1(6) a=6, b=18
    2 a=6, b=18
    18>6
    если b>a → swap(a,b)
    a=18, b=6
    18/6 =3(0) a=0, b=6
    6
    128  и  56
    1 a=128,b=56
    a>b
    нет
    a=128,b=56
    128/56=2(16) a=16,b=56
    2 a=16,b=56
    b>a
    если b>a → swap(a,b)
    a=56, b=16
    56/16=3(8) a=8,b=16
    3 a=8,b=16
    b>a
    если b>a → swap(a,b)
    a=16,b=8
    16/8=2(0) a=0, b=8
    8

    Задача procedure 5. Используя процедуры, построить фигуру:

    1_1

    Задача procedure 6. Даны 3 различных массива целых чисел (размер каждого 15 элементов). В каждом массиве найти сумму элементов и среднее арифметическое значение.
    Для формирования элементов массива и подсчета суммы и среднего арифметического использовать одну процедуру (среднее арифметическое и сумму оформить как параметры-переменные).

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

    Пример: Создать процедуру для вывода десяти элементов массива (два параметра: количество элементов, массив)

    Показать решение:

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 
    const n = 10; var i:integer; a, b: array[1..n] of integer; procedure arr_out (k:integer; arr: array[1..n] of integer); var i: byte; begin write ('вывод массива: '); for i := 1 to k do write (arr[i]:4); writeln; end; begin for i:=1 to n do a[i]:=random(10); arr_out (n, a); end.

    Пояснение:
    Тело основной программы:
    — формирование элементов массива (с функцией random).
    — вызов процедуры с двумя параметрами: количество элементов, массив.
    Тело процедуры:
    — вывод элементов массива с использованием параметров

    Продолжим нашу задачу:

    Пример: Создать процедуру для заполнения массива с использованием функции random

    Показать решение:

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 
    const n = 10; var a, b: array[1..n] of integer; procedure arr_rand (k:integer; var arr: array[1..n] of integer); var i: byte; begin write ('Заполнение массива случайными числами '); randomize; for i := 1 to k do arr[i]:=random(100); end; begin arr_rand (n, a); end.

    Задача procedure 7. Объедините обе решенные задачи (для заполнения и вывода массива).

    Задача procedure 8. Добавьте в задачу процедуру для заполнения значений массива пользователем (ввод значений с клавиатуры). Оформите вывод двух разных массивов: один — со значениями, сформированными случайным образом, другой — со значениями, введенными пользователем.

    Задача procedure 9. Составить программу с процедурой для вычисления степени числа (входные параметры: число и степень). Для вывода результата использовать параметр по ссылке.

    Задача procedure 10. Составить программу на Паскале с процедурой для вычисления факториала числа.   (0!=1, 1!=1, 2!=2,  3!=6 …)

    Передача аргументов по значению и по ссылке

      Рассмотрим более подробно два этих понятия:

    • Передача по значению: Значение фактического параметра копируется в соответствующий формальный параметр. Изменение формального параметра не ведет к изменению фактического параметра
    • 1 2 3 4 5 6 7 8 9 10 
      procedure p(a: integer); begin a := 666; // изменяется только формальный параметр! end;   begin var x := 555; p(x); Print(x); // 555 end.
    • Передача по ссылке: Оба параметра и формальный и фактический ссылаются на одно и то же расположение в памяти, поэтому все изменения в теле процедуры отражаются и на фактическом параметре.
    • Изменение формального параметра изменяет и фактический параметр тоже:
    • 1 2 3 4 5 6 7 8 9 10 
      procedure p(var a: integer); begin a := 666; end;   begin var x := 555; p(x); Print(x); // 666 – фактический параметр изменился тоже! end.

    Короткая запись

    Если тело процедуры состоит только из одного оператора, PascalABC.NET позволяет использовать при описании сокращенный синтаксис, без ключевых слов begin и end:

    1 2 3 4 5 6 
    ## procedure SqrtX(x: real) := print(sqrt(x)); // основная программа begin SqrtX(9); //3 end;

    Самостоятельная работа

    Общее задание 1: Написать процедуру рисования N прямоугольников сдвинутых по горизонтали. N, координаты точек x1, y1, x2, y2 и отступ O задаются параметрами процедуры (всего 6 параметров).

    Общее задание 2: Описать процедуру Mean(X, Y, AMean, GMean), вычисляющую:

    • среднее арифметическое AMean = (X+Y)/2
    • и среднее геометрическое GMean = √X*Y двух положительных вещественных чисел X и Y.

    X и Y — входные параметры, AMean и GMean — выходные параметры вещественного типа.
    В основной программе: Для заданных A, B, C, D найти среднее арифметическое и среднее геометрическое для пар (A, B), (A, C), (A, D), используя созданную процедуру.

    1 вариант: для 5 одномерных массивов определять произведение элементов каждого массива, используя процедуру с двумя параметрами — число элементов массива и параметр по ссылке — для вывода произведения.

    2 вариант: для 5 одномерных массивов определять минимальный элемент каждого массива, используя процедуру с двумя параметрами — число элементов массива и параметр по ссылке — для вывода минимального элемента.

    * сложное С помощью процедуры формировать случайным образом одномерные массивы из 10 элементов (значения от -20 до +20). Вызывать процедуру до тех пор, пока среди значений не появится ноль.

    Внутренние переменные

    Внутренние переменные
    доступны и используются внутри процедур.

    Внутренние
    переменные получившие инициализацию
    являются статическими,
    т.е. память выделяется на этапе компиляции
    (неявно обладают атрибутом static).

    Атрибут automatic устанавливает
    переменные автоматическими,
    т.е. память выделяется во время работы программы.

    program static_var call sub() ! M = 1 call sub() ! M = 2 call sub() ! M = 3 end subroutine sub() integer :: M = 0 M = M + 1 write(*,*) M end subroutine sub 
    program static_var call sub() ! M = 1 call sub() ! M = 1 call sub() ! M = 1 end subroutine sub() integer , automatic :: M M = 0 M = M + 1 write(*,*) M end subroutine sub 

    Передача параметров

    Формальные параметры

    1. входные, intent(in)
    2. выходные, intent(out)
    3. входные/выходные, intent(inout)
    subroutine sub(a,b,c) integer, intent(in) :: a real, intent(out) :: b character, intent(inout) :: c ... end subroutine sub 

    По умолчанию все параметры имеют атрибут inout, т.к. передаются по ссылке.

    Вид связи intent(in)

    Принимают значение от
    соответствующего фактического параметра
    и не могут изменяться при выполнении процедуры.

    Соответствующими
    фактическими параметрами могут быть
    выражения, переменные, значения, константы.

    program param_in call sub(100) end subroutine sub(a) integer, intent(in) :: a ! входной параметр ... end subroutine sub 

    Вид связи intent(out)

    Параметры передают свое значение
    соответствующему фактическому параметру и предназначены для вывода данных из процедуры.

    Соответствующий фактический параметр
    должен быть переменной.

    program param_out call sub(100) ! ошибка, ожидалась переменная end subroutine sub(a) integer, intent(out) :: a ! выходной параметр ... end subroutine sub 

    Вид связи intent(inout)

    Параметры могут как принимать
    значения от фактического параметра,
    так и передавать данные в фактический параметр.

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

    program param_inout integer :: q = 80 call sub(q) end subroutine sub(a) integer, intent(inout) :: a ! входной/выходной ... ! параметр end subroutine sub 

    Optional параметры

    Атрибут optional устанавливает
    формальные параметры необязательными.

    Функция present проверяет присутствие необязательного параметра при вызове процедуры.

    При отсутствии проверки функцией present возможны ошибки выполнения для параметров с
    видом связи intent(out, inout).

    Процедура должна иметь явный интерфейс.

    Optional параметры

    program param_in real res res = logarithm(144.0,base = 12.0) write(*,*) res CONTAINS real function logarithm(a, base) real, intent(in) :: a real, intent(in), optional :: base if (present(base)) then logarithm = log(a)/log(base) else logarithm = log10(a) end if end function logarithm END 

    Область видимости

    Объекты1Объекты – переменные, типы данных, внутренние процедуры
    (для головной программы или внешней процедуры)
    описанные в головной программе доступны во внутренних процедурах, недоступны во внешних.

    Объекты описанные во внутренней, внешней процедурах доступны только в них самих.

    При совпадении имен объектов головной программы и внутренней или внешней процедур,
    объекты являются разными.

    program array integer, parameter :: M = 10 integer :: A(M) = [2,4,6,8,9,1,1,1,1,1] call PrintArray() contains subroutine PrintArray() ! нет формальных параметров integer k ! доступ к массиву A do k = 1,M ! из головной программы write(*,"(i6,)") A(k) end do write(*,*) end subroutine PrintArray END 

    Оператор interface

    Почему при компиляции выдаётся ошибка?

    program question write(*,*) middle(3.0,2.0) END real function middle(a,b) real a,b middle = (a+b)/2 end function middle 

    По умолчанию тип функции middleцелый.
    Функция объявлена как вещественная,
    но головная программа об этом «не знает».

    Как указать головной программе
    про тип функции middle?

    Определяет явно заданный интерфейс.

    Используется для внешних процедур.

    Внутренние процедуры обладают явно заданным интерфейсом.

    interface тип имя_функции(формальные параметры) тип формальных параметров конец описания функции end interface 

    Исправленная версия программы

    program question interface real function middle(a,b) real a,b end function middle end interface write(*,*) middle(3.0,2.0) END real function middle(a,b) real a,b middle = (a+b)/2 end function middle 

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

    Подпрограммы делятся на встроенные и пользовательские. Встроенные подпрограммы входят в состав API DataExpress, пользовательские определяются разработчиком в скрипте. Синтаксис определения процедуры и функции:

    // Определение процедуры
    procedure MyProc([список параметров]);
    beginend;
    // Определение функции
    function MyFunc([список параметров]): [тип данных];
    beginend;

    Верхняя строка процедуры называется заголовком процедуры и состоит из служебного слова procedure, названия функции, списка параметров и точки с запятой. Следом идут операторные скобки begin-end, называемые телом процедуры. После end обязательно ставится точка с запятой. Процедура может не иметь параметров, в этом случае ставить скобки необязательно.

    Заголовок функции отличается тем, что вместо слова procedure пишется function, а после списка параметров или имени (если нет параметров) идет двоеточие и тип результата, который возвращает функция.
    Вызов встроенной или пользовательской подпрограммы имеет следующий синтаксис:

    Proc([список параметров]);
    MyFunc([список параметров]);
    x := a + MyFunc([список параметров]) – b …
    y := MyFunc2 + 1000 - b;

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

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

    procedure MyProc(Param1: Integer);
    var
    i, j: Integer;
    begin
    i := 1;end;

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

    Параметры процедур и функций

    Синтаксис описания параметров разберем на примере:

    function MyFunc(x, y: Integer; a: Double; const S, Str: String; var R: String): Boolean;

    Параметры в заголовке подпрограммы называются формальными параметрами. Параметры, передаваемые при вызове подпрограммы, называются фактическими.

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

    Параметры, передаваемые в подпрограмму, делятся на:

    • Параметры-значения. В примере это параметры x, y, a. В качестве фактических параметров могут передаваться константы, произвольные выражения, переменные. Результат вычисления параметра копируется в стек подпрограммы. Если в качестве параметра передается переменная, то изменения производятся над ее копией, а не оригиналом.

    • Параметры-переменные. В примере это параметр R. Перед параметрами указывается служебное слово var. В качестве параметра может передаваться только переменная. Тип фактического параметра должен строго соответствовать типу формального параметра. В процедуру или функцию передается ссылка на переменную. Все изменения производятся непосредственно над переменной.

    • Параметры-константы. В примере это параметры S, Str. Перед параметрами указывается служебное слово const. Параметры-константы похожи на параметры-значения, только в подпрограмму передается ссылка на адрес в памяти, где располагается результат вычисления параметра. Компилятор не позволяет изменять в подпрограмме параметр-константу. Таким образом, не тратится время на копирование параметра в стек подпрограммы, как в случае с параметром-значением.

    Пример вызова функции:

    var a: Word; MyStr, MyResult: String; b: Boolean; begin b := MyFunc(1, a, AnyFunc(20) + 30 / 0.5, MyStr, ‘Hello, World’, MyResult); end;

    В случае с параметрами-значениями и параметрами-константами тип формального и фактического параметра может быть совместимым. Если формальный определен как целое число, то фактический параметр может быть любого целого типа. Только нужно следить, чтобы формальный параметр мог «вместить» фактический параметр. В данном примере тип формального параметра Y «вмещает» переменную a, т. к. область допустимых значений больше. Целый формальный параметр несовместим с другими типами, в том числе с вещественными. А вот вещественный формальный параметр, совместим с целыми и вещественными.

    В случае с параметрами-переменными требуется строгое соответствие типов, даже если формальный и фактический параметры являются родственными, например целыми. Т. е. если формальный параметр имеет тип Integer, то фактический параметр тоже должен иметь тип Integer, а не Byte, Word и т. д. Это касается и классов, даже если фактический параметр является потомком класса формального параметра.

    Передача массивов в качестве параметров

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

    type TMyArr = array [1..20] of Integer; TMyArr2d = array [1..10] of array [1..5] of Byte; TDynaArr = array of String;   procedure MyProc(Arr: TMyArr; var Arr2d: TMyArr2d; DynaArr: TDynaArr); beginend;   procedure AnyProc; var A: TMyArr; A2d: TMyArr2d; DArr: TDynaArr; begin … MyProc(A, A2d, DArr); end;

    Фактический параметр должен быть переменной массива.

    Компилятор не сообщит об ошибке, если объявить параметр-массив таким образом:

    procedure MyProc(arr: array [1..10] of String); begin end;   procedure AnyProc; var A: array [1..10] of String; begin MyProc(a); // type mismatch end;

    Однако во время выполнения вы получите ошибку «type mismatch».

    В Паскале есть так называемые открытые массивы. Синтаксис формального параметра открытого массива следующий:

    procedure MyProc(OpenArr: array of [тип]);

    Открытый массив представляет собой одномерный массив. Нижняя граница массива всегда равна 0, даже если нижняя граница передаваемого массива отличается. Соответственно, верхняя граница равна длине массива минус 1. Для определения границ массива можно воспользоваться функциями Low и High. Пример:

    procedure MyProc(Arr: array of Integer); begin // Low(открытый массив) = 0 for i := Low(Arr) to High(Arr) doend;   procedure AnyProc; var arr: array [1..10] of Integer; arr2: array [-2..5] of Integer; begin MyProc(arr); MyProc(arr2); MyProc([1,4,8,9,11,34,23]); end;

    Как видно из примера фактическим параметром может быть не только переменная, но и конструктор массива, который представляет собой перечисление элементов через запятую, заключенных в квадратные скобки.

    В движке не поддерживаются вариантные открытые массивы, хотя некоторые встроенные подпрограммы имеют параметры такого типа (например, Format).

    procedure Proc(arr: array of const); // не поддерживается

    Возврат значения функции

    Функция имеет предопределенную переменную Result, в которую сохраняется возвращаемое значение. Пример:

    function SumAB(A, B: Double): Double; begin Result := A + B; end;

    Выход из подпрограммы

    В любой момент можно выйти из подпрограммы. Для этого предусмотрен оператор Exit.

    В движке не поддерживается передача в EXIT возвращаемого значения.

    Exit(-1); // Компилятор сообщит “internal error(20)”

    Хранимая подпрограмма

    Прикладная подпрограмма

    Хранится

    В базе данных

    В приложении

    Выполняется

    Из любого приложения или инструментального средства базы
    данных

    Только из данного приложения

    Подпрограмма может содержать до
    четырех секций:

    § 
    Обязательная секция заголовка – определяет имя, тип и аргументы
    подпрограммы

    §  Декларативная
    необязательная секция – содержит объявление локальных переменных, констант,
    курсоров, пользовательских исключений

    §  Обязательная секция
    выполняемого кода – содержит команды SQL для
    манипулирования данными в базе и команды PL/SQL для манипулирования данными в блоке

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

    Любое инструментальное средство Oracle
    позволяет создавать как хранимые, так и не хранимые программные единицы. Если
    Вы хотите создать не хранимую подпрограмму, действующую в пределах блока PL/SQL, в SQL*Plus, опишите ее в декларативной секции анонимного блока, в
    котором Вы будете ее использовать.

    Процедура PL/SQL

    Чтобы сохранить набор действий для последующего выполнения,
    можно создать процедуру PL/SQL.
    Процедура может иметь входные параметры, которые указываются при вызове
    процедуры.

    Процедура состоит из двух частей:

    · 
    спецификации, которая начинается ключевым словом PROCEDURE и заканчивается именем процедуры или списком
    параметров

    · 
    тела, которое начинается ключевым словом IS
    и заканчивается оператором END процедуры.

    PROCEDURE имя_процедуры

       [(имя_параметра [IN|OUT|IN OUT] тип_данных [:=|DEFAULT выражение], …) ]

    IS

       [список_переменных;]

    BEGIN

       тело_блока;

    END;

    имя_процедуры – имя процедуры, в соответствии со стандартными
    правилами присвоения имен

    имя_параметра – имя входного параметра процедуры

    тип_данных – тип данных параметра, указывается без размера

    выражение
    – начальное значение параметра

    список_переменных
    – определения локальных переменных, используемых в процедуре

    тело_блока – набор действий, выполняемых процедурой

    Процедура вызывается как целая команда PL/SQL, аргументы указываются в скобках в том же порядке, в
    котором были объявлены формальные параметры.

    SQL> DECLARE

      2     PROCEDURE emp_sal (v_job
    IN VARCHAR2)

      3     IS

      4        v_error_code NUMBER;

      5        v_error_text
    VARCHAR2(100);

      6        v_sal emp.sal%TYPE;

      7     BEGIN

      8        SELECT sal INTO v_sal
    FROM emp WHERE LOWER(job)=LOWER(v_job);

      9        DBMS_OUTPUT.put_line(‘Salary
    of ‘ || v_job || ‘ is ‘ || TO_CHAR(v_sal));

     10     EXCEPTION

     11        WHEN OTHERS THEN

     12           v_error_code :=
    SQLCODE;

     13           v_error_text :=
    SQLERRM;

     14          
    DBMS_OUTPUT.put_line(TO_CHAR(v_error_code) || ‘ — ‘ || v_error_text);

     15     END emp_sal;

     16  BEGIN

     17     emp_sal(‘President’);

     18     emp_sal(‘Engineer’);

     19     emp_sal(‘Clerk’);

     20  END;

     21  /

    Salary of President is 5000

    100 — ORA-01403: no data found

    -1422 —
    ORA-01422: exact fetch returns more than requested number of rows

    PL/SQL
    procedure successfully completed.

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

    Виды параметров:

    IN

    входной

    OUT

    выходной

    IN OUT

    входной/выходной

    Аргумент по умолчанию

    Должен быть задан

    Должен быть задан

    Передает значение из вызывающей среды в подпрограмму

    Возвращает значение из подпрограммы в вызывающую среду

    Передает значение из вызывающей среды в подпрограмму и
    возвращает значение из подпрограммы в вызывающую среду

    Формальный параметр выступает в качестве константы, изменить
    ее значение нельзя

    Формальный параметр выступает в качестве
    неинициализированной переменной

    Формальный параметр выступает в качестве инициализированной
    переменной

    Фактический параметр может быть выражением, константой,
    литералом или инициализированной переменной

    Фактический параметр должен быть переменной, он не может
    быть константой или выражением

    Фактический параметр должен быть переменной, он не может
    быть константой или выражением

    Функция PL/SQL

    Функции PL/SQL
    используются для возврата значений в вызывающую среду. Тип возвращаемого
    значения объявляется в секции заголовка функции с помощью ключевого слова RETURN. Само возвращаемое значение определяется в исполняемой
    секции блока (т.е. необходимо описать локальную переменную соответствующего
    типа для возвращаемого значения) и передается в вызывающую среду командой RETURN, которых может быть несколько в блоке. По крайней
    мере, одна команда RETURN в блоке должна быть.

    Функция состоит из двух частей:

    · 
    спецификации, которая начинается ключевым словом FUNCTION и заканчивается ключевым словом RETURN

    · 
    тела, которое начинается ключевым словом IS
    и заканчивается оператором END функции.

    FUNCTION имя_функции

       [(имя_параметра [IN|OUT|INOUT] тип_данных_параметра [:=|DEFAULT выражение], …) ]

    RETURN тип_данных

    IS

       [список_переменных;]

    BEGIN

       тело_блока;

    END;

    имя_функции
    – имя функции, в соответствии со стандартными правилами присвоения имен

    имя_параметра
    – имя входного параметра процедуры

    тип_данных_параметра
    – тип данных параметра, указывается без размера

    тип_данных
    – тип данных возвращаемого значения, указывается без размера

    выражение
    – начальное значение параметра

    список_переменных
    – определения локальных переменных, используемых в процедуре

    тело_блока – набор действий, выполняемых процедурой

    Функция вызывается как часть предложения PL/SQL.

    SQL> DECLARE

      2     v_sal emp.sal%TYPE;

      3     FUNCTION emp_sal (v_job IN
    VARCHAR2)

      4     RETURN NUMBER

      5     IS

      6        v_error_code NUMBER;

      7        v_error_text
    VARCHAR2(100);

      8        v_sal_inner
    emp.sal%TYPE;

      9     BEGIN

     10        SELECT sal INTO
    v_sal_inner FROM emp WHERE LOWER(job)=LOWER(v_job);

     11        RETURN v_sal_inner;

     12     END emp_sal;

     13  BEGIN

     14    
    DBMS_OUTPUT.put_line(‘Salary of President is ‘ ||
    TO_CHAR(emp_sal(‘President’)));

     15  END;

     16  /

    Salary of
    President is 5000

    PL/SQL
    procedure successfully completed.

    Сравнение процедур и функций

    Процедура

    Функция

    Вызывается
    в качестве целой команды PL/SQL

    Вызывается
    как часть выражения

    Может, но
    не обязана возвращать значение в вызывающую среду

    Обязана
    возвращать значение в вызывающую среду

    Не могут
    быть вызваны из предложений SQL

    Могут быть
    вызваны из предложений SQL

    Литература

    1.  Вильям
    Дж. Пэйдж Использование Oracle8/8i:
    пер. с англ. – М.: Издательский дом «Вильямс», 1999.

    Предыдущий раздел:

    Следующий раздел:

    11.4. Параметры-значения и параметры-переменные

    Существует два способа описывать параметры: как параметры-значения и как параметры-переменные. В предыдущем разделе использовались параметры-значения. Параметр-значение является просто локальной переменной, начальное значение которой задается при вызове процедуры.

    Пример:

      var a, b: integer; {Глобальные переменные} procedure P3(a, b: integer); {Внутри процедуры символами a и b обозначаются формальные параметры. Действия с ними никак не повлияют на значения глобальных переменных a и b} begin a:=a+1; b:=b+1; writeln(a+b); end; begin a:=1; b:=1; P3(a, b);{Вызов процедуры, где в качестве фактических параметров использованы значения глобальных переменных a и b} writeln(a, b); end. 

    Если в заголовке процедуры перед какими-либо из параметров поставить слово var, то это будут параметры-переменные. Например:

      procedure P3(var a, b: integer; c: real); 

    Здесь a и b – параметры-переменные, c – параметр-значение. При вызове процедуры фактический параметр, задающий значения этих формальных параметров не может быть выражением или константой, а должен быть обязательно переменной. То есть, недопустимы следующие вызовы:

        P3(x+y, y+1, z+2);
        P3(x, 2, z);

    где x, y, z – глобальные переменные. Такие инструкции вызовут синтаксическую ошибку. В то же время синтаксически правильными будут вызовы:

        P3(x, y, z+1);
        P3(x, y, 2);

    При использовании параметров-значений во время вызова процедуры происходит присваивание значения формальному параметру, то есть значение записывается в выделенные под хранение параметра ячейки памяти. При использовании параметров-переменных память под них не выделяется. Вместо этого на время работы процедуры они становятся синонимами тех переменных, которые указываются в качестве фактических параметров. Так при вызове P3(x, y, 2) формальные параметры a и b будут работать с теми же ячейками памяти, что и переменные x, y. Соответственно, если формальному параметру в процедуре присваивается новое значение, то и значение фактического параметра изменится. Воспроизведем пример, заменив тип параметров (добавим var перед их описанием):

      var a, b: integer; {Глобальные переменные} procedure P3(var a, b: integer); {Внутри процедуры символами a и b обозначаются формальные параметры. Теперь это параметры-переменные и действия с ними повлияют на значения глобальных переменных a и b} begin a:=a+1; b:=b+1; writeln(a+b); end; begin a:=1; b:=1; P3(a, b);{Вызов процедуры, где в качестве фактических параметров использованы глобальные переменные a и b. После вызова глобальные переменные увеличатся на 1} writeln(a, b); end. 

    Если без слова var программа выводила числа 4, 1, 1, то после его добавления получится 4, 2, 2.

    Следующий раздел:

    Предыдущий раздел:

    Добавить комментарий

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    
    program lalala;
    const
         n=5;
    Type
        mas = array[1..n,1..n] of real;
        vek = array[1..n] of real;
    const
          a:mas =( (1,2,0,0,0), (3,4,5,0,0), (0,6,7,8,0), (0,0,9,10,11), (0,0,0,12,13) );
          b:vek = (6,13,19,25,31);
    Var
       x,k,m,t,p,q:vek;
       tmp,ev:real;
     
     
    Procedure InitMas(Var a:mas; Var b:vek);
    Var i,j:integer;
    begin
        write('b(',i,')=');
        readln(b[i]);
     end;
     
     
    Procedure Prog(Var a:mas; Var k,m,t:vek);
    Var i,j:integer;
    Begin
    for i:=1 to n do
        begin
        if i=1 then
           k[i]:=0
        else
            k[i]:=a[i,i-1];
            m[i]:=-a[i,i];
        if i=n then
            t[i]:=0
        else
            t[i]:=a[i,i+1];
        end;
     end;
     
    Procedure Vec(Var a:mas; Var q,p,k,m,x:vek);
    Var i,j:integer;
    Begin
    p[1]:=t[1]/m[1];
    q[1]:=-b[1]/m[1];
    for i:=2 to n do
        begin
        p[i]:=-t[i]/(k[i]*p[i-1]-m[i]);
        q[i]:=(b[i]-k[i]*q[i-1])/(k[i]*p[i-1]-m[i]);
        end;
    x[n]:=(b[n]-k[n]*q[n-1])/(k[n]*p[n-1]-m[n]);
    for i:=n-1 downto 1 do
       x[i]:=p[i]*x[i+1]+q[i];
    end;
     
    Procedure PrintB(Var a:mas; Var x:vek);
    Var i,j:integer;
    begin
    for i:=1 to n do
        writeln('x(',i,')=',x[i]);
    end;
     
    Procedure Evklid(Var a:mas);
    Var i,j:integer;
    Var ev:real;
    begin
    ev:=0;
     for i:=0 to n do
            begin
                for j:=0 to n do
                 begin
                 ev:=ev + sqrt(sqr(a[i,j]));
                 end;
            end;
             writeln('ev=',ev);
     end;
     
    Procedure Proverka(Var a:mas);
    Var i,j:integer;
    f1:boolean;
    Begin
         for i:=2 to n do
        Begin
            for j:=0 to  i-1 do
            Begin
                if ((a[i,j] <> 0) or (a[j,i] <> 0)) then
                Begin
                f1:= false;
                end;
            end;
        end;
     
    if (f1) then
        Begin
            writeln('Matrix nn');
            Prog(a,k,m,t);
         end
         else
          Begin
          writeln('Error');
         end;
     end;
     
    begin
         InitMas(a,b);
         Prog(a,k,m,t);
         Vec(a,p,q,k,b,x);
         PrintB(a,x);
         Evklid(a);
     readln();
    end.

    Содержание

    1. Параметры процедур и функций
    2. Фактический параметр должен быть переменной что это значит
    3. 10.3.1. Параметры-значения
    4. 10.3.2. Параметры-переменные
    5. 10.3.3. Параметры-константы
    6. 10.3.4. Параметры без типа
    7. 10.3.5. Массивы и строки открытого типа
    8. 10.3.6. Параметры-процедуры и параметры-функции

    Параметры процедур и функций

    Параметры, указываемые при описании подпрограммы, называются формальными . Параметры, указываемые при вызове подпрограммы, называются фактическими .

    Если формальный параметр описан с предваряющим ключевым словом var или const , то его называют параметром-переменной и говорят, что он передается по ссылке . Если же параметр описан без слов var или const , то его называют параметром-значением и говорят, что он передается по значению . Слово ссылка используется в PascalABC.NET также в другом значении — для ссылочных типов.

    Если параметр передается по значению, то при вызове подпрограммы значения фактических параметров присваиваются соответствующим формальным параметрам. Типы фактических параметров-значений должны быть совместимы по присваиванию с типами соответствующих формальных параметров.

    Например, пусть имеется следующее описание процедуры:

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

    Например, если описана процедура

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

    При передаче параметра по ссылке в подпрограмму передается адрес фактического параметра. Поэтому если параметр занимает много памяти (массив, запись, строка), то обычно он также передается по ссылке. В результате в процедуру передается не сам параметр, а его адрес, что экономит память и время работы. При этом если параметр меняется внутри подпрограммы, то он передается с ключевым словом var , если не меняется — с ключевым словом const :

    procedure Print(const p: Person);
    begin
    write(p.name,’ ‘,p.age,’ ‘,p.height,’ ‘,p.weight);
    end;

    Отметим особенности передачи динамических массивов в качестве параметров подпрограмм.

    Поскольку динамический массив является ссылкой, то при изменении формального параметра-динамического массива внутри подпрограммы меняется соответствующий фактический параметр. Например, в результате работы программы

    будет выведено 2. Передавать динамические массивы по ссылке имеет смысл только в случае если память под динамический массив перераспределяется внутри подпрограммы:

    Источник

    Фактический параметр должен быть переменной что это значит

    Формальные параметры подпрограммы указывают, с какими параметрами следует обращаться к этой подпрограмме (количество параметров, их последовательность, типы). Они задаются в заголовке подпрограммы в виде списка формальных параметров, разбитого на группы, разделенные точками с запятыми. В группу формальных параметров включаются однотипные параметры одной категории.

    Все формальные параметры можно разбить на четыре категории:

    • параметры-значения (эти параметры в основной программе подпрограммой не меняются);
    • параметры-переменные (эти параметры подпрограмма может изменить в основной программе);
    • параметры-константы (используются только в версии 7.0);
    • параметры-процедуры и параметры-функции (т. е. процедурного типа).

    Для каждого формального параметра следует указать имя и, как правило, тип, а в случае параметра-переменной или параметра-константы — его категорию. Имена параметров могут быть любыми, в том числе и совпадать с именами объектов программы. Необходимо лишь помнить, что в этом случае параметр основной программы с таким именем становится недоступным для непосредственного использования подпрограммой. Тип формального параметра может быть практически любым, однако в заголовке подпрограммы нельзя вводить новый тип. Например, нельзя писать

    function Max(A: arrayt1..100] of Real): Real;

    Чтобы правильно записать этот заголовок, следует в основной программе ввести тип-массив, а затем использовать его в заголовке:

    type tArr = arrayt1..100] of Real; function Max(A: tArr): Real;

    При обращении к подпрограмме формальные параметры заменяются на соответствующие фактические вызывающей программы или подпрограммы.

    10.3.1. Параметры-значения

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

    Параметр-значение указывается в заголовке подпрограммы своим именем и через двоеточие — типом. Тип параметра-значения может быть любым за исключением файлового.

    Если параметров-значений одного типа несколько, их можно объединить в од ну группу, перечислив их имена через запятую, а затем уже указать общий тип Как отмечалось выше, отдельные группы параметров отделяются друг от точкой с запятой.

    procedure Inp(Max, Min: Real; N: Word);
    function Mult(X, Y: Integer): Real;

    В качестве фактического параметра на месте параметра-значения при вызове подпрограммы может выступать любое выражение совместимого для присваивания типа (см. п. 9.3), не содержащее файловую компоненту, например:

    Inp(Abs(Z), -Abs(T), 2 * К);
    M:=Mult(X + Y, X — Y);
    MA:=Max(B, 5);

    Пример. Функция вычисления максимального элемента в массиве. Пусть в основной программе определен тип-массив, массив этого типа и переменная целого типа

    type
    tArr = array[1..100] of Integer;
    var
    Massiv: tArr;
    Maxim: Integer;

    Функция в этом случае может иметь вид:

    function Max(Mas: tArr; N: Byte): Integer;
    var Ma: Integer;
    i: Byte;
    begin
    Ma := Mas[l];
    for i := 2 to N do
    if Ma

    Теперь, например, для определения максимального числа из первых пяти чисел массива Massiv и записи его в переменную Maxim можно записать оператор:

    Maxim : = Max(Massiv,5); /p>

    Следует иметь в виду, что подпрограмма может работать только с массивами типа tArr. Для массивов другого типа придется создавать другую аналогичную подпрограмму. Кроме того, при работе подпрограммы в стеке будет создана копия исходного массива, что приводит к уменьшению быстродействия и заполнению стека излишней информацией.

    10.3.2. Параметры-переменные

    При передаче параметров-переменных в подпрограмму фактически через стек передаются их адреса в порядке, объявленном в заголовке подпрограммы. Следовательно, подпрограмма имеет доступ к этим параметрам и может их изменять.

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

    procedure MaxMin(A: tArr; var Max, Min: Real; N: Word);

    Здесь Max, Min — параметры-переменные, А и N — параметры значения.

    Тип параметров-переменных может быть любым, включая и файловый.

    При вызове подпрограммы на месте параметра-переменной в качестве фактического параметра должна использоваться переменная идентичного типа (см. п. 9.1). Так, если формальный параметр имеет тип, определенный следующим образом:

    type tArr = array[1..100] of Integer;

    то и фактический параметр должен быть переменной или типизированной константой типа tArr.

    Пример. Функция вычисления максимального элемента в массиве. Модифицируем подпрограмму примера п. 10.3.1, используя в качестве первого параметра параметр-переменную:

    function Max(var Mas: tArr; N: Byte): Integer;
    var Ma: Integer;
    i: Byte;
    begin
    Ma := Mas[l];
    for i := 2 to N do
    if Ma

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

    10.3.3. Параметры-константы

    Часто в качестве параметра в подпрограмму следует передать ту или иную переменную, но изменять ее подпрограмма не должна. В этом случае нежелательно передавать этот параметр как параметр-переменную. Можно его передать как параметр-значение, однако, если эта переменная имеет большой размер (массив, запись и т. д.), то копия такого параметра займет большую часть стека и даже может его переполнить. Это же приводит и к уменьшению быстродействия программы. В этой ситуации параметр лучше передать как параметр-константу. Такой параметр, если он структурированного типа, передается своим адресом, не предусматривается защита от его изменения. Использовать параметр-константу можно только в версии 7.0.

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

    function NewString(const S: string): string;

    Тип параметра-значения может быть любым за исключением файлового.

    При вызове подпрограммы на месте параметра-переменной в качестве фактического параметра можно использовать любое выражение совместимого для присваивания типа (см. п. 9.3), не содержащего файловую компоненту.

    Параметр-константу нельзя передавать в другую подпрограмму в качестве фактического параметра.

    Пример. Функция вычисления максимального элемента в массиве. В примере п. 10.3.1 используем в качестве первого параметра параметр-константу:

    function Max(const Mas: tArr; N: Byte): Integer;
    var Ma: Integer;
    i: Byte;
    begin
    Ma := Mas[l];
    for i := 2 to N do
    if Ma

    10.3.4. Параметры без типа

    В Turbo Pascal можно использовать параметры-переменные и параметры-константы без указания типа. В этом случае фактический параметр может быть переменной любого типа, а ответственность за правильность использования того или иного параметра возлагается на программиста.

    function Equal(var Paraml, Param2; Len: Word): Boolean;

    Здесь Param1, Param2 — параметры-переменные без типа (вместо них можно использовать, например, любые переменные простого типа, типа-массив, типа-запись и т. д.); Len — параметр-значение.

    Следует иметь в виду, что параметр без типа внутри подпрограммы типа не имеет и его перед использованием следует преобразовать к конкретному типу, применяя идентификатор соответствующего типа так, как это указывалось в п. 9.4, при этом полученный результат может быть любого размера.

    Пример. Функция вычисления максимального элемента в массиве. Рассмотрим другой вариант подпрограммы примера п. 10.3.1, используя в качестве первого параметра параметр-переменную без типа:

    function Max(var Mas; N: Byte): Integer;
    type
    tArray = array[1..Maxint] of Integer;
    <тип массива максимального размера>
    var Ma: Integer;
    i: Byte;
    begin
    Ma := tArray(Mas)[1];
    for i := 2 to N do
    if Ma

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

    10.3.5. Массивы и строки открытого типа

    В версии 7.0 можно в качестве параметров-переменных использовать массивы 1 и строки открытого типа, у которых не задаются размеры. В качестве фактического параметра в этом случае можно использовать массив или строку любого ра- 1 змера, однако массив должен состоять из тех же компонент, что и компоненты j открытого массива. Такие параметры введены для того, чтобы подпрограмма мо- ] гла обрабатывать массив или строку любого размера. Фактический размер массива в этом случае может быть определен с помощью функции High (см, j п. 16.1). Открытый массив задается как и обычный массив, но только без указания типа индекса. Следует иметь в виду, что индексация элементов открытого массива всегда начинается с нуля, а максимальный индекс элемента равен значению функции High.

    Пример. Функция вычисления максимального элемента в массиве. Рассмотрим вариант подпрограммы примера п. 10.3.1, используя в качестве передаваемого параметра массив открытого типа:

    function Max(var Mas: array of Integer): Integer;
    var Ma: Integer;
    i: Byte;
    begin
    Ma := Mas[0];
    for i := 1 to High(Mas) do <цикл до наибольшего индекса>
    if Ma

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

    Разновидность открытого массива — открытая строка, которая может задаваться либо с помощью стандартного типа OpenString, либо с помощью типа string и использования ключа компилятора <$Р+>(см. п. 17.7.1), например заголовок процедуры, заполняющей каким-либо символом строку, может иметь вид:

    procedure FillChar(var Str: OpenString; Ch: Char);

    ($p+)
    procedure FillChar(var Str: string; Ch: Char);

    10.3.6. Параметры-процедуры и параметры-функции

    Передаваемым параметром может быть также параметр-процедура или параметр-функция, т. е. параметр процедурного типа. Фактически этот параметр является параметром-значением, т. к. записывается без зарезервированного слова var.

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

    Для параметров-процедур и параметров-функций существуют те же правила, что и для других переменных процедурного типа: подпрограммы должны компилироваться с ключом <$F+) или иметь директиву far, не должны быть стандартными подпрограммами, не должны объявляться внутри других подпрограмм, не иметь директив inline или interrupt.

    Пример. Программа, печатающая таблицы сложения и умножения двух целых чисел в заданном диапазоне.

    program EXAMPLE15;
    type
    Func = function(X, Y: Integer): Integer;
    ($F+)
    function Add(X, Y: Integer): Integer;
    begin
    Add := X + Y
    end;
    function Multiply(X, Y: Integer): Integer;
    begin
    Multiply := X * Y
    end;

    procedure PrintTable(A, B: Integer; Operation: Func);
    <процедура печати таблицы>
    var
    i, j: Integer;
    begin
    for i := 1 to A do
    begin
    for j := 1 to В do
    Write(Operation(i, j): 5);
    WriteLn
    end;
    WriteLn
    end;

    begin <начало основной программы>
    PrintTable(10, 10, Add);
    PrintTable(10, 10, Multiply)
    end.

    Источник

    Параметры-переменные

    При
    передаче параметров-переменных в
    подпрограмму фактически через стек
    передаются их адреса в порядке, объявленном
    в заголовке подпрограммы. Следовательно,
    подпрограмма имеет доступ к этим
    параметрам и может их изменять.

    Параметры-переменные
    указываются в заголовке подпрограммы
    аналогично параметру-значению, но только
    перед именем параметра пишется
    зарезервированное слово var.
    Его действие распространяется на все
    переменные, указанные до ближайшей
    точки с запятой, то есть в пределах одной
    группы.

    Пример

    procedure
    maxmin(a:tArr; var max, min :real; n :word);

    Тип
    параметров-переменных может быть любым,
    включая файловый.

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

    Пример
    Функция вычисления максимального
    элемента в массиве.

    type tarr =
    array [1..100] of integer;

    {фактический
    параметр должен быть переменной или
    типизированной
    константой
    типа
    tarr}

    function
    max (var mas:tarr; n:byte):integer;

    var

    ma:integer;

    i:byte;

    begin

    ma:=mas[1];

    for
    i:=2 to n do

    if
    ma<mas[i] then ma:=mas[i];

    max:=ma;

    end;

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

    Однако,
    при такой передаче параметра возможно
    его нежелательное
    изменение
    .

    Подпрограмма
    по-прежнему может работать с одним типом
    массивов.

    Параметры-константы

    Условие – параметр
    передается в подпрограмму, но изменять
    его подпрограмма не должна. Нежелательно
    передавать параметр как

    параметр-переменную.
    Можно передать как параметр-значение,
    но если этот параметр имеет большой
    размер (массив, запись и т.д.), то копии
    могут занять большую часть стека или
    даже переполнить его. Это ведет к
    уменьшению быстродействия программы.
    В этой ситуации параметр лучше передать
    как параметр-константу. Такой параметр,
    если он структурного типа, передается
    своим
    адресом
    ,
    но предусмотрена его защита от изменений
    (версия 7.0).

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

    Пример

    function
    NewString (const s :string) :string;

    Тип
    параметра-значения
    может быть любым, кроме файлового.

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

    Параметр-константу
    нельзя передавать в другую подпрограмму
    в качестве фактического параметра.

    Пример
    Функция вычисления максимального
    элемента в массиве.

    function
    max(const mas: tarr;n: byte): integer;

    var

    ma:integer;

    i:byte;

    begin

    ma:=mas[1];

    for i:=1
    to n do

    if
    ma<mas[i] then ma:=mas[i];

    max :=ma;

    end;

    Пример

    const

    a:
    integer = 5;

    b:
    integer = 7;

    procedure
    inc(var c: integer; b: integer)

    begin

    c:=
    c+c;

    b:=
    b+b;

    writeln(‘удвоенные
    : ’,c:
    5, b:
    5);

    end;

    begin

    writeln(‘исходные
    : ’,a: 5, b: 5);

    inc(a,b);

    writeln(‘результат
    : ’,a: 5,b: 5);

    end.

    исходные
    :

    5

    7

    удвоенные
    :

    10

    14

    результат
    :

    10

    7

    b
    – параметр-значение

    При
    вызове вычисляется значение, полученный
    результат копируется во временную
    память и передается подпрограмме.

    Любые
    возможные изменения в подпрограмме
    параметра-значения никак
    не воспринимаются вызывающей программой,
    т.к. в этом случае изменяется копия
    фактического параметра.

    а
    – параметр-переменная

    При
    вызове подпрограмме передается сама
    переменная (адрес переменной). Изменение
    параметра-переменной приводит к изменению
    фактического параметра в вызывающей
    программе.

    В
    случае параметра-константы
    в подпрограмму также передается адрес
    области памяти, в которой располагается
    переменная или вычисленное значение.
    Компилятор блокирует любые присваивания
    параметру-константе нового значения в
    теле подпрограммы.

    Пример
    может служить иллюстрацией механизма
    «закрывания» глобальной переменной
    одноименной локальной: хотя b
    объявлена как глобальная, в теле процедуры
    её «закрывает» локальная, объявленная
    как параметр-значение.

    Параметры-переменные используются как
    средство связи с внешним миром: с помощью
    этих параметров подпрограмма может
    передавать своей работы вызывающей
    программе.

    Всегда возможна
    передача результатов и через глобальные
    переменные.

    Оценка
    вариантов передачи результатов работы
    подпрограммы вызывающей программе

    • злоупотребление
      глобальными связями делает программу
      запутанной, трудной в понимании и
      сложной в отладке;

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

    • с
      другой стороны, описание всех формальных
      параметров, как параметров-переменных
      нежелательно по двум причинам: во-первых,
      это исключает возможность вызова
      подпрограммы с фактическими параметрами
      в виде выражений,
      что делает программу менее компактной,
      во-вторых, в подпрограмме возможно
      случайное использование формального
      параметра.

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

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

    Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]

    • #
    • #
    • #
    • #
    • #
    • #
    • #
    • #
    • #
    • #
    • #

    Цитата

    почему со всего исходного списка n-целых чисел, после подсчета средних, получается вещ. список, содержащий только одно среднее(последняя пара 2-ух целых чисел)?

    Значит, что-то неправильно вызываешь…

    Кстати, я посмотрел на твои изменения в программе. Ты очень много лишнего делаешь, тебе не кажется? Можно же обойтись одной структурой tlist для хранения обоих списков. Ведь Real совместим с Integer по присваиванию, то есть значение типа Integer можно без проблем занести в поле типа Real. И еще. Когда я говорил о написании процедуры Append, я имел в виду, что при заполнении первого списка тоже может использоваться эта процедура. Смотри:

    uses crt;
    type
    plist = ^tlist;
    tlist = record
    info: real; { <--- !!! }
    link: plist;
    end;

    procedure append(var first, last: plist; value: real);
    var p: plist;
    begin
    new(p);
    p^.info := value; p^.link := nil;
    if first = nil then first := p
    else last^.link := p;

    last := p;
    end;

    procedure print(p: plist; len: integer);
    begin
    while p <> nil do begin
    write(p^.info:7:len);
    p := p^.link
    end;
    writeln;
    end;

    procedure vvod(var first: plist);
    var
    s: integer;
    p, last: plist;
    begin
    first := nil; last := nil;
    repeat

    write('Vvedite sled element: '); readln(s);
    if s <> 25 then append(first, last, s);

    until s = 25;
    end;

    var
    first: plist;
    p, first_2, last_2: plist;
    ii, jj, nmin: plist;
    T: real;

    begin
    clrscr;
    writeln('Perviy spisok:');
    vvod(first);
    print(first, 0); { Печатаем целые числа, 0 знаков после запятой }

    first_2 := nil; last_2 := nil;
    p := first; { <--- íà÷àëî òâîåãî ñïèñêà }
    while (p <> nil) and (p^.link <> nil) do begin
    append(first_2, last_2, (p^.info + p^.link^.info) / 2);
    p := p^.link;
    end;

    print(first_2, 2); { это - проверка, как средние заносятся в список }

    { Sortirovka }
    ii := first_2;
    while ii^.link <> nil do begin
    nmin := ii;

    jj := ii^.link;
    while jj <> nil do begin
    if jj^.info < nmin^.info then nmin := jj;
    jj := jj^.link;
    end;

    T := ii^.info;
    ii^.info := nmin^.info;
    nmin^.info := T;

    ii := ii^.link;
    end;
    writeln('Otsort spisok:');
    print(first_2, 2); { Ну, и результат }
    end.

    Не забудь удалить списки…

  • Ошибка файн ридер нет доступа к файлу
  • Ошибка файлы отсутствуют при установке расширения
  • Ошибка файлы отсутствуют при скачивании html
  • Ошибка файлы отсутствуют на сервере при скачивании
  • Ошибка файлы отсутствуют chrome при скачивании