Урок №67. Цикл while | Уроки С++

  Обновл. 26 Апр 2019  | 

В этом уроке мы детально рассмотрим цикл while, его конструкцию, особенности и использование.

Цикл while

Цикл while является самым простым из четырёх циклов, которые есть в C++, и очень похож на ветвление if/else:

while (условие)
    тело цикла;

Цикл while объявляется с использованием ключевого слова while. В начале цикла обрабатывается условие. Если его значением является true (любое ненулевое значение), то тогда выполняется тело цикла.

Однако, в отличие от оператора if, после завершения выполнения тела цикла, управление возвращается обратно к while и процесс проверки условия повторяется. Если условие опять является true, то тогда тело цикла выполняется ещё раз.

Например, следующая программа выводит все числа от 0 до 9:

#include <iostream>

int main()
{
int count = 0;
while (count < 10)
{
std::cout << count << » «;
++count;
}
std::cout << «done!»;

return 0;
}



#include <iostream>

int main()

{

    int count = 0;

    while (count < 10)

        {

        std::cout << count << » «;

        ++count;

        }

    std::cout << «done!»;

    return 0;

}

Результат выполнения программы выше:

0 1 2 3 4 5 6 7 8 9 done!

Рассмотрим детальнее эту программу. Во-первых, инициализируется переменная: int count = 0;. Условие 0 < 10 имеет значение true, поэтому выполняется тело цикла. В первом стейтменте мы выводим 0, а во втором выполняем инкремент переменной count. Затем управление возвращается к началу цикла while для повторной проверки условия. Условие 1 < 10 имеет значение true, поэтому тело цикла выполняется ещё раз. Тело цикла будет повторно выполняться до тех пор, пока переменная count не будет равна 10, только в том случае, когда результат условия 10 < 10 будет false, цикл завершится.

Цикл while может и вообще не выполняться. Например:

#include <iostream>

int main()
{
int count = 15;
while (count < 10)
{
std::cout << count << » «;
++count;
}
std::cout << «done!»;

return 0;
}



#include <iostream>

int main()

{

    int count = 15;

    while (count < 10)

        {

        std::cout << count << » «;

        ++count;

        }

    std::cout << «done!»;

    return 0;

}

Условие 15 < 10 сразу принимает значение false, и тело цикла пропускается. Единственное, что выведет эта программа:

done!

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

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

#include <iostream>

int main()
{
int count = 0;
while (count < 10) // это условие никогда не будет false
std::cout << count << » «; // поэтому эта строка будет выполняться постоянно

return 0; // а эта строка никогда не выполнится
}



#include <iostream>

int main()

{

    int count = 0;

    while (count < 10) // это условие никогда не будет false

        std::cout << count << » «; // поэтому эта строка будет выполняться постоянно

    return 0; // а эта строка никогда не выполнится

}

Поскольку переменная count не увеличивается на единицу в этой программе, то условие count < 10 всегда будет true. Следовательно, цикл никогда не будет завершён, и программа будет постоянно выводить 0 0 0 0 0 ... .

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

while (1) // или while (true)
{
// Этот цикл будет выполняться бесконечно
}



while (1) // или while (true)

{

  // Этот цикл будет выполняться бесконечно

}

Единственный способ выйти из бесконечного цикла — использовать операторы return, break, exit, goto или выбросить исключение.

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

Счётчик цикла while

Часто нам нужно будет, чтобы цикл выполнялся определённое количество раз. Для этого обычно используется переменная в виде счётчика цикла. Счётчик цикла — это целочисленная переменная, которая объявляется с единственной целью: считать, сколько раз выполнился цикл. В примерах выше переменная count является счётчиком цикла.

Счётчикам цикла часто дают простые имена, такие как i, j или k. Однако, в этих именах есть одна серьёзная проблема. Если вы захотите узнать, где в вашей программе используется счётчик цикла и воспользуетесь функцией поиска i, j или k, то в результате получите половину своей программы, так как i, j или k используются во многих именах. Следовательно, лучше использовать iii, jjj или kkk в качестве имён для счётчиков. Они более уникальны, их значительно проще найти, и они выделяются в коде. А ещё лучше использовать «реальные» имена для переменных, например, count или любое другое имя, которое предоставляет контекст использования этой переменной.

Также для счётчиков цикла лучше использовать тип signed int. Использование unsigned int может привести к неожиданным результатам. Например:

#include <iostream>

int main()
{
unsigned int count = 10;

// Считаем от 10 к 0
while (count >= 0)
{
if (count == 0)
std::cout << «blastoff!»;
else
std::cout << count << » «;
—count;
}

return 0;
}


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

#include <iostream>

int main()

