7.8 – Инструкции do while

Добавлено 29 мая 2021 в 13:45

Рассмотрим случай, когда мы хотим показать пользователю меню и попросить его сделать выбор; и, если пользователь сделает неверный выбор, спросить его снова. Ясно, что меню и выбор должны находиться внутри какого-то цикла (чтобы мы могли продолжать спрашивать пользователя, пока он не введет правильное значение), но какой цикл мы должны выбрать?

Поскольку цикл while вычисляет условие заранее, он будет неудобен. Решить проблему можно так:

#include <iostream>
 
int main()
{
    // selection должна быть объявлена вне цикла while, чтобы мы могли использовать ее позже
    int selection{ 0 };
 
    while (selection != 1 && selection != 2 &&
        selection != 3 && selection != 4)
    {
        std::cout << "Please make a selection: \n";
        std::cout << "1) Addition\n";
        std::cout << "2) Subtraction\n";
        std::cout << "3) Multiplication\n";
        std::cout << "4) Division\n";
        std::cin >> selection;
    }
 
    // здесь что-то делаем с selection
    // например, оператор switch
 
    std::cout << "You selected option #" << selection << "\n";
 
    return 0;
}

Но это работает только потому, что наше начальное значение 0 для selection не входит в набор допустимых значений (1, 2, 3 или 4). Что, если бы 0 был корректным выбором? Нам пришлось бы выбрать другой инициализатор для представления «недопустимого» значения – и теперь мы вводим в наш код магические числа (4.13 – Литералы).

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

#include <iostream>
 
int main()
{
    int selection { 0 };
    bool invalid { true }; // новая переменная только для выхода из цикла
 
    while (invalid)
    {
        std::cout << "Please make a selection: \n";
        std::cout << "1) Addition\n";
        std::cout << "2) Subtraction\n";
        std::cout << "3) Multiplication\n";
        std::cout << "4) Division\n";
 
        std::cin >> selection;
        invalid = (selection != 1 && selection != 2 &&
            selection != 3 && selection != 4);
    }
 
    // здесь что-то делаем с selection
    // например, оператор switch
 
    std::cout << "You selected option #" << selection << "\n";
 
    return 0;
}

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

Инструкции do while

Чтобы помочь решить проблемы, подобные описанным выше, C++ предлагает оператор do-while:

do
    инструкция;
while (условие);

Оператор do while – это конструкция цикла, которая работает так же, как цикл while, за исключением того, что инструкция всегда выполняется хотя бы один раз. После выполнения инструкции цикл do-while проверяет условие. Если условие истинно, последовательность выполнения возвращается к началу цикла do-while и выполняет его снова.

Вот наш пример выше с использованием цикла do-while вместо цикла while:

#include <iostream>
 
int main()
{
    // selection должна быть объявлена вне do-while, чтобы мы могли использовать ее позже
    int selection{};
 
    do
    {
        std::cout << "Please make a selection: \n";
        std::cout << "1) Addition\n";
        std::cout << "2) Subtraction\n";
        std::cout << "3) Multiplication\n";
        std::cout << "4) Division\n";
        std::cin >> selection;
    }
    while (selection != 1 && selection != 2 &&
        selection != 3 && selection != 4);
 
    // здесь что-то делаем с selection
    // например, оператор switch
 
    std::cout << "You selected option #" << selection << "\n";
 
    return 0;
}

Таким образом, мы избежали как магических чисел, так и дополнительных переменных.

В приведенном выше примере стоит обсудить то, что переменная selection должна быть объявлена ​​вне блока do. Если бы переменная selection была объявлена ​​внутри блока do, она была бы уничтожена при завершении блока do, что происходит до того, как будет вычислено условие. Но эта переменная нужна нам в условном выражении while – следовательно, переменная selection должна быть объявлена ​​вне блока do (даже если она не будет использоваться в теле функции позже).

На практике циклы do-while используются нечасто. Расположение условного выражения в нижней части цикла скрывает условие цикла, что может привести к ошибкам. В результате многие разработчики рекомендуют вообще избегать циклов do-while. Мы займем более мягкую позицию и выступим за то, чтобы при равном выборе предпочтение было отдано циклам while, а не do-while.

Лучшая практика


При равном выборе отдавайте предпочтение циклам while, вместо do-while.

Теги

C++ / CppLearnCppwhileДля начинающихОбучениеПрограммированиеЦикл

На сайте работает сервис комментирования DISQUS, который позволяет вам оставлять комментарии на множестве сайтов, имея лишь один аккаунт на Disqus.com.

В случае комментирования в качестве гостя (без регистрации на disqus.com) для публикации комментария требуется время на премодерацию.