Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Практикум по основам программирования. Массивы. Строки. Подпрограммы. Учебное пособие
.pdf
2) подпрограмма должна решать самостоятельную задачу по прин-
ципу одна подпрограмма – одна функция. Например, ввод линейного
массива, вычисление произведения матриц, поиск наибольшего элемента в одномерном массиве и т. д.
3) подпрограмма должна возвращать управление в ту часть про-
граммы, которая ее вызвала;
4) подпрограмма может вызывать другую подпрограмму, в том
числе и саму себя, в последнем случае имеем дело с рекурсивной подпрограммой;
5) подпрограмма должна настраиваться на входные данные вызы-
вающей части и возвращать в вызывающую часть результат своих вычислений;
6) размер подпрограммы желательно ограничивать одной-двумя
страницами исходного текста.
Каждой подпрограмме дается имя, которое используется для акти-
вации действий, описанных в подпрограмме (вызова подпрограммы) в
тех местах программы, где необходимо их выполнить. В точке вызова
подпрограммы управление передается ее первой команде. Выполнение
подпрограммы завершается действиями по возвращению управления в
точку вызова – т. е. команде, непосредственно следующей за точкой
вызова, называемой точкой возврата.
Таким образом, в структурированной программе между программ-
ными единицами устанавливается отношение вызываемаявызывающая.
Синтаксически подпрограмма состоит из:
– определения подпрограммы,
– обращения к подпрограмме.
Определение подпрограммы:
<определение подпрограммы> ::= <заголовок подпрограммы>
<тело подпрограммы>
Тело подпрограммы является описанием того частичного алгорит-
ма, который объявляется подпрограммой.
Заголовок подпрограммы задает ее имя и определяет ее входные и
выходные данные.
Обращение к подпрограмме служит для ее активации.
51

Большинство языков программирования допускает подпрограммы
двух видов – подпрограммы-процедуры и подпрограммы-функции
(или просто процедуры и функции). В отличие от процедуры функция
реализует функциональную зависимость, у которой обязательно должен быть хотя бы один результат. Кроме того, результат функции может быть, как правило, простого типа.
Функции языка C
Программа на языке C это совокупность подпрограмм – функций (в
дальнейшем просто функций), среди которых выделяется одна обязательная (главная) с именем main. Остальные функции вводятся в
структуру программы для улучшения ее структурированности. Их выполнение инициируется прямо или косвенно вызовами из функции
main.
В простом случае определение функции на языке C:
<Определение функции> ::= <заголовок функции> <блок>
<заголовок функции> <составной оператор>
Таким образом, тело функции задается блоком (блок – это после-
довательность спецификаций переменных и операторов, заключенная в
фигурные скобки) или составным оператором.
<Заголовок функции> :: =
< тип результата функции> <имя функции> ( [ <cписок формаль-
ных параметров> ] )
| void <имя функции> ( [ <cписок формальных параметров> ] )
В заголовке функции задается тип ее результата, если функция
имеет возвращаемый результат (будем называть его основной результат), иначе тип void. Функция с типом void является подпрограммойпроцедурой. Список формальных параметров, если он не опущен, содержит перечисленные через запятую спецификации формальных параметров. В теле функции, если она возвращает результат, обязательно
должен быть хотя бы один оператор возврата в точку вызова:
52

return <выражение>;
Выражение определяет возвращаемый (основной) результат, его
тип описан в заголовке функции. Если функция не возвращает никакого значения (т.е. имеет тип void), оператор возврата может опускаться.
Обращение к функции, возвращающей основной результат, это
первичное выражение вида:
<имя функции>(<список фактических параметров>)
или <имя функции> ( ) , если у функции нет формальных параметров.
Вызов такой функции является операндом какого-либо выражения.
Синтаксически обращение к функции, не возвращающей результат,
задается также, но в этом случае обращение – это оператор вызова:
<имя функции>(<список фактических параметров>);
или <имя функции> ( );
Одним из важных моментов при организации подпрограмм являет-
ся задание данных, над которыми будут выполняться действия подпрограммы. Данные в подпрограмму можно передавать двумя способами:
1) используя для этого глобальные объекты, 2) используя формальные
параметры.
Функции без параметров
Если используется только первый способ, то в определении под-
программы (ее теле) непосредственно используются данные определенные вне тела функции. Такие подпрограммы не имеют параметров.
Пример определения функции без параметров (задача нахожде-
ния наибольшего значения среди двух чисел):
int MAX1( )
{
return a > b ? a : b;
}
Функция MAX1 может выполнять действия только над переменны-
ми a и b (входные данные функции). Переменные a и b должны быть
определены вне функций и называются внешними или глобальными
53

