Вы находитесь на странице: 1из 18

Оглавление

5. Операторы..............................................................................................................................................1
5.1. Виды операторов............................................................................................................................1
5.2. Оператор-выражение......................................................................................................................2
5.3. Условный оператор if.....................................................................................................................4
5.4. Безусловный оператор goto............................................................................................................7
5.5. Оператор выбора switch.................................................................................................................7
5.6. Оператор разрыва break.................................................................................................................9
5.7. Оператор цикла while...................................................................................................................11
5.8. Оператор цикла do while..............................................................................................................13
5.9. Оператор цикла for.......................................................................................................................15
5. 10. Оператор продолжения continue...............................................................................................17
5.11. Общая структура циклов (подведение итогов)..................................................................18

5. Операторы
В разделе 3.2.2. было приведено понятие оператора, т. е. некоторой
конструкции языка, заканчивающейся знаком точка с запятой (;) и являющейся
указанием на выполнение компьютером некоторого действия.

5.1. Виды операторов


Оператор – это единица выполнения программы. Операторы делятся на
простые, составные и блоки.

Простым называется оператор, не содержащий в своем составе никаких


других операторов. К простым операторам относятся рассматриваемые далее
оператор-выражение, оператор продолжения continue, оператор завершения
break, оператор возврата return, оператор перехода goto.

Составным называется оператор, содержащий в своем составе другие


операторы. К составным операторам относятся условный оператор if-else,
операторы цикла for, while, do while и оператор выбора switch.

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


скобки { и }. Операторы блока выполняются последовательно в порядке их записи
внутри блока. В начале блока могут быть описаны внутренние переменные. В этом
случае говорят, что эти переменные локализованы внутри блока, т.е. используются
со своими значениями, присвоенными им внутри этого блока, а не в каком-либо
другом месте программы. В Си-программах составной оператор и блок могут
употребляться везде, где допускается применение простого оператора.

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

Любой оператор может быть отмечен идентификатором, называемым меткой.


Метка отделяется от оператора двоеточием и, таким образом, в общем случае
оператор имеет вид:

<метка>:<тело оператора>;

Метка используется только тогда, когда управление передается на оператор с


помощью оператора безусловного перехода goto. В вышеприведенной
синтаксической конструкции может отсутствовать или <метка>, или <тело
оператора>, или то и другое. В случае отсутствия <тело оператора> приходим к
понятию пустого оператора, т.е. оператора, который не выполняет никакого
действия. Если <оператор> отсутствует, а метка присутствует, то имеем случай
пустого помеченного оператора. Например: empty:;
Если в качестве <тело оператора> используется блок, то признак конца
оператора (;) не ставится. В этом случае роль признака конца блока играет
закрывающая правая фигурная скобка, например label:{k=a=b; k+=8;}

5.2. Оператор-выражение
Любое выражение будет оператором, если за ним следует знак точка с
запятой. Таким образом, оператор-выражение имеет следующий общий вид записи:

<выражение>;

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

int x,y.z;
x=-3+4*5-6;
y=3+4%5-6;
z=-3*4%-6/5;

2
В результате выполнения этих операторов х примет значение 11, у значение 1,
а z значение 0. В соответствии с приоритетами операций распишем
последовательность действий, используя круглые скобки.

Для х=-3+4*5-6 Для у=3+4%5-6 Для z=-3*4%-6/5


