Программирование

145
Программирование Часть 5 Функции

Upload: xyla-cantu

Post on 30-Dec-2015

58 views

Category:

Documents


1 download

DESCRIPTION

Программирование. Часть 5 Функции. 4 . Структурное программирование 4 .10. Функции. void input_vect (double v [ ], int dim) { … return; }. Структурная декомпозиция программы. Выполнение начинается с main. int main() { … input_vect ( a,n ); … add_vect ( a,b,c,n ); - PowerPoint PPT Presentation

TRANSCRIPT

Программирование

Часть 5Функции

4. Структурное программирование 4.10. Функции

Структурная декомпозиция программы

int main(){ … input_vect (a,n); …

add_vect (a,b,c,n); … output_vect (c,n); … return 0 }

void input_vect (double v [ ], int dim){ …return; }

void add_vect (double v1 [ ], double v2 [ ], double res [ ], int dim)

{ … return; }

void output_vect (double v [ ], int dim){ … return; }

Выполнение начинается с main

Возврат из main в ОС

4. Структурное программирование 4.10. Функции

Структурная декомпозиция программы

int main(){ … input_vect (a,n); …

add_vect (a,b,c,n); … output_vect (c,n); … return 0 }

void input_vect (double v [ ], int dim){ …return; }

void add_vect (double v1 [ ], double v2 [ ], double res [ ], int dim)

{ … return; }

void output_vect (double v [ ], int dim){ … return; }

Выполнение начинается с main

Возврат из main в ОС

4. Структурное программирование 4.10. Функции

Структурная декомпозиция программы

int main(){ … input_vect (a,n); …

add_vect (a,b,c,n); … output_vect (c,n); … return 0 }

void input_vect (double v [ ], int dim){ …return; }

void add_vect (double v1 [ ], double v2 [ ], double res [ ], int dim)

{ … return; }

void output_vect (double v [ ], int dim){ … return; }

Выполнение начинается с main

Возврат из main в ОС

4. Структурное программирование 4.10. Функции

Структурная декомпозиция программы

int main(){ … input_vect (a,n); …

add_vect (a,b,c,n); … output_vect (c,n); … return 0 }

void input_vect (double v [ ], int dim){ …return; }

void add_vect (double v1 [ ], double v2 [ ], double res [ ], int dim)

{ … return; }

void output_vect (double v [ ], int dim){ … return; }

Выполнение начинается с main

Возврат из main в ОС

4. Структурное программирование 4.10. Функции

Структурная декомпозиция программы

int main(){ … input_vect (a,n); …

add_vect (a,b,c,n); … output_vect (c,n); … return 0 }

void input_vect (double v [ ], int dim){ …return; }

void add_vect (double v1 [ ], double v2 [ ], double res [ ], int dim)

{ … return; }

void output_vect (double v [ ], int dim){ … return; }

Выполнение начинается с main

Возврат из main в ОС

4. Структурное программирование 4.10. Функции

Структурная декомпозиция программы

int main(){ … input_vect (a,n); …

add_vect (a,b,c,n); … output_vect (c,n); … return 0 }

void input_vect (double v [ ], int dim){ …return; }

void add_vect (double v1 [ ], double v2 [ ], double res [ ], int dim)

{ … return; }

void output_vect (double v [ ], int dim){ … return; }

Выполнение начинается с main

Возврат из main в ОС

4. Структурное программирование 4.10. Функции

Структурная декомпозиция программы

int main(){ … input_vect (a,n); …

add_vect (a,b,c,n); … output_vect (c,n); … return 0 }

void input_vect (double v [ ], int dim){ …return; }

void add_vect (double v1 [ ], double v2 [ ], double res [ ], int dim)

{ … return; }

void output_vect (double v [ ], int dim){ … return; }

Выполнение начинается с main

Возврат из main в ОС

4. Структурное программирование 4.10. Функции

Структурная декомпозиция программы

int main(){ … input_vect (a,n); …

add_vect (a,b,c,n); … output_vect (c,n); … return 0 }

void input_vect (double v [ ], int dim){ …return; }

void add_vect (double v1 [ ], double v2 [ ], double res [ ], int dim)

{ … return; }

void output_vect (double v [ ], int dim){ … return; }

Выполнение начинается с main

Возврат из main в ОС

4. Структурное программирование 4.10. Функции

Структурная декомпозиция программы

int main(){ … input_vect (a,n); …

add_vect (a,b,c,n); … output_vect (c,n); … return 0 }

void input_vect (double v [ ], int dim){ …return; }

void add_vect (double v1 [ ], double v2 [ ], double res [ ], int dim)

{ … return; }

void output_vect (double v [ ], int dim){ … return; }

Выполнение начинается с main

Возврат из main в ОС

4. Структурное программирование 4.10. Функции

Структурная декомпозиция программы

int main(){ … input_vect (a,n); …

add_vect (a,b,c,n); … output_vect (c,n); … return 0 }

void input_vect (double v [ ], int dim){ …return; }

void add_vect (double v1 [ ], double v2 [ ], double res [ ], int dim)

{ … return; }

void output_vect (double v [ ], int dim){ … return; }

Выполнение начинается с main

Возврат из main в ОС

4. Структурное программирование 4.10. Функции

Структурная декомпозиция программы

int main(){ … input_vect (a,n); …

add_vect (a,b,c,n); … output_vect (c,n); … return 0 }

void input_vect (double v [ ], int dim){ …return; }

void add_vect (double v1 [ ], double v2 [ ], double res [ ], int dim)

{ … return; }

void output_vect (double v [ ], int dim){ … return; }

Выполнение начинается с main

Возврат из main в ОС

4. Структурное программирование 4.10. Функции

Структурная декомпозиция программы

int main(){ … input_vect (a,n); …

add_vect (a,b,c,n); … output_vect (c,n); … return 0 }

void input_vect (double v [ ], int dim){ …return; }

void add_vect (double v1 [ ], double v2 [ ], double res [ ], int dim)

{ … return; }

void output_vect (double v [ ], int dim){ … return; }

Выполнение начинается с main

Возврат из main в ОС

4. Структурное программирование 4.10. Функции

Структурная декомпозиция программы

int main(){ … input_vect (a,n); …

add_vect (a,b,c,n); … output_vect (c,n); … return 0 }

void input_vect (double v [ ], int dim){ …return; }

void add_vect (double v1 [ ], double v2 [ ], double res [ ], int dim)

{ … return; }

void output_vect (double v [ ], int dim){ … return; }

Выполнение начинается с main

Возврат из main в ОС

4. Структурное программирование 4.10. Функции

Структурная декомпозиция программы

int main(){ … input_vect (a,n); …

add_vect (a,b,c,n); … output_vect (c,n); … return 0 }

void input_vect (double v [ ], int dim){ …return; }

void add_vect (double v1 [ ], double v2 [ ], double res [ ], int dim)

{ … return; }

void output_vect (double v [ ], int dim){ … return; }

Выполнение начинается с main

Возврат из main в ОС

4. Структурное программирование 4.10. Функции

Структурная декомпозиция программы

int main(){ … input_vect (a,n); …

add_vect (a,b,c,n); … output_vect (c,n); … return 0 }

void input_vect (double v [ ], int dim){ …return; }

void add_vect (double v1 [ ], double v2 [ ], double res [ ], int dim)

{ … return; }

void output_vect (double v [ ], int dim){ … return; }

Выполнение начинается с main

Возврат из main в ОС

Функция – изолированный именованный блок кода, имеющий определенное назначение

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

Эти аргументы должны соответствовать формальным параметрам, указанным в описании функции.

4. Структурное программирование 4.10. Функции

int k = add_ints (2,3);

int add_ints (int a, int b){ return a+b;}

аргументы

формальные параметры

Значения аргументов заменяют соответствующие параметры в определении функции

Возвращается значение 5

Структура функций

Тип_Возврата Имя_функции (список_параметров){ операторы;

return выражение; } Область видимости параметров функции, объявленных в ее

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

Эти переменные, если они не объявлены с атрибутом static уничтожаются после завершения выполнения функции, а хранимые ими значения безвозвратно теряются.

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

4. Структурное программирование 4.10. Функции

Заголовок

Тело функции

Прототипы функций К моменту вызова функции компилятор должен иметь информацию

о ней, чтобы скомпилировать правильно ее вызов. Если текст функции размещен в файле с исходным текстом после

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

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

Описание прототипа ничем не отличается от описания заголовка функции:

Тип_Возврата Имя_функции (список_параметров); Описание прототипа, в отличие от заголовка, заканчивается точкой

с запятой.

4. Структурное программирование 4.10. Функции

4. Структурное программирование 4.10. Функции

void input_vect(double v[ ],int n);void output_vect(double v[ ],int n);

int main() { const int m=5; double x[5];

input_vect(x,m); output_vect(x,m);

return 0;}

void print_vector (double v[ ], int n){ cout << endl << "The vector is:"; for (int i=0; i<=n-1; i++) cout <<setw(10)<<v[i]; cout << endl; return;}

void input_vect( double v[ ], int n){ for (int i=0; i<=n-1; i++) { cout << "Enter vector[" << i << "] :"; cin >> v[i]; } return;}

Простой пример:функции для ввода и вывода одномерного массива

Способы передачи данных в вызываемую функцию

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

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

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

4. Структурное программирование 4.10. Функции

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

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

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

Значения аргументов копируются в созданные переменные. По завершении работы функции обратное копирование из

формальных параметров в переменные - аргументы не производится.

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

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

4. Структурное программирование 4.10. Функции

int my(int i);int main() { int k=3, m=0; m=my(k); cout << k << " " << m; // 3 8 _getch(); return 0;}int my(int i){ int p=2; i*=2; return p+i;}

3 0

F5C F5E F60 F62 F64 F66 F68 F7A F7C F7E F80

k m

АЛУ

4. Структурное программирование 4.10. Функции

Передача аргументов по значению

int my(int i);int main() { int k=3, m=0; m=my(k); cout << k << " " << m; // 3 8 _getch(); return 0;}int my(int i){ int p=2; i*=2; return p+i;}

3 3 0

F5C F5E F60 F62 F64 F66 F68 F7A F7C F7E F80

k mi

АЛУ

4. Структурное программирование 4.10. Функции

Передача аргументов по значению

int my(int i);int main() { int k=3, m=0; m=my(k); cout << k << " " << m; // 3 8 _getch(); return 0;}int my(int i){ int p=2; i*=2; return p+i;}

2 3 3 0

F5C F5E F60 F62 F64 F66 F68 F7A F7C F7E F80

k mip

АЛУ

4. Структурное программирование 4.10. Функции

Передача аргументов по значению

int my(int i);int main() { int k=3, m=0; m=my(k); cout << k << " " << m; // 3 8 _getch(); return 0;}int my(int i){ int p=2; i*=2; return p+i;}

2 3 3 0

F5C F5E F60 F62 F64 F66 F68 F7A F7C F7E F80

k mip

АЛУ3*2 = 6

4. Структурное программирование 4.10. Функции

Передача аргументов по значению

int my(int i);int main() { int k=3, m=0; m=my(k); cout << k << " " << m; // 3 8 _getch(); return 0;}int my(int i){ int p=2; i*=2; return p+i;}

2 6 3 0

F5C F5E F60 F62 F64 F66 F68 F7A F7C F7E F80

k mip

АЛУ3*2 = 6

4. Структурное программирование 4.10. Функции

Передача аргументов по значению

int my(int i);int main() { int k=3, m=0; m=my(k); cout << k << " " << m; // 3 8 _getch(); return 0;}int my(int i){ int p=2; i*=2; return p+i;}

2 6 3 0

F5C F5E F60 F62 F64 F66 F68 F7A F7C F7E F80

k mip

АЛУ2+6 =

4. Структурное программирование 4.10. Функции

Передача аргументов по значению

int my(int i);int main() { int k=3, m=0; m=my(k); cout << k << " " << m; // 3 8 _getch(); return 0;}int my(int i){ int p=2; i*=2; return p+i;}

8 2 6 3 0

F5C F5E F60 F62 F64 F66 F68 F7A F7C F7E F80

k mip

АЛУ2+6 = 8

4. Структурное программирование 4.10. Функции

my

Передача аргументов по значению

int my(int i);int main() { int k=3, m=0; m=my(k); cout << k << " " << m; // 3 8 _getch(); return 0;}int my(int i){ int p=2; i*=2; return p+i;}

8 3 8

F5C F5E F60 F62 F64 F66 F68 F7A F7C F7E F80

k m

АЛУ

4. Структурное программирование 4.10. Функции

my

Передача аргументов по значению

Передача аргументов в функцию по ссылке

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

Копии аргументов с именами формальных параметров не создаются.

Вместо этого, по ссылке обеспечивается доступ к участкам памяти, занимаемым аргументами.

Говоря другими словами, обработка аргументов ведется «на месте».

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

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

Если в качестве аргумента по ссылке передается константа, то формальный параметр-ссылка должен быть объявлен с модификатором const.

4. Структурное программирование 4.10. Функции

int my(int &i);int main() { int k=3, m=0; m=my(k); cout << k << " " << m; // 6 8 _getch(); return 0;}int my(int &i){ int p=2; i*=2; return p+i;}

3 0

F5C F5E F60 F62 F64 F66 F68 F7A F7C F7E F80

k m

АЛУ

4. Структурное программирование 4.10. Функции

Передача аргументов в функцию по ссылке

int my(int &i);int main() { int k=3, m=0; m=my(k); cout << k << " " << m; // 3 8 _getch(); return 0;}int my(int &i){ int p=2; i*=2; return p+i;}

3 0

F5C F5E F60 F62 F64 F66 F68 F7A F7C F7E F80

k m

i

АЛУ

4. Структурное программирование 4.10. Функции

Передача аргументов в функцию по ссылке

int my(int &i);int main() { int k=3, m=0; m=my(k); cout << k << " " << m; // 3 8 _getch(); return 0;}int my(int &i){ int p=2; i*=2; return p+i;}

2 3 0

F5C F5E F60 F62 F64 F66 F68 F7A F7C F7E F80

k mp

АЛУ

4. Структурное программирование 4.10. Функции

i

Передача аргументов в функцию по ссылке

int my(int &i);int main() { int k=3, m=0; m=my(k); cout << k << " " << m; // 3 8 _getch(); return 0;}int my(int &i){ int p=2; i*=2; return p+i;}

2 3 0

F5C F5E F60 F62 F64 F66 F68 F7A F7C F7E F80

k mp

АЛУ3*2 = 6

4. Структурное программирование 4.10. Функции

i

Передача аргументов в функцию по ссылке

int my(int &i);int main() { int k=3, m=0; m=my(k); cout << k << " " << m; // 3 8 _getch(); return 0;}int my(int &i){ int p=2; i*=2; return p+i;}

2 6 0

F5C F5E F60 F62 F64 F66 F68 F7A F7C F7E F80

k mp

АЛУ3*2 = 6

4. Структурное программирование 4.10. Функции

i

Передача аргументов в функцию по ссылке

int my(int &i);int main() { int k=3, m=0; m=my(k); cout << k << " " << m; // 3 8 _getch(); return 0;}int my(int &i){ int p=2; i*=2; return p+i;}

2 6 0

F5C F5E F60 F62 F64 F66 F68 F7A F7C F7E F80

k mp

АЛУ2+6 =

4. Структурное программирование 4.10. Функции

i

Передача аргументов в функцию по ссылке

int my(int &i);int main() { int k=3, m=0; m=my(k); cout << k << " " << m; // 3 8 _getch(); return 0;}int my(int &i){ int p=2; i*=2; return p+i;}

2 6 0

F5C F5E F60 F62 F64 F66 F68 F7A F7C F7E F80

k mp

АЛУ2+6 = 8

4. Структурное программирование 4.10. Функции

i

Передача аргументов в функцию по ссылке

int my(int &i);int main() { int k=3, m=0; m=my(k); cout << k << " " << m; // 3 8 _getch(); return 0;}int my(int &i){ int p=2; i*=2; return p+i;}

8 6 8

F5C F5E F60 F62 F64 F66 F68 F7A F7C F7E F80

k m

АЛУ

4. Структурное программирование 4.10. Функции

my

Передача аргументов в функцию по ссылке

Передача массивов по ссылке

Массивы передаются в функции по ссылке. При этом записывать перед формальным параметров знак ссылки & не следует:

int example (short a[3]); При описании в качестве формального параметра одномерного

массива, его размер указывать необязательно:int example(short a[ ]);

При описании в качестве формального параметра многомерного массива, его размер по левому измерению указывать необязательно:

int example(short y[ ][4][3]);

4. Структурное программирование 4.10. Функции

void set(short [ ][3], int);int main() { short a[2][3]={0}; set(a,2); return 0;}void set (short k[ ][3], int m) { for (short i=0; i<=m-1; i++) for (short j = 0; j<=2; j++) k[i][j]=i+j; return;} 0 0 0 0 0 0

F5C F5E F60 F62 F64 F66 F68 F7A F7C F7E F80

a

4. Структурное программирование 4.10. Функции

2

F2E F30 F32 F34 F36 …

Передача массивов по ссылке

void set(short [ ][3], int);int main() { short a[2][3]={0}; set(a,2); return 0;}void set (short k[ ][3], int m) { for (short i=0; i<=m-1; i++) for (short j = 0; j<=2; j++) k[i][j]=i+j; return;} 2 0 0 0 0 0 0

F5C F5E F60 F62 F64 F66 F68 F7A F7C F7E F80

4. Структурное программирование 4.10. Функции

2

F2E F30 F32 F34 F36 …

a

k

m

Передача массивов по ссылке

void set(short [ ][3], int);int main() { short a[2][3]={0}; set(a,2); return 0;}void set (short k[ ][3], int m) { for (short i=0; i<=m-1; i++) for (short j = 0; j<=2; j++) k[i][j]=i+j; return;} 0 0 2 0 0 0 0 0 0

F5C F5E F60 F62 F64 F66 F68 F7A F7C F7E F80

4. Структурное программирование 4.10. Функции

2

F2E F30 F32 F34 F36 …

a

k

mj i

Передача массивов по ссылке

void set(short [ ][3], int);int main() { short a[2][3]={0}; set(a,2); return 0;}void set (short k[ ][3], int m) { for (short i=0; i<=m-1; i++) for (short j = 0; j<=2; j++) k[i][j]=i+j; return;} 0 0 2 0 1 2 1 2 3

F5C F5E F60 F62 F64 F66 F68 F7A F7C F7E F80

4. Структурное программирование 4.10. Функции

2

F2E F30 F32 F34 F36 …

a

k

mj i

Передача массивов по ссылке

void set(short [ ][3], int);int main() { short a[2][3]={0}; set(a,2); return 0;}void set (short k[ ][3], int m) { for (short i=0; i<=m-1; i++) for (short j = 0; j<=2; j++) k[i][j]=i+j; return;} 0 1 2 1 2 3

F5C F5E F60 F62 F64 F66 F68 F7A F7C F7E F80

4. Структурное программирование 4.10. Функции

2

F2E F30 F32 F34 F36 …

a

Передача массивов по ссылке

Передача указателей в функции

Указатели обычно передаются по значению. Доступ к объектам, на которые они указывают при этом происходит «на месте».

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

4. Структурное программирование 4.10. Функции

int my(int *i);int main() { int k=3, m=0; m=my(&k); cout << k << " " << m; // 6 8 _getch(); return 0;}int my(int *i){ int p=2; *i *= 2; return p + *i;}

3 0

F5C F5E F60 F62 F64 F66 F68 F7A F7C F7E F80

k m

АЛУ

4. Структурное программирование 4.10. Функции

Передача указателей в функции

F7A 3 0

F5C F5E F60 F62 F64 F66 F68 F7A F7C F7E F80

k m&i

АЛУ

4. Структурное программирование 4.10. Функции

int my(int *i);int main() { int k=3, m=0; m=my(&k); cout << k << " " << m; // 6 8 _getch(); return 0;}int my(int *i){ int p=2; *i *= 2; return p + *i;}

Передача указателей в функции

2 F7A 3 0

F5C F5E F60 F62 F64 F66 F68 F7A F7C F7E F80

k mp

АЛУ

4. Структурное программирование 4.10. Функции

int my(int *i);int main() { int k=3, m=0; m=my(&k); cout << k << " " << m; // 6 8 _getch(); return 0;}int my(int *i){ int p=2; *i *= 2; return p + *i;}

&i

Передача указателей в функции

2 F7A 3 0

F5C F5E F60 F62 F64 F66 F68 F7A F7C F7E F80

k mp

АЛУ3*2 = 6

4. Структурное программирование 4.10. Функции

int my(int *i);int main() { int k=3, m=0; m=my(&k); cout << k << " " << m; // 6 8 _getch(); return 0;}int my(int *i){ int p=2; *i *= 2; return p + *i;}

&i

Передача указателей в функции

2 F7A 6 0

F5C F5E F60 F62 F64 F66 F68 F7A F7C F7E F80

k mp

АЛУ3*2 = 6

4. Структурное программирование 4.10. Функции

int my(int *i);int main() { int k=3, m=0; m=my(&k); cout << k << " " << m; // 6 8 _getch(); return 0;}int my(int *i){ int p=2; *i *= 2; return p + *i;}

&i

Передача указателей в функции

2 F7A 6 0

F5C F5E F60 F62 F64 F66 F68 F7A F7C F7E F80

k mp

АЛУ2+6 =

4. Структурное программирование 4.10. Функции

int my(int *i);int main() { int k=3, m=0; m=my(&k); cout << k << " " << m; // 6 8 _getch(); return 0;}int my(int *i){ int p=2; *i *= 2; return p + *i;}

&i

Передача указателей в функции

8 2 F7A 6 0

F5C F5E F60 F62 F64 F66 F68 F7A F7C F7E F80

k mp

АЛУ2+6 = 8

4. Структурное программирование 4.10. Функции

my

int my(int *i);int main() { int k=3, m=0; m=my(&k); cout << k << " " << m; // 6 8 _getch(); return 0;}int my(int *i){ int p=2; *i *= 2; return p + *i;}

&i

Передача указателей в функции

8 6 8

F5C F5E F60 F62 F64 F66 F68 F7A F7C F7E F80

k m

АЛУ

4. Структурное программирование 4.10. Функции

my

int my(int *i);int main() { int k=3, m=0; m=my(&k); cout << k << " " << m; // 6 8 _getch(); return 0;}int my(int *i){ int p=2; *i *= 2; return p + *i;}

Передача указателей в функции

Передача указателей на функции

Указатель может хранить адрес функции. Это позволяет присваивать ему адрес точки вызова функции и вызывать ее через указатель.

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

Объявление указателей на функцию:

Тип_возврата (*Имя_указателя) (список_типов_параметров); Скобки, в которые взято *Имя_указателя позволяет отличит

описание указателя на функциюdouble (*pfun)(char*, int);

от описания прототипа функции, возвращающей указатель на double:

double *pfun (char*, int);

4. Структурное программирование 4.10. Функции

Передача указателей на функции: пример

double calc_fun (double (*p_f)(double), double x); int main() { double (*p_func)(double)=NULL;

p_func=sin; // можно и p_func = &sin; cout << p_func(0) << endl; cout << calc_fun(cos, 0) << endl; // можно и calc_fun(&cos,0) _getch(); return 0;}double calc_fun (double (*p_f)(double), double x) { return p_f(x);}

4. Структурное программирование 4.10. Функции

Инициализация параметров

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

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

Инициализировать можно произвольное число параметров функции

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

4. Структурное программирование 4.10. Функции

Инициализация параметров

void repchar (char с = ‘_', int n = 20);int main (){ repchar (); // ___________________ repchar (‘&'); // &&&&&&&&&&&&&&&& repchar ('=', 10); / // ========= _getch(); return 0;}void repchar (char с, int n){ for (int i=1; i<=n; i++) cout << с; cout << endl;}

4. Структурное программирование 4.10. Функции

Перегрузка функций

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

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

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

4. Структурное программирование 4.10. Функции

Перегрузка функцийvoid repchar ();void repchar (char с);void repchar (int n);void repchar (char c, int n);int main (){ repchar (); // ______________ repchar (5); // _____ repchar ('=', 3); // === repchar ('+'); // ++++++++++++++ _getch(); return 0;}

4. Структурное программирование 4.10. Функции

void repchar (){

for (int i=1; i<=20; i++) cout << ’_’cout << endl;

}void repchar (char c){

for (int i=1; i<=20; i++) cout << c;cout << endl;

}void repchar (int n){

for (int i=1; i<=n; i++) cout << ’_';cout << endl;

}void repchar (char c, int n){

for (int i=1; i<=n; i++) cout << c;cout << endl;

}

Возвращаемые значения

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

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

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

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

4. Структурное программирование 4.10. Функции

Структуры как возвращаемые значения

В С в качестве возвращаемых значений могут фигурировать структуры.

struct myst{ short i; short j;};

myst init ();int main() { myst r; r=init(); return 0;}

4. Структурное программирование 4.10. Функции

myst init() { myst w; w.i=1; w.j=2; return w;}

Массивы и структуры как возвращаемые значения

Массив не может быть непосредственно возвращаемым значением. Зато вполне можно вот так:

struct myst{ short k [10];};myst init (int n);

int main() { myst r; r=init(10); return 0;}

4. Структурное программирование 4.10. Функции

myst init(int n) { myst w; for (int i=0; i<=n-1; i++) w.k[i]=i; return w;}

Возврат ссылок: функция в левой части оператора присваивания

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

4. Структурное программирование 4.10. Функции

char &repl (int i, char c[ ]);int main() { char str[]="Hehlo"; repl(2,str)=‘l'; cout << str; // Hello

_getch(); return 0;}

char &repl(int i, char c[]){ return c[i];}

H e h l o /0

F5C F5E F60 F62 F64 F66 F68 F6A F6C F6E F70

Str

4. Структурное программирование 4.10. Функции

l 2

F2E F30 F32 F34 F36 …

Возврат ссылок

char &repl (int i, char c[ ]);int main() { char str[]="Hehlo"; repl(2,str)=‘l'; cout << str; // Hello

_getch(); return 0;}

char &repl(int i, char c[]){ return c[i];}

2 H e h l o /0

F5C F5E F60 F62 F64 F66 F68 F6A F6C F6E F70

Str

4. Структурное программирование 4.10. Функции

l 2

F2E F30 F32 F34 F36 …

i

c

Возврат ссылок

char &repl (int i, char c[]);int main() { char str[]="Hehlo"; repl(2,str)=‘l'; cout << str; // Hello

_getch(); return 0;}

char &repl(int i, char c[]){ return c[i];}

2 H e h l o /0

F5C F5E F60 F62 F64 F66 F68 F6A F6C F6E F70

Str

4. Структурное программирование 4.10. Функции

i

c

c[2]

l 2

F2E F30 F32 F34 F36 …

Возврат ссылок

char &repl (int i, char c[]);int main() { char str[]="Hehlo"; repl(2,str)=‘l'; cout << str; // Hello

_getch(); return 0;}

char &repl(int i, char c[]){ return c[i];}

2 H e h l o /0

F5C F5E F60 F62 F64 F66 F68 F6A F6C F6E F70

Str

4. Структурное программирование 4.10. Функции

i

c

c[2]

repl

l 2

F2E F30 F32 F34 F36 …

Возврат ссылок

char &repl (int i, char c[]);int main() { char str[]="Hehlo"; repl(2,str)=‘l'; cout << str; // Hello

_getch(); return 0;}

char &repl(int i, char c[]){ return c[i];}

H e l l o /0

F5C F5E F60 F62 F64 F66 F68 F6A F6C F6E F70

Str

4. Структурное программирование 4.10. Функции

repl

l 2

F2E F30 F32 F34 F36 …

Возврат ссылок

Возврат ссылок: предупреждение

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

Гораздо спокойнее возвращать ссылки на глобальные или статические переменные.

Все сказанное относится и к возврату указателей. Пример некорректной функции:

char &repl(int i){ char c=“Hello”; return c[i];}

4. Структурное программирование 4.10. Функции

Области видимости и классы памяти переменных

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

Класс памяти определяет время, в течение которого перменная существует в памяти компьютера

В С++ существуют 3 типа области видимости переменных: локальная область видимости область видимости файла область видимости класса (будет рассмотрена позднее)

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

Переменные, имеющие область видимости файла, доступны из любого места файла, в котором они определены

4. Структурное программирование 4.10. Функции

Области видимости и классы памяти переменных В С++ существует 3 класса памяти:

auto (автоматический) static (статический) динамический (будет рассмотрен позднее)

Автоматическая переменная «рождается» в момент ее объявления и прекращает свое существование в момент завершения выполнения блока, где она определена. Автоматическая переменная не инициализируется автоматически. Если она инициализируется при объявлении, инициализация будет выполняться каждый раз при входе в блок и «рождении» переменной.

У переменных, имеющих класс памяти static, время жизни равно времени жизни всей программы. Статическая переменная по умолчанию инициализируется нулем. Статическая переменная создается и инициализируется один раз – при первом выполнении блока.

4. Структурное программирование 4.10. Функции

Локальные автоматические переменныеint main() { int k=1; int i=10; cout << k << endl; for (int j=1; j<=3; j++) { int k=2; //2 2 2 cout << k << endl; { cout << i << endl; // 10 int k; if (j==1) k=3; // Это неправильно! cout << k << endl; k++; //3 4 5 Но! В режиме отладки - ошибка

// выполнения: неинициализированная переменная } cout << k << endl; // 2 2 2 } cout << k << endl; // 1 return 0;}

4. Структурное программирование 4.10. Функции

Локальные статические переменные

int main() { static int k=1; for (int j=1; j<=3; j++) { static int k=2; //2 2 2 cout << k << endl; { static int k=3; // Корректно ! cout << k << endl; k++; //3 4 5 } cout << k << endl; // 2 2 2 } cout << k << endl; // 1 return 0;}

4. Структурное программирование 4.10. Функции

Области видимости и классы памяти переменных

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

Глобальные переменные можно сделать доступными и из других файлов, если программа состоит из нескольких файлов.

По умолчанию глобальные переменные имеют статический класс памяти.

Глобальные переменные живут все время выполнения программы. Если они не инициализируются явно, по умолчанию, глобальные переменные инициализируются нулевым значением.

По возможности, использования глобальных переменных следует избегать

4. Структурное программирование 4.10. Функции

Просто пример: внутреннее представление переменных

int internal_form (void *p, int n_bytes, char str [72])// Explores memory area from p within n_bytes (n_bytes <=8) // The result is string str[72]: // each bit is represented with '0' or '1‘ like bits in the memory// bytes are separated with space// Returns 0 if OK, -1 when n_bytes >8{

unsigned char k=0, m=0;if (n_bytes > 8) return -1;

unsigned char *pc = reinterpret_cast <unsigned char*> (p);for (int i=0; i<=70; i++)str[i]=' '; str[71]='\0';

4. Структурное программирование 4.10. Функции

Просто пример: внутреннее представление переменных

for (int i=0; i<=n_bytes-1; i++, pc++) // cycle on bytes{

k=*pc;for (int j=0; j<=7; j++, k>>=1) // bits in the byte {

m = k;k >>= 1; k <<= 1;str [i*8+7-j+i] = m==k ? '0‘ : '1';

}}return 0;

}

4. Структурное программирование 4.10. Функции

Просто пример: внутреннее представление переменных

int internal_form (void *p, int n_bytes, char str [72]);int main() // Example: how to get an internal form of a variable { typedef short my_type; //type to be explored

my_type c=-2; // variable to be explored char str [72] = {0}; // this string will represent memory void *p = &c; if (!internal_form (p, sizeof (my_type), str)) cout << str << endl; else cout << "Error while internal_form executed" << endl; _getch();

return 0;}

4. Структурное программирование 4.10. Функции

Преобразовать указатель void* p в указатель char* pc

Входные параметры: указатель на область памяти void *p,число байт n_bytesВыходной параметр: строка char str [72]

[n_bytes>8]return-1

[n_bytes<=8]

Инициализировать str пробелами, записать в str[71] символ конца строки

Номер анализируемого байта i=0

сохраняем анализируемый байт в char k= *pc

m=k; k>>=1; k<<=1

[i > n_bytes-1]

[i<=n_bytes-1]

Номер анализируемого бита j=0

str [i*8+7-j+i] = ‘0’ str [i*8+7-j+i] = ‘1’

j++; k>>=1 (отбрасываем обработанный бит)

i++; pc++ (сдвигаемся на 1 байт)

[j <= 7]

[j > 7]

Диаграмма деятельности для функции анализа внутреннего представления переменных

Аварийное завершение

Нормальное заверешение

[m == k] [m != k]

Пока не переберем все анализируемые байты

Пока не проанализируем все биты исследуемого байта

Индекс с учетом расстояния (пробела) между байтами в строке str

Если после битового сдвига вправо - сдвига влево число не изменилось, крайний правый бит - 0, иначе - 1

Еще один пример: решение нелинейного уравнения x=f(x) методом простых итераций

Постановка задачи Методом последовательных приближений найти решение уравнения x=f(x) с заданной точностью r.

Математическая модель . Выберем начальное приближение x0

Положим x1=f(x0); x2=f(x1); …xn=f(xn-1)

Погрешность d = |xn-1-f(xn-1)| = |xn-1-xn|Условие сходимости: |f'(x)|<1

4. Структурное программирование 4.10. Функции

Еще один пример: решение нелинейного уравнения x=f(x) методом простых итераций

Данные.Заданная точность float rТекущая погрешность float dТекущее значение xn-1 float xТекущее значение f(xn-1) float y

Алгоритм.1.Задать x=x0, r 2.Если r < 1e-6, положить r = 1e-63. Инициализировать d=2*r 4. Пока d>r выполнять 4.1. Вычислить y = cos(x)

4.2. Положить d = |x-y|4.3. Положить x = y

5. Вывести значение x

4. Структурное программирование 4.10. Функции

Полученный ранее алгоритм на псевдокоде

Еще один пример: решение нелинейного уравнения x=f(x) методом простых итерацийПараметры:

Заданная точность double rНачальное приближение double xУказатель на функцию double (*p_func)(double); Максимальное число итераций integer max_iДостигнутая точность double &d

Возвращаемое значение:Решение double x

Внутренние переменные:Текущее значение xn-1 double xТекущее значение f(xn-1) double y

Алгоритм.1. Если r < 1e-12, положить r = 1e-123. Инициализировать d=2*r, y=04. Пока d>r и число итераций не больше максимального и y<1e100 выполнять 4.1. Вычислить y = cos(x)

4.2. Положить d = |x-y|4.3. Положить x = y

5. Вывести значение x

4. Структурное программирование 4.10. Функции

Проект функции на псевдокоде

Еще один пример: решение нелинейного уравнения x=f(x) методом простых итераций

double solveqn (double r, double x, double (*p_func)(double), int max_i, double&d)// Solves equation f(x)=0// r - required precision (<=1e-12), x - initial approximation// p_func - pointer to the f(x), max_i - max number of iterations// d - attained accuracy { double y=0; if (r < 1e-12) r=1e-12; d=2*r;

for (int i=1; (i<=max_i) && (d > r) && abs(y)< 1e100; i++) { d = abs(x-(y=p_func(x))); x = y; } return y; }

4. Структурное программирование 4.10. Функции

Еще один пример: решение нелинейного уравнения x=f(x) методом простых итераций

double solveqn (double r, double x, double (*p_func)(double), int max_i, double&d);double myfun(double x); int main() // Example: how to solve an equation f(x)=0 { double d = 0; cout << setprecision(12) << solveqn (1e-5,1.0, cos, 10000, d) << " d = " << setprecision(12) << d << endl; // 0.739 d= 7.043e-006 cout << setprecision(12) << solveqn (1e-5,10.0, myfun, 10000, d) << " d = " << setprecision(12) << d << endl; //1e+128 d= 1e+128 divergence!!! _getch(); return 0;}double myfun(double x) { return x*x;}

4. Структурное программирование 4.10. Функции

4. Структурное программирование 4.11. Рекурсия

Рекурсивным называется объект, который частично определяется через самого себя.

(1)0!=1(2)для любых n>0 n! = n*(n-1)!

int fact (int i); int main() { cout << fact(4) << endl; // 24 return 0; } int fact (int i) // recursive function { return i == 0 ? 1: i * fact(i-1); }

4. Структурное программирование 4.11. Рекурсия

Нерекурсивное определение факториала

n!=1*2*3*…*n

int fact (int i); int main() { cout << fact(4) << endl; // 24 _getch(); return 0; } int fact (int i) // non-recursive function { int f=1; for (int j=1; j<=i; j++) f*=j; return f; }

Содержание и мощность рекурсивного определения, а также его главное назначение, состоит в том, что оно позволяет с помощью конечного выражения определить бесконечное множество объектов.

Аналогично, с помощью конечного рекурсивного алгоритма можно определить бесконечное вычисление, причем алгоритм не будет содержать повторений фрагментов текста.

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

4. Структурное программирование 4.11. Рекурсия

В общем случае любая рекурсивная процедура Rec включает в себя некоторое множество операторов S и один или несколько операторов рекурсивного вызова Р.

Вызов рекурсивной процедуры должен выполняться по условию, которое на каком-то уровне рекурсии станет ложным.

Если условие истинно, то цепочка рекурсивных вызовов продолжается. Когда оно становится ложным, то рекурсивный спуск заканчивается и начинается поочередный рекурсивный возврат из всех вызванных на данный момент копий рекурсивной процедуры.

4. Структурное программирование 4.11. Рекурсия

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

Число рекурсивных вызовов в каждый конкретный момент времени, называется текущим уровнем рекурсии.

4. Структурное программирование 4.11. Рекурсия

Структура рекурсивной процедуры может принимать три разных формы:

1.Форма с выполнением действий до рекурсивного вызова (с выполнением действий на рекурсивном спуске).

void Rec(){ … S … ; if (условие) Rec (); return; }

4. Структурное программирование 4.11. Рекурсия

Вычисление факториала на рекурсивном спуске:

unsigned int fact_dn (int m, unsigned int worker=1);int main (){ cout << fact_dn (5) << endl; _getch(); return 0;}int fact_dn (int m, int worker){ worker *= m; if (m!= 1) return fact_dn (m-1, worker); else return worker;}

4. Структурное программирование 4.11. Рекурсия

4. Структурное программирование 4.11. Рекурсия

Трассировка вызовов

1) cout << fact_dn (4) << endl (1) m=4, worker=1; fact_dn=?

int fact_dn (int m, int worker){ worker *= m; if (m!= 1) return fact_dn (m-1, worker); else return worker;}

4. Структурное программирование 4.11. Рекурсия

(1) m=3, worker=4; fact_dn=?

Трассировка вызовов

1) cout << fact_dn (4) << endl

int fact_dn (int m, int worker){ worker *= m; if (m!= 1) return fact_dn (m-1, worker); else return worker;}

4. Структурное программирование 4.11. Рекурсия

(1) m=4, worker=4; fact_dn=?

Трассировка вызовов

1)cout << fact_dn (4) << endl

2)if (4 !=1) return fact_dn (3, 4); (2) m=3, worker=4; fact_dn=?

int fact_dn (int m, int worker){ worker *= m; if (m!= 1) return fact_dn (m-1, worker); else return worker;}

4. Структурное программирование 4.11. Рекурсия

(1) m=4, worker=4; fact_dn=?

Трассировка вызовов

1)cout << fact_dn (4) << endl

2)if (4 !=1) return fact_dn (3, 4); (2) m=3, worker=12; fact_dn=?

int fact_dn (int m, int worker){ worker *= m; if (m!= 1) return fact_dn (m-1, worker); else return worker;}

4. Структурное программирование 4.11. Рекурсия

(1) m=4, worker=4; fact_dn=?

Трассировка вызовов

1)cout << fact_dn (4) << endl

2)if (4 !=1) return fact_dn (3, 4);

3)if (3 != 1) return fact_dn (2, 12);

(2) m=3, worker=12; fact_dn=?

(3) m=2, worker=12; fact_dn=?

int fact_dn (int m, int worker){ worker *= m; if (m!= 1) return fact_dn (m-1, worker); else return worker;}

4. Структурное программирование 4.11. Рекурсия

(1) m=4, worker=4; fact_dn=?

Трассировка вызовов

1)cout << fact_dn (4) << endl

2)if (4 !=1) return fact_dn (3, 4);

3)if (3 != 1) return fact_dn (2, 12);

(2) m=3, worker=12; fact_dn=?

(3) m=2, worker=24; fact_dn=?

int fact_dn (int m, int worker){ worker *= m; if (m!= 1) return fact_dn (m-1, worker); else return worker;}

4. Структурное программирование 4.11. Рекурсия

(1) m=4, worker=4; fact_dn=?

(2) m=3, worker=12; fact_dn=?

(3) m=2, worker=24; fact_dn=?

(4) m=1, worker=24; fact_dn=?

int fact_dn (int m, int worker){ worker *= m; if (m!= 1) return fact_dn (m-1, worker); else return worker;}

Трассировка вызовов

1)cout << fact_dn (4) << endl

2)if (4 !=1) return fact_dn (3, 4);

3)if (3 != 1) return fact_dn (2, 12);

4)if (2 ! = 1) return fact_dn (1, 24);

4. Структурное программирование 4.11. Рекурсия

(1) m=4, worker=4; fact_dn=?

(2) m=3, worker=12; fact_dn=?

(3) m=2, worker=24; fact_dn=?

(4) m=1, worker=24; fact_dn=?

int fact_dn (int m, int worker){ worker *= m; if (m!= 1) return fact_dn (m-1, worker); else return worker;}

Трассировка вызовов

1)cout << fact_dn (4) << endl

2)if (4 !=1) return fact_dn (3, 4);

3)if (3 != 1) return fact_dn (2, 12);

4)if (2 ! = 1) return fact_dn (1, 24);

4. Структурное программирование 4.11. Рекурсия

int fact_dn (int m, int worker){ worker *= m; if (m!= 1) return fact_dn (m-1, worker); else return worker;}

(1) m=4, worker=4; fact_dn=?

(2) m=3, worker=12; fact_dn=?

(3) m=2, worker=24; fact_dn=?

(4) m=1, worker=24; fact_dn=24

Трассировка вызовов

1)cout << fact_dn (4) << endl

2)if (4 !=1) return fact_dn (3, 4);

3)if (3 != 1) return fact_dn (2, 12);

4)if (2 ! = 1) return fact_dn (1, 24);

5)if (1 !=1)…else return worker

4. Структурное программирование 4.11. Рекурсия

int fact_dn (int m, int worker){ worker *= m; if (m!= 1) return fact_dn (m-1, worker); else return worker;}

(1) m=4, worker=4; fact_dn=?

(2) m=3, worker=12; fact_dn=?

(3) m=2, worker=24; fact_dn=24

Трассировка вызовов

1)cout << fact_dn (4) << endl

2)if (4 !=1) return fact_dn (3, 4);

3)if (3 != 1) return fact_dn (2, 12);

