Занятие 3. Pascal abc.net: Кортежи. Процедуры и функции (подпрограммы)

Работа с функциями и процедурами в pascal abc.net

Объявление и инициализация кортежей

  • Кортеж — набор из нескольких значений, возможно, разного типа.
  • Кортежи состоят как минимум из двух полей и максимум из семи.
  • Значения кортежей доступны только для чтения.

Объявление кортежей может иметь вид:

var t: (string,integer);
Кортеж t, состоит из двух полей, первое из которых имеет целый, а второе — строковый тип.

После объявления можно присвоить значения:

t := (10, 'Какой-то текст');

Можно также инициализировать переменную сразу при ее объявлении:

var t := (10, 'Какой-то текст');

Для обращения к полям кортежа можно использовать либо точечную нотацию, либо обращение по индексу:

print(t.Item1); // 10
print(t[1]); // Какой-то текст

Пример работы с кортежами:

var st:=('Ivanov',35);
print(st[0]); // Ivanov
print(st[1]); // 35
print(st);  // (Ivanov,35) 
st[1]:= 100; ///ошибка - нельзя изменять

Менять значения нельзя; создали, вывели и всё.

Кортежное присваивание или распаковка кортежа в переменные

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

Пример: распаковать значения кортежа в переменные
var st:=('Ivanov',35);
var name:string;
var age:integer;
(name,age):=st; // ~ name:=st[0]; age:=st[1];

Обмен

var a,b:integer;
(a, b):=(1,2);
(a,b):=(b,a);

ИЛИ

var a,b:integer;
(a, b):=(1,2);
swap(a,b);

Циклический сдвиг:

(a, b, c):=(c, b, a);

Другие примеры работы с кортежами:

  print((1, 2) + 3); // (1,2,3) 
  print((1, 2) + (3, 4)); // (1,2,(3,4)) 
 
// метод add():
  var t:=(1,2,3);
  print(t.Add(4));(1,2,3,4)

Использование кортежей в алгоритмах

Пример: распечатать числа ряда Фибоначчи

Выполнение:

1
2
3
4
5
6
7
8
9
begin
var a,b:integer;
 (a, b):=(1,1);
 print(a,b);
 for var i:=3 to 10 do begin
  (a,b):=(b, a+b);
  print(b);
 end;
end.

кортежи в алгоритмах

Подпрограммы: процедуры и функции в паскаль abc.net

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

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

  • Функции возвращают значение (например, функция min возвращает найденное минимальное значение).
  • Процедуры не возвращают значение, но самостоятельно выводят какие-то значения, либо считывают значения (write, read).
  • Пример: Поиск минимума из двух целых чисел. Реализовать с помощью процедуры и функции.

    ✍ Решение:
     

    Процедура:

    procedure minInt(x, y: integer);
    begin
      if x < y then
        writeln(x);
      else
        writeln(y);
    end;

    Функция:

    function minInt(x, y: integer): integer;
    begin
      if x < y then
        result := x
      else
        result := y;
    end;

    Параметры подпрограмм

      Можно выделить три типа параметров:

      • входные или параметры, передаваемые по значению;
      • входно-выходные или параметры, передаваемые по ссылке;
      • выходные, тоже передаются по ссылке.

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

    Пример входного параметра (по значению):

    procedure inc(x: integer);
    begin
      x := x + 1;
    end;
    // вызов процедуры в основной программе
    begin
      var y := 5;
      inc(y); // Значение 5 будет скопировано, и внутри процедуры переменная x будет равна 5.
      writeln(y);  // 5. Значение переменной y не меняется!
    end.

    Пример входно-выходного параметра (передача параметра по ссылке):

    procedure inc(var x: integer);
    begin
      x := x + 1;
    end;
    // вызов процедуры в основной программе
    begin
      var y := 5;
      writeln(y);  // 5
      inc(y);  // процедура будет работать не с копией x, а с оригиналом, самим x
      writeln(y);  // 6. Значение изменилось!
    end.
    Сокращенный синтаксис функции

    Если мы имеем функцию для вычисления суммы:

    function Add(a,b:real):real;
    begin
      Result:= a + b;
    end;

    То ее сокращенный синтаксис:

    function Add(a,b:real):real:= a + b;

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

    function Add(a,b:real):= a + b;
    begin
      print(Add(2,8));
    end;
    Пример: Вычислить S и P прямоугольника со сторонами a и b. Использовать кортеж и сокращенную запись.

    Выполнение:

    function SP(a,b: real):=(a*b,2*(a+b));
    begin
     print(SP(2,3));
    end;

    пример функции в паскаль абц

