Рубріки: Теория

Цикл с постусловием: принцип работы и примеры кода

Андрій Денисенко

Для повторения последовательности действий в программировании используются циклы. Существует несколько видов циклов. Эта статья посвящена циклу, который выполняется по крайней мере один раз и повторяется, пока истинно условие, которое указано после его тела. Это цикл с постусловием.

Что такое цикл с постусловием

Цикл с постусловием — это последовательность действий, которая выполняется как минимум один раз и повторяется, пока указанное в конце условие истинно.

Задачи и принцип работы цикла с постусловием

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

Цикл с постусловием работает по следующей схеме:

  • производится вход в цикл и выполняются инструкции, составляющие его тело;
  • выполняемые действия изменяют истинность постусловия;
  • после завершения итерации (повторения) проверяется истинность условия;
  • если условие выполняется, то тело цикла выполняется снова;
  • иначе происходит выход из цикла.

Примеры работы цикла с постусловием

Цикл с постусловием на разных языках программирования выглядит так:

C, C++, C#, Java, JavaScript и другие C-подобные языки

    do {
        <тело цикла>
    } while (<условие>);

Pascal

В Pascal вместо конструкции do ... while используется конструкция repeat ... until. Тело цикла выполняется один раз и повторяется не пока условие истинно, а пока оно не станет истинным. Когда при очередной проверке устанавливается, что условие истинно, производится выход из цикла.

repeat  
    <тело цикла> 
until <условие выхода>;

Python

Цикл с постусловием не реализован в Python. Поведение цикла с постусловием можно сымитировать, например, следующими двумя способами (в обоих реализован цикл repeat ... until, поскольку указывается условие выхода, а не продолжения).

Бесконечный цикл с принудительным выходом по break:

while True:
    <тело цикла>
    if <условие выхода>:
        break

Явная вставка тела цикла перед конструкцией цикла:

<тело цикла>
while not <условие выхода>:
    <тело цикла>

Простой цикл

Рассмотрим выполнение простого цикла с постусловием подробнее. Допустим, требуется выводить в консоли значение переменной i, пока оно меньше или равно 7. На C этот цикл можно записать так:

#include<stdio.h>  
int main(){    
    int i=3;      
    do{    
        printf("%d \n",i);    
        i++;    
    }while(i<=7);   
    return 0;  
}

Вывод будет таким:

3
4
5
6
7

Давайте посмотрим, что происходит при выполнении этого кода.

Итерация i i <= 7
1 3 True
2 4 True
3 5 True
4 6 True
5 7 True
6 8 False
  • Итерация 1. Сначала переменная i содержит значение 3, поэтому условие i <= 7 равно True. Выполняется вход в тело цикла. Выводится значение i (3), а затем оно увеличивается на 1. Цикл запускается снова.
  • Итерация 2. Теперь переменная i содержит значение 4, поэтому условие i <= 7 равно True. Выполняется вход в тело цикла. Выводится значение i (4), а затем оно увеличивается на 1. Цикл запускается снова.
  • Итерация 3. Теперь переменная i содержит значение 5, поэтому условие i <= 7 равно True. Выполняется вход в тело цикла. Выводится значение i (5), а затем оно увеличивается на 1. Цикл запускается снова.
  • Итерация 4. Теперь переменная i содержит значение 6, поэтому условие i <= 7 равно True. Выполняется вход в тело цикла. Выводится значение i (6), а затем оно увеличивается на 1. Цикл запускается снова.
  • Итерация 5. Теперь переменная i содержит значение 7, поэтому условие i <= 7 равно True. Выполняется вход в тело цикла. Выводится значение i (7), а затем оно увеличивается на 1. Цикл запускается снова.
  • Итерация 6. Теперь переменная i содержит значение 8, поэтому условие i <= 7 равно False. Поскольку условие не истинно, происходит выход из цикла.

Последовательность Фибоначчи

Рассмотрим работу цикла с постусловием на примере вывода N указанных пользователем первых чисел Фибоначчи.

