Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Необходимость передачи переменных

Поиск

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

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

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

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

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

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

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

Передача значений

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

Передача по значению (или копированием)

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

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

Массивы и указатели всегда передаются по адресу.

Передача по адресу (или по ссылке)

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

При передаче переменной по адресу принимающей функции происходит копирование ее адреса, а не значения. В С все массивы передаются по адресу. Фактически, передается копия адреса массива.

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

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

 

Задание:

1. Написать программу, состоящую из трех функций – main(), fun1(), fun2(). В функции main() объявить символьный массив из 10 элементов. Заполнить его буквами от a до j в fun1() и вывести на экран в fun2().

2. Написать функцию, в которую передаются две целые переменные по адресу. В самой функции объявить третью локальную переменную. С ее помощью обменять значения двух переданных так, чтобы каждая из них имела бы значение другой при возврате управления в вызывающую функцию. Напечатать значения переменных до вызова и после вызова функции, а также их адреса.

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

 

Контрольные вопросы

1. Какие типы переменных всегда передаются по адресу?

2. Какие типы переменных всегда передаются по значению?

3. Если переменная передается в функцию по значению и там изменяется, будет ли изменена переменная в вызывающей функции?

4. Если переменная передается в функцию по адресу и там изменяется, будет ли изменена переменная в вызывающей функции?

 


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

 

Возвращение значения функцией

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

 

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

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

Хорошим стилем программирования на С является описание прототипа каждой написанной функции. Прототипы гарантируют соответствие типов данных передаваемых параметров и возвращаемых значений функции.

Возвращаемые значения функции

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

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

return(возвращаемое_значение);

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

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

/* Вычисление среднего значения трех введенных пользователем чисел */

#include <stdio.h>

float calc_av(int num1, int num2, int num3)

{

float local_avg; /* Содержит среднее значение этих чисел*/

local_avg=(num1+num2+num3)/3;

return (local_avg);

}

Main ()

{

int num1, num2, num3;

float avg; /* Будет содержать возвращаемое значение */

puts(“ Введи три числа через пробел”);

scanf(“%d %d %d”, &num1, &num2, &num3);

/* Вызов функции, передача параметров и получение возвращаемого значения */

avg = calc_avg(num1, num2, num3);

printf (“\n Их среднее – это %f”, avg);

return 0;

}

Cледует обратить внимание на дополнительные моменты программы, связанные с тем, что функция возвращает значение. Начальная часть функции main() обычна. Описываются локальные переменные – три для входных данных пользователя и одна для вычисленного среднего значения. Вызов функции calc_av () также обычен; он передает по значению три переменные num1, num2, num3 в функцию calc_av () (если бы функция принимала их по адресу, каждому аргументу должен был предшествовать амперсанд (&)).

Принимающая функция calc_av () выглядит так же, как и другие функции, за исключением первой строки – строки описания функ­ции, которая имеет одно дополнение: ключевое слово float перед ее именем. Так указывается тип возвращаемого значения. Нужно всегда указывать тип воз­вращаемого функцией значения. Если тип не указан, С установит его по умолчанию как int, но от этого пострадает четкость программы.

Так как переменная local_avg, которая возвращается из функции calc_av (), является вещественной, именно ключевое слово float, означающее вещественный тип, помещено перед именем этой функции.

Нужно обратить внимание на то, что оператор возврата функции calc_av () включает возвращаемое значение local_avg. Эта переменная будет передана назад в вызывающую функцию main(). Можно возвратить только единственное значение в вызывающую функцию.

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

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

avg = calc_avg(num1, num2, num3);

Когда функция calc_av () возвращает значение (среднее арифметическое трех чисел), то это значение как бы заменяет вызов функции. Если среднее арифметическое, вычисленное функцией calc_av (), равно 40, выполняемая программа «видит» такой оператор на месте вызова функции:

avg=40;

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

Такой способ вызова функции calc_av () является некорректным:

calc_av (num1, num2, num3);

Если программа содержит такую строку, С ничего не будет делать с возвращаемым значением (игнорирует его).

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

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

Слово «прототип» при использовании его применительно к функциям является синонимом слова «модель». Прототип функции является моделью настоящей функции.

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

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

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

тип_возвращаемого_значения имя_функции (тип_ параметра имя_параметра, …);

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

 

Задание:

1. Написать программу, которая в функции main() запрашивает у пользователя число, которое передается в функцию fun1(). Эта функция возвращает ASCII – символ, соответствующий этому числу. Обеспечить контроль правильности ввода.

2. Используя предыдущую программу, вывести все печатные символы таблицы ASCII.

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

 

 

Контрольные вопросы

1. Как объявляется тип возвращаемого функцией значения?

2. Какое максимальное количество значений функция может вернуть?

3. Назовите хотя бы одну причину использования файлов заголовка.

4. Как описание прототипов защищает программу от ошибок?

5. Почему нет необходимости возвращать глобальные переменные?

 


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

 



Поделиться:


Последнее изменение этой страницы: 2016-04-08; просмотров: 618; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.144.38.184 (0.01 с.)