Сокращенный синтаксис процедуры
procedure p:=print(1);
Пример: выводить минимальное из двух чисел
procedure p(a, b: real):= if a<b then
   print(a)
 else
   print(b);
Перегрузка имен процедур и функций

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

function Srect(a, b: integer) := a * b;
function Srect(a, b: real) := a * b;
begin
 var a := Srect(3, 7);
 var b := Srect(2.5, 5);
 Print(a, b) // 21 12.5 
end.

Использование модуля

Функции и процедуры принято помещать в пользовательские модули.
Для модуля создается отдельный файл, например, MyUnit.pas, в котором прописывается код функции или процедуры:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Unit MyUnit;    {название модуля}
interface       {раздел служит для объявления используемых ниже функций и процедур}
    function MyFunc(x:real):real;
    procedure MyPr(x:real);
implementation  {реализация функций и процедур}
    function MyFunc(x:real):real;
      begin
        ...
      end;
   procedure MyPr(x:real);
      begin
        ...
      end;
end.

В файле с основной программой:

1
2
3
4
5
Uses MyUnit;
var ...
begin
  ...
end.
Пример: вычислять корень квадратный из x. Использовать модуль и кортеж

Формула для вычисления квадратного корня:
a0=x
a n+1= 1/2 (an+x/an)

Порядок выполнения:
Для модуля создается отдельный файл, например, MyUnit.pas, в котором прописывается код функции:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Unit MyInit;
interface
function MySQL(x:real):real;
implementation
function MySQL(x:real):real;
begin
var a,b:real;
 (a, b):=(x, real.MaxValue);
 var n:=0;
 while abs(b-a)>n do
   (a,b):=((a+x/a)/2,a);
 result:=b;
end;
end.

В файле с основной программой:

1
2
3
4
Uses MyUnit;
begin
print(MySQL(4.0))
end.

Тестирование процедур и функций

Все созданные процедуры принято тестировать. Для этого существует стандартная функция Assert:

function Add(a,b:integer):integer;
begin
  Result:= a + b;
end;
begin
Assert(Add(2,3)=(2+3), 'Тест не прошел');
print (Add(4,6));
end.

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

Важно: Функция пишется вместе с системой тестов к функции

Обобщенные функции (Generic-функции)

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

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

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

Запись такой функции выглядит так:

function MyFunc<T>(a:T):T;
begin
...
end;

В данном примере и аргумент и значение функции имеют изначально неопределенный тип.

Еще пример с обобщенной функцией.

Решение задач

Задание 1: Описать функцию и процедуру Fib(N), которая принимает целое положительное значение N ≥ 1 и возвращает N-ое число Фибоначчи

.
Фрагмент программы для функции:

1
2
3
4
5
6
7
8
9
10
11
12
13
function Fib(var n:integer):integer;
begin
var f1:=1;
var f2:=1;
for ...
  (f1,f2):=...;
result:=...;
end;
begin
  var n:=readinteger;
  ...
  print(...);
end.

Видеоразбор задания для функции:
youTube

Задание 2: Описать функцию IfNine(I), которая возвращает целое число, полученное следующим образом: если среди цифр числа имеется цифра 9, то перед числом добавляется («дописывается») I (I — входной параметр целого типа (параметр по значению)). Сделать задание и для процедуры, которая должна выводить результат в окно вывода (можно в одной и той же программе)
Пример: Описать в краткой форме функцию АSred(X, Y), вычисляющую среднее арифметическое X и Y

