ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 11.12.2025

Просмотров: 3258

Скачиваний: 1

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

Опытные программисты говорят, что область видимости переменной nAver-l age ограничена циклом w h i l e .

Несмотря на свою простоту, цикл w h i l e все же является вторым по распространен ности циклом в программах на С#. Пальму первенства прочно удерживает цикл foil имеющий следующую структуру:

for{Выражение 1;

Условие;

Выражение2)

{

 

 

I I . . . тело

цикла . . .

1

 

 

По достижении

цикла f o r

программа сначала выполняет Выражение!. Затем он

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

скобки управление

переходит Выражению2, после чего вновь вычисляется Условия

и цикл повторяется.

 

Определение цикла f o r можно переписать как следующий цикл w h i l e :

Выражение 1

;

 

whi1е( У с л о в и е )

 

{

 

 

I I . . .

тело

цикла . . .

Выражение2;

}

П р и м е р

Возможно, вы лучше разберетесь, как работает цикл for, взглянув на конкретны! пример:

// Некоторое выражение на С#

а= 1;

//Цикл

f o r ( i n t nYear = 1; nYear < n D u r a t i o n ; nYear = nYear + 1)

{

/ / . . . тело цикла . . .

}

//

Здесь программа продолжается

а

= 2 ;

 

Предположим, программа выполнила присваивание а = 1 ; . После этого она объявляя

переменную nYear и инициализирует ее значением 1. Далее программа сравнивает зна­ чение nYear со значением nDuration . Если nYear меньше nDuration, выполняется тело цикла в фигурных скобках. По достижении закрывающей скобки программа во}| вращается к началу цикла и выполняет инструкцию nYear=nYear+l, перед тем кап вновь перейти к проверке условия nYear<nDuration .

104

Часть II. Основы программирования в &


Переменная n Y e a r не определена вне области видимости цикла f o r , которая включает как тело цикла, так и его заголовок.

Зачем нужны разные ц и к л ы

Зачем в С# нужен цикл for, если в нем уже есть такой цикл, как w h i l e ? Наиболее простой и напрашивающийся ответ — он не нужен, так как цикл f o r не может сделать ничего такого, что нельзя было бы повторить с помощью цикла w h i l e .

Однако разделы цикла f o r повышают удобочитаемость исходных текстов, четко ука­ зывая три части, имеющиеся в каждом цикле: настройку, условие выхода и увеличение счетчика. Такой цикл не только проще для чтения и понимания, но и для проверки его корректности — вспомните, что основная ошибка при работе с циклом w h i l e — забы­ тое увеличение счетчика или некорректный критерий завершения цикла. Недаром цикл for встречается в программах на порядок чаще других разновидностей циклов.

Так уж сложилось, что в основном в первой части цикла f o r выполняется ини­ циализация переменной-счетчика, а в последней — ее увеличение. Но это не более чем традиция — С# не требует этого от программиста. В этих двух час­ тях цикла f o r можно выполнять какие угодно действия, хотя, конечно же, для того чтобы отойти от традиционной схемы, нужны серьезные основания.

В цикле f o r особенно часто используется оператор инкремента (который вместе с другими операторами был описан в главе 4, "Операторы"). Обычно приведенный ранее цикл for записывается как

for(int nYear = 1; nYear < n D u r a t i o n ; nYear++)

{

// . . . тело цикла .. .

}

Почти всегда в цикле f o r применяется постфиксная форма оператора инкре­ мента, хотя в данном случае функционально она идентична префиксной.4

У цикла f o r имеется одно правило, которое я не в состоянии пояснить — если усло­ вие в цикле отсутствует, считается, что оно равно t r u e . 5 Таким образом, f or (; ;) — такой же бесконечный цикл, как и w h i l e ( t r u e ) .

В реальных программах f o r (; ;) в качестве бесконечного цикла используется значительно чаще, чем w h i l e ( t r u e ) ; но чем это вызвано, объяснить сложно.

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

5Это правило легко пояснить тем, что если бы отсутствие условия воспринималось как false, то в таком цикле выполнялась бы исключительно первая часть заголовка, но не последняя

ине тело цикла. — Примеч. ред.

Глава 5. Управление потоком выполнения

105



Вложенные циклы

Один цикл может находиться в теле другого цикла: f o r ( . . . н е к о т о р о е у с л о в и е . . . )

