7 Средства создания универсальных
подпрограмм С++
7.1 Использование «структурных » типов в качестве
формальных параметров
7.1.1 Параметры - многомерные массивы
Как было показано в главе 4, массивы можно использовать для передачи
данных в подпрограммы. Однако, наличие контроля за его размерами,
ограничивает применение многомерных массивов в таком описании.
Кроме того, иногда в подпрограмме нужно сформировать новый массив,
размер которого заранее не известен, а определяется во время работы,
и вернуть его из подпрограммы.
С++ позволяет применять вспомогательные массивы указателей на
одномерные массивы, которые в свою очередь могут быть массивами
указателей.
В этом случае, по каждой размерности массив является одномерным и по
правилам С++ его размерность может быть опушена в спецификации
формальных параметров.
Такой подход позволяет в теле функции обрабатывать многомерные
1
массивы с изменяющимися размерами.

Многомерные массивы (2)
Пример обработки матрицы с переменными размерами.
Написать программу переформирования матрицы путем замены в
ней всех отрицательных элементов нулевыми с использованием
подпрограмм.

float B[3][4]={1.2,-4.9 ,5.0,-8.1,
-3,6.1,-8.5,9.6,
3.3,-6.7,-1.2,7.8};
float *ptr[]={&B[0],&B[1],&B[2]};

B[0]
B[1]
B[2]

ptr &B[0] &B[1] &B[2]

Однако следует помнить, что адрес начала
строки не типизированный и в программе его нужно явно
преобразовать к типу float : (float *)&B[0]
Прототип функции переформирования:

void pereform(int n,int m, float *p[]);

2

