Float sum(float a, float b, float c)

{float S=a+b+c;

return S;}

Пример. Функция находит большее из двух переменных. Функция имеет формальные параметры и два оператора return.

int max(int x, int y)

{if (x>y)return x;

else return y;}

Пример. Функция выводит значение переменной на экран. Функция имеет один формальный параметр и не имеет оператора return.

void prn1(int x)

{ printf("Заданное число =%d\n", x);}

Пример. Функция выводит строку на экран. Функция не имеет фор­мальных параметров и оператора return.

void prn2()

{ puts("Моя программа");}

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

имя_функции(список фактических параметров)

где список_фактических_параметров – это либо пусто, либо void, либо фактические параметры (константы или заранее определенные переменные, переменные с преобразованием типов, выражения).

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

Например:

int max(int x, int y)

{if (x>y)return x; else return y;}

void main()

{int a=10,res1,res2; float f=55.9;

res1=max(a,20); // res1=20

res2=max(int(f),a+30);} // res2=55

Пример.

int func1(int a, int b) // Определение функции

{return a+b;}

float sqr(float f, float g) // Определение функции

{return f*g;}

void main()

{int am=2,bm=3,res1;

res1=func1(am,bm); // Вызов функции

float em=2.5,gm=3.0,fm=4.2,res2,res3;

res2=sqr(fm,gm); // Вызов функции

res3=sqr(fm+0.5,sqr(em,gm)); // Вызов функции

int res4=(int)sqr(em,float(am)); } // Вызов функции

Если функция определена после функции main() или в другом файле, то до первого обращения к функции она должна быть описана. Описание функции называется прототипом. Это необходимо для проверки компилятором соответствия типов передаваемых в функцию параметров и возвращаемых значений. В прототипе можно не указывать имена формальных параметров. В конце прототипа обязательна точка с запятой. Примеры прототипов:

float sum(float a, float b, float c);

int max(int, int y);

float sqr(float, float g);

Пример. Функция определена ниже своего первого вызова, перед вызовом помещен прототип.

#include <stdio.h>

int sum(int, int);// Прототип функции – описание функции

void main()

{int a, b=3, g=4;

a=sum(b, g); // Вызов функции

printf("Сумма=%d\n", a); }

int sum(int arg1, int arg2) // Определение функции

{return arg1+arg2;}

2.2 Передача параметров в функции по значению и по указателю

В языке С++ передача параметров (кроме указателей и массивов) в функции при их вызове осуществляется по значению. Это означает, что для передаваемых (фактических) параметров в функции создаются копии этих параметров. Для формальных параметров выделяется память, в которую заносятся значения фактических параметров. Действия, производимые с этими параметрами (копиями) в функции не влияют на переменные вне функции, т.е. на фактические пере­менные. Формальные параметры недоступны вне тела функции. При выходе из функции выделенная для них память освобождается.

Пример.

#include <stdio.h>

void func(int intg,float fltp)

{printf("intg=%d &intg=%p ",intg, &intg);

printf("fltp=%f &fltp=%p\n",fltp, &fltp);

intg+=10; fltp*=2;

printf("intg_n=%d fltp_n=%f\n",intg,fltp);}

void main()

{int i=200; float f=100.25;

func(i,f);

printf("i=%d &i=%p f=%f &f=%p\n",i,&i,f,&f);}

В результате работы программы на экран выведется:

intg=200 &intg=8FD8:0FF2 fltp=100.25 &fltp=8FD8:0FF4

intg_n=210 fltp_n=200.5

i=200 &i=8FD8:0FFC f=100.25 &f=8FD8:0FF8

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

Пример. В функцию передаются указатели на переменные и значения этих переменных меняются местами:

#include <stdio.h>

void swap(int *a, int *b) // Определение функции

{printf("&a=%p a=%p *a=%d\n",&a,a,*a);

printf("&b=%p b=%p *b=%d\n",&b,b,*b);

int tmp=*a; *a=*b; *b=tmp;

printf("*a_n=%d *b_n=%d\n",*a,*b);}

void main()

{int i=5,j=60;

printf("&i=%p i=%d &j=%p j=%d\n",&i,i,&j,j);

swap(&i,&j); // Вызов функции

printf("i=%d j=%d\n",i,j);}

В результате работы программы на экран выведется:

&i=8FD8:0FFE i=5 &j=8FD8:0FFC j=60

