Студопедия

Главная страница Случайная лекция


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

Порталы:

БиологияВойнаГеографияИнформатикаИскусствоИсторияКультураЛингвистикаМатематикаМедицинаОхрана трудаПолитикаПравоПсихологияРелигияТехникаФизикаФилософияЭкономика



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




Функции

Читайте также:
  1. III. Предмет, метод и функции философии.
  2. IV. По функции различают мышцы: сгибатели и разгибатели, отводящие и приводящие и вращатели.
  3. Бакампициллина - тяжелые нарушения функции печени, почек, беременность, лактация, детский возраст.
  4. Банковская система, ее структура. Функции Центрального банка. Операции коммерческих банков.
  5. Банковская система. Банки и их функции
  6. Бесконечно малые и бесконечно большие функции.
  7. Билет 13. Основные характеристики и функции чувств.
  8. Билет 13. Основные характеристики и функции чувств.
  9. Билет 28. Общение, его функции и структура.
  10. Биологическая и социальная функции отвращения

Программирование вложенных циклов

Оператор цикла do while

Все представленные выше операторы циклов, так или иначе, проверяют условие перед выполнением цикла, благодаря чему существует вероятность, что операторы внутри цикла никогда не будут выполнены. Такие циклы называют циклы с предусловием. Однако бывают ситуации, когда целесообразно выполнять проверку условия после того, как будут выполнены операторы, стоящие внутри цикла. Это достигается путем использования операторов do while, которые реализуют цикл с постусловием. Следующий пример демонстрирует реализацию такого цикла.

const int secret_code = 13;
int code_ent;
do
{
printf(“Введите секретный код: ”);
scanf(“%d”,&code_ent);
}
while(code_ent != secret_code);

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

Все рассмотренные выше операторы циклов допускают использование любых других операторов языка С внутри цикла, в том числе и операторов цикла. Это значит, что внутри одного цикла может находиться другой, что приводит к реализации вложенных циклов. Вложенные циклы необходимы для решения большого числа задач, например, вычисления двойных, тройных и т.д. сумм, просмотр элементов двумерного массива и многих других задач. В качестве примера вложенных циклов рассмотрим задачу вычисления суммы двойного ряда S += i*j, i=0...N, j=0,...M:

long S = 0L;
int M = 10, N = 5;
for(int i = 0; i <= N;i++)
{
for(int j = 0;j <= M;j++)
S += i*j;
}

Того же результата можно добиться и с помощью оператора цикла while.

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

<тип> <имя функции> ([список параметров]) { <тело функции> }

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

Листинг 2.5. Пример задания функции.
double square(double x)
{
x = x*x;
return x;
}
int main()
{
double arg = 5;
double sq1=square(arg);
double sq2=square(3);
return 0;
}

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

int square(int x)
{
x = x*x;
return x;
printf(“%d”,x);
}

при вызове данной функции оператор printf() не будет выполнен никогда, т.к. оператор return завершит работу функции square. Оператор return является обязательным, если функция возвращает какие-либо значения. Если же она имеет тип void, т.е. ничего не возвращает, то оператор return может не использоваться.

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

Функция может принимать произвольное число аргументов, но возвращает только один или не одного (тип void). Для задания нескольких аргументов функции используется следующая конструкция:

void show(int x,int y,int z) {}

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

void show(int x, y, z) {} //неверное объявление

Если число пользовательских функций велико (50 и выше), то возникает неудобство в их визуальном представлении в общем тексте программы. Действительно, имея список из 100 разных функций с их реализациями, в них становится сложно ориентироваться и вносить необходимые изменения. Для решения данной проблемы в языке С при создании своих функций можно пользоваться правилом: сначала задаются объявления функции, а затем их реализации. Этот подход демонстрируется в листинге 2.6.

Листинг 2.6. Использование прототипов функций.

