Руководства, Инструкции, Бланки

Инструкция Switch C img-1

Инструкция Switch C

Рейтинг: 4.9/5.0 (1841 проголосовавших)

Категория: Инструкции

Описание

Инструкция switch c

Оператор switch

В отличие от операторов if-then и if-then-else. оператор switch применим к известному числу возможных ситуаций. Можно использовать простые типы byte. short. char. int. Также можно использовать Enum и String (начиная с JDK7), а также специальные классы, которые являются обёрткой для примитивных типов: Character, Byte, Short, Integer.

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

Команду switch часто называют командой выбора. Выбор осуществляется в зависимости от целочисленного выражения. Форма команды выглядит так:

Параметр ВыражениеДляСравнения - выражение, в результате вычисления которого получается целое число (как правило). Команда switch сравнивает результат ВыражениеДляСравнения с каждым последующим Совпадением. Если обнаруживается совпадение, то исполняется команда или набор команд, которые прописаны за данным оператором. Если совпадений не будет, то исполняется команда после ключевого слова default. Однако оператор default не является обязательным. В этом случае при отсутствии совпадений программа не выполняет никаких действий.

Каждая секция case обычно заканчивается командой break. которая передаёт управление к концу команды switch .

Рассмотрим простейший пример с месяцами. Запустим наш учебный проект и добавим код в обработчик нажатия кнопки:

Запустите проект и нажмите кнопку - в текстовом поле появится слово Март (любимый месяц котов).

При желании, можно переписать пример с использованием if-then-else :

В каждом блоке case имеется оператор break. который прерывает свой блок кода. Его нужно использовать обязательно, иначе выполнение кода продолжится. Хотя иногда это и используется.

Если код в блоках case совпадает, то блоки можно объединить. Например, код для подсчёта дней в месяце:

При изучении оператора if мы рассматривали пример с временами года. Перепишем его с использованием оператора switch :

Следующий пример случайным образом генерирует английские буквы. Программа определяет, гласные они или согласные:

Так как метод Random.nextInt(26) генерирует значение между 0 и 26, для получения символа нижнего регистра остаётся прибавить смещение 'a', при этом символ a автоматически преобразуется к типу int. Символы в секциях case также представляют собой целочисленные значения, используемые для сравнения.

Чтобы вывести переменную c в символьном виде, её необходимо преобразовать к типу char. иначе значение будет выведено в числовом виде.

В Java SE 7 появилась возможность использовать объект String в операторе switch. Возможно, это будет работать и на Android в будущем (Upd. вроде уже работает):

Допустимы вложенные операторы switch. но на практике я не сталкивался с таким кодом.

Запомните важные свойства оператора switch :

  • Оператор switch отличается от оператора if тем, что может выполнять проверку только равенства, а оператор if может вычислять результат булева выражения любого типа.
  • Две константы case в одном и том же операторе switch не могут иметь одинаковые значения
  • Оператор switch эффективнее набора вложенных операторов if

Страница документации: http://docs.oracle.com/javase/tutorial/java/nutsandbolts/switch.html

Реклама

Другие статьи

Глава 3 - 3

3.4. Инструкция switch

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

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

В главе 1 мы написали программу, подсчитывающую число вхождений в текст каждой цифры, символов-разделителей (пробелов, табуляций и новых строк) и всех остальных символов. В ней мы использовали последовательность if. else if. else. Теперь приведем вариант этой программы с инструкцией switch :

Инструкция break вызывает немедленный выход из инструкции switch. Поскольку выбор ветви case реализуется как переход на метку, то после выполнения одной ветви case. если ничего не предпринять, программа будет выполнять следующую ветвь. Инструкции break и return — наиболее распространенные средства выхода из инструкции множественного ветвления. Инструкция break используется также для принудительного выхода из циклов while. for и do-while (мы еще поговорим об этом чуть позже).

«Сквозное» выполнение ветвей case вызывает смешанные чувства. С одной стороны, это хорошо, поскольку позволяет несколько ветвей case объединить в одну, как мы и поступили с цифрами в нашем примере. Но с другой — это означает, что в конце почти каждой ветви придется ставить break. чтобы избежать перехода к следующей. Последовательный проход по ветвям — вещь ненадежная, это чревато ошибками, особенно при изменении программы. За исключением случая с несколькими метками для одного вычисления, старайтесь по возможности реже пользоваться сквозным проходом, но если уж вы его применяете, обязательно комментируйте эти особые места.

Добрый вам совет: даже в конце последней ветви (после default в нашем примере) помещайте инструкцию break. хотя с точки зрения логики в ней нет никакой необходимости. Эта маленькая предосторожность спасет вас, когда однажды вам потребуется добавить в конец инструкции еще одну ветвь case .

Напишите функцию escape(s, t). которая при копировании текста из строки t в строку s преобразует такие символы, как новая строка и табуляция в видимые управляющие последовательности (вроде \n и \t ). Используйте инструкцию switch. Напишите функцию, выполняющую обратное преобразование управляющих последовательностей в настоящие символы.

Простые и красивые программы - Учебник C - Инструкции сравнения if и switch

Главная » Учебник C++ » Инструкции сравнения if и switch

Предисловие
Зачастую в программе некоторые действия должны выполняться при соблюдении некоторых условий, например, если переменная принимает определенное значение, или переменная превосходит какую-то величину, или еще в самых различных случаях. Для осуществления такой проверки и выполнения действий в зависимости от ее результатов служат инструкции if и switch .
Прежде чем перейти к их описанию, позволю себе небольшое лингвистическое отступление. Часто в литературе if называется не инструкцией, а оператором. Однако, в языке C++ существует такое понятие, как operator. что как раз логично перевести как "оператор". if же, в числе прочих, относится к понятию statement. Ввиду того, что слово "оператор" уже использовано для обозначения совершенно другого понятия, в моих статьях statement будет переводиться как "инструкция". Таким образом, вопреки довольно распространенной практике, мы будем говорить не про оператор if. а про инструкцию if .