&a=8FD8:0FF4 a=8FD8:0FFE *a=5

&b=8FD8:0FF8 b=8FD8:0FFC *b=60

*a_n=60 *b_n=5

i=60 j=5

2.3 Функции и массивы

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

int func1(int arr[]) {...}

или int func2(int *mass) {...}

В обоих случаях в функции создается копия указателя соответст­вующего типа, который действует внутри функции как обычный ука­затель-переменная и может изменять свое значение. Например, arr++. Доступ к элементам массива внутри функции может осуществляться как с помощью индексов (arr[1], arr[i]), так и применяя опера­цию разыменования указателя (*(arr+1), *(arr+i)).

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

Есть два способа определения конца массива: 1) в качестве одного из параметров в функцию передается размер массива; 2) последний элемент массива задается каким-либо уникальным значением, которое анализируют в функции.

Пример. Функция вычисляет сумму элементов массива, в качестве одного из параметров в функцию передается размер массива.

#include <stdio.h>

int sum(int N,int x[]) // Определение функции

{int S=0;

for(int i=0;i<N;i++) S+=x[i];

return S;}

void main()

{int a[5]={1,3,5,10,2},c[3]={2,1,6},res1,res2;

res1=sum(5,a); // Вызов функции

printf("сумма элементов массива a=%d\n",res1); // 21

res2=sum(3,c); // Вызов функции

printf("сумма элементов массива c=%d\n",res2);} // 9

Пример. Функция вычисляет количество символов в слове, в качестве признака конца массива используется '\0'.

#include <stdio.h>

int len(char *); // Прототип функции

void main()

{char *name="TERMINATOR";

printf("Длина 1-ой строки=%d",len(name)); // 10

char *str="Высшая математика";

printf("Длина 2-ой строки=%d",len(str)); } // 17

int len(char *c) // Определение функции

{int i=0;

while(c[i++]);

return i-1; } // длина строки без учета символа ' \0 '

Пример. Функция изменяет значения элементов массива, поменяв их на квадраты этих значений, тип функции void

#include <stdio.h>

void exch(int, int []); // Прототип функции

void main()

{int a[5]={1,3,5,8,2};

printf("Массив до изменения: ");

for(int i=0;i<5;i++) printf(" %d",a[i]);

exch(5,a); // Вызов функции

printf("\nМассив после изменения: ");

for(int i=0;i<5;i++) printf(" %d",a[i]);

}

void exch(int N,int x[]) // Определение функции

{for(int i=0;i<N;i++) x[i]*=x[i];}

В результате на экран выведется:

Массив до изменения: 1 3 5 8 2.

Массив после изменения: 1 9 25 64 4.

2.4 Функции с умалчиваемыми значениями параметров

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

тип имя_параметра=умалчиваемое_значение

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

Пример. Функция находит произведение 2-х переменных

#include <stdio.h>

int def(int a=10, int b=3){return a*b;}

void main()

{int am=2, bm=5, res1,res2,res3;

res1=def(); // 10*3=30

res2=def(am); // 2*3=6

res3=def(am,bm); // 2*5=10

printf("res1=%d res2=%d res3=%d\n",res1,res2,res3); }

В результате работы программы на экран выведется:

res1=30 res2=6 res3=10

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

Пример. Функция находит сумму 3-х переменных

#include <stdio.h>

int sum(int,int=5,int=10); // Прототип функции

void main()

{int am=20, bm=50, cm=100, s1,s2,s3,s4;

s1=sum(am); // 20+5+10=35

s2=sum(am,bm); // 20+50+10=80

s3=sum(am,bm,cm); // 20+50+100=170

printf("s1=%d s2=%d s3=%d\n",s1,s2,s3);}

int sum(int a,int b,int c) // Определение функции

{return a+b+c;}

В результате работы программы на экран выведется:

s1=35 s2=80 s3=170

2.5 Функции с переменным числом параметров

Функции с переменным числом параметров – это функции, в ко­торых количество и типы параметров определяются только во время их вызова. Синтаксис определения прототипа таких функций:

тип имя(спецификация явных параметров,...);

Последняя запятая необязательна. Многоточие сообщает компи­лятору, что не нужно проводить дальнейший контроль соответствия количества параметров и их типов при обработке вызова. Переход в списке от параметра к параметру осуществляется с помощью указате­ля, тип которого является типом переменной. При увеличении указа­теля на единицу осуществляется переход к следующей переменной такого же типа. В ВС31 функции с переменным числом параметров не работают с типами char, unsigned char, float.

