Лекция 8
Основные понятия и определения
Основные понятия и определения
Основные понятия и определения
Виды функций
Описание функций
Прототип функции
Параметры функции
Прототип функции
Заголовок функции
Заголовок функции
Тело функции
Пример
Пример
Пример
Пример
Структура программы
Пример
Пример
Функциональная схема программы
Пример
Возвращаемое значение функции
Пример
Пример
Возврат значений сложных типов
Параметры функции
Передача параметров по значению и по ссылке
Передача по значению
Передача по ссылке
Передача по ссылке
Пример
Пример
Массивы как параметры функции
Массивы как параметры функции
Массивы как параметры функции
Массивы как параметры функции
Массивы как параметры функции
Строки как параметры функции
Строки как параметры функции
Передача параметров
Нижний уровень передачи параметров
211.50K
Category: programmingprogramming

Функции: понятие, описание. Структура программы. Передача параметров и возврат значений

1. Лекция 8

Функции: понятие, описание.
Структура программы.
Передача параметров и возврат значений.

2. Основные понятия и определения

Нисходящее программирование – процесс разработки программ, при
котором сложная программа разбивается на ряд более простых
подпрограмм, которые в свою очередь также могут быть разбиты на
ряд еще более простых подпрограмм. Этот процесс продолжается до
получения элементарных
подпрограмм,
реализация которых не
представляет большой сложности.
Восходящее программирование
– процесс разработки программ,
при котором
сложная
программа
реализуется посредством
интеграции более простых подпрограмм, начиная с элементарных
подпрограмм. Этот процесс продолжается до тех пор, пока не будет
получена основная программа.

3. Основные понятия и определения

Функция –
это синтаксически выделенный именованный
программный модуль, выполняющий определенное действие
или группу действий.
Каждая функция имеет свой интерфейс и реализацию.

4. Основные понятия и определения

Интерфейс функции

заголовок
функции, в котором
указывается название функции, список ее параметров и тип
возвращаемого значения.
Реализация функции

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

5. Виды функций

С точки зрения программиста функции бывают:
библиотечные – функции описанные в библиотеках
языка С (как стандартных, так и не стандартных);
пользовательские – функции реализованные
программистом в процессе разработки программы.

6. Описание функций

Описание функции на языке С осуществляется в любом месте
программы вне описания других функций и состоит из трех
элементов:
прототип функции;
заголовок функции;
тело функции.

7. Прототип функции

Прототип функции – необязательная часть описания функции,
предназначенная для объявления некоторой функции,
интерфейс которой соответствует данному прототипу.
Объявление прототипа имеет следующий вид:
возвращаемый тип имя(список типов формальных параметров);

8. Параметры функции

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

9. Прототип функции

Примеры прототипов:
int func(int, double, double);
void func(int, char *);
double func(void);

10. Заголовок функции

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

11. Заголовок функции

Каждый элемент (формальный параметр) имеет следующий
формат объявления:
тип имя
Примеры заголовков функций:
int func(int i, double x, double y)
void func(int ind, char *string)
double func(void)

12. Тело функции

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

13. Пример

Реализация функции вычисления факториала числа.
double factorial(unsigned);
...
double factorial(unsigned num)
{
double fact = 1.0;
for(unsigned i=1;i<=num;i++)
fact *= (double)i;
return fact;
}

14. Пример

Вызов функции вычисления факториала представлен в
следующем фрагменте программы:
unsigned n = 8;
double vals[2] = {0.0};
...
//Константа 5 – фактический параметр
vals[0] = factorial(5);
//Переменная n – фактический параметр
vals[1] = factorial(n);
...

15. Пример

Подсчет количества положительных элементов в целочисленном
массиве.
unsigned positive(int [], unsigned);
...
unsigned positive(int arr[], unsigned num)
{
unsigned count = 0;
for(unsigned i=0;i<num;i++)
if(arr[i] > 0) count++;
return count;
}

16. Пример

Вызов функции подсчета положительных элементов в
целочисленном массиве представлен в следующем
фрагменте программы:
unsigned n = 10;
int array[n];
...
unsigned cnt = positive(array,n);
...

17. Структура программы

1: подключение библиотек.
2: объявление глобальных пользовательских типов
данных и переменных.
3: объявление прототипов пользовательских
функций.
4: реализация функции main.
5: реализация (описание заголовков и тел)
пользовательских функций.

