Часто в программе требуется повторить определенную последовательность операторов в разных частях программы. Для того, чтобы описывать эту последовательность один раз, а применять многократно, в языках программирования применяются подпрограммы. Подпрограмма - автономная часть программы, выполняющая определенный алгоритм и допускающая обращение к ней из различных частей общей программы.
В языке Си существует один вид подпрограмм - функции. Каждая программа в своем составе должна иметь главную функцию main(), служащую точкой входа в программу. Кроме функции main(), в программу может входить произвольное число функций, выполнение которых инициализируется вызовами из функции main(). Каждая функция по отношению к другой является внешней. Для того, чтобы функция была доступной, необходимо, чтобы до ее вызова о ней было известно компилятору. Форма записи функции:
<тип > <имя функции>(<формальные параметры>){<тело функции >}
Если тип возвращаемого функцией значения не указан, то подразумевается int. Если с именем функции не связан результат, то нужно указать тип функции void. Параметры, записываемые в обращении к функции, называются фактическими; параметры, указанные в описании функции - формальными. Фактические параметры должны соответствовать формальным по количеству, порядку следования и типу. Объекты, объявленные вне функции, действуют в любой функции и называются глобальными. Объекты, объявленные в функции, действуют только в ней и называются локальными. В теле функции обычно присутствует оператор return <выражение>, определяющий возвращаемое функцией значение.
Все параметры функции, кроме массивов, передаются по значению, т.е. внутри функции создаются локальные копии параметров. Если необходимо передать саму переменную, а не её копию, то в функцию передаётся адрес этой переменной. Таким образом, через параметры можно передавать результат выполнения функции. То есть, параметры, с помощью которых результаты должны передаваться из функции в точку вызова, описываются как указатели. Вызов функции может быть оформлен в виде оператора, если с именем функции не связано возвращаемое значение, или в виде выражения, если возвращаемое значение связано с именем функции.
Прототип функции может указываться до вызова функции вместо описания функции для того, чтобы компилятор мог выполнить проверку соответствия типов аргументов и параметров. Прототип функции по форме такой же, как и заголовок функции. В конце него ставится “;”.
Функции можно подключать с помощью директивы #include <имя файла>. Такие файлы с функциями удобно использовать в диалоговых программах с пользовательским меню, позволяющих выбрать один из режимов.
Пример 1: Функция с параметрами-значениями. Результат связан с именем функции. В программе объявляется прототип функции, а сама функция описывается ниже.
#include <stdio.h> #include <conio.h> int max(int,int); //Прототип функции void main() {int x,y,z; printf(" input x,y "); scanf("%d%d",&x,&y); z=max(x,y); //Вызов функции с фактическими параметрами printf("x=%d y=%d max=%d",x,y,z); getch(); } int max(int a ,int b) //Заголовок функции с формальными параметрами {int c; if (a>b) c=a; else c=b; return c; }
Пример 2: Функция с параметрами-указателями. Здесь передаются адреса фактических параметров, по которым и получаем результат. Функция меняет местами переменные x,y.
#include <stdio.h> #include <conio.h> void swap(float *, float *); // Прототип функции с параметрами - указателями main() { float x,y; printf("\n введите x,y "); scanf("%f%f",&x,&y); swap(&x,&y); // Передаём адреса переменных printf("\n x=%4.2f y=%4.2f ",x,y); getch(); } void swap(float * a, float * b) { float c; c=*a; // *a - содержимое по адресу a *a=*b; *b=c; }
Пример 3: Подключение файлов с функциями и создание меню.
! Внимание! Следите за тем, чтобы константы, объявленные директивой #define, не переобъявлялись в функциях.
#include <stdio.h> #include <conio.h> #include "lab3.c" #include "lab4.c" #include "lab5.c" main() {int nom; while(1) {clrscr(); printf("\n 1. Сумма ряда \n"); printf(" 2. Матрица \n"); printf(" 3. Строки \n"); printf(" 4. Выход \n"); scanf("%d",&nom); switch(nom) { case 1:lab3();break; case 2:lab5();break; case 3:lab6();break; case 4:return 0; default:printf("Неверный режим"); } } getch(); }
Пример 4: Передача в функцию массива с использованием указателя. Результат – элементы массива возводятся в квадрат. Функция описывается до вызова, поэтому прототип не объявляется.
#include <stdio.h> #include <conio.h> void quart(int n, float * x) // Можно void quart(int n, float x[]) {int i; for (i=0;i<n;i++) x[i]=x[i]*x[i]; } main() {float z[]={1,2,3,4}; int j; clrscr(); for (j=0; j<4; j++) printf(" %6.2f",z[j]); quart(4,z); for (j=0; j<4; j++) printf("\n %6.2f",z[j]); getch(); }
1. Описание функции. Для чего объявляется прототип?
2. Что такое формальные и фактические параметры?
3. Как определяются локальные и глобальные параметры?
4. Как можно передавать массив в функцию?
5. Способы вызова функций.
6. Как можно передать результат выполнения функции ?