На прошлом уроке мы познакомились с циклами и разобрались, как использовать цикл по переменной. Сегодня мы разберём оставшиеся два вида циклов — цикл с предусловием и цикл с постусловием. Они очень похожи и просты в использовании.
Определить количество натуральных чисел, рассматривая их в порядке возрастания, сумма кубов которых не превышает 50000. Т.е. мы должны последовательно суммировать кубы чисел 1, 2, 3, . и делать это до тех пор, пока сумма не достигнет 50000, а в результате должны узнать, сколько чисел было пройдено.
Понятно, что решить задачу лучше использованием цикла. Но будет ли решение с циклом FOR оптимальным? Конечно, можно задать диапазон пробегаемых значений от 1 до 50000 — количество чисел точно будет найдено (очевидно, это кол-во будет даже менее 50, ведь 50^3 >> 50000). Но в этом случае придётся ставить дополнительное условие на значение суммы и выполнение команды Break.
Есть способ проще!
Цикл WHILE — цикл с предусловием
Цикл WHILE (англ. «пока») — цикл, в котором условие находится перед телом цикла, а сам цикл выполняется до тех пор, пока условие не станет ложным.
Цикл for. Что это. Что делает. Пример. Синтаксис. Циклы. Урок #16.
В качестве условия задаётся логическое выражение. Те операции, что будут выполняться в цикле, называются телом цикла.
Особенностью цикла с предусловием является то, что он может не выполниться ни разу — это произойдёт, если указанное условие изначально будет ложным. При этом, цикл может и стать «вечным» — если условие никогда не примет значения False. Именно поэтому следует следить за тем, чтобы всегда присутствовали условия для завершения работы цикла.
Решение задачи с помощью цикла WHILE
Вернёмся к нашей задаче. С помощью цикла с предусловием задача решается очень просто. Во-первых, нам потребуется переменная, в которой будет храниться текущее обрабатываемое число — это будут числа 1, 2, 3 и т.д. Во-вторых, ещё одна переменная потребуется для хранения суммы кубов чисел. Всё, этого достаточно. Теперь разберёмся, что писать в теле цикла.
Там мы должны: а) увеличивать переменную-счётчик на единицу, чтобы последовательно проходить числа; б) увеличивать сумму на куб текущего числа. Условием цикла будет главное условие нашей задачи — достижение суммой 50000. Вот что получается:
procedure TForm1.Button1Click(Sender: TObject);
var s,i: integer;
Label1.Caption:=IntToStr(i-1)
В данном случае процесс «повешен» на кнопку (Button1), а результат выводится в текстовую метку (Label1). Вы спросите, почему выводится i-1, а не само число i ? Всё просто. Ведь переменная-счётчик увеличивается после того, как проверяется условие цикла, а значит и результат получится на единицу больше. Удостовериться в этом можно, добавив в тело цикла вывод промежуточных результатов (в примере — в текстовое поле Memo1):
Memo1.Lines.Add(IntToStr(s)+’ : ‘+IntToStr(i));
Цикл REPEAT — цикл с постусловием
ИНФОРМАТИКА 8 класс: Цикл с предусловием на языке Паскаль | Видеоурок
Завершает тройку циклов цикл с постусловием — REPEAT (англ. «повтор»). Примечательно, что этого цикла во многих языках программирования нет — есть только FOR и WHILE. Между тем, цикл с постусловием очень удобен.
Работает цикл точно так же, как и WHILE, но с одним лишь отличием, следующим из его названия — условие цикла располагается после тела цикла, а не до него.
Есть несколько моментов, на которые стоит обратить внимание. Во-первых, в качестве условия задаётся уже условие выхода из цикла, в то время как в цикле WHILE задаётся условие продолжения цикла. Во-вторых, при наличии нескольких команд, которые помещаются в тело цикла, заключать их в блок BEGIN .. END не нужно — зарезервированные слова REPEAT .. UNTIL сами составляют аналогичный блок.
Цикл с постусловием, в отличие от цикла с предусловием, всегда выполняется хотя бы один раз! Но, как и цикл WHILE, при неверно написанном условии цикл станет «вечным».
Решение задачи с помощью цикла REPEAT
Решение нашей задачи практически не изменится — всё останется, только условие будет стоять в конце, а само условие изменится на противоположное:
procedure TForm1.Button2Click(Sender: TObject);
var s,i: integer;
until s >= 50000;
Label1.Caption:=IntToStr(i-1);
Команды Break и Continue
Команда Break, выполняющая досрочный выход из цикла, работает не только в цикле FOR, но и в циклах WHILE и REPEAT. Аналогично, команда Continue, немедленно запускающая следующую итерацию цикла, может использоваться в циклах WHILE и REPEAT.
Как остановить цикл?
Очень часто спрашивают, как написать такой цикл, который можно было бы остановить нажатием кнопки на форме, или, к примеру, клавишей [Esc]. В простейшем случае реализовать такой механизм достаточно просто. Однако, данный метод является не совсем верным — есть более удобные и правильные средства для организации таких операций. Тем не менее, рассмотрим пример.
Задание: при нажатии кнопки «Старт» программа начинает генерировать случайные комбинации из латинских букв (верхнего регистра) длиной 10 символов и все эти комбинации отображаются в текстовом поле TMemo. При нажатии кнопки «Стоп» генерация должна быть прекращена.
Каким образом решить поставленную задачу? Сначала сделаем акцент на механизме остановки. Понятно, что в данном случае нужно задать вечный цикл, да-да, самый настоящий, но каким образом предусмотреть его остановку? Очевидно, что выбор падает либо на WHILE, либо на REPEAT. Остановить цикл можно либо изменив значение логического выражения, заданного для цикла, либо вызвав команду Break.
Вопрос стоит теперь в том, как при нажатии кнопки «Стоп» изменить условие цикла, описанного в обработчике кнопки «Старт». Ответ прост — использовать ту память, которая доступна обработчикам обеих кнопок. Итак, заведём глобальную переменную, которая будет видна во всей программе. Глобальные переменные описываются над словом implementation модуля, там, где идёт описание формы:
Form1: TForm1;
Stop: Boolean = False;
В этой логической переменной мы будем хранить состояние процесса. Изначально будет стоять значение «ложь», а когда пользователь щёлкнет по кнопке «Стоп», мы изменим его в «истина».
На форме разместим Memo1 (TMemo) и 2 кнопки: Button1 («Старт»), Button2 («Стоп»). У кнопки «Стоп» поставим Enabled = False, т.е. выключим её.
Сразу приведу обработчики обеих кнопок, после чего подробно разберём их работу:
procedure TForm1.Button1Click(Sender: TObject);
var s: string; c: byte;
Button2.Enabled:=True;
Button1.Enabled:=False;
while not(Stop) do
for c := 1 to 10 do
s:=s+Chr(Random(Ord(‘Z’)-Ord(‘A’)+1)+Ord(‘A’));
Memo1.Lines.Add(s);
Application.ProcessMessages
procedure TForm1.Button2Click(Sender: TObject);
Button2.Enabled:=False;
Button1.Enabled:=True;
Начнём с кнопки «Стоп» (Button2). При её нажатии:
1) Значение переменной Stop устанавливается в True, т.е. мы подаём сигнал, что нужно остановиться;
2) Кнопку «Стоп» мы снова выключаем;
3) Кнопку «Старт» — наоборот, включаем.
Теперь кнопка «Старт» (Button1):
1) Кнопка «Стоп» включается, кнопка «Старт» выключается;
2) Переменной Stop присваивается значение False (если этого не сделать, то запустить процесс генерации второй раз будет невозможно);
3) Цикл с генерацией строки с условием на переменную Stop — цикл будет работать до тех пор, пока переменная Stop имеет значение False. Как только значение станет True, цикл сам завершит свою работу.
А теперь более подробно о том, что происходит в теле цикла. Начнём с генерации строки символов. Напомню, что строки можно складывать. Если сложить строку ‘A’ со строкой ‘B’, то получится строка ‘AB’. Именно этот приём здесь и использован. Сначала мы делаем строку пустой, а затем последовательно добавляем в неё 10 произвольных символов.
Как происходит добавление. Ну естественно с помощью цикла на 10 итераций. А вот выбор случайной из латинских букв не совсем прост и не для всех очевиден. Конечно, можно было заранее записать все буквы куда-либо (например, в массив, или в другую строковую переменную), а затем брать их оттуда. Но это не совсем хорошо, ведь можно сделать гораздо проще.
В данном случае решающим фактором является то, что латинские буквы в кодовой таблице символов идут по порядку. Т.е. ‘A’ имеет некоторый код n, ‘B’ имеет код n+1 и т.д. — весь алфавит идёт последовательно, без разрывов. Убедиться в этом можно с помощью программы «Таблица символов», которая есть в Windows.
Вернёмся к нашей задаче. Мы должны выбрать случайную из букв ‘A’..’Z’. Так как коды этих символов последовательны, то мы должны выбрать произвольное число от код_символа_A до код_символа_Z. Напомню, что для выбора случайного числа используется функция Random(n), возвращающая случайное число от 0 до n-1.
Недостаток функции в том, что она берёт числа всё время от нуля, а код символа ‘A’ уж явно не 0. Но и здесь ничего сложного нет: сначала узнаём «ширину» диапазона кодов — из кода символа ‘Z’ вычитаем код символа ‘A’. Не забываем прибавить 1, иначе буква ‘Z’ никогда не попадёт в строку, т.к. число берётся от 0 до n-1. Ну и дальше мы делаем сдвиг числа на код символа ‘A’.
На буквах: от ‘A’ до ‘Z’ p позиций. Сама ‘A’ стоит в позиции n. Очевидно, ‘Z’ стоит в позиции p+n. Берём случайное число от 0 до p, а прибавив n получаем число из интервала от n до n+p. Простая арифметика, которая не для всех кажется простой.
Итак, код символа мы получили — осталось только добавить соответствующий символ в нашу строку. Функция Chr() возвращает символ с указанным кодом.
Для справки: очень часто, глядя на такой код, говорят, что он не оптимален — мол, коды символов будут постоянно рассчитываться (речь о функции Ord). Однако знающие люди никогда этого не скажут, ведь в Delphi есть маленькая хитрость: компилятор вычислит эти значения ещё на этапе компиляции и в программе они будут просто константами. Т.е.
Ord(‘Z’) и Ord(‘A’) в программе не будут считаться никогда — там будут стоять вполне реальные числа, а значит никакого избытка вычислений идти не будет. Более того, даже вычитание будет произведено на этапе компиляции, ведь оба слагаемых являются константами. Мы пишем Ord(‘A’) и Ord(‘Z’) только из-за того, чтобы не лезть в кодовую таблицу, и не смотреть вручную коды этих символов. Кроме того, если вместо этого записать реальные коды, другой человек может испытать затруднение при чтении кода — он ведь не знает, откуда вы взяли эти числа и не помнит всю кодовую таблицу, чтобы определить, каким символам эти числа соответствуют.
Далее полученная строка s добавляется в Memo1 уже известным способом. А вот последняя строка в теле цикла — это маленькая хитрость. В одном из уроков об этой команде уже упоминалось. Дело в том, что при отсутствии этой команды программа просто зависнет с точки зрения пользовательского интерфейса — никаких изменений в Memo видно не будет, да и само окно перестанет реагировать на щелчки.
На самом деле, конечно, программа будет работать, в памяти генерация строк будет идти полным ходом. Команда Application.ProcessMessages заставляет приложение обработать всю очередь задач, в том числе по отрисовке окна программы и элементов формы. Если при генерации каждой строки это будет происходить, программа будет выглядеть вполне живой — можно будет легко переместить окно по экрану и, что самое главное, нажать на заветную кнопку «Стоп». Ради эксперимента попробуйте убрать эту строку, и посмотреть, что получится.
Как было сказано ранее, такой способ является не совсем верным. В серьёзных программах программировать процессы таким образом не допускается. Для параллельного выполнения операций, которые не должны мешать друг другу, существуют потоки, т.е. когда процессы работают одновременно, а сама программа при этом ими управляет.
У потоков очень много преимуществ — поток можно легко остановить, можно задать его приоритет и др. Работа с потоками достаточно сложна для начинающих программистов, поэтому мы пока ограничимся тем примером, что был приведён выше. В конце концов, наш урок посвящён циклам.
Подводим итог
Итак, мы познакомились с циклами — специальными конструкциями языка для многократного выполнения одних и тех же команд. Как правило, циклы встречаются практически везде, даже в простых на первый взгляд программах. Что уж говорить о каких-либо вычислениях или работе с базами данных.
Источник: dzen.ru
Цикл с постусловием repeat
Оператор repeat , как и оператор while , используется в программе в том случае, если необходимо выполнить повторные вычисления (организовать цикл), но число повторений во время разработки программы неизвестно и может быть определено только во время работы программы, т. е. определяется ходом вычислений. В общем виде оператор repeat записывается следующим образом: repeat последовательность операторов until условие Условие в данном случае — это выражение логического типа, определяющее, условие завершения цикла. Тело цикла с постусловием заключено между служебными словами repeat и until , поэтому заключать его в блок (т.е. между ключевыми словами begin и end ) не требуется.
7 Оператор repeat выполняется следующим образом: 1) Сначала выполняются находящиеся между repeat и until операторы тела цикла. 2) Затем вычисляется значение выражения условие . 3) Если условие ложно (значение выражения условие равно false ), то операторы тела цикла выполняются еще раз. 4) Если условие истинно (значение выражения условие равно true ), то выполнение цикла прекращается. Таким образом, в отличие от цикла while , операторы цикла, находящиеся между ключевыми словами repeat и unti1 , выполняются до тех пор, пока условие ложно (т.е. значение выражения условие равно false ). Алгоритм, соответствующий оператору repeat , представлен на рис. 2. Рис. 2. Алгоритм, соответствующий оператору repeat
Операторы тела цикла, находящиеся между repeat и until , выполняются как минимум один раз. Для того чтобы цикл завершился,
8 необходимо, чтобы операторы тела цикла, располагающиеся между repeat и until , изменяли значения переменных, входящих в выражение условие . Этот вид цикла применяется в тех случаях, когда тело цикла необходимо обязательно выполнить хотя бы один раз: например, если в цикле вводятся данные и выполняется их проверка. Разберем примеры оператора repeat . Пример 6.3 . repeat x:=x+1; y:=y-1; until (x>=2) and (y<4); Рассмотрим особенности выполнения данного оператора для случая, если перед выполнением оператора переменной x типа integer было присвоено значение x=0 , а переменной y типа integer было присвоено значение y=5 . 1) Сначала выполняются операторы тела цикла: x:=x+1; y:=y-1; Т.е. значение переменной x становится равным x=1 , а значение переменной y становится равным y=4 . 2) Затем вычисляется значение логического выражения: (x>=2) and (y<4) . 3) Т.к. значение выражения (1>=2) and (4<4) равно false , то заново выполняются операторы тела цикла: x:=x+1; y:=y-1; Т.е. значение переменной x становится равным x=2 , а значение переменной y становится равным y=3 . 4) Снова вычисляется значение логического выражения:
Цикл с параметром for
Оператор for используется в том случае, если некоторую последовательность действий (операторов программы) нужно выполнить несколько раз, причем число повторений заранее известно. В качестве параметра в данном операторе используются переменные порядкового типа, причем, как правило, целого типа. Рассмотрим особенности оператора for как раз для случая, когда параметр принимает целый тип, т.е. является счетчиком.
10 В общем виде оператор for записывается следующим образом: for счетчик := нач_знач to кон_знач do begin последовательность операторов end В данной записи оператора for были использованы следующие обозначения: 1) счетчик — переменная целого типа, представляющая собой число повторений операторов тела цикла; 2) нач_знач — выражение целого типа, определяющее начальное значение параметра цикла; 3) кон_знач — выражение целого типа, определяющее конечное значение параметра цикла. Количество повторений операторов тела цикла можно вычислить по формуле: кон_знач — нач_знач + l. Если в теле цикла находится только один оператор, то ключевые слова begin и end можно не писать. Алгоритм, соответствующий оператору for , представлен на рис. 3.
11 Рис. 3. Алгоритм оператора for (при использовании ключевого слова to ) Согласно рис. 3, выполнение оператора for происходит следующим образом: 1) Вычисляются выражения, определяющие начальное и конечное значения счетчика. Эти выражения вычисляются только один раз, при входе в цикл.
2) Счетчику цикла присваивается значение выражения нач_знач . 3) Значение счетчика цикла сравнивается со значением выражения кон_знач . Если счетчик цикла меньше или равен этому значению, то выполняется тело цикла, в противном случае выполнение цикла заканчивается. 4) Значение счетчика цикла автоматически увеличивается на 1. Происходит возврат к пункту 3. Таким образом, если начальное значение счетчика меньше или равно конечному, то последовательность операторов между begin и end будет выполнена хотя бы один раз. Если же начальное значение счетчика больше
12 конечного значения, то последовательность операторов между begin и end не будет выполнена ни разу. Переменную-счетчик можно использовать внутри цикла, но ни в коем случае не изменять. После нормального завершения цикла значение счетчика не определено.
Фактически оно равно первому значению, для которого выполняется условие выхода из цикла, но использовать это в программах не рекомендуется. Если в операторе for вместо ключевого слова to записать downto , то после очередного выполнения операторов тела цикла значение счетчика будет не увеличиваться, а уменьшаться на 1, и, следовательно, тело цикла выполнится хотя бы один раз только в случае, если конечное значение счетчика меньше или равно начальному (рис. 4). Рис. 4. Алгоритм оператора for (при использовании ключевого слова downto ) Разберем примеры оператора for . Пример 6.4 .
13 for i:=2 to 5 do begin x:=x+sqr(y); y:=y-1; end; В данном примере переменные i , x , y имеют тип integer . Число повторений данного цикла равно 4, в соответствии с формулой, рассмотренной выше: кон_знач — нач_знач + l = 5 – 2 + 1 = 4. Таким образом, операторы тела цикла будут выполнены 4 раза. Рассмотрим особенности выполнения этого цикла более детально. Пусть до начала выполнения цикла переменные x и y приняли соответственно значения x=1 и y=3 . 1) В первую очередь переменная-счетчик i принимает начальное значение, равное i=2 . 2) Далее вычисляется значение логического выражения i>5 , т.е. значение счетчика сравнивается с конечным значением. Т.к. выражение 2>5 равно false , то выполняются операторы тела цикла: x:=x+sqr(y); y:=y-1; Таким образом, значения переменных x и y становятся равными x=10 и y=2 соответственно. 3) Значение счетчика увеличивается на 1, т.е. переменная i становится равной i=3 . 4) Снова вычисляется значение логического выражения i>5 . Т.к. выражение 3>5 равно false , то выполняются операторы тела цикла. Таким образом, значения переменных x и y становятся равными x=14 и y=1 . 5) Значение счетчика увеличивается на 1, т.е. переменная i становится равной i=4 .
14 6) Снова вычисляется значение логического выражения i>5 . Т.к. выражение 4>5 равно false , то выполняются операторы тела цикла. Таким образом, значения переменных x и y становятся равными x=15 и y=0 . 7) Значение счетчика увеличивается на 1, т.е. переменная i становится равной i=5 . 8) Заново вычисляется значение логического выражения i>5 . Т.к. выражение 5>5 равно false , то выполняются операторы тела цикла.
Таким образом, значения переменных x и y становятся равными x=15 и y=-1 . 9) Значение счетчика увеличивается на 1, т.е. переменная i становится равной i=6 . 10) Вычисляется значение логического выражения i>5 . Т.к. выражение 6>5 равно true , то выполнение цикла завершается. Пример 6.5 . for j:=4 to 3 do z:=abs(x+y); В данном примере переменные j , x , y , z имеют тип integer . Поскольку в данном случае начальное значение счетчика больше конечного значения, то оператор тела цикла не будет выполнен ни разу.
Рассмотрим особенности выполнения этого цикла более детально, в соответствии с блок-схемой на рис. 3: 1) В первую очередь переменная-счетчик j принимает начальное значение, равное j=4 . 2) Далее вычисляется значение логического выражения j>3 , т.е. значение счетчика сравнивается с конечным значением. Т.к. выражение 4>3 равно true , то выполнение цикла завершается. Таким образом, операторы тела цикла не выполнились ни разу. Пример 6.6 . for i:=3 downto 1 do x:=x+sqr(i);
15 В данном примере переменные i и x имеют тип integer . Рассмотрим особенности выполнения этого цикла более детально. Пусть до начала выполнения цикла переменная x приняла значение x=100 . 1) В первую очередь переменная-счетчик i принимает начальное значение, равное i=3 . 2) Далее вычисляется значение логического выражения i
Источник: studfile.net
Оператор цикла с постусловием
В языке C++ этот оператор отличается от классической реализации цикла с постусловием тем, что при истинности выражения происходит продолжение работы цикла, а не выход из цикла.
Оператор пошагового цикла.
Тело оператора forвыполняется до тех пор, пока условное выражение не станет ложным (равным 0).Начальное выражение и выражение приращения обычно используются для инициализации и модификации параметров цикла и других значений. Любое из трех выражений заголовка цикла, и даже все три могут быть опущены.
Если опущено условное выражение, то оно считается истинным, и цикл становится бесконечным.
Оператор безусловного перехода
Оператор безусловного перехода прерывает выполнение операторов while, do, forи switch. Он может содержаться только в теле этих операторов. Управление передается оператору программы, следующему за прерванным. Если оператор безусловного перехода записан внутри вложенных операторов while, do, for, switch, то он завершает только непосредственно охватывающий его оператор.
Оператор продолжения передает управление на следующую итерацию в операторах цикла while, do, for. Он может содержаться только в теле этих операторов. В операторах doи whileследующая итерация начинается с вычисления условного выражения. В операторе forследующая итерация начинается с вычисления выражения приращения, а затем происходит вычисление условного выражения.
Оператора возврата заканчивает выполнение функции, в которой он содержится, и возвращает управление в вызывающую функцию. Управление передается в точку вызывающей функции, непосредственно следующую за оператором вызова. Значение выражения, если она задано, вычисляется, приводится к типу, объявленному для функции, содержащей оператор возврата, и возвращается в вызывающую функцию. Если выражение опущено, то возвращаемое функцией значение не определено.
С формальной точки зрения операторы break, continueи returnне являются операторами структурного программирования. Однако их использование в ограниченных количествах оправдано, когда они упрощают понимание программы и позволяют избегать больших вложенных структур. Например, мы проверяем входные данные на аномалии. Если не использовать эти операторы, то всю обработку придется вложить в условный блок, что ухудшает читабельность программы. Вместо этого можно написать небольшой условный блок, который организует выход из функции при неверных исходных данных.
Ввод/выводне является частью языка С++, а осуществляется функциями, входящими в состав стандартной библиотеки.
В С++ отсутствуют операторы ввода-вывода, так как все операции ввода-вывода реализуются с помощью функций, которые находятся в библиотеке С++, поддерживающей три уровня ввода-вывода: потоковый ввод-вывод;
Описание объектов для управления вводом-выводом содержится в файле iostream.h.При подключении этого файла с помощью директивы #includeв программе автоматически создаются виртуальные каналы связи cinдля ввода с клавиатуры и coutдля вывода на экран, а также операции помещения в поток « и чтения из потока »
С помощью объекта cin и операции можно присвоить значение любой переменной. Например, если переменная x описана как целочисленная, то команда cin»x;означает, что в переменную xбудет записано некое целое число, введенное с клавиатуры. Если необходимо ввести несколько переменных, то следует написать cin»x»y»z;.
Объект coutи операция позволяет вывести на экран значение любой переменной или текст. Текст необходимо заключать в двойные кавычки. Запись cout»x;означает вывод на экран значения переменной x.
Вычислить и вывести на экран в виде таблицы значения функции F на интервале от xнач. до xкон. с шагом dx.
где a,b,c – действительные числа
Источник: csaa.ru