Скачать 496.92 Kb.
|
ПОЛЬЗОВАТЕЛЬСКИЕ ФУНКЦИИ Функция — это именованная последовательность описаний и операторов, выполняющая какое-либо законченное действие. Программа должна иметь главную функцию main() - обеспечивает создание точки входа в объектный модуль.
Любая функция должна быть объявлена и определена. Объявление функции должно находиться в тексте раньше ее вызова Объявление функции (прототип) задает её имя, тип возвращаемого значения и список передаваемых параметров. Определение функции содержит объявление и тело функции, представляющее собой последовательность операторов и описаний в фигурных скобках. Синтаксис: [ класс ] тип имя ([ список_параметров ]) { тело функции } Класс - задает область видимости функции
Если функция не должна возвращать значение, указывается тип void. Элементы списка параметров разделяются запятыми. Для каждого параметра, передаваемого в функцию, указывается его тип и имя. Для вызова функции нужно указать ее имя, за которым в круглых скобках через запятую перечисляются имена передаваемых аргументов. Если тип возвращаемого значения не void, функция может входить в состав выражений. Функции возвращают значение с помощью оператора return. return [ выражение ]; Функция может содержать несколько операторов return. Если функция описана как void, выражение не указывается. Примеры: int fl(){return 1;} // правильно void f2(){return 1;} // неправильно double f3(){return 1;} // правильно. 1 преобразуется к типу double Пример 5.1. Функция, возвращающая сумму двух целых величин: #include int sum2(int , int);//прототип функции, тело функции находится ниже int main(){ int a = 2, b = 3, c, d; с = sum(a, b); // вызов функции cin >> d; cout << sum(c, d); // вызов функции return 0; } int sum(int a, int b){ // определение функции return (a + b);} Все величины, описанные внутри функции, а также ее параметры (которые не передаются по ссылке), являются локальными. Для сохранения значений локальных переменных используется спецификатор памяти static. Пример 5.2. void f(int a){ int m= 0; cout << "n m p\n"; while (a--){ static int n = 0; // инициализируется только один раз int p = 0; // локальная переменная cout << n++ << ‘ ‘ << m++ << ‘ ‘ << p++ << ‘\n’;}} int main(){ f(3); f(2); return 0;} Результат:
Нельзя возвращать из функции указатель на локальную переменную, поскольку память, выделенная локальным переменным при входе в функцию, освобождается после возврата из нее. Пример: int* f(){ int а = 5; // переменная существует только внутри функции return &а; // нельзя! } Параметры функций Параметры, перечисленные в заголовке описания функции, называются формальными, а записанные в операторе вызова функции — фактическими. При вызове функции формальные параметры замещаются фактическими. Существует два способа передачи параметров в функцию: по значению и по адресу. При передаче по значению внутри функции автоматически создается локальная переменная, в которую заносится копия фактического параметра. Внутри функции мы работаем с копией. Таким образом, переменная, переданная как фактический параметр, не изменяет своего значения после вызова функции. При передаче по адресу (передаем ссылку либо указатель) внутри функции мы работаем с настоящим значением передаваемого параметра. Отсюда следует, что после вызова функции значение фактического параметра может измениться. Пример 5.3. /* функция увеличивает значение передаваемых параметров на единицу*/ void f(int i, int* j, int& k){ i++; (*j)++; k++;}; int main(){ int i = 1, j = 2, k = 3; // инициализируем переменные cout < f(i, &j, k); // i – по значению, j и k – по адресу cout << i <<" "<< j <<" "<< k; // значения после вызова функции return 0;} В результате получим 1 2 3 , 1 3 4. Видно, что после вызова функции переменные переданные в функцию по адресу изменились, а по значению – нет.
Модификатор const, указанный перед параметром, запрещает изменение значения этого параметра внутри функции. При попытке изменения мы получим ошибку компиляции. Например, int f(const char*); Строка в C++ представляет собой массив символов и мы вынуждены передавать ее в функцию по адресу. В то же время модификатор const гарантирует, что данная строка не будет изменена. Передача массивов в качестве параметров. В C++ многомерный статический массив - понятие условное. Как известно, массив размерности n является одномерным массивом множества объектов производного типа - массивов размерности n-1. Главной особенностью передачи массивов в качестве параметров является то, что объявление одномерного массива-параметра преобразуется к объявлению указателя на элемент производного типа. Например, массив int a[10][3] сводится к указателю типа int (*)[3]. После такого приведения внутри функции ничего не известно о размере массива. Таким образом, при работе с массивами в качестве параметров следует передавать и количества элементов в размерностях либо делать эти значения глобальными константами (или определять с помощью директив препроцессора). Пример 5.4. Передача массивов как параметров в функции сложения элементов массива. /* функция суммирования элементов одномерного массива. Со статическими и с динамическими массивами проблем не возникает, т.к. при передаче параметра массив сводится к указателю. */ int sum1(int *a, int dim){ //int sum1(int a[], int dim){ эквивалентное описание cout< int s=0; for (int i=0;i return s;}; /* функция суммирования элементов двухмерного массива. Массив передается как указатель на тип элемента двухмерного массива. В функции используется тот факт, что элементы в памяти расположены подряд */ int sum2_v1(int *a, int dim1, int dim2){ // передаем количества элементов int s=0; for (int i=0; i for (int j=0; j s+=a[i*dim2+j]; // рассматриваем двухмерный массив как одномерный return s;} /* функция суммирования элементов двухмерного массива. Массив передается как указатель на указатель на тип элемента массива. Подходит для динамических массивов. */ int sum2_v2(int ** a, int dim1, int dim2){ int s=0; for (int i=0; i for (int j=0; j s+=a[i][j]; /* поскольку имеем указатель на указатель, можем пользоваться двойными индексами */ return s;} /* функция суммирования элементов статического двухмерного массива либо динамического массива, где динамически задавалось количество элементов только в первой размерности. Массив передается как указатель на массив из 3-х элементов. Тройка в int a[][3] не задает количество элементов (его передаем отдельным параметром) а лишь определяет тип. */ int sum2_v3(int a[][3], int dim1, int dim2){ int s=0; for (int i=0; i for (int j=0; j s+=a[i][j]; return s;} /* функция аналогичная предыдущей, но тип параметра другой */ int sum2_v4(int a[][10], int dim1, int dim2){return 0;} int main(){ int A[5]={1,2,3,4,5}; // статический одномерный массив int B[2][3]={{1,2,3},{4,5,6}}; // статический двухмерный массив int *C=new int [4]; /* двухмерный, динамически задается только количество элементов в первой размерности */ for (int i=1; i<=4;i++) C[i-1]=i; // инициализируем массив C int ** D= new int* [3]; // двухмерный полностью динамический массив for (int i=0;i<3;i++) D[i]=new int [4]; // инициализируем массив D for (int i=0;i<3;i++) for (int j=0;j<4;j++) D[i][j]=i*4+j+1; cout< cout << sum1(A,sizeof(A)/sizeof(A[0]))< cout << sum1(C,4)< /* сводим двухмерный статический к одномерному */ cout << sum2_v1(&B[0][0],2,3)< cout << sum2_v1((int *)B,2,3)< //cout << sum2_v2(B,2,3)< cout << sum2_v3(B,2,3)< //cout << sum2_v4(B,2,3)< cout << sum2_v2(D,3,4)< //cout << sum2(D[0],3,4)< delete [] C; // освобождаем память из под одномерного массива C for (int i=0;i<3;i++) delete [] D[i]; // освобождаем память из под D delete [] D; return 0;}
Передача функций в качестве параметров. Функцию можно вызвать через указатель на нее. Объявляется указатель соответствующего типа и ему с помощью операции взятия адреса присваивается адрес функции. тип (*имя_указателя) (список типов принимаемых параметров); Пример: void f(int а ){…} определение функции, принимающий один целочисленный параметр. void (*pf)(int); указатель на функцию, принимающую целочисленный параметр pf = f; указателю присваивается адрес функции pf(10); вызываем функцию f, через ее адрес и с аргументом равным десяти. С помощью ключевого слова typedef можно определять целое семейство однотипных функций. Пример 5.5. int add (int a,int b){return a+b;} //функция сложения двух чисел int sub (int a,int b){return a-b;} //функция вычитания двух чисел int mul (int a,int b){return a*b;} //функция умножения двух чисел typedef int (*op)(int, int); /* определяем новый тип - указатель на функцию, принимающую два целых параметра и возвращающую целый результат */ enum oper {plus, minus, production}; // определим набор операций int main(){ op doit[]={&add,&sub,&mul}; // массив из указателей на функции int a,b; cin>>a>>b; // вводим два числа oper action; // переменная определяет действие над числами /* вводим тип операции */ action = production; cout << doit[action](a,b); /* в зависимости от значения параметра action произойдет вызов необходимой функции */ return 0;} Данный подход избавляет нас от использования конструкций if и switch при выборе той или иной функции. Указатели на функции передаются в функции в качестве параметров подпрограмму таким же образом, как и параметры других типов: Пример 5.6. /*определим функцию, возвращающую максимальный элемент в массиве */ int max_array(int * a, int dim){ int max=a[0]; for(int i=1;i return max; } /* определим функцию, возвращающую сумму элементов массива */ int sum_array(int * a, int dim){int s=0; for(int i=0;i return s; } typedef int (* funct)(int *, int); // определим тип указателя на семейство функций // функция увеличивающая некоторую характеристику массива в три раза int array_param_3x(int *a, int dim, funct f){ return 3*f(a,dim); } int main(){ int a[]={4,2,7,5,3}; // выводим утроенное значение максимального элемента cout << array_param_3x(a,sizeof(a)/sizeof(a[0]), &max_array)< // выводим утроенное значение суммы элементов cout << array_param_3x(a,sizeof(a)/sizeof(a[0]), &sum_array)< return 0;} СЕМИНАРСКОЕ ЗАНЯТИЕ 1 Студент самостоятельно должен изучить следующий материал: Понятие среды разработки и её составные части. Понятие транслятора. Компиляторы, интерпретаторы, JIT- компиляторы, байт код. Компилятор C++. Понятие линковщика. Понятие препроцессора. Проект на C++. Файлы библиотек. Заголовочные файлы. Основные библиотеки, входящие в стандарт C++, их заголовочные файлы. Задания к семинарскому занятию:
СЕМИНАРСКОЕ ЗАНЯТИЕ 2 Студент самостоятельно должен изучить следующий материал: Структура программы на C++. Основные функции модуля ctime (time.h). Функции модуля cmath. Тригонометрические функции. Функции округления. Вычисление логарифма и экспоненты. Случайные числа. Вычисление корня, возведение в степень, абсолютное значение числа, вычисление остатка от деления вещественных чисел. |
Применение многопроцессорных вычислительных систем (мвс) ставит две задачи построения параллельных алгоритмов: распараллеливание... | Основы программирования и конфигурирования в корпоративных информационных системах | ||
Описать основные элементы структуры программы ( Раздел интерфейса, раздел реализации, раздел инициализации) | Цель контрольной работы – закрепление и проверка знаний, полученных студентами заочной формы обучения в процессе самостоятельного... | ||
Виртом в 1971 г., играет особую роль и в практическом программировании, и в его изучении. С непревзойденной четкостью в нем реализованы... | Методические указания предназначены для выполнения курсовой работы по дисциплине «Объектно-ориентированное программирование» для... | ||
Хотя набор стандартных функций электронных таблиц достаточно широк, для некоторых задач он либо недостаточен, либо выполнение таких... | Интерфейс среды matlab (окно команд, окно рабочего пространства, окно истории команд, окно «текущая папка», окно Details, меню Start,... | ||
Назовите основные разделы науки о языке и единицы языка, изучаемые в этих разделах | Представительством Европейского Союза в России для облегчения понимания правил конкурса для потенциальных российских участников.... |
Поиск Главная страница   Заполнение бланков   Бланки   Договоры   Документы    |