{

f o r ( . . .

н е к о т о р о е д р у г о е у с л о в и е . . . )

{

 

/ /

. . . к а к и е - т о д е й с т в и я . . .

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

Цикл, содержащийся внутри другого цикла, называется вложенным (nested) Вложенные циклы не могут "пересекаться", т.е. приведенный далее исходны текст некорректен:

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

Оператор b r e a k внутри вложенного цикла прекращает выполнение только этап вложенного цикла. В приведенном далее фрагменте исходного текста оператор brea) завершает работу цикла Б и возвращает управление циклу А:

// Цикл

f o r

А

 

 

 

f o r ( . . .

н е к о т о р о е у с л о в и е

. . . )

 

{

 

 

 

 

 

//

Цикл

f o r Б

 

 

 

f o r ( . . .

н е к о т о р о е д р у г о е у с л о в и е

. . . )

{

 

 

 

 

 

 

/ / . . . н е к о т о р ы е д е й с т в и я . . .

 

i f

(Истинное

у с л о в и е )

 

 

{

 

 

 

 

 

 

b r e a k ; //

Выход

из ц и к л а

Б, но не из ц и к л а А

}

}

}

В С# нет команды, которая бы обеспечивала одновременный выход из обоих циклов. | Это не настолько уж большое ограничение, как могло бы показаться. На прак­ тике зачастую сложную логику, содержащуюся внутри таких вложенных цик­ лов, лучше инкапсулировать в виде функций. Выполнение оператора r e t u r n в любом месте обеспечивает выход из функции, т.е. из всех циклов, какой бы ни была глубина вложенности. Функции и оператор r e t u r n будут рассматри­ ваться в главе 7, "Функции функций".

106

Часть II. Основы программирования в С#


В приведенной далее программе DisplayXWithNestedLoops , которую

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

II DisplayXWithNestedLoops

 

 

 

 

// Использует пару вложенных циклов для

вывода на

экран

// большой

буквы X

 

 

 

 

 

 

using System;

 

 

 

 

 

 

 

 

namespace DisplayXWithNestedLoop s

 

 

 

{

 

 

 

 

 

 

 

 

 

 

public

c l a s s Program

 

 

 

 

{

 

 

 

 

 

 

 

 

 

 

public

s t a t i c v o i d

M a i n ( s t r i n g [ ]

a r g s )

 

{

 

 

 

 

 

 

 

 

 

 

in t

nConsoleWidth = 4 0 ;

 

 

 

//

Итерация

по

строкам

 

 

 

f o r ( i n t

nRowNum

= 0;

 

 

 

 

 

nRowNum < nConsoleWidth ;

 

 

 

 

nRowNum + = 2)

 

 

 

 

{

 

 

 

 

 

 

 

 

 

 

//

Итерация по столбцам

 

 

 

fo r

( i n t

nColumnNum

= 0 ;

 

i

 

 

 

 

nColumnNum < nConsoleWidth ; nColumnNum++)

{

 

 

 

 

 

 

 

 

 

 

/ / П о

умолчанию используетс я пробел

 

 

cha r с

=

1

1;

 

 

 

 

 

//

Если номер строки и столбца

совпадают . . .

 

if

(nColumnNum ==

nRowNum)

 

 

 

 

{

 

 

 

 

 

 

 

 

 

 

//

. . .

заменим

пробел обратной косой

чертой

 

 

с =

' \\ ' ;

 

 

 

 

 

 

}

 

 

 

 

 

 

 

 

 

// Если столбец на противоположной

 

 

//

стороне строки . . .

 

 

 

 

i n t

nMirrorColumn

= nConsoleWidt h - nRowNum;

 

if

(nColumnNum ==

nMirrorColumn)

 

 

{

 

 

 

 

 

 

 

 

 

 

/ /

. . .

заменим

пробел косой

чертой

 

 

 

с =

' / 1 ;

 

 

 

 

 

 

}

 

 

 

 

 

 

 

 

 

//

Вывод

символа

в текущей

позиции

 

 

C o n s o l e . W r i t e ( с ) ;

 

 

 

 

}

 

 

 

 

 

 

 

 

 

C o n s o l e . W r i t e L i n e ( ) ;

 

 

 

}

 

 

 

 

 

 

 

 

 

 

//

Ожидаем подтверждения пользователя

 

Глава 5. Управление потоком выполнения

 

 

107

Si