4)if (2 ! = 1) return fact_dn (1, 24);

Трассировка вызовов

1)cout << fact_dn (4) << endl

2)if (4 !=1) return fact_dn (3, 4);

3)if (3 != 1) return fact_dn (2, 12);

4. Структурное программирование 4.11. Рекурсия

int fact_dn (int m, int worker){ worker *= m; if (m!= 1) return fact_dn (m-1, worker); else return worker;}

(1) m=4, worker=4; fact_dn=?

(2) m=3, worker=12; fact_dn=24

Трассировка вызовов

1)cout << fact_dn (4) << endl

2)if (4 !=1) return fact_dn (3, 4);

4. Структурное программирование 4.11. Рекурсия

int fact_dn (int m, int worker){ worker *= m; if (m!= 1) return fact_dn (m-1, worker); else return worker;}

(1) m=4, worker=4; fact_dn=24

Вычисление факториала на рекурсивном спуске:

int fact_dn (int m, int worker=1);int main (){ cout << fact_dn (5) << endl; _getch(); return 0;}int fact_dn (int m, int worker){ worker *= m; if (m!= 1) return fact_dn (m-1, worker); else return worker;}

4. Структурное программирование 4.11. Рекурсия

Можно записать короче

Оптимизируем типы аргументов

Вычисление факториала на рекурсивном спуске:

unsigned long fact_dn (unsigned int m, unsigned long worker=1);int main (){ cout << fact_dn (5) << endl; _getch(); return 0;}

unsigned long fact_dn (unsigned int m, unsigned long worker){ return m==1 ? worker : fact_dn (m-1, worker*m);}

4. Структурное программирование 4.11. Рекурсия

Структура рекурсивной процедуры может принимать три разных формы:

2.Форма с выполнением действий после рекурсивного вызова (с выполнением действий на рекурсивном возврате).

void Rec(){ if условие Rec (); … S … ; return; }

4. Структурное программирование 4.11. Рекурсия

Вычисление факториала на рекурсивном возврате:

int fact_up (int m);int main (){ cout << fact_up(6) << endl; _getch(); return 0;}

unsigned long fact_up (unsigned int m){ if (m > 1) return m * fact_up (m - 1); else return 1;}

4. Структурное программирование 4.11. Рекурсия

4. Структурное программирование 4.11. Рекурсия

Трассировка вызовов

1)cout << fact_up (4) << endl (1) m=4, fact_dn=?

unsigned long fact_up (unsigned int m){ if (m > 1) return m * fact_up (m - 1); else return 1;}

4. Структурное программирование 4.11. Рекурсия

Трассировка вызовов

1)cout << fact_up (4) << endl

