Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Алгоритмизация и программирование. Учебное пособие
.pdf
51
13. ФУНКЦИИ
Функции ‒ это подпрограммы, результатом которых обязательно является некоторое значение. Описание функции во многом совпадает с описанием процедуры. Если имя процедуры используется только для её вызова, то с именем функции, кроме того, связывается её результат. Функции
описываются по схеме:
Function Имя функции (список параметров): тип результата;
БЛОК ОПИСАНИЯ
Begin
БЛОК ОПЕРАТОРОВ
End;
Функция предполагает обязательную передачу информации из подпрограммы в программу через имя функции. Поэтому раздел операторов
обязательно должен содержать хотя бы один оператор, в котором имени
функции присваивается значение результата. В противном случае функция не возвратит результат (точнее, вернёт произвольный результат). Для
того, чтобы лучше понять принципиальные отличия функции от процедуры, рассмотрим решение следующей задачи.
Задание. Найти сумму двух чисел рассчитывается двумя способами
– с помощью процедуры и с помощью функции.
Текст программы.
Var a,b,c :integer;
Procedure PSum(Var x,y,z: integer); // Процедура нахождения суммы
Begin
z:=x+y;
End;
Function FSum(Var n,m:integer): integer;//Функция нахождения суммы
Begin
FSum:=n+m;
End;
BEGIN
Write(‘Введите первое слагаемое’);
Readln(a);
Write(‘Введите второе слагаемое’);
Readln(b);
Psum(a,b,c);
Writeln(‘Результат работы процедуры - ’,c);

52
Writeln(‘Результат работы функции - ’, FSum(a,b));
END.
Из текста программы видно, что, вызов функции в программе отличается от вызова процедуры. Вызов процедуры всегда представляет
собой самостоятельный оператор. Функция не может быть самостоятельным оператором. Вызов функции производится:
в различных выражениях;
только справа от знака присваивания;
как элемент вывода в операторе вывода информации.
С помощью функций передача информации осуществляется только
в одном направлении - от подпрограммы к программе. В то же время для
параметров функции справедливы все те же правила, что и для параметров процедур. В частности, использование слова Var перед формальными параметрами в функции может привести к изменению соответствующих фактических параметров основной программы.
Отметим, что оформлять некоторую подпрограмму как функцию целесообразно только в том случае, если ожидается некоторый результат её
работы. Если же подпрограмма ориентирована только на выполнение некоторой последовательности действий (вывод на экран, рисование и т.д.),
лучше оформить её как процедуру.
Задание. Описать функцию, находящую минимум двух чисел.
Текст программы.
function Min(a,b:integer):integer;
Begin
if a<b then Min:=a else Min:=b;
End;
Var x, y: integer;
BEGIN
Write(‘введите два числа’);
Readln(x);
Write(‘введите два числа’);
Readln(y);
Writeln(‘Наименьшее число=’, Min(x,y));
End.
Задание. Вычислить площадь треугольника по координатам его
вершин.

53
Решение. Формулы, непосредственно вычисляющей площадь треугольника по координатам его вершин, нет. Есть формула для вычисления
площади треугольника по длинам его сторон (формула Герона) и формула
нахождения длины отрезка по координатам его концов. Опишем данные
формулы как функции и используем для решения задачи.
Текст программы.
// функция нахождения длины отрезка по координатам его концов
Function dlotr(x1,y1,x2,y2:real):real;
Begin
dlotr:=Sqrt(sqr(x1-x2)+sqr(y1-y2));
End;
// функция нахождения площади треугольника по длинам его сторон
Function Geron(a,b,c:real):real;
Var p:real;
Begin
P:=(a+b+c)/2;
Geron:=sqrt(p*(p-a)*(p-b)*(p-c))
End;
Var m1,n1,m2,n2,m3,n3:real;
BEGIN
Write(‘x1=’); // Запрашиваем координаты вершин треугольника
Readln(m1);
Write(‘y1=’);
Readln(n1);
Write(‘x2=’);
Readln(m2);
Write(‘y2=’);
Readln(n2);
Write(‘x3=’);
Readln(m3);
Write(‘y3=’);
Readln(n3);
Writeln (‘Площадь треугольника=’,
Geron( dlotr(m1,n1,m2,n2), dlotr(m2,n2,m3,n3),dlotr(m3,n3,m1,n1)));
END.
Рекурсия. Рекурсивные подпрограммы.
Одной из замечательных особенностей подпрограмм является возможность обращения к себе из своего же собственного тела. Рекурсией
называется ситуация, когда какая-то подпрограмма напрямую или через