18. Пример

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

19. Пример

#include <stdio.h>
#include <string.h>
void division(double,double);
int main(int argc, char *argv[])
{
do{
char str[80];
printf("Введите два числа для/
вычислений\nили пустую/
строку для выхода\n>:");
gets(str);
if(strcmp(str,"") == 0) break;
double x,y;
sscanf(str,"%lf %lf",&x,&y);
division(x,y);
}while(1);
return 0;
}
double max(double x, double y)
{
return (x>y)?x:y;
}
double min(double x, double y)
{
return (x<y)?x:y;
}
void division(double x, double y)
{
double res = max(x,y)/min(x,y);
printf("Результат: %lf\n",res);
}

20. Функциональная схема программы

Функция main
Функция I-го уровня

Функция I-го уровня
Функция II-го уровня

Функция II-го уровня


21. Пример

main
division
max
min

22. Возвращаемое значение функции

Для реализации возврата значения и завершения выполнения
функции используется оператор завершения функции,
который относится к группе операторов управления, не
рассматривался ранее. Синтаксис использования оператора
завершения функции:
return выражение;
Если функция не возвращает никакого значения (в заголовке
указан тип void), то оператор возврата указывается без
какого-либо выражения:
return;

23. Пример

Функция, определяющую количество корней
квадратного уравнения (целочисленное значение),
заданного коэффициентами a, b и c (формальные
параметры функции):
int NumberOfRoots(double a, double b, double c)
{
double descr = b*b – 4.0*a*c;
if(descr < 0) return 0;
else if(descr > 0) return 2;
else return 1;
}

24. Пример

double descr=b*b–4.0*a*c;
if(descr<0) return 0;
else if(descr>0) return 2;
return 1;
double descr=b*b–4.0*a*c;
int num = 1;
if(descr<0) num = 0;
else if(descr>0) num = 2;
return num;

25. Возврат значений сложных типов

Возврат значений сложных типов (структур и объединений)
возможен только в стандарте С99.
В более ранних версиях языка возврат в качестве значений
структур или объединений невозможен.
Возвращать в качестве значений массивы в языке С нельзя. Для
этого можно использовать возврат указателя на массив.

26. Параметры функции

Параметры функции могут быть константными: их невозможно
изменить. Для описания такого параметра перед его типом
указывается ключевое слово const.
Пример:
int Length(const char *str)
{
int len = 0;
for(char *ptr = str;*ptr!=0;ptr++) len++;
return len;
}

27. Передача параметров по значению и по ссылке

В языках программирования высокого уровня
реализованы два механизма передачи
параметров:
по значению;
по ссылке.

28. Передача по значению

Механизм передачи параметра по значению заключается в
следующем: в вызываемую функцию передается значение
фактического параметра.
void Inc(int a) { a++; }
int main (int argc, char *argv[])
{
int val = 0;
printf(“Значение: %d\n”,val);
Inc(val);
printf(“Значение: %d\n”,val);
return 0;
}

29. Передача по ссылке

В языке С механизм передачи параметра по ссылке
реализован посредством указателей.
void Inc(int *a) { (*a)++; }
int main (int argc, char *argv[])
{
int val = 0;
printf(“Значение: %d\n”,val);
Inc(&val);
printf(“Значение: %d\n”,val);
return 0;
}

30. Передача по ссылке

Механизм передачи параметров по ссылке используется
для реализации возможностей:
изменение значения переменной, описанной внутри
вызывающей функции, вызываемой функцией;
реализации функций, возвращающих несколько значений.

31. Пример

Реализация функции поиска максимального и
минимального значения в целочисленном массиве.
void GetMinMax(int arr[], int n, int *min, int *max)
{
*min = arr[0]; *max = arr[0];
for(int i=1;i<n;i++){
if(arr[i] > *max) *max = arr[i];
if(arr[i] < *min) *min = arr[i];
}
}

32. Пример

Использование данной функции продемонстрировано в следующем
фрагменте программы:
int main(int argc, char *argv[])
{
int n;
... //Ввод переменной n
int array[n];
... //Ввод массива array
int maxel, minel;
GetMinMax(array,n,&minel,&maxel);
printf(“Минимум массива: %d\n”, minel);
printf(“Максимум массива: %d\n”, maxel);
...
}

33. Массивы как параметры функции

Так как в языке С имя массива является указателем на массив, то массивы в языке С
передаются только по ссылке.
void ProcArray(int arr[], int n)
{
for(int i=0;i<n;i++) arr[i]++;
}
int main(int argc, char *argv[])
{
int array[] = {0,1,2,3,4,5,6,7,8,9};
int num = sizeof(array)/sizeof(int);
for(int i=0;i<num;i++) printf("%d ",array[i]); //0 1 2 3 4 5 6 7 8 9
puts("");
ProcArray(array,num);
for(int i=0;i<num;i++) printf("%d ",array[i]); //1 2 3 4 5 6 7 8 9 10
puts("");
return 0;
}

34. Массивы как параметры функции

Массив можно передавать в параметрах используя синтаксис указателя.
void ProcArray(int *arr, int n)
{
for(int i=0;i<n;i++) arr[i]++;
}
int main(int argc, char *argv[])
{
int array[] = {0,1,2,3,4,5,6,7,8,9};
int num = sizeof(array)/sizeof(int);
for(int i=0;i<num;i++) printf("%d ",array[i]);
puts("");
ProcArray(array,num);
for(int i=0;i<num;i++) printf("%d ",array[i]);
puts("");
return 0;
}

35. Массивы как параметры функции

Массив в параметрах функции может быть объявлен как константный.
Значения элементов этого массива нельзя изменить внутри этой
функции, обратившись к ним через имя этого массива. Но можно
через дополнительный не константный указатель, установленный
на массив с явным приведением типа.
void ProcArray(const int arr[], int n)
{
for(int i=0;i<n;i++) arr[i]++;
//Ошибка
int *arrptr1 = arr;
//Ошибка
int *arrptr2 = (int *)arr;
//Корректно
for(int i=0;i<n;i++) arrptr2[i]++; //Корректно
}

36. Массивы как параметры функции

Передача в параметрах многомерных массивов (две и более
размерности) осуществляется иначе.
Неправильно:
void ProcArray(int arr[][], int n, int m)
{
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
arr[i][j]++;
}

37. Массивы как параметры функции

Правильный способ
void ProcArray(int n, int m, int arr[n][m])
{
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
arr[i][j]++;
}

38. Строки как параметры функции

Строки в языке С в качестве параметров передаются с использованием синтаксиса
указателя на символьный тип.
void ProcString(char *str)
{
for(int i=0;str[i]!=0;i++)
if(islower(str[i])) str[i] = 'A' + (str[i] - 'a');
else if(isupper(str[i])) str[i] = 'a' + (str[i] - 'A');
}
int main(int argc, char *argv[])
{
char string[] = "Hello World!";
puts(string);
//Hello World!
ProcString(string);
puts(string);
//hELLO wORLD!
return 0;
}

39. Строки как параметры функции

При передаче в качестве параметра массива строк необходимо использовать способ
передачи двумерных массивов. Или возможен следующий вариант:
void ProcString(char *str[], int n)
{
for(int i=0;i<n;i++){
for(int j=0;str[i][j]!=0;j++)
if(islower(str[i][j])) str[i][j] = 'A' + (str[i][j] - 'a');
else if(isupper(str[i][j])) str[i][j] = 'a' + (str[i][j] - 'A');
}
}
int main(int argc, char *argv[])
{
char string[][20] = {"One","Two","Three","Four","Five"};
char *strs[] = {string[0],string[1],string[2],string[3],string[4]};
for(int i=0;i<5;i++) puts(string[i]);
ProcString(strs,5);
for(int i=0;i<5;i++) puts(string[i]);
return 0;
}

40. Передача параметров

В языке С, как и во многих других языках
программирования высокого уровня, используется механизм
передачи параметров через стек. Т.е. сначала все
параметры заносятся в стек, а затем вызывается функция.
Существует два метода передачи параметров через стек:
в прямом порядке,
в обратном порядке.

41. Нижний уровень передачи параметров

В языке С по умолчанию используется метод передачи в
обратном порядке. Если необходимо изменить направление
передачи параметров или явно его указать, то перед
именем функции указывают одно из ключевых слов:
_stdcall (или __stdcall) – передача параметров в прямом
порядке;
_cdecl (или __cdecl) – передача параметров в обратном
порядке.
Например:
int __cdecl Function(int ind, double x, double y);
char * __stdcall Function(char *strs[], int num);
English     Русский Rules