Лабораторная работа № 8. Краткие теоретические сведения




Лабораторная работа № 8

Тема: Разработка программ с использованием функций.
Цель: Получить практические навыки проектирования, реализации и использования функций, научиться использовать различные способы передачи параметров и возврата результата.
Программное обеспечение   OC Windows, интегрированная среда программирования на С++ Сode::Blocks.
Задание:Разработать и протестовать работу следующих функций: 1. Напишите функцию, вычисляющую расстояние между двумя точками на плоскости (х1, у1) и (х2, у2). Используйте эту функцию для расчета суммарной длины ломаной линии, заданной набором из трех точек. 2. Напишите функцию, которая при каждом вызове будет выводить на экран количество раз, которое она вызывалась ранее. Напишите программу, которая будет вызывать эту функцию не менее десяти раз. Реализуйте данную функцию двумя различными способами: с использованием глобальной и статической локальной переменных для хранения числа вызовов функции. 3. Напишите функцию с именем hms (), имеющую три аргумента типа int: часы, минуты и секунды. Функция должна возвращать эквивалент переданного ей временного значения в секундах (типа long). Создайте программу, которая будет циклически запрашивать у пользователя ввод значения часов, минут и секунд и выводить результат на экран. 4. Разработать программу консольной логической игры «Быкы и коровы».Играют двое. Каждый задумывает и записывает 5-значное целое число, которое не содержит цифру 0 и повторяющихся цифр. Игрок, который начинает игру первым, делает попытку отгадать число. Противник сообщает в ответ, сколько цифры угаданы без совпадения с их позициями(коровы) в задуманном числе и сколько угадано с учетом позиции цифры в числе(быки). Например: Первый игрок задумал число: «32197». Второй игрок попробует отгадать: «23168». Результат: три «коровы» (цифры "2", "3" и "1" - угаданные) и один «бык» (одна цифра "1" угадана и стоит на своей позиции). Игроки делают попытки угадать поочередно. Побеждает тот, кто угадает число первым. 5. Оформить отчет.
Содержание отчета 1. Тема 2. Цель 3. Порядок выполнения работы. 4. Исходные коды программы с комментариями. 5. Результаты тестирования программ. 6. Выводы
Контрольные вопросы 1.Дайте определение пользовательской функции. Аргументы, возвращаемое значение и тело функции. Приведите пример. 2. Вызов функции и возврат из нее. Оператор return. Приведите пример. 3. Прототип функции. Общая форма записи и назначение. Приведите пример. 4. Чем аргумент функции отличается от параметра? Если функция использует параметр (аргумент), где он объявляется

Краткие теоретические сведения

Понятие функции в С++ аналогично понятию подпрограммы, которое имеется в большинстве языков программирования. Их использование связано с принципами модульного программирования, в основе которого лежит разделение программы на автономные фрагменты, или модули.

Таким образом, функции в С++ - это самостоятельные единицы программы, спроектированные для решения конкретных задач, обычно повторяющихся несколько раз. Примером являются все рассмотренные ранее функции стандартных библиотек stdio.h, conio.h, math.h. Однако пользователь может не только использовать готовые функции, но и создавать собственные. Более того, несколько функций пользователя могут быть впоследствии объединены в библиотеку.

Определение функции. Определение содержит код функции. Основная форма определения функции имеет вид:

тип возвращаемого значения <имя функции> (список параметров)

{

тело функции

}

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

Имя функции, как правило, отражает выполняемое ею действие. В качестве имени можно использовать любой допустимый идентификатор, который еще не был задействован в программе. После имени функции в круглых скобках указывается список параметров, который представляет собой последовательность пар (состоящих из типа данных и имени), разделенных запятыми. Параметры – это, по сути, переменные, которые получают значение аргументов, передаваемых функции при вызове. Если функция не имеет параметров, элемент «список параметров» отсутствует, т.е. круглые скобки остаются пустыми.

В фигурные скобки заключено тело функции, состоящее из последовательности операторов. Когда происходит вызов функции, программа передает управление первому оператору тела функции. Затем исполняются операторы, находящиеся в теле функции, и, когда достигается закрывающаяся фигурная скобка или инструкции return, управление передается обратно вызывающей программе. Для обращения к функции (ее вызова) используется имя функции с указанием набора передаваемых ей параметров в круглых скобках. Примером может служить функция, выбирающая наименьщее из трех чисел в приведенном ниже листинге программы:

