Глава 4 Средства модульного программирования
С увеличением объема и сложности программ, появилось большое
количество задач, выполнение которых повторяется как внутри одной
программы, так и в других программах.
Для улучшения эффективности программ, в языках высокого уровня были
разработаны
средства
модульного
программирования,
предусматривающие использование подпрограмм.
Подпрограмма – это относительно самостоятельный фрагмент
алгоритма, соответствующим образом оформленный и снабженный
именем.
В зависимости от способа описания и вызова, известны подпрограммы двух
видов процедуры и функции.
Процедуры предназначены для выполнения некоторых действий (например,
печать строки), а функция – позволяет получить некоторую величину,
которую возвращает в качестве результата.
Однако, принципы программирования С++ основаны на понятии функции.
Поэтому, в С++ нет процедур, как элементов языка, однако средства
языка позволяют создавать функции, которые не возвращают значения и
реализуют конструкцию, аналогичную процедурам.
1

4.1 Функции С++.
При программировании на С++ функция – это основное понятие.
1.
Каждая программа обязательно должна включать
единственную функцию с именем main (главная функция).
2.
В программу может входить произвольное количество
функций, выполнение которых прямо или косвенно
инициируется функцией main.
3.
Для доступности в программе, функция должна быть в ней
определена или описана до первого вызова.
4.
В определении функции указывается последовательность
действий, выполняемых при ее вызове, имя функции, тип
функции (тип возвращаемого ею результата ) и, если
необходимо, список параметров (для обмена данными между
подпрограммами.
Таким образом, для использования функций необходимо знать, как
их можно определять, как к ним обращаться и как
устанавливать связь между функцией и программой, ее
вызывающей.
2

4.1.1 Описание функции
([])
{ [< Объявление локальных переменных и констант >]

Объявление функции}
прототип
Пример:

int max(int a, int b);
int max(int a, int b)
Заголовок
функции
{ if (a>b) return a;
else return b;
Тело функции
}

Описание
функции

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

4.1.2 Передача данных в подпрограмму
Подпрограмма может Локальны
е данные
получать данные
двумя способами:
а) неявно – с
использованием
глобальных
Обращение к
переменных;
локальной
б) явно – через
переменной
параметры.
Неявная передача:
1) приводит к большому
количеству ошибок;
2) жестко связывает
подпрограмму и
данные.
Обращение к
глобальной
переменной

Глобальные переменные
int a,c,k;
int sum(int a,int b)
{int k,I,j;

k=c+a;
}
int max(int,int);
void main()
{int i,j,p;

p=max(k,c);
}

Обращение к
глобальной
переменной

Прототип
функции max

Обращение к
функции max

Обращение к
глобальным
переменным

int maxl(int b,int c);
Перекрывает глобальную
{int a;

a=sum(c,b);
Обращение к
k=a;
4
функции sum
}

4.1.3 Способы передачи параметров
Передача по значению
Основная
программа

Стек

Копии
параметров

Подпрограмма

Работа с
копиями
параметров

Параметры - значения – в
подпрограмму передаются копии фактических параметров, и никакие изменения этих
копий не возвращаются в вызывающую программу.

Передача по ссылке
Основная
программа

Стек

Адреса
параметров

Подпрограмма

Работа с
параметрами
через адреса

Параметры - переменные – в подпрограмму передаются адреса фактических параметров, соответственно все изменения этих параметров в подпрограмме происходят с
переменными основной программы.
5

4.1.4 Формальные и фактические параметры
Формальными называются параметры, определенные в заголовке
функции при ее описании .
Каждый формальный параметр не только перечисляется
(именуется), но и специфицируется (для него задается тип) .
Совокупность формальных параметров определяет сигнатуру
функции.
Сигнатура функции зависит от количества параметров, их типа и
порядка размещения в спецификации формальных параметров.
Спецификация формальных параметров это либо пусто, либо void
либо список отдельных параметров.
Примеры:
Формальные
параметры a b
float max(float a,float b){….}
int fun1()
Формальные параметры
{…..}
отсутствуют(пусто)
char F2(void)
Формальные параметры
{…..}
отсутствуют