54
другие подпрограммы вызывает себя в качестве подпрограммы. Реализуемый при этом алгоритм называется рекурсивным. Главное требование к
рекурсивным подпрограммам заключается в том, что вызов рекурсивной
подпрограммы должен выполнятся по условию, которое на каком-то
уровне рекурсии станет ложным. Если данное требование не соблюдено –
программа неизбежно зависнет.
Задание. Используя рекурсивную функцию найти факториал введён-
ного числа.
Решение. Факториалом числа N (обозначается N!) называется произведение 1*2*3*….*N, при этом 0!=1. Можно заметить, что факториал
числа N, равен факториалу числа N-1 умноженному на N. То есть факториал можно задать в виде рекурсивной функции
N!= (N-1)!*N для N>0.
Текст программы.
function F(n:integer):integer;
Begin
if (n=0) then F:=1 else F:=F(n-1)*n;
End;
Var x:integer;
BEGIN
Writeln(‘введите число’);
Readln(x);
Writeln( x,’!=’, f(x));
END.
Задание. Используя рекурсивную функцию найдите первые 10 членов
последовательности Фибоначчи, которая рассчитываются по следующей
формуле:
Текст программы.
function Fib(n:integer):integer;
Begin
if (n= 1) or (n=2) then Fib:=1 else Fib:=Fib(n-1)+ Fib(n-2);
End;
Var i:integer;

55
BEGIN
for i:= 1 to 10 do writeln(‘f(’,i,’)=’, Fib(i));
END.
Программы, в которых используются рекурсивные подпрограммы
отличаются простотой, наглядностью и компактностью текста. В то же
время выполнение рекурсивных подпрограмм требует значительно
большего потребления оперативной памяти, чем не рекурсивных. При
каждом рекурсивном вызове для локальных переменных, а также для
параметров подпрограмм, которые передаются по значению, выделяются
новые ячейки памяти.
Задания для самостоятельной работы
1. Опишите функцию, f(x) и найдите её значение для х, введённого с
клавиатуры.
2. Опишите функцию, f(x) и найдите её значение для х, введённого с
клавиатуры.
3. Опишите функцию, f(x) и найдите её значение для х, введённого с
клавиатуры.
4. Опишите функцию, f(x) и найдите её значение для х, введённого с
клавиатуры.
5. Опишите функцию FSR, находящую среднее арифметическое двух чисел. Для любых чисел a и b , введённых с клавиатуры, найдите значение
а+2*FSR(a,b) – b* FSR2(a,10).

56
6. Опишите функцию OST, находящую наименьший из остатков двух чи-
сел при делении на 5. Для любых чисел a и b, введённых с клавиатуры,
найдите значение
3*OST2(a,7) – a* OST(b,b)/2.
7. Опишите функцию MAX, находящую максимум двух чисел. Для лю-
бых чисел a и b, введённых с клавиатуры, найдите значение
Max2(a,b)+a*b- a*Max(10,b).
8. Опишите функцию Raz, находящую разность квадратов двух чисел.
Для любых чисел a и b, введённых с клавиатуры, найдите значение
Raz(3,a)+7*b- Raz3(a,b).
9. С помощью рекурсивной функции выведите на экран первые десять
членов геометрической прогрессии с первым членом 2 и шагом 1,2.
10. Используя рекурсивную функцию, напишите программу, находящую
результат возведения числа 3 в степень (например, f(2) = 9). Показатель
степени вводит пользователь.
11. Используя рекурсивную функцию, напишите программу, выводящую
на экран первые 15 членов арифметической прогрессии с первым членом
3 и шагом 2 (n вводится с клавиатуры).
12. Используя рекурсивную функцию, напишите программу, находящую
результат умножения натурального числа на 7 (например, f(5) = 35).
14. ТИПИЗИРОВАННЫЕ ФАЙЛЫ
Для хранения информации полученной в результате работы программ, используют различные носители информации (жёсткие диски,
оптические диски, флэш-накопители и т.д.). Организация хранения информации зависит от особенностей конкретного носителя. В общем случае хранение информации организуют в виде именованных областей
внешней памяти - физических файлов. Для организации работы с физическими файлами в языках программирования предусмотрены специальные структуры данных - тип данных файл. Файл в таком понимании
называют логическим файлом, так как в этом случае он представляет собой лишь логическую модель хранения информации, не зависящую от
организации конкретного физического файла. В дальнейшем мы будем
говорить именно о логических файлах.

57
Работа с файлами в Паскале осуществляется с помощью нескольких
типов данных. Наиболее простой из них – типизированный файл. Типизированный файл ‒ это потенциально бесконечная последовательность компонент одного и того же типа. Количество компонент в файле заранее не
оговаривается. Для описания переменных, имеющих файловый тип, используется конструкция
Var имя переменной: file of базовый тип;
Базовым типом может быть любой тип, кроме типа file.
Пример:
Var a: file of integer; // a – файл, состоящий из целых чисел.
Отметим, что при таком варианте описания данная файловая переменная не может быть использована в качестве параметров подпрограмм. Если предполагается использовать файловую переменную в подпрограммах, то сначала описывают пользовательский файловый тип,
а потом переменную данного типа. Такую переменную можно использовать как параметр процедур или функций.
Пример:
type Myfile = file of integer;
Var a: Myfile;
Работа с файлами.
Для простоты и наглядности файловую переменную можно представить, как последовательность однотипных компонент, хранящуюся на
магнитной ленте. В самом начале записывается имя файла, после него
идут компоненты файла, а в самом конце признак конца файла. Все компоненты пронумерованы. Нумерация начинается с нуля. Считывание
или запись информации из файла осуществляется с помощью воображаемой магнитной головки, которую мы в дальнейшем будем называть текущим указателем. Файл может находится в различных состояниях:
1. файл закрыт;
2. файл открыт для записи;
3. файл открыт для чтения.
Перед началом работы с логическим файлом его необходимо связать с файлом на диске (физическим файлом). Для этой цели используется процедура Assign(f, name), связывающая файловую переменную f с

