43
Циклы, циклы, циклы…
Кандидат физико-математических наук
Л. Ф. ШТЕРНБЕРГ
Программирование потеряло бы многое, если бы не было понятия ветвления или вспомогательного алгоритма, но все же сердце программы — это циклы. Однако раз написанная команда, стояшая внутри цикла, будет выполнять многоратно — это и придает смысл работе по составлению программы.
Работе команды потеряния отвечено 3 страницы в учебнике 9 класса, и с ее помощью решается много задач. Еще 2 страницы теории отвечено ей в учебнике «Информаτικά-10» *); вводится дополнительная конструкция — цикл для, которая удобна, но без которой можно было бы и обойтись. Так что же можно сказать о циклах? Komy неопоняна фраза на русском языке
пока условие потерять действия кц, из которого и получается команда
*) Так автор кратко называет учебное пособие «Основы информатики и вычислительной техники», Примеч. ред.)
повторения (если заменить слово «повторять» словом «нцц»)? Мы и далее в записи команд цикла будем использовать слово «повторять» — записанный так цикл легче читать и поннимать. И все-tаки циклы бывают разные.
Начнем с простейшей задачи: с помощью описанного на c. 78—81 учебника «Информаτικά-9» графический исполнитель нарисовать нотный стан с длиной линии 50 и расстоянием между линиями 3. Это можно сделать такой программиной (здесь и далее мы будем писать только программы, без заголовка и без описаний):
k:=1;
пока k≤5 повторять
направо (90); рисуй; вперед (50);
не рисуй; назад (50);
налево (90); вперед (3);
k:=k+1
кц
Если бы нашим исполнительом командоваал человек, не знакомый с программированием, то он был сказал так: «выполнить 5 раз следующее: направо (90); рисуй … вперед (3)». И действительно: переменная k нужна нам только для того, чтобы считать количество потеряний цикла, в теле цикла она нам не нужна; но исполнитель-то об этом не знает, и он честно завершет переменную k и будет записьать туда текущее значение k: а вдруг его будут использовать в те-
45
i:=0; y:=a[0];
пока i≠n повторять
i:=i+1; y:=y·x+a[i]
кц
Посмотрите на переменную i: на каждом шаге цикла она изменяется на одно и то же значение (в данном случае на 1), и именно по этой переменной определяется, когда надо кончать цикл. Пропистайте учебник — почти на каждой странице вы найдете цикл, в котором какая-то переменная каждой раз изменяется на одно и то же значение, и именно по ее значению определяется завершение работы цикла. Такая ситуация встречается очень часто, поэтому такие циклы получили специальное название — циклы с параметром.
Параметром цикла называется та самая переменная, которая меняется одинаковым образом и служит для определения окончания работы цикла. Есть для них и специальная форма записи:
меняя параметр от значения 1 шагом значение 2
до значения 3 повторять действия кц
Смысл этой конструкции, как всегда, соответствует значению фразы на русском языке. С ее помощью алгоритм схемы Горнера можно записать
y:=a[0];
меняя i от 1 шагом 1 до n повторять
y:=y·x+a[i]
кц
Как видим, здесь заголовок цикла возвращ в себя и установку начального значения параметра, и изменение его, и проверку на окончание цикла. При этом шаг, если он равен единице, можно не задавать. Так, в нашем случае можно записать
меняя i от 1 до n повторять
Такой цикл имеется практическим во всех языках программирования, но по традиции имеет чуть другую форму записи:
для … от … шаг … до … цикл и называется еще «цикл для». Именно в таком виде он есть в языках Panipa, ПЛ/1, Аллол-60, Аллол-68 и т. д. При этом в некоторых языках (Фортран, например, или школьный алгоритмический язык) сначала задается конечное значение, а затем шаг, а в некоторых (ПЛ/1) — можно писать и так, и так.
Почему же эта конструкция цикла появилась в учебнике «Информация-10»? На первый взгляд этот цикл, как и цикл повторять … раз, не дает нам ничего нового — только запись стала подобнее: вместе
x:=a;
пока x≤b повторять
… x:=x+h;
кц
пишем
меняя x от a шагом h до b повторять … кц и все. Но это не совсем так: например, если a=0, b=1, a h=0,1, то оба цикла сравотают одинаково, но если h=-0,1, то цикл показится (значение a никакогда не станет больше b), а цикл с параметром просто не выполняется ни одного раза: дело в том, что в этом цикле не просто проверяется условие «x≤b», а контрольуется нахождение значения параметра между a и b; при попытке выйти из диапазона в любую сторону, в частности, если шаг направлен не к b, а в обратную сторону, цикл выполнять не будет. Итак, цикл с параметром, как и цикл повторять …
раз — это защитеная конструкция: такие циклы никакогда не защищаются.
Уражение с применением цикла для (цикла меняя) алгоритмы МИНЭЛЕМЕНТ и УПОРЯДОЧЕНИЕ (A7, A8 на c. 93, «Информация-9»).
Но и у цикла с параметром может встречаться ситуация, когда заранее не ясно, сколько надо сделать шагов изменения параметра. Например, пусть в таблице из M элементов надо найти позицию, в которой встречается элемент, равный i. Для поиска элемента надо просмотреть таблицу элемента за элементом, меняя индекс на 1, но сколько шагов надо сделать — это заранее неизвестно. Справиться с этой задачей нам помогет грибид из цикла меняя и цикла пока:
меняя i от 1 шагом 1 пока a[i]≠x повторять кц Обратите внимание: тело цикла пустое — все, что надо, выполняет заголовок цикла; выход из цикла произойдет, когда a[i]=x, при том в i останется номер того элемента таблицы, на котором перевался цикл.
Такой цикл есть в языке ПЛ/1.
Понятно, что можно образовать и гибрид
меня … от … шаг … повторять … до … , в котором изменяется параметр, а проверка произойдет в конце. Приведенный выше метод поиска нужного элемента в таблице будет работать только тогда, когда мы уверены в
46
том, что искомый элемент в таблице есть. Если его нет, то через шагов значение выйдет за границу таблицы, и нам будет выдано сообщение об ошибке, либо же ЭВМ начнет делать что-то непредсказуемое. Изменим наш алгоритм так, чтобы при отсутствии нужного элемента он давал нам, например, нулевое значение номера. Каазалось бы, можно сделать так:
меняя от 1 шагом 1 показа и повторять кц;
если то ; все;
но так делать нельзя: если нужно элемента нет, то на шаг , даже убедившись в том, что , ЭВМ все равно попробует сравнить несуществующий элемент с — и может дать сообщение об ошибке. Заглянув в учебник на с. 57, мы найдем способ выкрутиться из этого положения ценой введения дополнительной переменной и дополнительных сравнений (число сравнения придает ни много ни мало — удвоить), и изучив его, признаем, что не каждый смог бы его самостоятельно придумать. Вот если бы нам удалось заставить ЭВМ сначала сравнить с , а второе сравнение проводить только при положительной результате первого сравнения…
Но читатель уже, наверное, понял основную нашу мысль: если нам неудобно работать, значит, нам чего-то не хватает и это «что-то» надо вести. А не хватает нам возможность выполнять две отдельные проверки и два выход из цикла: по обнаружению элемента и по исчернинию таблицы. Если учесть, что задача поиска — это весма частая задача, то введение удобных средств для поиска — не мелочь. Но признав, что в цикле может быть более одной причины выхода, не стоит ограничивать и думя. И вот в нашем алгоритмческом языке появляется мощная и удобная конструкция цикла, охватывающая почти все нужные случаи:
меняя … от … шагом … до …
пока … повторить … раз
тelo цикла
до … кц,
где может отсутствовать любая из подчерknутых частей, причем не должны присутствовать одновременно-