#include <iostream.h> // подключаем библиотеки потокового

#include <conio.h> // и консольного ввода-вывода

float min (float a, float b, float c) // определяем функцию min

{

float m=a; // определяем локальную переменную m

if (b<m) m=b; // выбираем наименьшее из двух чисел

if (c<m) m=c; // выбираем наименьшее из двух чисел

return m; // возвращаем результат к месту вызова

}

void main () // точка начала программы

{

clrscr ();

float a=2.5, b=3.1, c=5.8; // задаем три аргумента для функции

float minimal; // объявляем переменную для результата

minimal=min (a,b,c); // вызываем функцию

cout <<"min="<< minimal; // выводим результат на экран

getch();

}

Прототип функции. Прототип функции – это ее опережающее объявление. В прототипе указывается только имя функции, тип результата и типы аргументов. Он не содержит реализации (тела) функции, а всего лишь указывает компилятору, что ее определение будет дано ниже в тексте программы. Если программа использует прототип функции, то обычно он располагается перед функцией main или внутри нее, а определение функции дается после функции main. В следующем примере рассмотренная ранее функция min объявлена с помощью прототипа:

#include <iostream.h> // подключаем библиотеки потокового

#include <conio.h> // и консольного ввода-вывода

float min (float a, float b, float c); // объявляем функцию min с помощью // прототипа

void main () // точка начала программы

{

clrscr ();

float a=2.5, b=3.1, c=5.8; // задаем три аргумента для функции

float minimal; // объявляем переменную для результата

minimal=min (a, b, c); // вызываем функцию

cout <<"min="<< minimal; // выводим результат на экран

getch ();

}

float min (float a, float b, float c) // определяем функцию min

{

float m=a;

if (b<m) m=b;

if (c<m) m=c;

return m;

}

Передача аргументов в функцию. Аргументом называют единицу данных (например, переменную

типа int), передаваемую программой в функцию. Аргументы позволяют функции оперировать различными значениями или выполнять различные действия в зависимости от переданных ей значений.

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

//table.cpp

#include <iostream.h>

#include <conio.h>

// объявляем структуру

struct Distance

{

int feet;

float inches;

};

//объявляем функцию

void eng (Distance);

void main ()

{

clrscr ();

//объявляем переменные типа Distance

Distance d1, d2, d3;

cout<<"vvedite chislo futov";

cin>>d1.feet;

cout<<"vvedite chislo djumov";

cin>>d1.inches;

cout<<"vvedite chislo futov";

cin>>d2.feet;

cout<<"vvedite chislo djumov";

cin>>d2.inches;

//складываем дюймы

d3.inches=d1.inches+d2.inches;

d3.feet=0;

if (d3.inches>=12.0)

{

d3.inches-=12.0;

d3.feet++;

}

d3.feet+=d1.feet+d2.feet;

eng (d1);

eng (d2);

eng (d3);

getch();

}

//определяем функцию eng, выводящую результат каждый раз в новой

строке

void eng (Distance dd)

