Студопедия

КАТЕГОРИИ:

АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция

Лабораторная работа №9-10. Исправление ошибок в простой программе с условными операторами.




Что нужно знать:

· правила построения программы на Паскале, Python или Си

· правила работы с переменными (объявление, ввод, вывод, оператор присваивания)

· ветвление –  это выбор одного из двух возможных вариантов действий в зависимости от того, выполняется ли некоторое условие;

· на блок-схеме алгоритма ветвление изображается в виде блока-ромба с одним входом и двумя выходами:

       

· если условие, записанное внутри ромба, истинно (ответ «да» на вопрос «a=b?»), выполняются все команды, входящие в блок-1 (ветка «да»), иначе (если условие ложно) выполняются все команды в блоке-2 (ветка «нет»)

· в неполной форме условного оператора блок-2 пустой (отсутствует); теоретически можно сделать наоборот – так, чтобы блок-1 оказался пустой, но это очень неграмотное решение, поскольку оно осложняет понимание алгоритма, запутывает его

· одна команда ветвления может находиться внутри другой, например, так:

· на этой схеме блок-10 выполняется, когда a=b; блок-11 – когда a=b=c, блок-12 – когда a=b, но a¹c и, наконец, блок-2 – когда a¹b

· на этой схеме (Рисунок 3) одна команда ветвления (с условием «a=c») вложена в другую (с условием «a=b»), каждая из них – это ветвление в полной форме; если блок-12 будет пустой (отсутствует), внутреннее ветвление имеет неполную форму; аналогично, если блок-2 пустой, то внешнее ветвление имеет неполную форму

· условный оператор if–else служит для организации ветвления в программе на языке Паскаль

· условный оператор может иметь полную или неполную форму; вот фрагменты программы, реализующие ветвления, показанные на рисунках 1 и 2:

полная форма: неполная форма:
 if a = b then begin { блок-1 }  end  else begin { блок-2 }  end; if a = b then begin { блок-1 } end;

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

· обычно при записи программы операторы, находящиеся внутри обоих блоков, сдвигают вправо на 2-3 символа (запись «лесенкой»), это позволяет сразу видеть начало и конец блока (конечно, если «лесенка» сделана правильно)

· после else не надо (нельзя!) ставить какое-то условие, эта часть выполняется тогда, когда условие после if неверно (частая ошибка – после else пытаются написать условие, обратное тому, которое стоит после соответствующего ему if)

· в Паскале перед else не ставится точка с запятой, поскольку это ключевое слово обозначает не начало нового оператора, а вторую часть условного оператора if–else

· слова begin и end (их называют также «операторные скобки») ограничивают блок-1 и блок-2; если внутри блока всего один оператор, эти «скобки» можно не писать, например, допустимы такие операторы

 if a = b then c:=1  else c:=0;  if a = b then begin c:=1;  end  else c:=0; if a = b then c:=1;

· а вот такие операторы недопустимы

if a = b then begin c:=1  else c:=0;  if a = b then c:=1;  end  else c:=0; if a = b then c:=1; d:=1; else x:=1;

o в первом случае есть begin, но забыли про соответствующий ему end;

o во втором фрагменте наоборот, есть end, а begin отсутствует;

if a = b then begin c:=1; d:=1; end else x:=1;

o третий случай более сложный: судя по записи «лесенкой», здесь внутри блока-1 находятся 2 оператора, а операторных скобок begin-end нет; в результате получилось, что оператор c:=1 находится внутри блока-1, он выполняется только при условии a=b;
оператор d:=1 выполняется всегда, после того, как условный оператор закончил работу; а else вообще «висит» непонятно как, тут транслятор выдаст ошибку; исправить эту программу можно так, как показано справа (добавив пару begin-end):

· условный оператор может находиться внутри другого условного оператора, как в блоке-1, так и в блоке-2; например, схема на Рисунке 3 может быть записана на Паскале так:

if a = b then begin
if a = c then begin { блок-11 } end else begin { блок-12 } end;  
{ блок-10 }

if a = c then begin

{ блок-11 }

end

else begin

{ блок-12 }

end;

 end

 else begin

{ блок-2 }

 end;

· ключевая тема этого задания ЕГЭ – использование вложенных условных операторов, причем в тексте задания фрагмент программы обычно записан без отступов «лесенкой» или с неправильными отступами, например, так:

 if a = b then begin if a = c then c:=1;  end else c:=0;  if a = b then    if a = c then     c:=1  else c:=0;

