Программирование циклов. Циклы организуются, чтобы выполнить некоторый оператор или группу операторов
Циклы организуются, чтобы выполнить некоторый оператор или группу операторов определенное число раз. В языке Си три оператора цикла: for, while и do - while.
Цикл с параметром записывается, в следующем виде:
for (<выражение_1>; <выражение_2>; <выражение_3>) <тело_цикла>
Тело цикла составляет либо один оператор, либо несколько операторов, заключенных в фигурные скобки { ... } (после блока точка с запятой не ставится). В выражениях 1, 2, 3 фигурирует специальная переменная, называемая управляющей. По ее значению устанавливается необходимость повторения цикла или выхода из него.
Выражение_1 присваивает начальное значение управляющей переменной, выражение_З изменяет его на каждом шаге, а выражение_2 проверяет, не достигло ли оно граничного значения, устанавливающего необходимость выхода из цикла.
Пример 1:
for (i = 1; i < 10; i++)
{ ...
}
for (сh = 'a'; ch != 'p';) scanf ("%c", &ch);
/* Цикл будет выполняться до тех пор, пока с клавиатуры
не будет введен символ 'p' */
Любое из трех выражений в цикле for может отсутствовать, однако точка с запятой должна оставаться. Таким образом, for ( ; ; ) {...} - это бесконечный цикл, из которого можно выйти лишь другими способами.
Используя операцию «запятая», можно в выражение 1 внести инициализацию значений сразу нескольких переменных:
for(F=1,i=1; i<=N; i++) F=F*i;
Еще один вариант вычисления N!. В нем на месте тела цикла находится пустой оператор, а вычислительная часть внесена в выражение 3.
for(F=1,i=1; i<=N; F=F*i, i++);
Этот же оператор можно записать в следующей форме:
for(F=1,i=1; i<=N; F*=i++);
В языке Си оператор for является достаточно универсальным средством для организации циклов.
Цикл с предусловием записывается в таком виде:
while (<выражение>) <тело_цикла>
Выражение в скобках может принимать ненулевое (истинное) или нулевое (ложное) значение. Если оно истинно, то выполняется тело цикла и выражение вычисляется снова. Если выражение ложно, то цикл while заканчивается. Этот цикл может ни разу не выполнится, если выражение сразу же принимает нулевое значение.
Пример 2.Нахождение наибольшего общего делителя двух натуральных чисел.
// Определение НОД(a,b)
#include <iostream.h>
void main()
{ int a,b;
cout<<”a=”; cin>>a;
cout<<”b=”; cin>>b;
while(a!=b)
if(a>b) a-=b; else b-=a;
cout<<”\nНОД(”<<a<<”,”<<b<<”)=”<<a;
}
Цикл с постусловиемзаписывается следующим образом:
do {<тело_цикла>} while (выражение);
Основным отличием между циклами while и do - while является то, что тело в цикле do - while выполняется по крайней мере один раз. Тело цикла будет выполняться до тех пор, пока выражение в скобках не примет ложное значение. Если оно ложно при входе в цикл, то его тело выполняется ровно один раз.
Пример 3.Подсчет количества цифр в записи натурального числа.
#include <iostream.h>
void main()
{ int a,n=0;
cout<<”a=”; cin>>a;
do
{ n+=1; a/=10;}
while(a>0);
cout<<”\n n=”<<n;
}
Допускается вложенность одних циклов в другие, т.е. в теле любого цикла могут появляться операторы for, while и do - while.
Упражнения
1. Используя циклы while, do – while и for написать три варианта программы получения на экране таблицы синусов для значений аргумента в диапазоне от 0 до p/2 с заданным числом шагов.
2. Составить программу перевода целого десятичного числа в систему счисления с основанием меньшим 10.
3. Решить задачу обратную к задаче 2.
Функции
Мощность языка СИ во многом определяется легкостью и гибкостью в определении и использовании функций в СИ-программах. В отличие от других языков программирования высокого уровня в языке СИ нет деления на процедуры, подпрограммы и функции, здесь вся программа строится только из функций.
Функция - это совокупность объявлений и операторов, обычно предназначенная для решения определенной задачи. Каждая функция должна иметь имя, которое используется для ее объявления, определения и вызова. В любой программе на СИ должна быть функция с именем main (главная функция), именно с этой функции, в каком бы месте программы она не находилась, начинается выполнение программы.
При вызове функции ей при помощи аргументов (формальных параметров) могут быть переданы некоторые значения (фактические параметры), используемые во время выполнения функции. Функция может возвращать некоторое (одно !) значение. Оператором возврата из функции в точку ее вызова является оператор return. Он имеет вид
return <выражение>;
Это возвращаемое значение и есть результат выполнения функции, который при выполнении программы подставляется в точку вызова функции, где бы этот вызов ни встретился. Допускается также использовать функции не имеющие аргументов и функции не возвращающие никаких значений. Действие таких функций может состоять, например, в изменении значений некоторых переменных, выводе на печать некоторых текстов и т.п..
С использованием функций в языке СИ связаны три понятия - определение функции (описание действий, выполняемых функцией), объявление функции (задание формы обращения к функции) и вызов функции.
Определение функции задает тип возвращаемого значения, имя функции, типы и число формальных параметров, а также объявления переменных и операторы, называемые телом функции, и определяющие действие функции. В определении функции также может быть задан класс памяти.
Пример 1:
int rus (unsigned char r)
{ if (r>='А' && c<=' ') return 1; else return 0; }
В данном примере определена функция с именем rus, имеющая один параметр с именем r и типом unsigned char. Функция возвращает целое значение, равное 1, если параметр функции является буквой русского алфавита, или 0 в противном случае.
В языке СИ нет требования, чтобы определение функции обязательно предшествовало ее вызову. Определения используемых функций могут следовать за определением функции main, перед ним, или находится в другом файле.
Однако для того, чтобы компилятор мог осуществить проверку соответствия типов передаваемых фактических параметров типам формальных параметров до вызова функции нужно поместить объявление (прототип) функции.
Объявление функции имеет такой же вид, что и определение функции, с той лишь разницей, что тело функции отсутствует, и имена формальных параметров тоже могут быть опущены. Для функции, определенной в примере 1, прототип может иметь вид
int rus (unsigned char r); или rus (unsigned char);
В программах на языке СИ широко используются, так называемые, библиотечные функции, т.е. функции предварительно разработанные и записанные в библиотеки. Прототипы библиотечных функций находятся в специальных заголовочных файлах, поставляемых вместе с библиотеками в составе систем программирования, и включаются в программу с помощью директивы #include.
Если объявление функции не задано, то по умолчанию строится прототип функции на основе анализа первой ссылки на функцию, будь то вызов функции или определение. Однако такой прототип не всегда согласуется с последующим определением или вызовом функции. Рекомендуется всегда задавать прототип функции. Это позволит компилятору либо выдавать диагностические сообщения, при неправильном использовании функции, либо корректным образом регулировать несоответствие аргументов устанавливаемое при выполнении программы.
При вызове функции указываются ее имя и фактические параметры
<имя_функции>(<список_фактических_праметров>)
Между формальными и фактическими параметрами при вызове функции должны соблюдаться правила соответствия по последовательности и по типам. Фактический параметр – это выражение того же типа, что и у соответствующего ему формального параметра. Стандарт языка Си допускает автоматическое преобразование значений фактических параметров к типу формальных параметров. В Си++ такое преобразование не предусмотрено. Поэтому в дальнейшем мы будем строго следовать принципу соответствия типов.
В Си/Си++: передача параметров при вызове функции происходит только по значению. Поэтому выполнение функции не может изменить значения переменных, указанных в качестве фактических параметров.
Пример 2.Рассмотрим два варианта функции, меняющей местами значения двух переменных
Вариант 1. void swap (int a, int b) { int r=a; a=b; b=r; } | Вариант 2 void swap (int *a, int *b) { int r=*a; *a=*b; *b=r; } |
Обращение: int x=10, y=20; swap (x,y); | Обращение: swap (&x,&y); |
В первом варианте после обращения к функции значения переменных x и y не изменятся так как в функцию передаются значения этих переменных. Во втором варианте в функцию передаются адреса областей памяти, отведенных под эти переменные. Изменения происходят с содержимым этих областей. В этом примере формальные параметры являются указателями. Указатель — это переменная, значением которой является адрес области памяти.