–––––––––––––––––––––––––––––––––––––––––––––––––––
x=(-3)+4*5-6 y=3+(4%5)-6 z=(-3)*4%(-6)/5
x=(-3)+(4*5)-6 y=(3+(4%5))-6 z=((-3)*4)%(-6)/5
x=((-3)+(4*5))-6 y=((3+(4%5)-6) z=(((-3)*4)%(-6))/5
x=(((-3)+(4*5))-6) (y=((3+(4%5)-6)) z=((((-3)*4)%(-6))/5)
(x=(((-3)+(4*5)-6)) (z=((((-3)*4)%(-6)/5))

Пример 5.2.2.
int x=2,y,z;
x*=3+2, x*=y=z=4;
В этом примере оператор-выражение содержит выражение с запятой,
состоящее из двух подвыражений. В начале вычисляется первое подвыражение,
затем второе. В результате выполнения оператора-выражения z и у примут
значение 4, а х значение 40.Обратите внимание, что при описании x
инициализируется значением 2. Последовательность действий:
Для 1-го выражения Для 2-го выражения

х=х*(3+2) (z=4)
х=(х*(3+2)) (y=(z=4))
(х=(х*(3+2))) x=(x*(3+2))*(y=(z=4))
x=((x*(3+2))*(y=(z=4)))
(x=((x)*(3+2))*(y=(z=4))))
Пример 5.2.3.
int x=2, y=1, z=0;
x=x&&y||z; //x=1
y=x++-1; //x=2, y=0
z=++x-1; //x=3, z=2
В результате выполнения этого фрагмента х примет значение 3, у примет
значение 0, а z примет значение 2. В результате выполнения первого оператора-
выражения х примет значение 1, так как правая часть операции присваивания
(логическое выражение) будет ИСТИНА, затем после выполнения второго
оператора х примет значение 2, ввиду того что в нем содержится постфиксная
форма операции увеличения х++, и, наконец, при выполнении третьего оператора х
увеличится еще на единицу, ввиду наличия префиксной формы ++х. Значения для
у и для z очевидны и определяются спецификой применения постфиксной и
префиксной операции для х.

5.3. Условный оператор if


Условный оператор предназначен для организации разветвлений в
программах. Условный оператор if является составным и может быть использован
в одной из двух форм:
3
if (<выражение>) <оператор> или
if (<выражение>) <оператор1> else <оператор2>

Обратим внимание на то, что в общих формах записи оператора if отсутствует


признак конца оператора(;). Дело в том, что ранее определенная синтаксическая
конструкция <оператор> уже включает в себя признак конца. Если <оператор>
простой, то он будет завершен точкой с запятой. Если <оператор> является блоком,
то блок будет определен парными фигурными скобками, и правая фигурная скобка
определяет конец блока.
Оператор if работает следующим образом:

1. Форма записи if(<выражение>) <оператор>. Вначале вычисляется значение


выражения <выражение>. Если оно ИСТИНА (т.е. его значение отлично от нуля),
то выполняется

==0(ложь)
<выражение>?

!=0(истина)

<оператор>

на оператор
после IF-ELSE
Рис.5.1. Алгоритмическая схема выполнения if(<выражение>) <оператор>

<оператор>. Если значение ЛОЖЬ (выражение равно нулю), то <оператор>


пропускается. Форма записи if(<выражение>) <оператор> соответствует
алгоритмической схеме, представленной на рис.5.1.

Допустим, например, что если d равно c, то нам необходимо d увеличить на


единицу, а c увеличить на 3. При любых других условиях d и c должны остаться
без изменения. В этом случае можно записать такой условный оператор:

if (d==c) ++d,c+=3;

В этом примере в качестве <оператор> используется оператор-выражение с


запятой. Этот же пример перепишем по-другому:

if (d==c) ++d; c+=3;

4
Разница в том , что теперь здесь два оператора: оператор if и оператор-
выражение c+=3. Теперь в случае истинности (d==c) все будет по-прежнему: d
увеличится на единицу и c увеличится на три. Но в случае ложности (d==c) d не
изменится, а с увеличится на 3. Вновь видоизменив этот пример,

if (d==c) {++d;c+=3;}

возвращаемся к первоначальному эффекту; в случае ложности (d==c) d и c не


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

2. Форма записи if (<выражение>) <оператор1> else <оператор2>. Как и в


предыдущем случае, вначале вычисляется значение <выражение>. Если оно
отлично от нуля, т.е. истинно, то выполняется <оператор1>, иначе выполняется
<оператор2>. Алгоритмическая схема выполнения для этой формы записи
условного оператора представлена на рис.5.2.

!=0(истина) ==0(ложь)
<выражение>?

<оператор1> <оператор2>

на оператор после IF-ELSE

Рис.5.2. Алгоритмическая схема выполнения if (<выражение>)


<оператор1> else <оператор2>

Например, если необходимо вычислить z, равное max из a и b, то можно


записать:

if (a>b) z=a; else z=b;

Наличие точки с запятой после z=a обязательно, т.к. это есть оператор,
входящий в состав оператора if.

Если первая сокращенная форма оператора if позволяет в программе


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

Рассмотрим цепочку операторов:

if (<выр1>) <оператор1> else if (<выр2>) <оператор2>


else if (<выр3>) <оператор3> else <оператор4>

5
Такая цепочка вполне допустима, т. к. на месте оператора может быть любой
оператор, в том числе и оператор if в той или иной форме. Однако в такой записи
достаточно сложно разобраться, поэтому перепишем цепочку так, чтобы else
оказалось под соответствующим if:

if (<выр1>) <оператор1>
else if (<выр2>) <оператор2>
else if (<выр3>) <оператор3>
else <оператор4>
Сопоставим последний else с ближайшим if, и это будет новый оператор,
который включает в себя уже образованный. Схематично это отобразится
следующим образом:
if (<выр1>) <оператор1>

else if (<выр2_) <оператор2>

else if (<выр3_)
<оператор3> else
<оператор4>
_
ОПЕРАТОР

ОПЕРАТОР

Таким образом, мы пришли к канонической форме if-else и теперь понятно,


как она будет работать. Выражения вычисляются по порядку; если какое-либо
выражение истинно, то выполняется сопоставленный с ним оператор и на этом
завершается выполнение всей цепочки. Последний оператор цепочки <оператор4>
может быть диагностическим вариантом – реакцией программы на тот случай, если
ни одно из условий не выполнено. Рассмотрим конкретный пример организации
разветвлений в программе.

Допустим, необходимо рассчитать оплату за пользование электроэнергией.


Причем плата за электроэнергию производится на следующих условиях: за первые
израсходованные 5000 квт/ч оплачивается 0.4 лея за 1 квт/ч, за вторые 5000
взимается 0.6 лея за 1 квт/ч, за третьи 5000 взимается 0.8 лея за квт/ч и, наконец, за
израсходованную электроэнергию свыше 15000 квт/ч оплачивается 1.2 лея за
каждый превышающий квт/ч. Фрагмент программы, реализующей эти вычисления,
может быть записан следующим образом:

if(kwh<=5000) /*kwh - кол-во израсходованной электроэнергии */


st=kwh*0.4; /*st - плата за электроэнергию */
else if(kwh<=10000)
st=(5000*0.4)+(10000-kwh)*0.6;

6
else if(kwh<=15000)
st=(5000*0.4)+(5000*0.6)+(15000-kwh)*0.8;
else st=(5000*0.4)+(5000*0.6)+(5000*0.8)+(kwh-15000)*1.2;
Из примера видно, что фрагмент состоит из оператора if-else, для которого
часть else представляет собой другой оператор if-else.
Рассмотрим еще два простых примера, сопоставляя фрагменты программ а) и б).

Фрагмент а): Фрагмент б):