Выполнение:

1
2
3
4
5
6
function ASred(x,y:real):=(x+y)/2;
begin
var x:= readReal('введите x');
var y:= readReal('введите y');
println('результат средн. арифм: ',ASred(x,y));
end.
Задание 3: Описать в краткой форме функцию GSred(X, Y), вычисляющую среднее геометрическое двух положительных вещественных и целочисленных чисел X и Y. Выполнить перегрузку функции. Написать модуль для тестирования функции. Выполнить задание и для процедуры, можно в одной и той же программе.
Пример: Вычислить и вывести с тремя знаками после запятой значение х, найденное по формуле.

Выполнение:

1
2
3
4
function F(n: integer) := n + Sqrt(n);
begin
 Write(F(5) / F(7) + F(12) / F(8) + F(31) / F(2):0:3)
end.
Задание 4: Вычислить и вывести с 4 знаками после запятой значение х, найденное по формуле:
Пример: Опишите в модуле функцию вычисления площади и периметра прямоугольника, заданного своими сторонами.
function SP(a,b: real) :(real,real);
в разделе реализации используйте краткую форму.

Выполнение:
Листинг модуля pr1.pas:

1
2
3
4
5
6
7
8
9
unit pr1;
interface
function SP(a,b: real) :(real,real);
implementation
function SP(a,b: real) :(real,real);
  begin
    result:=(a*b,2*(a+b));
  end;
 end.

Листинг основной программы:

1
2
3
4
5
6
uses pr1;
begin
  var S,P: real;
  (S,P) := SP(2,3);  
  print(S,P);
end.
Задание 5: предыдущий пример выполнить в модуле
Пример: Дано целое число N > 3. Последовательность целых чисел Ak определяется следующим образом:
A1=1, A2=2, A3=3, Ak=Ak−1+Ak−2−2⋅Ak−3, k=4,5,… Вывести N-ое число

Выполнение:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function MakeSeq1(var n:integer):integer;
begin
var a1:=1;
var a2:=2;
var a3:=3;
for var i:=3 to n do
  (a1,a2,a3):=(a2,a3,a3+a2-2*a1);
  result:=a3;
end;
begin
  var n:=readinteger;
  dec(n);
  var a:=MakeSeq1(n);
  print(a);
end.
Задание 6: Дано целое число N > 2. Последовательность вещественных чисел Ak определяется следующим образом:
A1=2,Ak=2+1/Ak−1, k=2,3,… Вывести N-ое число.
Протестировать функцию операцией assert().

Примерный вывод:

тест пройден
>>10
результат: 2.41428571428571 

Фрагмент программы:

1
2
3
4
5
6
7
8
9
10
11
12
13
function MakeSeq(var n:integer):real;
begin
var a1:=2.0;
var a2:real;
for ...
  (a1,a2):=...;
result:=...;
end;
begin
  ...
  ...
  print(a);
end.

Задание 7: Описать обобщенную функцию IsitDigit(D), которая возвращает истину, если целое число D является цифрой (одноразрядное число, то есть D лежит в диапазоне 0–9). В основной программе вывести значение этой функции для N (N ≥ 0) данных чисел

Пример: Описать функцию AddToRightDigit(I, N), которая возвращает целое число, полученное «дописыванием» к целому положительному числу N справа цифры I (I — входной параметр (параметр по значению) целого типа, лежащий в диапазоне 0–9, N — входной положительный параметр (параметр по значению) целого типа).
Протестировать функцию операцией assert().

Выполнение:

1
2
3
4
5
6
7
8
9
10
function AddToRightDigit(i,n:integer):integer;
begin
  var str:=n.ToString+i;
  result:=str.ToInteger;
end;
begin
  var n :=readInteger ('введите число');
  var i :=readInteger('введите постфикс');
  print(AddToRightDigit(i,n))
end.