2)if (4 > 1) return m * fact_up (3);

(1) m=4, fact_up=?

unsigned long fact_up (unsigned int m){ if (m > 1) return m * fact_up (m - 1); else return 1;}

(2) m=3, fact_up=?

4. Структурное программирование 4.11. Рекурсия

Трассировка вызовов

1)cout << fact_up (4) << endl

2)if (4 > 1) return m * fact_up (3);

3)if (3 > 1) return m * fact_up (2);

(1) m=4, fact_up=?

unsigned long fact_up (unsigned int m){ if (m > 1) return m * fact_up (m - 1); else return 1;}

(2) m=3, fact_up=?

(3) m=2, fact_up=?

4. Структурное программирование 4.11. Рекурсия

Трассировка вызовов

1)cout << fact_up (4) << endl

2)if (4 > 1) return m * fact_up (3);

3)if (3 > 1) return m * fact_up (2);

4)if (2 > 1) return m * fact_up (1);

(1) m=4, fact_up=?

unsigned long fact_up (unsigned int m){ if (m > 1) return m * fact_up (m - 1); else return 1;}

(2) m=3, fact_up=?

(3) m=2, fact_up=?

(4) m=1, fact_up=?

4. Структурное программирование 4.11. Рекурсия

Трассировка вызовов