Пример обработки матрицы переменного размера (2)
Параметр – массив указателей на
// Ex7_1.cpp
строки матрицы
#include "stdafx.h"
#include
void pereform(int n,int m,float * p[])
{ for(int i=0;i
Пример передачи матрицы переменного размера (3)

pereform(3,4,ptr);
puts("RESULT MATRIX");
for(int i=0;i
Пример формирования матрицы переменного размера
Пример. Написать программу, формирующую матрицу переменного
размера в одной подпрограмме, а в другой – меняет отрицательные
элементы этой матрицы на их абсолютное значение.

int **M;
Указатель int **M указывает на массив указателей int *M, каждый из
элементов которого, в свою очередь адресует одномерный массив
элементов целого типа.
Так как размеры массивов нигде не указаны и память под массивы не
выделена, то все это можно сделать в программе во время
выполнения, когда размеры массива становятся известны.
*M

M
M[0]

0

M[1]

1

M[2]

2

*M[0]

M[1][3]=>*(*(M+1)+3)

*M[1]+3

0

1

2

3

5

Пример формирования матрицы переменного размера (2)
// Ex7_2.cpp
#include "stdafx.h"
#include
#include
int **matr(int &l,int &p)
{int **m;
int i,j;
printf(" input size of massiv
scanf("%d %d",&l,&p);

Функция, формирования
матрицы целого типа и
возвращающая указатель
на эту матрицу
(указатель на указатель)
Локальная переменная
указатель на указатель
целого типа,
используемый для
\n");
формирования
матрицы

printf(" input %4d strok iz %4d elementov\n",l,p);
m=new int* [l];
for (i=0;i
Пример формирования матрицы переменного размера (3)
void sortmas(int **m,int n,int l)
{int i,j;
Формальный параметр указатель на
указатель для передачи в
for(i=0;i
Пример формирования матрицы переменного размера (4)

sortmas(mat,n,l);
Фактический параметр – имя матрицы

Вызов подпрограммы
преобразования матрицы

Печать
printf("\n sorted massiv\n");
переформированной
for(i=0;i
7.1.2 Параметры - строки
При программировании функций работающих со строками обычно
используют прием, принятый в стандартных функциях обработки
строк.
Этот прием заключается в том, что такие функции пишут так, чтобы их
можно было вызывать и как процедуры, и как функции.
Рассмотрим несколько примеров.
Пример1. (Ex7_3)Написать подпрограмму удаления «лишних» пробелов.
Описание заголовка функции:

char * strdel(const char * tstring, char * trez)
Дубликат адреса результата

Исходная строка

{ char *ptr;
strcpy(trez,tstring);
while((ptr=strstr(trez,”
strcpy(ptr,ptr+1);
return trez;}

Строка результат

”))!=NULL)

Тело
функции
9

Параметры – строки (2)
Вызов функции strdel в основной программе:

Определение
переменных

int main(int argc, char* argv[])
{char st[40],st2[40],*ptr2;
puts("input string : world and space");
gets(st);
Вызов подпрограммы
puts("isxodnaya stroka");
как процедры
puts(st);
strdel(st,st2);
puts("Result string 1");
puts(st2);
printf("Result string 2:\n");
Выделение памяти под
ptr2=new char [40];
результат
puts(strdel(st,ptr2));
return 0;
Вызов подпрограммы
}
как функции 10

Параметры – строки (3)
Пример 2. Написать подпрограмму нахождения максимального слова
строки.(Ex7_4.cpp).
char * maxworld(const char * s,char* slmax)
Заголовок функции
{char slovo[10];
Параметры – исходная строка и
unsigned int i,j,dls,maxl;
максимальное слово
dls=0;slmax[0]='\0';maxl=0;j=0;
for(i=0;imaxl){ maxl=dls;
Если текущее слово длиннее
максимального, то сохраняем
strcpy(slmax,slovo);}
его и его длину
slovo[0]='\0';
j=0;
Переходим к следующему слову, обнуляя
все вспомогательные данные
dls=0;}
else {dls++;
Если слово не закончено, то
slovo[j++]=s[i];}
накапливаем его длину и само слово 11
} return slmax;}

Параметры – строки (4)
int main(int argc, char* argv[])
Вызов подпрограммы
{char st[80],maxsl[10];
как функции
puts("input string : world and space");
gets(st);
printf("V stroke slovo ");
printf("""%s"" - macsimalno \n",maxworld(st,maxsl));
puts("input string : world and space");
gets(st);
Вызов подпрограммы
maxworld(st,maxsl);
как процедуры
printf("V stroke slovo ");
printf("""%s"" - macsimalno \n", maxsl);
return 0;
}

12

Параметры – строки (5)
Пример 3. Написать подпрограмму нахождения максимального слова
строки, его длины и номнра в строке.(Ex7_4а.cpp).
char * infmaxw(const char * s,char* slmax,int & maxl,int
& maxnum)
Заголовок подпрограммы
{char slovo[10];int i,j,kols,dls;
kols=0;dls=0;slmax[0]='\0';maxl=0;maxnum=0;j=0;
for(i=0;imaxl)
maxl – длина максимального слова,
возвращается в оп по ссылке
{ maxl=dls;
maxnum –номер максимального
maxnum=kols;
слова, возвращается в оп по ссылке
strcpy(slmax,slovo);}
slovo[0]='\0';
dls – длина текущего слова
j=0; dls=0;}
kols – счетчик количества слов
else {dls++;
slovo[j++]=s[i];}
}
13
return slmax;}

7.1.3 Параметры структуры
В отличие от массивов и строк, имя структуры не является указателем,
поэтому для передачи в подпрограмму параметров типа структуры,
которые должны передаваться по адресу, необходимо использовать
ссылки или указатели.
Пример. Дан массив целых чисел на 10 элементов. Объединить данные
о массиве в структуру massiv, содержащую 3 поля:
массив, его текущий размер и сумму.
Написать подпрограмму, получающую структуру massiv в качестве
параметра, вычисляющую сумму элементов массива и
возвращающую эту структуру, как результат, с вычисленной суммой
элементов.
Реализовать передачу в подпрограмму параметр структуру можно с
использованием указателя, а можно описать его как ссылку.
Результат будет одинаков, а вот синтаксис описания и вызова
подпрограммы будут отличаться.

14

7.1.3.1 Использование указателя
Сумма элементов массива . Подпрограмма проектируется с
возможностью вызова ее как процедуры, и как функции.

Описание
структуры
massiv

struct mas{int n; int a[10]; int s;} massiv;
int summa(struct mas *x)
{ int i,s=0;
for(i=0;i< x->n;i++) s+=x->a[i];
x->s=s;
return s;
x
}

Формальный параметр –
указатель на структуру
Накопление
суммы

Обращение к элементам
структуры

massiv

Вызов:
summa(&massiv);

n
a
s

15

7.1.3.2 Использование ссылки
Сумма элементов массива.

Описание
структуры
massiv

struct mas{int n; int a[10]; int sum;}
massiv;
Формальный параметр –
ссылка на структуру

int summa(struct mas &x)
Обращение к
элементам структуры
{ int i,s=0;
for(i=0;i< x.n;i++) s+=x.a[i];
x.s=s;
return s;
x=massiv
}
Вызов:
summa(massiv);

n
a
s

16

7.1.3.3 Применение массива структур
Сумма элементов массива структур.

Описание
массива
структур

struct mas{int n;int a[10];int sum;} massiv[3];
int summa(struct mas *x)
Формальный параметр –
указатель на массивна
{ int i,k,s,ss=0;
структур
for(k=0;ka[i];
Сумма элементов
x->s=s;
одного массива
Сумма всех элементов
массива структур
ss+=s;
x massiv[3]
}
return ss;
}
n
Вызов: summa(massiv);

a
s

17

7.2 Параметры функции
Как уже отмечалось, функция характеризуется типом возвращаемого
значения, именем и сигнатурой.
Сигнатура определяется количеством, порядком следования и типами
параметров.
При использовании имени функции без последующих скобок и
параметров, имя функции выступает в качестве указателя на эту
функцию, и его значением служит адрес размещения функции в
памяти.
Это значение адреса может быть присвоено другому указателю, и затем
уже этот новый указатель можно применять для вызова функции.
Однако в определении нового указателя должен быть тот же тип, что и
возвращаемое функцией значение, и та же сигнатура.
Указатель на функцию определяется:

(* )();
Например:

int (*ptrfun)(int,int);

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

Параметры функции (2)
При присваивании указателей на функции тоже надо следить за
соответствием типов возвращаемых значений и сигнатур правой и
левой частей операции присваивания.
Пример.
Инициализированный
Описание
указатель
char f1(char){…}
функций
char f2(int){…}
void f3(float){…}
Определение
int f4(float){…}
указателей на функции
int f5(int){…}
void (*ptr1)(float)=f3;
Корректное присвоение
указателя на функцию
int (*ptr2)(int);
char (*ptr3)(int);
void main ()
{ ptr2=f5; ptr3=f2;
Ошибка присвоения.
prt2=f4; ptr3=f1;
Несоответствие типов или
}
сигнатур
19

Параметры функции (3)
Пример (Ex7_6). Написать программу вычисления элементарных
функций.

6+2=8
#include "stdafx.h"
8-2=6
#include
6*2=12
int add(int n,int m) {return n+m;}
int sub(int n,int m) {return n-m;}
12/2=6
int mul(int n,int m) {return n*m;}
int div(int n,int m) {return n/m;}
int main(int argc, char* argv[])
{ int (*ptr)(int,int);
Указатель на функцию
int a=6, b=2; char c='+';
while (c!=' ')
Присвоение значения указателю
{ printf("%d%c%d=",a,c,b);
switch (c) { case '+': ptr=add; c='-';break;
case '-': ptr=sub; c='*';break;
case '*': ptr=mul; c='/';break;
case '/': ptr=div; c=' '; }
printf("%d\n",a=ptr(a,b));
}
Вызов функции
20
return 0; }
по указателю

Параметры функции (4)
Пример2. Написать программу вычисления значения интеграла
функции одной переменной на отрезке a,b с точностью
eps.
Указатель на функцию
// Ex7_7.cpp
одной переменной
вещественного типа
#include "stdafx.h"
#include
Заголовок функции нахождения
интеграла функции одной
#include
переиенной
float (* funuk)(float);
float integral(float(*funuk)(float),
float a,float b,float eps)
{int i,n,k;
float s1,s2,x,d;
n=5;
d=(b-a)/n;
Формальный параметр
Установка
s2=1.0e+10;
– указатель на функцию
начальных
k=0;
значений

21

Параметры функции (5)
do
{s1=s2;
s2=0;n=n*2;
d=d/2;
x=a;k++;
for(i=1;ieps);
return s2;
}
float f1(float x)
{return x*x-1;}
float f2(float x)
{return 2*x;}

Цикл расчета
интеграла

Функции, для которых
ищется интеграл

22

Параметры функции (6)
int main(int argc, char* argv[])
Ввод исходных
{float a,b,eps;
данных
puts("input a,b,eps for y=x^2-1");
scanf("%f %f %f",&a,&b,&eps);
printf("Value integral= %10.5f\n",integral(f1,a,b,eps));
puts("input a,b,eps for y=2*x");
Ввод исходных
данных
scanf("%f %f %f",&a,&b,&eps);
printf("Value integral= %10.5f\n",integral(f2,a,b,eps));
return 0;
}

f2,f1- параметры
функции

Вызов функции с
параметром функцией

23






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