#include
double square(double x);
void my_puts(char ch, int cnt);
int main()
{
double sq = square(4.5);
char ch;
ch = ‘a’;
my_puts(ch,10);
return 0;
}
double square(double x)
{
x=x*x;
return x;
}
void my_puts(char ch, int cnt)
{
for(int i = 0;i < cnt;i++)
putchar(ch);
}

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

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

Листинг 2.7. Пример использования перегруженных функций.

#include
double abs(double arg);
float abs(float arg);
int abs(int arg);
int main()
{
double a_d = -5.6;
float a_f = -3.2;
int a_i;
a_d = abs(a_d);
a_f = abs(a_f);
a_i = abs(-8);
return 0;
}
double abs(double arg)
{
if(arg < 0) arg = arg*(-1);
return arg;
}
float abs(float arg)
{
return (arg < 0) ? –arg : arg;
}
int abs(int arg)
{
return (arg < 0) ? –arg : arg;
}

В представленной программе задаются три функции с именем abs и разными входными и выходными аргументами для вычисления модуля числа. Благодаря такому объявлению при вычислении модуля разных типов переменных в функции main() используется вызов функции с одним и тем же именем abs. При этом компилятор в зависимости от типа переменной автоматически выберет нужную функцию. Такой подход к объявлению функций называется перегрузкой.

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

void some_func(int a = 1, int b = 2, int c = 3)
{
printf(“a = %d, b = %d, c = %d\n”,a,b,c);
}

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

int main(void)
{
show_func();
show_func(10);
show_func(10,20);
show_func(10,20,30);
return 0;
}

В результате, на экране появятся следующие строки:

a = 1, b = 2, c = 3
a = 10, b = 2, c = 3
a = 10, b = 20, c = 3
a = 10, b = 20, c = 30

Из полученного результата видно, что по умолчанию значения аргументов равны установленным значениям при определении функции. В случае ввода новых значений, переменные a, b и c соответственно меняют свои значения на введенные.

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

void my_func(int a, int b = 1, int c = 1);//правильное объявление
void my_func(int a, int b, int c = 1); //правильное объявление
void my_func(int a=1, int b, int c = 1); //неправильное объявление
void my_func(int a, int b = 1, int c); //неправильное объявление

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

Листинг 2.8. Пример использования рекурсивных функций.

#include
void up_and_down(int );
int main(void)
{
up_and_down(1);
return 0;
}
void up_and_down(int n)
{
printf(“Уровень вниз %d\n”,n);
if(n < 4) up_and_down(n+1);
printf(“Уровень вверх %d\n”,n);
}

Результатом работы этой программы будет вывод на экран следующих строк:

Уровень вниз 1
Уровень вниз 2
Уровень вниз 3
Уровень вниз 4
Уровень вверх 4
Уровень вверх 3
Уровень вверх 2
Уровень вверх 1

Полученный результат работы программы объясняется следующим образом. Вначале функция main() вызывает функцию up_and_down() с аргументом 1. В результате аргумент n данной функции принимает значение 1 и функция printf() печатает первую строку. Затем выполняется проверка и если n < 4, то снова вызывается функция up_and_down() с аргументом на 1 больше n+1. В результате вновь вызванная функция печатает вторую строку. Данный процесс продолжается до тех пор, пока значение аргумента не станет равным 4. В этом случае оператор if не сработает и вызовется функция printf(), которая печатает пятую строку «Уровень вверх 4». Затем функция завершает свою работу и управление передается функции, которая вызывала данную функцию. Это функция up_and_down() с аргументом n=3, которая также продолжает свою работу и переходит к оператору printf(), который печатает 6 строку «Уровень вверх 3». Этот процесс продолжается до тех пор, пока не будет достигнут исходный уровень, т.е. первый вызов функции up_and_down() и управление вновь будет передано функции main(), которая завершит работу программы.


<== предыдущая страница | следующая страница ==>
Оператор цикла for | Область видимости переменных

Дата добавления: 2014-02-28; просмотров: 434; Нарушение авторских прав




Мы поможем в написании ваших работ!
lektsiopedia.org - Лекциопедия - 2013 год. | Страница сгенерирована за: 0.004 сек.