Инструкция if
Инструкция if может быть представлена в двух видах:
if( условие ) инструкция
и
if( условие ) инструкция else инструкция
Первый вариант в случае, если выражение в скобках не равно нулю (логическое выражение истинно), выполняет инстукцию, следующую после скобок. Второй же в случае отличия от нуля выражения в скобках также выполняет инструкцию после скобок, а в противном случае - инструкцию, следующую за ключевым словом else. Если необходимо выполнить не одну, а несколько инструкций, то их последовательность заключается в фигурные скобки.
В условных инструкциях используются операторы (в этом случае - именно operator ) сравнения == (равенство). = (неравенство), < (меньше), <= (меньше или равно), > (больше) и >= (больше или равно).
Замечу по поводу передаваемого аргумента, что сам if работает с численными значениями, однако благодаря неявному преобразованию типов выражение в скобках может быть произвольным арифметическим выражением, логическим выражением или выражением с указателями. Результатом преобразовании в int значения булевой величины, равного false. будет ноль, а равного true - единица (величина отличная от нуля, чего условному оператору достаточно). Тип bool обеспечивает более наглядное представление работы с условиями, нежели численное представление. Результатом применения операторов сравнения является значение логического типа.
Указатель, равный нулю - это указатель, который ни на что не ссылается.
В логических выражениях часто используются логические операторы && (и), || (или). (не). Оператор "не" - унарный, т.е. выполняте действия над единственным аргументом, стоящим справа (возвращает true. если аргумент равен false. возвращает false. если аргумент равен true ). Операторы "и" и "или" - бинарные, т.е. выполняют действия над двумя аргументами, стоящими справа и слева. Оператор "и" возвращает true. если оба аргумента равны true. во всех остальных случаях возвращает false. Оператор "или" возвращает true. если хотя бы один из аргументов равен true. если же оба равны false. оператор возвращает false .
Для иллюстрации всего вышеизложенного рассмотрим следующий пример:

void f(int a, int b, char* p)
<
if(a == b) std::cout << "a равно b\n";
if(p) std::cout << *p;
if(true)
<
if(!(a * b - b * b) && (a != b)) std::cout << "b == 0\n";
else return;
>
else std::cout << "Такого не может быть!\n";
>

Функции передается два целых числа и указатель на символ. Вначале проверяется равенство чисел - if(a == b). и в случае равенства выводится сообщение об этом. Затем проверяется, является ли p указателем на инициализированную переменную, и если так, то выводится объект, на который ссылается указатель ( *p ). Третий if выполняется всегда, а вложенный - тогда, когда a не равно b и отрицание выражения в скобках отлично от нуля, т.е. выражение в скобках равно нулю. В противном случае функция завершается - else выполняет инструкцию return .
При наличии большого числа вложенных инструкций if с соответствующими else при правильно расставленных фигурных скобках не произойдет никакой путаницы - они будут наглядно объединены, и не будет допущено случайной ошибки, которую компилятор интерпретирует совершенно неожиданным образом. То же самое относится и к конструкциям внутри скобок вложенного if из этого примера - скобки делают длинную строку более читабельной, и гарантируют, что компилятор поймет все именно так, как вы хотели. При отсутствии же скобок может оказаться, что приоритет операторов отличается от того, что вы себе представляли и в результате получится невесть что.
Некоторые условные if -инструкции можно записывать в виде условных выражений. Например,

можно также записать в виде

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

Инструкция switch
Часто приходится проверять какую-то величину на равенство одному из списка значений и, соответственно, в зависимости от результата, совершать различные действия. В принципе это можно было бы сделать с помощью нескольких if -инструкций:

Однако, в C++ предусмотрен более прозрачный способ оформления этой идеи. Он реализуется с помощью инструкции switch. Записывается она так:

В круглых скобках записывается проверяемая переменная, тело инструкции заключается в фигурные скобки. Константы, с которыми сравнивается величина, пишутся после слова case. действия в случае равенства переменной константе - после двоеточия. Если значение переменной не совпадает ни с одной из констант, выполняется инструкция, стоящая после необязательного default (если он есть).
Обратите внимание на инструкцию break;. стоящую после каждого из case. Дело в том, что если их убрать, то вместо того, чтобы выполнить инструкции, стоящие после нужного case. программа выполнит эти инструкции, а затем и все, что относятся к case. записанным ниже этого. Т.е. после срабатывания одного из case программа начнет выполнять все инструкции вплоть до конца тела switch. или пока не встретит break;. Кроме break может использоваться в подходящей ситуации также и return .
Пример использования switch вы можете посмотреть здесь

C: оператор SWITCH-CASE

C++: оператор SWITCH-CASE

Олег Житник Гуру (3206), закрыт 3 года назад

для одного CASE во всех примерах задается только одно значение, например
case 9: //вот тут одно значение
//выполнение
break;
а можно ли одному CASE задать диапазон чисел.
case 0-9: //вот тут хочу вставить много значений, но не получается, данный пример не правильный, хотя компилятор не ругается
//выполнение
break;

Cheery Высший разум (198518) 3 года назад

>а можно ли одному CASE задать диапазон чисел
нет, только если знать значения, которые могут использоваться, то
switch (value)
<
case 1: case 2: case 3:
// что то делаем для целочисленного value из диапазона 1-3
break;
case 4: case 5: case 6:
// что то делаем для целочисленного value из диапазона 4-6
break;
default:
//все остальное
break;
>

в gcc есть дополнительная возможность, к примеру

