Программирование циклов, цикл do while
Организация выполнения повторяющихся действий в VBA может быть выполнена несколькими операторами, которые условно разделяют на цикл-пока, цикл-до, цикл-для.
Оператор While
Общий вид оператора While:
While выражение [инструкции] Wend
Оператор While предназначен для организации цикла-пока.
Инструкции будут выполняться пока выражение будет истинно.
Пример. Вычислить сумму чисел от 0 до 100.
Решение.
Sub сумма1() Dim x, s As Double x = 0 s = 0 While x <= 100 s = s + x x = x + 1 Wend MsgBox ("s=" + Str(s)) End Sub
Пояснение решения.
В переменной s накапливается значение суммы.
Оператор Do While
Общий вид оператора Do While:
Do [While выражение] [инструкции] [Exit Do] [инструкции1] Loop
Оператор Do While предназначен для организации цикла-пока.
Инструкции будут выполняться пока выражение будет истинно. Конструкция Exit Do предназначена для преждевременного выхода из цикла.
Пример. Вычислить сумму чисел от 0 до 100.
Решение.
Sub сумма2() Dim x, s As Double x = 0 s = 0 Do While x <= 100 s = s + x x = x + 1 Loop MsgBox ("s=" + Str(s)) End Sub
Оператор Do Loop Until
Общий вид оператора Do Loop Until:
Do [инструкции] [Exit Do] [инструкции1] Loop [Until выражение]
Оператор Do Loop Until предназначен для организации цикла-до.
Инструкции будут выполняться до момента, когда выражение станет истинным. Конструкция Exit Do предназначена для преждевременного выхода из цикла.
Пример. Вычислить сумму чисел от 0 до 100.
Решение.
Sub сумма3() Dim x, s As Double x = 0 s = 0 Do s = s + x x = x + 1 Loop Until x > 100 MsgBox ("s=" + Str(s)) End Sub
Оператор For
Общий вид оператора For:
For счетчик = начальное_знач To конечное_знач [Step шаг] [инструкции] [Exit For] [инструкции1] Next [счетчик]
Оператор For предназначен для организации цикла-для. 2 Next x End Sub
Пример 2
Пример 2. Составить программу определения наибольшего общего делителя (НОД) двух натуральных чисел.
Решение.
Наибольший общий делитель двух натуральных чисел — это самое большое натуральное число, на которое они делятся. Например, у чисел 12 и 18 наибольшие делители: 2, 3, 6. наибольшим общим делителем является число 6. Это записывается так:
НОД(12, 18) = 6.
Идея
НОД(M, N) = НОД(M-N, N).
Иначе говоря, НОД двух натуральных чисел равен НОД их положительной разности и меньшего числа.
Sub Евклид() Dim M, N, NOD M = Cells(1, 2) N = Cells(2, 2) While M <> N If M > N Then M = M - N Else N = N - M End If Wend NOD = M Cells(3, 2).Value = NOD End Sub
Пример 3
Пример 3. Построить график функции: улитку Паскаля.
Улитка Паскаля задается следующим образом:
x=A*cos(t)+B*cos(t) y=A*cos(t)sin(t)+B*sin(t), A>B, B>0, 0<=t<2*Pi
Решение.
1. Подготовить данные в электронной таблице
2. Ввести код программы.
Sub улитка_паскаля() Dim a, b, Pi, t As Double Dim i As Integer a = Cells(1, 2) b = Cells(2, 2) Pi = 3.14 i = 2 t = 0 While t <= 2 * Pi x = a * Cos(t) + b * Cos(t) y = a * Cos(t) * Sin(t) + b * Sin(t) Cells(3, i).Value = x Cells(4, i).Value = y t = t + 0.1 i = i + 1 Wend End Sub
3. Построить график с помощью мастера диаграмм, выбрав точечную диаграмму.
4. Изменить данные a и b.
A=2 B=1
5. Перезапустить макрос.
VBA Excel. Цикл Do While… Loop
Цикл Do While… Loop в VBA Excel, его синтаксис и описание отдельных компонентов. Примеры использования цикла Do While… Loop.
Цикл Do While… Loop в VBA Excel предназначен для повторения блока операторов пока выполняется заданное условие (возвращается значение True). Синтаксис этого цикла аналогичен синтаксису цикла Do Until… Loop, который повторяется до тех пор, пока условие не выполняется (возвращается значение False).
Синтаксис цикла 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 | |
statements | Необязательный* атрибут. Операторы вашего кода. |
Exit Do | Необязательный атрибут. Оператор выхода** из цикла до его окончания. |
*Если не использовать в цикле свой код, смысл применения цикла теряется.
**Очень полезный оператор для цикла Do While… Loop, так как при некоторых обстоятельствах он может стать бесконечным. Если такой риск существует, следует предусмотреть возможность выхода из бесконечного цикла VBA с помощью оператора Exit Do.
Примеры циклов Do While… Loop
Простейшие циклы
Цикл Do While… Loop с условием до исполняемых операторов:
1 2 3 4 5 6 7 | Sub test1() Dim a As Byte Do While a < 10 a = a + 1 Loop MsgBox a End Sub |
Цикл Do While… Loop с условием после исполняемых операторов:
1 2 3 4 5 6 7 | 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 в дупле.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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
Пример бесконечного цикла:
2 3 4 5 6 7 8 9 | 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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 из этого примера.
Содержание рубрики VBA Excel по тематическим разделам со ссылками на все статьи.
python – Как эмулировать цикл do-while?
Задавать вопрос
Спросил
Изменено 3 месяца назад
Просмотрено 1,7 м раз
1044
Новинка! Сохраняйте вопросы или ответы и организуйте свой любимый контент.
Узнать больше.
Мне нужно эмулировать цикл do-while в программе Python. К сожалению, следующий простой код не работает:
list_of_ints = [ 1, 2, 3 ] итератор = list_of_ints.__iter__() элемент = Нет пока верно: если элемент: элемент печати пытаться: элемент = итератор.следующий() кроме StopIteration: ломать напечатать "сделано"
Вместо «1,2,3,done» выводится следующий вывод:
[stdout:]1 [стандартный вывод:]2 [стандартный вывод:]3 None['Traceback (последний последний вызов): ', ' Файл "test_python. py", строка 8, вs = i.следующий() ', 'Остановить итерацию ']
Что я могу сделать, чтобы поймать исключение «остановить итерацию» и прервать некоторое время петля нормально?
Пример того, почему такая вещь может понадобиться, показан ниже в виде псевдокода.
Конечный автомат:
с = "" пока Истина: если состояние STATE_CODE : если "//" в s : tokens.add(TOKEN_COMMENT, s.split("//")[1]) состояние = STATE_COMMENT еще : tokens.add(TOKEN_CODE, с) если состояние STATE_COMMENT : если "//" в s : tokens.append(TOKEN_COMMENT, s.split("//" )[1] ) еще состояние = STATE_CODE # Переоценить ту же строку Продолжать пытаться : s = i.следующий() кроме StopIteration : ломать
- python
- цикл while
- do-while
4
Я не знаю, что вы пытаетесь сделать. Вы можете реализовать цикл do-while следующим образом:
while True: вещи() если условие_ошибки: ломать
Или:
вещи() пока не fail_condition: вещи()
Что вы делаете, пытаясь использовать цикл do while для печати материала в списке? Почему бы просто не использовать:
для i в l: напечатать я напечатать "сделано"
Обновление:
Итак, у вас есть список строк? И вы хотите продолжать повторять это? Как насчет:
для s в l: пока верно: вещи() # используйте "перерыв" вместо s = i. next()
Это похоже на то, что вам нужно? В вашем примере кода это будет:
для s в some_list: пока верно: если состояние STATE_CODE: если "//" в s: tokens.add(TOKEN_COMMENT, s.split("//")[1]) состояние = STATE_COMMENT еще : tokens.add(TOKEN_CODE, с) если состояние STATE_COMMENT: если "//" в s: tokens.append(TOKEN_COMMENT, s.split("//" )[1] ) break # перейти к следующему s еще: состояние = STATE_CODE # переоценить ту же строку # продолжается автоматически
8
Вот очень простой способ эмулировать цикл do-while:
условие = Истина пока условие: # тело цикла здесь условие = test_loop_condition() # конец цикла
Ключевыми особенностями цикла do-while являются то, что тело цикла всегда выполняется хотя бы один раз, а условие оценивается в нижней части тела цикла. Показанная здесь управляющая структура выполняет обе эти функции без использования исключений или операторов break. Он вводит одну дополнительную логическую переменную.
12
Мой код ниже может быть полезной реализацией, подчеркивающей основное различие между do-while и while, как я понимаю.
Итак, в этом случае вы всегда проходите цикл хотя бы один раз.
first_pass = Истина в то время как first_pass или условие: first_pass = Ложь do_stuff()
6
сделать { вещи() } пока (условие())
->
, пока True: вещи() если не условие(): ломать
Вы можете выполнить функцию:
def do_while(материал, условие): в то время как условие (материал()): проходить
Но 1) Это некрасиво. 2) Условие должно быть функцией с одним параметром, которая должна быть заполнена данными (это единственная причина, по которой , а не , использует классический цикл while.)
3
Исключение разорвет цикл, поэтому вы можете обрабатывать его вне цикла.
попробуйте: пока верно: если с: печать с s = i.следующий() кроме StopIteration: проходить
Я предполагаю, что проблема с вашим кодом в том, что поведение break
внутри , кроме
, не определено. Обычно break
поднимается только на один уровень вверх, т.е. break
внутри try
переходит непосредственно к finally
(если он существует) an out of try
, но не из цикла.
Связанный PEP: http://www.python.org/dev/peps/pep-3136
Связанный вопрос: выход из вложенных циклов
13
Вот более сумасшедшее решение другого шаблона — использование сопрограмм. Код по-прежнему очень похож, но с одним важным отличием; условий выхода нет вообще! Сопрограмма (на самом деле цепочка сопрограмм) просто останавливается, когда вы перестаете кормить ее данными.
определение сопрограммы (функция): """Декоратор сопрограмм Корутины должны быть запущены, доведены до их первой точки «урожая», и этот декоратор делает это автоматически. """ def startcr(*ar, **kw): кр = функция (*ар, **кВт) кр.следующий() вернуть кр возврат startcr @сопрограмма сборщик деф (хранение): """Действовать как "приемник" и собирать все отправленные в @storage""" пока верно: storage.append((выход)) @сопрограмма def state_machine (раковина): """ .send() новые части, которые будут токенизированы конечным автоматом, токены передаются @sink """ с = "" состояние = STATE_CODE пока верно: если состояние STATE_CODE : если "//" в s : раковина.send((TOKEN_COMMENT, s.split("//" )[1] )) состояние = STATE_COMMENT еще : раковина.отправить(( TOKEN_CODE, s )) если состояние STATE_COMMENT : если "//" в s : sin.send(( TOKEN_COMMENT, s.split("//" )[1] )) еще состояние = STATE_CODE # переоценить ту же строку Продолжать с = (урожайность) токены = [] sm = state_machine (сборщик (токены)) для части в я: см. отправить(шт.)
Приведенный выше код собирает все токены в виде кортежей в токены
, и я предполагаю, что нет никакой разницы между .append()
и .add()
в исходном коде.
1
Я сделал это следующим образом…
условие = Истина пока условие: do_stuff() условие = (<что-то, что оценивается как Истина или Ложь>)
Это кажется мне упрощенным решением, я удивлен, что еще не видел его здесь. Это, очевидно, также может быть инвертировано в
пока не условие:
и т. д.
1
Я считаю, что эта симуляция do-while на Python имеет синтаксический формат, наиболее близкий к формату структуры do-while, присутствующему в C и Java.
сделать = Верно пока делай: [...] сделать = <условие>
4
В Python 3. 8 есть ответ.
Это называется выражениями присваивания. из документации:
# Цикл по блокам фиксированной длины в то время как (блок := f.read(256)) != '': процесс (блок)
2
для цикла do — while, содержащего операторы try
цикл = True пока цикл: generic_stuff() пытаться: сомнительный_вещь () # прерывать успешное завершение # цикл = Ложь кроме: необязательный_материал() # чтобы сломаться от неудачного завершения - # случай, упомянутый в вопросе ОП петля = ложь в конце концов: more_generic_stuff()
в качестве альтернативы, когда нет необходимости в пункте 9 «наконец-то»0003
пока Истина: generic_stuff() пытаться: сомнительный_вещь () # прерывать успешное завершение # ломать кроме: необязательный_материал() # чтобы сломаться от неудачного завершения - # случай, упомянутый в вопросе ОП ломать
, пока условие истинно: вещи() еще: вещи()
5
Быстрый взлом:
def dowhile(func = None, condition = None): если не работает или не условие: возвращаться еще: функция() пока условие(): функция()
Используйте так:
>>> x = 10 >>> защита f(): . .. глобальный х ... х = х - 1 >>> определение с(): глобальный х вернуть х > 0 >>> делать пока(f, c) >>> напечатать х 0
Почему бы вам просто не сделать
вместо s в l : печать с напечатать "сделано"
?
4
Пока цикл:
пока условие: распечатать("привет")
Цикл выполнения:
пока верно: распечатать("привет") если не условие: ломать
Также вы можете использовать любое истинное логическое значение в качестве условия:
в то время как 1: распечатать("привет") если не условие: ломать
Другой вариант:
чек = 1 пока проверяю: распечатать("привет") проверка = условие
Если вы находитесь в сценарии, когда вы зацикливаетесь, когда ресурс недоступен или что-то подобное, что вызывает исключение, вы можете использовать что-то вроде
время импорта пока верно: пытаться: f = открыть('некоторые/путь', 'г') кроме IOError: print('Файл не может быть прочитан. Повторная попытка через 5 секунд') время сна(5) еще: ломать
Вы задавались вопросом:
Что я могу сделать, чтобы перехватить исключение «остановить итерацию» и правильно разорвать цикл while?
Вы можете сделать это, как показано ниже, и в котором также используется функция выражений присваивания (также известная как «оператор моржа»), представленная в Python 3.8:
list_of_ints = [1, 2, 3] итератор = итератор (список_целых) пытаться: в то время как (элемент := следующий (итератор)): печать (элемент) кроме StopIteration: распечатать("сделано")
Другая возможность (которая будет работать от Python 2.6 до 3.x) состоит в том, чтобы предоставить аргумент по умолчанию
встроенной функции next()
, чтобы избежать исключения StopIteration
:
SENTINEL = object() # Уникальный объект. list_of_ints = [1, 2, 3] итератор = итератор (список_целых) пока верно: элемент = следующий (итератор, SENTINEL) если элемент SENTINEL: ломать печать (элемент) распечатать("сделано")
Посмотрите, поможет ли это:
Установите флаг внутри обработчика исключений и проверьте его, прежде чем работать с s.
flagBreak = ложь; пока Истина: если флагBreak : перерыв если с: печать с пытаться : s = i.следующий() кроме StopIteration : флагбрейк = истина напечатать "сделано"
2
Для меня типичный цикл while будет примерно таким:
xBool = True # Счетчик для принудительного выполнения условия (например, yCount = некоторое целочисленное значение) в то время как xBool: # устанавливаем условие (например, если yCount > 0): (Сделай что-нибудь) yCount = yCount - 1 еще: # (условие не выполнено, устанавливаем xBool False) xBool = Ложь
Я мог бы также включить for..loop в цикл while, если того требует ситуация, для прохождения другого набора условий.
пока верно: пытаться: # вещи материал_1() если некое_условие: Продолжать если другое_условие: ломать материал_2() в конце концов: # условие если не условие: ломать
- [x]
состояние
проверено только после обкаткиштучно
- [x]
материал
не является вызовом функции - [x]
условие
не является вызовом функции - [x]
материал
может содержать управление потоком - [ ] Не проверять условие
заполнить
, вызванное, сломать
(можно сделать с другим логическим значением)
Встроенная функция iter делает именно это:
для x в iter(YOUR_FN, TERM_VAL): . ..
(проверено в Py2 и 3):
класс Легкий: Х = 0 @классметод деф ком (клс): клс.Х += 1 вернуть cls.X для x в iter(Easy.com, 10): напечатать(">>>", х)
Если вы хотите указать условие завершения вместо значения, вы всегда можете установить равенство и потребовать, чтобы это равенство было True
.
while do (Справочное руководство Guile)
while do (Справочное руководство Guile)6.11.4 Механизмы итерации
Схема имеет лишь несколько механизмов итерации, главным образом потому, что итерация в
Программы-схемы обычно выражаются с использованием рекурсии. Тем не менее,
R5RS определяет конструкцию для циклов программирования, вызывая до
. В
Кроме того, Guile имеет явный синтаксис циклов, который называется , а
.
- синтаксис: do ((переменная инициализация [шаг]) …) (тестовое выражение …) тело …
Свяжите переменную s и оцените тело , пока тест не станет истинным. Возвращаемое значение — это последнее expr после test , если оно задано. А простой пример иллюстрирует основную форму,
(сделать ((я 1 (1+ я))) ((> я 4)) (показать я)) -| 1234
Или с двумя переменными и окончательным возвращаемым значением,
(делать ((я 1 (1+ я)) (3 р (*3 р))) ((> я 4) п) (формат #t "3**~s равен ~s\n" i p)) -| 3**1 равно 3 3**2 равно 9 3**3 равно 27 3**4 это 81 ⇒ 243
Привязки переменных устанавливаются аналогично
let
, в том все выражения оцениваются, а затем выполняются все привязки. Когда итерация, необязательные выражения шага оцениваются с помощью предыдущие привязки в области действия, а затем все новые привязки.Выражение test является условием завершения. Циклические остановки когда тест верен. Он оценивается перед запуском тело каждый раз, значит если правда первый раз то тело вообще не запускается.
Дополнительные expr s после теста оцениваются в конце цикла, с окончательными переменными привязками. last expr дает возвращаемое значение, или если нет выражение с возвращаемое значение не указано.
Каждая итерация устанавливает привязки к новым местоположениям для переменная s, как новый
пусть
для каждой итерации. Это сделано для переменных s без шагов выражений тоже. это иллюстрирует следующее, показывая, как новыйi
захватывается лямбда(определить lst '()) (сделать ((я 1 (1+ я))) ((> я 4)) (set!lst(cons(лямбда()i)lst))) (карта (лямбда (proc) (proc)) lst) ⇒ (4 3 2 1)
- синтаксис: в то время как конд тело …
Запустить цикл, выполняющий форму тела , пока условие истинно. условие проверяется в начале каждой итерации, поэтому, если оно
#f
первый раз потом тело вообще не выполняется.В пределах
и
предусмотрены два дополнительных крепления, их можно использовать как от конд так и от корпус .- Процедура схемы: break break-arg …
Вырваться из формы
в то время как
.
- Процедура схемы: продолжить
Отменить текущую итерацию, вернуться к началу и протестировать , снова и т. д.
Если цикл завершается нормально, по условию оценивается как
#f
, тогда выражениеwhile
в целом оценивается как#ф
. Если он завершается вызовом, сломайте
с некоторым номером аргументов, эти аргументы возвращаются из, а
выражение, как несколько значений. В противном случае, если он завершается вызовомпрерывает
без аргументов, тогда возвращается значение#t
.(пока #f (ошибка "не достигнут")) ⇒ #f (в то время как #t (перерыв)) ⇒ #t (в то время как #t (перерыв 1 2 3)) ⇒ 1 2 3
Каждая форма
в то время как
получает свой собственныйbreak
ипродолжить
процедуры, работающие на том, в то время как
. Это означает, что когда петли вложенный внешнийразрыв
можно использовать для полного выхода. Например,(пока (тест1) (пусть ((внешний разрыв разрыв)) (пока (тест2) (если что-то) (внешний разрыв #f)) ...)))
Обратите внимание, что каждая процедура
break
иcontinue
может быть используется в динамическом объеме его, а
. Внепока
их поведение не указано.
Другим очень распространенным способом выражения итерации в программах Scheme является использование так называемого по имени пусть .