Шрифт:
Правило недопущения "провалов" относится к тем особенностям языка С#, кото рыми он отличается от С, 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 или 3 i равно 1, 2 или 3 i равно 1, 2 или 3 i равно 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); } } }