switch (value)
<
case 1. 3:
//Do Something
break;
case 4. 6:
//Do Something
break;
default:
//Do the Default
break;
>

ps: возможно вам будет удобнее воспользоваться if структурами.

Олег Житник Гуру (3206) 3 года назад

Большое спасибо, первый ваш вариант заработал успешно. Жаль, что только gcc поддерживает диапазон чисел в CASE.

Инструкция switch c

SWITCH

Хотя конструкция if-else-if может выполнять многочисленные проверки, она не очень элегантна. Код очень труден для восприятия и в нем может запутаться даже автор через некоторое время. С этой целью С имеет оператор принятия решений switch, выполняющий действия, основываясь на сравнении значения со списком констант символов или целых чисел. При обнаружении совпадения выполняется оператор или операторы, ассоциированные с данным значением. Оператор switch имеет следующий вид:

switch (выражение) <
case константа1:
последовательность операторов
break;
case константа2:
последовательность операторов
break;
case константа3:
последовательность операторов break;
.
default:
последовательность операторов
>

Оператор default выполняется, если не найдено соответствий, default необязателен и, если его нет, то в случае отсутствия совпадений ничего не происходит. Когда обнаруживается совпадение, операторы, ассоциированные с соответствующим case, выполняются до тех пор, пока не встретится оператор break. В случае default (или последнего case, если отсутствует default), оператор switch заканчивает работу при обнаружении конца.

Следует знать о трех важных моментах оператора switch:

  1. switch отличается от if тем, что он может выполнять только операции проверки строгого равенства, в то время как if может вычислять логические выражения и отношения.
  2. Не может быть двух констант в одном операторе switch, имеющих одинаковые значения. Конечно, оператор switch, включающий в себя другой оператор switch, может содержать аналогичные константы.
  3. Если в операторе switch используются символьные константы, они автоматически преобразуются к целочисленным значениям.

Оператор switch часто используется для обработки команд клавиатуры типа работа с меню. Как показано ниже, функция menu() отображает меню для программы проверки орфографии и вызывает соответствующие процедуры:

void menu(void)
<
char ch;

printf("1. Check Spelling\n");
printf("2. Correct Spelling Errors\n");
printf("3. Display Spelling Errors\n");
printf("Strike Any Other Key to Skip\n");
printf (" Enter your choice: ");

ch = getche(); /* чтение клавиатуры */

switch(ch) <
case '1':
check_spelling();
break;
case '2':
correct_errors();
break;
case '3';
display_errors();
break;
default :
printf("No option selected");
>
>

С технической точки зрения операторы break являются необязательными в операторе switch. Они используются для окончания работы последовательности операторов, ассоциированных с данной константой. Если оператор break отсутствует, продолжают выполняться операторы следующего раздела, пока не будет достигнут оператор break или конец оператора switch. О константах выбора можно думать как о метках. Выполнение начинается с метки, соответствующей искомому значению, и продолжается, пока не будет достигнут break или конец оператора switch. Например, функция, показанная ниже, использует данную особенность оператора case для упрощения кода обработчика ввода драйвера устройства:

void inp_handler(void)
<
int ch, flag;
ch = read_device(); /* чтение какого-то устройства */
flag = -1;
switch(ch) <
case 1: /* данные случаи имеют общую последовательность */
case 2: /* операторов */
case 3:
flag = 0;
break;
case 4:
flag = 1;
case 5:
error(flag);
break;
default:
process(ch);
>
>

Данная подпрограмма иллюстрирует две грани оператора switch. Во-первых, можно иметь пустые условия. В данном случае первые три условия приводят к выполнению одних и тех же операторов:

Во-вторых, выполнение переходит к следующему case, если отсутствует break. Если ch соответствует 4, то flag устанавливается в 1, и, поскольку отсутствует оператор break, выполнение продолжается и выполняется оператор error(flag). В данном случае flag имеет значение 1. Если ch равно 5, то вызывается error(flag), а значение flag будет равно - 1. Способность запускать несколько операторов, соответствующих нескольким условиям при отсутствии оператора break, позволяет создавать эффективный код, поскольку это избавляет от необходимости дублировать код.

Важно понять, что операторы, ассоциированные с каждой меткой, являются не блоками кода, а скорее последовательностью операторов. (Сам оператор switch определяет блок.) Понимание этого необходимо в некоторых специфических ситуациях. Например, следующий фрагмент кода содержит ошибку и не будет компилироваться, поскольку невозможно объявить переменную в последовательности операторов:

Тем не менее переменная может быть добавлена:

Имеется возможность создания блока кода как одного из операторов в последовательности и объявление в нем переменной, как показано ниже:

ЗАМЕТКА: Все ранее обсуждаемое применимо только к С, но не к С++. В С++ можно объявлять переменную в любой точке, в том числе в последовательности операторов.

Операторы передачи управления

Операторы передачи управления

Операторы передачи управления меняют последовательность исполнения вашего кода, передавая управление от одного фрагмента кода другому. В Swift есть четыре оператора передачи управления:

Операторы continue. break. fallthrough будут описаны в следующих главах. А оператор return будет описан в главе "Функции".

Оператор Continue

Оператор continue говорит циклу прекратить текущую итерацию и начать новую. Он как бы говорит: "Я закончил с текущей итерацией", но полностью из цикла не выходит.

Заметка

В цикле for с условием и инкрементором все продолжает работать как и работало, а именно условие проверяется, инкрементор меняется как и обычно, в общем цикл работает как обычно, только код внутри цикла пропускается.

Следующий пример убирает все гласные и пробелы из строки с нижним регистром, для того чтобы создать загадочную фразу-головоломку:

Пример выше вызывает оператор continue. когда он находит соответствие с гласными звуками или пробелом, вызывая тем самым прекращение текущей итерации и начало новой. Такой подход позволяет блоку switch находить соответствие(и игнорировать) только гласные звуки и пробел, а не проверять каждую букву, которая может быть напечатана.

Оператор Break

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

Оператор Break в цикле

Когда оператор break используется внутри цикла, то break прекращает работу всего цикла немедленно, и выполнение кода продолжается с первой строки после закрывающей скобки цикла ( > ).

Оператор Break в инструкции Switch

Когда оператор break используется внутри инструкции switch. то он прекращает исполнение кода конкретного случая и перекидывает исполнение на первую строку после закрывающей скобки (>) инструкции switch .

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

Заметка

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

Следующий пример переключается на символьные значение Character и определяет, является ли символ целым числом на одном из четырех языков. Несколько языков включены в каждый случай (case) для краткости:

Этот пример проверяет numberSymbol на наличие в нем целого числа от 1 до 4 на арабском, латинском, китайском или тайском языках. Если совпадение найдено, то один из случаев switch устанавливает опциональную переменную Int. названную possibleIntegerValue в подходящее целочисленное значение.

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

Это не практично перечислять каждое возможное значение Character в примере выше, таким образом случай default улавливает все остальные варианты символов, которые не соответствуют первым четырем случаям. Случаю default не надо предпринимать каких-либо действий, так что там прописан только оператор break. После того как срабатывает случай default. срабатывает и break. что прекращает действие инструкции switch и код продолжает свою работу с if let .

Оператор Fallthrough

Инструкция switch в Swift не проваливается из каждого случая ( case ) в следующий. Напротив, как только находится соответствие с первым случаем, так сразу и прекращается работа всей инструкции. А в языке C, работа инструкции switch немного сложнее, так как требует явного прекращения работы при нахождении соответствия словом break в конце случая, в противном случае при соответствии мы провалимся в следующий случай и так далее пока не встретим слово break. Избежание провалов значит что инструкция switch в Swift более краткая и предсказуемая, чем она же в C, так как она предотвращает срабатывание нескольких случаев по ошибке.

Если вам по какой-то причине нужно аналогичное проваливание как в C, то вы можете использовать оператор fallthrough в конкретном случае. Пример ниже использует fallthrough для текстового описания целого числа:

В примере мы объявляем новую переменную типу String. названную description и присваиваем ей исходное значение. Потом мы определяем величину integerToDescribe. используя инструкцию switch. Если значение integerToDescribe одно из значений списка случая, то мы получаем текстовое описание значение, которое дополняется значением, которое находится в default. так как на уровень выше в сработавшем случае стоит ключевое слово fallthrough. после чего завершается работа инструкции switch .

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

После того как сработала инструкция switch. мы получаем описание числа, используя функцию print(). В нашем примере мы получаем 5. что корректно определено как простое число.

Заметка

Ключевое слово fallthrough не проверяет условие случая, оно позволяет провалиться из конкретного случая в следующий или в default. что совпадает со стандартным поведением инструкции switch в языке C.

Маркированные инструкции

Вы можете размещать циклы или инструкции switch внутри других циклов или switch инструкций, создавая тем самым сложное течение исполнение кода. Однако циклы и инструкции switch могут иметь break. что может прервать выполнение кода преждевременно. В общем иногда полезно явно указывать какой цикл или какую инструкцию switch вы хотите прервать оператором break. Так же, если у вас есть несколько вложенных циклов, то может быть полезным явное указание того, на какой цикл именно будет действовать оператор continue .

Для всех этих целей мы можем маркировать цикл или инструкцию switch маркером инструкций и использовать его вместе с оператором break или оператором continue для предотвращения или продолжения исполнения маркированной инструкции.

Маркированные инструкции обозначаются меткой в той же строке, что и ключевое слово начала инструкции, которое следует после метки через двоеточие. Ниже приведен пример синтаксиса цикла while. хотя принцип работы маркера такой же со всеми инструкциями:

В дальнейшем примере мы будем использовать break. continue с маркированным циклом while для адаптированной версии Змеи и Лестницы. которую вы видели ранее в "Циклы While". В этот раз у нас появилось новое правило:

  • Чтобы победить вы должны попасть точно на клетку 25 .

Если результат броска кубика дает вам ходов более чем на 25 клетку, то вы должны бросить еще раз, до тех пор пока не попадете точно на клетку 25 .

Игровая зона доски осталась такой же как и была:

Величины finalSquare. board. square и diceRoll инициализируются точно так же как и в прошлых примерах игры:

В этой версии игры используется цикл while и инструкция switch для воплощения логики игры. Цикл while маркер названный gameLoop. для индикации главного цикла игры.

Условие цикла while square != finalSquare показывает, что теперь нам нужно попасть строго на клетку 25 :

Игральная кость бросается в начале каждого цикла. Прежде чем двигаться по доске идет проверка в инструкции switch на валидность хода, потом обрабатывает его, если такое движение допустимо:

  • Если игральная кость двигает игрока на последнюю клетку, игра заканчивается. Оператор break с маркером gameLoop перекидывает исполнение кода на первую стоку кода после цикла while. которая и завершает игру.
  • Если игральная кость двигает игрока далее чем на последнюю клетка, то такое движение считается некорректным, и игроку приходится кидать кость еще раз. Оператор continue с маркером gameLoop заканчивает итерацию и начинает новую.
  • Во всех случаях движение игрока на diceRoll клеток допустимо и каждый ход идет проверка логики игры на наличие лестниц и змей. Когда кончается итерация, мы возвращаемся на начало цикла while. где проверяется условие на необходимость дальнейших ходов.
Заметка

Если оператор break не использует маркер gameLoop. то он будет прерывать выполнение инструкции switch. а не всего цикла while. Но используя маркер gameLoop мы можем указать какое исполнение инструкции нужно прервать.

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

