- •Лабораторная работа № 9 Программирование с использованием функций
- •Теоретические сведения
- •Стандартные функции
- •Определение функции
- •Программируемые функции
- •Параметры функций
- •Возвращение значений с помощью оператора return
- •Параметры функций Передача массивов в качестве аргументов функции
- •Понятие об указателях
- •Пример 9.7.
- •Пример 9.9 Использование указателей для нахождения среднего значения массива n целых чисел.
- •Понятие ссылки
- •Контрольные вопросы
- •Лабораторное задание
- •Порядок выполнения лабораторной работы
- •Требования к отчету
- •Варианты заданий
Пример 9.7.
#include <iostream.h>
swp(int *x, int *y);
void main()
{ int a, b;
cout<<»Введите значения a и b»;
cin>>a>>b;
swp(&a, &b);
cout<<»Измененные значения:a=»<<a<<”b=”<<b;
}
void swp(int *x, int *y)
// x и y – указатели, *x и *y – значения, на которые они указывают
{ int c;
c=*x;
x=y;
*y=c;
}
Пример 9.8. Рассмотрим функцию, которая находит среднее значение массива целых чисел. Для входа в функцию задано имя массива и количество его элементов. Результатом работы функции является среднее значение, которое передается при помощи оператора return.
Оператор вызова функции может выглядеть следующим образом:
cout<<»Среднее из заданных значений»<<mean (numbs, size)<<endl;
/* Находим среднее значение массива из n целых чисел.*/
int mean (int array [ ], int n)
{ int index;
long sum; /* Если массив содержит много элементов, сумма может оказаться довольно большой, поэтому используем тип long int */.
If (n>0)
{ for (index=0, sum=0; index<n; index++)
sum+=array [index];
return sum/n; // Возвращает int.
}
else
{cout<<”Нет массива.”<<endl;
return 0;
}
}
Перепишем эту же программу с использованием указателей. Объявим iPtr указателем на тип int и заменим элемент массива array[index] на соответствующее значение: *(iPtr+index).
Пример 9.9 Использование указателей для нахождения среднего значения массива n целых чисел.
Int mean (int *iPtr, int n)
{ intindex;
long sum;
if (n>0)
{ for (index=0, sum=0; index<n; index++)
sum+=*(iPtr+index);
return sum/n; // возвращает целое sum / n
}
else
{ cout<<”Нет массива”<<endl;
return 0;
}
}
При такой замене в вызове функции ничего менять не придется, так как имя массива и указатель в данном случае взаимозаменяемы. Поэтому можно присваивать указателю адрес первого элемента, используя просто имя массива.
Int iarray [10];
int *iPtr = iarray; // То же самое, что iPtr=&iarray[0].
В С++ указатели можно увеличивать или уменьшать. Указатель, увеличенный на 3, будет указывать на четвертый элемент массива (эквивалентно &array[3]). Другими словами, увеличивая указатель на единицу, мы в действительности увеличиваем адрес, который он представляет, на размер объекта связанного с ним типа.
Так как указателям типа voidне соответствует никакой тип данных, к ним нельзя применять арифметические операции.
Указатель можно индексировать точно так же, как массив. Компилятор в действительности преобразует индексацию в арифметику указателей: iarray[3]=10; представляется как *(iarray+3)=10;
Понятие ссылки
В С++ имеется несколько видоизмененная форма указателя, называемая ссылкой. Ссылка на некоторую переменную может рассматриваться как указатель, который при употреблении всегда разыменовывается. Однако для ссылки не требуется дополнительного пространства памяти: она является просто другим именем (псевдонимом) переменной.
Для определения ссылки применяется унарный оператор &.
Пример 9.10.
# include <iostream.h>
int value=10;
int &refval=value; // Ссылка на value
int main (void)
{ cout<<”value=”<<value<<endl;
refval+=5; // Модификация через ссылку
cout<<”value=”<<value<<endl;
cout<<”Адрес value равен “<<&value<<endl;
cout<<”Адрес refval равен “<<&refval<<endl;
return 0;
}
Хотя ссылка может быть определена как псевдоним переменной, прежде всего ссылки применяются для параметров функций и возвращаемых функциями значений. Вызов функции, ожидающей в качестве параметра ссылочную переменную, синтаксически не отличается от вызова, в котором параметр передается значением. Чтобы указать, что функция ожидает передачу параметра ссылкой, в прототипе перед именем переменной ставится модификатор &. Рассмотрим пример использования параметров-ссылок.
Пример 9.11.
# includе <iostream.h>
void Inc_val (int i) // Получает параметр-значение
{ i++; // Модификация не влияет на оригинал
}
void Inc_ptr (int *i) // Получает адрес оригинала
{(*i)++; // Модифицирует оригинал путем косвенной адресации
}
void Inc_ref (int & i) // Получает параметр-ссылку
{i++; // Модифицирует оригинал!
}
int main(void)
{ int j=10;
cout<<”j=”<<j<<endl;
Inc_val (j);
cout<<”После Inc_val (j) j = “<<j<<endl;
Inc_ptr (&j);
Cout<<”После Inc_ptr (j) j=”<<j<<endl;
Inc_ref (j);
Cout<<”После Inc_ref (j) j=”<<j<<endl;
return 0;
}
При вызове функции, ожидающей передачи ссылки, компьютер неявно передает адрес специфицированного параметра. Внутри самой функции компилятор транслирует все обращения к параметру, разыменовывая переданный адрес. При этом:
вызывающей функции не требуется применять операцию взятия адреса (&);
вызываемая функция избавляет от использования косвенных операций (*).
Ссылка может быть использована как тип, возвращаемый функцией. Это позволяет присваивать функции значение.
Пример 9.12. Ссылка как возвращаемый функцией тип.
#include <iostream.h>
const int arraySize = 0xF;
static int valArray[arraySize];
int &valueAt(int indx)
{ return valArray [indx];
}
int main (void)
{ for (int I=0; I<arraySize; I++)
valueAt (i)=1<<I;
for (I=0; I<arraySize; I++)
cout<<”Значение”<<I<<”=”<<valueAt(i)<<endl;
return 0;
}
Функцию valueAt(int) можно применять как для чтения элемента с определенным индексом, так и для присваивания нового значения этому элементу.