переменными. Тело функции MAX1– составной оператор. Обращение к
функции MAX1 – операнд выражения, например: x = MAX1 ( ); Переменной x будет присвоено значение функции MAX1, т. е. наибольшее
из значений a и b.
В таких подпрограммах жестко зафиксированы объекты, над кото-
рыми выполняются действия подпрограммы. Если необходимо применить эту подпрограмму для других объектов требуется изменение самих глобальных объектов (их имен) в теле подпрограммы.
Функции с параметрами
Чтобы сделать подпрограмму более гибкой и обеспечить ее общ-
ность, данные в подпрограмму передаются через список формальных
параметров. Формальные параметры задают не какие-то конкретные
данные программы, а лишь условно определяют объекты подпрограммы. Это позволяет применять подпрограммы к различным объектам
программы, конкретизируя при каждом обращении ее данные в списке
фактических параметров. Все объекты подпрограммы можно разделить на входные данные, промежуточные и выходные. В список формальных параметров необходимо вводить только те объекты, которые
изменяются при вызове подпрограммы, т. е. входные и выходные данные.
Формальные параметры в C задаются в списке формальных пара-
метров перечислением через запятую спецификаций отдельных параметров. Спецификация каждого параметра имеет вид:
<спецификация типа> <имя параметра>
Список фактических параметров задается перечислением через за-
пятую фактических данных, над которыми функция должна выполнять
действия при данном вызове. При обращении к функции между списком формальных и списком фактических параметров устанавливается
соответствие: по взаимному расположению параметров в списках
(первому формальному параметру соответствует первый фактический
параметр и т. д.), количеству, типу (как при присваивании) и способу
связывания.
Связь между формальными и фактическими параметрами может
устанавливаться двумя способами:
54

– связь по значению – значение фактического параметра присваи-
вается формальному. Действия в подпрограмме выполняются над
формальной переменной, получившей значение фактического параметра;
– связь по адресу – фактический параметр заменяет в теле подпро-
граммы формальный, и подпрограмма получает доступ к фактическому параметру. Если говорить более точно, то формальному параметру
присваивается адрес (ссылка) фактического параметра. Значение такого формального параметра при его использовании в операциях рассматривается как адрес того объекта, над которым надо выполнить эту
операцию. Такой способ используется как для передачи входных данных, так, и, прежде всего, для выходных данных (результатов).
В C связь между формальными и фактическими параметрами уста-
навливается по значению. Фактический параметр в этом случае – выражение того же типа, что и соответствующий ему формальный. В момент вызова функции вычисляется значение фактического параметра и
присваивается формальному параметру. Такой способ позволяет передать в подпрограмму значения входных данных. Изменение формального параметра, получившего значение фактического, не приводит к
изменению фактического параметра.
Пример определения функции с входными параметрами (задача
нахождения наибольшего значения среди двух чисел):
int MAX2(int a, int b)
{
return a > b ? a : b;
}
Функция MAX2 выполняет действия над формальными перемен-
ными a и b (входные данные функции). Переменные a и b получают
значения фактических параметров при обращении к MAX2 (т. е. связь
между параметрами устанавливается по значению). Результат функции
возвращается в точку вызова при выполнении оператора return. Обращение к функции MAX2 – операнд выражения, например: x = MAX2 (n
55

+ 1, m*m ); Переменной x будет присвоено значение функции MAX2, т.
е. наибольшее из значений выражений n + 1 и m * m.
Если через список формальных параметров должен передаваться
результат функции, то формальный параметр должен быть типа указатель, а соответствующий ему фактический параметр – это выражение,
значение которого есть адрес переменной результата.
Пример определения функции (процедуры) с входными и выход-
ным параметрами (задача нахождения наибольшего значения среди
двух чисел):
void MAX3(int a, int b, int *c)
{
*c = a > b ? a : b ;
}
Функция MAX3 выполняет действия над формальными перемен-
ными a, b и с. Переменные a, b и c получают значения фактических параметров при обращении к MAX3 (т. е. связь между параметрами устанавливается по значению). Результат функции передается через формальный параметр типа указатель – с. Фактический параметр, соответствующий с – это адрес переменной, которой надо присвоить результат. При выполнении оператора присваивания, в левой части которого
стоит выражение *c (здесь * – это операция разыменования указателя),
происходит обращение к области памяти (к переменной), адрес которой является значением с. И туда помещается вычисленное значение
правой части оператора присваивания. Обращение к функции MAX3 –
оператор вызова функции, например:
MAX3(n + 1, m * m, &y);
(здесь & – это операция получения адреса переменной). Перемен-
ная y получает значение наибольшего из выражений n + 1 и m*m.
Пример определения функции с двумя результатами (задача на-
хождения наибольшего и наименьшего значений среди трех целых чисел):
56

