Добавить в цитаты Настройки чтения

Страница 25 из 188

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

В приведенном выше примере оператором switch управляла переменная i типаint. Как пояснялось ранее, для управления оператором switch может быть использовано выражение любого целочисленного типа, включая и char. Ниже приведен пример применения выражения и констант выбора типа char в операторе switch.// Использовать элементы типа char для управления оператором switch.using System;class SwitchDemo2 { static void Main() { char ch; for(ch='A'; ch<= 'E'; ch++) switch(ch) { case 'A': Console.WriteLine("ch содержит A"); break; case 'В': Console.WriteLine("ch содержит В"); break; case 'С': Console.WriteLine("ch содержит С"); break; case 'D': Console.WriteLine("ch содержит D"); break; case 'E': Console.WriteLine("ch содержит E"); break; } }}

Вот какой результат дает выполнение этой программы.ch содержит Аch содержит Вch содержит Сch содержит Dch содержит Е

Обратите в данном примере внимание на отсутствие ветви default в оператореswitch. Напомним, что ветвь default не является обязательной. Когда она не нужна,ее можно просто опустить.

Переход последовательности операторов, связанных с одной ветвью case, в следующую ветвь case считается ошибкой, поскольку в С# должно непременно соблюдаться правило недопущения "провалов" в передаче управления ходом выполненияпрограммы. Именно поэтому последовательность операторов в каждой ветви caseоператора switch оканчивается оператором break. (Избежать подобных "провалов",можно также с помощью оператора безусловного перехода goto, рассматриваемогодалее в этой главе, но для данной цели чаще применяется оператор break.) Когдав последовательности операторов отдельной ветви case встречается оператор break,происходит выход не только из этой ветви, но из всего оператора switch, а выполнение программы возобновляется со следующего оператора, находящегося за пределами оператора switch. Последовательность операторов в ветви default также должнабыть лишена "провалов", поэтому она завершается, как правило, оператором break.

Правило недопущения "провалов" относится к тем особенностям языка С#, которыми он отличается от С, C++ и Java. В этих языках программирования одна ветвьcase может переходить (т.е. "проваливаться") в другую. Данное правило установленов C# для ветвей case по двум причинам. Во-первых, оно дает компилятору возможность свободно изменять порядок следования последовательностей операторов из ветвей case для целей оптимизации. Такая реорганизация была бы невозможной, еслибы одна ветвь case могла переходить в другую. И во-вторых, требование завершатькаждую ветвь case явным образом исключает непроизвольные ошибки программирования, допускающие переход одной ветви case в другую.

Несмотря на то что правило недопущения "провалов" не допускает переход однойветви case в другую, в двух или более ветвях case все же разрешается ссылаться с помощью меток на одну и ту же кодовую последовательность, как показано в следующемпримере программы.// Пример "проваливания" пустых ветвей case.using System;class EmptyCasesCanFall { static void Main() { int i; for(i=1; i < 5; i++) switch(i) { case 1: case 2: case 3: Console.WriteLine("i равно 1, 2 или 3"); break; case 4: Console.WriteLine("i равно 4"); break; } }}

Ниже приведен результат выполнения этой программы.i равно 1, 2 или 3i равно 1, 2 или 3i равно 1, 2 или 3i равно 4

Если значение переменной i в данном примере равно 1, 2 иди 3, то выполняется первый оператор, содержащий вызов метода WriteLine(). Такое расположение нескольких меток ветвей case подряд не нарушает правило недопущения "провалов"; поскольку во всех этих ветвях используется одна и та же последовательность операторов.

Расположение нескольких меток ветвей case подряд зачастую применяется в томслучае, если у нескольких ветвей имеется общий код. Благодаря этому исключаетсяизлишнее дублирование кодовых последовательностей.Вложенные операторы switch



Один оператор switch может быть частью последовательности операторов другого, внешнего оператора switch. И такой оператор switch называется вложенным.Константы выбора внутреннего и внешнего операторов switch могут содержать общие значения, не вызывая никаких конфликтов. Например, следующий фрагмент кодаявляется вполне допустимым.switch(ch1) { case 'A': Console.WriteLine("Эта ветвь А — Часть " + "внешнего оператора switch."); switch(ch2) { case 'A': Console.WriteLine("Эта ветвь A — часть " + "внутреннего оператора switch"); break; case 'В': // ... } // конец внутреннего оператора switch break; case 'В': // ...Оператор цикла for

Оператор for уже был представлен в главе 2, а здесь он рассматривается более подробно. Вас должны приятно удивить эффективность и гибкость этого оператора. Прежде всего, обратимся к самым основным и традиционным формам оператора for.Ниже приведена общая форма оператора for для повторного выполнения единственного оператора.for(инициализация; условие; итерация) оператор;

А вот как выглядит его форма для повторного выполнения кодового блока:for(инициализация; условие; итерация){последовательность операторов;}

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

Цикл for может продолжаться как в положительном, так и в отрицательном направлении, изменяя значение переменной управления циклом на любую величину.В приведенном ниже примере программы выводятся числа постепенно уменьшающиеся от 100 до -100 на величину 5.// Выполнение цикла for в отрицательном направлении.using System;class DecrFor { static void Main() { int x; for(x = 100; x > -100; x -= 5) Console.WriteLine(x); }}

В отношении циклов for следует особо подчеркнуть, что условное выражение всегда проверяется в самом начале цикла. Это означает, что код в цикле может вообще невыполняться, если проверяемое условие с самого начала оказывается ложным. Рассмотрим следующий пример.for(count=10; count < 5; count++)x += count; // этот оператор не будет выполняться

Данный цикл вообще не будет выполняться, поскольку первоначальное значениепеременной count, которая им управляет, сразу же оказывается больше 5. Это означает, что условное выражение count < 5 оказывается ложным с самого начала, т.е. ещедо выполнения первого шага цикла.

Оператор цикла for — наиболее полезный для повторного выполнения операцийизвестное число раз. В следующем примере программы используются два цикла forдля выявления простых чисел в пределах от 2 до 20. Если число оказывается непростым, то выводится наибольший его множитель.// Выяснить, является ли число простым. Если оно// непростое, вывести наибольший его множитель.using System;class FindPrimes { static void Main() { int num; int i; int factor; bool isprime; for(num = 2; num < 20; num++) { isprime = true; factor = 0; // Выяснить, делится ли значение переменной num нацело. for(i=2; i <= num/2; i++) { if((num % i) == 0) { // Значение переменной num делится нацело. // Следовательно, это непростое число. isprime = false; factor = i; } } if(isprime) Console.WriteLine(num + " — простое число."); else Console.WriteLine("Наибольший множитель числа " + num + " равен " + factor); } }}