
CSBasicCourse2ndedPodbelsky / CSBasicCourse2ndedPodbelsky
.pdfОператор break "оператор:оператор break" служит для принудительного выхода из цикла или переключателя. Определение "принудительный" подчеркивает
безусловность перехода. Например, в случае цикла не проверяются и не |
break |
рассматриваются условия дальнейшего продолжения итераций. Оператор |
|
прекращает выполнение оператора цикла или переключателя и осуществляет |
|
передачу управления (переход) к следующему за циклом или переключателем |
|
оператору. При этом в отличии от перехода с помощью goto оператор, к которому выполняется передача управления, может быть не помечен. Оператор break нельзя использовать нигде, кроме циклов и переключателей.
Необходимость в использовании оператора break в теле цикла возникает, когда условия продолжения итераций нужно проверять не в начале итерации (циклы for, while), не в конце итерации (цикл do), а в середине тела цикла. В этом случае
тело цикла может иметь такую структуру:
{ операторы
if (условие) break;
операторы
}
Например, если начальные значения целых переменных i, j таковы, что i < j, то следующий цикл определяет наименьшее целое, не меньшее их среднего
арифметического: |
if (i == j) break; j--; } |
while (i < j) { i++; |
Для i == 0, j == 3 результат i == j == 2 достигается при выходе из цикла с помощью оператора break. (Запись i == j == 2 не в тексте программы означает равенство значений переменных i, j и константы 2.) Для i == 0 и j == 2 результат i == j == 1 будет получен при естественном завершении цикла.
Как уже упомянуто, циклы могут быть многократно вложенными. Однако, следует помнить, что оператор break позволяет выйти только из того цикла, в
котором он размещен. При многократном вложении циклов оператор break не может вызвать передачу управления из самого внутреннего уровня непосредственно на самый внешний. Например, при решении задачи поиска в матрице хотя бы одного элемента с заданным значением, когда цикл перебора элементов строки вложен в цикл перебора строк, удобнее пользоваться не оператором break, а
оператором безусловной передачи управления goto.
В качестве примера, когда при вложении циклов целесообразно применение оператора break, назовём задачу вычисления произведений элементов отдельных строк матрицы. Задача требует вложения циклов. Во внешнем выбирается очередная строка, во внутреннем – вычисляется произведение её элементов.
Вычисление произведения элементов строки можно прервать, если один из сомножителей окажется равным 0. При появлении в строке нулевого элемента
оператор break прерывает выполнение только внутреннего цикла, однако внешний
цикл перебора строк выполнится для всех строк. |
"оператор:оператор безусловного |
Оператор безусловного перехода |
перехода" , который мы рассмотрели в связи с метками и переключателем, имеет вид:
goto идентификатор;
где идентификатор – имя метки оператора, расположенного в той же функции, где используется оператор безусловного перехода.
Принятая в настоящее время дисциплина программирования рекомендует либо вовсе отказаться от оператора goto, либо свести его применение к минимуму и строго придерживаться следующих рекомендаций:
не входить внутрь блока извне (компилятор C# этого не позволит – сообщит об ошибке);
не входить внутрь условного оператора, т.е. не передавать управление операторам, размещенным после служебных слов if или else;
не входить извне внутрь переключателя (компилятор C# сообщит об ошибке); не передавать управление внутрь цикла.
Следование перечисленным рекомендациям позволяет исключить возможные нежелательные последствия бессистемного использования оператора безусловного перехода. Полностью отказываться от оператора goto вряд ли стоит. Есть случаи, когда этот оператор обеспечивает наиболее простые и понятные решения. Один из них – это ситуация, когда нужно выйти из нескольких вложенных друг в друга циклов или переключателей. Оператор break здесь не поможет, так как он обеспечивает выход только из самого внутреннего вложенного цикла или переключателя.
Оператор continue "оператор:оператор continue" (оператор перехода к следующей итерации) употребляется только в операторах цикла. С его помощью завершается текущая итерация и начинается проверка условия возможности дальнейшего продолжения цикла, т.е. условия начала следующей итерации. Для объяснений действия оператора continue рекомендуется рассматривать операторы
цикла в следующем виде: while (foo) {
...
contin: ;
}
В каждой из форм многоточием обозначены операторы тела цикла. Вслед за ними размещен пустой оператор с меткой contin. Если среди операторов тела цикла есть оператор continue и он выполняется, то его действие эквивалентно оператору
безусловного перехода на метку contin.
Пример использования оператора continue. Вводя с клавиатуры последовательность вещественных чисел, подсчитать сумму только положительных. Окончанием ввода последовательности считать ввод нулевого
значения.
// 06_04.cs - оператор перехода к следующей итерации using System;
class Program
{
static void Main() { double sum = 0, x;
do { Console.Write("x = ");
x = Double.Parse(Console.ReadLine()); if (x < 0) continue;
sum += x;
}
while (x != 0); Console.WriteLine("Сумма = "+sum);
}
}
Результат выполнения программы: x = 2<ENTER>
x = -4<ENTER> x = 6<ENTER> x = 0<ENTER>
Сумма = 8
Напомним, что без обработки исключений применение метода Parse() делает
программу незащищённой от синтаксических ошибок во вводимых исходных
данных.
6.6. Переключатель
Переключатель "переключатель" является наиболее удобным средством для организации множественного (мульти-) ветвления. Синтаксис переключателя
таков:
switch (переключающее_выражение)
{ case константное_выражение_1: операторы_1; break;
case константное_выражение_2: операторы_2; break;
...
case константное_выражение_n: операторы_n;
default: операторы; break;
} |
switch, case, break, |
В переключателях используют 4 служебных слова: |
default и обязательные фигурные скобки, ограничивающие тело переключателя. Конструкция
case константное_выражение:
называется меткой переключателя "переключатель:метка переключателя" . Константное выражение может быть целочисленным, может быть символом, строкой или элементом перечисления. (О перечислениях речь пойдет в главе 15).
Заголовок, то есть управляющая конструкция |
|
switch (переключающее выражение), |
case операторов, для |
передает управление к тому из помеченных с помощью |
которого значение константного выражения совпадает со значением переключающего выражения. Значение переключающего выражения должно быть целочисленным или иметь тип char, string, тип перечисления, или приводиться к целому. Переключающее выражение не может иметь вещественный тип и не может
быть десятичным (decimal). |
|
|
Метка переключателя |
"переключатель:метка переключателя" вводит ветвь |
|
или раздел переключателя |
"переключатель:раздел переключателя" |
– |
последовательность операторов, завершаемая оператором break или goto case i или goto default. (В приведённом формате переключателя указаны только операторы
break, так как они используются наиболее часто.) Назначение оператора |
break – |
завершить выполнения переключателя. Операторы goto case i или goto |
default |
обеспечивают переход к другой "ветке" переключателя. |
|
Значения константных выражений, помещаемых за служебными словами case, |
|
приводятся к типу переключающего выражения. В одном переключателе все |
|
константные выражения должны иметь различные значения, но быть одного типа. Любой раздел из операторов, помещенных в фигурных скобках после конструкции switch(...), может быть помечен или одной или несколькими метками переключателя. То есть отдельный раздел переключателя может начинаться несколькими метками.
Если значение переключающего выражения не совпадает ни с одним из константных выражений, то выполняется переход к оператору, отмеченному меткой default "метка:метка default" . В каждом переключателе может быть не больше одной метки default. Если метка default отсутствует, то при несовпадении переключающего выражения ни с одним из константных выражений, помещаемых вслед за case, в переключателе не выполняется ни один из операторов.
В качестве примера приведём программу перевода оценки в баллах при
десятибалльной шкале в аттестационную (четырех бальную) оценку. Соответствие: 1, 2, 3 балла – не удовлетворительно;
4, 5 – удовлетворительно; 6, 7 – хорошо; 8, 9, 10 – отлично.
// 06_05.cs - переключатель using System;
class Program
{
static void Main()
{
int ball; // оценка в баллах: do
Console.Write("Введите оценку в баллах: "); while (!int.TryParse(Console.ReadLine(), out ball)
|| ball <= 0 || ball > 10) ; switch (ball)
{
case 1: case 2: case 3:
Console.WriteLine("Неудовлетворительно"); break;
case 4: case 5:
Console.WriteLine("Удовлетворительно"); break;
case 6: case 7:
Console.WriteLine("Хорошо"); break;
case 8: case 9: case 10:
Console.WriteLine("Отлично"); break;
default: Console.WriteLine("Ошибка в данных"); break;
} // Конец переключателя
}
}
Результат выполнения программы:
Введите оценку в баллах: гг<ENTER>
Введите оценку в баллах: -9<ENTER> Введите оценку в баллах: 0<ENTER> Введите оценку в баллах: 9<ENTER> Отлично
Обратите внимание на обязательность оператора |
break в каждой ветви |
|
переключателя. С его помощью управление всегда передаётся оператору, |
||
размещённому за переключателем. |
|
|
В переключателе могут находиться определения объектов. Тело |
||
переключателя, и каждый оператор, входящий в переключатель, может быть |
||
блоком. В этом случае нужно избегать ошибок "перескакивания" через |
||
определения: |
// Переключатель с ошибками |
|
switch (n) |
||
{ char d = 'D'; |
// Никогда не обрабатывается |
|
case 1: double f = 3.14;// Обрабатывается только для n == 1 |
||
break; |
// Ошибка: d и/или f не определены |
|
case 2:… if ((int)d != (int)f) |
||
break; |
|
|
... } |
|
|
Если в переключателе при некотором значении переключающего выражения необходимо выполнить более одного раздела, то программист может заранее выбрать последовательность обхода ветвей, применяя оператор перехода goto case i или goto default.
Пример программы с переключателем, где выводятся названия нечетных целых цифр, не меньших заданной.
// 06_06.cs - переключатель с внутренними переходами using System;
class Program
{
static void Main() { int ic = 5;
string line = ""; switch (ic)
{
case 0:
case 1: line += "one, "; goto case 2;
case 2:
case 3: line += "three, "; goto case 4;
case 4:
case 5: line += "five, "; goto case 6;
case 6:
case 7: line += "seven, ";
goto case 8; case 8:
case 9: line += "nine."; break;
default: line = "Error! It is not digit!"; break;
}
Console.WriteLine("Цифры: " + line);
}
}
Результат выполнения программы:
Цифры: five, seven, nine.
Контрольные вопросы
Каково назначение оператора в программах на C#? Перечислите операторы языка C#.
Каков обязательный признак отличного от блока оператора в C#? Что такое оператор-выражение?
Где пустой оператор? Что такое метка?
Дайте определение блока.
Какими правилами определяются вход в блок и выход из него? Назовите операторы выбора (ветвлений).
Какие операторы не могут входить в условный оператор? Что такое сокращённая форма условного оператора?
Как устанавливается соответствие между if и else при вложениях условных операторов?
Назовите виды операторов циклов в C#. Какой оператор не может быть телом цикла?
Какой тип имеет выражение-условие в операторе цикла?
Сколько элементов в заголовке цикла общего вида (цикла for) и как они разделяются?
Что такое инициализатор цикла общего вида (цикла for)? Когда вычисляется завершающее выражение цикла for?
Укажите область существования объектов, объявленных в инициализаторе цикла for.
Как выполняется вложение циклов?
Какие операторы могут прервать выполнение цикла до его завершения, запланированного выражением-условием?
Каково минимальное количество итераций в цикле с постусловием? Назовите назначение оператора break. Где его можно применять? Укажите возможности оператора goto при вложениях циклов.
Где и когда употребляется оператор continue?
Какого типа может быть значение переключающего выражения в переключателе?
Что называют меткой переключателя?
Каким оператором должна завершиться ветвь переключателя? Какая конструкция вводит ветвь переключателя?
В каких случаях выполняется ветвь переключателя, введённая меткой default?
Глава 7. Массивы
7.1. Одномерные массивы
Напомним, что система типов языка C# построена на основе классов. Типы делятся на четыре группы (значений, ссылок, указателей и тип void). С типами значений мы уже знакомы. К типам ссылок отнесены собственно классы
(библиотечные и определяемые программистом), массивы и строки. Рассмотрим массивы.
Одномерный массив "массив:одномерный массив" – набор однотипных элементов, доступ к которым осуществляется с помощью выражения с операцией индексирования:
имя_ссылки_на_массив [индексирующее_выражение]
Здесь имя_ссылки_на_массив – ссылка типа, производного от класса Array.
Индексирующее_выражение "индексирующее_выражение" должно иметь целочисленный тип (или приводится к целочисленному типу). Значение индексирующего выражения (иначе индекс) должно принадлежать фиксированному конечному диапазону [0, indMax], где 0 – нижняя граница, indMax – верхняя граница индекса. indMax однозначно определяет количество элементов (размер) массива,
равное indMax+1.
Имя_ссылки_на_массив – выбираемый пользователем идентификатор. Чтобы идентификатор стал именем ссылки на массив, используется объявление вида:
тип [ ] имя_ссылки_на_массив;
Этим оператором объявляется переменная типа ссылки на массив, а тип определяет тип элементов этого массива. Кроме того, объявление указанного
формата вводит в программу новый тип с обозначением тип[ ]. Примеры:
int [ ] integers;
double [ ] points;
Здесь integers – ссылка на массив типа int [ ] с элементами типа int; points – ссылка на массив типа double [ ] с элементами типа double.
В результате обработки таких объявлений компилятор выделит в стеке участки для размещения переменных (ссылок) integers и points. Однако, массивов,
которые могут адресовать эти ссылки, пока не существует, и значениями integers и points является null. Каждый конкретный массив создаётся как объект класса,
производного от класса Array точно от соответствующего ему системного класса
System.Array.
Для создания экземпляра (объекта) конкретного типа массивов используется операция new. Выражение:
new тип [размер-массива]
определяет объект-массив с заданным в квадратных скобках количеством элементов указанного типа. Этот объект компилятор размещает в области памяти, называемой кучей (heap). Результат выполнения операции new – ссылка на выделенный для объекта участок памяти.
Чтобы связать ссылку с этим объектом используют операцию присваивания:
имя_ссылки_на_массив= new тип[размер-массива];
Тип ссылки на массив "массив:ссылки на массив" должен соответствовать
типу, указанному после операции new.
Примеры: integers=new int [14]; points=new double [8];
После этих и предыдущих объявлений ссылка integers (размещённая в стеке)
будет адресовать (ссылаться на) участок памяти в куче, отведённый для конкретного массива из 14-ти элементов типа int. Ссылка points будет связана с массивом из 8-ми элементов типа double.
Допустимо объединение объявления ссылки на массив и определения массива-