Function Summa(x, y: Real): Real;
Var s : Real;
Begin
s := x + y; эта функция ничего не вычисляет!
End;
7. помимо формальных параметров, в функции могут использоваться локальные переменные. Они описываются внутри функции в разделе Var , существуют только в ней и служат для реализации алгоритма вычислений. При выходе из функции их значения исчезают:
Function Fact(n: Word): Word; n – формальный параметр
Var i, f : Word; i, f – локальные переменные
Begin эта функция вычисляет факториал
f:=1; заданного числа
For i:=1 To n Do
f := f * i;
Fact := f;
End;
8. если в функции используется цикл с параметром (цикл For), то параметр цикла должен быть описан внутри этой функции, то есть он должен быть обязательно локальной переменной (предыдущий пример),
9. связь вызывающей (головной) программы с функцией может осуществляться как через формальные и фактические, так и через глобальные параметры. Глобальные параметры (переменные) не описываются ни в заголовке функции, ни внутри ее. Они описываются в вызывающей программе и существуют как в ней, так и в любой функции, вызываемой из этой программы. Глобальные переменные могут изменять свои значения как в вызывающей программе, так и внутри функции:
Program Global;
Uses CRT;
Var a, b, c, s : Integer; с -глобальная переменная
Function Sum(x, y : Integer) : Integer;
Begin
c := c + 1; изменение значения глобальной
Sum := x + y + c; переменной в функции
End;
Begin
a := 1;
b := 1;
c := 1; инициализация глобальной переменной
s := c + Sum(a, b);
WriteLn(‘s=’, s);
ReadLn;
End.
После выполнения этой программы s = 5.
Следует избегать использования глобальных переменных в функциях, так как это может привести к непредсказуемым результатам вычислений. В предыдущем примере значение переменной s определялось оператором присваивания:
s := c + Sum(a, b);
и принимало значение s = 5. Поменяем местами слагаемые в этом операторе присваивания:
s := Sum(a, b) + c;
Казалось бы, результат измениться не должен, но после вычислений получим
s = 6 - значение глобальной переменной c изменилось внутри функции и стало равным с = 2, и с таким значением оно было добавлено в общую сумму в вызывающей программе.
Локальные и глобальные переменные размещаются в оперативной памяти в различных сегментах (частях). При трансляции программы формируются:
· сегмент кода, в котором хранится программа в виде машинных команд,
· сегмент данных, в котором выделяется память под глобальные переменные,
· сегмент стека, предназначенный для размещения локальных переменных:
Размер каждого сегмента не может превышать 64Кбайт. Адреса сегментов хранятся во время выполнения программы в сегментных регистрах:
CS – адрес сегмента кода,
DS – адрес сегмента данных,
SS – адрес сегмента стека.
В связи с размещением в различных сегментах памяти, глобальные и локальные переменные действуют по-разному:
· время жизни глобальных переменных – от начала работы программы до ее завершения,
· если глобальные переменные не были инициализированы явным образом, то есть им не были присвоены начальные значения, то перед началом работы программы они обнуляются,
· время жизни локальных переменных – с момента вызова подпрограммы и до ее окончания,
· значения локальных переменных между двумя вызовами одной и той же подпрограммы не сохраняются,
· неинициализированные локальные переменные предварительно не обнуляются, а принимают произвольные значения, зависящие от информации, оставшейся в занимаемых ими ячейках памяти,
· если переменная внутри подпрограммы определена в разделе описания константConst , то память под нее выделяется не в сегменте стека, а в сегменте данных, причем начальное значение ей присваивается один раз до начала работы программы, а не при входе в подпрограмму:
Function Func(k: Word) : Word;
Const n: Word = 0; n – типизированная константа
Var i: Word;
Begin
WriteLn(‘i=’,i); неопределенное значение переменнойi
WriteLn(‘n=’,n);
n:= n + k;
Func:=n;
End;
Переменной i будет присвоено заранее неизвестное значение. При первом обращении к функции переменная n, определенная в CONST, будет равна нулю, и при каждом последующем обращении она будет увеличиваться на k.
· время жизни такой переменной – время работы всей программы: значения этой переменной сохраняются между вызовами подпрограммы,
· область действия такой переменной – подпрограмма, в которой она описана, то есть вне подпрограммы к этой переменной обратиться нельзя,
10. локальные и глобальные переменные могут совпадать по имени; в этом случае в функции работают локальные переменные,
11. в качестве формальных параметров функций можно использовать имена переменных любого типа, имена массивов, множеств, файлов, записей, комбинированных структур, а также имена ранее определенных функций;
в качестве формальных параметров функций нельзя использовать конкретные значения (числа, символы), элементы массивов, поля записей, выражения и стандартные функции,
12. в качестве фактических параметров функций можно использовать константы, переменные, имена и элементы массивов, множеств, файлов, имена и поля записей, комбинированных структур, а также выражения, стандартные функции и имена ранее описанных функций,
13. значения входных (фактических) параметров функций не изменяются, даже если соответствующие им формальные параметры изменяются внутри функции; такие не изменяющиеся функцией входные переменные называются параметрами-значениями. При использовании параметров-значений в функцию передаются не сами фактические параметры, а их копии. Поэтому сами параметры остаются всегда неизменными:
Program Primer;
Uses CRT;
Var a, b, c : Integer;
Function Sum(x, y : Integer) : Integer; x, y – параметры-значения
Begin
x := x + 1; изменение значений формальных
y := y + 1; параметров в функции
Sum := x + y;
End;
Begin
a := 1;
b := 1;
c := Sum(a, b);
WriteLn(‘a=’, a, ‘ b=’, b);
ReadLn;
End.
Входные значения фактических параметров x = 1, y = 1. После выполнения программы они останутся теми же, хотя внутри функции соответствующие им формальные параметры изменились,
14. в качестве входных переменных можно использовать параметры переменные; их значения могут изменяться функцией, и эти изменения сохраняются при выходе из функции. Они описываются в списке формальных параметров функции с добавлением слова Var:
Program Primer;
Uses CRT;
Var a, b, c : Integer;
Function Sum(Var x, y : Integer) : Integer; x, y – параметры-переменные
Begin
x := x + 1; изменение значений формальных
y := y + 1; параметров в функции
Sum := x + y;
End;
Begin
a := 1;
b := 1;
c := Sum(a, b);
WriteLn(‘a=’, a, ‘ b=’, b);
ReadLn;
End.
Входные значения фактических параметров x = 1, y = 1. После выполнения программы они изменятся и примут значения x = 2, y = 2.
При использовании параметров-переменных в функцию передаются не копии фактических параметров, как это имело место с параметрами-значениями, а адреса фактических параметров, что позволяет сохранять их измененные функцией значения.
Зачастую использование параметров-переменных может тоже привести к непредсказуемым результатам вычислений:
Program Primer;
Uses CRT;
Var a, b : Integer;
Function Nemo(Var x : Integer; y : Integer) : Integer;
x – параметр-переменная,
y – параметр-значение
Begin
x := x + y;
a := y;
Nemo := x;
End;
Begin
a := 1;
b := 2;
WriteLn(‘Nemo=’, Nemo(a, b),‘ a=’, a, ‘ b=’, b);
ReadLn;
End.
Результат работы программы:
Nemo=2 a=2 b=2
Значение переменной a будет испорчено, так как значения переменных a и x будут записываться в одной ячейке памяти, а функция Nemo вместо 3 примет значение, равное 2. Ошибки такого рада трудно найти, поэтому в функциях и не рекомендуется использовать параметры-переменные,
15. в заголовке функции нельзя использовать формальные параметры безымянных типов (стандартные типы считаются поименованными):
Function Func(x : 1..10; r : array [1..20] Of Real) : Real;
Типы формальных параметров x и r являются безымянными, так как не относятся к стандартным. Поэтому в вызывающей эту функцию программе необходимо определить новые типы данных:
Type TCount = 20;
TVector = Array [1 .. TCount] Of Real;
TInterval = 1 .. 10;
а в заголовке функции использовать эти новые типы:
Function Func(x : TInterval; r : TVector) : Real;
16. в любой функции в качестве формальных параметров могут быть использованы другие функции, составленные программистом – параметры-функции.
Требования к таким функциям:
ü их тип должен быть определен в разделе описания типов Type,
ü они не должны быть стандартными,
ü они не должны быть вложенными,
ü они должны иметь только параметры-значения,
ü они должны быть откомпилированы с использованием директивы компилятору {$F+} – использование дальнего типа вызова подпрограмм.
Пример: создать функцию для определения суммы, произведения двух чисел и произведения их суммы на их разность. Функции для выполнения этих операций описать как параметры-функции:
Program Param_func;
Uses CRT;
Type TFunс = Function (x, y: Integer): Integer; описан процедурный тип TFunc – целой функции двух аргументов целого типа
Var a, b, c: Integer;
{$F+} директива компилятору- использование дальнего типа вызова подпрограмм
Function Add(x, y: Integer): Integer; функция для сложения двух переменных
Begin
Add := x + y;
End;
Function Mult(x, y: Integer): Integer; функция для перемножения двух переменных
Begin
Mult := x * y;
End;
Function Funny(x, y: Integer): Integer;
Begin
Funny := (x + y) * (x - y);
End;
{$F-} отменадирективы
функция, использующая параметр-функцию operation
Function Par_func(m, n : Integer; operation : TFunc): Integer;
Begin
Par_func := operation(m, n);
End;
Begin
ClrScr;
a := 5;
b := 3;
c := Par_func(a, b, Add); фактические параметры для параметров-функций не указываются!
WriteLn('c=', c);
c := Par_func(a, b, Mult);
WriteLn('c=', c);
c := Par_func(a, b, Funny);
WriteLn('c=', c);
ReadLn;
End.
На экран будет выведено:
с=8
с=15
с=16
17. в Паскале разрешено использовать рекурсию – обращение функции самой к себе, при этом имя функции со списком формальных параметров будет стоять в операторах функции справа от знака присваивания.
Рекурсия
Использование рекурсии в программировании базируется на рекурсивных математических определениях. Считается, что в математике рекурсивность как принцип определений используется с 1890 года. Впервые применил ее Д.Гильберт.
Основная идея рекурсии – определить некий объект через самого себя, по крайней мере, частично. Оказалось, что с помощью рекурсии удобно описывать различного рода последовательности, подчиняющиеся определенным закономерностям.
Например, вычисление факториала целого неотрицательного числа n! = 1·2·3·…·(n-1) · n . Кроме того, по определению, 0! = 1. Рекурсивное математическое определение факториала имеет вид:
1 при n = 0,
n!=
(n – 1)!·n при n > 0.
Последовательность чисел Фибоначчи имеет вид 1, 1, 2, 3, 5, 8, 13…
В ней два первых числа фиксированы и равны единице, а каждое последующее число равно сумме двух предыдущих. Рекурсивное математическое определение числа Фибоначчи с порядковым номером n имеет вид:
1 при n = 1,
Fn= 1 при n = 2,
Fn-2 + Fn-1 при n > 2.
Общей особенностью этих рекурсивных определений является то, что некий сложный объект определяется через себя же (рекурсивно обращается к себе же), но в более простом исполнении. Рекурсивные математические определения отличаются особой лаконичностью, что и подтверждается вышеприведенными примерами.
На базе рекурсивных определений можно построить компактные и выразительные подпрограммы. Вполне очевидно, что за любым из приведенных рекурсивных определений прячется некий циклический процесс вычислений. Такой циклический процесс допускает реализацию на базе некоей рекуррентной формулы, производной от соответствующего рекурсивного определения. Рекуррентные формулы являются составными и определяют числовые последовательности, в которых каждый очередной член зависит от одного или нескольких предыдущих. При этом для рекуррентной формулы характерно, что она представляет собой зависимость очередного члена последовательности от строго определенных предыдущих ее членов. Составной частью рекуррентной формулы является прямое определение одного или нескольких начальных членов последовательности. Чаще всего определяемая последовательность бесконечна, поэтому требуется указать требуемое количество ее членов. Трансформируем вышеприведенные рекурсивные математические определения в рекуррентные формулы.
Рассмотрим последовательность факториалов целых чисел 0!, 1!, 2!, 3!,…, в которой ai = i!, i = 1, 2, 3,… Эту же последовательность можно представить в виде рекуррентной формулы: ai = ai-1·i, a0 = 1, i = 1, 2, 3… Эта формула задает последовательность, в которой каждый очередной член зависит непосредственно от предшествующего. Начальный член последовательности a0 задан прямою. Найдя член последовательности с порядковым номером i = n, мы тем самым решим задачу вычисления n!
Рекуррентная формула для вычисления числа Фибоначчи с заданным порядковым номером i = n практически не отличается от рекурсивного определения: Fi = Fi-2 + Fi-1 , F1 = 1 , F2 = 1 , i = 3, 4, 5,…
Итак, функция считается рекурсивной, если при решении задачи она обращается к самой себе или непосредственно, или через другие подпрограммы. Известно, как технически реализуется обращение к подпрограмме в общем случае:
1. запоминается состояние программы, вызывающей подпрограмму – адрес точки, следующей за оператором обращения к подпрограмме, чтобы знать, куда вернуться после ее выполнения,
2. в свободном месте памяти располагаются все необходимые локальные переменные вызываемой подпрограммы, а также копии тех ее параметров, которые передаются по значению,
3. выполняются операторы подпрограммы, затем освобождается временно занятая область памяти, после чего осуществляется возврат в нужную точку программы, вызвавшей подпрограмму.
При рекурсивном обращении каждый раз приходится запоминать не только адрес возврата, но и всю совокупность данных вызывающей подпрограммы (локальные переменные и параметры-значения). С этой целью используется автоматически выделяемая область памяти – стек, структура, работающая по принципу LIFO (Last in – first out: последним пришел – первым вышел). Такой метод работы с памятью обеспечивает строгое соответствие прямого порядка записи данных обратному порядку их чтения. Только с помощью стека можно достаточно просто обеспечить корректное завершение работы цепочки подпрограмм, каждая из которых вызывает следующую: сначала должна быть завершена последняя, затем – предпоследняя и так далее. Максимальный размер стека – 65520 байт. Поэтому последовательность рекурсивных обращений не может быть бесконечной. В любой рекурсивной подпрограмме должна быть нерекурсивная (терминальная) ветвь, обеспечивающая выход из рекурсии. При переполнении стека работа программы прерывается, и появляется сообщение об ошибке Error 202: Stack overflow error.
Рекурсивная функция, вычисляющая факториал заданного числа n, может иметь вид:
Function Factorial(n: Word): Word;
Begin
If (n=0)
Then Factorial := 1 выход из рекурсии
Else Factorial := n * Factorial(n – 1); рекурсия
End;
При n = 5 эта функция будет работать следующим образом:
Factorial := 5 * Factorial(4)
5 * 4 * Factorial(3)
5 * 4 * 3 * Factorial(2)
5 * 4 * 3 * 2 * Factorial(1)
5 * 4 * 3 * 2 * 1 = 120
В данном случае реализована так называемая нисходящая рекурсия: вызов Factorial(5) означает, что функция Factorial вызывает себя раз за разом: Factorial(4), Factorial(3), … до тех пор, пока не будет достигнута терминальная ситуация – ситуация окончания рекурсии. При каждом вызове текущие вычисления откладываются, локальные переменные и адрес возврата остаются в стеке. Терминальная ситуация Factorial := 1 достигается при n = 0. При этом рекурсивный спуск заканчивается, начинается рекурсивный возврат изо всех вызванных в данный момент копий функции: начинает строиться ответ n*Factorial(n-1). Сохраненные локальные параметры выбираются из стека в обратной последовательности, а получаемые промежуточные результаты: 1*1, 2*1, 3*2*1, 4*3*2*1, 5*4*3*2*1 – передаются вызывающим функциям.
Рекурсивная функция, вычисляющая n-й член ряда Фибоначчи, может иметь вид:
Function Fibo(n: Word): Word;
Begin
If (n=1) Or (n=2)
Then Fibo := 1 выход из рекурсии
Else Fibo := Fibo(n-2) + Fibo(n-1); рекурсия
End;
Мы рассмотрели непосредственную рекурсию – функция вызывает саму себя. Помимо непосредственной, возможна косвенная рекурсия – функция Func_1 вызывает функцию Func_2, а функция Func_2, в свою очередь – функцию Func_1. Но как описать две функции, вызывающие одна другую? Ведь по правилам Паскаля подпрограмма обязательно должна быть объявлена до своего использования. В этом случае используется опережающее описание с помощью директивы Forward. При объявлении подпрограммы указывается только ее заголовок со списком формальных параметров и директивой Forward, а тело создается далее без повторного описания этих параметров:
Program Primer;
Uses CRT;
Var i: Integer; описание переменных головной программы
Function Func_1(x: Integer): Integer; Forward; опережающее объявление функции Func_1
Function Func_2(y: Integer): Integer; описание функции
Var k: Integer; Func_2
Begin
………
k := Func_1(y); обращение к функции Func_1
………
End;
Function Func_1; описание функции
Var n: Integer; Func_1 без списка формальных
Begin параметров
……….
n := Func_2(x); обращение к функции Func_2
……….
End;
Begin основная программа
……..
i := Func_1(i); обращение к функции Func_1
…….. в основной программе
End.
Примеры:
1. Составить функцию, рекурсивно определяющую значение биномиального коэффициента при 0<m<n по формулам:
= = 1, = +
Function Binom(m, n: Word): Word;
Begin
If (m=0) Or (m=n)
Then Binom := 1 выход из рекурсии
Else Binom := Binom(m, n-1) + Binom(m-1, n-1) рекурсия
End;
2. Составить функцию, рекурсивно определяющую максимальный элемент в заданной части целочисленного массива An , начиная с k-го и до n-го элемента:
Const n = 100;
Type TArray = Array [1..n] Of Integer;
………………………………………..
Function Max_element(a: TArray; k,n: Word): Integer;
Var temp : Integer;
Begin
If (k=n)
Then Max_element := a[n]
Else
Begin
temp := Max_element(a, k+1, n);
If (a[k] > temp)
Then Max_element := a[k]
Else Max_element := temp
End;
End;
Особенности рекурсии:
· использование рекурсивной формы организации алгоритма выглядит изящнее итерационной и дает более компактный текст программы,
· недостатки рекурсии состоят в следующем:
1. если глубина рекурсии велика, то программа будет требовать во время исполнения много памяти, что может привести к переполнению стека,
3. рекурсивные алгоритмы, как правило, выполняются более медленно,
· при рекурсивном программировании велика вероятность ошибок, вынуждающих программиста к перезагрузке компьютера.
Таким образом, если у программиста есть возможность выбора между итерацией и рекурсией, то предпочтительным выбором является итерация.
В целях повышения безопасности работы рекомендуется:
· для включения проверки переполнения стека необходимо использовать директиву компилятора {S+},
· для включения проверки диапазона необходимо использовать директиву компилятора {R+},
· в начале каждой рекурсивной процедуры или функции поместить строку
If KeyPressed Then Halt.Она позволяет при зависании программы выйти из нее без перезагрузки компьютера, просто нажав любую клавишу.
Процедуры
С математической точки зрения функция выполняет только одно действие – по значению аргументов – фактических параметров вычисляет единственное значение, присваиваемое имени функции. Еще раз напомню, что в функции не рекомендуется использовать параметры-переменные. Если необходимо одновременно вычислить несколько значений, то функцию использовать нельзя.
В этих случаях используют процедуру, которая позволяет одновременно вычислять несколько значений, присваиваемых различным переменным или элементам структур данных.
Как и функция, процедура располагается в вызывающей программе после раздела описания переменных Var и состоит из заголовка, блока описаний и блока операторов.
Заголовок записывается как первая строка процедуры и начинается словом Procedure, за которым следует ее имя. После имени процедуры в скобках перечисляются имена и типы формальных параметров (аргументов процедуры). Заголовок заканчивается точкой с запятой:
Procedure Proc(n,m: Integer; a: Real; Var k: Integer; Var s, d: Real);
Описан заголовок процедуры Proc, зависящей от двух аргументов (входных параметров) целого типа n, m и аргумента a вещественного типа. Выходные (вычисляемые) параметры: переменная k целого типа и переменные s и d вещественного типа.
Допускаются процедуры без списка формальных параметров:
Procedure Zagolovok;
Begin
WriteLn(‘Группа ИС-09’);
WriteLn(‘Студент Иванов Иван’);
End;
В отличие от функций, использующих в качестве аргументов только параметры-значения, не изменяющиеся после выхода из функции, процедуры в качестве выходных (вычисляемых) параметров используют параметры-переменные. Любые операции над формальными параметрами-переменными внутри процедуры выполняются и над соответствующими фактическими параметрами-переменными. Поэтому формальному параметру-переменной должна соответствовать фактическая переменная, а не константа или выражение. В заголовке процедуры выходные параметры-переменные перечисляются в скобках после слова Var с указанием своего типа, причем для каждого нового типа это слово должно повторяться.
В остальном структура процедуры не отличается от структуры программы на Паскале и может включать в себя следующие разделы:
· описания меток Label
· определения констант Const
· определения типов Type
· описания переменных Var
· описания процедур и функций Function, Procedure
· операторов процедуры Begin … End;
Переменные, описанные в разделе Var процедуры или указанные в ее заголовке, считаются локальными, все остальные – глобальными. Локальные переменные существуют только в процедуре, в которой они описаны, и после выхода из процедуры исчезают.
Пример: описать процедуру, обменивающую значениями две переменных целого типа:
Procedure Swap(x, y: Integer);x и y – входные параметры-значения
Var temp: Integer; temp – локальная переменная
Begin
temp := x; реализация алгоритма
x := y; циклического обмена
y := temp;
End;
Эта процедура ничего не делает: в списке формальных параметров указаны параметры-значения. Правильное описание с использованием параметров-переменных:
Procedure Swap(Var x, y: Integer);x и y – входные параметры-
Var temp: Integer; переменные
Begin
temp := x;
x := y;
y := temp;
End;
Обращение к процедуре в вызывающей программе производится по ее имени, за которым в скобках перечисляются фактические параметры, соответствующие формальным параметрам процедуры по количеству, типам и порядку следования:
Program Primer;
Uses CRT;
Var a, b: Integer; a и b – переменные основной программы (глобальные)
Procedure Swap(Var x, y: Integer);x и y – входные параметры-
Var temp: Integer; переменные
Begin
temp := x;
x := y;
y := temp;
End;
Begin
ClrScr;
a := 3;
b := 5;
Swap(a, b); обращение к процедуре
WriteLn(‘a=’,a);
WriteLn(‘b=’,b);
ReadLn;
End.
На экран будет выведено:
a=5
b=3
Правила построения и использования процедур не отличаются от правил построения и использования функций, в том числе и относительно рекурсии.
Как уже отмечалось в правилах формирования подпрограмм-функций, для передачи в подпрограмму массива необходимо предварительно определить его в разделе описания типов, то есть явно задать количество его элементов и их тип. Значит, подпрограмма, формальным параметром которой является массив из десяти чисел, не сможет работать с массивом из пятнадцати чисел. Это неудобно, поэтому в списке формальных параметров подпрограмм разрешается определять открытые массивы.
Открытые массивы – это вектора, состоящие из элементов любого типа, кроме файлового. На место открытого массива в качестве фактического параметра можно передавать вектор любого размера, состоящий из элементов того же типа, что и элементы открытого массива:
Procedure Summ(a: Array Of Integer; Var summa: Integer);
Var i: Word;
s: Integer;
Begin
s:= 0;
For i:=0 To High(a) Do нумерация элементов начинается с нуля!
s:= s + a[i]; номер последнего элемента определяетсяс
summa:= s; помощью функции High
End;
Передавать открытый массив можно как значение, переменную или константу. Поскольку тип индексов массива не указывается, используется соглашение, по которому эти элементы нумеруются с нуля. Номер последнего элемента в массиве можно определить с помощью функции High.
Примеры: задать целочисленный вектор a длиной n элементов случайным образом с элементами от m_min до m_max..
1. Определить минимальный min и максимальный max элементы вектора и их индексы i_min, i_max. Результаты сохранить в текстовом файле out_min_max.txt:
Program Primer_1;
Uses CRT;
Const n = 10; размер вектора
m_min = -50; диапазон значений
m_max = 50; элементов вектора
Type TVector = Array [1..n] Of Integer;
Var i, i_min, i_max: Word;
min, max: Integer;
a : TVector;
out_min_max: Text; файловая переменная
Procedure Init(elem_min, elem_max: Integer; Var Vector: Array Of Integer); используется открытый массив Vector
Var i: Word;
Begin
Randomize; запуск генератора случайных чисел
For i:=0 To High(Vector) Do задание элементов массива случайными числамив диапазоне от elem_min до elem_max
Vector[i]:=elem_max - Random(elem_max - elem_min +1);
End;
Procedure Min_max(m: Word; vector: TVector; Var min, max: Integer; Var i_min, i_max: Word); используется массив vector типа TVector
Var i: Word;
Begin
min:=vector[1]; перед поиском минимального и максимального элементов
max:=vector[1]; массива за таковые принимается первый элемент i_min:=1; массива
i_max:=1;
For i:=2 To m Do поиск начинаем со второго элемента
Begin
If (vector[i] < min) Then
Begin
min:=vector[i];
i_min:=i;
End;
If (vector[i] > max) Then
Begin
max:=vector[i];
i_max:=i;
End;
End;
End;
Begin
ClrScr;
Assign(out_min_max,’d:\User\out_min_max.txt’);
ReWrite(out_min_max); открытие текстового файла для записи
Init(m_min, m_max, a); инициализация массива
Writeln(out_min_max, ‘Исходный вектор:’);
For i:=1 To n Do
Write(out_min_max, a[i]:5);
WriteLn(out_min_max);
Min_max(n, a, min, max, i_min, i_max); поиск элементов массива
WriteLn(out_min_max, ‘min=’, min);
WriteLn(out_min_max, ‘i_min=’, i_min);
WriteLn(out_min_max, ‘max=’, max);
WriteLn(out_min_max, ‘i_max=’, i_max);
Close(out_min_max); закрытие текстового файла
ReadLn;
End.
Результат работы программы:
Исходный вектор:
-1 -19 -19 -35 50 26 -47 17 1 -7
min=-47
i_min=7
max=50
i_max=5
2. Отсортировать элементы массива методом простого выбора: в массиве отыскивается минимальный элемент и меняется с первым элементом массива, из оставшихся элементов снова находится минимальный и меняется со вторым элементом, и так далее. Последний, самый большой элемент, сам станет на свое место. Результаты сохранить в текстовом файле out_sort.txt:
Program Primer_2;
Uses CRT;
Const n = 10; размер массива
m_min = -50; диапазон значений
m_max = 50; элементов массива
Type TVector = Array [1..n] Of Integer;
Var i: Word;
a : TVector;
out_sort: Text; файловая переменная
Procedure Init(m: Word; elem_min, elem_max: Integer; Var vector: TVector);
Var i: Word;
Begin
Randomize; запуск генератора случайных чисел
For i:=1 To m Do задание элементов массива случайными числами
в диапазоне от elem_min до elem_max
vector[i]:=elem_max - Random(elem_max - elem_min +1);
End;
Procedure Sort_vybor(m: Word; Var vector: TVector);
Var i, j, k: Word;
temp: Integer;
Begin
For i := 1 To m-1 Do
Begin
k := i;
temp := vector[i];
For j := i + 1 To m Do
If (vector[j] < temp) Then
Begin
temp := vector[j];
k:= j;
End;
vector[k] := vector[i];
vector[i] := temp;
End;
End;
Begin
ClrScr;
Assign(out_sort,’d:\User\out_sort.txt’);
ReWrite(out_sort); открытие текстового файла для записи
Init(n, m_min, m_max, a); инициализация массива
Writeln(out_sort, ‘Исходный вектор:’);
For i:=1 To n Do
Write(out_sort, a[i]:5);
WriteLn(out_sort);
Sort_vybor(n, a); сортировка элементов массива
Writeln(out_sort, ‘Отсортированный вектор:’);
For i:=1 To n Do
Write(out_sort, a[i]:5);
WriteLn(out_sort);
Close(out_sort); закрытие текстового файла
ReadLn;
End.
Результат работы программы:
Исходный вектор:
-15 -31 12 -10 50 -27 36 -29 2 5
Отсортированный вектор:
-31 -29 -27 -15 -10 2 5 12 36 50
3. Отсортировать элементы массива методом простого обмена (методом пу