C для начинающих

5.4. Инструкция switch

Длинные цепочки инструкций if-else, наподобие приведенной в конце предыдущего раздела, трудны для восприятия и потому являются потенциальным источником ошибок. Модифицируя такой код, легко сопоставить, например, разные else и if. Альтернативный метод выбора одного их взаимоисключающих условий предлагает инструкция switch.
Для иллюстрации инструкции switch рассмотрим следующую задачу. Нам надо подсчитать, сколько раз встречается каждая из гласных букв в указанном отрывке текста. (Общеизвестно, что буква e – наиболее часто встречающаяся гласная в английском языке.) Вот алгоритм программы:

  1. Считывать по одному символу из входного потока, пока они не кончатся.
  2. Сравнить каждый символ с набором гласных.
  3. Если символ равен одной из гласных, прибавить 1 к ее счетчику.
  4. Напечатать результат.

Написанная программа была запущена, в качестве контрольного текста использовался раздел из оригинала данной книги. Результаты подтвердили, что буква e действительно самая частая:

Инструкция switch состоит из следующих частей:

  • ключевого слова switch, за которым в круглых скобках идет выражение, являющееся условием:
  • набора меток case, состоящих из ключевого слова case и константного выражения, с которым сравнивается условие. В данном случае каждая метка представляет одну из гласных латинского алфавита:
  • последовательности инструкций, соотносимых с метками case. В нашем примере с каждой меткой будет сопоставлена инструкция, увеличивающая значение соответствующего счетчика;
  • необязательной метки default, которая является аналогом части else инструкции if-else. Инструкции, соответствующие этой метке, выполняются, если условие не отвечает ни одной из меток case. Например, мы можем подсчитать суммарное количество встретившихся символов, не являющихся гласными буквами:

Константное выражение в метке case должно принадлежать к целому типу, поэтому следующие строки ошибочны:

Кроме того, две разные метки не могут иметь одинаковое значение.
Выражение условия в инструкции switch может быть сколь угодно сложным, в том числе включать вызовы функций. Результат вычисления условия сравнивается с метками case, пока не будет найдено равное значение или не выяснится, что такого значения нет. Если метка обнаружена, выполнение будет продолжено с первой инструкции после нее, если же нет, то с первой инструкции после метки default (при ее наличии) или после всей составной инструкции switch.
В отличие от if-else инструкции, следующие за найденной меткой, выполняются друг за другом, проходя все нижестоящие метки case и метку default. Об этом часто забывают. Например, данная реализация нашей программы выполняется совершенно не так, как хотелось бы:

Если значение ch равно i, выполнение начинается с инструкции после case 'i' и iCnt возрастет на 1. Однако следующие ниже инструкции, ++oCnt и ++uCnt, также выполняются, увеличивая значения и этих переменных. Если же переменная ch равна a, изменятся все пять счетчиков.
Программист должен явно дать указание компьютеру прервать последовательное выполнение инструкций в определенном месте switch, вставив break. В абсолютном большинстве случаев за каждой метке case должен следовать соответствующий break.
break прерывает выполнение switch и передает управление инструкции, следующей за закрывающей фигурной скобкой, – в данном случае производится вывод. Вот как это должно выглядеть:

Если почему-либо нужно, чтобы одна из секций не заканчивалась инструкцией break, то желательно написать в этом месте разумный комментарий. Программа создается не только для машин, но и для людей, и необходимо сделать ее как можно более понятной для читателя. Программист, изучающий чужой текст, не должен сомневаться, было ли нестандартное использование языка намеренным или ошибочным.
При каком условии программист может отказаться от инструкции break и позволить программе провалиться сквозь несколько меток case? Одним из таких случаев является необходимость выполнить одни и те же действия для двух или более меток. Это может понадобиться потому, что с case всегда связано только одно значение. Предположим, мы не хотим подсчитывать, сколько раз встретилась каждая гласная в отдельности, нас интересует только суммарное количество всех встретившихся гласных. Это можно сделать так:

Некоторые программисты подчеркивают осознанность своих действий тем, что предпочитают в таком случае писать метки на одной строке:

В данной реализации все еще осталась одна проблема: как будут восприняты слова типа

Наша программа не понимает заглавных букв, поэтому заглавные U и I не будут отнесены к гласным. Исправить ситуацию можно следующим образом:

Метка default является аналогом части else инструкции if-else. Инструкции, соответствующие default, выполняются, если условие не отвечает ни одной из меток case. Например, добавим к нашей программе подсчет суммарного количества согласных:

isalpha() – функция стандартной библиотеки С; она возвращает true, если ее аргумент является буквой. isalpha() объявлена в заголовочном файле ctype.h. (Функции из ctype.h мы будем рассматривать в главе 6.)
Хотя оператор break функционально не нужен после последней метки в инструкции switch, лучше его все-таки ставить. Причина проста: если мы впоследствии захотим добавить еще одну метку после case, то с большой вероятностью забудем вписать недостающий break.
Условная часть инструкции switch может содержать объявление, как в следующем примере:
switch( int ival = get_response() )
ival инициализируется значением, получаемым от get_response(), и это значение сравнивается со значениями меток case. Переменная ival видна внутри блока switch, но не вне его.
Помещать же инструкцию объявления внутри тела блока switch не разрешается. Данный фрагмент кода не будет пропущен компилятором:

Если бы разрешалось объявлять переменную таким образом, то ее было бы видно во всем блоке switch, однако инициализируется она только в том случае, если выполнение прошло через данную метку case.
Мы можем употребить в этом месте составную инструкцию, тогда объявление переменной file_name будет синтаксически правильным. Использование блока гарантирует, что объявленная переменная видна только внутри него, а в этом контексте она заведомо инициализирована. Вот как выглядит правильный текст:

