Ветвление в программе. Вложенные условные операторы. Оператор множественного выбора

Вложенные условные операторы

Когда требуется последовательно перепроверять несколько взаимоисключающих условий, для частей else не открывают отдельного блока (записывают следующий if как простую, а не как составную инструкцию), чтобы получить более компактную запись. Такие конструкции в коде называют else…if.

Рассмотрим сначала вариант записи со вложенными блоками. Для примера рассмотрим следующую задачу.

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

  1. Если указан возраст от 18 и до 27 лет, то сообщать, что заполняющий подлежит призыву на срочную службу или может служить по контракту.
  2. Если указан возраст от 28 до 59 лет, то сообщать, что заполняющий может служить по контракту.
  3. Если указан возраст менее 18 или более 59 лет, то сообщать о том, что заполняющий находится в непризывном возрасте.
  4. Если указан неположительный возраст или возраст более 100 лет, то сообщить об ошибке.

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

if (n>=18 && n<27) {
    System.out.println("Вы можете пройти срочную или контрактную службу");
} else {
    if (n>=27 && n<60) {
        System.out.println("Вы можете служить только по контракту");
    } else {
        if (n>0 && n<=100) {
            System.out.println("Вы находитесь в непризывном возрасте");
        } else {
            System.out.println("Скорее всего, вы допустили ошибку и неверно указали возраст");
        }
    }
}

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

Более того, для сообщения о непризывном возрасте условие подобрано с учётом того, что заполняющий анкету уже не подошёл ни к одному из вариантов призывного возраста. Конечно, можно было бы использовать вот такое условие:

n>0 && n<18 || n>=60 && n<=100

Но оно было бы избыточным, ведь ранее (за счёт выше стоящих проверок) мы уже убедились, что переменная n не попала в промежуток [18;60). Если бы переменная попадала в промежуток, то вывелось бы сообщение «Вы можете пройти срочную или контрактную службу» или «Вы можете служить только по контракту».

Но для случая, когда проверяется последовательность условий можно (но не необходимо) использовать более компактную запись, где содержание каждого else кроме последнего не оформляется в виде отдельного блока. Тот же фрагмент кода с учётом этой возможности может записываться так:

if (n>=18 && n<27) {
    System.out.println("Вы можете пройти срочную или контрактнуню службу");
} else if (n>=27 && n<60) {
    System.out.println("Вы можете служить только по контракту");
} else if (n>0 && n<=100) {
    System.out.println("Вы находитесь в непризывном возрасте");
} else {
    System.out.println("Скорее всего, вы допустили ошибку и неверно указали возраст");
}

Оператор множественного выбора

Инструкция множественного выбора switch позволяет выполнять различные части программы в зависимости от того, какое значение будет иметь некоторая целочисленная переменной (её называют «переменной-переключателем», а «switch» с английского переводится как раз как «переключатель»).

Схема инструкции такова:

switch (переключатель)  {
  case значение1:
    инструкция1;
    break;
  case значение2:
    инструкция2;
    break;
  …
  default:
    инструкция_по_умолчанию;
}

Рассмотрим все элементы оператора:

Рассмотрим такую ситуацию: в какой-то момент требуется просить у пользователя, надо ли продолжать программу или можно её завершить. Предположим, что ответ пользователя принимается в виде символа, вводимого с клавиатуры и сохраняемого в переменной ans: Д — да, продолжать, Н — нет, остановить.

Тогда получаем примерно такой программный код:

switch(ans) {
    case 'Д':
        System.out.println("Продолжаем программу");
        break;
    case 'Н':
        System.out.println("Останавливаем программу");
        break;
}

Если мы захотим как-то оповестить пользователя о том, что он ввёл неподходящий символ, то пригодится метка default:

switch(ans) {
    case 'Д':
        System.out.println("Продолжаем программу");
        break;
    case 'Н':
        System.out.println("Останавливаем программу");
        break;
    default:
        System.out.println("Вы ввели неподходящий символ");
}

После инструкций причастных к этой метке break обычно не ставят, потому что default располагается в конце всего блока switch и после неё всё равно завершится оператор множественного выбора. Но в остальных ветках — break необходим. Рассмотрим пример, в котором по ошибке пропущен первый break в ситуации, когда в переменной-переключателе будет находится символ «Д»:

char ans = 'Д';
switch(ans) {
    case 'Д':
        System.out.println("Продолжаем программу");
    case 'Н':
        System.out.println("Останавливаем программу");
        break;
    default:
        System.out.println("Вы ввели неподходящий символ");
}

На экран будут выведены сразу две фразы: «Продолжаем программу» и «Останавливаем программу». Это случилось потому, что после первой ветки с литералом «Д» программа выполнялась до первого встреченного break, т.е. выполнилась и часть, относящаяся к ветке с литералом «Н».

Такое поведение программы можно использовать во благо. Например, можно разместить несколько подряд идущих меток с разными литералами, для которых будет выполняться один и тот же код:

switch(ans) {
    case 'Д':
    case 'д':
    case 'Y':
    case 'y':                
        System.out.println("Продолжаем программу");
    case 'Н':
    case 'н':                
    case 'N':                
    case 'n':                                
        System.out.println("Останавливаем программу");
        break;
    default:
        System.out.println("Вы ввели неподходящий символ");
}

Теперь пользователь для продолжения программы сможет ввести не только символ «Д», но и символы «д», «Y», «y» (от английского «yes»).

Любой оператор switch можно заменить конструкцией if…else:

if (ans=='Д' || ans=='д' || ans=='Y' || ans=='y') {                
    System.out.println("Продолжаем программу");
} else if (ans=='Н' || ans=='н' || ans=='N' || ans=='n') {                                
    System.out.println("Останавливаем программу");
} else {
    System.out.println("Вы ввели неподходящий символ");
}

Обратное — неверно, ведь switch позволяет только сравнивать переключатель с конкретными значениями, но не позволяет для какой-то из веток задать условие в виде целого диапазона значений с использованием операторов сравнения (например, с использованием строгих неравенств и логических операторов «и» или «или»). Также напомним, что в качестве переключателя могут выступать только целочисленные переменные или выражения.

if…else более универсальный оператор, чем switch.

Задачи

  1. Создать программу, которая будет проверять попало ли случайно выбранное из отрезка [5;155] целое число в интервал (25;100) и сообщать результат на экран.

    Примеры работы программы:

    Число 113 не содержится в интервале (25,100)
    Число 72 содержится в интервале (25,100)
    Число 25 не содержится в интервале (25,100)
    Число 155 не содержится в интервале (25,100)
  2. Создать программу, выводящую на экран случайно сгенерированное трёхзначное натуральное число и его наибольшую цифру.

    Примеры работы программы:

    В числе 208 наибольшая цифра 8
    В числе 774 наибольшая цифра 7
    В числе 613 наибольшая цифра 6
  3. В три переменные a, b и c явно записаны программистом три целых попарно неравных между собой числа. Создать программу, которая переставит числа в переменных таким образом, чтобы при выводе на экран последовательность a, b и c оказалась строго возрастающей.

    Числа в переменных a, b и c: 3, 9, -1
    Возрастающая последовательность: -1, 3, 9
    Числа в переменных a, b и c: 2, 4, 3
    Возрастающая последовательность: 2, 3, 4
    Числа в переменных a, b и c: 7, 0, -5
    Возрастающая последовательность: -5, 0, 7
  4. На некотором предприятии инженер Петров создал устройство, на табло которого показывается количество секунд, оставшихся до конца рабочего дня. Когда рабочий день начинается ровно в 9 часов утра — табло отображает «28800» (т.е. остаётся 8 часов), когда времени 14:30 — на табло «9000» (т.е. остаётся два с половиной часа), а когда наступает 17 часов — на табло отображается «0» (т.е. рабочий день закончился).

    Программист Иванов заметил, как страдают офисные сотрудницы — им неудобно оценивать остаток рабочего дня в секундах. Иванов вызвался помочь сотрудницам и написать программу, которая вместо секунд будет выводить на табло понятные фразы с информацией о том, сколько полных часов осталось до конца рабочего дня. Например: «осталось 7 часов», «осталось 4 часа», «остался 1 час», «осталось менее часа».

    Итак, в переменную n должно записываться случайное (на время тестирования программы) целое число из [0;28800], далее оно должно выводиться на экран (для Петрова) и на следующей строке (для сотрудниц) должна выводиться фраза о количестве полных часов, содержащихся в n секундах.

    Примеры работы программы:

    23466
    Осталось 6 часов
    10644
    Осталось 2 часа
    5891
    Остался 1 час
    1249
    Осталось менее часа