{

cout<<"\n";

cout<<dd.feet<<"'-"<<dd.inches<<"'' ";

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

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

//power.cpp

#include <iostream.h> // подключаем библиотеки потокового

#include <conio.h> // и консольного ввода-вывода

void power (int base, int exp) // объявляем и определяем функцию power

{

int i;

// если показатель степени отрицательный, оператор return немедленно

// завершает функцию power

if (exp<0) return;

i=1;

for (;exp; exp--) i=base*i; // в теле функции организуем цикл по показателю

степени

cout<<"otvet="<<i;

}

void main () // точка начала программы

{

clrscr ();

power (10,2); // вызываем функцию и задаем ее аргументы

power (10,-2);

getch ();

}

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

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

Существуют три типа области видимости: локальная область видимости, область видимости файла, область видимости класса.

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

Переменные, имеющие область видимости файла, доступны из любого места файла, в котором они определены.

Существуют два класса памяти: automatic (автоматический) и static (статический).

У переменных, имеющих класс памяти automatic, время жизни равно времени жизни функции, внутри которой они определены.

У переменных, имеющих класс памяти static, время жизни равно времени жизни всей программы.

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

Область видимости переменной определяет участки программы, из которых возможен доступ к этой переменной. Это означает, что внутри области видимости переменной операторы могут обращаться к ней по имени и использовать ее значение при вычислении выражений. За пределами области видимости попытки обращения к переменной приведут к выдаче сообщения о том, что переменная неизвестна.

Например, имеется следующая функция:

void somerfunc ()

{

//локальные переменные

int somervar;

float othervar;

somervar=10; //корректно

othervar=11; //корректно

nextvar=12; // некорректно, переменная невидима в функции

}

Рассмотрим классы памяти локальных переменных. Локальная переменная не существует в памяти до тех пор, пока не будет вызвана функция, в которой она определена. Это означает, что в памяти нет места, выделенного для их хранения. Когда управление передается в функцию, переменные создаются и под них отводится место в памяти. Затем, когда выполнение функции завершается и управление передается вызывающей программе, переменные уничтожаются, а их значения теряются. Название автоматического класса памяти как раз указывает на то, что переменные автоматически создаются при входе в функцию и автоматически уничтожаются при выходе из нее.

В отличие от локальных переменных, определяемых внутри функции, глобальные переменные определяются вне каких-либо функций. Глобальная переменная видима из всех функций данного файла, потенциально – из других файлов. По этой причине определения глобальных переменных располагают в начале листинга. Следующий пример демонстрирует использование глобальной переменной тремя функциями:

//global.cpp

#include <iostream.h>

# include <conio.h>

char ch='a'; //глобальная переменная сh

//прототипы функций

void getachar ();

void putachar ();

/* пока не нажата клавиша Enter, вводим символ и он отражается на

экране, т.е. переменная ch доступна двум функциям */

void main ()

{

clrscr ();

while (ch!='\r')

{

getachar ();

putachar ();

}

}

void getachar ()

{

ch=getch();

}

void putachar ()

{

cout<<ch; //cout<<"\n";

}

Рассмотрим еще один тип переменных, называемый статическими локальными переменными. Существуют и статические глобальные переменные, но они используются в многофайловых программах, которые мы не рассматриваем. Статическая локальная переменная имеет такую же область видимости, как и автоматическая. Однако время жизни у статической локальной переменной совпадает с временем жизни глобальной переменной, с той разницей, что существование статической локальной переменной начинается при первом вызове функции, к которой она принадлежит. Далее переменная существует на протяжении выполнения программы. Статические локальные переменные используются в тех случаях, когда необходимо сохранить значение переменной в памяти после того, как выполнение функции будет завершено. Следующий пример демонстрирует использование статической локальной переменной:

//static.cpp

#include <iostream.h>

#include <conio.h>

float favg (float);

void main ()

{

clrscr ();

float data=1, avg;

while (data!=0)

{

cout<<"Vvedite chislo:";

cin>>data;

avg=favg (data);

cout<<"\nsrednee znachenie:"<<avg;

}

getch ();

}

// функция favg () находит среднее арифметическое всех введенных

// значений

float favg (float newdata)

{

//инициализация статических переменных при первом вызове

static float total=0;

static int count=0;

//увеличение счетчика

count++;

//добавление нового значения к сумме

total+=newdata;

//возврат нового среднего значения

return total/count;

}

Перегруженные функции. Перегруженная функция выполняет различные действия, зависящие от типов данных, передаваемых ей в качестве аргументов. Существуют две функции: starline(), выводящая на экран линию из 45 символов «*», и repchar (), выводящая заданный символ заданное число раз, используя два аргумента. Создадим третью функцию charline (), которая всегда печатает 45 символов, но позволяет задавать печатаемый символ. Все эти функции выполняют схожие действия, но их имена различны. Очевидно, было бы гораздо удобнее использовать одно и то же имя для всех трех функций, несмотря на то что они используют различные наборы аргументов. Программа overload демонстрирует, каким образом это можно осуществить:

//overload.cpp

#include <iostream.h>

#include <conio.h>

//прототипы функций

void repchar ();

void repchar (char);

void repchar (char, int);

void main ()

{

clrscr();

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

repchar ();

cout<<"\n";

repchar ('=');

cout<<"\n";

repchar ('+',30);

getch ();

}

void repchar () //функция выводит 45 раз символ *

{

for (int j=0; j<45; j++)

cout<<"*";

}

void repchar (char ch) //функция выводит 45 заданных символов

{

for (int j=0; j<45; j++)

cout<<ch;

}

void repchar (char ch, int n) //функция выводит заданный символ заданное

{ // количество раз

for (int j=0; j<n; j++)

cout<<ch;

}

 



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2018-09-16 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: