Смекни!
smekni.com

Паскаль. Отладка программ (стр. 2 из 3)

Пример. Имеется логическое выражение not a and b xor с. Требуется вывести на печать значения логических переменных а, Ь, с, при которых данное выражение истинно. Мы предлагаем перебор всех возможных значений а, b, с с проверкой выполнения условия для каждого сочетания значений.

Program Sample;

Vara, b, с : boolean;

begin

for a := false to true do

for b := false to true do

for с := false to true do

if not a and b xor с then

begin

Write('a=',a);

Write('b=',b);

WriteLn('c=',c)

End

End.

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

a =FALSE

b =FALSE

с =TRUE

a =FALSE

b =TRUE

с =FALSE

a =TRUE

b =FALSE

c =TRUE

a =TRUE

b =TRUE

с =TRUE

Программа состоит из одного сложного оператора for a := false to true do, в который вложены последовательно еще два оператора for и оператор if. Часть then последнего содержит сложный оператор, состоящий из трех простых операторов, охваченных программными скобкамиbegin и end.

Циклы с логическими условиями

Введенный в предыдущей главе оператор цикла for обеспечивает выполнение цикла заданное количество раз, однако часто циклические действия заканчиваются по условию, то есть выполняются до достижения определенного результата. В Паскале есть два таких оператора цикла, отличающиеся тем, что в одном из них условие проверяется в начале цикла (while...do), а в другом — в конце цикла (repeat...until).

Оператор while.. do

Оператор цикла while (пока, в то время как) имеет вид:

While<логическое выражение> do<тело цикла>;

Цикл While обеспечивает выполнение тела цикла, следующего за словом do до тех пор, пока условие имеет значение true (истина). В качестве тела цикла может использоваться простой или сложный оператор. Условие проверяется перед началом каждого выполнения тела цикла, поэтому, если до первого выполнения цикла условие имеет значение false (ложь), оператор не выполняется ни одного раза (рис. 5.2).

Пример. Необходимо преобразовать значение угла в градусах к стандартному диапазону ±180° путем исключения полных оборотов окружности ±360°. Эта процедура может быть выполнена с помощью оператора цикла

While abs(Angle) > 180 do

if Angle > 0 then Angle := Angle — 360

else Angle := Angle + 360;

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

Цикл состоит из оператора if. Допустим, угол равен —700. Тогда условие Angle > 0 в операторе if имеет значение false, при этом выполняется часть else оператора if, и угол получит значение —340. Снова происходит проверка условия выполнения цикла, и цикл выполняется второй раз, после чего угол равен 20. При третьей проверке условия выполнения цикла он заканчивается, поскольку условие его выполнения Abs(20)>180 приняло значение false.

Оператор repeat... until...

Оператор цикла repeat... until... (повторять до тех пор, пока) имеет вид Repeat <тело цикла> until -<логическое выражение>;

Принципиальное отличие оператора repeat...until от оператора while...do в том, что проверка условия производится не перед началом выполнения оператора, а в его конце, когда решается вопрос, повторить ли еще раз действия. Поэтому тело этого цикла всегда выполняется по крайней мере один раз (рис. 5.3). Это важное отличие: приведенный для цикла while... do пример реализовать с оператором цикла repeat... until невозможно без дополнительных проверок и усложнений.

Второе отличие от оператора while...do — в логике завершения цикла. Цикл оператора repeat...until выполняется до тех пор, пока не станет истинным логическое выражение, следующее за словом until. Таким образом, использование логического выражения здесь имеет противоположный оператору while...do смысл. Здесь при истинности логического выражения (условия) цикл прекращается, а у оператора while...do при истинности логического выражения цикл продолжается.

Третье отличие в том, что оператор repeat...until имеет две части:

начальную и завершающую, которые охватывают группу операторов, составляющих тело цикла. Оператор while...do не имеет завершающей части и требует для организации тела цикла из нескольких операторов программных скобок begin-end. Для оператора repeat...until таких скобок не требуется — их роль выполняют составные части оператора.

Пример. Найти методом подбора целочисленное решение Диофантова уравнения 5x-3y=1. В качестве первой пробы берутся единичные значения. Далее, если 5x-3y>1, то у увеличивается на 1, если 5x-3y<1, то на 1 увеличивается х.

Program Diophant;

var х, у: byte;

begin

x:=1;y:=1;

repeat

if(5*x-3*y)>1theny:=y+1;

if (5 * x - 3 * у) < 1 then х := х + 1 until(5*x-3*y)=1;

writeln('x= ',x, 'y=',y) end.

В результате на экране получим х=2у=3.

Пример. С помощью цикла repeat...until можно организовать процедуру ввода данных с защитой программы от завершения при ошибочном наборе. Если тип данных не соответствует инициализируемой при стандартном вводе переменной (например, требуется ввести целое число, а набрано дробное), то возникает ошибка в выполнении программы, и мы должны снова запускать программу, и, естественно, повторить набор. Чтобы защититься от последствий таких ошибок, можно использовать собственную процедуру ввода. Такая процедура должна отключить автоматическую проверку правильности ввода и проводить ее самостоятельно, причем при ошибке требовать повторного набора. Отключение проверки правильности ввода производится директивой компилятора {$!-} (Input/Output checking в окне настройки опций компилятора). После каждого действия по вводу-выводу специальная функция lOResult возвращает целое значение, соответствующее ошибкам ввода-вывода. Правильной работе ввода-вывода соответствует нулевое значение, возвращаемое этой функцией. Надежный ввод целого числа i выполняет фрагмент программы:

{$!-} {отключение проверки ввода-вывода} repeat

Write ('Введите i = '); {вывод на экран предложения для ввода}

ReadLn (i) {ввод целого числа}

until lOResult = 0; {lOResult — функция, равная 0, если нет ошибки} {$!+} {восстановление проверки ввода-вывода}

По крайней мере один раз вводится число; если при вводе была сделана ошибка, условие lOResult = 0 имеет значение false, и ввод будет повторяться до тех пор, пока он не будет сделан правильно.

Операторы Break и Continue

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

Пример. Игра с ЭВМ в кости. Условия игры. Компьютер выдает себе или Вам случайные числа от 1 до 6. Задача — набрать максимальную сумму очков. Набравший больше 21 очка проигрывает, в любой момент один из игроков может отказаться от набора очков (спасовать).

Program Bones;

Const MaxSum = 1; {максимальное число очков}

var SumYour, {сумма очков игрока}

SumComp, {сумма очков компьютера}

count: byte; {очередные выпавшие очки}

reply: string; {ответ на запрос ЭВМ}

begin

SumYour := 0;

SumComp:=12; {начальное количество очков}

Randomize; {установка датчика случайных чисел}

repeat {начало общего цикла, организующего игру}

write ('Бросить кость для Вас? (у/n)');

repeat {Начало цикла для ввода корректного ответа} readln(reply) {ввод ответа}

{выход из цикла — при корректном ответе}

until (reply = 'у') or (reply = 'Y') or (reply ='n') or (reply = 'N');

{метание кости для игрока при положительном ответе}

if (reply = 'у') or (reply = 'Y') then {если ответ ”да”}

begin Count := Random(6) + 1; {число очков игрока}

{Random(6) дает случайные числа от 0 до 5}

WriteLn( вам выпало ', count,' очков.'); {вывод выпавшего количества очков} SumYour := SumYour + count; {подсчет суммы очков игрока}

Writeln('y Вас всего ', SumYour,' очков.'); {вывод суммы очков}

if SumYour >= MaxSum then Вгеаk{прекращение игры при переборе} end;

{метание кости для компьютера — он играет,

если сумма очков меньше 18}

if SumComp < 18 then {если компьютер продолжает игру}

begin Count := Random(6) + 1; {число очков компьютера} WriteLn('мнe выпало ', count,' очков.'); {вывод количества очков} SumComp := SumComp + count; {подсчет суммы очков компьютера} Writeln('y меня всего ', SumComp,' очков.'); {вывод суммы очков}

if SumYour >= MaxSum then Break {прекращение игры при переборе} end

else begin {если компьютер пасует}

write(‘ пас. Будете продолжать? (у/п)’);{запрос о продолжении игры}

repeat

read(reply) until (reply = 'у') or (reply = 'Y') or (reply = 'n') or (reply = 'N');

if (reply = 'n') or (reply = 'N') then Break {прекращение игры

по взаимному согласию}

end

until false; {замыкание цикла метания костей} {подведение итогов}

if SumYour > MaxSum then writeln('Bы проиграли!')

{перебор игрока}

else if SumComp > MaxSum then writeln(‘Я проиграл!')

{перебор у компьютера}

else if SumYour < SumComp then writeln('Я выиграл!')

{сравнение очков}

else if SumYour = SumComp then writeln ('Ничья!')

{равенство очков}

else writeln('Вы выиграли!');

ReadLn

end.

Программа разбита на две основные части: метание костей и подведение итогов.

Первая часть реализует бесконечный цикл метания костей, ограниченный оператором repeat ... until false. Выбор оператора repeat мотивирован тем, что должен быть сделан, по крайней мере, один ход игры. Цикл может быть прерван оператором Break при переборе очков любым из игроков и при отказе обоих партнеров от продолжения игры. Объединение трех условий в одно и использование его как завершающего условия цикла repeat... until усложнит алгоритм, а применение для прекращения игры оператора Break алгоритм упрощает.

Цикл repeat... until с завершающим условием

(reply = 'у') or (reply = 'Y') or (reply ='n') or (reply = 'N');

продолжается до тех пор, пока не будет введен допустимый символ ('у', 'Y', 'п' или 'N') при ответе на вопрос о продолжении игры.