Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология
Образование Политология Производство Психология Стандартизация Технологии


Объявление и определение функции



 

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

 

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

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

{

операторы

}

Тип_возвр_знач - определяет тип значения, которое возвращается из функции. Если тип функции не указан считаются объявленными с типом int.

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

 

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

 

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

Для каждого элемента списка параметров указываются тип и имя параметра, элементы списка разделяются запятой.

 

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

Функция может быть задана без параметров и вместо списка может стоять слово void.

 

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

Для передачи управления и возврата значения из функции используется оператор return:

 

return выражение;

 

При выполнении оператора выполняются следующие действия:

1) выход из функции и возврат управления в точку её вызова;

2) вычисляется и возвращается значение выражения, указанного в операторе.

 

Если функция объявлена с типом void, то оператор имеет вид: return; Пример:

 

#include " stdafx.h"

#include < iostream>

 

using namespace std;

 

 

bool IsCratnoe(int delimoe, int delitel); // объявление (прототип) функции

 

 

int _tmain(int argc, _TCHAR* argv[])

{

int value1, value2;

 

cout< < " Input delimoe: "; cin> > value1; cout< < endl;

cout< < " Input delitel: "; cin> > value2; cout< < endl;

 

// вызов функции

cout< < value1< < " " < < (IsCratnoe(value1, value2)? " cratnoe ": " ne cratnoe " )< < value2;

 

return 0;

}

 

bool IsCratnoe(int delimoe, int delitel) // обпределение функции

{

if(delimoe % delitel==0)

return true;

else

return false;

}

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

 

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

 

Существует три способа передачи параметров в функцию:

1) по значению;

 

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

 

2) по адресу (указателю);

 

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

#include " stdafx.h"

#include < iostream>

 

using namespace std;

 

int DrobnoeCeloe(float src, float* drob); // объявление (прототип) функции

 

int _tmain(int argc, _TCHAR* argv[])

{

int celoe;

float value, drobnoe;

 

cout< < " Input value: "; cin> > value; cout< < endl;

celoe=DrobnoeCeloe(value, & drobnoe);

 

cout< < value< < " = " < < celoe< < " + " < < drobnoe;

 

return 0;

}

 

int DrobnoeCeloe(float src, float* drob) // обпределение функции

{

int celoe=(int)src; // получаем целую часть операцией приведения типа

 

*drob=src-celoe; // вычисляем дробную часть и

//записываем результат по указателю drob

return celoe; // возвращаем целую часть

}

3) по ссылке.

(не давать)

Составные типы данных

 

Для решения сложных задач, с которыми обачно сталкивается человек

рассмотренных выше элементарных типов недостаточно. Они очень просты (элементарны) по сравнению с объектами реального мира.

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

сложные типы данных.

К сложным типам данных относятся:

- массивы;

- строки;

- структуры;

- классы.

Язык С++ позволяет использовать эти типы для организации своих пользовательских типов.

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

 

Одномерные массивы

 

Массив — это набор данных одного типа, которые в памяти размещаются последовательно.

Как работать с массивами, что можно что нельзя:

1. Определение количества элементов массива.

 

При объявлении массива инициализацией программист не задает явно размер массива, а он необходим для организации обработки массива, поскольку нужно знать сколько элементов хранит массив. Как это сделать?

Пример:

#include " stdafx.h"

#include < iostream>

using namespace std;

 

 

int _tmain(int argc, _TCHAR* argv[])

{

float float_array[]={ 1.1f, 1.2f, 1.3f, 1.4f, 1.5f };

 

// определение кол-ва элементов массива

int num=sizeof(float_array)/sizeof(float);

 

// sizeof(float_array) возвращает кол-во байт памяти, связанное с массивом

cout< < " sizeof(float_array)=" < < sizeof(float_array)< < endl;

 

// sizeof(float) возвращает кол-во байт памяти, используемое для

// представления в памяти данного типа float

cout< < " sizeof(float)=" < < sizeof(float)< < endl;

 

cout< < " num=" < < num< < endl;

 

// используем значение num для распечатки элементов массива

for(int i=0; i< num; i++)

cout< < " float_array[" < < i< < " ]=" < < float_array[i]< < endl;

 

return 0;

}

