Слайд 2Вопрос 1
Передача массивов в качестве параметров
![Вопрос 1 Передача массивов в качестве параметров](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/863970/slide-1.jpg)
Слайд 3Общие положения
При использовании в качестве параметра массива в функцию передается указатель на
![Общие положения При использовании в качестве параметра массива в функцию передается указатель](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/863970/slide-2.jpg)
его первый элемент, иными словами, массив всегда передается по адресу.
При этом информация о количестве элементов массива теряется, и следует передавать его размерность через отдельный параметр.
Слайд 4Пример
Функция нахождения суммы элементов массива
#include
…
int sum(const int* mas, const int n);
int
![Пример Функция нахождения суммы элементов массива #include … int sum(const int* mas,](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/863970/slide-3.jpg)
const n = 5;
int main() {
setlocale(LC_ALL,"");
int marks[n] = {3, 4, 5, 4, 4};
cout << "Сумма элементов массива: " << sum(marks, n);
return 0;
}
Слайд 5Пример (продолжение)
int sum(const int* mas, const int n) {
// варианты: int sum(int
![Пример (продолжение) int sum(const int* mas, const int n) { // варианты:](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/863970/slide-4.jpg)
mas[], int n)
// или int sum(int mas[n], int n)
// (величина n должна быть константой)
int s = 0;
for (int i = 0; i s += mas[i];
return s;
}
Слайд 6Многомерные массивы
При передаче многомерных массивов все размерности, если они не известны на
![Многомерные массивы При передаче многомерных массивов все размерности, если они не известны](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/863970/slide-5.jpg)
этапе компиляции, должны передаваться в качестве параметров.
Внутри функции массив интерпретируется как одномерный, а его индекс пересчитывается в программе.
Слайд 7Пример
Нахождение суммы элементов двумерных массивов a и b
#inc1ude
#include
…
int sum(const int
![Пример Нахождение суммы элементов двумерных массивов a и b #inc1ude #include …](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/863970/slide-6.jpg)
*a, const int nstr, const int nstb);
Слайд 8Пример (продолжение)
int main(){
setlocale(LC_ALL,"");
int b[2][2] = {{2, 2}, {4, 3}};
printf("Сумма элементов b: %d\n",
![Пример (продолжение) int main(){ setlocale(LC_ALL,""); int b[2][2] = {{2, 2}, {4, 3}};](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/863970/slide-7.jpg)
sum(&b[0][0], 2, 2));
// имя массива передавать в sum нельзя из-за несоответствия
// типов
int i, j, nstr, nstb, *a;
printf("Введите количество строк и столбцов: \n");
scanf("%d%d", &nstr, &nstb);
a = (int *)malloc(nstr * nstb * sizeof(int));
for (i = 0; i for (j = 0; j scanf("%d", &a[i * nstb + j]);
printf("Сумма элементов а: %d\n", sum(a, nstr, nstb));
return 0;
}
Слайд 9Пример (продолжение)
int sum(const int *a, const int nstr, const int nstb){
int i,
![Пример (продолжение) int sum(const int *a, const int nstr, const int nstb){](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/863970/slide-8.jpg)
j, s = 0;
for (i = 0; i for (j = 0; j s += a[i * nstb + j];
return s;
}
Слайд 10Альтернативный пример
#include
int sum(int **a, const int nstr, const int nstb);
int main(){
int
![Альтернативный пример #include int sum(int **a, const int nstr, const int nstb);](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/863970/slide-9.jpg)
nstr, nstb;
cin >> nstr >> nstb;
int **a, i, j;
// Формирование матрицы a:
a = new int* [nstr];
for (i = 0; i a[i] = new int [nstb];
for (i = 0; i for (j = 0; j cin >> a[i][j];
cout << sum(a, nstr, nstb);
return 0;
}
Слайд 11Альтернативный пример (продолжение)
int sum(int **a, const int nstr, const int nstb){
int
![Альтернативный пример (продолжение) int sum(int **a, const int nstr, const int nstb){](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/863970/slide-10.jpg)
i, j, s = 0;
for (i = 0; i for (j = 0; j s += a[i][j];
return s;
}
Слайд 13Определение
Рекурсивной называется функция, которая вызывает саму себя. Такая рекурсия называется прямой.
Существует
![Определение Рекурсивной называется функция, которая вызывает саму себя. Такая рекурсия называется прямой.](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/863970/slide-12.jpg)
еще косвенная рекурсия, когда две или более функций вызывают друг друга.
Слайд 14Особенности
Если функция вызывает себя, в стеке создается копия значений ее параметров, как
![Особенности Если функция вызывает себя, в стеке создается копия значений ее параметров,](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/863970/slide-13.jpg)
и при вызове обычной функции, после чего управление передается первому исполняемому оператору функции.
При повторном вызове этот процесс повторяется.
Для завершения вычислений каждая рекурсивная функция должна содержать хотя бы одну нерекурсивную ветвь алгоритма, заканчивающуюся оператором возврата.
При завершении функции соответствующая часть стека освобождается, и управление передается вызывающей функции, выполнение которой продолжается с точки, следующей за рекурсивным вызовом.
Слайд 15Пример
Вычисление факториала числа n
long fact(long n){
if (n==0 || n==l) return 1;
return
![Пример Вычисление факториала числа n long fact(long n){ if (n==0 || n==l)](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/863970/slide-14.jpg)
(n * fact(n - 1));
}
Слайд 16Пример
Вычисление факториала числа n (альтернативный вариант)
long fact(long n){
return (n>l) ? n *
![Пример Вычисление факториала числа n (альтернативный вариант) long fact(long n){ return (n>l)](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/863970/slide-15.jpg)
fact(n - 1) : 1;
}
Слайд 17Вопрос 3
Передача имен функций в качестве параметров
![Вопрос 3 Передача имен функций в качестве параметров](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/863970/slide-16.jpg)
Слайд 18Особенности
Функцию можно вызвать через указатель на нее. Для этого объявляется указатель соответствующего
![Особенности Функцию можно вызвать через указатель на нее. Для этого объявляется указатель](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/863970/slide-17.jpg)
типа и ему с помощью операции взятия адреса присваивается адрес функции:
void f(int а ){/*...*/ } // определение функции
void (*pf)(int); // указатель на функцию
…
pf = &f; // указателю присваивается адрес функции
// (можно написать pf = f;)
pf(10); // функция f вызывается через указатель pf
// (можно написать (*pf)(10) )
Слайд 19Использование typedef
Для того чтобы сделать программу легко читаемой, при описании указателей на
![Использование typedef Для того чтобы сделать программу легко читаемой, при описании указателей](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/863970/slide-18.jpg)
функции используют переименование типов (typedef). Можно объявлять массивы указателей на функции (это может быть полезно, например, при реализации меню):
// Описание типа PF как указателя
// на функцию с одним параметром типа int:
typedef void (*PF)(int);
// Описание и инициализация массива указателей:
PF menu[] = {&new, &open, &save};
menu[l](10); // Вызов функции open
Здесь new, open и save – имена функций, которые должны быть объявлены ранее.
Слайд 20Передача функции через указатель
Указатели на функции передаются в подпрограмму таким же образом,
![Передача функции через указатель Указатели на функции передаются в подпрограмму таким же](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/863970/slide-19.jpg)
как и параметры других типов:
#include
typedef void (*PF)(int);
void f1(PF pf){ // функция f1 получает в качестве параметра
// указатель типа PF
pf(5); // вызов функции, переданной через указатель
}
void f(int i ){cout << i;}
int main(){
fl(f);
return 0;
}
Тип указателя и тип функции, которая вызывается посредством этого указателя, должны совпадать в точности.
Слайд 22Особенности
Функция, которой передается управление после запуска программы, должна иметь имя main.
Она
![Особенности Функция, которой передается управление после запуска программы, должна иметь имя main.](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/863970/slide-21.jpg)
может возвращать значение в вызвавшую систему и принимать параметры из внешнего окружения.
Возвращаемое значение должно быть целого типа.
Стандарт предусматривает два формата функции:
// без параметров:
тип main(){ /* ... */}
// с двумя параметрами:
тип main(int argc, char* argv[]){ /* ... */}
Слайд 23Параметры функции main
Первый параметр (argc) определяет количество параметров, передаваемых функции, включая имя
![Параметры функции main Первый параметр (argc) определяет количество параметров, передаваемых функции, включая](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/863970/slide-22.jpg)
самой программы.
Второй параметр (argv) является указателем на массив указателей типа char*.
Каждый элемент массива содержит указатель на отдельный параметр командной строки, хранящийся в виде строки, оканчивающейся нуль-символом.
Первый элемент массива (argv[0]) ссылается на полное имя запускаемого на выполнение файла, следующий (argv[l]) указывает на первый параметр, argv[2] – на второй параметр, и т.д.
Слайд 24Возвращаемое значение
Если функция main() ничего не возвращает, вызвавшая система получит значение, означающее
![Возвращаемое значение Если функция main() ничего не возвращает, вызвавшая система получит значение,](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/863970/slide-23.jpg)
успешное завершение.
Ненулевое значение означает аварийное завершение.
Оператор возврата из main() можно опускать.