1)cout << fact_up (4) << endl

2)if (4 > 1) return m * fact_up (3);

3)if (3 > 1) return m * fact_up (2);

4)if (2 > 1) return m * fact_up (1);

(1) m=4, fact_up=?

unsigned long fact_up (unsigned int m){ if (m > 1) return m * fact_up (m - 1); else return 1;}

(2) m=3, fact_up=?

(3) m=2, fact_up=?

(4) m=1, fact_up=1

4. Структурное программирование 4.11. Рекурсия

Трассировка вызовов

1)cout << fact_up (4) << endl

2)if (4 > 1) return m * fact_up (3);

3)if (3 > 1) return m * fact_up (2);

(1) m=4, fact_up=?

unsigned long fact_up (unsigned int m){ if (m > 1) return m * fact_up (m - 1); else return 1;}

(2) m=3, fact_up=?

(3) m=2, fact_up=2*1

4. Структурное программирование 4.11. Рекурсия

Трассировка вызовов

1)cout << fact_up (4) << endl

2)if (4 > 1) return m * fact_up (3);

(1) m=4, fact_up=?

unsigned long fact_up (unsigned int m){ if (m > 1) return m * fact_up (m - 1); else return 1;}

(2) m=3, fact_up=3*2

4. Структурное программирование 4.11. Рекурсия