Последовательность Фибоначчи — это последовательность, в которой каждое очередное число является суммой предыдущих двух. Обычно эта последовательность начинается с нуля, но в некоторых источниках ее начинают с 1 и 1 или с 1 и 2 (как делал и сам Фибоначчи).

Вот первые десять чисел этой последовательности:

0, 1, 1, 2, 3, 5, 8, 13, 21, 34

Пример кода составления последовательности Фибоначчи на Java

import java.util.*;

class Fibonacci
{
    public static void main (String[] args) throws java.lang.Exception
    {
        // Get user input and convert it to an integer
        System.out.print("How many Fibonacci values would you print? ");
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();

        // Initialize variables
        int index = 1; // Loop counter
        int prev1 = 1; // The previous number
        int prev2 = 0; // The number before the previous number

        do{
            System.out.println(prev2);

            // Calculate the next value
            int next = prev1 + prev2;
            // Move the previous back and set the previous to the current value
            prev2 = prev1;
            prev1 = next;

            // Increment index
            index++;

        }while(index <= n); // Check the condition
    }
}

Пример кода составления последовательности Фибоначчи на Python

# Get user input and convert it to an integer
n = int(input("How many Fibonacci values would you like to print? "))

# Initialize variables
index = 1 # Loop counter
prev1 = 1 # The previous number
prev2 = 0 # The number before the previous number

while(True):
    print(prev2)

    # Calculate the next value
    next = prev1 + prev2

    # Move the previous back and set the previous to the current value
    prev2 = prev1
    prev1 = next

    # Increment index
    index += 1

    # Check the condition
    if index > n:
        break

Вывод:

Программы с меню

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

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

import java.util.*;
import java.time.LocalDate;
import java.time.LocalTime;

class Menu
{
    public static void main (String[] args) throws java.lang.Exception
    {
        boolean exitLoop = false;

        do
        {
            System.out.println("Choose an operation below.");
            System.out.println("1. Print current date.");
            System.out.println("2. Print current time.");
            System.out.println("3. Exit.");
            System.out.print("Your choice > ");

            Scanner scanner = new Scanner(System.in);

            String n = scanner.nextLine();

            switch (n){
                case "1":
                    LocalDate d = LocalDate.now();
                    System.out.println(d);
                    break;
                case "2":
                    LocalTime t = LocalTime.now();
                    System.out.println(t);
                    break;
                case "3":
                    exitLoop = true;
                    break;
                default:
                    System.out.print("Wrong input.");
            }
            System.out.println();
        } while(!exitLoop);
    }
}

Результат:

Игровой цикл

Еще одним примером использования цикла с постусловием может послужить игра.

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

Пример кода игры с бросанием кубика на Java

import java.util.*;

public class RollADie
{
    private void greet()
    {
        System.out.println();
        System.out.println("*".repeat(52));
        System.out.println("Welcome to The Roll A Die Game");
        System.out.println("*".repeat(52));
    }

    private boolean continueGame()
    {
        System.out.println();
        System.out.print("Enter 'Y' to roll a die again or anything else to exit: ");
        Scanner scanner = new Scanner(System.in);

        String n = scanner.nextLine();
        return n.equalsIgnoreCase("Y");
    }

    private void gameLoop()
    {

        // Get user input and check for errors
        int guess = 0;
        System.out.print("Your guess: ");
        Scanner scanner = new Scanner(System.in);

        final Random random = new Random();

        try
        {
            guess = scanner.nextInt();
        } catch (Exception e) {
            guess = 0;
        }

        if (guess < 1 || guess > 6){
            System.out.println("Wrong value. Must be from 1 to 6.");
        } else {
            // The user input lies between 1 and 6. Roll the dice.
            int r = random.nextInt(6) + 1;

            // Answer the user
            if (r == guess){
                System.out.println("You win! It's " + r);
            } else {
                System.out.println("You lose! It's " + r);
            }
        }
    }

    public static void main (String[] args) throws java.lang.Exception
    {
        RollADie r = new RollADie();
        r.greet();

        do {
            // Execute the loop body if the precondition is satisfied
            r.gameLoop();
        } while (r.continueGame());
    }
}

Результат:

Цикл с пустым телом