if(n>0) if(n>0){
if(a>b) if(a>b)
z=a; z=a;
else }
z=b; else
z=b;
B чем разница между ними? Разница в том, что фрагмент а) представляет
собой сокращенную форму if, которой в качестве <оператор> стоит if-else;
фрагмент б) представляет собой полную форму if-else, в которой в качестве
<оператор1> использована сокращенная форма if. Фрагмент б) внешне отличается
от фрагмента а) только наличием фигурных скобок, определяющих блок, которые,
как мы видим, играют существенную роль при интерпретации этих операторов.
Существует правило интерпретации вложенных конструкций if-else, которое
гласит, что else соответствует ближайшему if, кроме тех случаев, когда
имеются фигурные скобки.

if ((s[i] == 'с' or s[i] == 'С') and (s[i + 1] == ' ' or s[i + 1] == '\0') and not(0)) {

count++;

5.4. Безусловный оператор goto


Безусловный оператор goto позволяет осуществить передачу управления на
любой оператор программы, имеющий метку. Оператор goto записывается в виде:
goto <метка>;
После оператора goto безусловно выполняется тот оператор программы, метка
которого совпадает с меткой в goto. Использование goto в Си никак не отличается
от его использования в других языках программирования. Однако Си имеет четко
выраженные свойства языков структурного программирования и поэтому
рекомендуется, по-возможности, избегать использование оператора goto, дабы не
нарушать каноны структурного программирования. Вместе с тем, имея в своем
распоряжении только операторы if и goto, программист уже имеет возможность
организовывать в программе достаточно сложные виды управления.
К операторам перехода можно отнести также операторы break и continue.

7
5.5. Оператор выбора switch
Оператор выбора (переключатель) предназначен для выбора одного варианта
из множества возможных вариантов разветвления программы. В принципе любое
ветвление программы можно организовать цепочкой операторов if-else if-...-else, но
в ряде случаев оказывается более удобным применять оператор выбора switch.
Оператор switch является составным и имеет следующую общую форму записи:

switch (<выражение>)
{
case <конст. выражение 1> : <оператор(ы)1>
case <конст. выражение 2> : <оператор(ы)2>
...
case <конст. выражение N> : <оператор(ы)N>
default : <оператор(ы)>
}
После ключевого слова switch в скобках записывается выражение, результат
выполнения которого обязательно должен иметь тип int. Далее в фигурных
скобках записываются операторы варианта, помеченные префиксами вида: case
<конст.выражение N>:, в которых константное выражение также должно быть
целым, а все префиксы должны быть различными. Один из вариантов может быть
отмечен префиксом default. Наличие варианта default необязательно, но чаще всего
он присутствует в конструкции switch.
Рис.5.3.
z=<выражение>
Алгоритмическая схема
выполнения Да

оператора switch. Z==<конст.выр1>_ Z==_конст.выр1_ ? оператор(ы)1


* Z==_конст.выр1_ ?

Оператор выбора Нет Да

работает следующим Z==<конст.выр2>_ Z==_конст.выр1_ ? оператор(ы)2


* Z==_конст.выр1_ ?
образом. Вначале
вычисляется выражение Нет Да
в
Z==<конст.вырN>_ Z==_конст.выр1_ ? * Z==_конст.выр1_ ?
круглых скобках оператор(ы)N

<выражение>. Значение
Нет Да
<выражение> Есть Default ?_ Z==_конст.выр1_ ? * Z==_конст.выр1_ ?
оператор(ы)
сравнивается с
константными Нет На оператор после switch
выражениями case-префиксов операторов варианта и выполняется i-тый вариант,
для которого эти значения совпадают. После завершения выполнения операторов
выбранного варианта выполняются операторы следующего за ним варианта и т.д.,
до исчерпания всех операторов варианта. Если значение выражения в switch не
совпадает ни с одним вариантом, то либо выполняется оператор варианта по
умолчанию default (если он присутствует), либо не выполняется никакой вариант
(если нет варианта по умолчанию default). На рис.5.3. представлена
алгоритмическая схема выполнения оператора switch.
8
Рассмотрим пример использования оператора switch. Допустим, необходимо
написать фрагмент программы, которая печатает некоторое четверостишие,
начиная с k-той строки:

switch(k)
{
case 1 : printf("У Лукоморья дуб зеленый\n");
case 2 : printf("Златая цепь на дубе том\n");
case 3 : printf("И днем и ночью кот ученый\n");
case 4 : printf("Все ходит по цепи кругом\n");
default: printf("А.С. Пушкин\n");
}

Например, при k, равном 3, программа отработала бы следующим образом:


И днем и ночью кот ученый
Все ходит по цепи кругом
А.С. Пушкин
При k, равном 5, программа отработала бы так:
А.С. Пушкин
5.6. Оператор разрыва break
В программистской практике часто возникает необходимость выполнения
только одного выбранного варианта без выполнения следующих за ним, т.е.
необходимо нарушить установленную логику работы оператора switch.
Естественно, что для этой цели среди операторов варианта нужно поместить
оператор, который бы завершал выполнение switch. Таким оператором является
оператор разрыва break, выполнение которого вызывает завершение работы
оператора switch. В этом случае оператор switch будет иметь следующую общую
форму записи:

switch(<выражение>)
{
case <конст. выражение 1>:<оператор(ы)1>
[break;]
case <конст. выражение >:<оператор(ы)2>
[break; ]
................
case <конст. выражение N>:<оператор(ы)N>
[break;]
default:<оператор(ы)>
[break;]
}
Операторы break записываются в вариантах по необходимости, и там, где они
есть, выполнение break приводит к передаче управления за пределы
переключателя, т.е. начинает выполняться оператор программы, записанный после
закрывающей фигурной скобки оператора switch. На первый взгляд кажется не
9
нужным записывать оператор break в варианте default. Но дело в том, что в
операторе switch варианты могут быть записаны в любой последовательности и
default может оказаться первым среди операторов вариантов или между ними и
тогда ему необходим break, чтобы не выполнялись последующие варианты. Кроме
того, это полезно в случае отладки программы, когда может понадобиться
добавлять новое case-выражение после варианта default.
Приведем пример использования оператора break в переключателе. Для этого
изменим постановку предыдущей задачи следующим образом: написать фрагмент
программы, печатающей к-ую строку четверостишия (в отличие от предыдущего
случая, когда необходимо было напечатать четверостишие, начиная с к-ой строки).

switch(k)
{
case 1 : printf("У Лукоморья дуб зеленый\n");
break;
case 2 : printf("Златая цепь на дубе том\n");
break;
case 3 : printf("И днем и ночью кот ученый\n");
break;
case 4 : printf("Все ходит по цепи кругом\n");
break;
default: printf("В стихотворении нет строки с таким номером\n");
}
В заключение раздела отметим, что операторы в case-вариантах и default-
варианте могут отсутствовать. Это используется тогда, когда мы желаем получить
одинаковый результат при переходе к разным префиксам. Например, фрагмент
программы:

case 'K': case 'k':


printf("компьютер\n");
break;

показывает, что будет напечатано слово компьютер в том случае, если на вход
переключателя поступит буква k независимо от того, строчная или прописная. Если
поступит буква К, то это вызовет выполнение соответствующего варианта, но
поскольку там операторы отсутствуют, то будут выполняться операторы,
расположенные ниже, пока не встретится оператор break. Этот же прием можно
реализовать по-другому, указав два или более case-префикса перед одним
вариантом, например, так: case 'K': case 'k':printf("компьютер\n"); break;

Эти примеры говорят о том, что <выражение> в switch и <конст.выр> в case


могут быть и типа char. Это правомерно, ибо переменные и константы типа char
интерпретируются как целые числа типа int.

10
5.7. Оператор цикла while
Операторы цикла позволяют организовать многократное выполнение
некоторого участка программы. Оператор цикла while является составным и имеет
следующую форму записи:

while(<выражение>)
<оператор>

Оператор цикла while работает следующим образом: если <выражение>


истинно (или не равно нулю, что с точки зрения Си одно и то же), то <оператор>
выполняется один раз, а затем <выражение> вновь проверяется. Эта
последовательность действий, состоящая из проверки <выражение> и выполнения
<оператор> , периодически повторяется до тех пор, пока <выражение> не станет
ложным (или с точки зрения Си равным нулю). <Оператор> , входящий в while,
часто называют телом цикла, ибо в большинстве случаев это блок, в состав
которого входит несколько операторов. Алгоритмическая схема выполнения
оператора цикла while представлена на рис 5.4.

Выражение ?

операто
р

на оператор после while


while

Рис.5.4 Алгоритмическая схема выполнения оператора цикла while.

Из алгоритмической схемы выполнения видно, что оператор while – это цикл


с предусловием; решение, выполнять ли в очередной раз тело цикла, принимается
перед началом его прохождения. Поэтому вполне возможно, что тело цикла не
будет выполнено ни разу. Кроме того, чтобы тело цикла выполнялось не
бесконечно, а определенное количество раз, необходимо при каждом новом
выполнении цикла изменять каким-то образом переменную, входящую в состав
<выражение> так, чтобы в конце концов <выражение> стало ложным. Такая
переменная, которая при каждом новом выполнении цикла изменяется,
обеспечивая завершение цикла, обычно называется переменной цикла. Си
позволяет обеспечить изменение переменной цикла либо в <выражение>, либо в
50
y=∑ n/(n+5)
<оператор>. Рассмотрим эти оба случая на примере вычисления n=1 т.е.
y =СУММА по n от 1 до 50 ДЛЯ n/(n+5).

Вариант 1. Изменение переменной цикла в <выражение> :


11
int n=0;float y=0;
while(++n<=50) y+=n/(n+5.0);
Вариант 2. Изменение переменной цикла в <оператор>:
int n=1;float y=0;
while(n<=50)
{
y+=n/(n+5.0);
++n;
}
Гибкость языка Си предоставляет возможность записать еще один вариант
этой программы:
int n=1;float y=0;
while(y+=n/(n+5.0),++n,n<=50);
В этом примере тело цикла вырождено, на месте <оператор> записан пустой
оператор, а вычисления, обеспечивающие суммирование, перенесены в
<выражение>, в качестве которого записано выражение с запятой. Это правомочно,
ибо значением выражения с запятой является значение самого правого выражения
– оно в данном случае является выражением отношения и обеспечивает
завершение выполнения оператора цикла while.
Организацию вложенных циклов рассмотрим на примере вычисления
100 50
y=∑ ∑ 1 /(i+ √ j)
i=1 j=1
int i=0;
double y=0;
{ j =0;
while(++i<=100)
while(++j<=50)
y+=1/(i+sqrt((double)j);
}
В этом фрагменте программы использована встроенная функция вычисления
квадратного корня sqrt, которая в качестве аргумента требует тип double, что
повлекло за собой применение операции приведения типа. Внутренний цикл с
заголовком while(++j<=50) работает под управлением внешнего цикла с заголовком
while(++i<=100). Выход из цикла, обусловленный ложным значением
<выражение>, является естественным и происходит при исчерпании числа
повторений тела цикла. Иногда необходимо выйти из цикла досрочно, т.е. при
истинном значении <выражение> на очередном шаге выполнения тела цикла. Для
этого в теле цикла используется оператор break, выполнение которого приводит к
передаче управления на оператор программы, записанный после тела цикла. Чаще
всего оператор break используется в тех случаях, когда заданы два различных
условия прекращения работы цикла.

12
100
sum= ∑ N /( N +1 . 0)
Например, необходимо вычислить N =1 , однако, если значение
sum превышает 25, то суммирование прекратить, иначе просуммировать все члены
N/(N+1.0):

float sum;
int N;
sum=0;N=1;
while(N<=100)
{
sum+=N/(N+1.0);
if(sum>25.0) break;
N++;
}
Оператор break используется для досрочного завершения циклов всех видов,
которые будут рассмотрены далее: циклов do while и циклов for. В операторе switch
и в операторах цикла оператор break действует идентично, передавая управление
на оператор, записанный после switch или после тела цикла.

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


Оператор цикла do while имеет следующую форму записи:

do <оператор> while(<выражение>);

Оператор do while работает следующим образом: сначала выполняется


<оператор>, а затем вычисляется значение <выражение> . Если значение
<выражение> истинно, то <оператор> выполняется повторно, если <выражение>
ложно, то выполнение цикла завершается. Алгоритмическая схема выполнения do
while представлена на рис. 5.5.

оператор
!=0 (истина)

выражение

==0 (ложь)

на оператор после do-while

Рис. 5.5. Алгоритмическая схема выполнения do while.

Оператор do while определяет цикл с постусловием, поскольку проверка на


необходимость повторного выполнения <оператор> осуществляется после
отработки тела цикла и, таким образом, тело цикла всегда выполняется, по
меньшей мере – единожды. Аналогично, как и для цикла while, программист
должен позаботиться о завершении цикла путем изменения переменной цикла либо
в теле цикла, либо в <выражение> для while.

13
Примеры, приведенные в предыдущем разделе 5.7, перепишем с
использованием оператора do while.
1. Изменение переменной цикла в <выражение>:
int n=1; float y=0;
do
y +=n/(n+5.0);
while (++n<=50);
2. Изменение переменной цикла в <оператор>:
int n=1; float y=0;
do
{
y +=n/(n+5.0);
++n;
} while (n<=50);
3. Внесение <оператор> в состав <выражение>:
int n=1; float y=0;
do
; /* тело цикла - пустой оператор */
while (y +=n/(n+5.0), ++n, n<=50);
4. Вложенные циклы:
int i=1, j;
double y=0;
do
{
j = 1;
do
{
y +=1/(i+sqrt((double)j);
}while (++j<=50);
}while (++i<=100);
5. Прерывание выполнения цикла оператором break; :
float sum;
int N;
sum=0,N=1;
do
{ sum +=N/(N+1.0);
if (sum>25.0) break;
N++;
} while (N<=100);
Таким образом, оператор do while действует точно так же, как и оператор while, за
исключением того, что тело цикла всегда выполняется хотя бы один раз.

5.9. Оператор цикла for


Оператор цикла for имеет следующую общую форму записи:

for(<инициализирующий опер-р/выр1>;<выр2>;<выр3>)<оператор>
14
В операторе for <выр1> называется инициализирующим выражением и
обычно оно устанавливает начальное значение переменной цикла. Выражение
<выр2> называется проверяющим выражением и определяет условие завершения
цикла. Выражение <выр3> называется корректирующим и обычно определяет шаг
изменения переменной цикла. Выражения в заголовке цикла for отделяются друг от
друга точкой с запятой. Например, фрагмент программы:
float y=0;
for(int n=1; n<=50; ++n) y +=n/(n+5.0);
50
y=∑ n/(n+1)
вычисляет n=1 . Здесь n=1 – инициализирующее выражение, n<=50 –
проверяющее выражение, ++n – корректирующее (отвечающее за итерацию)
выражение. Оператор цикла for работает следующим образом. Вначале
вычисляется инициализирующее выражение <выр1>. Затем, если проверяющее
выражение <выр2> истинно, то выполняется <оператор> . После выполнения
<оператор> выполняется корректирующее выражение и вновь вычисляется
проверяющее выражение, истинность которого влечет за собой повторное
выполнение <оператор>. Если проверяющее выражение имеет значение ложь, то
выполнение оператора for завершается и управление передается на оператор
программы, записанный после оператора for. На месте инициализирующего
выражения может быть записан инициализирующий оператор, например:
char *ptr = getStr();
int i = 0, j =0;
int lo = 0, hi = max, mid = max/2; //м.быть и другой оператор for
Алгоритмическая схема выполнения оператора for представлена на рис 5.6.

Рис 5.6. Алгоритмическая схема выполнения оператора for.

В соответствии с алгоритмической схемой, оператор for, вычисляющий


сумму, будет выполняться, как это представлено на рисунке 5.7.

15
n=1

нет
N <= 50?

да

y+=n/(n+5.0)
.0)

++n

на оператор после for


while

Рис 5.7. Схема выполнения оператора for.

Из алгоритмической схемы видно, что оператор for – это цикл с


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

for(; n<50; n++);


for(; ; n++);
for(; ;);
Если какое-либо из выражений заголовка цикла опущено, то в
алгоритмической схеме выполнения будет отсутствовать соответствующий
обрабатывающий блок. Пустое проверяющее выражение всегда считается
истинным. На примере вычисления k=7! рассмотрим циклы с различными видами
заголовка for:
1.Полный заголовок for:

k=1;
for(n=7; n>0; --n) k *= n;
2.Отсутствует инициализирующее выражение:
k=1,n=7;
for(; n>0; --n) k*=n;
3.Отсутствуют инициализирующие и проверяющие выражения:
k=1,n=7;
for(; ; --n)
if(n <= 0) break;
16
else k *= n;
4.Отсутствуют инициализирующие, проверяющие и корректирующие
выражения:
k=1,n=7;
for(; ;)
if(n <= 0) break;
else {k *= n; --n;}
Во всех этих примерах k=7! вычисляется по схеме k=7*6*5*4*3*2*1. Из
примеров видно, что если отсутствует инициализирующее выражение, то его
необходимо записать до входа в оператор for, а если отсутствует проверяющее и
корректирующее выражения, то их необходимо реализовать в теле цикла for.
Конечно, это справедливо, если мы желаем хотя бы каким-то образом завершить
цикл.
Большая свобода выбора количества и вида выражений, управляющих
работой цикла for, позволяет с помощью этого оператора делать весьма "заумные"
циклы. Однако оператор for становится более наглядным, если все выражения,
управляющие работой цикла, собраны в его заголовке.

5. 10. Оператор продолжения continue


Оператор continue имеет следующую общую форму:

continue;

Оператор continue может использоваться во всех трех типах циклов, но не в


операторе switch. Он служит для пропуска оставшейся части выполняемой
итерации цикла, непосредственно его содержащего. Т.е continue прерывает
текущую итерацию. Если условиями цикла допускается новая итерация, то она
выполняется, в противном случае она завершается. Рассмотрим фрагмент
программы обработки отрицательных элементов массива; положительные
элементы пропускаются:
for(I =0; i<N; i++)
{
if(a[i] > 0) /* пропуск положительных элементов */
continue;
... /* обработка отрицательных элементов */
}
Таким образом, оператор continue помогает иногда сократить некоторые
программы, особенно если они включают в себя вложенные операторы if else.

5.11. Общая структура циклов (подведение итогов)


Каждый цикл имеет 4 части
 [инициализация]
 [тело]
17
 [итерацию]
код, который выполняется каждый раз после(до) тела цикла, изменяет
управляющую переменную, либо еще что-то, что приведет к изменению
условия цикла.
 [завершение] (условие цикла)
Если правильно продумать все эти составные части, то можно гарантировать
составление правильно работающих фрагментов кода.
Примеры.
while(1){//вечный цикл
}

x = 0; [x = 0;]
while( x == 0){ while( x = get_value()){//( (x = get_value()) == 0){
… …
x = get_value(); }
}

18

Вам также может понравиться