Трассировка вызовов

1)cout << fact_up (4) << endl (1) m=4, fact_up=4*6

unsigned long fact_up (unsigned int m){ if (m > 1) return m * fact_up (m - 1); else return 1;}

Вычисление факториала на рекурсивном возврате:

int fact_up (int m);int main (){ cout << fact_up(6) << endl; _getch(); return 0;}

unsigned long fact_up (unsigned int m){ if (m > 1) return m * fact_up (m - 1); else return 1;}

Можно записать короче

4. Структурное программирование 4.11. Рекурсия

Вычисление факториала на рекурсивном возврате:

int fact_up (int m);int main (){ cout << fact_up(6) << endl; _getch(); return 0;}

unsigned long fact_up (unsigned int m){ return m == 1 ? 1: i * fact_up(m-1);}

4. Структурное программирование 4.11. Рекурсия

Структура рекурсивной процедуры может принимать три разных формы:

3.Форма с выполнением действий как до, так и после рекурсивного вызова (с выполнением действий как на рекурсивном спуске, так и на рекурсивном возврате).

void Rec () { … S1 …; if (условие) Rec(); … S2 … ; return; };

void Rec (){ if (условие) { … S1 …; Rec; … S2 … ; } return; }

4. Структурное программирование 4.11. Рекурсия

