|
Циклические операторы
С# включает достаточно большой набор циклических операторов, таких как for, while, do...while, а также цикл с перебором каждого элемента foreach. Кроме того, С# поддерживает операторы перехода и возврата, например goto, break, continue и return.
Оператор goto
Оператор goto был основой для реализации других операторов цикла. Но он был и базой многократных переходов, вследствие чего возникла запутанность кода программы. Поэтому опытные программисты стараются его не использовать, но для того чтобы узнать все возможности языка, рассмотрим и этот оператор.
Он используется следующим образом:
1. Создается метка в коде программы Label 1.
2. Организуется переход на эту метку goto Labe1.
Имя метки Labe1 обязательно должно заканчиваться двоеточием. Оно указывает на точку в программе, с которой будет выполняться программа после использования инструкции goto. Обычно инструкция goto привязывается к условию, как показано в следующем примере:
using System;
public class Labels
{
public static int Main()
{
int i = 0;
Label:
Console.WriteLine("i: {0 } ", i);
i = i + 1;
if (i < 10)
goto Label;
return 0;
}
}
|
Здесь мы выводим на экран строку со значением i десять раз (от 0 до 9). Инструкция goto помогает повторить выполнение одних и тех же инструкций определенное число раз. В этой программе число повторов определяется инструкцией if(i < 10). Значит, до тех пор пока переменная I будет иметь значение меньшее, чем 10, goto будет переносить нас на метку label:, а значит, вывод строки на экран будет повторяться. То есть с использованием goto мы можем организовать циклический повтор операций в программе.
Именно это явление привело к созданию альтернативного метода организации циклов, такого как while, do..while, for или foreach. Большинство программистов понимают, что использование goto в программе лучше заменять чем-нибудь другим, что приведет к созданию программного кода, более структурированного и понятного, нежели инструкции goto.
Цикл while
Эта циклическая инструкция работает по принципу: «Пока выполняется условие — происходит работа». Ее синтаксис выглядит следующим образом:
while (выражение)
{
инструкция;
}
|
Как и в других инструкциях, выражение — это условие, которое оценивается как булево значение. Если результатом проверки условия является истина, то выполняется блок инструкций, в противном случае в результате выполнения программы while игнорируется. Рассмотрим пример, приведенный выше, только с использованием while:
using System;
public class WhileCycle
{
public static int Main()
{
int i = 0;
while (i < 10)
{
Console.WriteLine("i: {0}", i);
++i;
}
return 0;
}
}
|
По своей функциональности и та, и другая реализация программы работают абсолютно одинаково, но логика работы несколько изменилась. Заметьте, что цикл while проверяет значение i перед выполнением блока statement. Это гарантирует, что цикл не будет выполняться, если проверяемое условие ложно. Таким образом, если первоначально i примет значение 10 и более, цикл не выполнится ни разу. Инструкция while является вполне самостоятельной, а в данном примере ее можно прочитать подобно предложению: «пока i меньше 10, выводим сообщение на экран и увеличиваем i».
Цикл do... while
Бывают случаи, когда цикл while не совсем удовлетворяет вашим требованиям. Например, вы хотите проверять условие не в начале, а в конце цикла. В таком случае лучше использовать цикл do...while.
do
{
Инструкция
}
while (выражение);
Подобно while, выражение — это условие, которое оценивается как булево значение.
Это выражение можно прочитать как: «выполнить действие; если выполняется условие — повторить выполнение еще раз». Заметьте разницу между этой формулировкой и формулировкой работы цикла while. Разница состоит в том, что цикл do...while выполняется всегда минимум один раз, до того как произойдет проверка условия выражения.
using System;
public class DoWhile
{
public static int Main()
{
int i = 0;
do
{
Console.WriteLine("i : {0}", i);
++i;
}
while (i < 10);
return 0;
}
}
|
На этом примере видно, что если первоначально i примет значение 10 и более, цикл выполнится. Затем произойдет проверка условия while (i < 10), результатом которой станет ложь (false), и повтора выполнения цикла не произойдет. То есть он выполнится один раз. Как вы помните, при таких же начальных условиях while не выполнился ни разу.
Цикл for
Если еще раз внимательно посмотреть на примеры (while, do...while, goto), можно заметить постоянно повторяющиеся операции: первоначальная инициализация переменной i, ее наращивание на 1 внутри цикла, проверка переменной i на выполнение условия (i < 10). Цикл for позволяет вам объединить все операции в одной инструкции.
for ( [инициализация ]; [ выражение]; [ наращивание] )
{
инструкция
}
Выполним тот же пример, но уже с использованием цикла for:
using System;
public class ForCycle
{
public static int Main()
{
for (int i = 0; i < 10; i++)
{
Console.WriteLine("i: {0}", i);
}
return 0;
}
}
|
Результатом выполнения такого цикла будет вывод на экран информации вида:
0
1
2
…
9
Принцип работы такой инструкции очень прост:
1. Происходит инициализация переменной i.
2. Выполняется проверка соответствия условию. Если условие истинно, то происходит выполнение блока вложенных инструкций; если условие оказалось ложным, то цикл прекращается и выполняется программа за фигурными скобками.
3. Переменная i увеличивается на 1.
Наращивание переменной внутри цикла происходит на такое число единиц, на которое вы сами зададите. Операция i++ означает «увеличить значение переменной на 1». Если вы хотите использовать другой шаг изменения i, то смело можете написать так i += 2. В этом случае значение переменной i будет изменяться на 2 единицы, и на экране вы увидите:
0
2
4
6
8
Цикл foreach
Эта инструкция незнакома программистам на языке С, она используется для перебора массивов и объединений (collection) по элементам. Разговор о ней пойдет в последующих уроках.
break И continue
Бывают ситуации, когда необходимо прекратить выполнение цикла досрочно (до того как перестанет выполняться условие) или при каком то условии не выполнять описанные в теле цикла инструкции, не прерывая при этом цикла. Для таких случаев очень удобно использовать инструкции break и continue. Если вы хотите на каком-то шаге цикла его прекратить, не обязательно выполняя до конца описанные в нем действия, то лучше всего использовать break. Следующий пример хорошо иллюстрирует его работу.
using System;
class Values
{
static void Main()
{
//объявляем флаг для обозначения простых чисел
bool IsPrimeNumber;
for(int i=100; i > 1; i--)
{
//устанавливаем флаг
IsPrimeNumber = true;
for (int j = i-1; j > 1; j--)
{
//если существует делитель с нулевым остатком
if(i%j == 0)
{
//сбрасываем флаг IsPrimeNumber = false;
// если не нашлось ни одного делителя
//с нулевым остатком-то число простое
if(IsPrimeNumber == true)
Console.WriteLine("{0}— простое число", i);
}
}
}
}
}
|
Программа выполняет поиск всех простых чисел от 2 до 100. В программе используется два цикла for. Первый цикл перебирает все числа от 100 до 2. Заметьте, именно от 100 до 2, а не наоборот. Переменная i инициализируется значением 100 и затем уменьшается на 1 с каждой итерацией. Второй цикл перебирает все числа от i до 2. Таким образом, второй цикл будет повторяться 99 + 98 + 97 + ... + 3+2 раз. То есть первый раз он выполнится 99 раз, второй — 98 и т. д. В теле второго цикла проверяется выполнение условия: делится ли число i на число j без остатка (i%j == 0). Если это условие верно, то число i нельзя отнести к разряду простых. Следовательно, флажок, определяющий число как простое, устанавливается в false. По окончании работы вложенного цикла проверяется условие — не установился ли флажок, определяющий число как простое, в false. Если нет, то число является простым, и на экран выводится соответствующее сообщение.
В данной программе происходит выполнение всех описанных действий внутри цикла. А что если программа уже отнесла число к разряду не простых чисел? Зачем в этом случае продолжать проверку на существование нулевого делителя? В этом нет необходимости. Это лишь дополнительная загрузка ресурсов программы. Для того чтобы прервать выполнение вложенного цикла, вы можете воспользоваться инструкцией break. Для этого необходимо изменить код второго цикла так, как показано ниже:
for(int j = i-1; j > 1; j--)
{
//если существует делитель с нулевым остатком
if (i%j == 0)
{
//сбрасываем флаг IsPrimeNunber = false;
// дальнейшая проверка бессмысленна
break;
}
}
|
Как только сбросится флаг IsPrimeNumber, вложенный цикл сразу же прервется и выйдет в основной цикл. Таким образом, количество итераций сократится многократно, что благоприятно скажется на производительности работы программы.
Оператор continue в отличие от break не прерывает хода выполнения цикла. Он лишь приостанавливает текущую итерацию и переходит сразу к проверке условия выполнения цикла.
for (int j = 0; j < 100; j++ )
{
if (j%2 == 0)
continue;
Console.WriteLine("{0}", j);
}
|
Такой цикл позволит вывести на экран все нечетные числа. Работает он следующим образом: перебирает все числа от 0 до 100. Если очередное число четное — все дальнейшие операции в цикле прекращаются, наращивается число j, и цикл начинается сначала.
Вечные циклы
При написании приложений с использованием циклов вам следует остерегаться зацикливания программы. Зацикливание — это ситуация, при которой условие выполнения цикла всегда истинно и выход из цикла невозможен. Давайте рассмотрим простой пример.
using System;
class Cycles
{
public static void Main()
{
int nl, r2;
r1 = 0;
r2 = n1 + 1;
while(nl < n2)
{
Console.WriteLine("nl = {0} , n2 = {1} " , n1 , n2 );
}
}
}
|
Здесь условие (n1 < n2) всегда истинно. Поэтому выход из цикла невозможен. Следовательно, программа войдет в режим вечного цикла. Такие ошибки являются критическими, поэтому следует очень внимательно проверять условия выхода из цикла.
Однако иногда бывает полезно задать в цикле заведомо истинное условие. Типичным примером вечного цикла является следующая запись:
while(true)
{...}
Возможно что такая конструкция приведет к зависанию системы, если не задать в теле цикла инструкцию его прерывания. Рассмотрим пример программы:
using System;
class Cycles
{
public static void Main()
{
String Name;
while (true)
{
Console.Write("Введите ваш имя ");
Name = Console.ReadLine();
Console.WriteLine("Здравствуйте {0}", Name);
}
}
}
|
Такая программа не имеет выхода. Что бы не ввел пользователь, программа выдаст строку приветствия и запросит ввод имени заново. Однако все изменится, если в программу добавить условие, при выполнении которого цикл прерывается.
using System;
class Cycles
{
public static void Main()
{
string Name;
while (true)
{
Console.WriteLine("Введите ваш имя ");
Name = Console.ReadLine();
if (Name == "")
break;
Console.WriteLine("Здравствуйте {0 ) ", Name);
}
}
}
|
На этот раз, как только пользователь нажмет клавишу «Enter» без ввода строки данных, сработает инструкция break, и программа выйдет из цикла.
Создание вечных циклов оправдывает себя, если существует несколько условий прерывания цикла и их сложно объединить в одно выражение, записываемое в блоке условия.
Вечный цикл можно создать не только при помощи оператора while.
Любой оператор цикла может быть использован для создания вечных циклов. Вот как выглядит та же программа, но с использованием цикла for:
using System;
class Cycles
{
public static void Main()
{
string Name;
for (; ; )
{
Console.Write("Введите ваш имя ");
Name = Console.ReadLine();
if (Name == "")
break;
Console.WriteLine("Здравствуйте {0} ", Name);
}
}
}
|
Цикл for может не содержать ни инструкции инициализации, ни инструкции проверки, ни инструкции итерации. Два оператора (;) внутри цикла for означают вечный цикл.
Предыдущая стр.   
Оглавление   
Следующая стр.
Средняя оценка:     (4,25 - 8 голосов) Для оценки необходимо зарегистрироваться
Только зарегистрировавшиеся пользователи могут оставлять комментарии
Комментирует james 11.01.2010 21:57:31 Отличная статья
Комментирует alwery 13.01.2010 16:21:35 Спасибо)понятно и интересно)
Комментирует netip 03.02.2010 20:14:16 Спасибо! Очень познавательно!
Комментирует aronov2004 11.02.2010 18:29:09 В примере int nl, r2;
r1 = 0;
r2 = n1 + 1;
while(nl < n2)
должны быть только переменные n1 и n2.
r1 и r2 - это ошибка?
Комментирует aronov2004 11.02.2010 18:31:07 а в примере break И continue флажок, определяющий число как простое, должен устанавливатся в false.
оператором присваивания
IsPrimeNumber = false;
так?
Комментирует james 11.02.2010 18:45:28 В первом случае опечатка.
Во втором случае в if (i % j == 0) надо добавить IsPrimeNumber = false;
а if (IsPrimeNumber == true)
Console.WriteLine("{0}— простое число", i); вынести в из второго цикла for в первый for
Комментирует aronov2004 13.02.2010 16:17:49 А если на добавлять sPrimeNumber = false; ???
Какое значение примет IsPrimeNumber после его определения в строке bool IsPrimeNumber;
По умолчанию ?
Комментирует Silver_off 07.07.2010 10:37:17 Вот готовий листинг с 6-го примера:
using System;
class Values
{
static void Main()
{
bool IsPrimeNumber;
for (int i = 100; i > 1; i--)
{
IsPrimeNumber = true;
for (int j = i - 1; j > 1; j--)
{
if (i % j == 0)
IsPrimeNumber = false;
break;
}
if (IsPrimeNumber == true)
Console.WriteLine("{0}— простое число", i);
}
Console.ReadLine();
}
}
Комментирует gavrikr1 07.08.2010 3:15:20 static void Main()
{
bool IsPrimeNumber;
int j;
for (int i = 100; i > 1; i--)
{
//IsPrimeNumber = true;
for (j = i - 1; j > 1; j--)
{
if (i % j == 0)// IsPrimeNumber = false;
break;
}
if (j == 1) Console.WriteLine("{0}— простое число", i);
}
Проверьте такой вариант
Комментирует idShura 01.09.2010 19:12:21 Отлиная статья) Только необходио подправить ошибки и опечатки. В девятом примере говорится что это вечный цикл. Но как я понял это не вечный цикл так как переменная int имеет диапозон от -2147483648 до 2147483647. т.е. цикл завершится
Комментирует vadiaoxy 14.04.2011 15:14:48 using System;
class Values
{
static void Main()
{
int x = 0;
for (int i = 1; i <= 100; i++)
{
for (int j = 1; j <= i; j++)
if (i % j == 0)
x++;
if( x <= 2)
Console.WriteLine("{0} — простое число", i);
x = 0;
}
}
}
А я вот так сделал.
Комментирует Weib_Perlen 27.10.2011 17:00:39 Спасибо вам огрномное!
Вы большие молодцы)
|
|