6

Формальные и фактические параметры(2)
Фактическими называются параметры, задаваемые при вызове функции.
Формальные и фактические параметры должны совпадать:
- по количеству;
- по типу;
- по порядку следования.
Однако, имена формальных и фактических параметров могут не совпадать.
Пример:
Формальные
int k,l,n=6; float d=567.5,m=90.45
параметры

void fun2(int a,float c,float b){….}
fun2(n,d,m);

// Правильный зов

fun2(4,8.7);

Фактические
параметры

// Ошибка в количестве параметров

fun2(4.67, 5,7);
fun2(3,m,d);

// описание функции fun2

// ошибка в типах параметров

// ошибка в порядке следования контролируется
пользователем

7

Формальные и фактические параметры(3)
Если в качестве параметров передаются параметры значения, то в
качестве фактических можно передавать переменные, константы
и выражения.
Пример:
Формальные параметры

int k,l,n=6;
float d,m=90.45
int fun1(int a,float b){….}
//

// описание функции fun1

вызовы функции

k=fun1(n,m);

// фактические параметры переменные

printf(“f=%5d”,fun1(5,78.9));
l=fun1(2-n%3,m/k-34.78);

// фактические параметры константы
// фактические параметры выражения
8

Формальные и фактические параметры(4)
1. Все параметры передаются по значению!
2. Если надо вернуть значение, то передают
указатель или ссылку:
а) указатель
void prog(int a, int *b) { *b=a; } // Будут описаны дальше
вызов: prog(c,&d);
б) ссылка
void prog(int a, int &b) { b=a; }
вызов: prog(c, d);
3. Если надо запретить изменение параметра,
переданного адресом, то его описывают const
int prog2(const int *a) { …}

9

Формальные и фактические параметры(5)
Понятие ссылки
В С++ ссылка определена как другое имя уже существующего
объекта. Основные достоинства ссылок проявляются при работе
с функциями.

&
В соответствии с синтаксисом определение может быть:

& =
или
& ( )
В качестве выражения может быть имя некоторого объекта,
имеющего место в памяти.
Значением ссылки после инициализации становится адрес этого
L
объекта.
SL
Пример определения ссылки:
127
int L=127;
int &SL=L; //Значением ссылки SL является адрес переменной L

10

Формальные и фактические параметры(6)
Если используется подпрограмма функция, которая возвращает в
вызывающую подпрограмму формируемое значение, то в теле
функции обязательно наличие оператора возврата, передающего
это значение .

int max(int a,int b)
{ if (a>b) return a
else
return b
}
вызов
k=max(i,j);
Если используется подпрограмма процедура, то она должна
возвращать результаты через параметры. В этом случае
необходимо использовать ссылки или указатели.

void swap (int &a, int &b)
{ int t;
t=a;a=b;b=t;
}
вызов swap(i,j);

11

Определение площади четырехугольника
a
b

e
d
c

Площадь четырехугольника
определяем как сумму
площадей треугольников.
Площадь треугольника
определяем по формуле
Герона.
В качестве подпрограммы
реализуем вычисление
площади треугольника,
поскольку эта операция
выполняется два раза с
разными параметрами.

12

Схемы алгоритмов подпрограмм
Подпрограмма-функция
Начало алгоритма
подпрограммы

Подпрограмма-процедура
Формальный параметр-переменная
в заголовке на схеме не выделяется

Формальные
параметры

Вызов
процедуры

Завершение
подпрограммы
Фактические
параметры

Фактическое
значение
параметрапеременной

13

Функция

Глобальные
переменные