Обычные массивы для работы предоставляют ограниченный набор средств:

- нельзя присвоить одну переменную-массив другой;

- недопустимо сравнивать массивы;

- нельзя складывать, умножать и т. д.

Единственное, что можно делать с массивами — передавать их функции как аргумент.

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

Все операции можно выполнять только с отдельными элементами массива. При копировании одного массива в другой достаточно скопировать по отдельности каждый элемент массива. При сравнении массивов сравниваются соответствующие элементы.

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

Если float float_array[10]; - это массив, то float_array[i] – это склаярная величина, т.е. элементарное данное, с которой можно все делать, что допустимо в данном случае на переменной типа float.

Т.е. допустимы, например, такие действия как:

float_array[i]=20.7;

float_array[i+2]= float_array[i]*10;

С++ интерпретирует квадратные скобки [] - как операцию, а не

просто как обозначение элемента. Эта операция имеет высокий приоритет.

Она называется операцией доступа по индексу.

Слева от неё стоит операнд – имя массива, а в скобках операнд – индекс массива, к которому осуществляется доступ.

В качестве индекса может применяться любое числовое выражение целого типа. Программист не может произвольно выбирать диапазон значений индексов массивов. В С++ индекс массива может лежать от значения 0 до значение nun-1, если num – это количество элементов в массиве.

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

Причина: разработчики компилятора С++ отказались от этого для обеспечения лучшего быстродействия разрабатываемых программ.

Если программа написана так, что индекс при обращении к массиву всегда имеет допустимоё значение, то проверка не нужна.

В любом случае решение принимает программист. Но, если индекс, указываемый в операторе, может выходить за пределы допустимого диапазона индексов, то программа будет работать не верно. И при отладке программы это надо помнить.

Пример:

#include " stdafx.h"

#include < iostream>

using namespace std;

 

 

int _tmain(int argc, _TCHAR* argv[])

{// как работать с массивами

 

float float_array[]={ 1.1f, 1.2f, 1.3f, 1.4f, 1.5f };

 

float new_array[10];

 

// копируем массив float_array в new_array

 

for(int i=0; i< 10; i++) //ошибка-кол-во элементов в мас. float_array =5

new_array[i]=float_array[i];

 

// выводим новый массив

for(int i=0; i< 10; i++)

cout< < " new_array[" < < i< < " ]=" < < new_array[i]< < endl;

 

return 0;

}

Вот что выведет программа.

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

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

В этом случае правильным решением будет, например такое:

#include " stdafx.h"

#include < iostream>

using namespace std;

 

int _tmain(int argc, _TCHAR* argv[])

{// как работать с массивами

 

float float_array[]={ 1.1f, 1.2f, 1.3f, 1.4f, 1.5f };

float new_array[10];

 

// копируем массив float_array в new_array

for(int i=0; i< 10; i++)

if (i< sizeof(float_array)/sizeof(float))

new_array[i]=float_array[i];

else

new_array[i]=0;

// выводим новый массив

for(int i=0; i< 10; i++)

cout< < " new_array[" < < i< < " ]=" < < new_array[i]< < endl;

 

return 0;

}

 

 

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

 

Пример 1:

Работа с указателем: инициализация указателя адресом, обращение по указателю.

// pointers1.cpp

#include " stdafx.h"

#include < iostream>

 

using namespace std;

 

int _tmain(int argc, _TCHAR* argv[])

{

int x=5;

 

// инициализация указателя адресом переменной x

int *y = & x;

 

// обращение к переменной по указателю *y

cout< < " Znachenie po ukazatelu: " < < *y< < endl;

 

cout< < " adress peremennoi: " < < y< < endl;

 

return 0;

}

Пример 2:

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

#include " stdafx.h"