Инвертирование строки

void reverse();int main(){ reverse(); cout << endl; _getch(); return 0;}void reverse(){ char c=_getche(); if (c != 13) reverse(); cout << c; return;}

 

4. Структурное программирование 4.11. Рекурсия

Инвертирование строки

void reverse();int main(){ reverse(); cout << endl; _getch(); return 0;}void reverse(){ char c=_getche(); if (c != 13) reverse(); cout << c; return;}

 

4. Структурное программирование 4.11. Рекурсия

_

Инвертирование строки

void reverse();int main(){ reverse(); cout << endl; _getch(); return 0;}void reverse(){ char c=_getche(); if (c != 13) reverse(); cout << c; return;}

 

4. Структурное программирование 4.11. Рекурсия

_1) c= ?

Инвертирование строки

void reverse();int main(){ reverse(); cout << endl; _getch(); return 0;}void reverse(){ char c=_getche(); if (c != 13) reverse(); cout << c; return;}

 

4. Структурное программирование 4.11. Рекурсия

1) c=H _

‘H’

Инвертирование строки

void reverse();int main(){ reverse(); cout << endl; _getch(); return 0;}void reverse(){ char c=_getche(); if (c != 13) reverse(); cout << c; return;}

 

4. Структурное программирование 4.11. Рекурсия

1) c=‘H’H

2) c=‘E’E _

Инвертирование строки

void reverse();int main(){ reverse(); cout << endl; _getch(); return 0;}void reverse(){ char c=_getche(); if (c != 13) reverse(); cout << c; return;}

 

4. Структурное программирование 4.11. Рекурсия

1) c=‘H’HEL

2) c=‘E’

3) c=‘L’

_

Инвертирование строки

void reverse();int main(){ reverse(); cout << endl; _getch(); return 0;}void reverse(){ char c=_getche(); if (c != 13) reverse(); cout << c; return;}

 

4. Структурное программирование 4.11. Рекурсия

1) c=‘H’HELL

2) c=‘E’

3) c=‘L’

4) c=‘L’

_

Инвертирование строки

void reverse();int main(){ reverse(); cout << endl; _getch(); return 0;}void reverse(){ char c=_getche(); if (c != 13) reverse(); cout << c; return;}

 

4. Структурное программирование 4.11. Рекурсия

1) c=‘H’HELLO

2) c=‘E’

3) c=‘L’

4) c=‘L’

5) c=‘O’

_

Инвертирование строки

void reverse();int main(){ reverse(); cout << endl; _getch(); return 0;}void reverse(){ char c=_getche(); if (c != 13) reverse(); cout << c; return;}

 

4. Структурное программирование 4.11. Рекурсия

1) c=‘H’HELLO

2) c=‘E’

3) c=‘L’

4) c=‘L’

5) c=‘O’

6) c=13

_

Инвертирование строки

void reverse();int main(){ reverse(); cout << endl; _getch(); return 0;}void reverse(){ char c=_getche(); if (c != 13) reverse(); cout << c; return;}

 