Упражнение 5.5

Модифицируйте программу из данного раздела так, чтобы она подсчитывала не только буквы, но и встретившиеся пробелы, символы табуляции и новой строки.

Упражнение 5.6

Модифицируйте программу из данного раздела так, чтобы она подсчитывала также количество встретившихся двухсимвольных последовательностей ff, fl и fi.


Упражнение 5.7

Паппас К, Мюррей У

/ Паппас К. Мюррей У. - Visual C++ 6. Руководство разработчика - 2000

o Инструкция break

o Инструкция continue

o Инструкция return

Чтобы приступить к созданию первых программ на языках C/C++, вам следует познакомиться с некоторыми дополнительными средствами программирования. В этой главе будут рассмотрены базовые инструкции, составляющие основу любой программы. Большинство из них вам должно быть хорошо знакомо по другим языкам программирования высокого уровня.

Это такие инструкции, как if, if /else и switch/case, а также циклы for, while и do/while. В то же время ряд инструкций уникален для C/C++, например условный оператор. ключевые слова break и continue. Они не имеют аналогов в более ранних языках программирования, таких как FORTRAN, COBOL или Pascal. По этой причине начинающие программисты часто оставляют их без внимания и не используют в своих программах. В результате остаются невостребованными некоторые уникальные возможности, предоставляемые языками C/C++. Кроме того, это выдает в вас новичка, которому вряд ли доверят работу над серьезным проектом.

В языках C/C++ имеются четыре базовые инструкции выбора: if,if /else, switch/case и оператор. Прежде чем приступить к изучению каждой из них, следует упомянуть об общих принципах построения условных выражений. Инструкции выбора используются для выборочного выполнения определенных блоков программы, состоящих либо из одной строки, либо из нескольких. В первом случае строка не выделяется фигурными скобками, во втором — выделяется весь блок.

Одиночная инструкция if предназначена для выполнения команды или блока команд в зависимости от того, истинно заданное условие или нет. Ниже показан простейший пример инструкции if:

if (условие) выражение;

Обратите внимание, что условие заключается в круглые скобки. Если в результате проверки условия возвращается значение true, то выполняется выражение, после чего управление передается следующей строке программы. Если же результатом условия будет false, то выражение будет пропущено. Перейдем к конкретному примеру. В следующем фрагменте на экран выводится приветствие "Добрый день!" всякий раз, когда значение переменной ioutside_temp оказывается большим или равным 72:

if(ioutside_temp >= 72) printf("Добрыйдень!");

В более сложном случае, когда инструкция if охватывает несколько выполняемых команд, синтаксис немного меняется:

if(условие) <. выражение1; выражение2;

Весь блок команд выделяется фигурными скобками, а каждая строка заканчивается точкой с запятой. Ниже показан пример программы, в которой применяется инструкция if:

* В этой программе на языке С демонстрируется использование инструкции if.

printf("\nВведите число предметов, по которым вы получили оценку ХОРОШО: ");

printf("\nВведите число предметов, по которым получили оценку УДОВЛЕТВОРИТЕЛЬНО: '") ;

fGPA = (inum_As*5 + inum_Bs*4 + inum_Cs*3)/(float)(inum_As + inum_Bs + inum_Cs);

printf("\nВаш средний балл: %5.2f\n",fGPA); if (fGPA >= 4.5)< printf("\nПОЗДРАВЛЯЕМ!\n");

printf ("\nВы прошли по конкурсу."); return(0); >

Обратите внимание, что инструкция if контролирует вывод только поздравительного сообщения, которое отображается, если значение переменной fGPA больше или равно 4,5.

Инструкция if /else позволяет выборочно выполнять одно из двух действий в зависимости от условия. Ниже показан синтаксис данной инструкции:

if (условие) выражение1; else выражение2;

Если проверка условия дает результат true, то выполняется выражение1, в противном случае

if (ckeypressed — UP) iy_pixel_coord++; else iy_pixel_coord--;

В этом фрагменте выполняется увеличение или уменьшение текущей горизонтальной координаты указателя мыши в зависимости от значения переменной ckeypressed (предполагается, что она содержит код нажатой клавиши).

Если операторная часть ветви if или else содержит не одно выражение, а несколько, необходимо заключать их в фигурные скобки, как показано в следующих примерах:

if (условие) ( выражение1; else < выражение2; выражениеЗ; выражение4 ;

if (условие) < выражение1; выражение2; выражениеЗ;

выражение 4; выражение5; выражение 6; >

Обратите внимание, что после закрывающей фигурной скобки точка с запятой не ставится.

В следующем примере демонстрируется использование инструкции if /else:

* В этой программе на языке С демонстрируется использование

* инструкции if /else.

#include <stdio.h> int main ()

int ihow_many, i, imore; while (imore == 1) <

printf ("Введите название товара: "); if (scanf ("%c",&c)!= EOF)

< while (c != '\n') scanf ("%c",&c) ; printf ("Сколько заказано? ");

scanf ("%d",&ihow_many) ; scanf ("%c",&c) ;

for(i= 1; i <= ihow_many; i++) printf ("*");

printf ("\n"); > else imore = 0 ;> return(0); >

Эта программа предлагает пользователю ввести название товара, и, если не получен признак конца файла [Ctrl+C] (EOF), то название будет прочитано буква за буквой, пока не встретится символ конца строки (генерируется при нажатии клавиши [Enter]). В следующей строке отобразится надпись "Сколько заказано?", после которой необходимо ввести число заказанных единиц товара. Затем в цикле for на экран выводится ряд звездочек, количество которых соответствует введенному числу. При обнаружении признака конца файла программный блок ветви if пропускается и выполняется строка программы в ветви else. В этой строке

устанавливается нулевое значение флага imore, что служит признаком завершения программы.

Вложенные инструкции if/else

Если используется несколько вложенных инструкций if, следует тщательно следить, какой из них соответствует ветвь else. Взгляните на следующий пример и попытайтесь определить порядок выполнения команд:

if(itemperature < 50) if(itemperature < 30) printf("Наденьте меховую куртку."); else printf("Наденьте шубу!");

В этом примере мы специально не делали отступов с помощью табуляции, чтобы не давать вам подсказок. Что произойдет, если значение переменной itemperature будет 55? Появится ли сообщение "Наденьте шубу!"? Конечно же, нет. В данном примере ветвь else связана со второй инструкцией if. Дело в том, что компилятор всегда связывает инструкцию else с ближайшей к ней несвязанной инструкцией if.

Безусловно, профессиональный программист должен позаботиться о том, чтобы отступы в программе позволяли четко выявить связи между инструкциями:

if(itemperature < 50) if (itemperature < 30)

printf ("Наденьте меховую куртку."); else printf("Наденьте шубу!");

Еще нагляднее следующая нотация:

if(itemperature < 50) if(itemperature < 30) printf("Наденьте меховую куртку."); else printf("Наденьте шубу!");

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

if(условие1) if(условие2) выражение2; else выражение1 ;

Нетрудно заметить, что выделения отступами в этом примере ошибочны, и данный код ничем не отличается от предыдущего примера. Многие начинающие программисты часто пытаются устанавливать связи внутри блоков путем изменения отступов. Но ведь компилятор не учитывает отступы! Как же сделать так, чтобы выражение1 действительно было связано с условием1, а не условием2?

Чтобы исправить ошибку, необходимо использовать фигурные скобки:

if(условие1) < if (условие.2) выражение2;

С помощью фигурных скобок мы объединили условие2 и выражение2 в единый блок, выполняемый в том случае, если условие1 равно true. В результате ветвь else связывается с, первой, а не со второй инструкцией if.

Конструкция if/else/if используется для того, чтобы последовательно проверить несколько условий. Ее синтаксис выглядит следующим образом:

выражение1; else if(условие2) выражение2; else if (условие3) выражениеЗ;

Каждое выражение может представлять собой не одну строку, а блок команд. В таком случае требуются фигурные скобки (но помните, что после закрывающей фигурной скобки не ставится точка с запятой). В данном примере программа будет проверять условие за условием до тех пор, пока одно из них не возвратит значение true. Как только это произойдет, все остальные операторы else и связанные с ними действия будут пропущены. Если ни одно из условий не равно true, ни одно из действий не будет выполнено.

Теперь рассмотрим слегка видоизмененную версию предыдущего примера:

выражение1; else if(условие2) выражение2; else if(условиеЗ) выражениеЗ; else действие_по_умолчанию;

В данном случае какое-то действие обязательно будет выполнено. Если ни одно из условий не равно true, выполняется действие_по_умолчанию. Чтобы понять, в каких случаях лучше применять эту конструкцию, рассмотрим следующий пример. Здесь переменная fconverted_value содержит значение длины в футах, а переменная econvert_to — признак преобразования. Если значение последней не соответствует ни одному из известных типов преобразования, отображается соответствующее сообщение.

printf ("Преобразование невозможно");

Оператор. позволяет создавать простые однострочные условные выражения, в которых выполняется одно из двух действий в зависимости от значения условия. Данный оператор можно использовать вместо инструкции if /else, а синтаксис его таков:

условие. выражение1. выражение2;

Оператор. называют тернарным, поскольку он требует наличия трех операндов. Рассмотрим пример, в котором определяется модуль числа:

if (f value >= 0.0) fvalue = fvalue; else fvalue = -fvalue;

С помощью условного оператора его можно записать в одну строку: fvalue = (fvalue >= 0.0)? fvalue. -fvalue;

В следующей программе на языке C++ условный оператор применяется для того, чтобы выбрать правильный вид выводимых данных:

// В этой программе на языке C++ демонстрируется использование

#include <math.h> #include <iostream.h> int main() <

float fbalance, fpayment;

cout << "Введите сумму заема: ";

cin >> fbalance;

cout << "\nВведите сумму погашения: "; cin >> fpayment;

cout << "\n\nВаш баланс: ";

cout << ((fpayment > fbalance). "переплачено на $". "уплачено $"); cout << ((fpayment > fbalance). (fpayment - fbalance). fpayment); cout << " по заему на сумму $" << fbalance << ".";

Первый раз условный оператор используется для того, чтобы выяснить, какой текст выводить на экран: "переплачено на $" или "уплачено $". В следующем выражении с условным оператором определяется, какую денежную сумму следует отобразить:

cout << ((fpayment > fbalance). (fpayment - fbalance). fpayment);

Часто возникает необходимость проверить переменную на равенство целому ряду значений. Это можно выполнить либо с помощью конструкции if/else/if, либо с помощью похожей конструкции switch/case. Обратим ваше внимание на то, что инструкция switch в языке С имеет ряд особенностей. Ее синтаксис таков:

саsе константа2: выражение2; break;

case константа-n: выражение-п; break;

Заметьте: инструкция break повторяется во всех ветвях, кроме самой последней. Если, скажем, из первой ветви удалить эту инструкцию, то после выражения1 будет выполняться выражение2, что не всегда желательно. Таким образом, инструкция break отвечает за то, что после выполнения одной из ветвей case все остальные ветви будут пропущены. Рассмотрим несколько примеров.

Предположим, имеется такой фрагмент:

fycoord = 5; else iftemove == SMALL_CHANGE_DOWN) fycoord = -5; else if(emove == LARGE_CHANGE_DP) fycoord = ,10;

