[an error occurred while processing this directive]

.шп2

3. ОСОБЕННОСТИ ПРИМЕНЕНИЯ НЕКОТОРЫХ ОПЕРАТОРОВ.

.шп0

3.1 Операторы FOR и NEXT.

Операторы FOR и NEXT используются также часто, как, скажем, оператор VTAB. И программисты иногда допускают в них логические ошибки. Такие ошибки иногда бывает обнаружить так трудно, что на это уходит очень много времени. Ниже мы рассмотрим особенности применения операторов FOR и NEXT.

Синтаксис операторов:

.шп2

FOR I=X TO Y STEP Z: ..... :NEXT I

.шп0

Где, I - счетчик цикла;
     X - начальное значение счетчика цикла;
     Y - конечное значение;
     Z - шаг цикла (при шаге=1 оператор STEP 1 можно опустить).

..... - точками показано 'Тело цикла' которое может содержать один оператор или несколько, а также может содержать другие циклы или обращения к подпрограммам.

Параметры X,Y,Z могут быть константами, переменными или выражениями. Например: FOR I=23*2-1 TO A(6)*2 STEP C(U).

Цикл (в упрощении) работает следующим образом. Например у нас есть цикл:

   FOR I=1 TO 3: PRINT: NEXT I

а) Счетчик цикла принимает значение I=1, выполняет оператор PRINT, и когда встречает оператор NEXT I увеличивает значение счетчика на 1 (теперь I=2), затем значение счетчика цикла сравнивается с конечным значением цикла, и если счетчик цикла больше конечного значения, то цикл заканчивается.

.сс

б) i=2, выполняется оператор PRINT, встречая NEXT I увеличивает значение счетчика на 1 (теперь I=3) и делает проверку, т.к. счетчик =3, но не больше, то цикл снова повторяется.

в) I=3, выполняется оператор PRINT, счетчик увеличивается на 1 (теперь I=4), при сравнении получается, что счетчик больше конечного значения, поэтому цикл заканчивается.

Как видно из примера цикл выполнил оператор PRINT три раза.

К отрицательной стороне цикла FOR и NEXT относится следующий момент:

Если задать цикл FOR I=3 TO 1 , то по идее цикл не должен выполниться ни разу. но поскольку проверка счетчика цикла производится только при прохождении оператора NEXT, то перед тем как мы попадем на оператор NEXT мы один раз выполним тело цикла, а затем пройдем проверку увеличив при этом счетчик цикла на 1. К этому моменту I=4 будет естественно больше 1, и цикл закончит работу. Тоже самое произойдет при выполнении цикла FOR I=1 TO 80 STEP 100.

Теперь рассмотрим программу:

   200 A=0:FOR I=1 TO 20: IF A=0 THEN 220
   210 NEXT I

   220 FOR J=1 TO 20
   225 FOR I=1 TO 20:NEXT I
   230 NEXT J
   240 ?"НОРМАЛЬНОЕ ЗАВЕРШЕНИЕ ПРОГРАММЫ"

Попробуйте набрать эту программу и запустить ее. Программа не закончится нормально. Вот что произойдет: в строке 200 программа перейдет к строке 220 т.к. выполняется условие А=0, затем программа пройдет строку 220, затем выполнит цикл в строке 225, а затем произойдет останов программы с выдачей ошибки:

 'NEXT БЕЗ FOR'
  230 NEXT J

Это произошло из-за того, что в строке 200 мы вышли из цикла минуя оператор NEXT I (строка 210). Итак мы пришли к тому, что для написания надежных программ все циклы FOR должны выходить через NEXT , а не минуя их. Конечно эту ошибку можно обойти, но это не дает гарантии, что из-за нее в следующем цикле не произойдет ошибки.

В таком случае возникает вопрос, как поступить если из цикла необходимо выйти не нарушая при этом последовательности цикла, но и не выполняя при этом ни одного раза тела цикла. Правильное решение несет за собой некоторое увеличение программы. Но автор считает, что лучше писать длинные и надежные программы, чем короткие и ненадежные. Рассмотрим пример, как это можно реализовать:

   200 K%=0:FOR I=1 TO 100:RIBBON=3:HTAB6
   210 IF I=10 THEN K%=I:I=100:GOTO230
   220 PRINT I*I
   230 NEXT I
   235 IF K%>0 THEN END
   240 FOR J=1 TO 10
   250 FOR I=1 TO 20:NEXT I
   260 NEXT J

.сс

Программа напечатает первые 9 чисел, которые являются квадратами чисел от 1 до 9. На 10-м шагу цикла выполнится условие I=10 и программа выполнит следующие действия:

а) переменной K% присвоит текущее значение счетчика I. в данном примере это не нужно, но в некоторых программах требуется знать значение счетчика на котором произошел выход из цикла

б) Переменной I будет присвоено значение 100 т.к. конечное значение цикла. Это нужно для выхода из цикла

в) Затем программа уйдет на NEXT минуя тело цикла. Там значение счетчика будет увеличено на 1 и цикл завершится т.к. I станет равно 101.

Условие в строке 235 необходимо вот для чего. К строке 235 мы перейдем в любом случае выполнилось условие в строке 210 или нет, но если условие не выполнялось, то нужно продолжить действия, а если выполнялось нужно выйти в другое место (например в меню). Для этого служит проверка в строке 235. Ведь если условие (210) не выполнилось, то K% будет равно 0, а если условие (210) выполнялось то K% будет иметь значение от 1 до 100.

3.2 Операторы GOSUB, RETURN и POP.

Синтаксис операторов:

.шп2;GOSUB XXX

.шп0;- обратиться к подпрограмме в строке XXX.

.шп2;RETURN

.шп0;- возврат из подпрограммы.