{

    unsigned int count = 10;

    // Считаем от 10 к 0

    while (count >= 0)

    {

        if (count == 0)

            std::cout << «blastoff!»;

        else

            std::cout << count << » «;

        —count;

    }

    return 0;

}

Взгляните на программу выше ещё раз и постарайтесь обнаружить ошибку.

Оказывается, эта программа представляет собой бесконечный цикл. Она начинается с вывода 10 9 8 7 6 5 4 3 2 1 blastoff! как и предполагалось, но затем уходит с рельсов и начинает отсчёт с 4294967295. Почему? Потому что условие цикла count >= 0 никогда не будет ложным! Когда count = 0, то и условие 0 >= 0 имеет значение true, выводится blastoff, а затем выполняется декремент переменной count, происходит переполнение и значением переменной становится 4294967295. И так как условие 4294967295 >= 0 является истинным, то программа продолжает своё выполнение. А поскольку счётчик цикла является типа unsigned, то он никогда не сможет быть отрицательным, и поскольку он никогда не сможет быть отрицательным, то цикл никогда не завершится.

Правило: Всегда используйте тип signed int для счётчиков цикла.

Итерации

Каждое выполнение цикла называется итерацией (или ещё «повтором»).

Поскольку тело цикла обычно является блоком, и поскольку этот блок выполняется по новой с каждым повтором, то любые переменные, объявленные внутри тела цикла, создаются, а затем и уничтожаются по новой. В следующем примере переменная z создаётся и уничтожается 6 раз:

#include <iostream>

int main()
{
int count = 1;
int result = 0; // переменная result определена здесь, поскольку она нам понадобится позже (вне тела цикла)

while (count <= 6) // итераций будет 6
{
int z; // z создаётся здесь по новой с каждой итерацией

std::cout << «Enter integer #» << count << ‘:’;
std::cin >> z;

result += z;

// Увеличиваем значение счётчика цикла на единицу
++count;
} // z уничтожается здесь по новой с каждой итерацией

std::cout << «The sum of all numbers entered is: » << result;

return 0;
}


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

#include <iostream>

int main()

{

    int count = 1;

    int result = 0; // переменная result определена здесь, поскольку она нам понадобится позже (вне тела цикла)

    while (count <= 6) // итераций будет 6

    {

        int z; // z создаётся здесь по новой с каждой итерацией

        std::cout << «Enter integer #» << count << ‘:’;

        std::cin >> z;

        result += z;

        // Увеличиваем значение счётчика цикла на единицу

        ++count;

    } // z уничтожается здесь по новой с каждой итерацией

    std::cout << «The sum of all numbers entered is: » << result;

    return 0;

}

Для фундаментальных типов переменных это нормально. Для не фундаментальных типов переменных (таких как структуры или классы) это может сказаться на производительности. Следовательно, не фундаментальные типы переменных лучше определять перед циклом.

Обратите внимание, переменная count объявлена вне тела цикла. Это важно и необходимо, поскольку нам нужно, чтобы значение переменной сохранялось на протяжении всех итераций (не уничтожалось по новой с каждым повтором цикла).

Иногда нам может быть нужно выполнить что-то при достижении определённого количества итераций, например, вставить символ новой строки. Это легко осуществить, используя оператор остатка от деления со счётчиком цикла:

#include <iostream>

int main()
{
int count = 1;
while (count <= 50)
{
// Выводим числа до 10 (добавляем к каждому числу 0)
if (count < 10)
std::cout << «0» << count << » «;
else
std::cout << count << » «; // выводим остальные числа

// Если счётчик цикла делится на 10 без остатка, то тогда вставляем символ новой строки
if (count % 10 == 0)
std::cout << «\n»;

// Увеличиваем значение счётчика цикла на единицу
++count;
}

return 0;
}


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

#include <iostream>

int main()

{

    int count = 1;

    while (count <= 50)

    {

        // Выводим числа до 10 (добавляем к каждому числу 0)

        if (count < 10)

            std::cout << «0» << count << » «;

        else

            std::cout << count << » «;   // выводим остальные числа

        // Если счётчик цикла делится на 10 без остатка, то тогда вставляем символ новой строки

        if (count % 10 == 0)

            std::cout << «\n»;

        // Увеличиваем значение счётчика цикла на единицу

        ++count;

    }

    return 0;

}

Результат выполнения программы выше:

01 02 03 04 05 06 07 08 09 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
31 32 33 34 35 36 37 38 39 40
41 42 43 44 45 46 47 48 49 50

Вложенные циклы while

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

#include <iostream>

int main()
{
int outer = 1;
while (outer <= 5)
{
int inner = 1;
while (inner <= outer)
std::cout << inner++ << » «;

// Вставляем символ новой строки в конце каждого рядка
std::cout << «\n»;
++outer;
}

return 0;
}


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

