ГЛАВА II. ПРОГРАММИРОВАНИЕ ЛИНЕЙНЫХ АЛГОРИТМОВ Приступая к лечению, врач должен делать это изящно и весело; хмурый врач никогда не преуспеет в своем ремесле. М.Монтень Прежде чем переходить к непосредственному программированию, мы хотим дать два совета: 1) овладеть основами программирования можно лишь при условии повседнев- ной практики на вычислительной машине; 2) не рекомендуем читать описание языка программирования "просто так",в расчете на то,что "может быть, потом пригодится". Выберите задачу и начинайте составлять программу ее решения параллель- но с лекционным курсом.Тогда Вы поймете главное: зачем нужны и как исполь- зуются те или иные конструкции языка. Если по постановке Ваша задача отли- чается от задач, разобранных нами в качестве примеров, ищите аналогию в действиях. В процессе составления алгоритма и программирования учтите,что: 1. В любой сколь угодно малой программе есть, по крайней мере, одна ошибка. 2. Всякую программу можно сократить, по меньшей мере, на одну команду. 3. Начиная с некоторого уровня сложности программы, появление непред- виденной ошибки становится неизбежным. 4. Всякое непроверенное вычисление неверно. Из старинной книги "Заповеди программиста" 5. Человеку свойственно ошибаться, глупцу упорствовать (в своих ошиб- ках). Марк Туллий Цицерон 6. В программировании как в гольфе: любой может научиться за месяц, но в конце месяца программируют так же, как и играют: о ч е н ь п л о х о. J.R.Rice 7. ЭВМ многократно увеличивает некомпетентность вычислителя. Принцип некомпетентности Питера 8. Экспериментальное тестирование программ может служить для доказа- тельства наличия ошибок, но никогда не докажет их отсутствие. Н.Вирт 9. Умствуй - и придет! Л.Ф.Магницкий II.1. РЕЖИМЫ РАБОТЫ После одновременного нажатия на клавиатуре компьютера клавиш "CTRL" и "STOP"(что обозначается "CTRL"+"STOP") на экран дисплея выводится "систем- ная подсказка" "Ok" ("o'kay"-"о'кей, все в порядке"). С этого момента Вы можете работать в любом из двух режимов: 1. Режим прямого, или непосредственного, выполнения команд; ─────────────────────────────────────────────────────── при работе в режиме прямого выполнения команд на клавиатуре ЭВМ набирает- ся последовательность к о м а н д (указаний,предписаний), которая воспро- изводится на экране дисплея. Затем она вводится в оперативную память ком- пьютера нажатием клавиши ┌──────────┐ │ │ │ │ ◀──┘ │ , └──────────┘ которая имеет следующие названия: клавиша "RETURN", клавиша "возврата каретки-перевода строки", клавиша "ввода", "ENTER" ("to enter"-"вводить"), клавиша "CR"("Carriage Return"-"возврат каретки"), клавиша "клюшка" (шутливое название). Немедленно после этого вычислительное устройство ЭВМ выполняет данную по- следовательность команд. Сами команды после исполнения не запоминаются (теряются). ┌───────────────────────────────────────────────────────────────────────┐ │ Важно помнить,что ввести информацию в компьютер - это значит не только│ │ набрать на клавиатуре соответствующий текст, но и нажать после этого│ │ клавишу "RETURN"! │ └───────────────────────────────────────────────────────────────────────┘ Простейшие вычисления в режиме прямого выполнения команд производятся при помощи команд: LET и PRINT (см. разделы II.4.1. и II.4.4.). Например,вычисление значения арифметического выражения SQR(3^2+4^2) вы- полняется по команде: PRINT SQR(3^2+4^2) После набора этой команды на клавиатуре и введения ее в оперативную па- мять компьютера (нажатием клавиши "RETURN"), производится вычисление зна- чения арифметического выражения,стоящего справа от служебного слова PRINT. В результате на экране дисплея остается следующая информация: Ok PRINT SQR(3^2+4^2) 5 Ok Напомним, что признаком готовности ЭВМ к работе в режиме прямого выпол- нения команд является наличие "системной подсказки" "Ok" на экране дис- плея.Пока "Оk" не выведено на экран дисплея,Вы не можете обратиться к ЭВМ: она занята своей работой и только по окончании ее выводит на экран дис- плея "системную подсказку" "Ok"! Приведем еще пример: Ok print "Стремитесь к простоте программ." Заметим, что служебное слово print при вводе можно заменять символом "?", например: Ok ? "Стремитесь к простоте программ." После набора этой команды на клавиатуре и нажатия клавиши "RETURN", эк- ран дисплея примет следующий вид: Ok ? "Стремитесь к простоте программ." Стремитесь к простоте программ. Оk Таким образом, по указанной команде компьютер вывел на экран дисплея текст, который был заключен в кавычки. Появившееся после этого сообщение "Ok" свидетельствует о готовности интерпретатора (см. II.2) "принять" новую команду. Несколько следующих друг за другом команд прямого режима можно поме- щать на одной строке,которая называется к о м а н д н о й строкой. При этом команды одной командной строки отделяются друг от друга двоеточием. Максимально допустимое число символов в одной командной строке равно 255, поэтому длинная строка может занимать до семи 40 - символьных или четырех 80-символьных дисплейных (физических) строк. При вводе командной строки клавишу "RETURN" нажимают всего лишь один раз после набора последней ко- манды данной строки.Если при вводе командной строки дисплейная строка уже заполнена, то дальнейший текст а в т о м а т и ч е с к и переносится на следующую дисплейную строку (без какого-либо символа переноса). Н е о п а с а й т е с ь э т о г о! Прямой режим полезен при о т л а д к е программ и при использовании MSX-BASIC в качестве калькулятора для проведения коротких вычислений. П р и м е р ы: ───────────── 1) Ok 2) Ok 3) Ok print (5^2-7) ? SIN(ATN(1)*4/2) ? LOG(EXP(1)) 18 1 .99999999999986 Ok Ok Ok 4) Ok 5) Ok 6) Ok ? ATN(1)*4 ? 25.68MOD6.99 ? 15AND14 3.1415926535898 1 14 Ok Ok Ok 7) Оk 8) Ok 9) Ok print 25.68\6.99 ? (-1)OR(-2) print 3>1 4 -1 -1 Ok Ok Ok 10) Ok 11) Ok 12) Ok ? "BONY"+"'M" ? "1AAA"<"2aaa" ? (4<>4)AND(9<1) BONY'M -1 0 Ok Ok Ok 13) Ok 14) Ok 15) Ok ? 1/SIN(0) ? 1/COS(2*ATN(1)) ? TAN(2*ATN(1)) Division by zero -15915494309189 -15915494309189 Ok Ok Ok 16) Ok Ok ?(-32768%)/(-1%) однако... ? (-32768)/(-1) Owerflow 32768 Ok Ok Заметим, что арифметические, логические и строковые выражения, стоящие после служебного слова PRINT, могут содержать имена переменных.Разумеется, этим переменным до вычисления значения выражения должны быть присвоены на- чальные значения. Это осуществляется при помощи команды присваивания LET. 17) Ok 18) Ok LET A#=-1/3: PRINT ABS(A#*2)+2 DIM A(78):A(45)=SIN(4*ATN(1)) 2.6666666666667 :?A(45) Ok -1.2566370614359E-13 Ok Отметим,что служебное слово LET при записи команды присваивания можно опускать. 19) Длину окружности и площадь круга радиуса R=2 можно вычислить при помощи следующей последовательности команд: Ok PI=4*ATN(1):R=2:PRINT 2*PI*R:PRINT PI*R^2 12.566370614359 12.566370614359 Ok Более того, команда PRINT в прямом режиме позволяет мгновенно перево- дить числа из двоичной, восьмеричной и шестнадцатеричной систем счисления в десятичную, например: 20) Ok 21) Ok 22) Ok ? &b11100111 print &hffff print &O4567 231 -1 2423 Ok Ok Ok 23) Ok 24) Ok 25) Ok ? &hff-&o7+&b11 ? &hffMOD&b10 ? &O3456/&HF2 251 1 7.595041322314 Ok Ok Ok 2. Режим выполнения программы (или программмый режим); ────────────────────────── ───────────────── вначале ответим на вопрос: "Что же такое п р о г р а м м а ?" В "Матема- тической энциклопедии" (т.4, стр.646) читаем: "П р о г р а м м а - план действий, подлежащих выполнению некоторым исполнителем,обычно автоматичес- ким устройством, чаще всего ЭВМ; предписание,алгоритм. Программа представ- ляется в виде конечной совокупности о п е р а т о р о в (команд,инструк- ций), каждый из которых побуждает исполнителя выполнить некоторую элемен- тарную операцию над данными, хранящимися в памяти исполнителя, и имена ко- торых являются параметрами оператора. Автоматизм исполнения достигается тем, что любой текущий оператор, кроме завершающего, указывает однозначно на оператор программы, который должен выполняться после текущего...". Итак,вместо того, чтобы вводить команды в режиме непосредственного (не- медленного) исполнения, можно составить из них программу,которая будет вы- полняться позже в нужный момент.Такой способ работы с ЭВМ называется р е- ж и м о м в ы п о л н е н и я п р о г р а м м ы или п р о г р а м - м н ы м р е ж и м о м . В этом режиме команды обычно называются о п е- р а т о р а м и , хотя часто оба термина употребляются как синонимы. Это связано с тем, что большинство команд режима прямого выполнения можно ис- пользовать в качестве операторов режима выполнения программы и наоборот. Однако есть такие команды (например, AUTO, RENUM), которые целесообраз- но использовать только в режиме прямого выполнения, и такие операторы (на- пример, DATA,DEFFN), которые выполняются только в программном режиме. II.2. ИНТЕРПРЕТАТОРЫ И КОМПИЛЯТОРЫ BASIC - язык программирования высокого уровня. Это значит, что он уни- версален, не связан с конкретной вычислительной машиной. Чтобы программа, написанная на таком языке, могла быть исполнена на реальной ЭВМ, необходи- ма особая программа - т р а н с л я т о р, выполняющая роль переводчика на машинный язык.Благодаря наличию транслятора программист приобретает су- щественное удобство: ему нет нужды знать специфику конкретной машины.Напи- санная на языке высокого уровня, его программа становится,как говорят,"пе- реносимой" с одной ЭВМ на другую. Есть два основных типа трансляторов: и н т е р п р е т а т о р ы и к о м п и л я т о р ы . Для BASIC типичны первые, для многих других язы- ков программирования (например, Паскаля) - вторые. И н т е р п р е т а т о р работает как синхронный переводчик: он пыта- ется понять каждое очередное предложение (оператор) программы, то есть вы- разить его "смысл" в виде цепочки команд ЭВМ и тут же выполнить их. По-другому действует к о м п и л я т о р .Если продолжить аналогию,он работает как создатель добротного литературного перевода;он переводит про- грамму,как некий связный рассказ, учитывая взаимоотношения ее частей и вы- являя не только ошибки в отдельных элементах,но и несогласованности между ними.Требования к "правильности" программы у компилятора намного выше.Ком- пиляция часто производится за несколько просмотров программы. Программа при этом не исполняется: перевод готов, но "не звучит".Одна из причин это- го состоит в том, что компилируется программа обычно по частям (м о д у - л я м), особенно если она большая и сложная. Особая программа - к о м п о- н о в щ и к собирает отдельные модули, полученные после трансляции,в еди- ное целое: окончательный, готовый к исполнению м а ш и н н ы й к о д. Уже из этих кратких характеристик понятно, что интерпретатор намного проще в обращении. Вследствие этого BASIC позволяет непосредственно ощу- тить процесс программирования. Программа может быть составлена (даже не полностью) и тут же исполнена "на пробу". Программист может вмешиваться в процесс исполнения и сразу вносить необходимые коррективы в работу про- граммы, пока она еще не свободна от ошибок, а затем быстро исправлять ее текст с учетом пробного запуска и тут же повторять все эти действия снова. Для начинающего программиста, который часто ошибается, эти свойства языка, конечно,чрезвычайно привлекательны, поскольку ошибка во многих случаях об- наруживается легко и быстро. В некоторых других языках программирования (Pascal) обнаружение ошибки в программе и ее исправление сопряжено со значительно большими затратами труда и времени. Во-первых, нужно еще дождаться, пока можно будет попробовать программу в деле. Компиляция каждого модуля может длиться несколько минут, а ведь затем надо еще собрать их воедино. Во-вторых, даже при безошибочной компиляции отдельных частей отнюдь не гарантирована правильная работа программы в целом: части могут быть плохо пригнаны друг к другу. Предположим теперь, что ошибка обнаружена.Мы не мо- жем исправить одно лишь ошибочное место программы так, как мы делаем это на BASICe. Придется перекомпилировать весь модуль,иногда из-за одной стро- ки - несколько сотен. Однако, потом оттранслированная и скомпанованная программа будет рабо- тать намного быстрее,чем подобная программа на BASIC. Ведь интерпретатор BASIC переводит каждый оператор перед каждым его выполнением, а значит - каждый раз тратит время на перевод. Как синхронный переводчик, он, сказав, тут же забывает сказанное, и в следующий раз должен будет повторить всю проделанную работу по переводу. Создатель литературного перевода держит в уме весь текст целиком; он знает, что его перевод, сделанный однажды, бу- дут потом читать тысячи читателей в течение многих лет,и работает над ним тщательнейшим образом. Компилятор выполняет свою работу, так же тщательно выверяя окончательный результат. После компиляции и сборки отлаженную про- грамму можно запускать многократно, и затраты труда на ее разработку так же, как и затраты времени на трансляцию, окупятся с лихвой. Существует еще один вид транслятора. В советском компьютере БК-0010.01 используется компилятор с элементами интерпретатора,что позволяет в какой- то мере получить достоинства и того и другого. В частности, такой необыч- ный "гибридный" транслятор по столь важному параметру, как быстродействие, ставит БК-0010.01 в ряд популярных зарубежных б ы т о в ы х компьютеров (т.е. ЭВМ для дома, для игр, развлечений, создания личного архива, карто- теки, справочника, решения сравнительно простых задач). II.3. ОФОРМЛЕНИЕ И РЕДАКТИРОВАНИЕ ПРОГРАММ При записи программы на MSX-BASIC необходимо соблюдать ряд требований, а именно: 1. Текст программы записывается п о с т р о ч н о, четкими п е ч а т- н ы м и символами;при записи служебных слов разрешается использовать как прописные, так и строчные латинские буквы в любом сочетании, причем все строчные латинские буквы после ввода преобразуются интерпретатором в про- писные (однако, символы, заключенные в кавычки, всегда выводятся на экран дисплея без изменения). 2. Каждая строка программы (программная строка) начинается н о м е- р о м этой строки и заканчивается нажатием клавиши "RETURN" ┌──────────┐ │ │ │ │ ◀──┘ │ ; └──────────┘ до нажатия этой клавиши ЭВМ "не интересуется" тем, что пользователь напи- сал на экране дисплея, а после нажатия "приступает" к анализу содержимого программной строки. Интерпретатор игнорирует все пробелы между номером строки и началом оператора в этой строке(аналогично не учитывается и боль- шинство остальных пробелов (хотя и не всегда!)). 3. Программные строки нумеруются целыми числами от 0 до 65529 в возрас- тающем порядке. 4. При составлении начального варианта программы рекомендуется нумеро- вать строки с интервалом 10: 10, 20, 30,... . Нумерация программных строк через 10 позволяет дополнять программу, вставляя новые программные строки между введенными в память ранее (новые строки при этом имеют промежуточ- ные номера: 15, 17, 21, 23 и т.д. и, даже будучи введенными с клавиатуры в разное время, размещаются в памяти ЭВМ в строгом соответствии со своими номерами). 5. В каждой программной строке старайтесь размещать один з а к о н- ч е н н ы й оператор (в случае размещения в строке нескольких закончен- ных операторов операторы внутри строки отделяются друг от друга символом ":" (двоеточие), причем после последнего оператора в программной строке двоеточие не ставится); строка программы может занимать до с е м и дис- плейных строк на 40-символьном экране дисплея, так как максимальное число знаков в строке программы, включая номер строки, равно 255. Избегайте "с и н д р о м а о д н о й с т р о к и"! Данная "болезнь" начинающего программиста заключается в старательном размещении в каждой программной строке "огромного" количества операторов, в результате чего программа ста- новится совершенно "нечитабельной". 6. Последним оператором программы может быть оператор окончания про- граммы END с другой стороны, иногда можно обойтись и без этого оператора: выполнив последнюю строку программы, ЭВМ останавливается сама - ей больше нечего делать, операторы (команды) кончились! 7. Для записи программы в память ЭВМ и для ее исполнения необходимо со- проводить программу к о м а н д а м и (разумеется,они не нумеруются!) NEW и RUN ("new"-"новый", "to run"-"бежать"), первая из которых записывается на пер- вой перед программой дисплейной строке, вторая - на свободной дисплейной строке, расположенной за последней строкой программы. Обе команды заканчи- ваются нажатием клавиши "RETURN". По команде NEW из оперативной памяти удаляются все предыдущие програм- мы пользователя и значения переменных.Обязательно используйте эту команду для уничтожения старых программ, прежде чем начать вводить новую програм- му, иначе Вы только "измените" Вашу старую программу. Отметим, что команда NEW является и оператором! Команда RUN в ее простейшей форме (в виде одного служебного слова) яв- ляется сигналом к выполнению введенной программы, начиная с программной строки с наименьшим номером. Команда RUN является также и о п е р а т о р о м. Если эта команда за- дана как строка Вашей программы,то она перезапускает Вашу программу таким образом, как будто она была сначала остановлена, а затем запущена снова. Существует, однако, модификация команды RUN, позволяющая запускать про- грамму с л ю б о й д р у г о й с т р о к и: для этого после служебного слова RUN указывается номер существующей программной строки,с которой про- граммист пожелает начать выполнение программы, например: RUN 23 Отличительной особенностью команды (оператора) RUN n является "стира- ние" значений всех переменных. Таким образом достигается идентичное состо- яние памяти при каждом новом запуске программы. Запомните, что если Вы хотите начать выполнение программы со строки с заданным номером n, но при этом сохранить значения всех переменных, не ис- пользуйте команду RUN n а примените в режиме прямого выполнения команду GOTO n или GOSUB n (см. разделы III.1 и IV.4). Разумеется, номер строки, указанной в операторе RUN не должен находить- ся внутри цикла или подпрограммы! Таким образом, программы на BASIC имеют такой общий вид: NEW Ok 10 оператор 1 20 оператор 2 30 оператор 3:оператор 4 ··· NN [END] run Заметим, что здесь и всюду далее к в а д р а т н ы е с к о б к и - обозначение,указывающее,что информация внутри них не является обязательной. ┌───────────────────────────────────────────────────────────┐ │ Напомним еще раз, что при вводе программы в память в конце│ │ каждой программной строки надо нажимать клавишу "RETURN"! │ └───────────────────────────────────────────────────────────┘ Нумерация строк программы имеет целью: 1) отметить каждую программную строку индивидуальной меткой - н о м е - р о м , что позволяет обратиться к любой строке из любой другой програм- мной строки; 2) упорядочить расположение операторов в программе, которая обрабатыва- ется интерпретатором построчно ; 3) существенно облегчить процедуру р е д а к т и р о в а н и я (исправ- ления) программы, так как интерпретатор выдает сообщение об ошибке в конк- ретной программной строке, указывая ее номер, и пользователь получает воз- можность либо исключить строку из программы,либо записать в память ЭВМ от- корректированный (исправленный) текст строки. Рассмотрим несколько команд редактирования программ. II.3.1. К о м а н д а AUTO . К о м а н д а RENUM Автоматизировать процедуру присвоения номеров программным строкам мож- но командой АUTO [n1][,n2] где: AUTO ("AUTOmatic"-"автоматический") - служебное слово; n1,n2 - целые числовые константы; 0 ≤ n1,n2 ≤ 65529 . По этой команде происходит задание режима автоматической нумерации про- граммных строк от строки с номером n1 и далее с шагом n2. По умолчании n1=10 и n2=10. Таким образом, команда AUTO без параметров позволяет автоматически нумеровать программные строки через 10, начиная с программной строки с номером 10. Нажатие клавиш "CTRL"+"STOP" отменяет действие команды AUTO. Если очередной номер строки, сгенерированной режимом автоматической ну- мерации,совпадает с номером уже находящейся в памяти строки (введенной ра- нее), то на экране дисплея индицируется номер этой программной строки со звездочкой "*", например: 55*. В этом случае,если мы хотим сохранить "ста- рое" значение этой программной строки, мы должны нажать клавишу "RETURN"- компьютер сохранит эту программную строку и перейдет к генерации следующе- го номера. Общий вид команды изменения нумерации программных строк: RENUM [n1][,n2][,n3] где: RENUM("to RENUMber"-"перенумеровать") - служебное слово; n1,n2,n3 - целые константы, 0≤n1,n2,n3≤65529. По команде RENUM производится перенумерация (изменение нумерации) про- граммных строк, начиная со строки с номером n2 и дальше с шагом n3.Причем, n1 - это новый номер прежней строки n2. По умолчании: n1=10, n3=10, n2 - номер начальной строки программы. Параметр n2 может быть опущен, но запя- тая, относящаяся к нему, должна быть сохранена. В качестве параметров n1 и n2 может быть использован символ ".", который является ссылкой на "те- кущий" номер программной строки (имеется в виду последний, упомянутый но- мер программной строки). Команда RENUM, кроме того, проверяет, все ли программные строки, на ко- торые имелись ссылки в операторах программы, действительно существуют (не- зависимо от этого осуществляется перенумерация всех строк); если програм- мная строка с номером n не существует, а на нее имеется ссылка в строке m, то выдается сообщение: "Undefined line n in m" ("О т с у т с т в у е т с т р о к а n в m"). Перенумеровать операторы можно: 1) перед последующим слиянием программ; 2) для проверки существования строк программы, на которые имеются ссыл- ки. Для этого используйте команду RENUM с параметром n2, превышающим все существующие номера строк, например, RENUM 65000,65000 Перенумерация при этом не осуществляется, но Вы получите информацию обо всех пропущенных номерах строк. П р и м е р ы: RENUM ───────────── RENUM 200,150,5 RENUM 200,100 Обратите внимание: новый номер строки должен быть больше или равен ста- рому номеру! Куда девал сокровища убиенной тобою тещи? Отец Федор II.3.2. К о м а н д а DELETE . К о м а н д а [L]LIST Команда DELETE может быть записана в одной из следующих форм: DELETE n1-n2 DELETE . DELETE -n2 DELETE .-n2 DELETE n1 DELETE n1-. Здесь: DELETE ("to delete"-"стереть") - служебное слово; n1 и n2 - целые константы, 0≤n1,n2≤65529. По команде DELETE из программы удаляются программные строки с номерами от n1 до n2 включительно. Если параметр n1 отсутствует, то в качестве n1 берется номер первой строки программы. Символ ".", используемый вместо но- мера строки обозначает "текущий" (последний упомянутый) номер программной строки. П р и м е р ы: DELETE 70-100 DELETE . ───────────── DELETE -50 DELETE .-34 DELETE 23 DELETE 40-. Если строка с номером, указанным в команде DELETE, в программе отсутс- твует, то выдается сообщение об ошибке "Illegal function call" ("Н е п р а в и л ь н ы й в ы з о в ф у н к ц и и").