Правила записи и использования функций
1. Имя определяет деление функций на главную и дополнительные. Главная – функция с именем main, WinMain, OwlMain (головная). В ней, как правило, описатель типа, список формальных параметров и оператор return не указываются.
2. Дополнительная – функция с любым именем, кроме указанных выше. В пользовательских – имя формирует сам пользователь аналогично идентификаторам переменных. Для стандартных – указывается в технической документации.
3. Операнды любой функции – локальные параметры и формальные, перечисленные в заголовке.
4. В качестве формальных параметров используются переменные и указатели.
Количество, типы и последовательность расположения формальных параметров в списке задается создателем функции.
Результаты вычислений тела функции – константы.
7. В качестве выражения РВ оператора return используются константы, переменные и их совокупности.
8. В основную (вызывающую) функцию передается значение константы указанной (вычисленной) в выражении return. Если все планируемые в подпроцессе вычисления могут быть сведены к одной формуле, тело функции может состоять только из одного оператора return с соответствующим выражением.
9. Тип возвращаемого значения определяется типом функции. Если он не указан, подразумевается целочисленный результат (int). Результат возвращается в точку вызова.
10. В теле функции в соответствии с требованиями ветвящегося алгоритма могут использоваться несколько операторов возврата (return), но выполняться будет только один из них.
11. Отсутствие в головной функции оператора return подтверждается на этапе компиляции соответствующим предупреждением.
12. Головная и дополнительные функции – отдельные программные модули. Поэтому в них могут использоваться одноимённые переменные, указатели и массивы.
13. Тексты дополнительных пользовательских функций могут располагаться в любом месте программы (вне тела любой из функций).
14. Тексты стандартных функций располагаются в соответствующих библиотеках языка Си/Си++ в виде объектных модулей.
15. Независимо от взаиморасположения функций выполнение программного модуля начинается с головной функции.
16. Из тела каждой функции можно обращаться к любой другой (вызывать ее).
17. Фактические и формальные параметры в списках должны совпадать по количеству, месту расположения и типу.
18. В качестве фактических параметров используются константы, переменные, вызовы дополнительных функций, арифметические выражения, адреса переменных и массивов.
19. Вызов дополнительной функции требует ее предварительного определения (расположения над вызывающей). В противном случае её необходимо описать (задать прототипом). Описание размещается над вызывающей функцией. Описания стандартных функций (их прототипы) находятся в стандартных заголовочных файлах.
Прототип – конструкция, аналогичная описателям переменных.
Он позволяет проверить указанные в вызове типы фактических параметров и возвращаемого результата на соответствие указанным в заголовке функции.
Прототип функции идентичен ее заголовку и имеет структуру
[тип] имя([тип [b1], . . . ,тип [bi], . . . ,тип [bn]]);
где имя – идентификатор (название) функции;
тип – описатель типа функции (результата) и формальных параметров;
b1 … bi bn – элементы списка формальных параметров с указанием типа;
, , , – разделители элементов списка;
( ) – ограничители списка формальных параметров;
[ ] – признак необязательности содержимого;
; – признак оператора.
Структура прототипа определяет, что в списке можно указывать только типы формальных параметров.
Рассмотрим конкретные примеры определения, вызова, описания функций при взаимодействии головной с одной пользовательской и стандартными.
Вариант 1.
#include<stdio.h>/*файл с прототипами функций ввода-вывода*/
#include<math.h> /*файл с прототипами математич. функций */
float sum(float a, float b);/*прототип пользовательской ф-ции*/
main( ) /* заголовок головной функции */
{
float a, b, c, d, d1; /* описатели локальных переменных */
. . .
c = pow( a, 2 ) + b; /* вычисление с вызовом
стандартной функции pow */
d = sum( a, b ) - 0.5*c; /* вычисления с вызовами пользователь-*/
d1=d+sum(3.6, sqrt(d)); /*ской функции sum и стандартной sqrt*/
. . .
printf(“%f %f %f ”, c, d, d1); /* вызов функции printf */
}
/* определение пользовательской функции sum */
float sum(float s1, float s2 ) /* заголовок пользовательской функции */
{
float s; /* описание локальной переменной s */
s = s1 + s2; /*вычисление s по формальным параметрам s1 и s2*/
return s; /* возвращение значения s в вызывающую функцию */
}
В представленном варианте до определения главной функции заголовочными файлами выполнены описания стандартных функций (математических и ввода-вывода), а затем пользовательской функции sum – указанием её прототипа.
Главная функция расположена над дополнительной и не содержит в заголовке описатель типа и список формальных параметров. В теле главной функции выполнены обращения к стандартным функциям: sqrt – с одним фактическим параметром (d), pow – с двумя (a, 2) и printf – с тремя (“%f %f %f ”, c, d, d1). В арифметическом выражении вычисления переменной d в качестве первого операнда используется вызов пользовательской функции sum с указанием фактических параметров – a и b, описанных в головной функции как локальные переменные. Типы (вещественные) определяет постановка задачи, последовательность расположения в списке задана произвольно.
В арифметическом выражении вычисления переменной d1 в качестве второго операнда используется вызов пользовательской функции sum с указанием фактических параметров – 3.6 и sqrt( d ). Последовательность их расположения в списке аналогична выбранной для а и b.
Дополнительная функция предназначена для вычисления суммы двух операндов (формальных параметров) и выполнена по левому варианту структуры. Ее заголовок определяет тип возвращаемого значения (float), название функции (sum) и список формальных параметров – вещественных переменных s1 и s2. Порядок их расположения в списке определяется соответствующими фактическими параметрами (a и b), (3.6 и sqrt( d )) в обращениях главной функции.
Выполнение программного модуля (аналогично работе со стандартными функциями) приведет к двукратной автоматической передаче численных значений фактических параметров (a, b), а затем (3.6, sqrt(d)) из головной функции в вызываемую пользовательскую (sum) – формальным параметрам (s1, s2). После выполнения вычислений тела функции результаты (s) автоматически возвратятся в точки вызова как операнды вычисления переменных d и d1. Время существования переменных s1, s2 и s соответствует длительности работы функции sum.
Вариант 2.
#include<stdio.h>/*файл с прототипами функций ввода-вывода */
#include<math.h> /* файл с прототипами математич. функций */
/* определение пользовательской функции sum */
float sum(s1, s2 ) /* заголовок дополнительной функции */
float s1, s2; /*описание формальных параметров*/
{
return s2+s1;/*возвращение значения s в вызывающую ф-цию*/
}
main( ) /* заголовок головной функции */
{
float a, b, c, d, d1; /* описатели локальных переменных */
. . .
c = pow( a, 2 ) + b; /* вычисление с вызовом
стандартной функции pow */
d = sum( a, b ) - 0.5*c; /* вычисления с вызовами поль- */
d1 = d + sum( 3.6, sqrt(d) ); /* зовательской функции sum */
. . .
printf(“%f %f %f ”, c, d, d1); /* вызов стандартной функции printf */
}
Дополнительная функция составлена с использованием правого варианта структуры. Тело дополнительной функции составляет один оператор return.
Дополнительная функция расположена над основной. Описание типов формальных параметров вне заголовка подпрограммы при машинной обработке приведет к выдаче предупреждений «по заголовку функции невозможно проконтролировать типы параметров, что может повлиять на результаты счета». Устранение возможных последствий выполняется стандартным способом – указанием прототипа дополнительной функции над главной.
Прототип не требуется, если дополнительная функция выполнена по левому варианту структуры и размещена над основной. В этом варианте заголовок функции играет роль прототипа.
Рассмотренные структуры и правила их использования позволяют осуществить программирование задачи с факториалами. Идентификация переменных представлена в табл. 10.1.
Таблица 10.1
Обозначение в алгоритме | a | z | n | m | k | f | fi | i |
Обозначение в программе | a | z | n | m | k | f | fi | i |
Классический вариант программирования задачи
#include<stdio.h>/*файл с прототипами функций ввода-вывода*/
#include<conio.h>/*файл с прототипом функций getch(), clrscr()*/
#include <math.h> /*файл с прототипами математич. функций*/
#include<windows.h>/* файл с прототипом функции СharToOem*/
long fakt(int fi); /* прототип функции расчета факториала */
main( ) /* определение головной функции */
{
float a, z1, z2, z;
int n, m, k;
char buf[30];
clrscr( );
CharToOem(" Введите значения a, n, m, k: ",buf);
printf("\n %s \n",buf);
scanf("%f%d%d%d", &a, &n, &m, &k);
z1 = log(a) + fakt(n);
z2 = fakt(m) - fakt( k-m );
z = z1 + z2 - 0.2*a;
printf( "\n a=%.2f n=%d m=%d k=%d"
"\n z1=%.2f z2=%.2f"
"\n z=%.2f\n", a, n, m, k, z1, z2, z);
getch( );
}
long fakt(int f) /* заголовок дополнительной функции расчета факториала */
{
int i;
long fi;/*описание переменной текущего значения факториала*/
for(fi=1, i=1; i<=f; i++) /*заголовок цикла расчета факториала */
{
fi = fi * i; /* расчет текущего значения факториала */
}
return fi;/* возврат в головную функцию значения fi */
}
16.9 5 4 10
Под закрывающей скобкой приведены исходные данные для решения задачи.
В подпрограмме наряду с формальным параметром f использованы локальные переменные fi и i. Первая из них определяет значение вычисляемого факториала, изменяясь от единицы до конечного возможно большого (long) значения. Вторая используется как параметр цикла для организации последовательного умножения в заданном диапазоне.
Результаты решения представлены в приложении 10.1.
Программирование задачи с графическим интерфейсом
Программирование задачи при использовании графического интерфейса предварим его разработкой. Для ввода значений a, n, m, k планируем однострочные поля редактирования (EditA, EditN, EditM, EditK).
Вывод расчетных значений z1, z2, z реализуем в однострочные поля редактирования (EditZ1, EditZ2, EditZ).
Управление процессом решения реализуем двумя командными кнопками, расположенными в нижней части окна. Назначение каждой определяется ее названием.
С учетом планируемого интерфейса выполним программирование задачи.
#include <stdio.h>/*файл с прототипами функций ввода-вывода*/
#include <math.h>
long fakt(int fi); /* прототип функции расчета факториала */
…
void TSumprDlgClient::BNClickedOk()
{
// INSERT>> Your code here.
float a, z1, z2, z;
int n, m, k;
char buf[30];
EditA->GetText(buf,10); /*ввод */
a=atof(buf); /*значения а*/
EditN->GetText(buf,10); /*ввод */
n=atoi(buf); /*значения n*/
EditM->GetText(buf,10); /*ввод */
m=atoi(buf); /*значения m*/
EditK->GetText(buf,10); /*ввод */
k=atoi(buf); /*значения k*/
z1 = log(a) + fakt(n);
z2 = fakt(m) + fakt( k-m );
z = z1 + z2 - 0.2*a;
sprintf(buf,"%.2f ",z1); /* вывод */
EditZ1->SetText(buf); /*значений z1*/
sprintf(buf,"%.2f ", z2); /* вывод */
EditZ2->SetText(buf); /* значений z2*/
sprintf(buf,"%.2f",z); /* вывод */
EditZ->SetText(buf); /*значений z3*/
}
long fakt(int f) /* заголовок дополнительной функции расчета факториала */
{
int i;
long fi;/*описание переменной текущего значения факториала*/
char buf[30];
for(fi=1, i=1; i<=f; i++)/*заголовок цикла расчета факториала*/
{
fi = fi * i; /* расчет текущего значения факториала */
}
return fi; /* возврат в головную функцию значения fi */
}
16.9 5 4 10
Под закрывающей скобкой приведены исходные данные для решения задачи.
Результаты решения представлены в приложении 10.2.
10.2. Подпроцесс с аргументом – одномерным массивом и одним результатом
В задаче 10.1 в качестве операндов использовались константы, переменные, вызовы функций и составляющие их арифметические выражения. В реальных задачах возможно также использование массивов (индексированных переменных). Рассмотрим программирование подобных вычислений на конкретной задаче (10.2) о расчете сумм элементов одномерных массивов.
Постановка задачи
Вычислить значение функции:
Вычисления функции проводить с элементами массивов X(n) и Y(m), когда n £ 10, m £ 15, при a = 0,96; b = 35.