Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
119
Добавлен:
13.03.2016
Размер:
470.02 Кб
Скачать

2.2.3. Место описания функции в программе

Функция не может быть описана внутри другой функции. Функция (как всё в программе) должна быть описана до использования; если это не так, то до использования необходимо поместить прототип (шаблон)функции. Самый простой и лучший вариант шаблона: заголовок функции, в котором могут отсутствовать имена формальных параметров (но присутствуют их типы). Формальное отличие шаблона от заголовка функции состоит в присутствии точки с запятой после скобки, закрывающей список формальных параметров. Наличие шаблона позволяет компилятору контролировать соответствие типа возвращаемого функцией значения и соответствие количества и типов формальных и фактических параметров.

Общеупотребительная практика состоит в соблюдении следующих правил:

1) надо ставить шаблоны в начало программного файла;

  1. удобно записывать часто употребляемые шаблоны в заголовочный файл, подключаемый к программе директивой includeпрепроцессора (см. п. 2.3.3). Обратите внимание, что в всех рассмотренных примерах Си-программ с помощью директивы include подключались именно файлы, содержащие шаблоны библиотечных функций, т. е. заголовочные файлы.

2.2.4. Примеры программ, использующих функции

Пример 1. Даны две матрицы: а из 3-х строк и 5 столбцов (в дальнейшем будем условно записывать а[3*5]) иb[7*3]. Вычислить минимальные значения для каждой строки каждой из этих матриц.

Естественно, вычисление минимальных значений строк произ­вольной матрицы следует оформить как функцию (назовем ее minmatr), а затем применить ее два раза к конкретным (фактическим) матрицам а иb. Алгоритм ввода одинаков для матриц а иb, поэтому ввод также оформим как функцию (назовем ееmatrin). Аналогично вывод массива результатов будет процедураmasout.

Поясним, как составляются заголовки на примере функции minmatr.Функция имеет столько результатов, сколько строк у матрицы, все они равноправны, поэтому нет причины передавать один из них через имя функции, и, следовательно, тип функции -void.В список формальных параметров передаются "входные" данные для функции: матрицаа и ее размеры (n - число строк,m - число столбцов), и "выходные" данные:min - массив минимальных значений строк. Заметим, что обозначения, принятые в одной функции (a, n,m,min) никоим образом не связаны с обозначениями в других функциях (в том числеmain), т. е. программирование функций выполняется автономно друг от друга. Переменнаяmin- результат работы функции, поэтому в список формальных параметров должен быть включен ее адрес. Так какmin является массивом, то это требование удовлетворяется автоматически, без применения специальных операций.

Типы фактических и формальных параметров должны совпадать, поэтому размеры формальных массивов должны подходить и для матрицы а, и для матрицы b. Чтобы удовлетворить этому требованию, используем максимальный второй размер (число столбцов), подходящий и для а, и дляb, т. е. память под массивы отводится с избытком.Первый размер - число строк - в списке формальных параметров можно не указывать.

Получаем заголовок:

void minmatr(float a[ ][5],int n,int m,float min[ ]).

Дальнейшие комментарии приведены в тексте программы. Блок-схема функцииminmatr приведена на рис. 10.

Программа:

#include <stdio.h>

#include <math.h>

void masout(float a[ ],intn,charc);/* если стоит ";", то это шаблон*/

/*первый размер у массивов-формальных параметров можно*/

/*не указывать, второй задан по максимуму*/

void matrin(float [ ][5],intn,intm,char с);/* c -имя матрицы*/

/* используется при выводе пояснительных фраз и приглашений*/

void minmatr(float [ ][5],intn,intm,floatmin[ ]);

/* n и mво всех функциях передаются по значению, т. к. их*/

/*фактические значения - константы*/

void main()

{float a[3][5],b[7][5], mina[3], minb[7];

matrin(a,3,5,'a'); matrin(b,7,3,'b');

minmatr(a,3,5,mina); minmatr(b,7,3,minb);

masout(mina,3,'a'); masout(minb,7,'b');

}

void minmatr(float a[][5],int n,int m,float min[])

{int i,j;

for (i=0; i<n; i++)

{min[i]=a[i][0];/* минимум каждой строки вычисляется*/

/*последовательным сравнением*/

for (j=1;j<m; j++)

if (a[i][j]<min[i])

min[i]=a[i][j];

}

}

void matrin(float a[][5],int n,int m,char c)

{int i,j;

printf("Введите матрицу%1c %2d * %2d\n",c,n,m);

for (i=0;i<n;i++)

for (j=0;j<m;j++)

scanf("%f",&a[i][j]);

}

void masout(float a[],int n,char c)

{int i;

printf("Минимальные значения строк матрицы%1c\n",c);

for (i=0;i<n;i++)

printf("%4.1f ",a[i]);

printf("\n");

}

Пример 2. Вычислить полусумму минимальных значений двух одномерных массивов: а[5] и b[8].

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

Заметим, что у функции min один результат, логично возвращать его через имя функции, тип функции будетfloat(совпадает с типом результата).

#include <stdio.h>

#include <math.h>

float min(float a[], int n);

void masin(float a[],int n,char c);

void main()

{float a[5],b[8],srmin;

masin(a,5,'a'); masin(b,8,'b');

srmin=(min(a,5)+min(b,8))/2;

printf("Полусумма минимумов pавна %4.1f\n",srmin);

}

float min(float a[], int n)

{int i; float m;/*переменнаяm заменяет min, т. к. использование*/

m=a[0]; /*предполагает рекурсивное обращение к функции*/

for (i=1;i<n;i++)

if (a[i]<m )

m=a[i];

return (m);

}

void masin(float a[],int n,char c)

{int i;

printf(" Введите массив %1c из %1d элементов\n",c,n);

for (i=0;i<n;i++)

scanf("%f",&a[i]);

}

Пример 3. Приведенная ниже программа содержит функциюkv_urрешения квадратного уравненияax2+bx+c=0. Результаты функции: дискриминант уравнения и либо два действительных корня, либо действительная и мнимая часть комплексно-сопряженных корней. Результаты должны передаваться по имени, поэтому в список формальных параметров включены их адреса. В главной функции вводятся значения коэффициентов уравнения, вызываетсяkv_urи выводятся результаты.

#include <stdio.h>

#include <math.h>

void kv_ur(float a, float b, float c, float *d, float *x1, float *x2);

// *d - дискриминант

// если *d<0, то *х1 и *х2 - действительная и мнимая часть комп. коpней,

// иначе *х1 и *х2 - два действительных коpня.

void main()

{float a, b, c, d, x1, x2;

printf("введите коэффициенты a,b,c уpавнения\n", a, b, c);

scanf("%f%f%f", &a, &b, &c);

kv_ur(a, b, c, &d, &x1, &x2);

if (d<0)

{printf("уpавнение имеeт комплексно-сопpяженные коpни\n");

printf("действ. часть =%f , мнимая часть =%f\n", x1,x2);

}

else

{printf("уравнение имеeт два действительных коpня\n", "x1=%fx2=%f\n", x1,x2);

}

}

void kv_ur(float a, float b, float c, float *d, float *x1, float *x2)

{*d=b*b-4*a*c;

if(*d<0)

{*x1=-b/2/a;

*x2=sqrt(-*d)/2/a;

}

else

{*x1=-b/2/a+sqrt(*d);

*x2=-b/2/a-sqrt(*d);

}

}