Урок №67. Цикл while

  Юрий  | 

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

 34753

 ǀ   34 

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

Цикл while

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

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

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

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

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

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

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 может и вообще не выполняться. Например:

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

done!

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


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

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

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

Единственный способ выйти из бесконечного цикла — использовать операторы 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 может привести к неожиданным результатам. Например:

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

Оказывается, эта программа представляет собой бесконечный цикл. Она начинается с вывода 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 раз:

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

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

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

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

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. В следующем примере внутренний и внешний циклы имеют свои собственные счётчики. Однако, обратите внимание, условие внутреннего цикла использует счётчик внешнего цикла!

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

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

Задание №3

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

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

Ответ №3

Задание №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

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

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (101 оценок, среднее: 4,89 из 5)
Загрузка...

Комментариев: 34

  1. Аватар Кекс:

    Здравствуйте, скажите, пожалуйста, как возвратить значение переменной из while?

  2. Аватар Игорь:

    додумался только до такого варианта!

  3. Аватар Ivan:

  4. Аватар zashiki:

    тут ромб-челлендж, значит…
    Попробовала так, чтобы цифры в обратном порядке шли к центру.
    вводить лучше до 9, так как дальше числа едут.

    Как сократить код? И как сделать, чтобы числа не ехали, если больше 9?

    1. Аватар zashiki:

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

      для нижнего треугольника:

      так можно делать треугольники из 2значных цифр, с шириной насколько позволяет ide

    2. Аватар Saliwer:

      Получилось 2 варианта решения до 3-значных чисел.
      1 вариант базируясь на знаниях полученных до этого урока.
      Для красивого вывода используется функция printf() и ввода scanf_s().

      2 вариант — используется цикл for() и тернарный оператор.
      Для красивого вывода использую функцию std::setw() из библиотеки <iomanip>

      1. Аватар zashiki:

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

        1. Аватар Saliwer:

          У Вас неплохо получилось:). Можно было в условии while(—rowWide > 0) убрать >0, если изначально число положительное, то по достижении переменной rowWide значения 0 (0 = false), произойдёт выход из цикла. Также, что б ромбик был красивее, можно было в строчке int printNumRow{numRow}; Вместо numRow использовать просто num.

          Добавил комменты:)

  5. Аватар Алексей:

    Второе сделал следующим образом.

  6. Аватар Dima Malovanyy:

    Тоже интересная программа с использованием while, если писать самому, то далеко не очевидная. Попробуйте сами!
    Задание: Напишите программу используя выкл while, которая просит ввести число от 1 до 9, а потом делает из него ромб чисел, по типу

    1
    1 2 1
    1 2 3 2 1
    1 2 1
    1

    Важно: программа должна выводить числа по уменьшению ( 1 всегда по краю)
    УДАЧИ!!!

    1. Аватар Алексей:

      Из головы не выходит)
      Вот как вывести после)

      В тесте простые проги, просто немного фантазии, хотя 4й сразу не сделал.

    2. Аватар Mirovengil:

      Можно короче (знаю, что лучше функциями):

    3. Аватар zashiki:

      попыталась, чтобы ромб был ровным и красивым при числах больше 9.

  7. Аватар Максим:

  8. Аватар Константин:

    Юра, если захочешь, можешь этот код как задание №5 вывесить. Я его написал в процессе выполнения задания №4 (которое, как ни парадоксально, я не смог осилить:-) Ромб из чисел:

  9. Аватар Владислав:

    Все разобрался 🙂
    Вот решение если кому нужно делал в DEV C++

  10. Аватар Владислав:

    Порылся вроде должно выглядеть так, но не работает.

  11. Аватар Владислав:

    Всем, здравствуйте! Извиняюсь за наверное слишком простой вопрос, но может кто помочь сделать такое задание: Написать программу для вычисления заданного выражения и вывода на экран полученного значения, используя циклический оператор While. Выражение: — 0,1+ 0,4 -0,7+…-1,9. Не могу сам сообразить ка это сделать, в программировании ноль но сделать нужно 🙁

  12. Вячеслав Вячеслав:

    вот задание №3:

  13. Вячеслав Вячеслав:

    вот первое задание :

  14. Аватар Alexey:

    или так:

  15. Аватар kmish:

  16. Аватар Алексей:

    Задание 3:

  17. Аватар Adel:

    Здравствуйте Юрий! Спасибо за такой пост! Все было очень понятно, кроме , посл. примера(треугольник). Можете объяснить каждую строку?!!!

  18. Аватар Игорь:

  19. Аватар Tairak:

    Спасибо за уроки, но я не могу понять как выводиться результат в последнем примере. Если цикл while повторяет себя до выполнения условия, то почему std::cout сробатывает с каждым разом на один раз больше? Почему на последней строчке 5 цифр, хоть и используется только один cout?

    1. Юрий Юрий:

      Потому что используется инкремент outer:

  20. Аватар Денис:

    Как вариант:

  21. Аватар master114:

    Поделюсь своим вариантом для 4 задачи

    1. Юрий Юрий:

      Как вариант может быть.

  22. Аватар Николай:

    Добрый вечер! Скажите, пожалуйста, на каком уроке и будет ли вообще разбор таких понятий, как printf и scanf?

    1. Юрий Юрий:

      Привет, printf и scanf в этих уроках не рассматриваются, но, возможно, позднее напишу статью о них (но это точно будет не скоро).

  23. Аватар Максим:

Добавить комментарий

Ваш E-mail не будет опубликован. Обязательные поля помечены *

telegram канал
НОВОСТИ RAVESLI