4. Структурное программирование 4.11. Рекурсия

1) c=‘H’HELLO

2) c=‘E’

3) c=‘L’

4) c=‘L’

5) c=‘O’

6) c=13

_

Инвертирование строки

void reverse();int main(){ reverse(); cout << endl; _getch(); return 0;}void reverse(){ char c=_getche(); if (c != 13) reverse(); cout << c; return;}

 

4. Структурное программирование 4.11. Рекурсия

1) c=‘H’OELLO

2) c=‘E’

3) c=‘L’

4) c=‘L’

5) c=‘O’

_

Инвертирование строки

void reverse();int main(){ reverse(); cout << endl; _getch(); return 0;}void reverse(){ char c=_getche(); if (c != 13) reverse(); cout << c; return;}

 

4. Структурное программирование 4.11. Рекурсия

1) c=‘H’OLLLO

2) c=‘E’

3) c=‘L’

4) c=‘L’

_

Инвертирование строки

void reverse();int main(){ reverse(); cout << endl; _getch(); return 0;}void reverse(){ char c=_getche(); if (c != 13) reverse(); cout << c; return;}

 

4. Структурное программирование 4.11. Рекурсия

1) c=‘H’OLLLO

2) c=‘E’

3) c=‘L’

_

Инвертирование строки

void reverse();int main(){ reverse(); cout << endl; _getch(); return 0;}void reverse(){ char c=_getche(); if (c != 13) reverse(); cout << c; return;}

 

4. Структурное программирование 4.11. Рекурсия

1) c=‘H’OLLEO

2) c=‘E’_

Инвертирование строки

void reverse();int main(){ reverse(); cout << endl; _getch(); return 0;}void reverse(){ char c=_getche(); if (c != 13) reverse(); cout << c; return;}

 

4. Структурное программирование 4.11. Рекурсия

1) c=‘H’OLLEH _

Инвертирование строки

void reverse();int main(){ reverse(); cout << endl; _getch(); return 0;}void reverse(){ char c=_getche(); if (c != 13) reverse(); cout << c; return;}

 

4. Структурное программирование 4.11. Рекурсия

OLLEH_

Подадим на вход строку ‘HELLO’:Текущий уровень рекурсии Рекурсивный спуск

Рекурсивный возврат

0 Reverse;

1 с != 13; Ввод:c=‘H'; Reverse; Вывод:'Н';

2 c != 13; Ввод:c='Е'; Reverse; Вывод:’E';

3 c != 13; Ввод:c=‘L'; Reverse; Вывод:'L';

4 c != 13; Ввод:c=‘L'; Reverse; Вывод:’L';

5 c != 13; Ввод:c=‘O'; Reverse; Вывод:‘O';

6 c = 13; Нажатие <Enter>

4. Структурное программирование 4.11. Рекурсия

4. Структурное программирование 4.11. Рекурсия

Быстрая сортировка

9 4 12 1 7 6 8 4 2 10

2 4 4 1 6 7 8 12 9 10Qsort(1,5) Qsort(6,10)

Qsort(1,10)

2 4 4 1 6 7 8 12 9 10

2 1 4 4 6 7 8 10 9 12j=2, i=4 j=9, i=10=R

Qsort(1,2) Qsort(4,5) Qsort(6,9) Вызов не выполняется

2 1 4 6 7 8 10 9

1 2 4 6 7 8 10 9

Qsort(8,9)

10 9

9 10

B=7

B=4 B=12

j=1=L, i=2=R

j=3<L, i=5=R Вызов не

выполня-ется

Быстрая сортировка

Сортируем массив, содержащий информацию о деталях:

struct detail{

int id;float weight;

};

Спецификация функции быстрой сортировки:void qsort (detail s [ ], int l, int r);

4. Структурное программирование 4.11. Рекурсия

struct detail{ int id; float weight;};void qsort (detail s [ ], int l, int r);int main() { const int n=9; detail st [n+1]; srand( static_cast <unsigned int> (time(NULL))); for (int i=0; i<=n; i++) st[i].id = rand()%33; for (int i=0; i<=n; i++) cout << setw (4) << st[i].id; cout << endl; qsort (st, 0, 9); for (int i=0; i<=n; i++) cout << setw (4) << st[i].id; _getch(); return 0;}

4. Структурное программирование 4.11. Рекурсия

void qsort (detail s[ ], int l, int r){ int b=0, i=0, j=0; detail tmp; b = s[(l+r)/2].id; i = l; j = r; while (i <= j) { while (s[ i ].id < b) i++; while (s[ j ].id > b) j--; if (i <= j) { tmp = s[ i ]; s[ i ] = s[ j ]; s[ j ] = tmp; i++; j--; } } if (l < j) qsort ( s, l, j ); if (i < r) qsort ( s, i, r ); return;} 

4. Структурное программирование 4.11. Рекурсия

struct Member{ int id; Name ownname; Date birth; char address [80]; Date enter; char position [30]; bool tradeunion;};

4. Структурное программирование 4.12. Шаблоны функций

struct detail{ int id; float weight;};

Быстрая сортировка: шаблоны функций

template <class T> void qsort (T s [ ], int l, int r);  

struct Date{ unsigned short year; unsigned short month; unsigned short day;};

struct Name{ char surname [80]; char firstname [40]; char patronymic [60]; };

Быстрая сортировка: шаблоны функцийint main() {

const int n=12;detail st[n+1];

srand( static_cast <unsigned int> (time(NULL)));for (int i=0; i<=n; i++) st[i].key = rand()%33;for (int i=0; i<=n; i++) cout << setw (4) << st[i].key;cout << endl;

qsort (st,0,9);for (int i=0; i<=n; i++) cout << setw (4) << st[i].key;cout << endl;_getch();return 0;

}

4. Структурное программирование 4.12. Шаблоны функций

template <class T> void qsort (T s [ ], int l, int r){ int b=0, i=0, j=0, k=0; T tmp; b = s[(l+r)/2].key; i = l; j = r; while (i <= j) { while (s[ i ].key < b) i++; while (s[ j ].key > b) j--; if (i <= j) { tmp = s[ i ]; s[ i ] = s[ j ]; s[ j ] = tmp; i++; j--; } } if (l < j) qsort ( s, l, j ); if (i < r) qsort ( s, i, r ); return;}

4. Структурное программирование 4.12. Шаблоны функций

Шаблоны функций

Заголовку тела функции также должна предшествовать конструкция template.Шаблонная функция может быть перегружена другим шаблоном или не шаблонной функцией с таким же именем, но с другим набором параметров. Еще один простой пример шаблона – функция, осуществляющая перестановку элементов произвольного типа: template <class T> void myswap (T *a, T *b)

{ T tmp=*a; *a=*b; *b=tmp; }

4. Структурное программирование 4.12. Шаблоны функций

Шаблоны функций

Еще один простой пример шаблона – функция, осуществляющая перестановку элементов произвольного типа:

template <class T> void myswap (T *a, T *b){ T tmp=*a; *a=*b; *b=tmp; }int main(){ int short x=15, y=2; double a=0, b=12.4; myswap (&x,&y); myswap (&a,&b); return 0;}

4. Структурное программирование 4.12. Шаблоны функций

Шаблоны функцийТо же самое лучше можно сделать с помощью ссылок, а не указателей: template <class T> void myswap (T &a, T &b){ T tmp= a; a=b; b=tmp; }int main(){ int short x=15, y=2; double a=0, b=12.4; myswap (x,y); myswap (a,b); return 0;}

4. Структурное программирование 4.12. Шаблоны функций