Его можно переписать с использованием инструкции switch:

case SMALL_CHANGE_UP: fycoord = 5;

break; case SMALL_CHANGE_DOWN: fycoord = -5;

break; case LARGE_CHANGE_UP: fycoord = 10;

break; default: fycoord = -10;

Здесь значение переменной emove последовательно сравнивается с рядом констант в ветвях case. Если обнаруживается совпадение, переменной fycoord присваивается нужное приращение. Затем выполняется инструкция break, которая передает управление строке, следующей после закрывающей фигурной скобки. Если же ни одно из сравнений не дало результата, то переменной fycoord присваивается значение по умолчанию (-10). Поскольку это последняя строка всего блока, нет необходимости ставить после нее инструкцию break. Следует также упомянуть о том, что ветвь default является необязательной.

Умелое манипулирование инструкциями break позволяет рациональнее строить блоки switch/case, как показано в следующем примере:

* В этой программе на языке С демонстрируется, как рационально

* строить блоки switch/case.

int main () < char с = 'a' ;

int ivowelct = 0, iconstantct = 0; switch(c)

case 'a' case 'A' case 'e' case 'E' case 'i' case 'I' case 'o' case '0' case 'u' case 'U' ivowelct++;

break; default. iconstantct++; return(0);

Если переменная с содержит ASCII-код любой гласной буквы, увеличивается счетчик гласных ivowelct, в противном случае осуществляется приращение счетчика согласных iconstantct.

В других языках высокого уровня допускается объединение в одной проверке всех констант, приводящих к выполнению одного и того же действия. Но в C/C++ требуется, чтобы каждая константа была представлена отдельной ветвью case. Эффект объединения достигается за счет того, что связанные ветви не разделяются инструкциями break.

В следующей программе на языке С инструкция switch используется для организации вызова правильной функции:

* В этой программе на языке С демонстрируются другие возможности

#include <stdio.h> #define QUIT 0 #define BLANK ' '

printf("\nВведите выражение вида (а (оператор) b): "); scanf("%f%c%c%f", &fx, &cblank, &coperator, &fy) ; switch (coperator) <

case '+':printf("ответ= %8.2f\n",fadd(fx, fy)); break; case '-':printf("ответ= %8.2f\n",fsub(fx, fy)); break; case '*':printf("ответ= %8.2f\n",fmul(fx, fy)); break; case '/':printf("ответ= %8.2f\n",fdiv(fx, fy)); break; case 'x': coperator = QUIT;

default. printf("\nОператор не распознан.");>

double fadd (float fx, float fy) < return (fx+ fy) ; >

double fsub (float fx, float fy) < return (fx - fy) ; >

double fmul (float fx, float fy) < return (fx* fy) ; >

double fdiv (float fx, float fy) < return (fx/ fy) ; >

Хотя синтаксис описания и вызова функций может быть еще непонятен вам (с функциями нам предстоит познакомиться в следующей главе), в целом использование инструкции switch в данном примере позволяет сделать текст программы максимально компактным и наглядным. Если пользователь введет какое-нибудь математическое выражение, скажем 10+10 или 23*15, соответствующий оператор (+ или *) будет сохранен в переменной coperator, значение которой затем сравнивается в блоке switch с набором стандартных арифметических операторов. Если же вместо арифметического оператора введен символ х, то программа присвоит переменной coperator значение quit, что является признаком завершения цикла, а с ним и всей программы.

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

В языке C++ инструкция switch используется аналогичным образом, в чем можно убедиться на следующем примере:

// В этой программе на языке C++ демонстрируется использование

// инструкции switch для создания ежегодного календаря. #include <fstream.h>

int jan_l_start_day, num_days_per_month, month, date, year; bool leap_year_flag;

cout << "Укажите, на какой день недели приходится 1-е января\n"; cout << "\n(0— понедельник,";

cout << "\n 1 — вторник и т.д.): "; cin >> jan_l_start_day;

cout << "\nВведите год, для которого вы хотите построить календарь:”;

for (date = 1; date < jan_l_start_day*4; date++) fout << " ";

for (date = 1; date <= num_days_per_month; date++) < fout.width.(3) ;

if ((date+ jan_l_start_day) % 7 > 0) fout << " ";

jan_l_start_day = (jan_l_start_day + num_days_per_month) % 7;

fout.close () ; return (0);

Программа начинает свою работу с того, что предлагает пользователю указать день недели, на который приходится 1-е января (0 соответствует понедельнику, 1 — вторнику и т.д.) Далее программа просит указать год, для которого вы. хотите построить календарь. Введенное значение отображается в виде заголовка календаря и сохраняется в переменной year. Выполнив ряд проверок, программа определяет, является ли введенный год високосным или нет, и сохраняет результат в переменной leap_year_flag (високосным является год, номер которого делится на 4, но не делится на 100, а также год, номер которого делится на 400).

Затем запускается цикл for, выполняющийся 12 раз — по одному разу для каждого месяца. Сначала выводится название месяца, а в переменную num_days_per_month записывается количество дней в данном месяце. Это осуществляется в блоке switch/case, состоящем из 12ти ветвей. Вслед за этим отображаются заголовки дней недели и в отдельной строке — ряд пробелов, чтобы начать выводить числа с того дня, на который приходится 1-е число данного месяца. В последнем цикле for выводятся собственно номера дней месяца. В последней строке внешнего цикла for вычисляется порядковый номер дня недели первого числа следующего месяца.

Совместное использование конструкций if/else/if и switch/case

В следующем примере выполняется преобразование имеющегося значения длины в футах в значение другой системы измерений:

* В этой программе на языке С демонстрируется использование

* конструкции if /else/if в сочетании с конструкцией switch/ case.