Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Алгоритмизация и программирование. Учебное пособие

.pdf
Скачиваний:
0
Добавлен:
06.09.2026
Размер:
1 Мб
Скачать
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.
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]