#include <iostream>

int main()

{

    int outer = 1;

    while (outer <= 5)

    {

        int inner = 1;

        while (inner <= outer)

            std::cout << inner++ << » «;

        // Вставляем символ новой строки в конце каждого рядка

        std::cout << «\n»;

        ++outer;

    }

    return 0;

}

Результат выполнения программы выше:

1
1 2
1 2 3
1 2 3 4
1 2 3 4 5

Тест


Задание №1

Почему в программе выше переменная inner объявлена внутри блока while, а не сразу после объявления переменной outer (вне блока while)?

Ответ №1

Переменная inner объявлена внутри блока while так, чтобы она была восстановлена (и повторно инициализирована до 1) каждый раз, когда выполняется внешний цикл. Если бы переменная inner была объявлена вне цикла while, то её значение никогда не было бы сброшено до 1, или нам бы пришлось это сделать самостоятельно с помощью операции присваивания. Кроме того, поскольку переменная inner используется только внутри внешнего цикла while, то имеет смысл объявить её именно там. Помните, что переменные нужно объявлять максимально близко к их первому использованию!

Задание №2

Напишите программу, которая выводит буквы английского алфавита от a до z вместе с кодами из таблицы ASCII.

Подсказка: Чтобы выводить символы как целые числа — используйте оператор static_cast.

Ответ №2

#include <iostream>

int main()
{
char mychar = ‘a’;
while (mychar <= ‘z’)
{
std::cout << mychar << » » << static_cast<int>(mychar) << «\n»;
++mychar;
}

return 0;
}



#include <iostream>

int main()

{

    char mychar = ‘a’;

    while (mychar <= ‘z’)

    {

        std::cout << mychar  << » » << static_cast<int>(mychar) << «\n»;

        ++mychar;

    }

    return 0;

}

Задание №3

Инвертируйте программу с последнего подзаголовка «Вложенные циклы» так, чтобы она выводила следующее:

5 4 3 2 1
4 3 2 1
3 2 1
2 1
1

Ответ №3

#include <iostream>

int main()
{
int outer = 5;
while (outer >= 1)
{
int inner = outer;
while (inner >= 1)
std::cout << inner— << » «;

// Вставляем символ новой строки в конце каждого рядка
std::cout << «\n»;
—outer;
}

return 0;
}


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

#include <iostream>

int main()

{

    int outer = 5;

    while (outer >= 1)

    {

        int inner = outer;

        while (inner >= 1)

            std::cout << inner— << » «;

        // Вставляем символ новой строки в конце каждого рядка

        std::cout << «\n»;

        —outer;

        }

    return 0;

}

Задание №4

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

        1
      2 1
    3 2 1
  4 3 2 1
5 4 3 2 1

Подсказка: Разберитесь сначала, как вывести числа следующим образом:

X X X X 1
X X X 2 1
X X 3 2 1
X 4 3 2 1
5 4 3 2 1

Ответ №4

#include <iostream>

int main()
{
// Цикл с 1 до 5
int outer = 1;

while (outer <= 5)
{
// Числа в рядах появляются в порядке убывания, поэтому цикл начинаем с 5 и до 1
int inner = 5;

while (inner >= 1)
{
// Первое число в любом ряде совпадает с номером этого ряда
// Поэтому числа должны выводиться только если <= номера ряда, в противном случае, выводится пробел
if (inner <= outer)
std::cout << inner << » «;
else
std::cout << » «; // вставляем дополнительные пробелы

—inner;
}

// Этот ряд вывели, переходим к следующему
std::cout << «\n»;

++outer;
}
}


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

#include <iostream>

int main()

{

// Цикл с 1 до 5

int outer = 1;

while (outer <= 5)

{

// Числа в рядах появляются в порядке убывания, поэтому цикл начинаем с 5 и до 1

int inner = 5;

while (inner >= 1)

{

// Первое число в любом ряде совпадает с номером этого ряда

// Поэтому числа должны выводиться только если <= номера ряда, в противном случае, выводится пробел

if (inner <= outer)

std::cout << inner << » «;

else

std::cout << »  «; // вставляем дополнительные пробелы

—inner;

}

// Этот ряд вывели, переходим к следующему

std::cout << «\n»;

++outer;

}

}

Оценить статью:

Загрузка…

За репост +20 к карме и моя благодарность!

ravesli.com

Цикл while java / оператор while

Введение

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

Вот как можно было бы закодировать включение кондиционера на обогрев и охлаждение:

if (tempRoom>tempComfort)
    airConditionerOn();