58
физическим файлом, имеющим имя name. Имя файла может содержать
путь к файлу в формате DOS. При отсутствии пути подразумевается, что
файл находится в текущем каталоге. После использования процедуры
Assign файловая переменная станет “представителем” физического файла в программе.
Пример:
Assign(f1, 'c:\work\bank.dat');
Assign(f2, 'data.dat');
Процедура Reset(f) предназначена для открытия файла для чтения
или записи. При её выполнении указатель перемещается к первой компоненте файла, то есть к элементу с номером 0. Отметим, что физический файл, связанный с переменной f должен обязательно существовать.
В противном случае произойдёт ошибка в работе программы.
Процедура Rewrite (f) предназначена для создания нового файла,
или для подготовки к записи с начала существующего файла (к перезаписи). Текущий указатель перемещается к началу файла. Если файл существует, то его предыдущее содержимое уничтожается. Если файла
нет, то он будет создан. После применения данной процедуры файл становится открытым для записи и закрытым для чтения.
Процедура Close(f) ‒ закрывает открытый файл. Файл становится
закрытым для чтения и закрытым для записи. Однако, связь переменной
f с физическим файлом, установленная ранее командой Assign сохраняется. Ни в коем случае не следует пренебрегать этой операцией. Оставшийся открытым файл, как правило, может вызвать аварийную ситуацию.
Процедура Erase(f) ‒ удаляет файл. Файл должен быть закрыт.
Процедура Read (f,v1,v2,...,vn) предназначена для чтения значений
из файла в программу. f – это файловая переменная, остальные параметры – это переменные, в которые будет помещаться информация из компонент файла. Тип этих переменных должен совпадать с базовым типом
файла. При прочтении компоненты из файла текущий указатель перемещается к следующей компоненте.
Процедура Write (f,v1,v2,...,vn) предназначена для записи информации в файл. f - файловая переменная, остальные параметры - переменные, содержимое которых будет помещено в файл.
Все компоненты типизированных файлов пронумерованы. Это
позволяет организовать произвольное перемещение по файлу и доступ к
любой компоненте такого файла. Для навигации по файлу используются
следующие функции:
Seek(f, n) ‒ перемещает текущий указатель в файле f на позицию
номер n (нумерация начинается с нуля).

59
Truncate(f) ‒ усекает файл (обрезает его) на текущей позиции.
FileSize(f) ‒ возвращает текущий размер файла (номер последней
компоненты).
FilePos(f) ‒ возвращает положение текущего указателя в файле.
EOF(f) ‒ функция определения конца файла. Возвращает значение
true, если текущий указатель находится за последней компонентой файла, false в противном случае. Данную функцию удобно использовать
как условие выхода из мягкого цикла при чтении файла.
Задание. На диске С создать файл целых чисел. Поместить в него
все числа от 1 до 100.
Текст программы.
Var f: file of integer;
i: integer;
BEGIN
Assign(f,’c:\primer.dat’);
Rewrite(f);
for i:=1 to 100 do Write(f,i);
Close(f);
END.
Задание. Открыть ранее созданный файл. Вывести его содержимое
на экран. Найти среднее арифметическое элементов файла.
Текст программы.
Var f: file of integer;
i,s,m: integer;
BEGIN
Assign(f,’c:\primer.dat’);
Reset(f);
s:=0;
Repeat // цикл мягкий, так как число компонент файла обычно
// неизвестно
Read(f,m);
Write(m,’ ‘);
Until EOF(f); // если достигнут конец файла,
//то завершаем считывание
Writeln;
Writeln('Среднее арифметическое =', s/filesize(f));
Close(f);
END.

60
Задание. Создать файл a.dat, заполнить его 10ю вещественными числами с клавиатуры. Вывести содержимое на экран. Создать файл b.dat,
поместить в него все отрицательные числа из файла a.dat. Вывести содержимое на экран.
Текст программы.
Var a,b: file of real;
m:real;
i:integer;
BEGIN
Assign(a,’c:\a.dat’);
Assign(b,’c:\b.dat’);
Rewrite(a);
Write(‘Введите 10 чисел’); // Заполняем файл a.dat
for i:=1 to 10 do begin
Write (‘число №’,i,’=’);
Readln(m);
Write(a,m);
end;
Close(a);
Writeln;
Writeln(‘ Содержимое файла a.dat’);
Reset(a);
Repeat
Read(a,m);
Write(m,’ ‘);
Until EOF(a);
Close(a);
Reset(a);
Rewrite(b);
Repeat // Заполняем файл b.dat
Read(a,m);
if m<0 then Write(b,m);
Until EOF(a);
Close(a);
Close(b);
Writeln(‘ содержимое файла b.dat’);
Reset(b);
Repeat
Read(b,m);
Write(m,’ ‘);
Until EOF(b);
Close(b);
END.
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