Цикл с постусловием может быть «пустотелым». Пустые циклы используются, когда вычисления производятся в условии цикла, как в следующем примере на Java:

import java.util.*;

class Empty
{
    public static void main (String[] args) throws java.lang.Exception
    {
        int i, j;
        i = 20;
        j = 40;

        do{
            ;
        }while (++i < --j);
        System.out.println("Average is " + i);
    }
}

В этом примере перед каждым вычислением условия цикла производится увеличение i на единицу и уменьшение j на единицу. Это делается с помощью преинкремента (++i) и предекремента (--j).

Бесконечный цикл

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

Рассмотрим такой пример на Java:

import java.util.*;
class InfiniteLoop
{
    public static void main (String[] args)
    {
        int i = 10;
        do{
            System.out.println(i);
            i--;
        } while (i > 0);
    }
}

Этот код будет выводить в консоли числа от 10 до 1:

10
9
8
7
6
5
4
3
2
1

Но если пропущен декремент (уменьшение счетчика на единицу), то цикл будет бесконечно выводить десятку. Чтобы убедиться в этом, закомментируем строку с декрементом:

import java.util.*;
class InfiniteLoop
{
    public static void main (String[] args)
    {
        int i = 10;
        do{
            System.out.println(i);
            // i--;
        } while (i > 0);
    }
}

Вывод:

10
10
10
10
10
10
10
10
10
...

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

Принудительный выход из цикла

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

Рассмотрим пример программы с циклом обработки сообщений на языке C:

do
{
    bRet = GetMessage(&msg, NULL, 0, 0);

    if (bRet > 0)  // (Such a message must be processed.)
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    else if (bRet < 0)  // (Return code -1 indicates an error.)
    {
        // Handle the error.
        // ...
    }
    else  // (Return code 0 indicates "exit".)
    {
        break;
    }
} while (1);

В этом фрагменте:

  • запускается цикл;
  • принимается сообщение, и в зависимости от него выполняется ветвление:
    • если значение, возвращенное функцией GetMessage (код возврата), больше нуля, то он соответствует сообщению, которое нужно обработать;
    • если код возврата меньше нуля, то произошла ошибка, и ее нужно обработать, а потом, возможно, выйти из программы;
    • если код возврата равен нулю, то производится выход из программы с помощью оператора break;
  • если выхода из цикла не было, то он повторяется (1 рассматривается как булевское значение true).

Когда в цикле используется переменная и ее значение изменено так, что значение условия становится ложным, то после этого цикл выполняется до конца.

Оператор break используют, чтобы принудительно выйти из цикла после строки с этим оператором.

Особенности цикла с постусловием

Сравнение цикла с постусловием с другими видами циклов:

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

Заключение

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

Некоторые языки позволяют использовать цикл с пустым телом. В этой конструкции вычисления выполняются в условии цикла.

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

Останні статті

Обучение Power BI – какие онлайн курсы аналитики выбрать

Сегодня мы поговорим о том, как выбрать лучшие курсы Power BI в Украине, особенно для…

13.01.2024

Work.ua назвал самые конкурентные вакансии в IТ за 2023 год

В 2023 году во всех крупнейших регионах конкуренция за вакансию выросла на 5–12%. Не исключением…

08.12.2023

Украинская IT-рекрутерка создала бесплатный трекер поиска работы

Unicorn Hunter/Talent Manager Лина Калиш создала бесплатный трекер поиска работы в Notion, систематизирующий все этапы…

07.12.2023

Mate academy отправит работников в 10-дневный оплачиваемый отпуск

Edtech-стартап Mate academy принял решение отправить своих работников в десятидневный отпуск – с 25 декабря…

07.12.2023

Переписки, фото, история браузера: киевский программист зарабатывал на шпионаже

Служба безопасности Украины задержала в Киеве 46-летнего программиста, который за деньги устанавливал шпионские программы и…

07.12.2023

Как вырасти до сеньйора? Девелопер создал популярную подборку на Github

IT-специалист Джордан Катлер создал и выложил на Github подборку разнообразных ресурсов, которые помогут достичь уровня…

07.12.2023