Вступление
Здраствуйте, те кто читает эту рассылку! |
|
Теория
Сегодня мы поговорим о циклах. Что это такое? Давайте представим, что вам необходимо вывести на экран слово ПРИВЕТ! двадцать раз. Писать: writeLn ('ПРИВЕТ'); 20 раз !!! А если нужно сто раз? А если заранее неизвестное число раз?? Как быть? Вот тут и нужны циклы. Этот цикл наиболее часто используется в программах ввиду его чрезвычайной удобности. Итак знакомтесь, цикл for! for i := 1 to 20 do writeLn ('Привет!'); Цикл записывается так for переменная_цикла := начальное_значение to конечное_значение do операторы; В нашем примере мы взяли в качестве переменной цикла взята переменная i, начальное значение 1, конечное - 20. Что это значит? А это значит, что цикл будет выполняться для i = 1, 2, 3, 4, 5 ... 19, 20. Т.е. 20 раз. Каждый раз мы прибавляем к i еденицу. При этом начальное и конечное значение переменной цикла может задаваться численным выражением (например for i := 1 to 3*65 do ....) или выражением с переменной (например for i := X + Y to X * Y / Z + 45 *j do ....). При этом эти значения вычисляются компилятором один раз перед выполнением цикла. Например, результат такой программы:
Будет таким :
Как видите предел i не поменялся, хотя х мы меняем! Использую цикл for нужно соблюдать следующее правило: не нужно менять переменную цикла (т.е. ту переменную, по которой идёт цикл, у нас это была i) внутри него. for i := 20 downto 1 do writeLn ('Привет!'); Теперь i = 20, 19, ... 2, 1. А так всё аннологично. Основное неудобство состоит в том, что мы не можем задавать закон изменения переменной цикла. Однако и это не так страшно, как кажется на первый взгляд.
Цикл номер два: while! Этот цикл называется циклом с предусловием. Записывается он так: while 1 do writeLn ('Привет!'); Приведёт к "зависанию" компьютера, т.к. выражение 1 всегда истинно (не могут же быть числа ложными). выйдти из этого цикла можно нажатием клавиши Ctrl+Break (Ctrl+C) - стандартный выход из ДОС программ. Проверка истистинности условия проводится как и в операторе if. i := 1; x := 10; while i <= x do begin writeLn (i, ' ', x); x := x + 1; i := i + 1 end; Попробуйте этот код... ну как эффект не тот? :) Давайте разберёмся в чём дело. А вся проблемма в том, что условие (максимальное значение) для цикла for считается зарание один раз заранее! А у нас оно всё время меняется. Ок. Теперь посмотрите результат программы: она останавливается при i = 32 757. Давайте посмотрим ещё один вариант: i := 1; x := 10; while i <> x do begin writeLn (i, ' ', x); x := x + 1; i := i + 1 end; Запустите и подождите немного.... СТОП! А откуда там отрицательные числа?? Ведь мы прибавляем каждый раз по 1 и 1, т.е. i и х растут ??? Давайте разберёмся по подробнее. Что из себя представляет числовая прямая? Это окружность максимального радиуса, т.е. радиуса бесконечность. Такая окружность вырождается в прямую. Однако для целых чисел (типа integer) эта "бесконечность" известна - 32767 (помните выпуск Типы данных?). Счечик i можно представить, как точку, которая движется по этой окружности. Когда i доходит до максимума, то она становится отрицательной, т.е. -32767!!
А помните предыдущий пример, где всё останавливалось при x = 32 767. Почему так вышло? Прибавляя к х = 32767 один что мы получаем: x + 1 = -32767 !!!! А условие цикла у нас стоит i <= x т.е. когда х = 32 767 i = 32 757, далее х + 1 = -32 767 i + 1 = 32 758 т.е. условие i <= x не выполняется! И поэтому мы выходим из цикла! Теперь напишем нормальный вариант цикла for через цикл while: i := 1; x := 10; Temp := x; while i <= Temp do begin writeLn (i, ' ', x); x := x + 1; i := i + 1 end; Здесь мы заранее посчиталь верхнюю границу цикла в переменную temp и тем самым всё работает правильно. Ну вот мы подошли к последнему циклу. Он называется цикл с постусловием, цикл: repeat-until ! Этот цикл в общем и целом анологичен while, но есть два отличия. Вот как он записывается: repeat оператор until условие; Итак его отличия от while:
Давайте же рассмотрим какой-нить пример: i := 10; repeat writeLn (i); i := i - 1 until i = 0; Этот цикл выполняется пока i не равно нулю. Т.е. для значений i = 10, 9, 8 ..... 2, 1. Обратите внимание, что мы не используем операторы begin-end т.к. этот цикл доспукает использовать в своём теле сколько хочешь операторов в отличие от while и for. Вот написал и вспомнил о том, что не сказал, что такое тело цикла :( Вот дырявая башка! Итак тело цикла - это та последовательность операторов, которая выполниется. Т.е. например все операторы между repeat и until - это и есть тело цикла. |
|
Программа
Итак сегодня мы продолжим изучать Отладчик и напишем ещё одну программу.
Давайте же помотрим результат!!!! Запускаем вводим число... ЧТО ЭТО ЗА НАФИГ??? Почему 0? ... запускаем вновь ... опять 0! Досада. Видимо в программу залезла логическая ошибка! Ну вот теперь мы познаем всю мощь отладчика! begin ClrScr; Write ('Какое значение? '); ReadLn (n); Выглядят довольно понятно и ошибка явно не в них. Так зачем же нам тратить наше драгоценное время на их пошаговое исполнение? Давайте сразу же перейдем к следующей строке. Наведите на неё курсор и нажмите Ctrl+F8 (меню Debug - > Add breakpoint) Она подсветится красным цветом. Что же такого чудесного мы сделали? А вот что: мы добавили breakpoint (по-русски: брякпоинт, бряк:) - точку остановки. Когда исполнение программы дойдёт до этой строчки, то мы сразуже перейдём в режим по-шагового исполнения. Увидите список бряков можно Debug -> Breakpoints.
Второе на мой взгляд несколько предпочтительнее :) Давайте сделаем вот что: выберем Debug -> Add Watch или Ctrl+F7 - в появившемся диалоге укажем имя нашей переменной: Result (в поле Watch expression) Появится окно watches (если не появилось, то Debug -> Watch). В нём вы увидите значение переменной Result. Так же можно для практики добавить туда и переменные i и n. Так тепрь мы можем наблюдать, что же там внутри и как меняются переменные.
Ну вот, теперь запускаем программу (Ctrl+F9), вводим для примера 5 и сразу же оказываемся внутри программы. Входим в цикл (давим F8)... Заметьте, что я специально добавил в цикл конструкцию begin-end (в неё нет надобности). Я это сделал, что бы при отладке внутри цикла у нас подсветка двигалась :) а иначе она просто будет висеть на строчке: Result := Result * i; и создаётся впечатление остановки программы. Итак проходим первый этап цикла (i = 0) опа!! Вот оно! Result сразу же изменился на 0 ! Давайте посмотрим, что же будет дальше... а дальше он так и останется 0. Можно заметить, что мы умножаем Result на i, но ведь в начале цикла i = 0 т.е. мы умножаем на 0 и поэтому Result всегда 0! УРА! Нашли ошибку! Прервём исполнение программы (Ctrl+F2). Для устранения ошибки мы сделаем следующее: в цикле i должно изменяться от 1 до n. Я надеюсь, что переписать программу для вас не составит труда. Итак исправим, уберём бряк (на той строчке Ctrl+F8)
Запустим программу... ВОТ ЧЁРТ! Теперь Result не 0 но очень уж большой!!!! В чём же дело?? Давайте повторим всё заново: поставим бряк и запустим её снова... введём 5... Постойте ка а почему это у нас Result в начале равен 5?? Ведь факториал это произведение от 1 до n ??? Да вот же в чём дело! Мы вначале присваиваем Result := n; А надо так: Result := 1; Теперь всё нормально! Ещё одна мелочь, которая не сразу бросается в глаза: переменная Result у нас типа longint, однако и этого не достаточно, что бы вместить факториалы чисел больше 31! Как подсчитать факториал для любых чисел мы поговорим попозже. Обязательно поговорим! |
|
ГолосованиеИтак в прошлый раз нам было интересно узнать, что вы думаете по поводу нового дизайна рассылки. Так вот только после выхода выяснилось, что в почтовой программе the Bat! некоторые места отображаются некорректно. Поэтому лучше чиать странику в Opere'e или ещё лучше в Internet Explorer'e. Соответственно дизайн рассылки некоторое время останется неизменным, а потом мы чего-нибудь придумаем получше. Кстате голосование доступно до 5 ноября по этой ссылке. |
|
ПослесловиеЗа сим позвольте откланятся. |