Чтобы разобраться с работой этих программ, нужно определить, к какому из условных операторов if относится часть else; для этого используют такое правило: «любой else относится к ближайшему if».

Рассмотрим фрагмент слева, в нем перед else стоит end, поэтому для него нужно найти соответствующий ему begin; таким образом определяем, что else относится к первому (внешнему) условному оператору.

В правом фрагменте перед else нет end, поэтому он относится к ближайшему по тексту внутреннему условному оператору.

Блок-схемы для двух фрагментов показаны ниже, желтым цветом выделен «переехавший» блок:

     

 

· в условных операторах можно использовать сложные условия, которые строятся из простых отношений (<, <=, >, >=, =, <>) с помощью логических операций not («НЕ», отрицание), and («И», одновременное выполнение двух условий) и or («ИЛИ», выполнение хотя бы одного из двух условий)

· в сложном условии сначала выполняются действия в скобках, потом – not, затем – and, затем – or и, наконец, отношения;
операции равного уровня (приоритета) выполняются последовательно слева направо

· поскольку отношения в Паскале имеют низший приоритет, в сложном условии их приходится брать в скобки:

if (a = b) or (b < c) and (c <> d) then begin ... end;

· в приведенном выше примере сначала определяются результаты сравнения (выражения в скобках), затем выполняется операция and («И»), а затем – or («ИЛИ»)

Примеры заданий:

 На обработку поступает последовательность из четырёх неотрицательных целых чисел (некоторые числа могут быть одинаковыми). Нужно написать программу, которая выводит на экран количество нечётных чисел в исходной последовательности и максимальное нечётное число. Если нечётных чисел нет, требуется на экран вывести «NO». Известно, что вводимые числа не превышают 1000. Программист написал программу неправильно. Вот она:

const n = 4;

var i, x: integer;

var maximum, count: integer;



Begin

count := 0;

maximum := 999;

for i := 1 to n do begin

read(x);

if x mod 2 <> 0 then begin

count := count + 1;

if x > maximum then maximum := i

end

end;

if count > 0 then begin

writeln(count);

writeln(maximum)

end

else writeln('NO')

End.

Последовательно выполните следующее.

1. Напишите, что выведет эта программа при вводе последовательности: 2 9 4 3

2. Приведите пример такой последовательности, содержащей хотя бы одно нечётное число, что, несмотря на ошибки, программа печатает правильный ответ.

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

1) выпишите строку, в которой сделана ошибка;

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

Решение:

1) обратим внимание на две строки в начале программы, которые начинаются с ключевого слова var: это не ошибка, такое повторение, действительно, допустимо в языке Паскаль; возможно, это была одна из ловушек разработчиков КИМ, которую они применили на реальном ЕГЭ-2014

2) теперь выполним программу для заданной последовательности 2 9 4 3, записывая все изменения переменных в таблицу:

  условие i x maximum count вывод
count:=0;         0  
maximum:=999;       999    
for i := 1 to n do   1        
read(x);     2      
if x mod 2 <> 0 then нет          
end   2        
read(x);     9      
if x mod 2 <> 0 then да          
count:=count+1;         1  
if x > maximum then нет          
end   3        
read(x);     4      
if x mod 2 <> 0 then нет          
end   4        
read(x);     3      
if x mod 2 <> 0 then да          
count:=count+1;         2  
if x > maximum then нет          
end   5        
if count > 0 then да          
writeln(count);           2
writeln(maximum)           999

3) при ручной прокрутке программы мы увидели, что она правильно подсчитала количество нечётных чисел во входной последовательности, но неверно определила максимум: значение переменной maximum, которое было выведено на экран, осталось равным начальному значению 999, так как все остальные нечётные числа были меньше этого начального значения; поэтому ответ на п. 1 задания должен быть таким:

1) Программа выведет числа 2 и 999.

4) поскольку все числа по условию неотрицательны и не превышают 1000, программа всегда будет выдавать 999 вместо максимального нечётного числа; в то же время мы выяснили, что количество нечётных чисел в последовательности считается правильно; поэтому любая последовательность, содержащая 999, будет обрабатываться правильно

5) таким образом, правильный ответ на п. 2 должен быть таким:

2) Программа работает правильно для последовательности: 2 9 3 999.