В таких функциях существуют два способа определения коли­чества параметров: 1) передача в функцию в списке фактических параметров информации об их количестве; 2) добавление параметра–индикатора в конец списка фактических параметров.

Пример. В функцию передается в списке явных параметров количес­тво элементов, которые суммируются.

#include <stdio.h>

int sumi(int i,...)// Определение функции

{int *num=&i; // 1-й параметр – число переменных в списке

int sum=0;

for(;i;i--) sum+=*(++num);// вычисляем сумму со 2-го элемента

return sum;}

double sumd(int i,double d...)// Определение функции

{double *ptr=&d; // указатель на 2-й параметр типа double

double sum=0.0;

for(;i;i--) // 1-й параметр – число переменных в списке

sum+=*(ptr++);

return sum;}

void main()

{int a1=10,a2=20,a3=30,s1,s2;

s1=sumi(3,a1,a2,a3); // сумма 3-х чисел a1,a2,a3

s2=sumi(6,1,a1,3,a2,a3,4); // сумма 6-и чисел

double d1=5.7, d2=1.3,s3;

s3=sumd(4,d1,1.25,d2,2.5); // сумма 4-х чисел

printf("s1=%d s2=%d s3=%.2lf\n",s1,s2,s3);}

В результате работы программы на экран выведется:

s1=60 s2=68 s3=10.75

Пример. В функции вычисляется произведение элементов, при этом каждый элемент сравнивается с параметром–индикатором, который находится в конце списка явных параметров.

#include <stdio.h>

#define term 0.0

double mult(double arg...) // Определение функции

{double a=1.0, *ptr=&arg;

if(*ptr==0.0) return 0.0;

for(;*ptr!=term;ptr++)

a*=*ptr;

return a;}

void main()

{double a=2.5,b=2.0,md1,md2;

md1=mult(a,b,0.3,term);

md2=mult(0.5,a,4.0,b,1.1,term);

printf("md1=%.2lf md2=%.2lf\n",md1,md2);}

В результате работы программы на экран выведется:

md1=1.50 md2=11.00

При работе с функциями, имеющими переменное параметров, имеется набор макроопределений, помещенных в заголовочном файле stdarg.h:

Макрокоманда void va_start (va_list param, последний явный параметр) связываетвспомогательный параметр param с последним явным параметром в списке.

Макрокоманда type va_arg (va_list param,type) переме­щает указатель param на число байтзаданного типа type.

Макрокоманда va_end (va_list param) вызывается после обработки списка и организует корректный возврат из функции (вместо оператора return).

2.6 Передача параметров в функцию main()

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

[тип] main(int argc, char **argv){...}

[тип] main(int argc, char **argv, char **envp){...}

[тип] – тип функции main может быть void или int.

Параметр int argc определяет число слов в командной строке.

Параметр char **argv ‑ указатель на массив строк, вводимых из командной строки. Массив строк –это массив указателей, являющихся адресами первых символов этих строк. Размер этого массива строк равен argc. Нулевое слово, на которое указывает указатель argv[0], всегда является спецификацией запускаемой на выполнение програм­мы (именем программы с расширением .exe).

Параметр char **envp ‑ это указатель на массив указателей на строки среды программы. С помощью этого параметра в программу можно передать всю информацию среде окружения программы, ко­торая определяет некоторые особенности операционной системы и др.

В следующих примерах демонстрируется передача параметров в функцию main. Для работы программ их необходимо запустить из командной строки, например в среде FAR, NC, VC, DN и др.

Пример.

#include <stdio.h>

#include <conio.h>

int main(int argc,char**argv,char**envp)

{clrscr();

for(int i=0;i<argc;i++)

printf("argv[%d]=%s\n",i,argv[i]);

getch();

puts("Среда окружения");

while(*envp) puts(*envp++);

getch();

return 0;}

Пусть исполняемый файл этой программы prog1.exe располо­жен в корневом каталоге диска C:\. Тогда, если в командной строке набрать c:\>prog1.exe my age 19, то результат работы программы может быть такой:

argv[0]=C:\PROG1.EXE

argv[1]=my

argv[2]=age

argv[3]=19


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  




Подборка статей по вашей теме: