Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
delphi / песни о паскале.pdf
Скачиваний:
63
Добавлен:
26.03.2016
Размер:
5.16 Mб
Скачать

Глава 17 И вновь за парту

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

«отлично» – за ноль ошибок;

«хорошо» – за 1-2 ошибки;

«удовлетворительно» – за 3-5 ошибок;

«неуд» – за 6 ошибок и более.

Цикл со счетчиком

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

Счетчик вопросов = 0 Счетчик ошибок = 0

 

Задать вопрос и получить ответ

 

 

 

 

 

 

 

Ошибка?

Да

 

 

 

Увеличить счетчик ошибок

 

 

 

 

 

Нет

 

 

 

 

 

 

Увеличить счетчик вопросов

Нет

Все вопросы?

Да

Выставить оценку

Рис. 39 – Блок-схема экзаменатора, выставляющего оценку

Основное отличие этой версии от предыдущих состоит в применении счетчиков. Один из них подсчитывает количество заданных вопросов (то есть

111

Глава 17

И вновь за парту

проходов цикла), а другой — количество ошибок. Что такое счетчик? Это числовая переменная, наращиваемая по ходу выполнения программы. Сначала рассмотрим тонкости, связанные с подсчетом вопросов.

Зададимся простой задачей: распечатать на экране числа от 1 до 10. Вот как это делается оператором REPEAT-UNTIL.

var N : integer;

{ счетчик }

begin

 

N:=1; repeat

Writeln(N);

N:= N+1;

until N>10

end.

Первый из подчеркнутых операторов устанавливает счетчик цикла в единицу,

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

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

Цикл со счетчиком объединяет в одной конструкции три действия: инициализацию счетчика, его приращение и проверку условия завершения цикла. Если б написать его по-русски, то оператор выглядел бы так:

ДЛЯ N:= начальное_значение ДО конечное_значение ВЫПОЛНИТЬ оператор

Но русским Паскаль не владеет, а потому переведем это на английский:

FOR N:= начальное_значение TO конечное_значение DO оператор

Как видите, конструкция построена на трех ключевых словах: FOR-TO-DO. После слова FOR следует оператор присваивания начального значения счетчику цикла. За словом TO указывают конечное значение счетчика, а после DO — выполняемый внутри цикла оператор. Но где наращивается счетчик? А нигде, это происходит автоматически! Теперь задача распечатки чисел может быть решена одним составным оператором.

112

Глава 17

И вновь за парту

var N : integer;

{ счетчик }

begin

for N:=1 to 10 do Writeln(N);

end.

Испытайте эту программку. Согласитесь, что ошибиться здесь труднее, чем в варианте с REPEAT. Как только вы написали FOR, то обязаны тут же указать начальное и конечное значения счетчика, а наращивать его Паскаль будет и без вас. В качестве начального и конечного значений вы вправе указать не только числа, но и выражения, — они будут вычислены один раз в начале цикла. Если начальное значение счетчика окажется равным конечному, цикл выполнится единожды. А если конечное значение окажется меньше начального, то ни разу!

Осталось ответить лишь на один вопрос: что, если внутри цикла надо выполнить несколько операторов? Ведь после слова DO предусмотрен лишь один. Впрочем, те, кто помнит об операторных скобках BEGIN-END, знают ответ. Напомню, что эти скобки превращают группу операторов в единый блок, этим мы и воспользуемся в новой версии экзаменатора.

{ P_17_1 –

экзаменатор,

выставляющий оценку }

var A, B,

C : integer; { сомножители и произведение }

Q,

E : integer; { счетчик вопросов и счетчик ошибок }

S:

string;

begin

Randomize;

E:= 0; { обнуляем счетчики ошибок }

for Q:= 1 to 15 do begin

{ 15 вопросов }

A:= 1+ Random(10);

B:= 1+ Random(10);

Write(Q,’) Сколько будет ’, A,’ x ’,B, ’ ? ’);

Readln(C);

{ Если ответ неверный, увеличиваем счетчик ошибок }

if A*B <> C then E:= E+1;

end; { цикл и блок завершаются здесь}

case E of

{ выставляем оценку }

0:

S:=’Отлично!’;

1,2:

S:=’Хорошо’;

3..5:

S:=’Удовлетворительно’;

else

S:=’Ну оччччень плохо!’;

end;

 

Writeln(S, ’ Нажмите Enter’); Readln;

end.

113

Глава 17

И вновь за парту

Рассмотрим изюминки этой программы. В операторе

Write(Q,’) Сколько будет ’, A,’ x ’,B, ’ ? ’);

вместе с вопросом печатается его порядковый номер Q.

Но самое интересное — это метки в операторе CASE. Напротив оценки «хорошо» стоит метка из двух разделенных запятой чисел (1, 2), — эта ветвь оператора CASE выполнится для этих двух значений. Такие объединенные метки

могут содержать несколько чисел. А если числа следуют подряд, их заменяют числовым диапазоном — это два числа, разделенные двумя точками («многоточием»), причем первое число должно быть меньше второго. Такой диапазон (3..5) служит меткой для ветви «Удовлетворительно».

Итоги

Цикл со счетчиком FOR-TO-DO удобен при известном количестве повторений, которое вычисляется при входе в цикл.

Счетчик цикла внутри оператора наращивается автоматически, цикл завершается, когда счетчик превысит указанное максимальное значение.

Оператор выбора CASE-OF-ELSE-END допускает метки из нескольких чисел, и даже диапазоны целых чисел.

Аслабо?

А) Позвольте ученику отказаться от сдачи экзамена. Признаком отказа будет ввод нуля в качестве ответа. В этом случае надо досрочно выйти из цикла и обойти выставляющий оценку оператор (вспомните о процедуре Break).

Б) Напишите программу, которая по введенному числу дает заключение о том, какому дню недели оно соответствует — рабочему (1-5) или выходному (6,7), например:

День = 2

Рабочий

День = 7

Выходной

День = 20

Ошибка!

Здесь подчеркнутые числа напечатаны пользователем.

В) Напишите программу, которая, запросив число N, печатала бы числа от 1 до N в обратном порядке, например:

114

Глава 17

И вновь за парту

N = 3

3

2

1

Г) Существует вариант цикла FOR, где счетчик цикла не наращивается, а уменьшается, этот оператор выглядит так:

FOR N:= начальное_значение DOWNTO конечное_значение DO оператор

Ключевое слово DOWNTO задает счет в обратном порядке (DOWN — «вниз»); при этом начальное значение счетчика должно быть больше или равно конечному, иначе цикл не выполнится ни разу. Воспользуйтесь этим оператором для решения предыдущей задачи (задание В).

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

Е) Напишите программу, вычисляющую сумму чисел от 1 до N, где N — число, вводимое пользователем.

Ж) Напишите программу, вычисляющую сумму только тех чисел от 1 до N, которые делятся либо на три, либо на пять.

Задачи на темы предыдущих глав

И) Платный участок трассы протянулся с километра P1 до километра P2 (P1<P2). А пост ГАИ размещен на километре M. Попадает ли этот пост на платный участок трассы? Пусть ваша программа разберется с этим.

К) Дорожная служба запланировала ремонт трассы на участке с R1 по R2 (R1<R2). В сочетании с условием предыдущей задачи ваша программа должна определить:

Будут ли ремонтировать весь платный участок P1-P2 ?

Будут ли ремонтировать хотя бы часть платного участка P1-P2 ? Если да, то определить длину ремонтируемой платной части.

Будут ли ремонтировать хотя бы часть бесплатного участка? Если да, то определить длину ремонтируемой бесплатной части.

115

Соседние файлы в папке delphi