// Ex4_1.cpp :
#include "stdafx.h"
Тип
возвращаемого
#include
значения
#include
float a,b,c,d,e;
float stf(double x,double y,double z)
{double p;
Локальная
p=(x+y+z)/2;
переменная
return sqrt(p*(p-x)*(p-y)*(p-z));
}
Вычисление
int main(int argc, char* argv[])
возвращаемого
{ puts("Input side a,b,c,d");
значения
scanf("%f %f %f %f",&a,&b,&c,&d);
puts("Input diagonal e");
scanf("%f",&e);
printf("A= %5.2f , A=%5.2f , C=%5.2f , D=%5.2f , E=
%5.2f \n",a,b,c,d,e);
printf("PLOSHAD= %8.4f\n",stf(a,b,e)+stf(c,d,e));
return 0;
Вызов функции14
из
}
выражения

Функция не возвращающая результата(процедура)
// Ex4_2.cpp
Глобальные
переменные
#include "stdafx.h"
#include
#include
Возвращаемое
Значение-ссылка
float a,b,c,d,e,S1,S2;
void stp(float x,float y,float z,float &S)
{float p;
Локальная
переменная
p=(x+y+z)/2;
S=sqrt(p*(p-x)*(p-y)*(p-z));}
int main(int argc, char* argv[])
{ puts("Input side a,b,c,d");
scanf("%f %f %f %f",&a,&b,&c,&d);
puts("Input diagonal e");
Вызов
scanf("%f",&e);
процедуры
stp(a,b,e,S1); stp(c,d,e,S2);
printf("PLOSHAD= %8.4f\n",S1+S2);
return 0;}
15

Пример использования функций
Пример.
Написать программу вычисления корня функции y=x2*cos(x)-x+1 на
отрезке a,b c точностью eps методом половинного деления.
root(a,b,eps)

начало

x=(a+b)/2

a,b,eps
f(a)*f(b)
Программа вычисления корня функции y=x2*cos(x)-x+1
Функция для вычисления
// Ex4_3.cpp
F1=x2*cos(x)-x+1
#include "stdafx.h"
#include
#include
float F1(float x)
{ return x*x*cos(x)-x+1;}
float root(float a,float b, float eps)
{ float fx,fa,fb,x;
x=(a+b)/2;
Список формальных
fx=F1(x);
параметров
while(fabs(fx)>=eps)
{ fa=F1(a); fb=F1(b);
Локальные
if (fx*fa
Программа вычисления корня функции y=x2*cos(x)-x+1(2)
int main(int argc, char* argv[])
{float xn,xk,eps;

Проверка
существования
корня на отрезке

puts("Input Xn,Xk,eps");
scanf("%f %f %f",&xn,&xk,&eps);
if (F1(xn)*F1(xk)
Примеры использования подпрограмм
Пример. Написать программу вычисления суммы ряда с заданной
точностью.
k=?

S=? (-1)i*i/xi);

-1/x+2/x2-3/x3+4/x4-….

i=1

R1=-1/x;

x>1

R2=-R1*2/(1*x);
R3=-R2*3/(2*x);
…..
Ri=-Ri-1*i/((i-1)*x);

19

Примеры использования подпрограмм (2)
// Ex4_4.cpp
#include "stdafx.h"
Формальные
параметры
#include
#include
float sumr(float x,float eps)
{int i; float s,r;
локальные
данные
s=0;
r=-1/x;
i=1;
while(fabs(r)>eps)
{ s+=r;
i=i+1;
r=-r*i/((i-1)*x);
}
return s;

Возвращаемое
значение

sumr(x,eps)
s=0
r=-1/x
i=1
нет
|r|>eps
да
s=s+r
i=i+1

return s

r=-r*i/((i-1)*x)

}
возврат

20

Примеры использования подпрограмм (3)
начало
Ввод x,eps
Вывод sumr(x,eps)
конец

int main(int argc, char* argv[])
{ float x,eps;
puts("Input x,eps");
scanf("%f %f",&x,&eps);

Вызов функции

puts("Result");

Фактические
параметры

printf("SUMMA Ryada. = %8.7f\n",sumr(x,eps));
return 0;
}

21

Примеры использования подпрограмм (4)
//Ex4_4a.cpp Подпрограмма - процедура
sumrp(x,eps,s,k)
#include "stdafx.h"
Формальные
параметры
#include
s=0
#include
void sumrp(float x,float eps,
r=-1/x
float& s,int & k)
{float r;
k=1
s=0;
локальные
нет
данные
r=-1/x;
|r|>0
k=1;
да
while(fabs(r)>eps)
s+=r
{ s+=r;
k=k+1;
k=k+1
r=-r*k/((k-1)*x);
}
}

Возвращаемые
значение

r=-r*k/((k-1)*x)

возврат

22

Примеры использования подпрограмм (3)
начало
Ввод x,eps
Sumrp(x,eps,s,i)
Вывод s

Вызов функции

конец

int main(int argc, char* argv[])
{ float x,eps,sm;int n;
puts("Input x,eps");
scanf("%f %f",&x,&eps);
smrp(x,eps,sm,n);
printf("SUMMA Ryada. = %8.7f\n",sm);
printf(“Kol. Iteraciy = %8d\n",n);
return 0;
}

Фактические
параметры

23

4.2 Передача массивов в подпрограммы
При решении многих задач для хранения и обработки данных
используются массивы.
Как уже отмечалось, существуют приемы, позволяющие
осуществлять различную обработку массивов.
Такие приемы реализуют универсальные алгоритмы, которые
подходят для широкого круга задач, отличающихся только типами и
размерами обрабатываемых массивов.
Вполне естественно, что многие из алгоритмов целесообразно
оформить в виде функции.
Массивы можно использовать в функции двояко:
- их можно описать в теле функции;
- массивы могут быть аргументами (параметрами функции) .
В силу специфики организации массивов в С++, массивы передаются
в подпрограмму как параметры переменные, однако, без
использования ссылок (особенности организации массивов будет
рассмотрены далее).
24

Параметры-массивы (2)
В С++ отсутствует контроль размерности массива по первому
индексу при передачи этих массивов в качестве параметров!

а) int x[5] ? int x[]- размерность
б) int
Пример:

проверяться не будет
y[4][8] ? int y[][8] – будет
проверяться размерность
массива по второму индексу
Формальные
параметры - массивы

void summa(const float x[][3], float y[],int n)
{ int i,j;
for(i=0;i
Примеры использования параметров массивов
Пример. Функция вычисления суммы элементов массива.

26

Программа
// Ex4_5.cpp
#include "stdafx.h"
#include
Объявление
int sum(int a[],int n)
параметра
массива
{int i,s;
s=0;
for(i=0;i
Примеры использования параметров массивов
Пример. Написать программу удаления из матрицы l строки и k столбца с
использованием подпрограмм.
#include "stdafx.h"
Формальные
#include
параметры
#include
#include
#include
#include
void delsts(int a[][10],int & n,int & m,int l,int k)
{ int i,j;
for(i=l;i
Пример использования параметров массивов
int main(int argc, char* argv[])
{ int matr[10][10],n,m,l,k,i,j;
puts("Input n,m
4.3 Классы памяти
В С++ переменные могут быть описаны как вне, так и внутри функций.
При этом каждой переменной присваивается класс памяти.
Класс памяти определяет
- размещение объекта в памяти (место описания);
- область действия (доступность переменной из функций);
- время жизни переменной (как долго она находится в памяти).
Есть 4 ключевых слова, используемые для описания классов памяти:

extern (внешние), auto (автоматические), static
(статические), register (регистровые).

1. Автоматические переменные (auto)
main()

{auto int a;…}
abc()
{auto int a;…}

Две разные
переменные

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

Классы памяти(2)
2. Внешние переменные (extern)

extern int a;
main()
{extern int a;…}
abc()
{extern int a;…}
bcd()
{int a;…}

Одна и та же
переменная
Автоматическая
переменная, которая
внутри функции
перекрывает внешнюю

Место описания – глобальная память, область действия – все
файлы программы, где она определена, время действия –
существует с момента вызова программы и до возврата
управления операционной системы.
По умолчанию, если переменная описана вне функции, то она –
внешняя.
31

Классы памяти(3)
3. Статические переменные (static)
abc()
В отличие от автоматической
{ int a=1; static int b=1;
статическая переменная
… a++; b++; …}
увеличивается с каждым
вызовом

Локальная переменная.
При каждом вызове
начинается с 1

Принимает значение 1 только первый раз.
При каждом следующем вызове начинается
с последнего значения

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

32

Классы памяти (4)
4. Внешние статические переменные (extern static)
int a;
Внешняя переменная a доступна во
всех файлах программы, а внешняя
extern static int b;
статическая b только в том файле,
где она описана

Файл1
int a;
static int b;
main(){b=…}
asd()
{...b=a;…}

Файл2
ff(){a=7;…}
F3(){
d=a;….
}
F5(){a=6...}

Место описания – глобальная
память,
область действия – внутри
всех функций того файла
программы, где она
определена,

время действия – существует
с момента вызова программы
Переменная a доступна обоим файлам, и до возврата управления
операционной системы.
переменная b – только первому
33

Классы памяти (5)
5. Регистровые переменные (register)
register int a;

По доступу аналогична
автоматической, но по
возможности размещается в
регистрах

Регистровые переменные аналогичны автоматическим, но по
возможности их нужно размещать в регистровой памяти.
Если регистры заняты, то переменная размещается аналогично
переменной auto.
Общие рекомендации:
- По возможности следует использовать автоматические
переменные.
- Внешние и статические переменные сложных структурных типов
можно инициализировать.
34

4.4 Дополнительные возможности С++
1. Подставляемые функции

inline int abs(int a) {return a>0?a:-a;}
При таком описании функции код подставляемой функции вставляется
в то место программы, откуда она вызывается.
Если вставка не возможна, то вызов идет по стандартному механизму.
Однако, на использование inline функции есть ограничения:
- функция не должна быть большой;
- не должна содержать циклов ;
- не должна содержать операторов переходов или переключателей ;
- не может быть рекурсивной ;
- не должна вызываться более одного раза в выражении ;
- не должна вызываться до определения.
35

Дополнительные возможности С++(2)
2. Переопределяемые функции
В С++ функции могут различаться по сигнатуре (списку, количеству
и типам параметров) и типу возвращаемого параметра.
Поэтому можно определить несколько вариантов одной и той же
функции с одинаковыми именами, но с разными списками
параметров (сигнатурами).
При вызове, компилятор по сигнатуре определяет нужный аспект
функции и вызывает нужную реализацию функции.

int lenght(int x,int y)
{return sqrt(x*x+y*y);}
int lenght(int x,int y,int z)
{return sqrt(x*x+y*y+z*z);}
36

Пример переопределения функции
Пример. Написать программу для

определения максимального элемента float max_elem(int n,float
массива произвольного размера и типа. array[])
{float max;
// Ex4_15.cpp
max=array[0];
#include "stdafx.h"
#include
for(int i=1;imax)
{int max;
max=array[i];
max=array[0];
return max;
for(int i=1;imax)
double max_elem(int n,double
max=array[i];
array[])
return max;
{double max;
}
max=array[0];
long max_elem(int n,long array[])
{long max;
for(int i=1;imax)
for(int i=1;imax)
return max;
max=array[i];
}
return max;
37
}

Пример переопределения функции(2)
int main(int argc, char* argv[])
{
int x[]={10,20,30,40,50,25};
long f[]={12L,34L,10L,44L,8L};
float y[]={0.1,0.003,0.5,0.7,0.009};
double z[]={0.0007,0.00008,0.0002,0.00004};

Вызов
функции

printf(" max_elem(6,x)=%4d\n",max_elem(6,x));
printf(" max_elem(5,f)=%6d \n",max_elem(5,f));
printf(" max_elem(5,y)=%5.3f\n",max_elem(5,y));
printf(" max_elem(4,z)=%7e \n",max_elem(4,z));
return 0;
}
38

Дополнительные возможности С++(3)
3. Параметры функции, принимаемые по умолчанию
void InitWindow(int xSize=80, int ySize=25,
int barColor=BLUE,
Список параметров
по умолчанию
int frameColor=CYAN){...}
Примеры вызова:
Все параметры берутся по
умолчанию
InitWindow();
Меняются размеры окно,
остальные - по умолчанию

InitWindow(20,10);
Если нужно изменить например цвет, то все
предыдущие надо повторить.
Меняем цвет рамки окна,
InitWindow(80,25,GREEN);
остальное – по умолчанию
InitWindow(80,25,BLUE,GREEN);

Меняем цвет фона окна,
остальное - по умолчанию
39

4.4 Аргументы командной строки
int main( int argc,char *argv[ ]) { ... }
где argc - количество параметров командной
строки +1;
argv[0] - может содержать полное имя файла
программы, например “A:\ddd.exe”.
argv[1] - содержит первый параметр из
командной строки;
argv[2] - содержит второй параметр из
командной строки и т.д. Номер
предпоследнего элемента массива argv[ ]
равен argc. Он содержит последний параметр.
Последний элемент массива argv содержит
NULL.
Примечание. Пример использования параметров
командной строки будет рассмотрен позднее.

40

Модули C++. Файлы заголовков.
Среда Visual C++ позволяет создавать и отлаживать программы,
использующие не только стандартные, но и пользовательские
библиотеки (модули).
Модуль C++ обычно включает два файла:
-

заголовочный файл с расширением .h

-

файл реализации с расширением .cpp.

Заголовочный файл играет роль интерфейсной секции модуля.
В него помещают объявление экспортируемых ресурсов модуля:
- прототипы (заголовки) процедур и функций,
- объявление переменных, типов и констант.
Заголовочный файл подключают командой #include “.h”
в файле реализации программы или другого модуля, если они
используют ресурсы описываемого модуля

.
41

Модули C++(2)
Файл реализации представляет собой секцию реализации модуля.
Он должен содержать команды подключения используемых модулей,
описания экспортируемых процедур и функций, а также объявления
внутренних ресурсов модуля.
В начало каждого файла реализации необходимо поместить оператор
подключения заголовочного файла stdafx.h:
#include “stdafx.h”.
Этот файл осуществляет подсоединение специальных библиотек
среды, и при его отсутствии компилятор выдает ошибку «не найден
конец файла».
При создании файл проекта уже содержит заготовку главной функции
программы – функции main().
Для создания файлов модуля и добавления их к проекту необходимо
вновь вызвать многошаговый Мастер заготовок.
Это делается с использованием команды меню File/New.
Выполнение этой команды при открытом проекте вызовет открытие
окна Мастера заготовок на вкладке Files
42

Модули C++ (Ex3_03)
Файл Mod.h:
int nod(int a,int b);

Зависит

Файл Mod.cpp:
#include "stdafx.h"
Ex1.cpp
#include "Mod.h"
int nod(int a,int b)
{ while (a!=b)
if (a>b) a=a-b; else b=b-a;
return a; }
Файл Ex3_03.cpp:
#include "stdafx.h"
#include
#include "Mod.h"
int main(int argc, char* argv[])
{ int a=18,b=24,c;
c=nod(a,b);
printf("nod=%d\n",c);
return 0; }

Реализует

Mod.h

Mod.cpp

43






Чтобы не видеть здесь видео-рекламу достаточно стать зарегистрированным пользователем.
Чтобы не видеть никакую рекламу на сайте, нужно стать VIP-пользователем.
Это можно сделать совершенно бесплатно. Читайте подробности тут.