9.1. Организация циклов

9.2. Типы ошибок в программе. Исправление ошибок

9.3. Составление программ с использованием ввода данных

9.4. Порядок решения задач с использованием ЭВМ

9.5. Составление программ разветвляющейся структуры. Контроль ввода данных

9.6. Составление программ для обработки потока данных

9.7. Этапы решения задачи на ЭВМ

В качестве примеров здесь приводятся программы на языке Basic. Basic очень похож на “естественный” язык, но в качестве служебных слов в Basic вместо русских используются английские слова: IF — если, GO ТО — идти к, SТОР — закончить вычисления, INPUT — задать (ввести) значения переменных. Будет использоваться также оператор PRINT — печатать — для вывода результатов вычислений на экран дисплея.

9.1. Организация циклов

Как уже отмечалось ранее, существуют два основных вида цикла — До и Пока. Рассмотрим их подробнее.

В языке Basic циклу До (рис. 8.3) соответствует следующая структура программы:

  1. Операторы начальных присваиваний
  2. Тело цикла
  3. IF условие GO ТО 2

Циклу Пока (рис. 8.4) соответствует структура программы:

  1. Операторы начальных присваиваний
  2. IF условие GO ТО 5
  3. Тело цикла
  4. GO TO 2
  5. . . .

Рассмотрим следующую программу

10 P=0
20 PRINT P, P*P
30 Р=Р+1
40 IF P<=10 GО ТО 20

(*—знак умножения, <= употребляется вместо ).При выполнении программы на экран дисплея выводятся числа от 0 до 10 и их квадраты.

Это пример цикла До. Здесь операторы 20, 30 образуют тело цикла. Собственно телом цикла является оператор 20. Оператор 30 относится к операторам, организующим цикл (наряду с операторами 10 и 40). Оператор 40— оператор условного перехода — осуществляет после каждого прохода цикла проверку условия выхода из цикла (вернее сказать — условия продолжения цикла). Оператор 10 осуществляет начальные присваивания и обеспечивает возможность выполнения цикла при первом его прохождении. В цикле — многократно — выполняются операторы 20—40.

Для организации цикла в этой программе используется переменная Р, которая называется управляющей переменной цикла или параметром цикла. Для организации цикла нужно знать начальное значение управляющей переменной Рнач, конечное значение управляющей переменной Ркон и шаг ее изменения Н.

Значения Рнач, Ркон, Н назовем параметрами цикла. При этом количество повторений цикла определяется по формуле

.

Это значение можно использовать для контроля правильности организации цикла.

Перед тем как писать программу, содержащую цикл, целесообразно заполнить таблицу такого вида:

Таблица 9.1. Управляющая переменная и параметры цикла

Управляющая переменная цикла

Начальное значение

Конечное значение

Шаг изменения

Количество повторений цикла

Р

0

10

1

11

Таблица заполнена для управляющей переменной Р, использованной в предыдущей программе.

Дополним рассмотренную программу.

1. Предусмотрим печать заголовка таблицы оператором

PRINT “ЧИСЛО”, “КВАДРАТ ЧИСЛА”

Этот оператор должен быть расположен до входа в цикл.

2. Предусмотрим вывод пустой строки после заголовка оператором

PRINT

3. В конце программы разместим оператор STOP, который прекращает выполнение программы, когда будет Р > 10, и перенумеруем строки программы стандартным образом, изменив также номер строки в операторе условного перехода.

Тогда программа будет иметь вид

10 PRINT “ ЧИСЛО”, “ КВАДРАТ ЧИСЛА”
20 PRINT
30 Р=0
40 PRINT P, P*P
50 P=P+1
60 IF P<=10 GO TO 40
70 STOP

При выполнении этой программы на экране будут высвечиваться результаты:

ЧИСЛО

КВАДРАТ ЧИСЛА

0

0

1

1

2

4

3

9

4

16

5

25

6

36

7

49

8

64

9

81

10

100

Как самому составить программу решения задачи, требующей использования циклов? Рассмотрим порядок разработки программы на примере.

Пример. Составить таблицу перевода миль в километры для расстояний от 5 до 75 миль с шагом 5. 1 миля составляет 1,609 км.

С чего начать разработку программы?

1. Сначала нужно решить, в каком виде мы хотим получить результат. Допустим, что это должна быть таблица с заголовком, например, такого вида:

Мили

Км

5

8.045

10

16.09

….

….

75

120.675

2. Выделить повторяющиеся действия.
Для рассматриваемой задачи для 5 миль, для 10, для 15 и т. д. нужно печатать расстояние в милях и соответствующее ему расстояние в километрах.

3. Продумать организацию цикла для выполнения повторяющихся действий требуемое число раз.

Для организации цикла необходимо выбрать управляющую переменную. Для нашего примера это может быть количество миль. Обозначим управляющую переменную через М и заполним таблицу 9.2.

Таблица 9.2

Управляющая переменная цикла

Начальное значение

Конечное значение

Шаг изменения

Количество повторений цикла

М

5

75

5

15

Для вывода заголовка таблицы по аналогии с предыдущей программой используем два оператора, один из которых выведет на экран заголовок, а второй обеспечит вывод пустой строки перед печатью самих результатов.

Таким образом, программа может быть составлена в виде

10 PRINT “МИЛИ”,”КМ”
20 PRINT
30 M=5
40 PRINT М, 1.609*Н
50 М=М+5
60 IF М<=75 GO ТО 40
70 SТОР

Пояснения к программе. Оператор 10 печатает заголовок.

Оператор 20 выводит пустую строку.

Оператор 30 устанавливает начальное значение управляющей переменной цикла.

Оператор 40 составляет тело цикла и при каждом изменении переменной М выводит на экран ее значение (количество миль) и его эквивалент в километрах.

Оператор 50 увеличивает текущее значение управляющей переменной на шаг, равный 5.

Оператор 60 осуществляет проверку, пройдено ли последнее значение.

Оператор 70 прекращает выполнение программы.

В результате выполнения этой программы на экране появится следующая таблица:

МИЛИ

КМ

5

8.045

10

16.09

15

24.135

20

32.18

25

40.225

30

48.27

35

56.315

40

64.36

45

72.405

50

80.45

55

88.495

60

96.54

65

104.585

70

112.63

75

120.675

В языке Basic имеются операторы цикла FOR и NEXT (FOR — для, NEXT — следующий), которые обеспечивают многократное выполнение операторов, расположенных между ними и образующих тело цикла.

С использованием операторов FOR, NEXT предыдущая программа будет иметь вид

10 PRINT “МИЛИ”,”КМ”
20 PRINT
30 FOR M=5 TO 75 STEP 5
40 PRINT M, 1.609*M
50 NEXT M
60 STOP

В операторе FOR используются еще два служебных слова ТО — до, STEP — шаг.

9.2. Типы ошибок в программе. Исправление ошибок

Если программа только что составлена, то в очень редких случаях она не содержит ошибок. Нужно заранее настраиваться на то, что в программе есть ошибки, и их нужно найти и исправить.

Можно выделить три типа ошибок:

  • синтаксические ошибки, т. е. несоответствие конструкций в программе правилам Basic. Эти ошибки самые простые, их легко исправить. При вводе оператора, содержащего синтаксическую ошибку на экране, как правило, появляется указание на то место в операторе, где эта ошибка сделана, и на то, какого рода эта ошибка. То есть машина сама контролирует соответствие вводимой программы правилам языка. Однако в обнаружении и исправлении синтаксических ошибок нельзя полностью положиться на ЭВМ. Предположим, что при умножении переменной А на 2 вы забыли написать знак умножения (т. е. вместо А*2 .в программе написано А2). Однако машина не воспринимает эту запись как ошибочную, считая, что вы используете переменную с именем А2 (что допускается правилами Basic). Программа может быть даже выполнена, но она не даст правильного результата.
  • ошибки в организации программы. Например, в программе имеется оператор GO ТО 500 а оператора с номером 500 в программе нет. При выполнении такого оператора машина выдает соответствующее сообщение об ошибке.
  • ошибки в алгоритме. Эти ошибки труднее всего найти. Они не могут быть обнаружены машиной, так как она не “знает” решаемой задачи. Это, например, так называемые зацикливания, когда программа не выходит из цикла и ничего не печатает. Иногда просто высвечиваются неправильные результаты или результаты вычисляются правильно, но не выводятся из-за отсутствия оператора PRINT. В этом случае нужно остановить выполнение программы и просмотреть программу внимательно.

Однако, как правило, сразу за дисплеем найти ошибки не удается. В этом случае нужно сесть за стол (выключить машину) и применить очень действенный метод проверки работы вашей программы, который называется: выполнение программы вручную. Для этого нужно представить себе, что вы — машина, и, начав с первого оператора программы, выполнять оператор за оператором, пока не будет обнаружена причина неправильной работы программы. Нужно выполнять эту работу методично и терпеливо, отключив свой интеллект, не делая правдоподобных догадок и не перескакивая через несколько операторов.

Конечно, лица, имеющие опыт составления программ и работы на ЭВМ, обычно выполняют эту работу до первого выхода на машину. Тем, кто только приступает к изучению программирования, требуется некоторое время, чтобы уяснить, как машина воспринимает и выполняет операторы программы. И в первых своих программах новички делают ошибки, которые они сами обнаружить не в состоянии. Они могут, поверить в ошибки, только если машина не выполняет составленную ими программу или выполняет ее неправильно.

Чтобы имитировать работу ЭВМ, нужно хорошо понимать, как она работает. Представим себе, что мы остановили выполнение программы и заглянули внутрь ЭВМ. Что бы мы там “увидели”?

1. В памяти записана программа в той форме, в которой мы ее ввели.

2. В другом участке памяти располагаются переменные, которые были созданы к настоящему моменту. Каждая переменная занимает свое место в памяти (ячейку памяти) и имеет значение.

3. В памяти хранится еще одна специальная переменная, в которой находится номер выполняемой в данный момент строки (оператора). То есть машина “знает”, в каком месте программы она находится. После выполнения очередного оператора значение этой специальной переменной, которая имеет название указатель программы, изменяется. Если выполняемым оператором был оператор PRINT, по которому что-то появилось на экране, или оператор присваивания, по которому в ячейку памяти помещено значение, то после его выполнения значение указателя программы заменяется на следующий (в порядке возрастания) номер в последовательности операторов и машина начнет выполнять оператор с этим следующим номером.

При выполнении оператора GO TO ничего не высвечивается и не изменяются значения переменных, просто значение указателя программы заменяется на тот номер, который указан в операторе GO TO .

Оператор IF выполняется так же, как GO TO, если условие выполняется (имеет значение да). Если условие не выполняется (имеет значение нет), то в указателе программы появляется номер следующего оператора в программе.

По оператору STOP прекращается выполнение программы.

Имитируя работу машины, мы должны иметь:

  • программу;
  • переменные с их текущими значениями;
  • значение указателя программы (номер выполняемого оператора);
  • информацию, высвечиваемую на дисплее при выполнении программы.

Для нас памятью (подобной памяти ЭВМ) будет лист бумаги, на котором в отведенных местах записана эта необходимая информация.

При выполнении программы вручную удобно пользоваться следующей таблицей. Назовем ее таблицей выполнения программы.

Таблица 9.3. Таблица выполнения программы

Номер выполняемого оператора

Переменные и их текущие значения

Дисплей

Программа

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

Если значение переменной изменяется, то старое значение зачеркнем и рядом напишем новое. В основной части таблицы справа располагаем выполняемую программу, а слева выписываем то, что в соответствии с операторами PRINT должно появляться на экране.

Выполняя программу вручную, нужно на время забыть “цель” программы и выполнять оператор с номером 20 только потому, что такое значение имеет указатель программы.

Как же найти ошибку в программе, выполняя ее вручную? Для этого нужно переключаться из состояния “робота”, в котором вы находитесь, выполняя очередной оператор, в состояние человека, обладающего интеллектом. Сначала вы — “робот” и выполняете оператор точно так, как это делает машина, потом опять становитесь человеком и спрашиваете: “Тот ли получен результат, которого я ожидал?” Если — да, то продолжаете выполнение программы. Если — нет, нужно думать, почему программа работает неправильно.

Рассмотрим пример. Предположим, что мы хотим напечатать таблицу умножения для числа 12, т. е. получить на экране:

ТАБЛИЦА УМНОЖЕНИЯ НА 12

1*12=12
2*12=24
. . . . .
12* 12= 144

Для этого мы написали программу

10 PRINT “ТАБЛИЦА УМНОЖЕНИЯ НА 12"
20 Р=1
30 Р=Р+1
40 IF Р<=12 GO ТО 30
50 PRINT P; ”*12=”; P*12
60 STOP

Ввели эту программу и после ее выполнения получили на экране:

ТАБЛИЦА УМНОЖЕНИЯ НА 12

13*12 = 156

Мы видим, что получен не тот результат, который мы ожидали.

Для проверки работы программы выполним её вручную. Составим таблицу выполнения.

Таблица 9.4

Номер выполняемого оператора 10 20 30 40 30

Переменные и их текущие значения P : 1 2 3

Дисплей

 

Программа
10 PRINT “ТАБЛИЦА УМНОЖЕНИЯ НА 12”
20 P=1
30 P=P+1
40 IF P<=12 GO TO 30
50 PRINT P; “*12=”; P*12
60 STOP

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

10 PRINT “ТАБЛИЦА УМНОЖЕНИЯ НА 12"
20 PRINT
30 Р=1
40 PRINT P; “*12=”; P*12
50 Р=Р+1
60 IF Р<=12 GO TO 40
70 STOP

Однако описанный метод проверки работы программы не дает результата, если вы не знаете языка Basic. Допустим, вы считаете, что * означает сложение. Тогда, например, если Р = 4, и вы выполняете вручную оператор Т=Р*Р, то Т будет иметь у вас значение 8, тогда как при выполнении этого оператора машиной Т будет присвоено значение 16. Таким образом, если результат работы программы не совпадает с ожидаемым, а выполнение программы вручную дает ожидаемый результат, то вам нужно повторить основы языка Basic.

9.3. Составление программ с использованием ввода данных

Программы, которые мы рассматривали до сих пор, не требуют никакой дополнительной информации для того, чтобы машина могла их выполнить. Каждая из них решает одну конкретную задачу, и при ее выполнении всегда получается один и тот же результат.

Обычно программа составляется в общем виде так, чтобы без каких-либо изменений она могла использоваться для решения различных задач одного класса (вспомним свойство алгоритма—массовость). Так как задачи одного класса различаются исходными данными, а решаются с использованием одной и той же программы, то, следовательно, эти исходные данные в самой программе фигурировать не должны. Но при выполнении программа должна обрабатывать конкретный набор исходных данных.

Пусть, например, мы хотим составить программу для получения таблицы умножения для любого натурального числа. Вместо конкретного числа в программе используем переменную N. Тогда в предыдущей программе оператор 40 нужно заменить на

40 PRINT Р; "*"; N; "="; Р*N

и оператор 60 на

60 IF Р <= N GO TO 40

(Оператор 10 также требует изменения, но на выполнение программы он не влияет.)

Перед началом вычислений в переменные (точнее, в ячейки памяти), предусмотренные в программе для исходных данных, должны быть введены значения. Для выполнения этой операции предназначен оператор ввода INPUT. Так, оператор

INPUT N

обеспечит при выполнении программы ввод значения, набираемого на клавиатуре, в переменную N. Этот оператор должен быть выполнен до первого использования переменной N в программе.

При выполнении оператора INPUT на экране появляется знак ?, означающий, что машина ждет ввода данных. Желательно, чтобы при этом на экране появлялось также точное указание о том, какие данные должны быть введены в ЭВМ.

Вывести сообщение на экран можно при помощи оператора PRINT. Например, при выполнении операторов

10 PRINT "ВВЕДИТЕ ЧИСЛО , ДЛЯ КОТОРОГО"
11 PRINT"ХОТИТЕ ПОЛУЧИТЬ ТАБЛИЦУ УМНОЖЕНИЯ"
20 INPUT N

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

ВВЕДИТЕ ЧИСЛО, ДЛЯ КОТОРОГО
ХОТИТЕ ПОЛУЧИТЬ ТАБЛИЦУ УМНОЖЕНИЯ
?

Далее нужно набрать это число на клавиатуре и нажать Enter.

Программа 9.1 составлена для получения таблицы умножения для любого числа.

Программа 9.1

10 PRINT “ВВЕДИТЕ ЧИСЛО , ДЛЯ КОТОРОГО”
11 PRINT “ХОТИТЕ ПОЛУЧИТЬ ТАБЛИЦУ УМНОЖЕНИЯ”
20 INPUT N
30 P=1
40 PRINT P; ” * ”; N; “=”; P*N
50 P=P+1
60 IF P<=N GO TO 40
70 STOP

В Basic, помимо числовых переменных, с которыми мы имели дело до сих пор, могут использоваться и символьные переменные, значениями которых являются последовательности символов. Для обозначения символьной переменной к ее имени приписывается знак $. Значения символьных переменных можно задавать так же, как значения числовых, в частности, использовать оператор ввода INPUT.

Возможность ввода данных (строк символов) в символьные переменные в Basic делает возможным разработку программ, обладающих диалоговыми свойствами, так что работа ЭВМ по программе воспринимается как реакция или даже инициатива вполне сознательного партнера.

Составим, например, программу, которая спрашивает имя и затем здоровается с его обладателем. При выполнении программы на экране должен появиться вопрос: “Как Вас зовут?”. Имя, набираемое далее на клавиатуре, машина должна запомнить в какой-либо символьной переменной (например, N$) и далее значение этой переменной выводить на экран со словами приветствия. Далее приводится программа 9.2 и результат ее выполнения.

Программа 9.2

10 PRINT "КАК ВАС ЗОВУТ ?"
20 INPUT N $
30 PRINT "ПРИВЕТ ,";N $ ; “! “
40 STOP
RUNNH
КАК ВАС ЗОВУТ ?
? ВАСЯ
ПРИВЕТ, ВАСЯ !

9.4. Порядок решения задач с использованием ЭВМ

Решение задач с использованием ЭВМ включает следующие этапы: формулировка - задачи на профессиональном языке, математическая постановка задачи, выбор метода решения, выбор структуры данных и разработка алгоритма, программирование, отладка и тестирование программы, счет по готовой программе и анализ результатов. Подробно эти этапы рассмотрены в п. 7. Здесь в упрощенном виде рассмотрены те этапы, выполнение которых необходимо при решении простых задач в начальный период изучения программирования.

1. Точная формулировка цели решения задачи, т.е. - определение, что именно нужно получить в результате решения задачи и в каком виде желательно получить результат.

2. Выбор обозначений для переменных программы. Выделение исходных данных и результатов.

Обозначения переменных должны быть согласованы с возможностями обозначения переменных в алгоритмическом языке (в частности, в Basic). Информацию об используемых переменных удобно разместить в таблице 9.5.

Таблица 9.5. Характеристика переменных программы

Имя переменной в программе

Физический смысл переменой

Назначение переменной

Ограничения на исходные данные

Эту таблицу обычно не удается полностью заполнить перед составлением программы, так как в процессе разработки программы может появиться необходимость в дополнительных переменных для хранения промежуточных результатов, поэтому таблицу приходится дополнять при составлении программы (алгоритма).

3. Разработка алгоритма решения задачи, т. е. расчленение исходной задачи на отдельные простые этапы.

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

4. Написание по схеме программы на Basic.

При составлении программы нужно следить за тем, чтобы переменные, являющиеся исходными данными, вводились оператором INPUT, а результаты выводились оператором PRINT. В программе нужно предусмотреть печать необходимых заголовков и пояснений к выводимым результатам, а также печать указаний для выполнения операторов ввода.

Работа по составлению программы на Basic не должна вызывать трудностей. Если вы испытываете трудности, значит, плохо был выполнен этап разработки алгоритма.

5. Ввод программы в машину и проверка ее работы на различных исходных данных.

Используя эти правила, составим программу для решения следующей задачи.

Задача . Представим себе пирамиду из шаров, основание которой представляет собой квадрат со стороной, состоящей из N шаров. Следующий слой состоит из шаров, лежащих в углублениях нижнего слоя, т. е. представляет собой квадрат со стороной, состоящей из N—1 шаров и т. д. Верхний слой содержит один шар. Требуется определить, сколько шаров потребуется для строительства пирамиды из N слоев.

Решение . Легко заметить, что один слой содержит число шаров, равное квадрату номера слоя (верхний слой, содержащий один шар, считаем первым). Поэтому математически задача сводится к вычислению суммы квадратов натуральных чисел от 1 до N. т. е. вычислению 12+22+. . .+ N2.

В результате решения задачи должно быть получено одно число — суммарное количество шаров, необходимое для строительства пирамиды. Это число должно быть выведено на экран с поясняющим текстом.

Исходными данными для задачи является количество слоев пирамиды, которое обозначим через N. Результат решения задачи — суммарное число шаров обозначим через К. Понадобится еще вспомогательная переменная: текущий номер слоя — обозначим его через К. Заполним таблицу 9.6 для переменных программы.

Для решения задачи будем постепенно накапливать в переменной R сумму (“текущее” общее количество) шаров, составляющих один слой, два слоя, три слоя и т.д. После окончания суммирования в R будет получена сумма шаров, составляющих все N слоев, т. е. результат решения задачи.

Таблица 9.6. Характеристика переменных программы

Имя переменной

Физический смысл переменной

Назначение переменной

Ограничения н исходные данные

R

“Текущее” общее число шаров

Результат

 

N

Число слоев пирамиды

Исх. дан.

Любое натуральное

K

Число слоев, обработанных к данному моменту

Вспомогат. перемен.

 

Таким образом, программа должна содержать цикл по номеру слоя. Данные, необходимые для организации цикла, внесем в таблицу 9.7.

Таблица 9.7

Управляющая переменная цикла

Начальное значение

Конечное значение

Шаг изменения

Количество повторений цикла

К

1

N

1

N

Составим промежуточный вариант схемы (рис. 9.1а), в котором показана организация цикла, но некоторые блоки (обозначены пунктирной линией) требуют конкретизации. Уточним их содержание. Начнем с тела цикла. Тело цикла должно содержать действия, выполняемые для одного слоя. Это—вычисление числа шаров в К-м слое, равное К*К, и прибавление его к “текущему” общему R. Это действие записывается как

R= R + K*K

Рис. 9.1а
Рис. 9.1б

Начальными операторами должны быть заданы значения тех переменных, которые используются в цикле, с тем чтобы при первом прохождении цикла переменные в правых частях операторов присваивания и в операциях сравнения имели значения. Для нашей задачи переменной R должно быть присвоено значение 0 и введено значение N.

Введем эти уточнения и составим схему в окончательном варианте (рис. 9.1б).

Далее приводится программа 9.3, составленная в соответствии со схемой, и результат ее выполнения при N=4.

Программа 9.3

10 PRINT "СКОЛЬКО СЛОЕВ"
20 INPUT N
30 R=0
40 К=1
50 К=К+К*К
60 К=К+1
70 IF К<=N GO ТО 50
80 PRINT R;”Шаров понадобится”
90 SТОР
RUNNH
СКОЛЬКО СЛОЕВ
? 4
30 ШАРОВ ПОНАДОБИТСЯ

9.5. Составление программ разветвляющейся структуры. Контроль ввода данных

При программировании разветвления на языке Basic следует иметь в виду, что на схеме (рис. 8.5) отдельные ветви разветвления расположены параллельно, а в программе они должны следовать друг за другом. Причем, если одна ветвь выполнена, то другую выполнять не нужно. Этот обход второй ветви (действие 2) осуществляется оператором GO TO N, который обеспечивает переход к общей части программы после выполнения первой ветви (действие 1).

Организация разветвления в программе на Basic осуществляется оператором условного перехода IF. Сразу за оператором IF должны располагаться операторы действия 2. Эта часть программы начинает выполняться, если условие в операторе IF имеет значение нет, т. е. структура разветвления имеет следующий программный эквивалент:

1 IF условие GO TO 4
2 Операторы действия 2
3 GO TO 5
4 Операторы действия 1
6 Операторы общей части программы

В качестве примера составим программу для решения (нахождения вещественных корней при а≠ 0) квадратного уравнения

2+Ьх-+с=0.

Квадратное уравнение имеет решение, если дискриминант D=Ь2—4ас не является отрицательным, т. е. после ввода коэффициентов а, Ь, с нужно вычислить D и проверить условие D<0. Если это условие выполняется (имеет значение да), то нужно вывести сообщение “Уравнение не имеет решения”. Если условие D<0 не выполняется, нужно напечатать корни, вычисляемые по формулам

x1 =(- b + D)/2a, x2 =( -b - D)/2a.

Схема представлена на рис. 9.2.

Рис. 9.2.

Далее приводится программа 9.4, составленная в соответствии со схемой.

Программа 9.4

10 PRINT “ВВЕДИТЕ КОЭФФИЦИЕНТЫ УРАВНЕНИЯ ”
20 INPUT A, B, C
30 D = В*В-4*А*С
40 IF D<0 GO TO 90
50 PRINT “КОРНИ УРАВНЕНИЯ"
60 X1=(-B+SQR (D))/(2*A) \ X2=(-B-SQR (D))/(2*A)
70 PRINT X1;X2
80 GO TO 100
90 PRINT "УРАВНЕНИЕ НЕ ИМЕЕТ РЕИЕНИЯ"
100 STOP

Используя составленную программу, решим следующую задачу. Определить, через сколько секунд упадет на землю камень, брошенный с высоты 2 м вверх с начальной скоростью 10 м/с.

Зависимость вертикальной координаты камня от времени определяется уравнением
h(t)= 2+10t-gt2 /2,

где g=9,8 м/с2 — ускорение свободного падения.

Для решения поставленной задачи нужно найти значение t, при котором h(t)== 0, т. е. необходимо решить квадратное уравнение

— gt2/2 + 10t+2= 0.
Это можно сделать, выполнив составленную программу при A=-4.9, В=10, С=2.

Результат выполнения программы

ВВЕДИТЕ КОЭФФИЦИЕНТЫ УРАВНЕНИЯ
? –4.9,10,2
КОРНИ УРАВНЕНИЯ
-,1835 2,22432

Физический смысл имеет только второй (положительный) корень — искомое время в секундах.

Частный случай разветвления — обход (см. рис. 8.6) имеет следующий программный эквивалент:

1 IF условие GO TO 3 ,
2 Операторы действия
3 Операторы общей части программы

При программировании обхода нужно следить за тем, чтобы обход осуществлялся по стрелке да во избежание .лишних операторов GO TO.

В качестве примера составим программу для нахождения максимального из двух чисел х и у, используя структуру обход. По сравнению со схемой (см. рис. 8.10) программа 9.5 дополнена операторами ввода данных и вывода результата.

Программа 9.5

10 PRINT "ВВЕДИТЕ ДВА ЧИСЛА"
20 INPUT X, Y
30 U=X
40 IF U>=Y GO TO 60
50 U=Y
60 PRINT “БОЛЬШЕЕ ЧИСЛО”; U
70 STOP

(>= употребляется вместо ³ ).

При вводе данные, как правило, подвергаются различным видам контроля. В частности, если исходные данные не принадлежат диапазону, для которого программа обеспечивает правильную обработку, программа не должна выполняться. Организация контроля вводимых данных для этого случая демонстрируется в следующем примере.

Пример . Программа — льстец.

На экране должен появляться вопрос: “Кто ты: мальчик или девочка? Введи М или D”, и в зависимости от ответа на экране должен появляться текст “Мне нравятся девочки” (если было введено D) или “Мне нравятся мальчики” (если было введено М).

Исходные данные (М или D) будем вводить в символьную переменную, например S$. Текст, подлежащий выводу (в зависимости от ответа), присвоим другой символьной

переменной, например Т$, и затем эту переменную выведем на печать (см. программу 9.6).

Схема алгоритма для этого примера приведена на рис. 9.3.

Рис. 9.3.

Программа 9.6

10 PRINT "КТО ТЫ: МАЛЬЧИК ИЛИ ДЕВ0ЧКА ? ";
20 PRINT "ВВЕДИ М ИЛИ D"
30 INPUT S$
40 IF S$=”M” GO ТО 70
50 Т$=”МНЕ НРАВЯТСЯ ДЕВОЧКИ"
60 GO TO 80
70 Т$=''МНЕ НРАВЯТСЯ МАЛЬЧИКИ"
80 PRINT Т$
90 SТОР

Рис. 9.4.

Недостатком
этой программы является то, что она не защищена от неправильного ввода. Действительно, если вводится любой другой символ (или символы), кроме М, на экране появится текст “Мне нравятся девочки”. Например, недостаточно внимательный мальчик может ввести что-нибудь вроде: “Я — мальчик”, и ответ машины будет неверным. Для защиты программы от неправильного ввода необходимо, если условие S$= "М" не выполняется, проверять также условие S$== "D”, и если оно также не выполняется, то нужно вернуться к оператору ввода. Этот прием иллюстрируется следующей схемой (рис. 9.4) и программой 9.7.

Программа 9.7

10 PRINT ”КТО ТЫ: МАЛЬЧИК ИЛИ ДЕВОЧКА ? ";
20 PRINT "ВВЕДИ М ИЛИ D"
30 INPUT S$
40 IF S$=”M” GO TO 90
50 IF S$=”D” GO TO 70
60 GO TO 20
70 Т$=''МНЕ НРАВЯТСЯ ДЕВОЧКИ"
80 GO TO 100
90 T$="МНЕ НРАВЯТСЯ МАЛЬЧИКИ"
100 PRINT T$
110 STOP

Замечание. В приведенной программе (а также на схеме) допущено отступление от структурного подхода. Строгое соблюдение правил, допускающих использование только типовых структур алгоритма, потребовало бы введения вспомогательной переменной и привело бы к необоснованному усложнению программы и потере ее наглядности.

9.6. Составление программ для обработки потока данных

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

  • число данных известно до начала работы программы. Тогда в начале программы количество данных вводится в переменную, которая используется далее везде, где требуется общее число данных (например, для проверки условия окончания цикла).
  • число данных произвольно и заранее неизвестно. В этом случае для окончания ввода используется специальное значение того же типа, что и вводимые данные (признак конца данных), которое заведомо не может встретиться в потоке данных. Например, если все вводимые числа положительные, то в качестве признака конца может использоваться любое отрицательное число. Следующие два примера иллюстрируют рассмотренные способы.

Пример. В классе N учеников. Определить средний рост учеников класса, вводя в ЭВМ по очереди рост каждого ученика.

Решение. Рост учеников будем суммировать в переменной 5, а затем разделим эту сумму на общее число учеников N.

Далее приводится программа 9.8 для решения этой задачи.

Программа 9.8

10 PRINT "СКОЛЬКО УЧЕНИКОВ В КЛАССЕ ?"
20 INPUT N
30 S=0
40 FOR I=1 ТО N
50 PRINT "ВВЕДИТЕ РОСТ СЛЕДУЮЩЕГО УЧЕНИКA”
60 INPUT P
70 S=S+P
80 NЕХТ I
90 IF N=0 GO TO 130
100 S=S/N
110 PRINT “СРЕДНИЙ РОСТ УЧЕНИКОВ=”;S
120 STOP
130 PRINT “В КЛАССЕ НЕТ УЧЕНИКОВ”
140 STOP

Список используемых переменных. Исходные данные:

N — число учеников, Р — рост одного ученика.
Результат: S — средний рост учеников класса.
Вспомогательные переменные: I — счетчик числа учеников (управляющая переменная цикла).

Чтобы получить результат работы этой программы, нужно ввести все N данных.

Пример. Определить средний рост учеников класса. Для окончания ввода, ввести 0.

Далее приводится программа 9.9 для решения этой задачи.

Программа 9.9

10 S=0
20 I=0
30 PRINT "ВВЕДИТЕ РОСТ СЛЕДУЮЩЕГО УЧЕНИКА"
40 PRINT "ДЛЯ ОКОНЧАНИЯ ВВОДА ИСПОЛЬЗУЙТЕ НОЛЬ"
50 INPUT Р
60 IF Р=0 GO TO 100
70 S=S+P
80 I=I+1
90 GO TO 30
100 IF I=0 GO TO 140
110 S=S/1
120 PRINT "СРЕДНИЙ РОСТ УЧЕНИКОВ = ";S
130 SТОР
140 PRINT "В КЛАССЕ НЕТ УЧЕНИКОВ"
150 SТОР

Список используемых переменных. Исходные данные:

P- рост одного ученика.
Результат: 8 — средний рост учеников.
Вспомогательные переменные: I — число учеников.

Если общее число данных произвольно (второй способ), но при каждом прохождении цикла вводится и обрабатывается не одно (как в последнем примере), а два или более данных, то для удобства работы с программой одно данное целесообразно вводить отдельно от других и использовать его для организации цикла. Этот прием иллюстрируется в следующем примере.

Пример. Определить средний рост и вес учеников класса.

Решение. Рост и вес каждого ученика будем вводить различными операторами INPUT. Для окончания ввода в переменную для роста введем 0. Далее приводится программа 9.10, в которой реализован описанный прием для решения поставленной задачи.

9.7. Этапы решения задачи на ЭВМ

Рассмотрим теперь подробнее все этапы решения задач на ЭВМ.

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

Первым этапом постановки и решения задачи на ЭВМ являются четкая формулировка задачи (обычно на профессиональном языке), выделение исходных данных для ее решения и точные указания относительно того, какие результаты и в каком виде должны быть получены.

Второй этап — формальная (математическая) постановка задачи, т.е. представление ее в виде уравнений, соотношений, ограничений и т. п. При этом некоторые задачи, решаемые в настоящее время на ЭВМ, либо не допускают, либо не требуют математической постановки (например, задачи обработки текстов).

Третий этап — выбор метода решения. Выбор метода определяется решаемой задачей, а также возможностями ЭВМ (ее быстродействием, объемом памяти, точностью представления чисел, наличием разработанных ранее готовых программ и т. п.). Выполнение этого этапа требует наличия некоторого кругозора как в области программирования, так и в области используемых методов.

Четвертый этап — разработка алгоритма на основе выбранного метода. При выборе алгоритма желательно рассмотреть и проанализировать несколько вариантов, прежде чем сделать окончательный выбор. Следует обратить внимание на тесную взаимосвязь третьего и четвертого этапов, так как алгоритм в большой степени определяется выбранным методом, хотя один и тот же метод в свою очередь может быть реализован при помощи различных алгоритмов.

При разработке алгоритма решения сложной задачи следует использовать метод пошаговой детализации, следя за тем, чтобы на каждом шаге структура алгоритма оставалась простой и ясной. Следует максимально использовать существующие типовые или разработанные ранее алгоритмы для отдельных фрагментов (блоков) алгоритма.

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

Шестой этап — собственно программирование, т. е. запись разработанного алгоритма на языке программирования. Вопросы выбора подходящего языка здесь не рассматриваются.

Если разработка алгоритма выполнена хорошо, то программирование принципиальных трудностей не вызывает. Однако можно высказать некоторые рекомендации по составлению программы, которые облегчат ее отладку и дальнейшее использование.

1. Программа должна быть универсальной, т. е. не зависящей от конкретного набора данных. Если данные представлены в виде массивов, то в качестве исходных данных следует рассматривать не только сами данные, но и их количество, для того чтобы одна и та же программа могла быть использована для обработки массивов различных размеров.

Универсальная программа должна обрабатывать вырожденные случаи (например, число элементов вектора равно 0 или 1) и печатать сообщение об ошибке, если размер массива превысил допустимое значение (использованное в описании массива).

2. Вместо констант лучше использовать переменные. Если в программе используются константы, то при их изменении нужно изменять в исходной программе каждый оператор, содержащий прежнюю константу. Эта процедура отнимает много времени и часто вызывает ошибки. В программе следует предусмотреть контроль вводимых данных (в частности, программа не должна выполняться, если данные выходят за пределы допустимого диапазона.

3. Некоторые простые приемы позволяют повысить эффективность программы (т. е. уменьшить количество выполняемых операций и время работы программы). К таким приемам относятся:

  • использование операции умножения вместо возведения в степень для низких степеней, например Х*Х*Х вместо Х^3, выполняется быстрее;
  • арифметическое выражение, которое несколько раз вычисляется программе с одними и теми же данными, лучше вычислить один раз и присвоить его значение переменной, которую и использовать везде вместо арифметического выражения;
  • при организации циклов в качестве границ индексов использовать переменные, а не выражения, которые вычислялись бы при каждом прохождении цикла;
  • особое внимание обратить на организацию циклов, убрав из них все повторяющиеся с одинаковыми данными вычисления и выполняя их до входа в цикл.

4. Программа должна содержать комментарии, позволяющие легко проследить за логической взаимосвязью и функциями отдельных ее частей.

При написании программы следует заботиться о ее структуре так, чтобы программа была удобочитаемой. В частности, в программе должны быть хорошо видны циклы. Для этого операторы FOR и NЕXТ нужно размещать в различных строках, не содержащих других операторов. Если цикл организуется без использования операторов FOR и NЕXТ, то в отдельных строках, не содержащих других операторов, должны быть размещены операторы, организующие цикл (задающие начальное значение управляющей переменной цикла, осуществляющие проверку условия выхода из цикла и т. п.).

Седьмой этап — тестирование и отладка программы — это проверка правильности работы программы и исправление обнаруженных ошибок.

Для выполнения тестирования необходимо подготовить тесты. Тест — это специально подобранные исходные данные в совокупности с теми результатами, которые должна выдавать программа при обработке этих данных. Разработка тестов — трудоемкая работа, часто требующая выполнения ручных просчетов. При составлении тестов нужно стремиться обеспечить проверку всех ветвей программы.

Далее даются некоторые рекомендации по тестированию и отладке.

  1. Проверьте работу программы (или отдельных ее частей) вручную до выхода на машину.
  2. Проводите тестирование и отладку отдельно для логически самостоятельных частей программы.
  3. Используйте отладочную печать в наиболее ответственных местах программы. Операторы печати для отладки располагайте в отдельных строках так, чтобы можно было легко убрать их из программы после окончания отладки.
  4. При тестировании, если это возможно, используйте меньшие объемы данных, чем те, на которые рассчитана программа.

Восьмой этап — счет по готовой программе и анализ результатов. Этот этап является итогом выполнения всех предыдущих этапов и служит подтверждением (или опровержением) их правомерности. После этого этапа, возможно, потребуется пересмотр самого подхода к решению задачи и возврат к первому этапу для повторного выполнения всех этапов с учетом приобретенного опыта.