6) теперь будем искать ошибки; как уже отмечалось, повторное использование ключевого слова var допустимо и указывать это в качестве ошибки нельзя!

7) как следует из результатов ручной прокрутки программы, во многих случаях она выдаёт неверный результат из-за того, что неверно задано начальное значение переменной maximum: оно должно быть меньше, чем любой возможный результат;

8) наименьшее нечётное неотрицательное число – это 1, поэтому можно принять в качестве начального значения maximum любое число, меньшее единицы (на самом деле, программа будет правильно работать и для 1), например:

3) Ошибка 1. maximum:=999;

Исправление: maximum:=0;

9) если теперь (с исправленной первой ошибкой) сделать ручную прокрутку программы, то мы увидим, что на последовательности 2 9 4 3 она выдает сначала 2, а потом – 4, то есть, значение максимума вычисляется опять неверно;

10) откуда появится число 4 в переменной maximum? оно будет записана в результате выполнения оператора if x > maximum then maximum:=i, который записывает в переменную maximum не значение полученного числа (x), а его номер (i); таким образом, мы нашли вторую ошибку:

Ошибка 2. if x > maximum then maximum:=i

Исправление: if x > maximum then maximum:=x

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

var N: longint;

s: integer;

Begin

readln(N);                                                        (1)

s := 0;                                                               (2)

while N > 1 do begin                                        (3)

if N mod 2 = 0 then begin                              (4)

s := N mod 10;                                             (5)

end;                                                                (6)

N := N div 10;                                                (7)

end;                                                                  (8)

write(s);                                                            (9)

End.

Последовательно выполните следующее.

1. Напишите, что выведет эта программа при вводе числа 1984.

2. Приведите пример числа, при вводе которого программа выдаст верный ответ.

3. Найдите в программе все ошибки (их может быть одна или несколько).

Для каждой ошибки выпишите строку, в которой она допущена, и приведите эту же строку в исправленном виде.

Обратите внимание: вам нужно исправить приведённую программу, а не написать свою. Вы можете только заменять ошибочные строки, но не можете удалять строки или добавлять новые. Заменять следует только ошибочные строки: за исправления, внесённые в строки, не содержащие ошибок, баллы будут снижаться.

Решение:

11) начнем с того, что разберёмся в условии задачи: ограничение N < 109 введено для того, чтобы число поместилось в 4-байтовую переменную целого типа, для совместимости со всеми трансляторами Паскаля соответствующая переменная объявлена как longint

12) теперь разберём программу; строка (1) – это ввод исходного числа; очевидно, что переменная s – это результат, поскольку именно она выводится в строке (9)

13) в строке (2) переменная s обнуляется, это естественно при накоплении суммы

14) строки (3)-(8) – это цикл, который выполняется пока N > 1; на каждом шаге цикла N делится на 10 нацело, то есть, из десятичной записи числа отбрасывается последняя цифра (строка (7)); такой цикл используется для того, чтобы перебрать все цифры числа, но обычно ставят условие «N > 0», поскольку в приведенном варианте цикл остановится при N = 1; однако в данном случае это не влияет на результат, поскольку по условию нас интересуют только чётные цифры, а 1 – нечётная

15) в строке (4) проверяется чётность числа (и одновременно чётность его последней цифры!), если число чётное, в строке (5) в переменную s записывается остаток от деления числа на 10, то есть последняя цифра десятичной записи этого числа

16) таким образом, после выполнения цикла будет выведена последняя рассмотренная цифра, для которой сработает условие в строке (4)

17) поскольку цифры перебираются с конца, выводится первая чётная цифра в записи числа

18) начнём выполнять задание:

1. При вводе числа 1984 будет выведено число 8 – значение первой чётной цифры числа.

19) когда программа выдаст верный ответ? очевидно, что тогда, когда сумма чётных цифр и значение первой чётной цифры совпадают; это возможно, если в числе

· нет чётных цифр (сумма останется равной 0)

· все чётные цифры – нули

· одна чётная цифра

· одна ненулевая чётная цифра, а нули стоят после неё (нули не меняют суммы!)

2. Программа выдаст правильный ответ для N = 1981.

20) как исправить программы? очевидно, нужно, чтобы она считала сумму чётных цифр, то есть, получив очередную чётную цифру, нужно добавить её к «старому» значению переменно s, изменив строку (5) так:

s := s + N mod 10;                                             (5)

3. Ошибка допущена в строке

s := N mod 10;

Эта строка должна в правильной программе выглядеть так

s := s + N mod 10;                                                 

 Требовалось написать программу, которая вводит с клавиатуры координаты точки на плоскости (x,y – действительные числа) и определяет принадлежность точки заштрихованной области, включая ее границы. Программист торопился и написал программу неправильно. Вот она:

var x,y: real;

Begin

readln(x,y);

if y>=x then

if y>=0 then

if y<=2-x*x then

write('принадлежит')

else

write('не принадлежит')

End.

Последовательно выполните следующее:

1. Перерисуйте и заполните таблицу, которая показывает, как работает программа при аргументах, принадлежащих различным областям (A, B, C, D, E, F и G). Точки, лежащие на границах областей, отдельно не рассматривать.

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

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

Решение:

21) начнем заполнять таблицу, выписывая истинность каждого из трёх условий

22) условие y>=x истинно выше прямой y=x, то есть в областях A, B, E, F

Область y>=x? y>=0? y<=2-x*x? вывод верно?
A да        
B да        
C нет        
D нет        
E да        
F да        
G нет        

23) условие y>=0 истинно выше прямой y=0, то есть в областях A, E, G, однако это условие проверяется только тогда, когда первое условие, y>=x, истинно; поэтому для всех областей, где первое условие неверно (это области C, D, G), сразу в столбце второго условия ставим прочерк (условие не будет проверяться)

Область y>=x? y>=0? y<=2-x*x? вывод верно?
A да да      
B да нет      
C нет      
D нет      
E да да      
F да нет      
G нет      

24) третье условие выполняется для областей «внутри» параболы, то есть для E, F, G, D; однако оно проверяется только тогда, когда первые два истинны (для А и Е), в остальных строках ставим прочерк:

Область y>=x? y>=0? y<=2-x*x? вывод верно?
A да да нет    
B да нет    
C нет    
D нет    
E да да да    
F да нет    
G нет    

25) как следует из текста программы, она выведет что-то на экран только в том случае, когда выполняются первые два условия и программа выходит на третье: для области А будет выведено «не принадлежит», для области Е – «принадлежит», именно в этих двух случаях программа работает правильно, в остальных – нет:

Область y>=x? y>=0? y<=2-x*x? вывод верно?
A да да нет не принадлежит да
B да нет нет
C нет нет
D нет нет
E да да да принадлежит да
F да нет нет
G нет нет

26) для того, чтобы доработать программу, проще всего составить одно сложное условие, описывающее всю заштрихованную область

27) в данном случае удобно представить данную область в виде объединения областей, первая из которых включает области E+G, а вторая – области E+F

28) область E+G соответствует условию (y>=0) and (y <=2-x*x)

29) область E+F соответствует условию (y>=x) and (y <=2-x*x)

30) объединение областей выполняется с помощью операции ИЛИ (or), так что полное условие принимает вид

(y>=0) and (y <=2-x*x) or (y>=x) and (y <=2-x*x)

поскольку операция И (and) имеет более высокий приоритет, чем ИЛИ (or), порядок выполнения операций тут правильный; в случае сомнений можно поставить дополнительные скобки:

((y>=0) and (y <=2-x*x)) or ((y>=x) and (y <=2-x*x))

31) поскольку в обоих условиях есть условие y <=2-x*x, запись можно немного сократить:

(y <=2-x*x) and ((y>=x) or (y>=0))

32) доработанная программа выглядит так:

var x,y: real;

Begin

readln(x,y);

if (y <=2-x*x) and ((y>=x) or (y>=0)) then

write('принадлежит')

Else

write('не принадлежит')

End.

Требовалось написать программу, которая вводит с клавиатуры координаты точки на плоскости (x,y – действительные числа) и определяет принадлежность точки заштрихованной области, включая ее границы. Программист торопился и написал программу неправильно. Вот она:

var x,y: real;

Begin

readln(x,y);

if y <= 1 then

if x >= 0 then

if y >= sin(x) then

write('принадлежит')










Последнее изменение этой страницы: 2018-06-01; просмотров: 272.

stydopedya.ru не претендует на авторское право материалов, которые вылажены, но предоставляет бесплатный доступ к ним. В случае нарушения авторского права или персональных данных напишите сюда...