int MAXMIN(int x, int y, int z, int *max)
{
int min;
if (x > y)
if (x > z)
{
*max = x;
if (y < z)
min = y;
else min = z;
}
else
{
*max = z;
min = y;
}
else
if (y > z)
{
*max = y;
if (x < z)
min = x;
else min = z;
}
else
{
*max = z;
min = x;
}
return min;
}
Один результат – это наименьшее значение из трех величин x, y, z,
он возвращается как основной результат функции. Второй результат –
наибольшее из x, y, z, для его возврата используется формальный параметр max. Вызов подпрограммы: int r = MAXMIN(a, b, c, &x);
57

Вариант 1:
Вариант 2:
void sqrarray (float a[ ], int n)
{
for (int i = 0; i < n; i++)
a[i] *=a[i];
}
void sqrarray (float *a, int n)
{
for (int i = 0; i < n; i++)
a[i] *= a[i];
}
Вариант 3:
Вариант 4:
void SquareArray (float *a, int n)
{
for (i = 0; i < n; i++)
*(a + i) *= *(a+ i);
}
void sqrarray (float *a, int n)
{
for (i = 0; i < n; i++)
*a *= *a++;
}
Функции с параметрами типа массив
Параметром функции может быть величина сложного типа, напри-
мер массив. В этом случае в функцию передается адрес массива.
Пример определения процедуры с параметром типа массив (за-
дача возведения в квадрат элементов массива):
Все четыре варианта равнозначны, но в первом варианте формаль-
ный параметр a задан более наглядно, он имеет тип массив. Во 2-4 вариантах используется то, что имя массива является указателем на начало массива, поэтому формальный параметр задан как параметр типа
указатель. В 4-м варианте изменение параметра a (a++) приводит к
вычислению указателя (адреса) на очередной элемент массива. Вызов
подпрограммы sqrarray:
1) const int n = 20; float x [n]; sqrarray (x, n);
Все 20 элементов массива x будут возведены в квадрат.
2) const int n = 20; float x [n]; sqrarray (x, n / 2);
Первые 10 элементов x будут возведены в квадрат.
58

3) const int n = 20; float x [n]; sqrarray (&x[10], 10);
Последние 10 элементов x будут возведены в квадрат.
Пример определения процедуры с параметром типа двумерный
массив (задача поиска строки квадратной матрицы с наибольшей сум-
мой элементов):
const int N =25;
void matr(int a[ ][N], int n, int b[ ])
{
int i, j, k, s, max;
for ( s = 0, i = 0; i < n; i++ )
s += a[0][i];
max = s; k = 0;
for ( i = 0; i < n; i++ )
{
s = 0;
for ( j = 0; j < n; j++ )
s += a[i][j];
if (s > max)
{
max = s;
k = i;
}
}
for ( i = 0; i < n; i++ )
b[i] = a[k][i];
}
Вызов процедуры:
main ( )
{
int d [N][N], c[N], m;
. . .
matr (d, m, c); // Поиск строки среди всех строк матрицы
59

matr (d[2], m-2, c); // Поиск строки среди строк матрицы с
// номерами от 2 до m - 1
matr (&d[m/2][0], m/2, c); // поиск строки среди строк матрицы с
// номерами от m/2 до m-1
}
Пример программы с функциями, параметры которых типа
массив (задача вычисления произведения матриц Z
n×n2
= X
n×n1∙Yn1×n2
#include <stdio.h>
#include <conio.h>
const int n = 15;
const int n1= 10;
const int n2 = 20;
void MULT(float a[ ][n1], float b[ ][n2], float c[ ][n2],
int n, int m, int p)
{
int i, j, k ;
float s;
for ( i = 0; i < n; i++ )
for ( j = 0; j < p; j++ )
{
for ( s = k = 0; k < m; k++ )
s += a[i][k] * b[k][j];
c[i][j] = s;
}
}
void input(float a[ ][m], int n, int m)
{
int i, j;
for ( i = 0; i < n; i++ )
for ( j = 0; j < m; j++ )
scanf("%f ", &a[i][j]);
}
)
60
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
