Передача нескольких результатов
Передача аргументов по ссылке и указателю может пригодиться в случае если функция должна возвращать несколько результатов. Как мы указали выше в функции не может содержаться две и более операции return, если они не входят в конструкцию ветвления. Также параметры функции не могут указываться через запятую после операции return. Кроме того, в языках Си/Си++ отсутствуют подпрограммы (процедуры), а существуют только функции. В классическом понимании, функция не может возвратить больше одного результата. Как выйти из данного положения, если необходимо возвратить несколько результатов. В этом случае поступают, например так:
void f(int a, int *r1, int r2){
(*r1)+=a;
(*r2)-=a;
}
или в языке Си++ так:
void f(int a, int &r1, int &r2){
r1+=a;
r2-=a;
}
где r1 и r2 результаты функции.
Кроме того, возможен следующий вариант:
int f(int a, int &r1){
r1+=a;
r2-=a;
return r2
}
Существует еще один вариант передачи результатов: при помощи структуры.
struct myStruct {
int r1;
int r2;
};
myStruct ms;
myStruct f(int a){
ms.r1+=a;
ms.r2-=a;
return ms;
}
Локальные переменные
В первом приближении будем считать, что переменные, которые описаны внутри тела функции, называются локальными. Переменные, которые описаны вне данной функции будут являться глобальными по отношению к данной функции. В дальнейшем мы дополним данные определения. Мы подчеркиваем, что локальные переменные являются действительно локальными. Даже в том случае, когда мы используем одно и то же имя для переменных в двух различных функциях, компилятор считает их разными переменными.
Это означает, что формальные параметры (аргументы) функции локализованы в ней, то есть недоступны вне определения функции и никакие операции над формальными параметрами в теле функции не изменяют значения фактических параметров.
Следует учесть, что не рекомендуется, например, следующая запись:
int *f(){
int local = 5;
return &local;
}
Переменная local является локальной поэтому невозможно вернуть указатель на данную переменную, т.к. ее не существует вне данной функции. Вместе с тем, если записать так:
int f(){
int local = 5;
return local;
}
то такое объявление вполне законно, т.к. в точку вызова функции передается копия локальной переменной.
Передача массивов в качестве параметров
Существует несколько способов передачи массивов в качестве параметров функции, однако наиболее универсальным является передача массивов по указателю. Итак, условимся, что массивы будем передавать в функцию только через указатель:
int a[3]={2,5,-6};
int f(int *a){
if (*(a+1)==5) return 1;
else return 0;
}
Возможна и следющая запись:
int a[3]={2,5,-6};
int f(int *a){
if (a[1]==5) return 1;
else return 0;
}
Вызов функции будет, например, следующим:
f(a);
Обратите внимание, т.к. массив уже является указателем на его нулевой элемент, то знак & при вызове функции писать не нужно.
Передавать многомерные массивы лучше всего следующим способом:
void print_mij(int *m, int dim1, int dim2)
{
for(int i=0;i<dim1;i++){
for(int j=0;j<dim2;j++)
cout << m[i*dim2+j] ;
cout << endl;
}
}
Однако, если размерность массива известна заранее, то можно передать массив и следующим способом:
void print_m35(int m[3][5])
{
for(int i=0;i<3;i++){
for(int j=0;j<5;j++)
cout << m[i][j] ;
cout << endl;
}
}
Массивы передаются в любом случае как указатель, а не копируются
Возвращение значений в качестве результата функции по ссылке и указателю.
Существует возможность возврата указателя или ссылки в операции return. Не стоит только забывать, что нельзя возвращать указатель или ссылку на локальную переменную.
Прототипы функций.
Для более ясной структуры программы, а также для удобства обработки компилятором функций использовать предварительные объявления функций, так называемые прототипы.
Пример.
void f(int a);
void f(int a){
for (int i=0;i<a;i++)printf("Hello world");
}
имя переменной в прототипе можно опустить:
void f(int);
void f(int a){
for (int i=0;i<a;i++)printf("Hello world");
}
Использование прототипов может быть выгодно в следующем случае:
void f(){
g(3);
}
void g(int a){
for (int i=0;i<a;i++)printf("Hello world");
}
В данном участке кода будет выдана ошибка, т.к. функцию g компилятор еще не «знает», а она уже вызывается в функции f. Для нормальной работы программы следует написать так:
void g(int a){
for (int i=0;i<a;i++)printf("Hello world");
}
void f(){
g(3);
}
либо так:
void g(int);
void f(){
g(3);
}
void g(int a){
for (int i=0;i<a;i++)printf("Hello world");
}
Обратите внимание, в конце описания прототипа ставится «;»
Задание
1. Реализуйте приведенные ниже задачи на языке С.
2. В работе обязательно использовать псевдонимы функции.
3. В работе запрещено использовать глобальные переменные для пользовательских функций.
4. Составьте отчет по приведенному образцу.
Варианты для самостоятельного решения.
Вариант 1
Даны две матрицы. Определить функцию для нахождения произведения двух матриц. Ввод и вывод данных, а также вызов вышеуказанной функции, осуществить в функции main().
Вариант 2
Дана квадратная матрица. Определить функцию для нахождения определителя данной матрицы. Ввод и вывод данных, а также вызов вышеуказанной функции, осуществить в функции main().
Вариант 3
Вариант 4
Составьте программу вычисления НОК по формуле. Вычисление НОК и НОД организуйте в виде отдельных функции.
Вариант 5
Даны два предложения. В каком из них доля (в %) букв, введенных с клавиатуры больше. Определить функцию для расчета некоторой буквы в предложении.
Вариант 6
Даны 4 числа. Организуйте перестановку данных чисел в обратном порядке. Перестановку двух чисел организуйте в виде отдельной функции. Запрещено использовать массивы.
Вариант 7
Заданы две прямые (уравнениями y=kx+b). Запрограммируйте процесс нахождение координат точки пересечения данных прямых. Оформите его в виде отдельной функции. Если точки пересечения не существует, то вывести на экран соответствующее сообщение.
Вариант 8
Даны координаты четырех точек. Определить функцию, которая должна определять лежат ли данные точки на одной прямой. Ввод и вывод данных, а также вызов вышеуказанной функции, осуществить в функции main().
Вариант 9
Даны координаты четырех точек в заданном порядке. Определите косинус между векторами, задаваемыми этими точками. Вычисление координат вектора и его длины оформите в виде отдельных функций.
Вариант 10
Задано квадратное уравнение. Запрограммируйте решение данного квадратного уравнения. Вычисление дискриминанта оформите в виде отдельной функции, а вычисление корней уравнения в виде другой отдельной функции (если квадратное уравнение имеет два корня, то их вычисление оформить в виде одной функции)
Вариант 11
Вариант 12
функцию
Вариант 13
Вариант 14
Вариант 15
Вариант 16
Вариант 17
Вариант 18
Вариант 19
Вариант 20
Вариант 21
Даны два комплексных числа (в алгебраической форме). Определить функции сложения и вычитания данных чисел. В данную функцию передаются и возвращаются из функции только действительная и мнимая часть комплексных чисел (в виде отдельных переменных). Ввод и вывод данных, а также вызов вышеуказанной функции, осуществить в функции main(). При вводе и выводе учесть мнимую единицу (вывести как часть строки), т.е., например, число a+bi на экран будет выводиться так: printf("%d+%d i",a,b);
Вариант 22
Напишите программу, которая определяет упорядочены ли цифры числа по возрастанию. «Вырезку» цифры и определение порядка цифр оформите в виде отдельных функций.
Вариант 23
Даны две матрицы. Определить функцию для нахождения суммы двух матриц. Ввод и вывод данных, а также вызов вышеуказанной функции, осуществить в функции main().
Вариант 24
Составьте программу, которая определяет равновелики ли два треугольника. Вычисление площади оформите в виде отдельной функции. Треугольники задаются координатами вершин.
Вариант 25
Вариант 26
Даны координаты трех векторов. Определить функцию, которая должна определять компланарны ли данные векторы. Ввод и вывод данных, а также вызов вышеуказанной функции, осуществить в функции main().
Вариант 27
Даны координаты двух векторов. Определить функцию, которая должна определять колиниарны ли данные векторы. Ввод и вывод данных, а также вызов вышеуказанной функции, осуществить в функции main().
Вариант 28
Даны два комплексных числа (в алгебраической форме). Определить функцию, которая должна вычислять произведение данных чисел. В данную функцию передаются и возвращаются из функции только действительная и мнимая часть комплексных чисел (в виде отдельных переменных). Ввод и вывод данных, а также вызов вышеуказанной функции, осуществить в функции main(). При вводе и выводе учесть мнимую единицу (вывести как часть строки), т.е., например, число a+bi на экран будет выводиться так: printf("%d+%d i",a,b);
Вариант 29
Вариант 30