#include < iostream>

 

using namespace std;

 

 

int _tmain(int argc, _TCHAR* argv[])

{

// указатель на переменную целого типа

int *y;

// выделение участка динамической памяти размером sizeof(int)

y = new int;

// присвоение значения переменной по указателю

*y=10;

 

cout< < " y= " < < y< < endl;

cout< < " *y= " < < *y< < endl;

 

// освобождение памяти

delete y;

 

return 0;

}

Пример 3:

Вычислить среднее арифметическое 10 элементов одномерного массива.

#include " stdafx.h"

#include < iostream>

 

using namespace std;

 

// объвление функций

// функция для ввода чисел массива

void Input(int* a, int N);

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

float Average(int* a, int N);

 

int _tmain(int argc, _TCHAR* argv[])

{

// выделение памяти массивом из 10 символов

int ar[10];

 

// ввод массива

Input (ar, 10);

 

// вывод среднего арифметического

cout< < " Srednee= " < < Average(ar, 10);

 

return 0;

}

 

 

void Input(int* a, int N)

{

cout< < " Input the numbers: " < < endl;

for (int i=0; i< N; i++)

{

cout< < " a[" < < i< < " ]= ";

cin> > a[i];

cout< < endl;

}

}

float Average(int* a, int N)

{

int sum=0;

 

// вычисления суммы элементов

for (int i=0; i< N; i++)

sum+=a[i];

// возвращение среднего арифметического элементов массива

return (float)sum/N;

}

работа с динамическим массивом.

 

#include " stdafx.h"

#include < iostream>

 

using namespace std;

 

// объвление функций

// функция для ввода чисел массива

void Input(int* a, int N);

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

float Average(int* a, int N);

 

int _tmain(int argc, _TCHAR* argv[])

{

int* arptr; // указатель на int - используется как указатель на первый

// элемент массива

 

int n; // количество элементов массива

 

cout< < " Input the quantity of elements: ";

 

// ввод количества элементов массива

cin> > n;

 

// выделение памяти под n элементов массива целых чисел

arptr = new int [n];

 

// ввод массива

Input (arptr, n);

 

// вывод среднего арифметического

cout< < " Srednee= " < < Average(arptr, n);

 

// освобождение памяти от массива

delete [] arptr;

 

return 0;

}

 

void Input(int* a, int N)

{

cout< < " Input the numbers: " < < endl;

for (int i=0; i< N; i++)

{

cout< < " a[" < < i< < " ]= ";

cin> > a[i];

cout< < endl;

}

}

float Average(int* a, int N)

{

int sum=0;

 

// вычисления суммы элементов

for (int i=0; i< N; i++)

sum+=a[i];

// возвращение среднего арифметического элементов массива

return (float)sum/N;

}

Многомерные массивы

 

Статические массивы

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

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

Так для массива int mas[3][2]; в памяти формируется такая последовательностьразмещения:

 

[0][0], [0][1], [1][0], [1][1], [2][0], [2][1]

 

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

(1) как одномерного массива, при этом значения надо задавать согласно размещению элементов массива в памяти:

 

int mas[3][2]={0, 1, 2, 3, 4, 5};

 

(2) как многомерного массива, приєтом каждое измерение представляется как массив:

 

int mas[3][2]={

{0, 1},

{2, 3},

{4, 5}

};

 

Доступ к элементам многомерного массива производится указанием индексного выражения:

 

mas[2][1]

при этом для обращения к элементу массива индексное выражение приводится к выражению с указателями:

 

*(*(mas+2)+1)

что следует из pe[ie] ó *(pe+ie).

 

Отсюда также следует, что mas является переменной указателем типа:

int **mas;

 

что означает, что переменая mas является указателем на указатель типа int*.

 


Поделиться:



Последнее изменение этой страницы: 2017-03-14; Просмотров: 300; Нарушение авторского права страницы


lektsia.com 2007 - 2024 год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! (0.131 с.)
Главная | Случайная страница | Обратная связь