if (tempRoom<tempComfort
    heaterOn();

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

  1. Если в тазике есть яблоки, то выполняем шаги с 1.1 по 1.4:

    1. 1.1. Берём яблоко
    2. 1.2. Чистим и нарезаем его дольками
    3. 1.3. Помещаем на основание пирога из теста на сковороде
    4. 1.4. Возвращаемся на шаг 1.

Допустим у вас 10 яблок, 2 руки и один нож. В жизни вы последовательно чистите весь десяток, руководствуясь одним и тем же алгоритмом. А как заставить программу делать повторяющееся действие с каждым яблоком?

  • Привяжем себя к числу яблок,но если у нас их мало – часть команд выполнялось бы вхолостую без «полезной нагрузки» (и, возможно, порезались, очищая кожуру несуществующего яблока).
  • Если яблок больше, чем наших команд обработки – часть продуктов пропала бы необработанной.
  • Подобный «код» тяжело читать, в нём много повторов, его трудно модифицировать.

Циклы – операторы многократного выполнения действий

Цикл while Java (цикл вайл) хорошо подойдёт в нашем случае. Эта конструкция оформляет многократные действия в лаконичную и понятную структуру. Алгоритм по нарезке яблок для пирога в виде while в Java мог бы выглядеть как:

while(числоЯблокВТазике>0) {
    яблоко = тазик.взятьОчередноеЯблоко();
    положитьВПирог(яблоко.чистить().нарезать());
    числоЯблокВТазике--;
}
System.out.println('Яблоки для пирога обработаны.');

Синтаксис команды

Первый способ описания оператора while следующий:

while(Логическое выражение) {
	
}

Выполняется следующим образом (по шагам):

  1. Вычисляем Логическое условие, следующее в скобках за while.
  2. Если логическое условие истинно, то выполняются операторы в теле цикла, после выполнения последнего оператора в теле цикла, переходим на шаг 1
  3. Если логическое условие ложно, то переходим к первому оператору за пределами цикла while.

Цикл с предусловием

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

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

public static void main(String[] args) {
    int number = 3; 
    int result = 1; 
    int power = 1; 
    while(power <= 10) { 
        result = result * number;
        System.out.println(number + " в степени " + power + " = " + result);
        power++;
    }
}

Результат вывода на консоль:

3 в степени 1 = 3
3 в степени 2 = 9
3 в степени 3 = 27
3 в степени 4 = 81
3 в степени 5 = 243
3 в степени 6 = 729
3 в степени 7 = 2187
3 в степени 8 = 6561
3 в степени 9 = 19683
3 в степени 10 = 59049
Process finished with exit code 0

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

Второй вид цикла:

do {
    
}while (Логическое выражение);

Выполняется следующим образом (шаги):

  1. Выполняется тело цикла (сразу после ключевого слова do).
  2. Вычисляем Логическое условие, следующее в скобках за while.
  3. Если логическое условие истинно, то переходим на шаг 1
  4. Если логическое условие ложно, то переходим к первому оператору за пределами цикла while.

Два основных отличия от предыдущего вида цикла: тело цикла как минимум выполняется один раз и логическое условие проверяется после выполнения тела цикла. Поэтому этот вид цикла while называют циклом с постусловием.

На этот раз выведем таблицу степеней числа, не превышающую 10000:

public static void main(String[] args) {
    int number = 3;
    int result = number;
    int power = 1;
    do {
        System.out.println(number + " в степени " + power + " = " + result);
        power++;
        result = result * number;
    }while (result < 10000); 

Результат вывода на консоль:

3 в степени 1 = 3
3 в степени 2 = 9
3 в степени 3 = 27
3 в степени 4 = 81
3 в степени 5 = 243
3 в степени 6 = 729
3 в степени 7 = 2187
3 в степени 8 = 6561
Process finished with exit code 0

Обратите внимания на изменения в коде, сравнив с вариантом цикла с предусловием.

Интересные факты о работе с циклами

Управляющие команды в теле цикла

Существуют две команды, влияющие на ход выполнения цикла: break, особенности применения которого мы покажем в следующей главе, и continue.

  • continue – прекращает выполнение тела текущего цикла и осуществляет переход к логическому выражению оператора while. Если вычисленное выражение будет истинно – выполнение цикла будет продолжено.
  • break – немедленно прекращает выполнение текущего цикла и осуществляет переход к первой команде за его пределами. Таким образом, выполнение текущего цикла прерывается. Подробнее мы рассмотрим её в следующей теме.

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

while(числоЯблокВТазике>0) {
    яблоко = тазик.взятьОчередноеЯблоко();
    числоЯблокВТазике--;
    if (яблоко.плохое()) {  
        яблоко.выкинутьВМусор();
        continue; 
    }
    положитьВПирог(яблоко.чистить().нарезать());
}

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

public static void main(String[] args) {
    int sum = 0;    
    int i = 0;      
    int count = 20; 
    while(i<=count) {
        i++;        
        if (i*i=<count)  
            continue;   
                        
        sum += i*i*i; 
    } 
    System.out.println(sum);
}

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

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

while(true) {
    
}

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

Для демонстрации вернёмся к степеням числа:

public static void main(String[] args) {
    int number = 3; 
    int result = 1; 
    int power = 1; 
    while(true) {
        result = result * number;
        System.out.println(number + " в степени " + power + " = " + result);
        power++;
        if (power>10)
            break; 
    }
}

Результат вывода на консоль:

3 в степени 1 = 3
3 в степени 2 = 9
3 в степени 3 = 27
3 в степени 4 = 81
3 в степени 5 = 243
3 в степени 6 = 729
3 в степени 7 = 2187
3 в степени 8 = 6561
3 в степени 9 = 19683
3 в степени 10 = 59049
Process finished with exit code 0

Вложенные циклы

Вот мы и подошли к завершающей теме о наших циклах. Вспомним о яблочном пироге (надеюсь, вы не голодны в данный момент) и наш «цикл»:

  1. Если в тазике есть яблоки, выполняем шаги с 1.1 по 1.4:

    1. 1.1. Берем яблоко
    2. 1.2. Чистим и нарезаем его дольками
    3. 1.3. Помещаем на основание пирога из теста на сковороде
    4. 1.4. Возвращаемся на шаг 1.

Подробнее распишем процесс нарезания дольками:

  1. Число долек = 0
  2. Пока число долек < 12, выполнить шаги с 2.1 по 2.3

    1. 2.1. Отрезать очередную дольку от яблока
    2. 2.2. Кол-во долек ++
    3. 2.3. Возвращаемся на шаг 2

И вставим в наш кондитерский алгоритм:

  1. Если в тазике есть яблоки, то выполняем шаги с 1.1 по 1.6:

    1. 1.1. Берем яблоко
    2. 1.2. Очищаем его от кожуры
    3. 1.3. Число долек = 0
    4. 1.4. Пока число долек < 12, выполнить шаги с 1.4.1 по 1.4.3
      1. 1.4.1. Отрезать очередную дольку от яблока
      2. 1.4.2. Кол-во долек ++
      3. 1.4.3. Возвращаемся на шаг 1.4

    5. 1.5. Помещаем дольки на тестовое основание пирога из теста на сковороде
    6. 1.6. Возвращаемся на шаг 1.

Получили цикл в цикле. Подобные конструкции весьма частые.

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

public static void main(String[] args) {
    
    System.out.println("    2  3  4  5  6  7  8  9");
    int i = 2;      
    while(i<10) {   
        System.out.print(i + " | ");
        int j = 2;                  
        while (j<10) { 
            int mul=i*j; 
            if (mul<10)  
                System.out.print(mul + "  ");
            else   
                System.out.print(mul + " ");
            j++;     
        }            
        System.out.println(); 
        i++;                  
    }                         
}

Результат вывода на консоль:

2  3  4  5  6  7  8  9
2 | 4  6  8  10 12 14 16 18
3 | 6  9  12 15 18 21 24 27
4 | 8  12 16 20 24 28 32 36
5 | 10 15 20 25 30 35 40 45
6 | 12 18 24 30 36 42 48 54
7 | 14 21 28 35 42 49 56 63
8 | 16 24 32 40 48 56 64 72
9 | 18 27 36 45 54 63 72 81
Process finished with exit code 0

Циклы (в частности, оператор while) – один из фундаментальных кирпичиков построения программ. Решая задачи на JavaRush, вы изучите все их разнообразие, разберёте тонкости функционирования и получите практические навыки их применения.

javarush.ru

Циклы в программировании. Цикл while. Урок 9

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

Цикл while

«While» переводится с английского как «пока». Но не в смысле «до свидания», а в смысле «пока имеем это, делаем то».

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

while логическое_выражение {
    выражение 1;
    … 
    выражение n;
}

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

В случае while, после того как его тело выполнено, поток возвращается к заголовку цикла и снова проверяет условие. Если логическое выражение возвращает истину, то тело снова выполняется. Потом снова возвращаемся к заголовку и так далее.

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

Рассмотрите блок-схему цикла while.

На ней ярко-голубыми прямоугольниками обозначена основная ветка программы, ромбом – заголовок цикла с логическим выражением, бирюзовым прямоугольником – тело цикла.

С циклом while возможны две исключительные ситуации:

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

  • Если логическое выражение в заголовке while никогда не возвращает False, а всегда остается равным True, то цикл никогда не завершится, если только в его теле нет оператора принудительного выхода из цикла (break) или вызовов функций выхода из программы – quit(), exit() в случае Python. Если цикл повторяется и повторяется бесконечное количество раз, то в программе происходит зацикливание. В это время она зависает и самостоятельно завершиться не может.

Вспомним наш пример из урока про исключения. Пользователь должен ввести целое число. Поскольку функция input() возвращает строку, то программный код должен преобразовать введенное к целочисленному типу с помощью функции int(). Однако, если были введены символы, не являющиеся цифрами, то возникает исключение ValueError, которое обрабатывается веткой except. На этом программа завершается.

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

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

n = input("Введите целое число: ")
 
while type(n) != int:
    try:
        n = int(n)
    except ValueError:
        print("Неправильно ввели!")
        n = input("Введите целое число: ")
 
if n % 2 == 0:
    print("Четное")
else:
    print("Нечетное")

Примечание 1. Не забываем, в языке программирования Python в конце заголовков сложных инструкций ставится двоеточие.

Примечание 2. В выражении type(n) != int с помощью функции type() проверяется тип переменной n. Если он не равен int, т. е. значение n не является целым числом, а является в данном случае строкой, то выражение возвращает истину. Если же тип n равен int, то данное логическое выражение возвращает ложь.

Примечание 3. Оператор % в языке Python используется для нахождения остатка от деления. Так, если число четное, то оно без остатка делится на 2, т. е. остаток будет равен нулю. Если число нечетное, то остаток будет равен единице.

Проследим алгоритм выполнения этого кода. Пользователь вводит данные, они имеют строковый тип и присваиваются переменной n. В заголовке while проверяется тип n. При первом входе в цикл тип n всегда строковый, т. е. он не равен int. Следовательно, логическое выражение возвращает истину, что позволяет зайти в тело цикла.

Здесь в ветке try совершается попытка преобразования строки к целочисленному типу. Если она была удачной, то ветка except пропускается, и поток выполнения снова возвращается к заголовку while.

Теперь n связана с целым числом, следовательно, ее тип int, который не может быть не равен int. Он ему равен. Таким образом логическое выражение type(n) != int возвращает False, и весь цикл завершает свою работу. Далее поток выполнения переходит к оператору if-else, находящемуся в основной ветке программы. Здесь могло бы находиться что угодно, не обязательно условный оператор.

Вернемся назад. Если в теле try попытка преобразования к числу была неудачной, и было выброшено исключение ValueError, то поток выполнения программы отправляется в ветку except и выполняет находящиеся здесь выражения, последнее из которых просит пользователя снова ввести данные. Переменная n теперь имеет новое значение.

После завершения except снова проверяется логическое выражение в заголовке цикла. Оно даст True, т. к. значение n по-прежнему строка.

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

Рассмотрим следующий пример:

total = 100
 
i = 0
while i < 5:
    n = int(input())
    total = total - n
    i = i + 1
 
print("Осталось", total)

Сколько раз «прокрутится» цикл в этой программе, т. е. сколько итераций он сделает? Ответ: 5.

  1. Сначала переменная i равна 0. В заголовке цикла проверяется условие i < 5, и оно истинно. Тело цикла выполняется. В нем меняется значение i, путем добавления к нему единицы.

  2. Теперь переменная i равна 1. Это меньше пяти, и тело цикла выполняется второй раз. В нем i меняется, ее новое значение 2.

  3. Два меньше пяти. Тело цикла выполняется третий раз. Значение i становится равным трем.

  4. Три меньше пяти. На этой итерации i присваивается 4.

  5. Четыре по прежнему меньше пяти. К i добавляется единица, и теперь ее значение равно пяти.

Далее начинается шестая итерация цикла. Происходит проверка условия i < 5. Но поскольку теперь оно возвращает ложь, то выполнение цикла прерывается, и его тело не выполняется.

«Смысловая нагрузка» данного цикла – это последовательное вычитание из переменной total вводимых чисел. Переменная i в данном случае играет только роль счетчика итераций цикла. В других языках программирования для таких случаев предусмотрен цикл for, который так и называется: «цикл со счетчиком». Его преимущество заключается в том, что в теле цикла не надо изменять переменную-счетчик, ее значение меняется автоматически в заголовке for.

В языке Python тоже есть цикл for. Но это не цикл со счетчиком. В Питоне он предназначен для перебора элементов последовательностей и других сложных объектов. Данный цикл и последовательности будут изучены в последующих уроках.

Для while наличие счетчика не обязательно. Представим, что надо вводить числа, пока переменная total больше нуля. Тогда код будет выглядеть так:

total = 100
 
while total > 0:
    n = int(input())
    total = total - n
 
print("Ресурс исчерпан")

Сколько раз здесь выполнится цикл? Неизвестно, все зависит от вводимых значений. Поэтому у цикла со счетчиком известно количество итераций, а у цикла без счетчика – нет.

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

Примечание 1. Не обязательно в выражениях total = total - n и i = i + 1 повторять одну и ту же переменную. В Python допустим сокращенный способ записи подобных выражений: total -= n и i += 1.

Примечание 2. При использовании счетчика он не обязательно должен увеличиваться на единицу, а может изменяться в любую сторону на любое значение. Например, если надо вывести числа кратные пяти от 100 до 0, то изменение счетчика будет таким i = i - 5, или i -= 5.

Примечание 3. Для счетчика не обязательно использовать переменную с идентификатором i. Можно назвать переменную-счетчик как угодно. Однако так принято в программировании, что счетчики обозначают именами i и j (иногда одновременно требуются два счетчика).

Практическая работа

  1. Измените последний код из урока так, чтобы переменная total не могла уйти в минус. Например, после предыдущих вычитаний ее значение стало равным 25. Пользователь вводит число 30. Однако программа не выполняет вычитание, а выводит сообщение о недопустимости операции, после чего осуществляет выход из цикла.

  2. Используя цикл while, выведите на экран для числа 2 его степени от 0 до 20. Возведение в степень в Python обозначается как **. Фрагмент вывода:

    ...
      32
      64
     128
     256
     512
    1024
    ...

Примеры решения в android-приложении и pdf-версии курса.

younglinux.info

VBA Excel. Цикл Do While… Loop

Цикл Do While… Loop в VBA Excel, его синтаксис и описание отдельных компонентов. Примеры использования цикла Do While… Loop.

Цикл Do While… Loop в VBA Excel предназначен для повторения блока операторов пока выполняется заданное условие (возвращается значение True). Синтаксис этого цикла аналогичен синтаксису цикла Do Until… Loop, который повторяется до тех пор, пока условие не выполняется (возвращается значение False).

  1. Синтаксис цикла Do While… Loop
  2. Компоненты цикла Do While… Loop
  3. Примеры циклов Do While… Loop

Синтаксис цикла Do While… Loop

Синтаксис цикла Do While… Loop существует в двух вариантах, определяющих, когда проверяется условие.


Условие проверяется до выполнения операторов:


Do While condition
    [ statements ]
    [ Exit Do ]
    [ statements ]
Loop

Условие проверяется после выполнения операторов:


Do
    [ statements ]
    [ Exit Do ]
    [ statements ]
Loop While condition

В квадратных скобках указаны необязательные атрибуты цикла Do While… Loop.

Компоненты цикла Do While… Loop

Компонент Описание
condition Обязательный атрибут. Условие выполнения цикла. Выражение, возвращающее значение типа Boolean.
statements Необязательный* атрибут. Операторы вашего кода.
Exit Do Необязательный атрибут. Оператор выхода** из цикла до его окончания.

*Если не использовать в цикле свой код, смысл применения цикла теряется.

**Очень полезный оператор для цикла Do While… Loop, так как при некоторых обстоятельствах он может стать бесконечным. Если такой риск существует, следует предусмотреть возможность выхода из бесконечного цикла VBA с помощью оператора Exit Do.

Примеры циклов Do While… Loop

Простейшие циклы

Цикл Do While… Loop с условием до исполняемых операторов:


Sub test1()
Dim a As Byte
  Do While a < 10
    a = a + 1
  Loop
MsgBox a
End Sub

Цикл Do While… Loop с условием после исполняемых операторов:


Sub test2()
Dim a As Byte
  Do
    a = a + 1
  Loop While a < 10
MsgBox a
End Sub

В обоих случаях окно MsgBox выведет число 10. Когда значение переменной a будет равно 10, проверяемое условие выдаст значение False, и цикл будет остановлен.

Проход по строкам листа

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

Дни Игрок Брошено Попало в цель
1 день Белка 1 15 6
1 день Белка 2 12 7
2 день Белка 1 14 8
2 день Белка 2 16 7
3 день Белка 1 20 9
3 день Белка 2 14 6
4 день Белка 1 26 10
4 день Белка 2 13 5
5 день Белка 1 17 4
5 день Белка 2 21 7

Исходя из этих данных необходимо узнать, сколько шишек осталось у Белки 1 в дупле. Для этого необходимо вычесть из 100 шишек количество выброшенных Белкой 1 и прибавить шишки, заброшенные в ее дупло Белкой 2. Вычисления начинаем со второй строки (в первой заголовки) и в условии для цикла Do While… Loop указываем «первая ячейка текущей строки не является пустой». Таблица должна начинаться с первой ячейки рабочего листа «A1», и под ней, как минимум, одна строка должна быть пустой, точнее, первая ячейка этой строки.


Sub test3()
Dim i As Long, n As Long
i = 2
n = 100
  Do While Cells(i, 1) <> ""
    If Cells(i, 2) = "Белка 1" Then
      n = n - Cells(i, 3)
    Else
      n = n + Cells(i, 4)
    End If
    i = i + 1
  Loop
MsgBox n
End Sub

Результат, выведенный в информационном сообщении MsgBox, будет равен 40. Вы можете скопировать таблицу на рабочий лист книги Excel и поэкспериментировать с кодом VBA.

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

Пример бесконечного цикла:


Sub test4()
Dim a As Byte
  Do While a < 10
  a = a + 1
    If a = 9 Then
      a = 0
    End If
  Loop
End Sub

При запуске этой процедуры цикл Do While… Loop начинает выполняться бесконечно. Мне приходилось останавливать бесконечные циклы VBA в Excel 2000 и Excel 2016. В Excel 2000 помогло сочетание клавиш Ctrl+Break, а в Excel 2016 при закрытии редактора VBA крестиком появляется окно:

Информационное окно «Microsoft Excel не отвечает»

Ожидать отклика программы нет смысла, поэтому нажимаем «Перезапустить программу» или «Закрыть программу».

Совет: перед запуском процедуры с циклом Do While… Loop, который может стать бесконечным, обязательно сохраните книгу, иначе, при принудительном закрытии редактора VBA ваши изменения будут утеряны. Кроме того, при принудительном закрытии редактора VBA, Excel может отключить макросы. Включите их в окне «Центр управления безопасностью», открыть которое можно по ссылке «Безопасность макросов» на ленте в разделе «Разработчик». Подробнее о включении макросов в разных версиях Excel читайте в статье: Как разрешить выполнение макросов в Excel?.

Пример использования оператора Exit Do:


Sub test5()
Dim a As Byte, n As Long
  Do While a < 10
  a = a + 1
  n = n + 1
    If a = 9 Then
      a = 0
    End If
    If n = 1000 Then
      Exit Do
    End If
  Loop
MsgBox n
End Sub

Когда число итераций цикла дойдет до 1000, он будет завершен, и информационное сообщение MsgBox выведет на экран число повторений цикла Do While… Loop из этого примера.

vremya-ne-zhdet.ru

Цикл while

В этой части Учебника Perl мы узнаем, как работает цикл while в Perl.

use strict;
use warnings;
use 5.010;

my $counter = 10;

while ($counter > 0) {
  say $counter;
  $counter -= 2;
}
say 'done';

Цикл while имеет условие (в нашем случае оно проверяет, положительна ли переменная
$counter) и блок кода в фигурных скобках.

Когда по ходу выполнения программа впервые встречает начало цикла while, она проверяет,
истинно ли условие. Если оно возвращает FALSE, блок
пропускается и программа переходит к следующему выражению, в нашем случае к выводу ‘done’.

Если условие цикла while возвращает TRUE, блок выполняется, и затем программа
возвращается к проверке условия. Условие снова проверяется. Если результат проверки — ложь, блок
пропускается и выводится ‘done’. Если результат — истина, то блок выполняется и программа
возвращается к условию…


Это продолжается, пока условие выполняется, говоря по-русски:

while (условие-истинно) { сделать-что-то }

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

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

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

Если это случается по ошибке, это баг.

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

Например:

while (42) {
  # делать что-то
}

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

while (1) {
  # делать что-то
}

Естественно, увидев, что в коде нет выхода из цикла, кто-то может удивиться, как вообще эта
программа может закрыться без насильного прекращения извне?

Для этого существует несколько способов.

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

use strict;
use warnings;
use 5.010;

while (1) {
  print "Какой язык программирования вы сейчас изучаете? ";
  my $name = <STDIN>;
  chomp $name;
  if ($name eq 'Perl') {
    last;
  }
  say 'Неверно! Попробуйте еще раз!';
}
say 'готово';

В этом примере мы спрашиваем пользователя и надеемся, что он сможет ответить на вопрос и
использовать правильный регистр. Он застрянет на этом вопросе навечно, если не сможет набрать
‘Perl’.

Так что общение может происходить примерно так:

Какой язык программирования вы сейчас изучаете?
>  Java
Неверно! Попробуйте еще раз!
Какой язык программирования вы сейчас изучаете?
>  PHP
Неверно! Попробуйте еще раз!
Какой язык программирования вы сейчас изучаете?
>  Perl
готово

Как вы видите, когда пользователь ввел правильный ответ, вызвалось выражение last, остаток
блока, включая say ‘Неверно! Попробуйте еще раз!’;, был пропущен, и выполнение продолжилось
с конца цикла while.

ru.perlmaven.com