.шп2;POP

.шп0;- удаление из стека последнего адреса возврата.

Механизм действия операторов GOSUB, RETURN и POP следующий. Выполняя оператор GOSUB интерпретатор Бейсика запоминает то место, в котором находится оператор, т.е. заносит в стек место расположения оператора GOSUB. Затем уходит на подпрограмму, выполфяет ее и встречая оператор RETURN вспоминает из стека адрес откуда был сделан вызов подпрограммы, т.е. место расположения оператора GOSUB. Затем интерпретатор выполняет следующий за оператором GOSUB оператор, независимо от того, где этот оператор находится, в следующей строке или в этой же. Механизм действия оператора POP проще об'яснить на примере:

   100 K=9:GOSUB200
   110 END
   200 GOSUB300
   210 ?"ПРИ К=9 ЭТО МЕСТО НЕ ВЫПОЛНИТСЯ"
   220 RETURN
   300 IF K=9 THEN POP
   310 RETURN

Программа исполняя операторы уйдет на подпрограмму 200, запомнив в стеке, что нужно вернуться в строку 100. Затем на подпрограмму 300, запомнив в стеке, что нужно вернуться на строку 200. Здесь выполняя условие K=9 программа выполнит оператор POP т.е. снимет верхнее значение со стека (а это номер строки 200) и выполнит оператор RETURN. Сначала в стеке не было ничего. Затем там появился номер строки 100, затем номер строки 200, затем выполняя POP мы удалили со стека верхнее значение т.е. 200. Теперь при выполнении оператора RETURN со стека будет снято значение 100 и произойдет возврат к строке 100. Следующим оператором за GOSUB200 идет END и программа завершит свою работу не выполнив операторы в строках 210 и 220. Для выполнения этих операторов поменяйте значение К в строке 100 и Вы увидите как программа напечатает на экране 'При К=9 это место не выполнится'.

.сс

В примере были использованы вложенные подпрограммы. Бейсик позволяет обращаться из одной подпрограммы в другую. Таким образом УРОВЕНЬ ПОДПРОГРАММЫ - это степень вложенности подпрограммы в данном выполнении программы. В примере приведенном выше подпрограмма в строке 200 является подпрограммой 1-го уровня, а подпрограмма в строке 300 подпрограмма 2-го уровня. Но уровень одной и той же подпрограммы может быть разным. Поясним это на примере:

   100 GOSUB200
   110 GOSUB300
   120 END
   ............

   200 GOSUB300
   210 GOSUB400
   220 RETURN
   ............

   300 RETURN
   ............

   400 RETURN

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

Это может стать источником ошибок при использовании оператора POP. Так как операторы: POP:GOTO100 справедливы только для подпрограмм 1-го уровня. Причем ошибка может возникнуть незаметно. Например у Вас есть подпрограмма 1-го уровня использующая операторы 750 POP:GOTO XXX. В результате доработки Вам понадобилось еще раз ей воспользоваться и Вы безо всяких сомнений ставите GOSUB750. Но при этом забываете, что делаете обращение из подпрограммы и вследствие этого строка 750 это уже подпрограмма 2-го уровня. Поэтому цепочка POP:GOTO XXX в данном случаее является ошибкой.

Причем вся проблема в том, что этот кусочек все-таки выполнится но в стеке останется неснятым одно значение, т.к. GOSUB мы делали 2 раза а RETURN (в данном случае POP) , только 1. Причем после каждого выполнения этого кусочка программы на стеке будет появляться еще одно значение. Так будет продолжаться пока стек возвратов не заполнится полностью, тогда при выполнении первого же оператора GOSUB будет выдана ошибка 'МАЛО ПАМЯТИ В' и далее номер строки в которой произошел останов. Но если даже Вы и догадаетесь, что это произошло от неправильного использования стека возвратов, то найти источник ошибки будет очень трудно т.к. при переполнении стека останов происходит на первом же операторе GOSUB, который работает вполне нормально и от реального источника ошибки отстоит на сотни строк.

.сс

3.3 Оператор IF.

Синтаксис оператора:

.шп2;IF XXX then YYY

.шп0

Механизм работы оператора следующий: если выполняется условие XXX, тогда выполнить операторы YYY.

Под XXX подразумевается условие простое или сложное. Но в любом результатом условия является Булево значение 'Истина' или 'Ложь'. Истина это '1', ложь - '0', т.е. при проверке условия XXX всегда вырабатывается значение 1 или 0, и если условие истинно, то выполняются операторы YYY. Простой пример: IF X=0 THEN K=9.

В выражении XXX могут применяться следующие логические операции:

"="   - проверка на равенство
">"   - проверка на больше
"<"   - меньше
"<>"  - не равно
"=>"  - больше или равно
"<="  - меньше или равно
"AND" - логическое И
"OR"  - логическое ИЛИ
"NOT" - логическое НЕ

Пример: IF (X1>X2 OR L2+40=169) AND (I=5 OR K>=0 THEN STOP

После оператора THEN могут соять операторы и присваивания, а также разрешается указывать номер строки на которую необходимо осуществить переход, например: IF K=5 THEN 250. При выполнении условия произойдет переход к строке 250. Этот переход аналогичен действию оператора GOTO.

Допускается такая форма записи: IF K% then y=y+1. В данном примере условие выполняется если переменная K% отлична от нуля. Это немного сокращает запись, хотя не совсем удобно при чтении текста программы. Такую форму записи можно использовать только в тех случаях, когда K% принимает значения 'нуля' или 'не нуля'.

3.4 Оператор RUN.

Синтаксис оператора:

.шп2;RUN NNN

.шп0; - запуск программы со строки NNN.

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

[an error occurred while processing this directive]