Министерство образования и науки Российской Федерации

Федеральное государственное образовательное учреждение
высшего профессионального образования
«ЮЖНЫЙ ФЕДЕРАЛЬНЫЙ УНИВЕРСИТЕТ»

А. В. Абрамян, М. Э. Абрамян

Основы программирования на языке Паскаль в задачах

Электронное учебное пособие

Ростов-на-Дону 2010

Публикуется по решению учебно-методической комиссии
факультета математики, механики и компьютерных наук ЮФУ
от 16 апреля 2010 г.

Рецензенты:
к. ф.-м. н., доцент С. С. Михалкович,
старший преподаватель В. Н. Брагилевский

Аннотация

Электронное учебное пособие содержит материал, который можно отнести к начальной ступени изучения программирования. По форме изложения материала пособие является практическим введением в программирование: рассмотрение основных типов и конструкций языка программирования и связанных с ними алгоритмов проводится посредством обсуждения большого количества учебных заданий. Пособие содержит 360 задач; часть их снабжена полными решениями, к остальным даются подробные указания. В качестве языка программирования используется язык Паскаль, в качестве программных сред — среды Borland Delphi, Free Pascal Lazarus и PascalABC.NET. При описании процесса выполнения учебных заданий предполагается, что к используемой программной среде подключен электронный задачник по программированию Programming Taskbook.

Пособие состоит из 6 модулей, каждый из которых посвящен определенной теме базового курса программирования: вводу и выводу данных, оператору присваивания (модуль 1), целым числам и логическим выражениям (модуль 2), условному оператору и оператору выбора (модуль 3), операторам цикла (модуль 4), процедурам и функциям (модуль 5), обработке числовых последовательностей (модуль 6). Помимо основного содержания — формулировок учебных задач, решений и указаний — модули включают контрольные разделы (набор контрольных вопросов и итоговое задание), позволяющие определить уровень усвоения изученной темы.

Для преподавателей программирования, старшеклассников и студентов.

Авторы: А. В. Абрамян, М. Э. Абрамян.


Введение

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

В качестве языка программирования используется язык Паскаль — наиболее распространенный в настоящее время язык, применяемый на начальных этапах обучения. Предполагается, что задания будут выполняться в одной из следующих программных сред: Borland Delphi, Free Pascal Lazarus (sourceforge.net/projects/lazarus), PascalABC.NET (pascalabc.net). Каждая из этих сред содержит удобный редактор кода и быстрый компилятор, все они реализуют близкие по возможностям современные версии языка Паскаль. Кроме того, среды Free Pascal Lazarus и PascalABC.NET являются бесплатными программными продуктами (freeware).

При описании процесса выполнения учебных заданий предполагается, что к используемой среде программирования подключен электронный задачник по программированию Programming Taskbook (ptaskbook.com, автор доц. М. Э. Абрамян), который позволяет быстро ознакомиться с любым заданием, обеспечить получение различных вариантов исходных данных и автоматически проверить результат. Тем не менее, использование задачника не является обязательным, так как все этапы решения заданий можно реализовать и без него (соответствующий пример приведен в модуле 1).

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

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

При подготовке пособия были использованы материалы книг [1–11].

Ниже приводится перечень модулей и их разделов.

Модуль 1. Ввод и вывод данных, оператор присваивания

  • Комплексная цель
  • Решения типовых задач
  • Учебные задания и указания к ним
  • Контрольные вопросы
  • Итоговое задание

Модуль 2. Целые числа и логические выражения

  • Комплексная цель
  • Решения типовых задач
  • Учебные задания и указания к ним
  • Контрольные вопросы
  • Итоговое задание

Модуль 3. Условный оператор и оператор выбора

  • Комплексная цель
  • Решения типовых задач
  • Учебные задания и указания к ним
  • Контрольные вопросы
  • Итоговое задание

Модуль 4. Операторы цикла

  • Комплексная цель
  • Решения типовых задач
  • Учебные задания и указания к ним
  • Контрольные вопросы
  • Итоговое задание

Модуль 5. Процедуры и функции

  • Комплексная цель
  • Решения типовых задач
  • Учебные задания и указания к ним
  • Контрольные вопросы
  • Итоговое задание

Модуль 6. Обработка последовательностей

  • Комплексная цель
  • Решения типовых задач
  • Учебные задания и указания к ним
  • Контрольные вопросы
  • Итоговое задание


Модуль 1. Ввод и вывод данных, оператор присваивания

Комплексная цель

Знакомство со структурой программы на языке Паскаль, знание особенностей процедур ввода-вывода и оператора присваивания. Умение выполнять учебные задания, используя электронный задачник Programming Taskbook. Освоение базовых алгоритмов, связанных с присваиванием (в частности, алгоритма перемены местами содержимого двух или нескольких переменных). Знакомство с дополнительными возможностями задачника Programming Taskbook, связанными с выводом отладочной информации.

Структура модуля

  • Решения типовых задач
  • Учебные задания и указания к ним
  • Контрольные вопросы
  • Итоговое задание


Модуль 1. Ввод и вывод данных, оператор присваивания

Решения типовых задач

Ввод и вывод данных, оператор присваивания: Begin3, Begin22, Begin27

В данном разделе подробно описывается процесс выполнения учебных заданий на языке Паскаль с применением электронного задачника Programming Taskbook. Предполагается, что используется программная среда Borland Delphi (версии 7.0 или 2006), Free Pascal Lazarus версии 0.9 или PascalABC.NET.

Порядок выполнения учебного задания опишем на примере задания Begin3.

Begin3. Даны стороны прямоугольника a и b. Найти его площадь S = a·b и периметр P = 2·(a + b).

Чтобы создать проект, содержащий заготовку для требуемого задания, воспользуемся программным модулем PT4Load; для этого перейдем в рабочий каталог задачника и запустим ярлык Load.lnk. На экране появится окно модуля PT4Load. В заголовке этого окна указывается имя текущей среды программирования для задачника Programming Taskbook. Необходимо, чтобы в качестве текущей среды была установлена среда Borland Delphi (в этом случае будет указано имя DELPHI с номером версии) или среда Free Pascal Lazarus (в этом случае будет указано имя LAZARUS1, как на приведенном ниже рисунке). Если для задачника установлена другая среда, то заменить ее на требуемую можно с помощью контекстного меню модуля PT4Load, которое вызывается щелчком правой кнопки мыши.

В окне модуля PT4Load надо ввести имя нужного задания и нажать кнопку «Загрузка»:

После выполнения указанных действий запустится выбранная среда программирования и в нее немедленно загрузится программа-заготовка для выполнения выбранного задания. Эта заготовка будет содержать следующий текст:

program Begin3;
uses PT4;

begin
  Task('Begin3');
end.

Примечание 1. При выполнении заданий в среде PascalABC.NET порядок действий при создании заготовки должен быть другим: надо вначале запустить среду PascalABC.NET, а затем выполнить в данной среде команду «Модули | Создать шаблон программы», которая обеспечит запуск модуля PT4Load.

Заметим, что созданная программа-заготовка будет автоматически сохранена в файле, имя которого совпадает с именем задания. Расширение файла зависит от выбранной среды программирования: dpr для среды Delphi, lpr для среды Lazarus, pas для среды PascalABC.NET.

Опишем содержимое программы-заготовки.

Директива uses обеспечивает подключение модуля PT4. Модули языка Паскаль можно рассматривать как библиотеки, содержащие дополнительные подпрограммы (процедуры и функции). После подключения модуля к программе все содержащиеся в нем подпрограммы станут доступны для использования в подключившей его программе. Модуль PT4 содержит подпрограммы, связанные с электронным задачником Programming Taskbook.

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

Единственным оператором нашей программы является вызов процедуры Task. Эта процедура определена в модуле PT4, она предназначена для инициализации требуемого учебного задания. После имени процедуры Task в скобках указывается имя задания, которое надо инициализировать. Имя задания (в нашем случае Begin3) является строковой константой и поэтому по правилам языка Паскаль должно заключаться в апострофы: 'Begin3'.

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

Для компиляции и немедленного запуска программы (при отсутствии в ней синтаксических ошибок) в любой из рассматриваемых программных сред достаточно нажать клавишу [F9]. Запустив нашу программу, мы увидим на экране окно задачника Programming Taskbook с формулировкой задания и примером исходных данных:

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

Далее располагается раздел с исходными данными. В нашем случае это числа a и b — длины сторон исходного прямоугольника. Наличие у чисел дробной части означает, что они являются вещественными. При необходимости данные могут снабжаться комментариями; здесь это строки «a =» и «b =», расположенные перед числами a и b.

Последним разделом является раздел контрольных данных и результатов, содержащий две вкладки: «Пример верного решения» и «Полученные результаты». Если в программе не выполняются действия по вводу-выводу данных, то при запуске программы активной становится вкладка «Пример верного решения» с контрольными (то есть «правильными») результирующими данными. В нашем случае в ней отображаются правильные значения площади и периметра, снабженные комментариями. Если перейти на вкладку с результатами, щелкнув мышью на ярлычке «Полученные результаты» или нажав комбинацию клавиш [Ctrl]+[Tab], то в ней отобразятся только комментарии, поскольку наша программа пока не выводит никаких результирующих данных.

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

В нижней части окна располагается информационная панель и кнопка «Выход». Так как наша программа не выполняет действий по вводу-выводу данных, ее текущий запуск рассматривается как ознакомительный, и проверка правильности решения не производится. Для выхода из программы надо нажать кнопку «Выход» или клавишу [Esc]. Можно также нажать клавишу [F9], то есть ту же клавишу, которая использовалась для запуска программы.

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

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

program Begin3;
uses PT4;
var
  A, B, S, P: real;
begin
  Task('Begin3');
  GetR(A);
  GetR(B);
  S := A * B;
  P := 2 * (A + B);
end.

Прокомментируем полученную программу.

Раздел программы, начинающийся с ключевого слова var, содержит описания переменных. Переменные необходимы для хранения данных, которые используются в программе. Каждая переменная может содержать данные определенного типа: целочисленного, вещественного, строкового и т. д. При описании переменной указывается ее имя и тип. В качестве имени переменной можно использовать любую последовательность латинских букв и цифр (а также символ подчеркивания «_») при условии, что эти последовательность не начинается с цифры (имя переменной называется также ее идентификатором). В нашей программе мы описали четыре переменные A, B, S, P, перечислив их имена через запятую и указав после их списка тип этих переменных: real. Переменные типа real позволяют хранить вещественные числа, то есть числа, которые могут содержать дробную часть. В вариантах языка Паскаль, реализованных для сред Borland Delphi, Free Pascal Lazarus и PascalABC.NET, данные типа real имеют размер 8 байт и могут хранить вещественные числа с точностью до 15–16 значащих цифр, причем значения этих чисел по модулю не могут превосходить 1.7·10308. Заметим, что для очень больших (и очень маленьких) вещественных чисел удобно использовать экспоненциальный числовой формат. Так, максимальное вещественное число, которое можно записать в переменную типа real, представляется в этом формате следующим образом: 1.7e308 (вначале указывается мантисса числа — число, модуль которого лежит в диапазоне 1–10, затем буква e, а затем — порядок числа, то есть показатель степени 10, на которую надо умножить мантиссу для получения требуемого числа). В качестве десятичного разделителя в программах на Паскале используется точка.

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

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

Процедуры ввода используются в нашей программе для того, чтобы получить исходные данные: длины сторон исходного прямоугольника. Стандартные процедуры ввода языка Паскаль Read и Readln обеспечивают ввод исходных данных с клавиатуры (заметим, что эти процедуры могут использоваться и для считывания данных из файла). У нас — другая ситуация: исходные данные уже сформированы процедурой Task при инициализации задания; нам требуется лишь получить к ним доступ. Для этого надо использовать специальные процедуры ввода, имеющиеся в электронном задачнике Programming Taskbook:

GetN обеспечивает ввод исходных данных целого типа (integer);

GetR обеспечивает ввод исходных данных вещественного типа (real);

GetC обеспечивает ввод исходных данных символьного типа (char);

GetS обеспечивает ввод исходных данных строкового типа (string);

GetB обеспечивает ввод исходных данных логического типа (boolean).

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

Примечание 2. При выполнении заданий в среде PascalABC.NET для ввода исходных данных, подготовленных задачником, можно использовать стандартную процедуру Read, так как модуль PT4 переопределяет ее действие, заставляя вместо считывания данных с клавиатуры обращаться за этими данными к задачнику.

Более подробно процедуры группы Get описаны в приложении.

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

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

переменная := выражение;

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

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

Запустив программу, мы получим сообщение: «Выведены не все результирующие данные. Количество выведенных данных: 0 (из 2)», причем фон информационной панели станет красным. Ситуация понятна: приступая к вводу исходных данных, мы тем самым продемонстрировали намерение выполнить задание. Однако, найдя требуемые данные, мы не вывели их, и поэтому электронный задачник не смог их проанализировать и сравнить с контрольными данными.

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

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

Для вывода данных в языке Паскаль предусмотрены стандартные процедуры Write и Writeln. Однако в нашей программе требуется не только отобразить результаты на экране, но и передать их электронному задачнику для сравнения с контрольными данными. Эти действия обеспечивают специальные процедуры вывода, имеющиеся в электронном задачнике Programming Taskbook:

PutN обеспечивает вывод результатов целого типа (integer);

PutR обеспечивает вывод результатов вещественного типа (real);

GetC обеспечивает вывод результатов символьного типа (char);

PutS обеспечивает вывод результатов строкового типа (string);

PutB обеспечивает вывод результатов логического типа (boolean).

В качестве параметров в этих процедурах можно указывать не только переменные, но и выражения (в отличие от описанных выше процедур группы Get, параметрами которых могут быть только переменные). Арифметическое выражение может содержать арифметические операции, числовые константы и круглые скобки, например, 2.5 * (b - 5) - 4. Для процедур вывода, как и для процедур ввода, необходимо, чтобы тип параметра соответствовал типу данных, для вывода которых предназначена процедура.

Примечание 3. При выполнении заданий в среде PascalABC.NET для вывода результатов можно использовать стандартную процедуру Write, так как модуль PT4 переопределяет ее действие, заставляя вместо вывода результатов на экран пересылать их задачнику для проверки и отображения в его окне.

Более подробно процедуры группы Put описаны в приложении.

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

Добавим в конец программы вывод результатов:

  PutR(P);
  PutR(S);

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

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

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

Изменяя порядок вывода результатов, мы, наконец, получим правильный вариант программы:

program Begin3;
uses PT4;
var
  A, B, S, P: real;
begin
  Task('Begin3');
  GetR(A);
  GetR(B);
  S := A * B;
  P := 2 * (A + B);
  PutR(S);
  PutR(P);
end.

Примечание 4. Следует заметить, что в использовании вспомогательных переменных S и P при выполнения задания Begin3 нет необходимости, поскольку при выводе данных можно указывать не только переменные, но и выражения. Учитывая эту возможность, можно получить более короткий вариант решения задания Begin3:

program Begin3a;
uses PT4;
var
  A, B: real;
begin
  Task('Begin3');
  GetR(A);
  GetR(B);
  PutR(A * B);
  PutR(2 * (A + B));
end.

После запуска правильного варианта информационная панель (фон которой теперь станет зеленым) будет содержать сообщение «Верное решение. Тест номер 1 (из 3)». Мы провели первое успешное испытание нашей программы. Однако однократное успешное испытание алгоритма еще не означает, что он является правильным. Для того чтобы получить уверенность в правильности алгоритма, его надо проверить (протестировать) несколько раз на различных наборах исходных данных. Количество тестовых испытаний, требующихся для каждого учебного задания, различно и может меняться в пределах от 3 до 10 (для простого задания Begin3 число испытаний равно трем). Если нужное количество испытаний, проведенных подряд, прошло успешно, то на информационной панели появится сообщение «Задание выполнено!»:

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

Примечание 5. После выполнения требуемого количества успешных тестовых испытаний на информационной панели вместо сообщения «Задание выполнено!» может появиться сообщение «Верное решение. Покажите преподавателю текст программы». Подобная ситуация обычно возникает, если преподаватель желает убедиться в том, что программа оформлена надлежащим образом и удовлетворяет все требованиям, указанным в формулировке задания. Просмотрев текст программы и убедившись, что все требования учебного задания выполнены, преподаватель еще раз запустит программу и введет специальный код, означающий, что задание им проверено. При этом на информационной панели появится сообщение «Задание выполнено!#» (символ # означает, что программа не только прошла тестовые испытания, но и была проверена преподавателем).

Напомним, что закрыть окно программы с учебным заданием можно не только нажатием клавиши [Esc], но и нажатием клавиши [F9], то есть той же клавиши, которая в средах Delphi, Lazarus и PascalABC.NET запускает программу на выполнение. Таким образом, для проверки программы на нескольких наборах исходных данных достаточно несколько раз подряд нажать [F9].

Информация о ходе выполнения задания записывается в файл результатов. Если задания выполняются в средах Delphi или Lazarus, то для просмотра файла результатов надо использовать ярлык Results.lnk, находящийся в рабочем каталоге учащегося и предназначенный для запуска программного модуля PT4Results. В случае среды PascalABC.NET достаточно выполнить ее команду «Модули | Просмотреть результаты».

Результаты, связанные с выполнением задания Begin3, будут выглядеть следующим образом:

Begin3      p05/05 12:09 Ознакомительный запуск.--2
Begin3      p05/05 12:16 Ошибочное решение.
Begin3      p05/05 12:24 Задание выполнено!

Число 2, указанное после текста «Ознакомительный запуск», означает, что было выполнено два запуска программы с одним и тем же результатом, а буква p, указанная перед датой, означает, что задание выполнялось на языке Паскаль в среде Delphi или Lazarus (если задание выполнялось в среде PascalABC.NET, то перед датой указывается заглавная буква A).

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

Рассмотрим еще два задания из группы Begin.

Begin22. Поменять местами содержимое переменных A и B и вывести новые значения A и B.

При решении этого задания (как и всех прочих заданий группы Begin) нам достаточно использовать процедуры ввода-вывода и операторы присваивания:

program Begin22;
uses PT4;
var
  A, B, V: real;
begin
  Task('Begin22');
  GetR(A);
  GetR(B);
  V := A;
  A := B;
  B := V;
  PutR(A);
  PutR(B);
end.

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

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

  A := A + B;
  B := A - B;
  A := A - B;

Хотя на практике этот алгоритм обычно не используется, он является хорошей иллюстрацией особенностей оператора присваивания. Проанализируем работу алгоритма, предполагая, что вначале переменная A содержит значение 4, а переменная B — значение 7. Первый оператор вычисляет сумму исходных значений (11) и записывает ее в переменную A. Теперь в A содержится число 11, а в B — прежнее значение 7. Второй оператор вычитает текущее значение переменной B из текущего значения переменной A и записывает полученный результат (11 – 7 = 4) в переменную B. Таким образом, в переменной B уже записано требуемое значение (4), а в переменной A по-прежнему содержится сумма исходных чисел (11). Осталось еще раз вычесть из переменной A переменную B (11 – 4 = 7) и записать полученный результат в переменную A.

Описанные нами действия удобно оформить в виде так называемой трассировочной таблицы, в которой для каждой переменной отводится свой столбец, а в качестве строк указываются выполняемые операторы. Если какой-либо оператор изменяет значение некоторой переменной, то новое значение переменной указывается в ее столбце рядом с этим оператором; если ячейка является пустой, то для получения текущего значения переменной надо подняться в ее столбце до первой непустой ячейки:

Операторы | Переменная A | Переменная B
 | 4 | 7
A := A + B; | 11 |
B := A - B; |  | 4
A := A - B; | 7 |

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

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

В качестве примера применения процедуры Show дополним приведенный выше второй вариант алгоритма обмена таким образом, чтобы по тексту в разделе отладки можно было проследить за изменением содержимого переменных A и B:

program Begin22;
uses PT4;
var
  A, B: real;
begin
  Task('Begin22');

  GetR(A);
  GetR(B);
  Show('A = ', A, 5);
  ShowLine('B = ', B, 5);

  A := A + B;
  Show('A = ', A, 5);
  ShowLine('B = ', B, 5);

  B := A - B;
  Show('A = ', A, 5);
  ShowLine('B = ', B, 5);

  A := A - B;
  Show('A = ', A, 5);
  ShowLine('B = ', B, 5);

  PutR(A);
  PutR(B);
end.

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

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

Begin27. Дано число A. Вычислить A8, используя вспомогательную переменную и три операции умножения. Для этого последовательно находить A2, A4, A8. Вывести все найденные степени числа A.

Если вычислять целочисленную степень AN, перемножая N экземпляров числа A, то количество операций умножения будет на 1 меньше показателя степени, то есть числа N. В частности, для нахождения восьмой степени потребуется семь операций умножения: A * A * A * A * A * A * A * A. Число операций при нахождении степени можно уменьшить, если в процессе вычислений сохранять промежуточные результаты в одной или нескольких вспомогательных переменных. При этом, как следует из формулировки задания Begin27, для нахождения восьмой степени числа будет достаточно использовать всего три операции умножения:

program Begin27;
uses PT4;
var
  A, P: real;
begin
  Task('Begin27');
  GetR(A);
  P := A * A;  // в P записана вторая степень A: A*A
  PutR(P);
  P := P * P;  // в P записана четвертая степень A: (A*A)*(A*A)
  PutR(P);
  P := P * P;  // в P записана восьмая степень A: ((A*A)*(A*A))*((A*A)*(A*A))
  PutR(P);
end.

В приведенной программе в переменную P последовательно записывается вторая, четвертая и восьмая степень числа A. Заметим, что можно было бы обойтись без вспомогательной переменной P, последовательно записывая эти же степени в переменную A, но в этом случае мы потеряли бы ее исходное значение, что обычно является нежелательным.

После каждого оператора присваивания в текст программы мы добавили комментарий, поясняющий смысл этого оператора. Комментарии к программе не обрабатываются компилятором и не учитываются при выполнении программы; они позволяют сделать более понятной программу для человека, который читает ее текст. В программе были использованы так называемые однострочные комментарии, которые начинаются с двух символов // и продолжаются до конца текущей строки. Комментарии такого типа можно использовать не во всех реализациях Паскаля, однако в средах Borland Delphi, Free Pascal Lazarus и PascalABC.NET они доступны. В любой реализации Паскаля можно использовать многострочные комментарии, начинающиеся с открывающей фигурной скобки { и оканчивающиеся закрывающей фигурной скобкой }. Многострочные комментарии можно также ограничивать двухсимвольными комбинациями (* и *).

О способах ввода и вывода данных, не использующих средства электронного задачника

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

В данном разделе описывается, как выполнять задания без использования электронного задачника на языке Паскаль в средах Borland Delphi, Free Pascal Lazarus и PascalABC.NET. При этом приводится дополнительная информация о стандартных процедурах ввода-вывода. Указанная информация пригодится, в частности, при выполнении итоговых заданий, приведенных в заключительном разделе каждого из 6 учебных модулей, входящих в настоящее пособие, поскольку итоговые задания требуется выполнить без использования электронного задачника Programming Taskbook.

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

В среде Borland Delphi заготовку для консольного приложения можно создать, выполняя следующие действия: в меню Delphi выбрать команду «File | New | Other…», в появившемся окне «New Items» выбрать в списке проектов вариант «Console Application» и нажать кнопку «OK» или клавишу [Enter]. В результате будет создан новый проект — консольное приложение, и основной файл этого проекта (dpr-файл) будет загружен в редактор среды Delphi.

Приведем содержимое dpr-файла:

program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils;

begin
  { TODO -oUser -cConsole Main : Insert code here }
end.

Созданный dpr-файл содержит специальную директиву компилятора {$APPTYPE CONSOLE}, позволяющую связать с данной программой консольное окно, а также директиву uses, с помощью которой к программе подключается стандартный модуль SysUtils, содержащий различные полезные подпрограммы. Раздел операторов программы является пока пустым; содержащийся в нем текст, заключенный в фигурные скобки {}, является комментарием, который при компиляции и выполнении программы не учитывается. Обратите внимание на то, что директива компилятора {$APPTYPE CONSOLE} выглядит как комментарий (покольку она тоже заключена в фигурные скобки), однако она учитывается при компиляции программы. Любую директиву компилятора отличает от обычного комментария наличие символа $ сразу после открывающей скобки {.

Заметим, что при использовании стандартных средств Паскаля модуль SysUtils не требуется, поэтому директиву uses SysUtils можно из текста программы удалить, как и весь комментарий TODO (директиву {$APPTYPE CONSOLE} удалять не следует!):

program Project1;

{$APPTYPE CONSOLE}

begin
end.

Аналогичные действия для создания консольного приложения предусмотрены и в среде Free Pascal Lazarus. Если в этой среде используется русский интерфейс, то достаточно выполнить команду меню «Файл | Создать…» и в появившемся окне «Создать…» в группе «Projects» выбрать вариант «Program» (вариант «Console application» выбирать не следует, поскольку данный вариант предназначен для создания заготовки консольного приложения более сложного вида). После нажатия кнопки «OK» в редактор среды Lazarus будет загружен основной файл созданного проекта (этот файл будет иметь расширение lpr):

program Project1;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Classes
  { you can add units after this };

{$IFDEF WINDOWS}{$R project1.rc}{$ENDIF}

begin
end.

Несколько устрашающий вид этого файла объясняется наличием большого числа директив компилятора и комментариев. Однако все эти директивы и комментарии, а также директиву uses, можно убрать, и в результате мы получим программу простейшего вида:

program Project1;

begin
end.

Примечание 6. В среде PascalABC.NET отсутствует специальное средство для создания заготовки консольного приложения. Для создания новой программы достаточно выполнить команду «Файл | Новый» и ввести текст

begin
end.

Сразу после создания заготовки консольного приложения ее надо сохранить в рабочем каталоге. Для этого достаточно нажать комбинацию клавиш [Ctrl]+[S], выбрать в появившемся диалоговом окне рабочий каталог и ввести имя приложения (рекомендуется в качестве имени указывать имя выполняемого задания, например, Begin3). Заметим, что в среде Delphi и Lazarus указанное имя автоматически заменит имя Project1 в строке program.

При выполнении задания с помощью «обычного» консольного приложения отличия проявятся лишь в организации ввода-вывода. Откорректируем второй вариант решения задания Begin3 (не использующий вспомогательные переменные S и P — см. примечание 4), организовав ввод и вывод с помощью стандартных процедур языка Паскаль. В результате получим следующую программу (в приведенном тексте не указана начальная часть программы, содержащая строку program и директиву компилятора {$APPTYPE CONSOLE} в случае использования среды Delphi):

var
  A, B: real;
begin
  Write('A = '); Readln(A);
  Write('B = '); Readln(B);
  Writeln('S = ', A * B);
  Writeln('P = ', 2 * (A + B));
  Readln;
end.

Подробно опишем операторы ввода-вывода, использованные в данной программе.

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

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

Для ввода исходных данных используется процедура Readln; каждый ее вызов, подобно вызову процедуры GetR, позволяет определить значение переменной, указанной в качестве ее параметра. Заметим, что в процедуре Readln можно указывать список параметров (например, Readln(A, B)), однако мы не воспользовались этой возможностью, так как она не позволяет вывести приглашение перед вводом каждого элемента исходных данных. Не следует также применять вариант процедуры ввода Read (причина этого будет объяснена ниже — см. примечание 7).

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

Осталось объяснить смысл последнего оператора: вызова процедуры Readln без параметров. Этот вызов приостанавливает работу программы до тех пор, пока не будет нажата клавиша [Enter]. Таким образом, после вывода полученных результатов программа будет ожидать нажатия [Enter], консольное окно останется на экране, и мы сможем ознакомиться с его содержимым. После нажатия [Enter] программа завершит работу, что приведет к немедленному закрытию консольного окна. Если бы оператор Readln в конце программы отсутствовал, то после вывода результатов консольное окно было бы немедленно закрыто, и мы не успели бы ознакомиться с его содержимым.

Примечание 7. Если использовать для ввода исходных данных процедуру Read, то однократный вызов процедуры Readln в конце программы не приведет к приостановке программы; именно поэтому для ввода исходных данных рекомендуется использовать вариант Readln (мы не будем подробно рассматривать причину подобного поведения различных вариантов стандартной процедуры ввода).

Примечание 8. При выполнении программы в среде PascalABC.NET последний оператор Readln указывать не обязательно, так как в этой среде ввод и вывод данных выполняется по умолчанию не в «обычное» консольное окно, а в особое окно вывода, расположенное в нижней части окна среды PascalABC.NET. Окно вывода постоянно отображается на экране, поэтому просмотреть данные, выведенные программой, можно и после ее завершения (окно вывода можно временно скрыть, нажав клавишу [F5]; эта же клавиша используется для повторного отображения окна вывода).

После компиляции и запуска созданной программы (выполняемых по нажатию клавиши [F9]) и появления в консольном окне очередного запроса на ввод следует ввести требуемый элемент исходных данных и нажать клавишу [Enter]. Для исправления ошибочно введенных символов можно использовать клавишу [Backspace], но только до нажатия [Enter], после которого введенный элемент передается программе. При вводе вещественных чисел их дробная часть должна отделяться от целой части точкой. После ввода всех исходных данных программа вычислит и выведет в консольное окно результат. Приведем вид консольного окна для сред Delphi и Free Pascal Lazarus после ввода исходных данных A = 6.5, B = 9:

A = 6.5
B = 9
S =  5.85000000000000E+0001
P =  3.10000000000000E+0001

В окне вывода среды PascalABC.NET результаты будут выглядеть следующим образом:

A = 6.5
B = 9
S = 58.5
P = 31

Результаты в обоих случаях являются правильными, однако в консольном окне они представлены в не слишком наглядном экспоненциальном числовом формате. Как правило, для вывода вещественных данных бывает достаточно указать два знака после десятичного разделителя (заметим, что именно так в большинстве заданий отображаются вещественные данные в окне задачника Programming Taskbook). Для того чтобы указанным образом вывести результат в консольном окне, следует использовать при выводе данных в процедуре Writeln специальные атрибуты форматирования.

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

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

Если атрибут Decimal отсутствует, то вещественное число отображается в экспоненциальном формате. Если отсутствует атрибут Width, то элемент занимает на экране столько позиций, сколько минимально требуется для его вывода.

Используем описанные выше атрибуты форматирования в двух последних операторах вывода:

  Writeln('S = ', A * B:6:2);
  Writeln('P = ', 2 * (A + B):6:2);

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

A = 6.5
B = 9
S =  58.50
P =  31.00

Если при выполнении задания надо обработать много исходных данных (например, некоторую числовую последовательность, как в заданиях, приведенных в модуле 6), то для ввода данных с клавиатуры при каждом тестовом запуске программы может потребоваться много времени. В этом случае удобно вместо ввода данных с клавиатуры генерировать их с помощью программного датчика случайных чисел; это позволит при каждом запуске испытывать программу на новом наборе исходных данных, который будет формироваться автоматически (подобно тому, как это происходит в задачнике Programming Taskbook). Заметим, что на самом деле программный датчик генерирует псевдослучайные числа, поскольку для генерации действительно случайных чисел необходимо использовать специальные устройства.

Для генерации случайных чисел в языке Паскаль предусмотрены процедура Randomize, инициализирующая датчик случайных чисел, и функция Random. Функция Random реализована в двух вариантах: без параметров (в этом случае она возвращает очередное вещественное случайное число, лежащее на полуинтервале [0, 1)) и с одним параметром N целого типа (в этом случае она возвращает целое случайное число, лежащее в диапазоне от 0 до N - 1). Заметим, что для получения вещественного числа, лежащего на полуинтервале [A, B), достаточно применить к результату функции Random следующее преобразование: A + Random * (B – A). Если требуется получить одно из целых чисел в диапазоне от A до B – 1, можно воспользоваться выражением A + Random(B – A) (так как функция Random(B – A) возвращает числа в диапазоне от 0 до B – A – 1).

Приведем пример генерации исходных данных с помощью датчика случайных чисел для задания Begin3 в предположении, что стороны прямоугольника a и b могут принимать вещественные значения из полуинтервала [5, 15):

. . .
Randomize;
A := 5 + Random * 10;
B := 5 + Random * 10;
. . .

В среде PascalABC.NET вызов процедуры Randomize выполняется автоматически в начале работы любой программы, поэтому в явном ее вызове нет необходимости. В средах Delphi и Lazarus данную процедуру надо обязательно вызывать явным образом в начале программы, так как в случае ее отсутствия при каждом запуске программы будет генерироваться один и тот же набор случайных чисел.


Модуль 1. Ввод и вывод данных, оператор присваивания

Учебные задания и указания к ним

Ввод и вывод данных, оператор присваивания

Все входные и выходные данные в заданиях этой группы являются вещественными числами.

Begin1. Дана сторона квадрата a. Найти его периметр P = 4·a.

Begin2. Дана сторона квадрата a. Найти его площадь S = a2.

Begin3. Даны стороны прямоугольника a и b. Найти его площадь S = a·b и периметр P = 2·(a + b).

Begin4. Дан диаметр окружности d. Найти ее длину L = p·d. В качестве значения p использовать 3.14.

Begin5. Дана длина ребра куба a. Найти объем куба V = a3 и площадь его поверхности S = 6·a2.

Begin6. Даны длины ребер a, b, c прямоугольного параллелепипеда. Найти его объем V = a·b·c и площадь поверхности S = 2·(a·b + b·c + a·c).

Begin7. Найти длину окружности L и площадь круга S заданного радиуса R:

L = 2·p·R, S = p·R2.

В качестве значения p использовать 3.14.

Begin8. Даны два числа a и b. Найти их среднее арифметическое: (a + b)/2.

Begin9. Даны два неотрицательных числа a и b. Найти их среднее геометрическое, то есть квадратный корень из их произведения: (a·b)1/2.

Begin10. Даны два ненулевых числа. Найти сумму, разность, произведение и частное их квадратов.

Begin11. Даны два ненулевых числа. Найти сумму, разность, произведение и частное их модулей.

Begin12. Даны катеты прямоугольного треугольника a и b. Найти его гипотенузу c и периметр P:

c = (a2 + b2)1/2, P = a + b + c.

Begin13. Даны два круга с общим центром и радиусами R1 и R2 (R1 > R2). Найти площади этих кругов S1 и S2, а также площадь S3 кольца, внешний радиус которого равен R1, а внутренний радиус равен R2:

S1 = p·(R1)2, S2 = p·(R2)2, S3 = S1 – S2.

В качестве значения p использовать 3.14.

Begin14. Дана длина L окружности. Найти ее радиус R и площадь S круга, ограниченного этой окружностью, учитывая, что L = 2·p·R, S = p·R2. В качестве значения p использовать 3.14.

Begin15. Дана площадь S круга. Найти его диаметр D и длину L окружности, ограничивающей этот круг, учитывая, что L = p·D, S = p·D2/4. В качестве значения p использовать 3.14.

Begin16. Найти расстояние между двумя точками с заданными координатами x1 и x2 на числовой оси: |x2 – x1|.

Begin17. Даны три точки A, B, C на числовой оси. Найти длины отрезков AC и BC и их сумму.

Begin18. Даны три точки A, B, C на числовой оси. Точка C расположена между точками A и B. Найти произведение длин отрезков AC и BC.

Begin19. Даны координаты двух противоположных вершин прямоугольника: (x1, y1), (x2, y2). Стороны прямоугольника параллельны осям координат. Найти периметр и площадь данного прямоугольника.

Begin20. Найти расстояние между двумя точками с заданными координатами (x1, y1) и (x2, y2) на плоскости. Расстояние вычисляется по формуле

((x2 – x1)2 + (y2 – y1)2)1/2.

Begin21. Даны координаты трех вершин треугольника: (x1, y1), (x2, y2), (x3, y3). Найти его периметр и площадь, используя формулу для расстояния между двумя точками на плоскости (см. задание Begin20). Для нахождения площади треугольника со сторонами a, b, c использовать формулу Герона:

S = (p·(p – a)·(p – b)·(p – c))1/2,

где p = (a + b + c)/2 — полупериметр.

Begin22. Поменять местами содержимое переменных A и B и вывести новые значения A и B.

Begin23. Даны переменные A, B, C. Изменить их значения, переместив содержимое A в B, B — в C, C — в A, и вывести новые значения переменных A, B, C.

Begin24. Даны переменные A, B, C. Изменить их значения, переместив содержимое A в C, C — в B, B — в A, и вывести новые значения переменных A, B, C.

Begin25. Найти значение функции y = 3x6 – 6x2 – 7 при данном значении x.

Begin26. Найти значение функции y = 4(x–3)6 – 7(x–3)3 + 2 при данном значении x.

Begin27. Дано число A. Вычислить A8, используя вспомогательную переменную и три операции умножения. Для этого последовательно находить A2, A4, A8. Вывести все найденные степени числа A.

Begin28. Дано число A. Вычислить A15, используя две вспомогательные переменные и пять операций умножения. Для этого последовательно находить A2, A3, A5, A10, A15. Вывести все найденные степени числа A.

Begin29. Дано значение угла a в градусах (0 £ a < 360). Определить значение этого же угла в радианах, учитывая, что 180° = p радианов. В качестве значения p использовать 3.14.

Begin30. Дано значение угла a в радианах (0 £ a < 2·p). Определить значение этого же угла в градусах, учитывая, что 180° = p радианов. В качестве значения p использовать 3.14.

Begin31. Дано значение температуры T в градусах Фаренгейта. Определить значение этой же температуры в градусах Цельсия. Температура по Цельсию TC и температура по Фаренгейту TF связаны следующим соотношением:

TC = (TF – 32)·5/9.

Begin32. Дано значение температуры T в градусах Цельсия. Определить значение этой же температуры в градусах Фаренгейта. Температура по Цельсию TC и температура по Фаренгейту TF связаны следующим соотношением:

TC = (TF – 32)·5/9.

Begin33. Известно, что X кг конфет стоит A рублей. Определить, сколько стоит 1 кг и Y кг этих же конфет.

Begin34. Известно, что X кг шоколадных конфет стоит A рублей, а Y кг ирисок стоит B рублей. Определить, сколько стоит 1 кг шоколадных конфет, 1 кг ирисок, а также во сколько раз шоколадные конфеты дороже ирисок.

Begin35. Скорость лодки в стоячей воде V км/ч, скорость течения реки U км/ч (U < V). Время движения лодки по озеру T1 ч, а по реке (против течения) — T2 ч. Определить путь S, пройденный лодкой (путь = время · скорость). Учесть, что при движении против течения скорость лодки уменьшается на величину скорости течения.

Begin36. Скорость первого автомобиля V1 км/ч, второго — V2 км/ч, расстояние между ними S км. Определить расстояние между ними через T часов, если автомобили удаляются друг от друга. Данное расстояние равно сумме начального расстояния и общего пути, проделанного автомобилями; общий путь = время · суммарная скорость.

Begin37. Скорость первого автомобиля V1 км/ч, второго — V2 км/ч, расстояние между ними S км. Определить расстояние между ними через T часов, если автомобили первоначально движутся навстречу друг другу. Данное расстояние равно модулю разности начального расстояния и общего пути, проделанного автомобилями; общий путь = время · суммарная скорость.

Begin38. Решить линейное уравнение A·x + B = 0, заданное своими коэффициентами A и B (коэффициент A не равен 0).

Begin39. Найти корни квадратного уравнения A·x2 + B·x + C = 0, заданного своими коэффициентами A, B, C (коэффициент A не равен 0), если известно, что дискриминант уравнения положителен. Вывести вначале меньший, а затем больший из найденных корней. Корни квадратного уравнения находятся по формуле

x1, 2 = (–B ± (D)1/2)/(2·A),

где D — дискриминант, равный B2 – 4·A·C.

Begin40. Найти решение системы линейных уравнений вида

A1·x + B1·y = C1,
A2·x + B2·y = C2,

заданной своими коэффициентами A1, B1, C1, A2, B2, C2, если известно, что данная система имеет единственное решение. Воспользоваться формулами

x = (C1·B2 – C2·B1)/D, y = (A1·C2 – A2·C1)/D,
где D = A1·B2 – A2·B1.

Указания

В тексте указаний используется сокращенное обозначение для диапазона заданий, включающее имя темы, номер начального и номер конечного задания (например, диапазон заданий от Begin1 до Begin9 обозначается следующим образом: Begin1–9).

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

Begin10–11. Для хранения квадратов (Begin10) и модулей (Begin11) исходных чисел используйте вспомогательные переменные. Для нахождения модуля числа предназначена функция Abs.

Begin12–15. В этих заданиях некоторые из результирующих данных используются при последующих вычислениях, поэтому перед выводом таких данных их следует сохранить во вспомогательных переменных. Например, при выполнении Begin12 следует сохранить найденную гипотенузу (используемую далее при вычислении периметра треугольника). Для вычисления квадратного корня используйте функцию Sqrt.

Begin16–19. При вычислении длин отрезков используйте функцию Abs (заметим, что в Begin18 правильный ответ можно получить и без использования этой функции).

Begin22–24. См. решение задачи Begin22. Задачи Begin23–24 решаются аналогично.

Begin25–26. В Begin25 при вычислении x6 используйте ранее найденное значение x2; аналогично, в Begin26 при вычислении (x – 3)6 используйте ранее найденное значение (x – 3)3. При вычислении (x– 3)3 удобно предварительно сохранить значение выражения x – 3 во вспомогательной переменной.

Begin27–28. См. решение задачи Begin27. Задача Begin28 решается аналогично.

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


Модуль 1. Ввод и вывод данных, оператор присваивания

Контрольные вопросы

Для каждого вопроса щелкните мышью на радиокнопке с номером варианта ответа, который, по вашему мнению, является правильным. После того как вы ответите на все вопросы, проверьте правильность ответов, нажав на кнопку «Проверка».

1. Значение переменной C типа real равно 8. Укажите значение, которое получит переменная C после выполнения оператора

C := C * 4 + C / 2 - 1;
(1) | 47 | (2) | 19
(3) | 35 | (4) | 24

2. Переменная A1 имеет значение 1, переменная A2 — значение 2; обе переменные имеют тип real. Укажите значения, которые будут содержать эти переменные после выполнения следующих операторов:

A1 := A1 + A2;
A2 := A1 + A2;
(1) | A1 = 3, A2 = 3 | (2) | A1 = 3, A2 = 5
(3) | A1 = 4, A2 = 3 | (4) | A1 = 4, A2 = 5

3. Укажите значение, которое будет содержать переменная P типа real после выполнения оператора

P := 12 + 12 / 4 * 3;
(1) | 2 | (2) | 13
(3) | 18 | (4) | 21

4. Значение вещественного числа B требуется вывести на экран вместе с комментарием «B = ». Выберите правильный вариант процедуры вывода.

(1) | Write(B = , B); | (2) | Write('B = ', B);
(3) | Write(B = , 'B'); | (4) | Write('B = ', 'B');

5. Выберите такой вариант атрибутов форматирования вещественного числа A, равного 729.438, при которых это число будет выведено в виде « 7.294E+0002».

(1) | Специальные атрибуты не требуются. | (2) | :12
(3) | :12:3 | (4) | :12:9

6. Укажите значение, которое не может содержаться в переменной D типа real после выполнения оператора

D := 200 * Random - 100;
(1) | 0.0 | (2) | 50.0
(3) | –50.0 | (4) | 150.0


Модуль 1. Ввод и вывод данных, оператор присваивания

Итоговое задание

Используя датчик случайных чисел, сформировать три вещественных числа: A, B, C. Модули этих чисел должны лежать в диапазоне от 10 до 100; числа A и B должны быть положительными, а число C — отрицательным.

Решить уравнение A·x2 + B·x + C = 0, используя формулу корней квадратного уравнения:

x1, 2 = (–B ± (D)1/2)/(2·A),
где D — дискриминант, равный B2 – 4·A·C.

Вывести значение дискриминанта D, затем значение меньшего корня x1, затем — значение большего корня x2.

Для проверки правильности найденных корней вывести значения левой части уравнения при x = x1 и x = x2 (полученные значения должны быть близки к 0).

Все числа должны выводиться с двумя знаками после десятичной точки. Коэффициенты уравнения, дискриминант и корни выводятся в формате с фиксированной точкой, а значения левых частей — в экспоненциальном формате.

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

A =  88.83
B =  17.79
C = -15.37

D  =  5779.49
x1 = -0.53
x2 =  0.33

A*x1*x1 + B*x1 + C =  5.49E-0016
A*x2*x2 + B*x2 + C =  1.13E-0015

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


Модуль 2. Целые числа и логические выражения

Комплексная цель

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

Структура модуля

  • Решения типовых задач
  • Учебные задания и указания к ним
  • Контрольные вопросы
  • Итоговое задание


Модуль 2. Целые числа и логические выражения

Решения типовых задач

Целые числа: Integer8, Integer11

Для описания целых чисел в Паскале используется описатель integer. В вариантах языка Паскаль, реализованных для сред Borland Delphi, Free Pascal Lazarus и PascalABC.NET, данные этого типа имеют размер 4 байта и принимают значения в диапазоне от –2147483648 до 2147483647. Заметим, что в современных реализациях Паскаля имеются и другие целочисленные типы, например, byte (размер 1 байт, диапазон значений — от 0 до 255) или int64 (размер 8 байт, диапазон значений — от –9 223 372 036 854 775 808 до 9 223 372 036 854 775 807), однако в большинстве случаев используется именно тип integer. Этот же тип следует использовать в программах, выполняющих учебные задания с применением электронного задачника Programming Taskbook.

Для целых чисел (как и для вещественных) определены операции сложения +, вычитания –, умножения *, причем результат каждой из этих операций с целочисленными операндами является целым числом. Что же касается деления, то в языке Паскаль операция / всегда обозначает «обычную» операцию деления (с результатом вещественного типа), а для деления нацело в нем предусмотрена особая операция div. Кроме того, в языке Паскаль определена операция mod для нахождения остатка от деления. И операция целочисленного деления div, и операция взятия остатка mod может применяться только к операндам целого типа.

Использование этих операций продемонстрируем на примере решения задания Integer8.

Integer8. Дано двузначное число. Вывести число, полученное при перестановке цифр исходного числа.

program Integer8;
uses PT4;
var
  N, A, B: integer;
begin
  Task('Integer8');
  GetN(N);
  A := N div 10;
  B := N mod 10;
  PutN(B * 10 + A);
end.

В данном решении первая слева цифра (десятки) двузначного числа N сохраняется в переменной A, а вторая цифра (единицы) — в переменной B. При перестановке цифр эти переменные «меняются ролями»: B обозначает количество десятков, A — количество единиц.

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

Integer11. Дано трехзначное число. Найти сумму и произведение его цифр.

program Integer11;
uses PT4;
var
  N, A, B, C: integer;
begin
  Task('Integer11');
  GetN(N);
  C := N mod 10;
  N := N div 10;
  B := N mod 10;
  A := N div 10;
  PutN(A + B + C);
  PutN(A * B * C);
end.

В данном решении цифры числа N вычисляются в обратном порядке (то есть справа налево): в C записываются единицы, в B — десятки, в A — сотни.

Логические выражения: Boolean2, Boolean7

Особым типом данных являются данные логического типа, описываемые с помощью ключевого слова boolean. Эти данные могут принимать только два значения: True (истина) или False (ложь).

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

К операциям отношения относятся следующие: «равно» =, «не равно» <>, «меньше» <, «больше» >, «меньше или равно» <=, «больше или равно» >=. Операндами этих операций обычно являются выражения числовых типов (хотя допустимо применять эти операции и к данным других типов, например, к символам и строкам), а результатом операций является значение типа boolean. Например, выражение 1 < 2 имеет значение True, а 2 = 3 — значение False. Выражение A <> 4 принимает значение False, если значение переменной A равно 4, и False в противном случае.

Основными логическими операциями являются следующие: «отрицание» not, «логическое И» and, «логическое ИЛИ» or, «исключающее логическое ИЛИ» xor. Выражение not A равно True, если операнд A имеет значение False, и False, если операнд A имеет значение True. Выражение A and B равно True только в случае, если оба операнда (A И B) имеют значение True. Выражение A or B равно True, если хотя бы один операнд (A ИЛИ B) имеет значение True. Выражение A xor B равно True, если операнды имеют различные значения (то есть один из операндов имеет значение True, а другой — False).

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

A | B | A and B | A or B | A xor B
False | False | False | False | False
False | True | False | True | True
True | False | False | True | True
True | True | True | True | False

В языке Паскаль логические операции имеют более высокий приоритет, чем операции отношения, поэтому в сложных логических выражениях, как правило, требуются скобки. Например, выражение 2 < 3 and 4 < 5 приведет к ошибке компиляции, так как в силу более высокого приоритета вначале должна быть обработана операция and, а ее операнды (3 и 4) имеют недопустимый тип (целый, а не логический). Для исправления выражения необходимо добавить в него скобки: (2 < 3) and (4 < 5), явно указывающие, что вначале надо выполнять операции отношения, а затем к их результатам (логического типа) применять логическую операцию and.

Среди логических операций наивысший приоритет имеет операция отрицания, за ней следует операция «И», затем операция «ИЛИ»; низший приоритет имеет операция «исключающее ИЛИ». Таким образом, если предположить, что A, B, и C являются переменными логического типа, то в выражении A or not B and C скобки по умолчанию расставляются следующим образом: A or ((not B) and C).

Примечание. В рассматриваемых нами средах программирования (Borland Delphi, Free Pascal Lazarus, PascalABC.NET) логические операции and и or выполняются по так называемой сокращенной схеме. Это означает, что данные операции могут возвращать результат, не вычисляя второй операнд, если этот результат однозначно определяется по первому операнду. Для операции and второй операнд не вычисляется, если первый операнд равен False (в качестве результата возвращается False); для операции or второй операнд не вычисляется, если первый равен True (в качестве результата возвращается True).

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

Boolean2. Дано целое число A. Проверить истинность высказывания: «Число A является нечетным».

program Boolean2;
uses PT4;
var
  A: integer;
begin
  Task('Boolean2');
  GetN(A);
  PutB(A mod 2 <> 0);
end.

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

Имеется другой способ решения этой задачи, использующий стандартную логическую функцию Паскаля Odd(N), которая возвращает значение True, если число N (целого типа) является нечетным, и False в противном случае. Таким образом, последний оператор программы, решающей задачу Boolean2, можно записать также следующим образом:

  PutB(Odd(A));

Boolean7. Даны три целых числа: A, B, C. Проверить истинность высказывания: «Число B находится между числами A и C».

program Boolean7;
uses PT4;
var
  A, B, C: integer;
begin
  Task('Boolean7');
  GetN(A);
  GetN(B);
  GetN(C);
  PutB((A < B) and (B < C) or (A > B) and (B > C));
end.

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

Заметим, что для решения задачи можно использовать более простое логическое выражение, поскольку достаточно проверить, что выражения A – B и B – C имеют один и тот же знак, а для этого достаточно убедиться в том, что произведение этих выражений положительно. Приведем последний оператор этого варианта решения:

PutB((A - B) * (B - C) > 0);


Модуль 2. Целые числа и логические выражения

Учебные задания и указания к ним

Целые числа

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

Integer1. Дано расстояние L в сантиметрах. Используя операцию деления нацело, найти количество полных метров в нем (1 метр = 100 см).

Integer2. Дана масса M в килограммах. Используя операцию деления нацело, найти количество полных тонн в ней (1 тонна = 1000 кг).

Integer3. Дан размер файла в байтах. Используя операцию деления нацело, найти количество полных килобайтов, которые занимает данный файл (1 килобайт = 1024 байта).

Integer4. Даны целые положительные числа A и B (A > B). На отрезке длины A размещено максимально возможное количество отрезков длины B (без наложений). Используя операцию деления нацело, найти количество отрезков B, размещенных на отрезке A.

Integer5. Даны целые положительные числа A и B (A > B). На отрезке длины A размещено максимально возможное количество отрезков длины B (без наложений). Используя операцию взятия остатка от деления нацело, найти длину незанятой части отрезка A.

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

Integer7. Дано двузначное число. Найти сумму и произведение его цифр.

Integer8. Дано двузначное число. Вывести число, полученное при перестановке цифр исходного числа.

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

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

Integer11. Дано трехзначное число. Найти сумму и произведение его цифр.

Integer12. Дано трехзначное число. Вывести число, полученное при прочтении исходного числа справа налево.

Integer13. Дано трехзначное число. В нем зачеркнули первую слева цифру и приписали ее справа. Вывести полученное число.

Integer14. Дано трехзначное число. В нем зачеркнули первую справа цифру и приписали ее слева. Вывести полученное число.

Integer15. Дано трехзначное число. Вывести число, полученное при перестановке цифр сотен и десятков исходного числа (например, 123 перейдет в 213).

Integer16. Дано трехзначное число. Вывести число, полученное при перестановке цифр десятков и единиц исходного числа (например, 123 перейдет в 132).

Integer17. Дано целое число, большее 999. Используя одну операцию деления нацело и одну операцию взятия остатка от деления, найти цифру, соответствующую разряду сотен в записи этого числа.

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

Integer19. С начала суток прошло N секунд (N — целое). Найти количество полных минут, прошедших с начала суток.

Integer20. С начала суток прошло N секунд (N — целое). Найти количество полных часов, прошедших с начала суток.

Integer21. С начала суток прошло N секунд (N — целое). Найти количество секунд, прошедших с начала последней минуты.

Integer22. С начала суток прошло N секунд (N — целое). Найти количество секунд, прошедших с начала последнего часа.

Integer23. С начала суток прошло N секунд (N — целое). Найти количество полных минут, прошедших с начала последнего часа.

Integer24. Дни недели пронумерованы следующим образом: 0 — воскресенье, 1 — понедельник, 2 — вторник, …, 6 — суббота. Дано целое число K, лежащее в диапазоне 1–365. Определить номер дня недели для K-го дня года, если известно, что в этом году 1 января было понедельником.

Integer25. Дни недели пронумерованы следующим образом: 0 — воскресенье, 1 — понедельник, 2 — вторник, …, 6 — суббота. Дано целое число K, лежащее в диапазоне 1–365. Определить номер дня недели для K-го дня года, если известно, что в этом году 1 января было четвергом.

Integer26. Дни недели пронумерованы следующим образом: 1 — понедельник, 2 — вторник, …, 6 — суббота, 7 — воскресенье. Дано целое число K, лежащее в диапазоне 1–365. Определить номер дня недели для K-го дня года, если известно, что в этом году 1 января было вторником.

Integer27. Дни недели пронумерованы следующим образом: 1 — понедельник, 2 — вторник, …, 6 — суббота, 7 — воскресенье. Дано целое число K, лежащее в диапазоне 1–365. Определить номер дня недели для K-го дня года, если известно, что в этом году 1 января было субботой.

Integer28. Дни недели пронумерованы следующим образом: 1 — понедельник, 2 — вторник, …, 6 — суббота, 7 — воскресенье. Дано целое число K, лежащее в диапазоне 1–365, и целое число N, лежащее в диапазоне 1–7. Определить номер дня недели для K-го дня года, если известно, что в этом году 1 января было днем недели с номером N.

Integer29. Даны целые положительные числа A, B, C. На прямоугольнике размера A ´ B размещено максимально возможное количество квадратов со стороной C (без наложений). Найти количество квадратов, размещенных на прямоугольнике, а также площадь незанятой части прямоугольника.

Integer30. Дан номер некоторого года (целое положительное число). Определить соответствующий ему номер столетия, учитывая, что, к примеру, началом 20 столетия был 1901 год.

Логические выражения

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

Boolean1. Дано целое число A. Проверить истинность высказывания: «Число A является положительным».

Boolean2. Дано целое число A. Проверить истинность высказывания: «Число A является нечетным».

Boolean3. Дано целое число A. Проверить истинность высказывания: «Число A является четным».

Boolean4. Даны два целых числа: A, B. Проверить истинность высказывания: «Справедливы неравенства A > 2 и B £ 3».

Boolean5. Даны два целых числа: A, B. Проверить истинность высказывания: «Справедливы неравенства A ³ 0 или B < –2».

Boolean6. Даны три целых числа: A, B, C. Проверить истинность высказывания: «Справедливо двойное неравенство A < B < C».

Boolean7. Даны три целых числа: A, B, C. Проверить истинность высказывания: «Число B находится между числами A и C».

Boolean8. Даны два целых числа: A, B. Проверить истинность высказывания: «Каждое из чисел A и B нечетное».

Boolean9. Даны два целых числа: A, B. Проверить истинность высказывания: «Хотя бы одно из чисел A и B нечетное».

Boolean10. Даны два целых числа: A, B. Проверить истинность высказывания: «Ровно одно из чисел A и B нечетное».

Boolean11. Даны два целых числа: A, B. Проверить истинность высказывания: «Числа A и B имеют одинаковую четность».

Boolean12. Даны три целых числа: A, B, C. Проверить истинность высказывания: «Каждое из чисел A, B, C положительное».

Boolean13. Даны три целых числа: A, B, C. Проверить истинность высказывания: «Хотя бы одно из чисел A, B, C положительное».

Boolean14. Даны три целых числа: A, B, C. Проверить истинность высказывания: «Ровно одно из чисел A, B, C положительное».

Boolean15. Даны три целых числа: A, B, C. Проверить истинность высказывания: «Ровно два из чисел A, B, C являются положительными».

Boolean16. Дано целое положительное число. Проверить истинность высказывания: «Данное число является четным двузначным».

Boolean17. Дано целое положительное число. Проверить истинность высказывания: «Данное число является нечетным трехзначным».

Boolean18. Проверить истинность высказывания: «Среди трех данных целых чисел есть хотя бы одна пара совпадающих».

Boolean19. Проверить истинность высказывания: «Среди трех данных целых чисел есть хотя бы одна пара взаимно противоположных».

Boolean20. Дано трехзначное число. Проверить истинность высказывания: «Все цифры данного числа различны».

Boolean21. Дано трехзначное число. Проверить истинность высказывания: «Цифры данного числа образуют возрастающую последовательность».

Boolean22. Дано трехзначное число. Проверить истинность высказывания: «Цифры данного числа образуют возрастающую или убывающую последовательность».

Boolean23. Дано четырехзначное число. Проверить истинность высказывания: «Данное число читается одинаково слева направо и справа налево».

Boolean24. Даны числа A, B, C (число A не равно 0). Рассмотрев дискриминант D = B2 – 4·A·C, проверить истинность высказывания: «Квадратное уравнение A·x2 + B·x + C = 0 имеет вещественные корни».

Boolean25. Даны числа x, y. Проверить истинность высказывания: «Точка с координатами (x, y) лежит во второй координатной четверти».

Boolean26. Даны числа x, y. Проверить истинность высказывания: «Точка с координатами (x, y) лежит в четвертой координатной четверти».

Boolean27. Даны числа x, y. Проверить истинность высказывания: «Точка с координатами (x, y) лежит во второй или третьей координатной четверти».

Boolean28. Даны числа x, y. Проверить истинность высказывания: «Точка с координатами (x, y) лежит в первой или третьей координатной четверти».

Boolean29. Даны числа x, y, x1, y1, x2, y2. Проверить истинность высказывания: «Точка с координатами (x, y) лежит внутри прямоугольника, левая верхняя вершина которого имеет координаты (x1, y1), правая нижняя — (x2, y2), а стороны параллельны координатным осям».

Boolean30. Даны целые числа a, b, c, являющиеся сторонами некоторого треугольника. Проверить истинность высказывания: «Треугольник со сторонами a, b, c является равносторонним».

Boolean31. Даны целые числа a, b, c, являющиеся сторонами некоторого треугольника. Проверить истинность высказывания: «Треугольник со сторонами a, b, c является равнобедренным».

Boolean32. Даны целые числа a, b, c, являющиеся сторонами некоторого треугольника. Проверить истинность высказывания: «Треугольник со сторонами a, b, c является прямоугольным».

Boolean33. Даны целые числа a, b, c. Проверить истинность высказывания: «Существует треугольник со сторонами a, b, c».

Boolean34. Даны координаты поля шахматной доски x, y (целые числа, лежащие в диапазоне 1–8). Учитывая, что левое нижнее поле доски (1, 1) является черным, проверить истинность высказывания: «Данное поле является белым».

Boolean35. Даны координаты двух различных полей шахматной доски x1, y1, x2, y2 (целые числа, лежащие в диапазоне 1–8). Проверить истинность высказывания: «Данные поля имеют одинаковый цвет».

Boolean36. Даны координаты двух различных полей шахматной доски x1, y1, x2, y2 (целые числа, лежащие в диапазоне 1–8). Проверить истинность высказывания: «Ладья за один ход может перейти с одного поля на другое».

Boolean37. Даны координаты двух различных полей шахматной доски x1, y1, x2, y2 (целые числа, лежащие в диапазоне 1–8). Проверить истинность высказывания: «Король за один ход может перейти с одного поля на другое».

Boolean38. Даны координаты двух различных полей шахматной доски x1, y1, x2, y2 (целые числа, лежащие в диапазоне 1–8). Проверить истинность высказывания: «Слон за один ход может перейти с одного поля на другое».

Boolean39. Даны координаты двух различных полей шахматной доски x1, y1, x2, y2 (целые числа, лежащие в диапазоне 1–8). Проверить истинность высказывания: «Ферзь за один ход может перейти с одного поля на другое».

Boolean40. Даны координаты двух различных полей шахматной доски x1, y1, x2, y2 (целые числа, лежащие в диапазоне 1–8). Проверить истинность высказывания: «Конь за один ход может перейти с одного поля на другое».

Указания

В тексте указаний используется сокращенное обозначение для диапазона заданий, включающее имя темы, номер начального и номер конечного задания (например, диапазон заданий от Integer1 до Integer5 обозначается следующим образом: Integer1–5).

Integer1–5. Простейшие задания на применение операций div (Integer1–4) и mod (Integer5).

Integer6–10. См. решение Integer8, прочие задачи решаются аналогично.

Integer11–16. См. решение Integer11, выделяющее из трехзначного числа все цифры. Используя полученные цифры, нетрудно сформировать числа, требуемые в заданиях Integer12–16 (cр. с решением Integer8).

Integer19–23. Для нахождения количества полных минут (задание Integer19) достаточно воспользоваться выражением N div 60; прочие задачи решаются аналогично: в Integer20 используйте операцию div, в Integer21–22 — операцию mod, в Integer23 — обе эти операции.

Integer24–28. В Integer24 номер дня недели для K-го дня года получается в результате нахождения остатка от целочисленного деления K на 7; это легко определить, составив таблицу зависимости номера дня недели от K для нескольких начальных значений K (например, для K = 1, 2, …, 10). В остальных заданиях для нахождения требуемых формул также удобно составить таблицу зависимости (заметим, что в этих формулах, помимо операции взятия остатка от деления, будут использоваться и другие арифметические операции).

Integer29. В ходе решения необходимо определить, сколько сторон квадрата c умещается на сторонах прямоугольника a и b (заметим, что сравнение площадей квадрата и прямоугольника не позволит получить правильный ответ).

Boolean1. Если исходное число содержится в переменной A, то достаточно вывести значение логического выражения A > 0.

Boolean2–3. См. решение Boolean2; задача Boolean3 решается аналогично, с заменой операции сравнения <> на операцию =. Для проверки того, что число A является четным, можно также использовать выражение not Odd(A).

Boolean4–5. В Boolean4 используйте операцию and, в Boolean5 используйте операцию or.

Boolean6. Двойное неравенство A < B < C означает, что A < B и B < C. Данное условие на языке Паскаль имеет вид (A < B) and (B < C).

Boolean7. См. решение этой задачи.

Boolean8–11. По поводу проверки четности см. решение Boolean2. В Boolean8 используйте операцию and, в Boolean9 — операцию or. В Boolean10–11 можно использовать операцию xor, однако проще проанализировать четность суммы исходных чисел.

Boolean12–15. В Boolean12 используйте операцию and, в Boolean13 — операцию or. В Boolean14–15 используйте логические выражения, содержащие обе эти операции.

Boolean16–17. По поводу проверки четности см. решение Boolean2. При определении количества знаков достаточно учесть, что двузначные числа лежат в диапазоне 10–99, а трехзначные — в диапазоне 100–999.

Boolean18–19. При выполнении этих заданий можно обойтись без логических операций. Например, в Boolean18 достаточно проанализировать выражение (A – B) * (B – C) * (C – A). В Boolean19 надо перемножать не разности, а суммы исходных чисел.

Boolean20–23. По поводу нахождения цифр, входящих в целое число, см. решения Integer8 и Integer11. Ср. Boolean20 с Boolean18, Boolean21 с Boolean6, Boolean22 с Boolean7.

Boolean25–28. В Boolean25–26 используйте логическую операцию and; в Boolean27–28 можно обойтись без использования логических операций.

Boolean29. Достаточно проверить, что одновременно выполняются два двойных неравенства: x1 < x < x2 и y2 < y < y1 (по поводу проверки двойных неравенств см. указание к Boolean6).

Boolean31–32. Ср. Boolean31 с Boolean18. В Boolean32 достаточно проверить, что квадрат какой-либо стороны равен сумме квадратов двух других сторон.

Boolean34–35. Цвет клетки с координатами (x, y) зависит от четности выражения x + y. По поводу проверки четности см. решение Boolean2.

Boolean36–40. При перемещении ладьи одна из ее координат не изменяется. При перемещении короля его координаты изменяются (по модулю) не более чем на 1: |x1 – x2| £ 1 и |y1 – y2| £ 1. Слон ходит по диагонали, поэтому каждая его координата должна изменяться на одинаковое (по модулю) число. Ферзь ходит как ладья и как слон. При перемещении коня одна из его координат изменяется (по модулю) на 1, а другая — на 2; таким образом, модуль произведения разностей координат при любом правильном перемещении коня должен быть равен 2.


Модуль 2. Целые числа и логические выражения

Контрольные вопросы

Для каждого вопроса щелкните мышью на радиокнопке с номером варианта ответа, который, по вашему мнению, является правильным. После того как вы ответите на все вопросы, проверьте правильность ответов, нажав на кнопку «Проверка».

1. Укажите выражение, значение которого равно количеству нечетных чисел, лежащих в диапазоне от 1 до N (включая концы диапазона), если N — некоторое целое положительное число.
(1) | N div 2 | (2) | N div 2 + 1
(3) | N div 2 - 1 | (4) | (N + 1) div 2

2. Дано целое число N, равное 9753. Укажите значение, которое будет содержаться в переменной K целого типа после выполнения оператора

K := N div 100 mod 10;
(1) | 7 | (2) | 5
(3) | 0 | (4) | 97

3. Даны три логические переменные: A = False, B = False, C = True. Укажите значения логических переменных D и E после выполнения следующих операторов:

D := not A or B and C;
E := B or not C and A;
(1) | D = True, E = True | (2) | D = False, E = True
(3) | D = True, E = False | (4) | D = False, E = False

4. Дан фрагмент программы (A, B, C — переменные целого типа):

A := 1;
B := 0;
C := 5;
Write(C < 0 and A / B < 1);

Укажите, что произойдет при обработке этого фрагмента.

(1) | Возникнет ошибка компиляции | (2) | Возникнет ошибка времени выполнения
(3) | Будет напечатана логическая константа False | (4) | Будет напечатана логическая константа True

5. Даны целые числа A и B. Укажите, какое условие проверяется следующим выражением:

not Odd(A) and Odd(B)
(1) | A является нечетным, а B — четным | (2) | A является четным, а B — нечетным
(3) | Оба числа являются четными | (4) | Хотя бы одно из чисел является четным

6. Укажите, какое из приведенных значений переменной A целого типа не удовлетворяет данному условию:

not Odd(A) or (A div 8 + A mod 4 = 6)
(1) | A = 30 | (2) | A = 31
(3) | A = 32 | (4) | A = 33


Модуль 2. Целые числа и логические выражения

Итоговое задание

Используя датчик случайных чисел, сформировать целое положительное трехзначное число N и вывести все его цифры в порядке слева направо, сумму S и произведение P этих цифр.

Также вывести значения следующих четырех высказываний (как логические константы True или False).

Высказывание A1: «Количество сотен в числе N больше количества десятков и больше количества единиц».

Высказывание A2: «Количество единиц или количество сотен в числе N меньше количества десятков».

Высказывание A3: «Число N содержит хотя бы две одинаковые цифры».

Высказывание A4: «Цифры в числе N упорядочены либо по возрастанию, либо по убыванию».

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

N = 663

Digits: 6 6 3
S = 15
P = 108

A1: FALSE
A2: TRUE
A3: TRUE
A4: FALSE

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


Модуль 3. Условный оператор и оператор выбора

Комплексная цель

Изучение условного оператора if и оператора выбора case, а также вариантов их применения, в том числе вложенных условных операторов. Умение составлять простейшие разветвляющиеся алгоритмы, в том числе алгоритм нахождения минимального/максимального из двух и трех чисел, а также его номера, алгоритм проверки упорядоченности трех чисел, алгоритм вычисления функции, заданной различными формулами на различных участках своей области определения, и т. п.

Структура модуля

  • Решения типовых задач
  • Учебные задания и указания к ним
  • Контрольные вопросы
  • Итоговое задание


Модуль 3. Условный оператор и оператор выбора

Решения типовых задач

Условный оператор: If6, If8, If12, If26

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

if условие then
    оператор_1
[else
    оператор_2];

Оператор_1 выполняется, если условие является истинным. Раздел else является необязательным; при его наличии оператор_2 выполняется, если условие является ложным. Если в условном операторе требуется выполнить не один, а несколько операторов, то их надо превратить в один составной оператор, заключив требуемые операторы в операторные скобки begin–end.

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

Оператор if, содержащий раздел else, называется полным условным оператором (или условным оператором в полной форме), а оператор if без раздела else — сокращенным условным оператором (или условным оператором в краткой форме).

Использование полного условного оператора проиллюстрируем на примере решения двух простых заданий.

If6. Даны два числа. Вывести большее из них.

program If6;
uses PT4;
var
  A, B, Max: real;
begin
  Task('If6');
  GetR(A);
  GetR(B);
  if A > B then
    Max := A
  else
    Max := B;
  PutR(Max);
end.

Обратите внимание не отступы, которые были использованы при записи условного оператора: тот оператор, который располагается после слов then или else, набирается с дополнительным отступом (равным двум пробелам). Это позволяет легко определить, какие операторы входят в состав условного оператора.

If8. Даны два числа. Вывести вначале большее, а затем меньшее из них.

program If8;
uses PT4;
var
  A, B, Min, Max: real;
begin
  Task('If8');
  GetR(A);
  GetR(B);
  if A > B then
  begin
    Max := A;
    Min := B;
  end
  else
  begin
    Max := B;
    Min := A;
  end;
  PutR(Max);
  PutR(Min);
end.

Поскольку и в случае, когда условие A > B является истинным, и в случае, когда это условие является ложным, требуется выполнить два оператора присваивания, их необходимо «превратить» в один оператор, заключив в операторные скобки begin–end. Обратите внимание на то, что слова begin и end указываются на уровне слов if и else, а заключенные между ними операторы набираются с дополнительным отступом.

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

program If6;
uses PT4;
var
  A, B: real;
begin
  Task('If6');
  GetR(A);
  GetR(B);
  if A > B then
    PutR(A)
  else
    PutR(B);
end.

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

Рассмотрим еще две задачи на условный оператор.

If12. Даны три числа. Найти наименьшее из них.

program If12;
uses PT4;
var
  A, B, C, Min: real;
begin
  Task('If12');
  GetR(A);
  GetR(B);
  GetR(C);
  Min := A;
  if B < Min then
    Min := B;
  if C < Min then
    Min := C;
  PutR(Min);
end.

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

If26. Для данного вещественного x найти значение следующей функции f, принимающей вещественные значения:
f(x) = –x, если x £ 0; x2, если 0 < x < 2; 4, если x ³ 2.

При решении этой задачи возникают вложенные условные операторы:

program If26;
uses PT4;
var
  X, Y: real;
begin
  Task('If26');
  GetR(X);
  if X <= 0 then
    Y := -X
  else
    if X < 2 then
      Y := X * X
    else
      Y := 4;
  PutR(Y);
end.

Раздел else первого (внешнего) условного оператора содержит второй (внутренний) условный оператор. Поскольку перейти на внутренний условный оператор можно только в случае, когда значение X является положительным, для проверки того, что X лежит в интервале (0, 2), достаточно выполнить единственное сравнение: X < 2. Если и эта проверка возвращает False, значит, число X удовлетворяет условию X >= 2, и поэтому переменной Y следует присвоить значение 4.

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

C := 0;
if A < 2 then
  if B < 3 then
    C := 4
  else
    C := 5;

Если же раздел else в приведенном фрагменте следует связать в внешним условным оператором, то необходимо заключить внутренний оператор if в операторные скобки begin–end:

C := 0;
if A < 2 then
begin
  if B < 3 then
    C := 4;
end
else
  C := 5;

Ясно, что приведенные фрагменты будут выполняться по-разному. Так, если A = 4, а B = 5, то после выполнения первого фрагмента переменная C сохранит начальное значение, равное 0, а после выполнения второго — изменит свое значение на 5.

Оператор выбора: Case4, Case9

Оператор выбора позволяет выполнить одно действие из нескольких возможных в зависимости от значения некоторого выражения, называемого переключателем. Приведем вид оператора выбора для языка Паскаль:
case переключатель of
  знач_1: оператор_1;
  знач_2: оператор_2:
    . . .
  [else
    оператор_0]
end;

Если значение переключателя равно знач_1, то выполняется оператор_1, если значение равно знач_2 — выполняется оператор_2, и т. д. Если в операторе выбора указан вариант по умолчанию else, то он выполняется, если значение переключателя не равно ни одному из явно указанных значений. Следует заметить, что в операторе выбора перед ключевым словом else надо указывать точку с запятой.

В качестве переключателя следует использовать выражение целого или символьного типа, а в качестве его возможных значений — константы соответствующего типа. Как обычно, если для некоторого значения переключателя требуется выполнить несколько операторов, их необходимо превратить в один составной оператор, заключив в операторные скобки begin–end (исключением является раздел else, в котором можно указывать несколько операторов, не превращая их в составной оператор). Обратите внимание на то, что слово end также используется для обозначения конца оператора выбора, причем в данном случае парное к нему слово begin отсутствует (парным словом можно считать слово case, с которого начинается оператор выбора).

Допустимо объединять значения, соответствующие одной и той же группе операторов, в список значений, перечисляя их через запятую, например, 3, 5, 6. Кроме того, в списке значений можно указывать диапазоны, например, 4..10, 20..25.

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

Case4. Дан номер месяца — целое число в диапазоне 1–12 (1 — январь, 2 — февраль и т. д.). Определить количество дней в этом месяце для невисокосного года.

program Case4;
uses PT4;
var
  N, K: integer;
begin
  Task('Case4');
  GetN(N);
  case N of
    2: K := 28;
    4, 6, 9, 11: K := 30;
  else
    K := 31;
  end;
  PutN(K);
end.

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

Case9. Даны два целых числа: D (день) и M (месяц), определяющие правильную дату невисокосного года. Вывести значения D и M для даты, следующей за указанной.

program Case9;
uses PT4;
var
  D, M, K: integer;
begin
  Task('Case9');
  GetN(D);
  GetN(M);
  case M of
  2: K := 28;
  4, 6, 9, 11: K := 30;
  else
    K := 31;
  end;
  if D < K then
    Inc(D)
  else
  begin
    D := 1;
    Inc(M);
    if M = 13 then
      M := 1;
  end;
  PutN(D);
  PutN(M);
end.

Первая часть программы определяет число дней в месяце M, поэтому она почти дословно повторяет текст предыдущей программы.

Для увеличения значения переменных D и M на единицу в программе использовалась процедура Inc (другой способ увеличить значение переменной на 1 состоит в использовании оператора присваивания: K := K + 1). «Парной» к процедуре Inc является процедура Dec(K), уменьшающая на единицу значение своего параметра K. В качестве параметра этих процедур можно указывать только переменные, имеющие целый или символьный тип.


Модуль 3. Условный оператор и оператор выбора

Учебные задания и указания к ним

Условный оператор

If1. Дано целое число. Если оно является положительным, то прибавить к нему 1; в противном случае не изменять его. Вывести полученное число.

If2. Дано целое число. Если оно является положительным, то прибавить к нему 1; в противном случае вычесть из него 2. Вывести полученное число.

If3. Дано целое число. Если оно является положительным, то прибавить к нему 1; если отрицательным, то вычесть из него 2; если нулевым, то заменить его на 10. Вывести полученное число.

If4. Даны три целых числа. Найти количество положительных чисел в исходном наборе.

If5. Даны три целых числа. Найти количество положительных и количество отрицательных чисел в исходном наборе.

If6. Даны два числа. Вывести большее из них.

If7. Даны два числа. Вывести порядковый номер меньшего из них.

If8. Даны два числа. Вывести вначале большее, а затем меньшее из них.

If9. Даны две переменные вещественного типа: A, B. Перераспределить значения данных переменных так, чтобы в A оказалось меньшее из значений, а в B — большее. Вывести новые значения переменных A и B.

If10. Даны две переменные целого типа: A и B. Если их значения не равны, то присвоить каждой переменной сумму этих значений, а если равны, то присвоить переменным нулевые значения. Вывести новые значения переменных A и B.

If11. Даны две переменные целого типа: A и B. Если их значения не равны, то присвоить каждой переменной большее из этих значений, а если равны, то присвоить переменным нулевые значения. Вывести новые значения переменных A и B.

If12. Даны три числа. Найти наименьшее из них.

If13. Даны три числа. Найти среднее из них (то есть число, расположенное между наименьшим и наибольшим).

If14. Даны три числа. Вывести вначале наименьшее, а затем наибольшее из данных чисел.

If15. Даны три числа. Найти сумму двух наибольших из них.

If16. Даны три переменные вещественного типа: A, B, C. Если их значения упорядочены по возрастанию, то удвоить их; в противном случае заменить значение каждой переменной на противоположное. Вывести новые значения переменных A, B, C.

If17. Даны три переменные вещественного типа: A, B, C. Если их значения упорядочены по возрастанию или убыванию, то удвоить их; в противном случае заменить значение каждой переменной на противоположное. Вывести новые значения переменных A, B, C.

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

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

If20. На числовой оси расположены три точки: A, B, C. Определить, какая из двух последних точек (B или C) расположена ближе к A, и вывести эту точку и ее расстояние от точки A.

If21. Даны целочисленные координаты точки на плоскости. Если точка совпадает с началом координат, то вывести 0. Если точка не совпадает с началом координат, но лежит на оси OX или OY, то вывести соответственно 1 или 2. Если точка не лежит на координатных осях, то вывести 3.

If22. Даны координаты точки, не лежащей на координатных осях OX и OY. Определить номер координатной четверти, в которой находится данная точка.

If23. Даны целочисленные координаты трех вершин прямоугольника, стороны которого параллельны координатным осям. Найти координаты его четвертой вершины.

If24. Для данного вещественного x найти значение следующей функции f, принимающей вещественные значения:

f(x) | = | 2·sin(x), | если x > 0,
 |  | 6 – x, | если x £ 0.

If25. Для данного целого x найти значение следующей функции f, принимающей значения целого типа:

f(x) | = | 2·x, | если x < –2 или x > 2,
 |  | –3·x | в противном случае.

If26. Для данного вещественного x найти значение следующей функции f, принимающей вещественные значения:

 |  | –x, | если x £ 0,
f(x) | = | x2, | если 0 < x < 2,
 |  | 4, | если x ³ 2.

If27. Для данного вещественного x найти значение следующей функции f, принимающей значения целого типа:

 |  | 0, | если x < 0,
f(x) | = | 1, | если x принадлежит [0, 1), [2, 3), …,
 |  | –1, | если x принадлежит [1, 2), [3, 4), … .

If28. Дан номер года (положительное целое число). Определить количество дней в этом году, учитывая, что обычный год насчитывает 365 дней, а високосный — 366 дней. Високосным считается год, делящийся на 4, за исключением тех годов, которые делятся на 100 и не делятся на 400 (например, годы 300, 1300 и 1900 не являются високосными, а 1200 и 2000 — являются).

If29. Дано целое число. Вывести его строку-описание вида «отрицательное четное число», «нулевое число», «положительное нечетное число» и т. д.

If30. Дано целое число, лежащее в диапазоне 1–999. Вывести его строку-описание вида «четное двузначное число», «нечетное трехзначное число» и т. д.

Оператор выбора

Case1. Дано целое число в диапазоне 1–7. Вывести строку — название дня недели, соответствующее данному числу (1 — «понедельник», 2 — «вторник» и т. д.).

Case2. Дано целое число K. Вывести строку-описание оценки, соответствующей числу K (1 — «плохо», 2 — «неудовлетворительно», 3 — «удовлетворительно», 4 — «хорошо», 5 — «отлично»). Если K не лежит в диапазоне 1–5, то вывести строку «ошибка».

Case3. Дан номер месяца — целое число в диапазоне 1–12 (1 — январь, 2 — февраль и т. д.). Вывести название соответствующего времени года («зима», «весна», «лето», «осень»).

Case4. Дан номер месяца — целое число в диапазоне 1–12 (1 — январь, 2 — февраль и т. д.). Определить количество дней в этом месяце для невисокосного года.

Case5. Арифметические действия над числами пронумерованы следующим образом: 1 — сложение, 2 — вычитание, 3 — умножение, 4 — деление. Дан номер действия N (целое число в диапазоне 1–4) и вещественные числа A и B (B не равно 0). Выполнить над числами указанное действие и вывести результат.

Case6. Единицы длины пронумерованы следующим образом: 1 — дециметр, 2 — километр, 3 — метр, 4 — миллиметр, 5 — сантиметр. Дан номер единицы длины (целое число в диапазоне 1–5) и длина отрезка в этих единицах (вещественное число). Найти длину отрезка в метрах.

Case7. Единицы массы пронумерованы следующим образом: 1 — килограмм, 2 — миллиграмм, 3 — грамм, 4 — тонна, 5 — центнер. Дан номер единицы массы (целое число в диапазоне 1–5) и масса тела в этих единицах (вещественное число). Найти массу тела в килограммах.

Case8. Даны два целых числа: D (день) и M (месяц), определяющие правильную дату невисокосного года. Вывести значения D и M для даты, предшествующей указанной.

Case9. Даны два целых числа: D (день) и M (месяц), определяющие правильную дату невисокосного года. Вывести значения D и M для даты, следующей за указанной.

Case10. Робот может перемещаться в четырех направлениях («С» — север, «З» — запад, «Ю» — юг, «В» — восток) и принимать три цифровые команды: 0 — продолжать движение, 1 — поворот налево, –1 — поворот направо. Дан символ C — исходное направление робота и целое число N — посланная ему команда. Вывести направление робота после выполнения полученной команды.

Case11. Локатор ориентирован на одну из сторон света («С» — север, «З» — запад, «Ю» — юг, «В» — восток) и может принимать три цифровые команды поворота: 1 — поворот налево, –1 — поворот направо, 2 — поворот на 180°. Дан символ C — исходная ориентация локатора и целые числа N1 и N2 — две посланные команды. Вывести ориентацию локатора после выполнения этих команд.

Case12. Элементы окружности пронумерованы следующим образом: 1 — радиус R, 2 — диаметр D = 2·R, 3 — длина L = 2·p·R, 4 — площадь круга S = p·R2. Дан номер одного из этих элементов и его значение. Вывести значения остальных элементов данной окружности (в том же порядке). В качестве значения p использовать 3.14.

Case13. Элементы равнобедренного прямоугольного треугольника пронумерованы следующим образом: 1 — катет a, 2 — гипотенуза c = a·(2)1/2, 3 — высота h, опущенная на гипотенузу (h = c/2), 4 — площадь S = c·h/2. Дан номер одного из этих элементов и его значение. Вывести значения остальных элементов данного треугольника (в том же порядке).

Case14. Элементы равностороннего треугольника пронумерованы следующим образом: 1 — сторона a, 2 — радиус R1 вписанной окружности (R1 = a·(3)1/2/6), 3 — радиус R2 описанной окружности (R2 = 2·R1), 4 — площадь S = a2·(3)1/2/4. Дан номер одного из этих элементов и его значение. Вывести значения остальных элементов данного треугольника (в том же порядке).

Case15. Мастям игральных карт присвоены порядковые номера: 1 — пики, 2 — трефы, 3 — бубны, 4 — червы. Достоинству карт, старших десятки, присвоены номера: 11 — валет, 12 — дама, 13 — король, 14 — туз. Даны два целых числа: N — достоинство (6 £ N £ 14) и M — масть карты (1 £ M £ 4). Вывести название соответствующей карты вида «шестерка бубен», «дама червей», «туз треф» и т. п.

Case16. Дано целое число в диапазоне 20–69, определяющее возраст (в годах). Вывести строку-описание указанного возраста, обеспечив правильное согласование числа со словом «год», например: 20 — «двадцать лет», 32 — «тридцать два года», 41 — «сорок один год».

Case17. Дано целое число в диапазоне 10–40, определяющее количество учебных заданий по некоторой теме. Вывести строку-описание указанного количества заданий, обеспечив правильное согласование числа со словами «учебное задание», например: 18 — «восемнадцать учебных заданий», 23 — «двадцать три учебных задания», 31 — «тридцать одно учебное задание».

Case18. Дано целое число в диапазоне 100–999. Вывести строку-описание данного числа, например: 256 — «двести пятьдесят шесть», 814 — «восемьсот четырнадцать».

Case19. В восточном календаре принят 60-летний цикл, состоящий из 12-летних подциклов, обозначаемых названиями цвета: зеленый, красный, желтый, белый и черный. В каждом подцикле годы носят названия животных: крысы, коровы, тигра, зайца, дракона, змеи, лошади, овцы, обезьяны, курицы, собаки и свиньи. По номеру года определить его название, если 1984 год — начало цикла: «год зеленой крысы».

Case20. Даны два целых числа: D (день) и M (месяц), определяющие правильную дату. Вывести знак Зодиака, соответствующий этой дате: «Водолей» (20.1–18.2), «Рыбы» (19.2–20.3), «Овен» (21.3–19.4), «Телец» (20.4–20.5), «Близнецы» (21.5–21.6), «Рак» (22.6–22.7), «Лев» (23.7–22.8), «Дева» (23.8–22.9), «Весы» (23.9–22.10), «Скорпион» (23.10–22.11), «Стрелец» (23.11–21.12), «Козерог» (22.12–19.1).

Указания

В тексте указаний используется сокращенное обозначение для диапазона заданий, включающее имя темы, номер начального и номер конечного задания (например, диапазон заданий от If1 до If3 обозначается следующим образом: If1–3).

If1–3. Простейшие задания на применение условного оператора. В If1 используйте краткую форму условного оператора (без раздела else), в If2 — полную форму, в If3 — вложенные условные операторы (ср. с решением If26).

If4–5. Задача If4 решается с использованием одной переменной-счетчика, а задача If5 — с использованием двух.

If6–8. См. решение If6 и решение If8; задача If7 решается аналогично.

If9. См. решение Begin22.

If12–15. См. решение If12, аналогично находится наибольшее число в If14. Для нахождения среднего числа (If13) или двух наибольших чисел (If15) можно использовать либо сложные условия с логическими операциями, либо вложенные условные операторы.

If16–17. В If16 достаточно проверить, что исходные числа A, B, C удовлетворяют двойному неравенству A < B < C (см. указание к Boolean6), в If17 достаточно проверить, что B находится между A и С (см. решение Boolean7).

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

If20. По поводу нахождения расстояния между точками на числовой оси см. задание Begin16 и указание к нему.

If21–22. См. указание к If18–19.

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

If24–25. В решении достаточно использовать один полный условный оператор. В If25 можно обойтись без логической операции or, если воспользоваться функцией Abs(X), возвращающей модуль числа X.

If26. См. решение этой задачи.

If27. В случае неотрицательного x достаточно найти его целую часть и проанализировать ее четность. Для нахождения целой части неотрицательного числа используйте функцию Trunc; по поводу проверки четности см. решение Boolean2.

If28. В условии, отбирающем високосные годы, необходимо использовать операцию mod взятия остатка от деления (на 4, на 100 и на 400).

If29–30. В программе следует отдельно сформировать первую и вторую половины строки-описания, после чего объединить их операцией сцепления строк «+». Например, в If29 надо по отдельности проанализировать четность и знак данного числа (по поводу проверки четности см. решение Boolean2). Завершающая часть строки-описания не зависит от значения исходного числа, поэтому ее можно добавлять к результирующей строке после выхода из условного оператора. Между словами в строке-описании должно располагаться по одному пробелу.

Case2. Используйте оператор выбора с вариантом по умолчанию else.

Case3. В списках выбора оператора case удобно использовать диапазоны: 3..5 (весна), 6..8 (лето) и т. д.

Case4. См. решение этой задачи.

Case8–9. См. решение Case9. Задача Case8 решается аналогично; в ней также следует использовать вспомогательную переменную K, но уже для определения числа дней в предыдущем месяце (необходимость в этой переменной возникает при D = 1).

Case10–11. При выполнении этих заданий удобно перейти (используя оператор выбора) от символьных обозначений сторон света к числовым: 0 — север, 1 — запад, 2 — юг, 3 — восток. Теперь для получения нового направления достаточно прибавить значение команды (или обеих команд для Case11) к исходному значению стороны света и вернуться к символьному значению для найденной стороны света (еще раз используя оператор выбора). Необходимо также учитывать, что полученное число может лежать вне диапазона 0–3; например, результирующему северному направлению может соответствовать не только число 0, но и число 4, восточному направлению — не только 3, но и –1, и т. д.

Case15–19. Ср. с If29–30. Для выделения цифр из данного числа (в Case16–18) используйте операции целочисленного деления и взятия остатка — см. решения Integer8 и Integer11. Эти же операции надо использовать в Case19 для определения номера подцикла и порядкового номера года в пределах подцикла. Во всех этих заданиях надо использовать несколько операторов выбора; например, в Case16 требуются три оператора выбора: для определения названий десятков, единиц и заключительного слова (в зависимости от исходного числа это будет либо «год», либо «года», либо «лет»).


Модуль 3. Условный оператор и оператор выбора

Контрольные вопросы

Для каждого вопроса щелкните мышью на радиокнопке с номером варианта ответа, который, по вашему мнению, является правильным. После того как вы ответите на все вопросы, проверьте правильность ответов, нажав на кнопку «Проверка».

1. Даны три переменные целого типа: A = 1, B = 2, C = 3. Укажите, какое значение получит переменная C после выполнения следующего фрагмента программы:

if A < 2 then
  if B < 1 then
    C := C + 1
else C := C - 1;
(1) | C = 1 | (2) | C = 2
(3) | C = 3 | (4) | C = 4

2. Дан фрагмент программы (A и B — переменные целого типа):

A := 3;
B := 2;
if A / B - 2 > -1 then
  A := B + 2;
  B := A + 1
else
  B := A + 1;
  A := B + 2;
Write(A, ' ', B);

Укажите, что произойдет при обработке этого фрагмента.

(1) | Возникнет ошибка компиляции | (2) | Возникнет ошибка времени выполнения
(3) | Будут напечатаны числа 4 и 5 | (4) | Будут напечатаны числа 6 и 4

3. Дано начало фразы:

Ключевое слово else …

Какой вариант продолжения этой фразы соответствует неверному утверждению?

(1) | … может входить в условный оператор | (2) | … может входить в оператор выбора
(3) | … всегда входит в полный условный оператор | (4) | … всегда входит в сокращенный условный оператор

4. Дано начало фразы:

Перед двоеточием в операторе выбора можно указывать …

Какой вариант продолжения этой фразы соответствует верному утверждению?

(1) | … список целочисленных переменных | (2) | … список строковых переменных
(3) | … список целочисленных констант | (4) | … список строковых констант

5. Дан следующий фрагмент программы (A — переменная типа real):

case A of
2: A := A + 2;
end;

Выберите правильное утверждение.

(1) | Данный фрагмент не содержит синтаксических ошибок | (2) | Данный фрагмент является ошибочным, так как переключатель в операторе выбора не может иметь тип real
(3) | Данный фрагмент является ошибочным, так как оператор выбора должен содержать не менее двух вариантов значений переключателя | (4) | Данный фрагмент является ошибочным, так как в операторе выбора нельзя изменять значение переменной, указанной в качестве переключателя

6. Дан следующий фрагмент программы (A и B — переменные типа integer):

A := 10;
B := 20;
case A of
0: B := B - 5;
5: if B > 50 then
     B := 2 * B;
   else B := 3 * B;
end;
Write(B);

Укажите, что произойдет при обработке этого фрагмента.

(1) | Возникнет ошибка компиляции | (2) | Будет напечатано число 15
(3) | Будет напечатано число 20 | (4) | Будет напечатано число 60


Модуль 3. Условный оператор и оператор выбора

Итоговое задание

Используя датчик случайных чисел, сформировать целочисленные координаты двух точек на плоскости: A(x1, y1) и B(x2, y2). Модуль каждой координаты должен лежать в диапазоне от 5 до 500, знак определяется случайным образом.

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

Дополнительно проверить, пересекает ли отрезок AB оси координат: если он пересекает обе оси, то вывести текст «AB intersects Ox and Oy», если он пересекает только одну из осей (Ox или Oy), то вывести соответственно «AB intersects Ox» или «AB intersects Oy». Если отрезок не пересекает оси координат, то вывести текст «No intersections».

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

A = (-479, -363)
B = ( 307,   81)

A: 3 quarter
B: 1 quarter

1-digit numbers: 0
2-digit numbers: 1
3-digit numbers: 3

AB intersects Ox and Oy

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


Модуль 4. Операторы цикла

Комплексная цель

Изучение различных вариантов операторов цикла в Паскале: цикл с параметром for, циклы с условием while и repeat; ознакомление с особенностями каждого варианта. Освоение базовых итерационных алгоритмов, в том числе алгоритмов нахождения суммы и произведения, умение применять переменные-счетчики и проводить вычисления по рекуррентным формулам. Умение использовать вложенные циклы.

Структура модуля

  • Решения типовых задач
  • Учебные задания и указания к ним
  • Контрольные вопросы
  • Итоговое задание


Модуль 4. Операторы цикла

Решения типовых задач

Цикл с параметром: For5, For12, For13, For16, For20, For33, For36

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

for парам := знач_1 to знач_2 do
  оператор_1

Здесь парам обозначает переменную — параметр цикла. Обычно параметр цикла является переменной целого типа; допускаются также переменные символьного типа, хотя используются они достаточно редко. Знач_1 и знач_2 определяют соответственно начальное и конечное значение параметра цикла, шаг изменения параметра считается равным 1. Для перебора значений параметра цикла по убыванию можно использовать другой вариант оператора цикла с параметром, в котором вместо ключевого слова to используется слово downto:

for парам := знач_1 downto знач_2 do
  оператор_1

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

Следует заметить, что конечное значение параметра цикла вычисляется один раз (в начале выполнения цикла), и затем это вычисленное значение на каждой итерации сравнивается с параметром цикла.

Тело цикла (оператор_1) выполняется для каждого значения параметра цикла. Если начальное значение параметра больше конечного, а шаг изменения параметра равен 1 (а также если начальное значение меньше конечного, а шаг равен –1), то тело цикла ни разу не выполняется. Если в цикле необходимо выполнить несколько операторов, то их надо превратить в один составной оператор, заключив в операторные скобки begin–end.

В большинстве современных реализаций Паскаля, в том числе во всех программных средах, рассматриваемых в настоящем пособии (Borland Delphi, Free Pascal Lazarus, PascalABC.NET), изменение параметра цикла в теле цикла запрещено, поскольку подобное изменение параметра цикла, как правило, делает алгоритм сложным для восприятия и может приводить к появлению трудно выявляемых ошибок. После выхода из цикла к параметру данного цикла обращаться не следует, так как его значение в этой ситуации считается неопределенным.

В современных реализациях Паскаля имеется возможность досрочного выхода из цикла; для этого надо использовать оператор break. Кроме того, можно досрочно прервать текущую итерацию цикла; для этого следует использовать оператор continue. Примеры использования этих операторов приводятся в модуле 6 (см. решение задания Series15).

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

For5. Дано вещественное число — цена 1 кг конфет. Вывести стоимость 0.1, 0.2, …, 1 кг конфет.

Так как в цикле for нельзя использовать вещественный параметр с шагом, равным 0.1, нам придется вычислять требуемое вещественное значение по целочисленному параметру цикла:

program For5;
uses PT4;
var
  A: real;
  I: integer;
begin
  Task('For5');
  GetR(A);
  for i := 1 to 10 do
    PutR(0.1 * I * A);
end.

For12. Дано целое число N (> 0). Найти произведение 1.1 · 1.2 · 1.3 · … (N сомножителей).

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

program For12;
uses PT4;
var
  A: real;
  N, I: integer;
begin
  Task('For12');
  A := 1;
  GetN(N);
  for I := 1 to N do
    A := A * (1 + 0.1 * I);
  PutR(A);
end.

Так как в переменной A будет вычисляться произведение чисел, данная переменная инициализируется значением 1.

Аналогично решается и задание For13.

For13. Дано целое число N (> 0). Найти значение выражения 1.1 – 1.2 + 1.3 – … (N слагаемых, знаки чередуются). Условный оператор не использовать.

program For13;
uses PT4;
var
  A: real;
  N, I, K: integer;
begin
  Task('For13');
  A := 0;
  K := 1;
  GetN(N);
  for I := 1 to N do
  begin
    A := A + K * (1 + 0.1 * I);
    K := -K;
  end;
  PutR(A);
end.

Смену знака у слагаемых обеспечивает вспомогательный множитель K, принимающий попеременно значения 1 и –1. Поскольку тело цикла состоит из двух операторов, приходится заключать их в операторные скобки begin–end.

В программе вычисляется сумма чисел, поэтому переменная A инициализируется значением 0.

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

For16. Дано вещественное число A и целое число N (> 0). Используя один цикл, вывести все целые степени числа A от 1 до N.

program For16;
uses PT4;
var
  A, P: real;
  N, I: integer;
begin
  Task('For16');
  GetR(A);
  GetN(N);
  P := 1;
  for I := 1 to N do
  begin
    P := P * A;
    PutR(P);
  end;
end.

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

For20. Дано целое число N (> 0). Используя один цикл, найти сумму 1! + 2! + 3! + … + N! (выражение N! — N-факториал — обозначает произведение всех целых чисел от 1 до N: N! = 1·2·…·N). Чтобы избежать целочисленного переполнения, проводить вычисления с помощью вещественных переменных и вывести результат как вещественное число.

program For20;
uses PT4;
var
  S, P: real;
  N, I: integer;
begin
  Task('For20');
  GetN(N);
  S := 0;
  P := 1;
  for I := 1 to N do
  begin
    P := P * I;
    S := S + P;
  end;
  PutR(S);
end.

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

For33. Дано целое число N (> 1). Последовательность чисел Фибоначчи FK (целого типа) определяется следующим образом: F1 = 1, F2 = 1, FK = FK–2 + FK–1, K = 3, 4, :… . Вывести элементы F1, F2, …, FN.

program For33;
uses PT4;
var
  N, I, A, B, C: integer;
begin
  Task('For33');
  GetN(N);
  A := 1;
  B := 1;
  PutN(A);
  PutN(B);
  for I := 3 to N do
  begin
    C := A + B;
    PutN(C);
    A := B;
    B := C;
  end;
end.

При выполнении этого задания приходится использовать две вспомогательные переменные A и B, в которых хранятся два предыдущих элемента последовательности Фибоначчи. С их помощью вычисляется очередной элемент C, после чего происходит корректировка значений вспомогательных переменных (в переменную A записывается значение переменной B, а затем в переменную B записывается значение переменной C). Также обратите внимание на то, что начальное значение переменной цикла равно 3 (поскольку первые два числа Фибоначчи обработаны и выведены до цикла).

Следующее задание демонстрирует использование вложенных циклов.

For36. Даны целые положительные числа N и K. Найти сумму 1K + 2K + … + NK. Чтобы избежать целочисленного переполнения, вычислять слагаемые этой суммы с помощью вещественной переменной и выводить результат как вещественное число.

program For36;
uses PT4;
var
  N, K, I, J: integer;
  S, P: real;
begin
  Task('For36');
  GetN(N);
  GetN(K);
  S := 0;
  for I := 1 to N do
  begin
    P := 1;
    for J := 1 to K do
      P := P * I;
    S := S + P;
  end;
  PutR(S);
end.

Во внутреннем цикле (по параметру J) вычисляется K-я степень числа I, которая затем добавляется к сумме S. При этом переменная P, используемая при вычислении K-й степени, должна инициализироваться числом 1 на каждой итерации внешнего цикла. Обратите внимание на то, что переменная внутреннего цикла (в нашем случае J) обязательно должна отличаться от переменной внешнего цикла (в нашем случае I).

Цикл с условием: While1, While4, While11, While22

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

while условие do
  оператор_1

Цикл работает, выполняя на каждой итерации оператор_1, указанный в теле цикла, пока условие остается истинным. Заметим, что если уже при первой проверке условие окажется ложным, то не выполнится ни одной итерации цикла.

Цикл с последующим условием на языке Паскаль имеет вид
repeat
  операторы
until условие;

Данный цикл работает до тех пор, пока условие остается ложным, причем первая проверка условия выполняется уже после выполнения операторов, входящих в тело цикла, поэтому при использовании данного варианта цикла обязательно выполняется хотя бы одна его итерация (в этом состоит основное отличие цикла с последующим условием от цикла с предварительным условием). Еще одним отличием цикла repeat от цикла while состоит в том, что при указании в теле цикла repeat нескольких операторов можно не заключать их в операторные скобки begin–end (в цикле while использование операторных скобок begin–end в подобной ситуации является обязательным). Наконец, следует еще раз подчеркнуть, что условия в цикле while и в цикле repeat имеют противоположный смысл: в цикле while истинность условия означает, что цикл следует продолжать, а в цикле repeat истинность условия означает, что цикл следует прервать.

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

Приведем решения нескольких заданий группы While, посвященной циклу с условием.

While1. Даны положительные числа A и B (A > B). На отрезке длины A размещено максимально возможное количество отрезков длины B (без наложений). Не используя операции умножения и деления, найти длину незанятой части отрезка A.

program While1;
uses PT4;
var
  A, B: real;
begin
  Task('While1');
  GetR(A);
  GetR(B);
  while A > B do
    A := A - B;
  PutR(A);
end.

Приведенный алгоритм фактически является алгоритмом нахождения остатка при делении вещественного числа A на вещественное число B. Отметим, что операция mod нахождения остатка от деления в данном случае неприменима, так как ее операндами могут быть только целые числа.

While4. Дано целое число N (> 0). Если оно является степенью числа 3, то вывести True, если не является — вывести False.

program While4;
uses PT4;
var
  N, P: integer;
begin
  Task('While4');
  GetN(N);
  P := 1;
  while P < N do
    P := P * 3;
  PutB(N = P);
end.

В цикле while последовательно вычисляются степени числа 3 до тех пор, пока найденная степень P не станет большей или равной числу N. После этого в случае равенства этих переменных выводится True, а в случае неравенства — False. Обратите внимание на то, что в данной ситуации нет необходимости использовать условный оператор вида

if N = P then
  PutB(True)
else
  PutB(False);

Вместо такого условного оператора достаточно указать единственный оператор вывода, параметр которого является логическим выражением, совпадающим с условием оператора if:

  PutB(N = P);

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

program While4a;
uses PT4;
var
  N: integer;
begin
  Task('While4');
  GetN(N);
  while N mod 3 = 0 do
    N := N div 3;
  PutB(N = 1);
end.

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

While11. Дано целое число N (> 1). Вывести наименьшее из целых чисел K, для которых сумма 1 + 2 + … + K будет больше или равна N, и саму эту сумму.

program While11;
uses PT4;
var
  N, K, S: integer;
begin
  Task('While11');
  GetN(N);
  K := 0;
  S := 0;
  while S < N do
  begin
    Inc(K);
    S := S + K;
  end;
  PutN(K);
  PutN(S);
end.

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

While22. Дано целое число N (> 1). Если оно является простым, то есть не имеет положительных делителей, кроме 1 и самого себя, то вывести True, иначе вывести False.

program While22;
uses PT4;
var
  N, K: integer;
begin
  Task('While22');
  GetN(N);
  K := N - 1;
  while N mod K <> 0 do
    Dec(K);
  PutB(K = 1);
end.

В цикле последовательно перебираются по убыванию все числа, меньшие N, пока не будет обнаружен делитель числа N, то есть такое число K, на которое число N делится без остатка. Если число N составное, то этот делитель K будет больше 1, если простое, то он будет равен 1. Количество итераций можно уменьшить, если заметить, что числа от N div 2 + 1 до N – 1 не могут быть делителями N, и с учетом этого инициализировать переменную K значением N div 2.

На самом деле достаточно анализировать числа от Sqrt(N) до 1 (Sqrt(N) — функция, возвращающая квадратный корень из N), поскольку легко доказать, что если у числа N найдется делитель, больший Sqrt(N), то у него обязательно будет и делитель, меньший этой величины. Правда, инициализировать целочисленную переменную K значением Sqrt(N) нельзя, так как функция Sqrt возвращает вещественное число. Поэтому следует дополнительно округлить возвращаемое значение до целого, используя функцию округления Round: K := Round(Sqrt(N)).

Дополнительного уменьшения числа итераций можно добиться, если не анализировать четные значения K (за исключением K = 2).


Модуль 4. Операторы цикла

Учебные задания и указания к ним

Цикл с параметром

For1. Даны целые числа K и N (N > 0). Вывести N раз число K.

For2. Даны два целых числа A и B (A < B). Вывести в порядке возрастания все целые числа, расположенные между A и B (включая сами числа A и B), а также количество N этих чисел.

For3. Даны два целых числа A и B (A < B). Вывести в порядке убывания все целые числа, расположенные между A и B (не включая числа A и B), а также количество N этих чисел.

For4. Дано вещественное число — цена 1 кг конфет. Вывести стоимость 1, 2, …, 10 кг конфет.

For5. Дано вещественное число — цена 1 кг конфет. Вывести стоимость 0.1, 0.2, …, 1 кг конфет.

For6. Дано вещественное число — цена 1 кг конфет. Вывести стоимость 1.2, 1.4, …, 2 кг конфет.

For7. Даны два целых числа A и B (A < B). Найти сумму всех целых чисел от A до B включительно.

For8. Даны два целых числа A и B (A < B). Найти произведение всех целых чисел от A до B включительно.

For9. Даны два целых числа A и B (A < B). Найти сумму квадратов всех целых чисел от A до B включительно.

For10. Дано целое число N (> 0). Найти сумму

1 + 1/2 + 1/3 + … + 1/N

(вещественное число).

For11. Дано целое число N (> 0). Найти сумму

N2 + (N + 1)2 + (N + 2)2 + … + (2·N)2

(целое число).

For12. Дано целое число N (> 0). Найти произведение

1.1 · 1.2 · 1.3 · …

(N сомножителей).

For13. Дано целое число N (> 0). Найти значение выражения

1.1 – 1.2 + 1.3 – …

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

For14. Дано целое число N (> 0). Найти квадрат данного числа, используя для его вычисления следующую формулу:

N2 = 1 + 3 + 5 + … + (2·N – 1).

После добавления к сумме каждого слагаемого выводить текущее значение суммы (в результате будут выведены квадраты всех целых чисел от 1 до N).

For15. Дано вещественное число A и целое число N (> 0). Найти A в степени N:

AN = A·A· … ·A

(числа A перемножаются N раз).

For16. Дано вещественное число A и целое число N (> 0). Используя один цикл, вывести все целые степени числа A от 1 до N.

For17. Дано вещественное число A и целое число N (> 0). Используя один цикл, найти сумму

1 + A + A2 + A3 + … + AN.

For18. Дано вещественное число A и целое число N (> 0). Используя один цикл, найти значение выражения

1 – A + A2 – A3 + … + (–1)N·AN.

Условный оператор не использовать.

For19. Дано целое число N (> 0). Найти произведение

N! = 1·2·…·N

(N–факториал). Чтобы избежать целочисленного переполнения, вычислять это произведение с помощью вещественной переменной и вывести его как вещественное число.

For20. Дано целое число N (> 0). Используя один цикл, найти сумму

1! + 2! + 3! + … + N!

(выражение N! — N–факториал — обозначает произведение всех целых чисел от 1 до N: N! = 1·2·…·N). Чтобы избежать целочисленного переполнения, проводить вычисления с помощью вещественных переменных и вывести результат как вещественное число.

For21. Дано целое число N (> 0). Используя один цикл, найти сумму

1 + 1/(1!) + 1/(2!) + 1/(3!) + … + 1/(N!)

(выражение N! — N–факториал — обозначает произведение всех целых чисел от 1 до N: N! = 1·2·…·N). Полученное число является приближенным значением константы e = exp(1).

For22. Дано вещественное число X и целое число N (> 0). Найти значение выражения

1 + X + X2/(2!) + … + XN/(N!)

(N! = 1·2·…·N). Полученное число является приближенным значением функции exp в точке X.

For23. Дано вещественное число X и целое число N (> 0). Найти значение выражения

X – X3/(3!) + X5/(5!) – … + (–1)N·X2·N+1/((2·N+1)!)

(N! = 1·2·…·N). Полученное число является приближенным значением функции sin в точке X.

For24. Дано вещественное число X и целое число N (> 0). Найти значение выражения

1 – X2/(2!) + X4/(4!) – … + (–1)N·X2·N/((2·N)!)

(N! = 1·2·…·N). Полученное число является приближенным значением функции cos в точке X.

For25. Дано вещественное число X (|X| < 1) и целое число N (> 0). Найти значение выражения

X – X2/2 + X3/3 – … + (–1)N–1·XN/N.

Полученное число является приближенным значением функции ln в точке 1 + X.

For26. Дано вещественное число X (|X| < 1) и целое число N (> 0). Найти значение выражения

X – X3/3 + X5/5 – … + (–1)N·X2·N+1/(2·N+1).

Полученное число является приближенным значением функции arctg в точке X.

For27. Дано вещественное число X (|X| < 1) и целое число N (> 0). Найти значение выражения

X + 1·X3/(2·3) + 1·3·X5/(2·4·5) + … +
+ 1·3·…·(2·N–1)·X2·N+1/(2·4·…·(2·N)·(2·N+1)).

Полученное число является приближенным значением функции arcsin в точке X.

For28. Дано вещественное число X (|X| < 1) и целое число N (> 0). Найти значение выражения

1 + X/2 – 1·X2/(2·4) + 1·3·X3/(2·4·6) – … +
+ (–1)N–1·1·3·…·(2·N–3)·XN/(2·4·…·(2·N)).

Полученное число является приближенным значением функции (1+X)1/2.

For29. Дано целое число N (> 1) и две вещественные точки на числовой оси: A, B (A < B). Отрезок [A, B] разбит на N равных отрезков. Вывести H — длину каждого отрезка, а также набор точек

A, A + H, A + 2·H, A + 3·H, …, B,

образующий разбиение отрезка [A, B].

For30. Дано целое число N (> 1) и две вещественные точки на числовой оси: A, B (A < B). Отрезок [A, B] разбит на N равных отрезков. Вывести H — длину каждого отрезка, а также значения функции F(X) = 1 – sin(X) в точках, разбивающих отрезок [A, B]:

F(A), F(A + H), F(A + 2·H), …, F(B).

For31. Дано целое число N (> 0). Последовательность вещественных чисел AK определяется следующим образом:

A0 = 2, AK = 2 + 1/AK–1, K = 1, 2, … .

Вывести элементы A1, A2, …, AN.

For32. Дано целое число N (> 0). Последовательность вещественных чисел AK определяется следующим образом:

A0 = 1, AK = (AK–1 + 1)/K, K = 1, 2, … .

Вывести элементы A1, A2, …, AN.

For33. Дано целое число N (> 1). Последовательность чисел Фибоначчи FK (целого типа) определяется следующим образом:

F1 = 1, F2 = 1, FK = FK–2 + FK–1, K = 3, 4, … .

Вывести элементы F1, F2, …, FN.

For34. Дано целое число N (> 1). Последовательность вещественных чисел AK определяется следующим образом:

A1 = 1, A2 = 2, AK = (AK–2 + 2·AK–1)/3, K = 3, 4, … .

Вывести элементы A1, A2, …, AN.

For35. Дано целое число N (> 2). Последовательность целых чисел AK определяется следующим образом:

A1 = 1, A2 = 2, A3 = 3, AK = AK–1 + AK–2 – 2·AK–3, K = 4, 5, … .

Вывести элементы A1, A2, …, AN.

Вложенные циклы

For36. Даны целые положительные числа N и K. Найти сумму

1K + 2K + … + NK.

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

For37. Дано целое число N (> 0). Найти сумму

11 + 22 + … + NN.

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

For38. Дано целое число N (> 0). Найти сумму

1N + 2N–1 + … + N1.

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

For39. Даны целые положительные числа A и B (A < B). Вывести все целые числа от A до B включительно; при этом каждое число должно выводиться столько раз, каково его значение (например, число 3 выводится 3 раза).

For40. Даны целые числа A и B (A < B). Вывести все целые числа от A до B включительно; при этом число A должно выводиться 1 раз, число A + 1 должно выводиться 2 раза и т. д.

Цикл с условием

While1. Даны положительные числа A и B (A > B). На отрезке длины A размещено максимально возможное количество отрезков длины B (без наложений). Не используя операции умножения и деления, найти длину незанятой части отрезка A.

While2. Даны положительные числа A и B (A > B). На отрезке длины A размещено максимально возможное количество отрезков длины B (без наложений). Не используя операции умножения и деления, найти количество отрезков B, размещенных на отрезке A.

While3. Даны целые положительные числа N и K. Используя только операции сложения и вычитания, найти частное от деления нацело N на K, а также остаток от этого деления.

While4. Дано целое число N (> 0). Если оно является степенью числа 3, то вывести True, если не является — вывести False.

While5. Дано целое число N (> 0), являющееся некоторой степенью числа 2: N = 2K. Найти целое число K — показатель этой степени.

While6. Дано целое число N (> 0). Найти двойной факториал N:

N!! = N·(N–2)·(N–4)·…

(последний сомножитель равен 2, если N — четное, и 1, если N — нечетное). Чтобы избежать целочисленного переполнения, вычислять это произведение с помощью вещественной переменной и вывести его как вещественное число.

While7. Дано целое число N (> 0). Найти наименьшее целое положительное число K, квадрат которого превосходит N: K2 > N. Функцию извлечения квадратного корня не использовать.

While8. Дано целое число N (> 0). Найти наибольшее целое число K, квадрат которого не превосходит N: K2 £ N. Функцию извлечения квадратного корня не использовать.

While9. Дано целое число N (> 1). Найти наименьшее целое число K, при котором выполняется неравенство 3K > N.

While10. Дано целое число N (> 1). Найти наибольшее целое число K, при котором выполняется неравенство 3K < N.

While11. Дано целое число N (> 1). Вывести наименьшее из целых чисел K, для которых сумма 1 + 2 + … + K будет больше или равна N, и саму эту сумму.

While12. Дано целое число N (> 1). Вывести наибольшее из целых чисел K, для которых сумма 1 + 2 + … + K будет меньше или равна N, и саму эту сумму.

While13. Дано число A (> 1). Вывести наименьшее из целых чисел K, для которых сумма 1 + 1/2 + … + 1/K будет больше A, и саму эту сумму.

While14. Дано число A (> 1). Вывести наибольшее из целых чисел K, для которых сумма 1 + 1/2 + … + 1/K будет меньше A, и саму эту сумму.

While15. Начальный вклад в банке равен 1000 руб. В конце каждого месяца размер вклада увеличивается на P процентов от имеющейся суммы (P — вещественное число, 0 < P < 25). По данному P определить, через сколько месяцев размер вклада превысит 1100 руб., и вывести найденное количество месяцев K (целое число) и итоговый размер вклада S (вещественное число).

While16. Спортсмен-лыжник начал тренировки, пробежав в первый день 10 км. Каждый следующий день он увеличивал длину пробега на P процентов от пробега предыдущего дня (P — вещественное, 0 < P < 50). По данному P определить, после какого дня суммарный пробег лыжника за все дни превысит 200 км, и вывести найденное количество дней K (целое) и суммарный пробег S (вещественное число).

While17. Дано целое число N (> 0). Используя операции деления нацело и взятия остатка от деления, вывести все его цифры, начиная с самой правой (разряда единиц).

While18. Дано целое число N (> 0). Используя операции деления нацело и взятия остатка от деления, найти количество и сумму его цифр.

While19. Дано целое число N (> 0). Используя операции деления нацело и взятия остатка от деления, найти число, полученное при прочтении числа N справа налево.

While20. Дано целое число N (> 0). С помощью операций деления нацело и взятия остатка от деления определить, имеется ли в записи числа N цифра «2». Если имеется, то вывести True, если нет — вывести False.

While21. Дано целое число N (> 0). С помощью операций деления нацело и взятия остатка от деления определить, имеются ли в записи числа N нечетные цифры. Если имеются, то вывести True, если нет — вывести False.

While22. Дано целое число N (> 1). Если оно является простым, то есть не имеет положительных делителей, кроме 1 и самого себя, то вывести True, иначе вывести False.

While23. Даны целые положительные числа A и B. Найти их наибольший общий делитель (НОД), используя алгоритм Евклида:

НОД(A, B) = НОД(B, A mod B), если B № 0; НОД(A, 0) = A,

где «mod» обозначает операцию взятия остатка от деления.

While24. Дано целое число N (> 1). Последовательность чисел Фибоначчи FK определяется следующим образом:

F1 = 1, F2 = 1, FK = FK–2 + FK–1, K = 3, 4, … .

Проверить, является ли число N числом Фибоначчи. Если является, то вывести True, если нет — вывести False.

While25. Дано целое число N (> 1). Найти первое число Фибоначчи, большее N (определение чисел Фибоначчи дано в задании While24).

While26. Дано целое число N (> 1), являющееся числом Фибоначчи: N = FK (определение чисел Фибоначчи дано в задании While24). Найти целые числа FK–1 и FK+1 — предыдущее и последующее числа Фибоначчи.

While27. Дано целое число N (> 1), являющееся числом Фибоначчи: N = FK (определение чисел Фибоначчи дано в задании While24). Найти целое число K — порядковый номер числа Фибоначчи N.

While28. Дано вещественное число e (> 0). Последовательность вещественных чисел AK определяется следующим образом:

A1 = 2, AK = 2 + 1/AK–1, K = 2, 3, … .

Найти первый из номеров K, для которых выполняется условие |AK – AK–1| < e, и вывести этот номер, а также числа AK–1 и AK.

While29. Дано вещественное число e (> 0). Последовательность вещественных чисел AK определяется следующим образом:

A1 = 1, A2 = 2, AK = (AK–2 + 2·AK–1)/3, K = 3, 4, … .

Найти первый из номеров K, для которых выполняется условие |AK – AK–1| < e, и вывести этот номер, а также числа AK–1 и AK.

While30. Даны положительные числа A, B, C. На прямоугольнике размера A ´ B размещено максимально возможное количество квадратов со стороной C (без наложений). Найти количество квадратов, размещенных на прямоугольнике. Операции умножения и деления не использовать.

Указания

В тексте указаний используется сокращенное обозначение для диапазона заданий, включающее имя темы, номер начального и номер конечного задания (например, диапазон заданий от For2 до For3 обозначается следующим образом: For2–3).

For2–3. Для нахождения количества чисел, выведенных в цикле, можно использовать либо явную формулу, либо вспомогательную переменную-счетчик, которая увеличивается на 1 на каждой итерации цикла. В For3 для перебора чисел по убыванию проще всего использовать цикл с шагом, равным –1.

For4–6. В For4 достаточно умножать цену 1 килограмма на текущее значение целочисленного параметра цикла, меняющегося от 1 до 10 с шагом 1. См. решение For5; задача For6 решается аналогично; для нее, как и для For5, множитель является вещественным числом, поэтому его необходимо вычислять на каждой итерации цикла.

For7–11. Простейшие задания на применение стандартных алгоритмов нахождения суммы и произведения. В For7–8 в качестве очередного обрабатываемого числа (слагаемого или сомножителя) достаточно брать параметр цикла, изменяя его от A до B с шагом 1. В For9–11 очередное слагаемое необходимо вычислять, используя текущее значение параметра цикла; при этом начальное и конечное значение параметра цикла удобно выбирать следующим образом: от A до B в For9, от 1 до N в For10, от N до 2·N в For11 (шаг всюду равен 1).

For12–13. См. решения For12 и For13.

For14. Для перебора в цикле всех нечетных чисел используйте явную формулу 2*I-1 (I меняется от 1 до N). В этом задании, как и в заданиях For1–6, вывод результатов осуществляется в самом цикле.

For15–18. См. решение For16; если в этом решении выводить P не в цикле, а после цикла, то получим решение задачи For15. Задачи For17–18 решаются аналогично; в них совместно используются алгоритмы нахождения суммы и произведения (ср. с решением For20). По поводу чередования знаков в For18 см. решение For13 (однако в данном случае нет необходимости в использовании особой переменной, отвечающей за знак элемента выражения: достаточно умножать ранее найденное слагаемое на число –A).

For19–21. См. решение For20; задачи For19 и For21 решаются аналогично.

For22–28. В этих заданиях при вычислении очередного слагаемого AK не следует заново пересчитывать степенную функцию и факториал (ср. с For17 и For21). Воспользуйтесь рекуррентным соотношением AK = CK·AK–1, подобрав подходящим образом множитель CK. Например, для For22 множитель CK равен X/K. В случае знакопеременных выражений (For23–26 и For28) множитель CK будет отрицательным (ср. с For18).

For31–35. Задания на вычисление элементов последовательности, определенной рекуррентным соотношением. В For31–32 очередной элемент последовательности определяется по единственному предыдущему элементу, поэтому в этих заданиях для последовательного нахождения элементов достаточно использовать одну переменную. В For33–34 для вычисления очередного элемента необходимо учитывать значения двух предыдущих элементов, поэтому приходится использовать три переменные (см. решение For33; задача For34 решается аналогично). В For35 надо использовать четыре переменные.

For36–38. См. решение For36. Задачи For37–38 решаются аналогично, с учетом того, что в данном случае число итераций внутреннего цикла зависит от номера итерации внешнего цикла (например, в For37 параметр J внутреннего цикла следует менять от 1 до I, где I — параметр внешнего цикла).

For39–40. Внутренний цикл в этих заданиях используйте для вывода очередного числа (требуемое количество раз), а внешний — для перебора выводимых чисел. В обоих заданиях число итераций внутреннего цикла зависит от номера итерации внешнего цикла (ср. с For37–38).

While1–2. См. решение While1. Задача While2 решается аналогично, с дополнительным подсчетом количества итераций цикла.

While3. Ср. с While1–2.

While4–5. См. решение While4. Для решения While5 достаточно модифицировать первый вариант решения While4, заменив множитель 3 на 2 и добавив подсчет числа итераций цикла.

While6. Каждый следующий сомножитель в формуле двойного факториала меньше предыдущего на 2. Поэтому заведем переменную I, до цикла инициализируем ее значением N, а в цикле будем накапливать произведение (умножая его на I) и уменьшать I на 2 (используя оператор I := I – 2), пока выполняется неравенство I > 1.

While7–8. Для решения While7 следует завести счетчик K (инициализировав его нулем) и увеличивать его в цикле, пока выполняется неравенство K2 £ N. Для решения While8 достаточно использовать алгоритм решения While7 и уменьшить полученное значение счетчика K на 1.

While9–14. Ср. While9–10 с While7–8. См. решение While11; задачи While12–14 решаются аналогично.

While17–19. Последовательно выделяйте, обрабатывайте и удаляйте цифры из исходного числа N, пока выполняется условие N > 0. Для выделения и последующего удаления цифр используйте операции целочисленного деления и взятия остатка — см. решения Integer8 и Integer11. В While19 для добавления очередной правой цифры к формируемому числу достаточно умножить прежнее значение числа на 10 и прибавить к нему эту цифру.

While20–21. В этих заданиях, в отличие от While17–19, цикл надо продолжать, пока выполняются два условия: основное условие N > 0 и дополнительное условие, указанное в задании («очередная цифра D не равна 2» для While20 или «очередная цифра D является четной» для While21). Таким образом, в условии цикла необходимо использовать логическую операцию and. Поскольку выделение цифр выполняется в самом цикле, удобно использовать цикл с последующим условием repeat–until. После выхода из цикла достаточно проанализировать последнюю найденную цифру D (например, в While20 надо вывести значение логического выражения D = 2). По поводу проверки четности в задании While21 см. решение Boolean2.

While22. См. решение этой задачи.

While24–27. Последовательно находите числа Фибоначчи FK, пока выполняется условие FK < N (или FK £ N в While25). В While27 дополнительно вычисляйте номер текущего числа Фибоначчи. По поводу нахождения чисел Фибоначчи см. решение For33.

While28–29. Ср. While28 с For31, While29 с For34.

While30. Ср. с While1–2.


Модуль 4. Операторы цикла

Контрольные вопросы

Для каждого вопроса щелкните мышью на радиокнопке с номером варианта ответа, который, по вашему мнению, является правильным. После того как вы ответите на все вопросы, проверьте правильность ответов, нажав на кнопку «Проверка».

1. Укажите утверждение, которое является верным.

(1) | Начальное значение параметра цикла for не может быть больше конечного | (2) | Параметр цикла for не может иметь вещественный тип
(3) | Шаг параметра в цикле for всегда равен 1 | (4) | Тело цикла for выполняется хотя бы один раз

2. Дан фрагмент программы (A и I — переменные целого типа):

A := 0;
for I := 1 to 5 do;
  A := A + 1;
Write(A);

Укажите, что произойдет при обработке этого фрагмента.

(1) | Возникнет ошибка компиляции | (2) | Будет напечатано число 0
(3) | Будет напечатано число 1 | (4) | Будет напечатано число 5

3. Дан фрагмент программы (A и I — переменные целого типа):

A := 2;
for I := A to 2 * A do
  A := A + 2;
Write(A);

Укажите, что произойдет при обработке этого фрагмента.

(1) | Возникнет ошибка компиляции | (2) | Программа зациклится
(3) | Будет напечатано число 4 | (4) | Будет напечатано число 8

4. Дан фрагмент программы (A и I — переменные целого типа):

A := 2;
I := A;
while I <= 2 * A do
  I := I + 1;
  A := A + 2;
Write(A);

Укажите, что произойдет при обработке этого фрагмента.

(1) | Возникнет ошибка компиляции | (2) | Программа зациклится
(3) | Будет напечатано число 4 | (4) | Будет напечатано число 8

5. Дано начало фразы:

Если условие цикла истинно, то …

Какой вариант продолжения этой фразы соответствует верному утверждению?

(1) | … циклы while и repeat продолжают работу | (2) | … циклы while и repeat прекращают работу
(3) | … цикл while продолжает, а цикл repeat прекращает работу | (4) | … цикл while прекращает, а цикл repeat продолжает работу

6. Дан фрагмент программы (I и J — переменные целого типа):

for I := 1 to 5 do
begin
  if I = 3 then continue;
  for J := 1 to 3 do
  begin
    Writeln(1);
    if J = 2 then break;
  end;
end;

Укажите, сколько раз будет напечатано число 1.

(1) | 10 раз | (2) | 8 раз
(3) | 6 раз | (4) | 4 раза


Модуль 4. Операторы цикла

Итоговое задание

Организовать запрос о вводе целого числа N — количества чисел, которые будут в дальнейшем обработаны. Ввод числа N организуется с клавиатуры, при этом допускаются только числа из диапазона 2–20; при ошибочном вводе выводится сообщение об ошибке «Number is not in range 2..20» и повторяется запрос на ввод числа N.

После ввода числа N сформировать N целых чисел (используя датчик случайных чисел) в диапазоне от 5 до 100 и обработать каждое число следующим образом:

1) вывести все простые множители данного числа, начиная от наименьшего (например, для числа 50 следует вывести три множителя: 2, 5, 5);

2) если число является простым, то есть содержит единственный множитель, равный самому этому числу (например, число 7), то вывести текст «prime number» (простое число); в противном случае вывести текст «composite number» (составное число).

После обработки всех N чисел вывести следующие данные: количество обнаруженных простых чисел N1 и сумма их значений S1; количество обнаруженных составных чисел N2 и сумма их значений S2.

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

N = 30
Number is not in range 2..20
N = 0
Number is not in range 2..20
N = 18

K1 = 9: 3 3 (composite number)
K2 = 88: 2 2 2 11 (composite number)
K3 = 69: 3 23 (composite number)
K4 = 19: 19 (prime number)
K5 = 30: 2 3 5 (composite number)
K6 = 49: 7 7 (composite number)
K7 = 65: 5 13 (composite number)
K8 = 95: 5 19 (composite number)
K9 = 82: 2 41 (composite number)
K10 = 24: 2 2 2 3 (composite number)
K11 = 23: 23 (prime number)
K12 = 97: 97 (prime number)
K13 = 9: 3 3 (composite number)
K14 = 18: 2 3 3 (composite number)
K15 = 94: 2 47 (composite number)
K16 = 82: 2 41 (composite number)
K17 = 11: 11 (prime number)
K18 = 87: 3 29 (composite number)

N1 = 4
S1 = 150
N2 = 14
S2 = 801

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


Модуль 5. Процедуры и функции

Комплексная цель

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

Структура модуля

  • Решения типовых задач
  • Учебные задания и указания к ним
  • Контрольные вопросы
  • Итоговое задание


Модуль 5. Процедуры и функции

Решения типовых задач

Процедуры и функции: Proc4, Proc8, Proc21, Proc25

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

procedure имя[(параметры)]
[раздел описаний]
begin
  операторы
end;

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

Для досрочного выхода из процедуры следует использовать специальный оператор exit.

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

function имя[(параметры)]: тип
[раздел описаний]
begin
  операторы
end;

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

имя_функции := выражение;

В современных вариантах Паскаля, реализованных в системах Borland Delphi, Free Pascal Lazarus, PascalABC.NET, можно использовать другой способ указания возвращаемого значения функции — с помощью специальной переменной Result, которая неявно описывается в любой функции и имеет тип, совпадающий с типом возвращаемого значения функции. Для задания возвращаемого значения в функции достаточно присвоить это значение переменной Result:

Result := выражение;

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

Result := Result * 10;

Если попытаться использовать в левой и правой части оператора присваивания имя функции, то в большинстве реализаций Паскаля (в частности, в средах Borland Delphi и PascalABC.NET) это приведет к ошибке компиляции, поскольку появление имени функции в правой части оператора присваивания (и вообще в любом выражении) обычно расценивается компилятором как очередной вызов этой функции. Исключением является среда Free Pascal Lazarus, в которой при стандартных настройках компилятора имя определяемой функции ведет себя подобно переменной Result, то есть как обычная локальная переменная. Заметим, что если установить в среде Lazarus режим компиляции, совместимый с синтаксисом Delphi, то попытка использования имени функции в выражениях будет приводить к ошибке компиляции (для установки режима, совместимого с синтаксисом Delphi, надо выполнить команду меню «Проект | Параметры компилятора…», в появившемся диалоговом окне перейти на вкладку «Обработка» и выбрать в выпадающем списке «Режим синтаксиса» вариант «Delphi»).

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

Обратимся к параметрам процедур и функций. Параметры указываются в списке параметров через точку с запятой (;); определение каждого параметра имеет вид

[модификатор] имя: тип

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

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

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

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

Если параметр является одновременно входным и выходным, то он тоже должен передаваться по ссылке, то есть снабжаться модификатором var.

Если несколько рядом стоящих параметров подпрограммы имеют один и тот же модификатор (или не имеют его), а также имеют один и тот же тип, то допустимо описать их совместно, указав для них общий модификатор и общий описатель типа; при этом имена параметров должны перечисляться через запятую. Например, вместо пары описаний var A: integer; var B: integer можно привести совместное описание двух параметров: var A, B: integer.

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

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

Proc4. Описать процедуру TrianglePS(a, P, S), вычисляющую по стороне a равностороннего треугольника его периметр P = 3·a и площадь S = a2·Sqrt(3)/4 (a — входной, P и S — выходные параметры; все параметры являются вещественными). С помощью этой процедуры найти периметры и площади трех равносторонних треугольников с данными сторонами.

program Proc4;
uses PT4;

procedure TrianglePS(A: real; var P, S: real);
begin
  P := 3 * A;
  S := A * A * Sqrt(3) / 4;
end;

var
  I: integer;
  A1, P1, S1: real;
begin
  Task('Proc4');
  for I := 1 to 3 do
  begin
    GetR(A1);
    TrianglePS(A1, P1, S1);
    PutR(P1);
    PutR(S1);
  end;
end.

Параметр A процедуры TrianglePS является входным, параметры P и S — выходными. Для извлечения квадратного корня из 3 используется функция Sqrt.

Для того чтобы подчеркнуть независимость имен формальных и фактических параметров, мы дали глобальным переменным (A1, P1, S1) имена, отличные от имен соответствующих формальных параметров процедуры (A, P, S). Разумеется, ничто не мешает использовать для глобальных переменных те же имена, что и для локальных. Эти имена не будут конфликтовать, так как они находятся в разных областях видимости: локальные переменные и формальные параметры используются внутри процедуры, а глобальные переменные (в том числе и те, которые указываются в качестве фактических параметров) используются в разделе операторов основной программы.

Обратите внимание на то, что в использовании специальных переменных для хранения сторон трех исходных треугольников (например, A1, A2, A3) нет необходимости, так как треугольники обрабатываются последовательно, и после обработки очередного треугольника связанные с ним переменные (в нашем случае A1, P1, S1) можно использовать при обработке следующего треугольника.

Чтобы продемонстрировать важность правильного указания модификаторов при описании параметров процедур/функций, можно временно убрать из заголовка процедуры TrianglePS модификатор var (перед описанием параметров P и S). Измененная программа успешно откомпилируется, однако при ее выполнении в качестве результирующих данных всегда будут выводиться нулевые значения. Это объясняется тем, что теперь все параметры передаются по значению, то есть при вызове процедуры создаются копии фактических параметров, и в дальнейшем все действия в процедуре выполняются с этими копиями, и поэтому полученные результаты не будут переданы обратно в программу, вызывавшую данную процедуру. Таким образом, в глобальных переменных P1 и S1 сохранятся их начальные значения, равные 0.

Простое задание Proc8 демонстрирует использование параметра, одновременно являющегося входным и выходным.

Proc8. Описать процедуру AddRightDigit(D, K), добавляющую к целому положительному числу K справа цифру D (D — входной параметр целого типа, лежащий в диапазоне 0–9, K — параметр целого типа, являющийся одновременно входным и выходным). С помощью этой процедуры последовательно добавить к данному числу K справа данные цифры D1 и D2, выводя результат каждого добавления.

program Proc8;
uses PT4;

procedure AddRightDigit(D: integer; var K: integer);
begin
  K := K * 10 + D;
end;

var
  K, D, I: integer;
begin
  Task('Proc8');
  GetN(K);
  for I := 1 to 2 do
  begin
    GetN(D);
    AddRightDigit(D, K);
    PutN(K);
  end;
end.

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

Proc21. Описать функцию SumRange(A, B) целого типа, находящую сумму всех целых чисел от A до B включительно (A и B — целые). Если A > B, то функция возвращает 0. С помощью этой функции найти суммы чисел от A до B и от B до C, если даны числа A, B, C.

program Proc21;
uses PT4;

function SumRange(A, B: integer): integer;
var
  I: integer;
begin
  Result := 0;
  for I := A to B do
    Result := Result + I;
end;

var
  A, B, C: integer;
begin
  Task('Proc21');
  GetN(A);
  GetN(B);
  GetN(C);
  PutN(SumRange(A, B));
  PutN(SumRange(B, C));
end.

Следует заметить, что особая ситуация A > B в функции SumRange не требует специальной обработки, поскольку в этом случае в цикле не выполняется ни одной итерации, и переменная Result сохраняет свое начальное значение, равное 0. В функции SumRange используется локальная переменная I, которая создается при каждом вызове данной функции и уничтожается при завершении ее работы. Обратите внимание на то, что в разделе операторов основной программы вызов функции SumRange совмещен с выводом значения, возвращаемого этой функцией. Таким образом, раздел операторов содержит только операторы ввода исходных данных и вывода результатов.

Proc25. Описать функцию IsSquare(K) логического типа, возвращающую True, если целый параметр K (> 0) является квадратом некоторого целого числа, и False в противном случае. С ее помощью найти количество квадратов в наборе из 10 целых положительных чисел.

program Proc25;
uses PT4;

function IsSquare(K: integer): boolean;
var
  A: integer;
begin
  A := 1;
  while A * A < K do
    Inc(A);
  Result := A * A = K;
end;

var
  N, K, I: integer;
begin
  Task('Proc25');
  N := 0;
  for I := 1 to 10 do
  begin
    GetN(K);
    if IsSquare(K) then
      Inc(N);
  end;
  PutN(N);
end.

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

Создание и использование модулей: Proc10

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

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

Рассмотрим задание Proc10.

Proc10. Описать процедуру Swap(X, Y), меняющую содержимое переменных X и Y (X и Y — вещественные параметры, являющиеся одновременно входными и выходными). С ее помощью для данных переменных A, B, C, D последовательно поменять содержимое следующих пар: A и B, C и D, B и C и вывести новые значения A, B, C, D.

Процедура Swap, которую требуется описать в этом задании, пригодится при выполнении других заданий (например, Proc11, Proc12 и Proc13). Поэтому целесообразно включить ее во вспомогательный модуль, который можно назвать MyProc.

Создавать новый модуль удобно после создания проекта-заготовки для данного задания; в средах Borland Delphi и Free Pascal Lazarus это обеспечит автоматическое подключение созданного модуля к данному проекту.

Вначале опишем действия по созданию модулей для сред Borland Delphi и Free Pascal Lazarus. Для создания модуля в среде Delphi надо выполнить команду «File | New | Unit», в среде Lazarus — команду «Файл | Создать модуль». В результате в редакторе программного кода появится новая вкладка с заготовкой нового модуля, имеющего по умолчанию имя Unit1:

unit Unit1;

interface

implementation

end.

Обратите внимание на то, что текст модуля завершается закрывающей операторной скобкой end, которой не соответствует открывающая операторная скобка begin.

Желательно сразу изменить имя созданного модуля; для этого достаточно нажать комбинацию клавиш [Ctrl]+[S] и в появившемся диалоговом окне ввести новое имя (в нашем случае MyProc); расширение .pas указывать не требуется. Сразу после изменения имени модуля будет откорректирована его первая строка:

unit MyProc;

Модули в Borland Delphi и Free Pascal Lazarus содержат два обязательных раздела: раздел интерфейса (начинается с ключевого слова interface) и раздел реализации (начинается с ключевого слова implementation). В разделе интерфейса перечисляются все элементы модуля (типы, константы, переменные, процедуры и функции), которые будут доступны любой программе, подключившей данный модуль; при этом для процедур и функций указываются только заголовки. В разделе реализации приводятся полные описания процедур и функций, указанных в разделе интерфейса, а также описания других (вспомогательных) данных, которые необходимы для нормальной работы модуля, но не должны использоваться вне этого модуля. Таким образом, наличие двух разделов позволяет реализовать важный принцип инкапсуляции, или скрытия, данных, состоящий в запрете доступа к тем элементам модуля, которые не предназначены для использования внешними программами.

В среде PascalABC.NET для создания нового модуля специальная команда не предусмотрена. Поэтому необходимо выполнить команду «Файл | Новый» и явным образом ввести в созданный файл нужные операторы:

unit MyProc;

interface

implementation

end.

После этого останется сохранить файл под именем MyProc.pas (расширение .pas указывать не обязательно).

Примечание 1. Модули в Borland Delphi и Free Pascal Lazarus могут также включать два дополнительных раздела: инициализации (initialization) и завершения (finalization). Раздел инициализации содержит операторы, которые выполняются один раз, в момент подключения модуля к внешней программе. Раздел завершения может указываться только в модуле, содержащем раздел инициализации; этот раздел содержит операторы, которые выполняются один раз в момент завершения работы внешней программы. Эти разделы обычно используются в тех модулях, которые требуют для своей нормальной работы некоторые инициализирующие, а также завершающие действия. В модулях, создаваемых при выполнении учебных заданий, дополнительные разделы не требуются.

Примечание 2. В среде PascalABC.NET можно использовать упрощенный вариант определения модуля, не требующий указания разделов interface и implementation. При использовании упрощенного варианта достаточно сразу после заголовка модуля unit <Имя модуля> привести описания типов, констант, переменных, процедур и функций, которые требуется включить в данный модуль. Таким образом, можно считать, что модуль содержит единственный раздел, включающий полные описания всех его элементов, которые будут доступны любой программе, подключившей данный модуль.

Приведем вид модуля MyProc после добавления в него описания процедуры Swap:

unit MyProc;

interface

procedure Swap(var A, B: real);

implementation

procedure Swap(var A, B: real);
var
  C: real;
begin
  C := A;
  A := B;
  B := C;
end;

end.

При выполнении задания в среде PascalABC.NET можно воспользоваться упрощенным вариантом определения модуля:

unit MyProc;

procedure Swap(var A, B: real);
var
  C: real;
begin
  C := A;
  A := B;
  B := C;
end;

end.

После ввода требуемых описаний в модуль MyProc надо вернуться к основной программе (напомним, что заготовка программы для решения задания Proc10 по умолчанию имеет имя Proc10; ее расширение зависит от выбранной среды программирования) и добавить текст решения задания, в котором используется процедура, описанная в модуле. В средах Delphi и Lazarus в директиву uses основной программы будет автоматически добавлено имя созданного модуля MyProc; в среде PascalABC.NET это имя необходимо будет добавить явным образом:

program Proc10;
uses PT4, MyProc;

var
  A, B, C, D: real;
begin
  Task('Proc10');
  GetR(A);
  GetR(B);
  GetR(C);
  GetR(D);
  Swap(A, B);
  Swap(C, D);
  Swap(B, C);
  PutR(A);
  PutR(B);
  PutR(C);
  PutR(D);
end.

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

uses PT4, MyProc;

Заметим, что после этого можно очень быстро загрузить в редактор данный модуль. Для загрузки модуля достаточно щелкнуть правой кнопкой мыши на имени этого модуля и выбрать из появившегося контекстного меню соответствующий пункт («Open File at Cursor» в Delphi, «Найти объявление» в Lazarus, «Перейти к определению» в PascalABC.NET).


Модуль 5. Процедуры и функции

Учебные задания и указания к ним

Процедуры с числовыми параметрами

Proc1. Описать процедуру PowerA3(A, B), вычисляющую третью степень числа A и возвращающую ее в переменной B (A — входной, B — выходной параметр; оба параметра являются вещественными). С помощью этой процедуры найти третьи степени пяти данных чисел.

Proc2. Описать процедуру PowerA234(A, B, C, D), вычисляющую вторую, третью и четвертую степень числа A и возвращающую эти степени соответственно в переменных B, C и D (A — входной, B, C, D — выходные параметры; все параметры являются вещественными). С помощью этой процедуры найти вторую, третью и четвертую степень пяти данных чисел.

Proc3. Описать процедуру Mean(X, Y, AMean, GMean), вычисляющую среднее арифметическое AMean = (X+Y)/2 и среднее геометрическое GMean = (X·Y)1/2 двух положительных чисел X и Y (X и Y — входные, AMean и GMean — выходные параметры вещественного типа). С помощью этой процедуры найти среднее арифметическое и среднее геометрическое для пар (A, B), (A, C), (A, D), если даны A, B, C, D.

Proc4. Описать процедуру TrianglePS(a, P, S), вычисляющую по стороне a равностороннего треугольника его периметр P = 3·a и площадь S = a2·(3)1/2/4 (a — входной, P и S — выходные параметры; все параметры являются вещественными). С помощью этой процедуры найти периметры и площади трех равносторонних треугольников с данными сторонами.

Proc5. Описать процедуру RectPS(x1, y1, x2, y2, P, S), вычисляющую периметр P и площадь S прямоугольника со сторонами, параллельными осям координат, по координатам (x1, y1), (x2, y2) его противоположных вершин (x1, y1, x2, y2 — входные, P и S — выходные параметры вещественного типа). С помощью этой процедуры найти периметры и площади трех прямоугольников с данными противоположными вершинами.

Proc6. Описать процедуру DigitCountSum(K, C, S), находящую количество C цифр целого положительного числа K, а также их сумму S (K — входной, C и S — выходные параметры целого типа). С помощью этой процедуры найти количество и сумму цифр для каждого из пяти данных целых чисел.

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

Proc8. Описать процедуру AddRightDigit(D, K), добавляющую к целому положительному числу K справа цифру D (D — входной параметр целого типа, лежащий в диапазоне 0–9, K — параметр целого типа, являющийся одновременно входным и выходным). С помощью этой процедуры последовательно добавить к данному числу K справа данные цифры D1 и D2, выводя результат каждого добавления.

Proc9. Описать процедуру AddLeftDigit(D, K), добавляющую к целому положительному числу K слева цифру D (D — входной параметр целого типа, лежащий в диапазоне 1–9, K — параметр целого типа, являющийся одновременно входным и выходным). С помощью этой процедуры последовательно добавить к данному числу K слева данные цифры D1 и D2, выводя результат каждого добавления.

Proc10. Описать процедуру Swap(X, Y), меняющую содержимое переменных X и Y (X и Y — вещественные параметры, являющиеся одновременно входными и выходными). С ее помощью для данных переменных A, B, C, D последовательно поменять содержимое следующих пар: A и B, C и D, B и C и вывести новые значения A, B, C, D.

Proc11. Описать процедуру Minmax(X, Y), записывающую в переменную X минимальное из значений X и Y, а в переменную Y — максимальное из этих значений (X и Y — вещественные параметры, являющиеся одновременно входными и выходными). Используя четыре вызова этой процедуры, найти минимальное и максимальное из данных чисел A, B, C, D.

Proc12. Описать процедуру SortInc3(A, B, C), меняющую содержимое переменных A, B, C таким образом, чтобы их значения оказались упорядоченными по возрастанию (A, B, C — вещественные параметры, являющиеся одновременно входными и выходными). С помощью этой процедуры упорядочить по возрастанию два данных набора из трех чисел: (A1, B1, C1) и (A2, B2, C2).

Proc13. Описать процедуру SortDec3(A, B, C), меняющую содержимое переменных A, B, C таким образом, чтобы их значения оказались упорядоченными по убыванию (A, B, C — вещественные параметры, являющиеся одновременно входными и выходными). С помощью этой процедуры упорядочить по убыванию два данных набора из трех чисел: (A1, B1, C1) и (A2, B2, C2).

Proc14. Описать процедуру ShiftRight3(A, B, C), выполняющую правый циклический сдвиг: значение A переходит в B, значение B — в C, значение C — в A (A, B, C — вещественные параметры, являющиеся одновременно входными и выходными). С помощью этой процедуры выполнить правый циклический сдвиг для двух данных наборов из трех чисел: (A1, B1, C1) и (A2, B2, C2).

Proc15. Описать процедуру ShiftLeft3(A, B, C), выполняющую левый циклический сдвиг: значение A переходит в C, значение C — в B, значение B — в A (A, B, C — вещественные параметры, являющиеся одновременно входными и выходными). С помощью этой процедуры выполнить левый циклический сдвиг для двух данных наборов из трех чисел: (A1, B1, C1) и (A2, B2, C2).

Функции с числовыми параметрами

Proc16. Описать функцию Sign(X) целого типа, возвращающую для вещественного числа X следующие значения:

–1, если X < 0; 0, если X = 0; 1, если X > 0.

С помощью этой функции найти значение выражения Sign(A) + Sign(B) для данных вещественных чисел A и B.

Proc17. Описать функцию RootCount(A, B, C) целого типа, определяющую количество корней квадратного уравнения A·x2 + B·x + C = 0 (A, B, C — вещественные параметры, A № 0). С ее помощью найти количество корней для каждого из трех квадратных уравнений с данными коэффициентами. Количество корней определять по значению дискриминанта:

D = B2 – 4·A·C.

Proc18. Описать функцию CircleS(R) вещественного типа, находящую площадь круга радиуса R (R — вещественное). С помощью этой функции найти площади трех кругов с данными радиусами. Площадь круга радиуса R вычисляется по формуле S = p·R2. В качестве значения p использовать 3.14.

Proc19. Описать функцию RingS(R1, R2) вещественного типа, находящую площадь кольца, заключенного между двумя окружностями с общим центром и радиусами R1 и R2 (R1 и R2 — вещественные, R1 > R2). С ее помощью найти площади трех колец, для которых даны внешние и внутренние радиусы. Воспользоваться формулой площади круга радиуса R: S = p·R2. В качестве значения p использовать 3.14.

Proc20. Описать функцию TriangleP(a, h), находящую периметр равнобедренного треугольника по его основанию a и высоте h, проведенной к основанию (a и h — вещественные). С помощью этой функции найти периметры трех треугольников, для которых даны основания и высоты. Для нахождения боковой стороны b треугольника использовать теорему Пифагора:

b2 = (a/2)2 + h2.

Proc21. Описать функцию SumRange(A, B) целого типа, находящую сумму всех целых чисел от A до B включительно (A и B — целые). Если A > B, то функция возвращает 0. С помощью этой функции найти суммы чисел от A до B и от B до C, если даны числа A, B, C.

Proc22. Описать функцию Calc(A, B, Op) вещественного типа, выполняющую над ненулевыми вещественными числами A и B одну из арифметических операций и возвращающую ее результат. Вид операции определяется целым параметром Op: 1 — вычитание, 2 — умножение, 3 — деление, остальные значения — сложение. С помощью Calc выполнить для данных A и B операции, определяемые данными целыми N1, N2, N3.

Proc23. Описать функцию Quarter(x, y) целого типа, определяющую номер координатной четверти, в которой находится точка с ненулевыми вещественными координатами (x, y). С помощью этой функции найти номера координатных четвертей для трех точек с данными ненулевыми координатами.

Proc24. Описать функцию Even(K) логического типа, возвращающую True, если целый параметр K является четным, и False в противном случае. С ее помощью найти количество четных чисел в наборе из 10 целых чисел.

Proc25. Описать функцию IsSquare(K) логического типа, возвращающую True, если целый параметр K (> 0) является квадратом некоторого целого числа, и False в противном случае. С ее помощью найти количество квадратов в наборе из 10 целых положительных чисел.

Proc26. Описать функцию IsPower5(K) логического типа, возвращающую True, если целый параметр K (> 0) является степенью числа 5, и False в противном случае. С ее помощью найти количество степеней числа 5 в наборе из 10 целых положительных чисел.

Proc27. Описать функцию IsPowerN(K, N) логического типа, возвращающую True, если целый параметр K (> 0) является степенью числа N (> 1), и False в противном случае. Дано число N (> 1) и набор из 10 целых положительных чисел. С помощью функции IsPowerN найти количество степеней числа N в данном наборе.

Proc28. Описать функцию IsPrime(N) логического типа, возвращающую True, если целый параметр N (> 1) является простым числом, и False в противном случае (число, большее 1, называется простым, если оно не имеет положительных делителей, кроме 1 и самого себя). Дан набор из 10 целых чисел, больших 1. С помощью функции IsPrime найти количество простых чисел в данном наборе.

Proc29. Описать функцию DigitCount(K) целого типа, находящую количество цифр целого положительного числа K. Используя эту функцию, найти количество цифр для каждого из пяти данных целых положительных чисел.

Proc30. Описать функцию DigitN(K, N) целого типа, возвращающую N-ю цифру целого положительного числа K (цифры в числе нумеруются справа налево). Если количество цифр в числе K меньше N, то функция возвращает –1. Для каждого из пяти данных целых положительных чисел K1, K2, …, K5 вызвать функцию DigitN с параметром N, изменяющимся от 1 до 5.

Proc31. Описать функцию IsPalindrome(K), возвращающую True, если целый параметр K (> 0) является палиндромом (то есть его запись читается одинаково слева направо и справа налево), и False в противном случае. С ее помощью найти количество палиндромов в наборе из 10 целых положительных чисел.

Proc32. Описать функцию DegToRad(D) вещественного типа, находящую величину угла в радианах, если дана его величина D в градусах (D — вещественное число, 0 £ D < 360). Воспользоваться следующим соотношением: 180° = p радианов. В качестве значения p использовать 3.14. С помощью функции DegToRad перевести из градусов в радианы пять данных углов.

Proc33. Описать функцию RadToDeg(R) вещественного типа, находящую величину угла в градусах, если дана его величина R в радианах (R — вещественное число, 0 £ R < 2·p). Воспользоваться следующим соотношением: 180° = p радианов. В качестве значения p использовать 3.14. С помощью функции RadToDeg перевести из радианов в градусы пять данных углов.

Proc34. Описать функцию Fact(N) вещественного типа, вычисляющую значение факториала N! = 1·2·…·N (N > 0 — параметр целого типа; вещественное возвращаемое значение используется для того, чтобы избежать целочисленного переполнения при больших значениях N). С помощью этой функции найти факториалы пяти данных целых чисел.

Proc35. Описать функцию Fact2(N) вещественного типа, вычисляющую двойной факториал:

N!! = 1·3·5·…·N, если N — нечетное;
N!! = 2·4·6·…·N, если N — четное

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

Proc36. Описать функцию Fib(N) целого типа, вычисляющую N-й элемент последовательности чисел Фибоначчи FK, которая описывается следующими формулами:

F1 = 1, F2 = 1, FK = FK–2 + FK–1, K = 3, 4, … .

Используя функцию Fib, найти пять чисел Фибоначчи с данными номерами N1, N2, …, N5.

Дополнительные задания на процедуры и функции

Proc37. Описать функцию Power1(A, B) вещественного типа, находящую величину AB по формуле AB = exp(B·ln(A)) (параметры A и B — вещественные). В случае нулевого или отрицательного параметра A функция возвращает 0. С помощью этой функции найти степени AP, BP, CP, если даны числа P, A, B, C.

Proc38. Описать функцию Power2(A, N) вещественного типа, находящую величину AN (A — вещественный, N — целый параметр) по следующим формулам:

A0 = 1;
AN = A·A·…·A (N сомножителей), если N > 0;
AN = 1/(A·A·…·A) (|N| сомножителей), если N < 0.

С помощью этой функции найти AK, AL, AM, если даны числа A, K, L, M.

Proc39. Используя функции Power1 и Power2 из Proc37 и Proc38, описать функцию Power3(A, B) вещественного типа с вещественными параметрами, находящую AB следующим образом: если B имеет нулевую дробную часть, то вызывается Power2(A, N), где N — переменная целого типа, равная числу B; иначе вызывается Power1(A, B). С помощью Power3 найти AP, BP, CP, если даны числа P, A, B, C.

Proc40. Описать функцию Exp1(x, e) вещественного типа (параметры x, e — вещественные, e > 0), находящую приближенное значение функции exp(x):

exp(x) = 1 + x + x2/(2!) + x3/(3!) + … + xn/(n!) + …

(n! = 1·2·…·n). В сумме учитывать все слагаемые, большие e. С помощью Exp1 найти приближенное значение экспоненты для данного x при шести данных e.

Proc41. Описать функцию Sin1(x, e) вещественного типа (параметры x, e — вещественные, e > 0), находящую приближенное значение функции sin(x):

sin(x) = x – x3/(3!) + x5/(5!) – … + (–1)n·x2·n+1/((2·n+1)!) + … .

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

Proc42. Описать функцию Cos1(x, e) вещественного типа (параметры x, e — вещественные, e > 0), находящую приближенное значение функции cos(x):

cos(x) = 1 – x2/(2!) + x4/(4!) – … + (–1)n·x2·n/((2·n)!) + … .

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

Proc43. Описать функцию Ln1(x, e) вещественного типа (параметры x, e — вещественные, |x| < 1, e > 0), находящую приближенное значение функции ln(1 + x):

ln(1 + x) = x – x2/2 + x3/3 – … + (–1)n·xn+1/(n+1) + … .

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

Proc44. Описать функцию Arctg1(x, e) вещественного типа (параметры x, e — вещественные, |x| < 1, e > 0), находящую приближенное значение функции arctg(x):

arctg(x) = x – x3/3 + x5/5 – … + (–1)n·x2·n+1/(2·n+1) + … .

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

Proc45. Описать функцию Power4(x, a, e) вещественного типа (параметры x, a, e — вещественные, |x| < 1; a, e > 0), находящую приближенное значение функции (1 + x)a:

(1 + x)a = 1 + a·x + a·(a–1)·x2/(2!) + … + a·(a–1)·…·(a–n+1)·xn/(n!) + … .

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

Proc46. Описать функцию GCD2(A, B) целого типа, находящую наибольший общий делитель (НОД, greatest common divisor) двух целых положительных чисел A и B, используя алгоритм Евклида:

НОД(A, B) = НОД(B, A mod B), если B ≠ 0; НОД(A, 0) = A,

где «mod» обозначает операцию взятия остатка от деления. С помощью GCD2 найти наибольшие общие делители пар (A, B), (A, C), (A, D), если даны числа A, B, C, D.

Proc47. Используя функцию GCD2 (см. Proc46), описать процедуру Frac1(a, b, p, q), преобразующую дробь a/b к несократимому виду p/q (все параметры процедуры — целого типа, a и b — входные, p и q — выходные). Знак результирующей дроби p/q приписывается числителю (т. е. q > 0). С помощью Frac1 найти несократимые дроби, равные a/b + c/d, a/b + e/f, a/b + g/h (числа a, b, c, d, e, f, g, h даны).

Proc48. Наименьшее общее кратное (least common multiple) двух целых положительных чисел A и B равно A·(B/НОД(A, B)), где НОД(A, B) — наибольший общий делитель A и B. Используя функцию GCD2 (см. Proc46), описать функцию LCM2(A, B) целого типа, находящую наименьшее общее кратное чисел A и B. С помощью LCM2 найти наименьшие общие кратные пар (A, B), (A, C), (A, D), если даны числа A, B, C, D.

Proc49. Учитывая соотношение НОД(A, B, C) = НОД(НОД(A, B), C) и используя функцию GCD2 (см. Proc46), описать функцию GCD3(A, B, C) целого типа, находящую наибольший общий делитель трех целых положительных чисел A, B, C. С помощью GCD3 найти наибольшие общие делители троек (A, B, C), (A, C, D) и (B, C, D), если даны числа A, B, C, D.

Proc50. Описать процедуру TimeToHMS(T, H, M, S), определяющую по времени T (в секундах) содержащееся в нем количество часов H, минут M и секунд S (T — входной, H, M и S — выходные параметры целого типа). Используя эту процедуру, найти количество часов, минут и секунд для пяти данных отрезков времени T1, T2, …, T5.

Proc51. Описать процедуру IncTime(H, M, S, T), которая увеличивает на T секунд время, заданное в часах H, минутах M и секундах S (H, M и S — входные и выходные параметры, T — входной параметр; все параметры — целые положительные). Дано время (в часах H, минутах M, секундах S) и целое число T. Используя процедуру IncTime, увеличить данное время на T секунд и вывести новые значения H, M, S.

Proc52. Описать функцию IsLeapYear(Y) логического типа, которая возвращает True, если год Y (целое положительное число) является високосным, и False в противном случае. Вывести значение функции IsLeapYear для пяти данных значений параметра Y. Високосным считается год, делящийся на 4, за исключением тех годов, которые делятся на 100 и не делятся на 400.

Proc53. Используя функцию IsLeapYear из задания Proc52, описать функцию MonthDays(M, Y) целого типа, которая возвращает количество дней для M-го месяца года Y (1 £ M £ 12, Y > 0 — целые числа). Вывести значение функции MonthDays для данного года Y и месяцев M1, M2, M3.

Proc54. Используя функцию MonthDays из задания Proc53, описать процедуру PrevDate(D, M, Y), которая по информации о правильной дате, включающей день D, номер месяца M и год Y, определяет предыдущую дату (параметры целого типа D, M, Y являются одновременно входными и выходными). Применить процедуру PrevDate к трем исходным датам и вывести полученные значения предыдущих дат.

Proc55. Используя функцию MonthDays из задания Proc53, описать процедуру NextDate(D, M, Y), которая по информации о правильной дате, включающей день D, номер месяца M и год Y, определяет следующую дату (параметры целого типа D, M, Y являются одновременно входными и выходными). Применить процедуру NextDate к трем исходным датам и вывести полученные значения следующих дат.

Proc56. Описать функцию Leng(xA, yA, xB, yB) вещественного типа, находящую длину отрезка AB на плоскости по координатам его концов:

|AB| = ((xA – xB)2 + (yA – yB)2)1/2

(xA, yA, xB, yB — вещественные параметры). С помощью этой функции найти длины отрезков AB, AC, AD, если даны координаты точек A, B, C, D.

Proc57. Используя функцию Leng из задания Proc56, описать функцию Perim(xA, yA, xB, yB, xC, yC) вещественного типа, находящую периметр треугольника ABC по координатам его вершин (xA, yA, xB, yB, xC, yC — вещественные параметры). С помощью этой функции найти периметры треугольников ABC, ABD, ACD, если даны координаты точек A, B, C, D.

Proc58. Используя функции Leng и Perim из заданий Proc56 и Proc57, описать функцию Area(xA, yA, xB, yB, xC, yC) вещественного типа, находящую площадь треугольника ABC по формуле

SABC = (p·(p–|AB|)·(p–|AC|)·(p–|BC|))1/2,

где p — полупериметр. С помощью этой функции найти площади треугольников ABC, ABD, ACD, если даны координаты точек A, B, C, D.

Proc59. Используя функции Leng и Area из заданий Proc56 и Proc58, описать функцию Dist(xP, yP, xA, yA, xB, yB) вещественного типа, находящую расстояние D(P, AB) от точки P до прямой AB по формуле

D(P, AB) = 2·SPAB/|AB|,

где SPAB — площадь треугольника PAB. С помощью этой функции найти расстояния от точки P до прямых AB, AC, BC, если даны координаты точек P, A, B, C.

Proc60. Используя функцию Dist из задания Proc59, описать процедуру Altitudes(xA, yA, xB, yB, xC, yC, hA, hB, hC), находящую высоты hA, hB, hC треугольника ABC (выходные параметры), проведенные соответственно из вершин A, B, C (их координаты являются входными параметрами). С помощью этой процедуры найти высоты треугольников ABC, ABD, ACD, если даны координаты точек A, B, C, D.

Указания

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

Proc1–2. Простейшие задания на разработку процедур. Исходные числа удобно обрабатывать в цикле, последовательно считывая их в одну и ту же переменную и затем передавая эту переменную в требуемую процедуру (как в решении Proc4). Аналогичный прием можно использовать и в других заданиях данной группы (например, Proc4–7, Proc12–15 и т. д.).

Proc3. Ср. с Begin8–9.

Proc4. См. решение этой задачи.

Proc5. Ср. с Begin19.

Proc6. Ср. с While18.

Proc7. Ср. с While19.

Proc8–9. В Proc8 достаточно умножить исходное число K на 10 и прибавить к нему цифру D (см. решение этой задачи). В Proc9 надо к числу K прибавить цифру D, умноженную на 10 в степени, равной количеству цифр числа K (требуемую степень числа 10 вычисляйте в цикле; для определения количества цифр числа K можно воспользоваться процедурой DigitCountSum из задания Proc6).

Proc10. См. решение этой задачи; ср. его с решением Begin22. Полезно сохранить созданную процедуру Swap в отдельном модуле, чтобы в дальнейшем использовать при решении других задач (например, Proc11–13).

Proc11. Ср. с If9. Для перемены местами содержимого X и Y можно использовать процедуру Swap из задания Proc10.

Proc12–13. Для сортировки трех значений A, B, C по возрастанию достаточно выполнить три последовательных вызова процедуры Minmax из задания Proc11 с параметрами (A, B), (B, C) и (A, B). Для сортировки этих значений по убыванию достаточно отсортировать их по возрастанию и поменять местами содержимое A и C (для этого можно использовать процедуру Swap из задания Proc10).

Proc14–15. Ср. с Begin23–24.

Proc16–17. Простейшие задания на разработку функций. По поводу ввода исходных данных см. указание к Proc1–2. В этих и последующих заданиях вызов требуемых функций можно совместить с выводом результатов; например, в Proc16 требуемое выражение Sign(A) + Sign(B) можно поместить непосредственно в процедуру вывода PutN.

Proc18–19. Ср. с Begin13.

Proc21. См. решение этой задачи.

Proc22. Ср. с Case5. В данном случае удобно использовать оператор выбора с вариантом по умолчанию еlse.

Proc23. Ср. с If22.

Proc24–28. Задания на разработку функций, возвращающих логические значения. Ср. Proc24 с Boolean3, Proc25–27 с While4–5, Proc28 с While22.

Proc29–30. Ср. с While17–18.

Proc32–33. Ср. с Begin31–32.

Proc34. Ср. с For19.

Proc35. Ср. с While6.

Proc36. Ср. с For33.

Proc37–39. При описании функции Power1 в Proc37 используйте функции Exp и Ln; ср. Proc38 с For15. Созданные в Proc37–38 функции Power1 и Power2 удобно сохранить в отдельном модуле (см. решение Proc10), чтобы упростить их использование при решении Proc39.

Proc40–45. См. указание к For22–28. Поскольку количество слагаемых в сумме заранее не известно, используйте цикл с условием.

Proc46–49. Ср. Proc46 с While23. Для хранения созданных процедур и функций используйте отдельный модуль (см. решение Proc10).

Proc50–55. Ср. Proc50 с Integer19–23, Proc52 с If28, Proc53 с Case4, Proc54–55 с Case8–9. В Proc51 переведите исходное время в количество секунд, прибавьте к нему число T и выполните обратное преобразование времени в часы, минуты и секунды (для обратного преобразования удобно воспользоваться процедурой TimeToHMS из задания Proc50). Для хранения созданных процедур и функций используйте отдельный модуль (см. решение Proc10).

Proc56–60. Ср. Proc56–58 с Begin20–21. Для хранения созданных процедур и функций используйте отдельный модуль (см. решение Proc10).


Модуль 5. Процедуры и функции

Контрольные вопросы

Для каждого вопроса щелкните мышью на радиокнопке с номером варианта ответа, который, по вашему мнению, является правильным. После того как вы ответите на все вопросы, проверьте правильность ответов, нажав на кнопку «Проверка».

1. Укажите высказывание, которое является неверным.

(1) | Входные параметры можно передавать по значению | (2) | Входные параметры можно передавать по ссылке
(3) | Выходные параметры можно передавать по значению | (4) | Выходные параметры можно передавать по ссылке

2. Среди приведенных ниже высказываний только одно является неверным для вариантов языка Паскаль, реализованных в средах Borland Delphi, Free Pascal Lazarus и PascalABC.NET. Укажите это неверное высказывание.

(1) | Функции можно вызывать как отдельные операторы | (2) | Функции можно вызывать в выражении
(3) | Процедуры можно вызывать как отдельные операторы | (4) | Процедуры можно вызывать в выражении

3. Учащийся описал процедуру P1:

procedure P1(var A: integer; B: integer);
var
  C: integer;
begin
  C := A;
  A := B;
  B := C;
end;

Для тестирования этой процедуры используется следующий фрагмент основной программы (M, N и K — переменные целого типа):

M := 1;
N := 2;
K := 3;
P1(M, N);
P1(N, K);
Write(M, ' ', N, ' ', K);

Укажите, что произойдет при обработке данного фрагмента.

(1) | Возникнет ошибка компиляции | (2) | Будут напечатаны числа 1, 2, 3
(3) | Будут напечатаны числа 2, 3, 3 | (4) | Будут напечатаны числа 2, 3, 1

4. Учащийся описал функцию F1:

function F1(N: integer): integer;
var
  I: integer;
begin
  F1 := 1;
  for I := 1 to N do;
    F1 := F1 div N;
end;

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

Write(F1(0));

Укажите, что произойдет при обработке данного фрагмента.

(1) | Возникнет ошибка компиляции | (2) | Возникнет ошибка времени выполнения
(3) | Будет напечатано число 0 | (4) | Будет напечатано число 1

5. Учащийся описал функцию F2:

function F2(N: integer): integer;
var
  I: integer;
begin
  Result := 1;
  for I := 1 to N do;
    Result := Result div N;
end;

Для тестирования этой функции в среде PascalABC.NET используется следующий оператор основной программы:

Write(F2(0));

Укажите, что произойдет при обработке данного фрагмента.

(1) | Возникнет ошибка компиляции | (2) | Возникнет ошибка времени выполнения
(3) | Будет напечатано число 0 | (4) | Будет напечатано число 1

6. Укажите высказывание, которое является неверным.

(1) | В разделе interface указываются заголовки всех процедур и функций, описания которых содержатся в данном модуле | (2) | В разделе implementation указываются описания всех процедур и функций, имеющихся в данном модуле
(3) | Описания типов, переменных и констант можно указывать как в разделе interface, так и в разделе implementation | (4) | Раздел finalization можно указывать в модуле только после раздела initialization


Модуль 5. Процедуры и функции

Итоговое задание

Описать функцию IsLeapYear(Year) типа boolean, которая возвращает True, если параметр Year (типа integer) определяет високосный год, и False в противном случае (високосным считается год, делящийся на 4, за исключением тех годов, которые делятся на 100 и не делятся на 400).

Используя функцию IsLeapYear, описать функцию DaysInMonth(Month, Year) типа integer, которая возвращает число дней для месяца Month года Year (оба параметра типа integer). Номер месяца Month должен лежать в диапазоне от 1 до 12, год Year должен быть положительным. Если указанные условия на параметры нарушаются, то функция возвращает 0.

Используя функцию DaysInMonth, описать процедуру NextDate(Day, Month, Year), которая изменяет правильную дату, задаваемую параметрами Day, Month, Year, на следующую за ней дату, а неправильную дату оставляет неизменной (параметры данной процедуры имеют тип integer и являются одновременно входными и выходными). Правильной считается дата, имеющая положительное значение года, допустимое значение номера месяца (от 1 до 12) и допустимое значение дня для данного месяца и года.

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

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

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

Input Date: 3 12 2001
Output Date: 4 12 2001
Input Date: 31 12 2003
Output Date: 1 1 2004
Input Date: 28 2 1993
Output Date: 1 3 1993
Input Date: 29 2 1900
Output Date: 29 2 1900
Input Date: 29 2 2000
Output Date: 1 3 2000
Input Date: 0 0 0

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


Модуль 6. Обработка последовательностей

Комплексная цель

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

Структура модуля

  • Решения типовых задач
  • Учебные задания и указания к ним
  • Контрольные вопросы
  • Итоговое задание


Модуль 6. Обработка последовательностей

Решения типовых задач

Последовательности: Series1, Series15, Series17, Series19, Series21

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

Series1. Даны десять вещественных чисел. Найти их сумму.

При выполнении заданий на обработку последовательностей мы сталкиваемся со следующей проблемой: как обеспечить хранение в памяти всех элементов последовательности? Если в задании известно количество таких элементов, то можно, конечно, описать столько же простых переменных, ввести в эти переменные исходные элементы, а затем явным образом выполнить над ними нужное действие. Однако такой вариант решения является очень громоздким и неудобным. В самом деле, даже если нам даны всего 10 чисел (как в задании Series1), нам потребуется описать столько же переменных (например, A1, A2, A3 и так далее до A10), после чего ввести их десятью операторами ввода GetR и просуммировать все введенные значения в одном большом выражении вида A1 + A2 + A3 + A4 + A5 + A6 + A7 + A8 + A9 + A10. А если бы нам было предложено просуммировать 100 чисел? Кроме того, описанный способ обработки последовательности оказывается совершенно непригодным в ситуации, когда заранее (до запуска программы) неизвестно количество элементов последовательности.

Мы видим, что для одновременного хранения в памяти всех элементов последовательности неудобно (а иногда и невозможно) использовать набор простых переменных. Однако зададимся вопросом: а надо ли для решения задачи, подобной Series1, одновременно хранить все элементы в памяти? В самом деле, если мы введем первый элемент последовательности в некоторую переменную A, а затем, в соответствии с алгориомом суммирования, добавим ее к переменной S, в которой накапливается сумма (используя оператор S := S + A), то после этого первый элемент нам уже не потребуется, и на следующем шаге мы сможем ввести следующий (второй) элемент последовательности в ту же самую переменную A, заменив ее старое значение на новое. Обработав второй элемент (в нашем случае добавив его к сумме S), мы прочтем в переменную A третий элемент, и т. д. Повторяя описанные действия для каждого из элементов последовательности в цикле, мы сможем найти требуемую сумму, и при этом нам потребуются всего две переменные (не считая переменной цикла): S для накопления суммы и A для хранения текущего элемента последовательности:

program Series1;
uses PT4;
var
  I: integer;
  A, S: real;
begin
  Task('Series1');
  S := 0;
  for I := 1 to 10 do
  begin
    GetR(A);
    S := S + A;
  end;
  PutR(S);
end.

В соответствии с алгоритмом суммирования мы инициализировали переменную S нулевым значением.

Обратите внимание на то, что реализованный нами алгоритм можно без каких-либо существенных модификаций использовать и для суммирования 100, и для суммирования 1000 элементов: достаточно изменить количество итераций цикла. Более того, если число элементов последовательности заранее неизвестно, однако сообщается в начале выполнения программы, то достаточно прочесть это число в некоторую переменную N целого типа, после чего указать эту переменную в заголовке цикла for в качестве конечного значения параметра цикла.

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

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

Примечание 1. Разумеется, не всякую задачу, связанную с обработкой последовательности, можно решить подобным способом. Например, даже задачу вывода элементов последовательности в обратном порядке нельзя решить без одновременного хранения в памяти всех элементов. В этом случае приходится использовать специальные составные типы данных, простейшим их которых является массив. Однако если задача может быть решена за однократный просмотр последовательности (без последующего обращения к уже просмотренным элементам), то в применении массивов нет необходимости. Алгоритмы обработки последовательности, которые требуют однократного просмотра ее элементов, называются однопроходными. Для решения любой задачи из группы Series (а также рассматриваемой далее группы Minmax) можно использовать однопроходные алгоритмы. Задачи, требующие для своего решения обязательного применения массивов, в данном пособии не рассматриваются (в задачнике Programming Taskbook подобные задачи входят в группы Array и Matrix).

Series15. Дано целое число K и набор ненулевых целых чисел; признак его завершения — число 0. Вывести номер первого числа в наборе, большего K. Если таких чисел нет, то вывести 0.

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

program Series15;
uses PT4;
var
  K, A, I, N: integer;
begin
  Task('Series15');
  GetN(K);
  GetN(A);
  I := 0;
  N := 0;
  while A <> 0 do
  begin
    I := I + 1;
    if A > K then
    begin
      N := I;
      break;
    end;
    GetN(A);
  end;
  PutN(N);
end.

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

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

Примечание 2. Стандартная процедура break может вызываться только внутри цикла; при ее вызове происходит немедленный выход из текущего оператора цикла и переход на следующий за ним оператор. Данная процедура впервые появилась в версии 7.0 системы Borland Pascal для DOS и в настоящее время имеется во всех распространенных реализациях языка Паскаль. Следует также упомянуть процедуру continue, которая также имеется во всех современных реализациях Паскаля (начиная с Borland Pascal 7.0) и обеспечивает немедленное завершение текущей итерации цикла (эту процедуру, как и процедуру break, можно вызывать только внутри цикла).

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

При решении данного задания удобно использовать переменную-флаг F логического типа. Переменная F инициализируется значением True и сохраняет это значение до тех пор, пока не будет выведено число B. Вывод числа B надо выполнить в тот момент, когда обнаружится, что очередной элемент последовательности (прочитанный в переменную A) окажется больше числа B и при этом значение флага равно True. После вывода числа B значение флага F надо изменить на False; благодаря этому в дальнейшем число B не будет выведено повторно, несмотря на то что для всех последующих элементов A также будет выполнено условие A > B:

program Series17;
uses PT4;
var
  A, B: real;
  F: boolean;
  I, N: integer;
begin
  Task('Series17');
  GetR(B);
  GetN(N);
  F := True;
  for I := 1 to N do
  begin
    GetR(A);
    if (A > B) and F then
    begin
      PutR(B);
      F := False;
    end;
    PutR(A);
  end;
  if F then
    PutR(B);
end.

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

Примечание 3. При анализе значения флага F в условном операторе не требуется использовать равенства вида F = True или F = False. Поскольку само значение флага является логическим, вместо указанных равенств достаточно использовать выражения F или not F соответственно.

Series19. Дано целое число N (> 1) и набор из N целых чисел. Вывести те элементы в наборе, которые меньше своего левого соседа, и количество K таких элементов.

Особенность этого задания заключается в том, что на каждой итерации цикла, перебирающего элементы последовательности, необходимо знать значение не только текущего элемента, но и предшествующего ему элемента («левого соседа»). Договоримся для большей наглядности хранить значение текущего элемента в переменной B, а значение предыдущего элемента — в переменнной A. Текущий элемент меньше своего левого соседа, если выполняется неравенство A > B; в этом случае надо увеличить на 1 счетчик K:

program Series19;
uses PT4;
var
  N, A, B, I, K: integer;
begin
  Task('Series19');
  GetN(N);
  GetN(A);
  K := 0;
  for I := 2 to N do
  begin
    GetN(B);
    if A > B then
    begin
      PutN(B);
      K := K + 1;
    end;
    A := B;
  end;
  PutN(K);
end.

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

Series21. Дано целое число N (> 1) и набор из N вещественных чисел. Проверить, образует ли данный набор возрастающую последовательность. Если образует, то вывести true, если нет — вывести false.

В данном задании, как и в ранее рассмотренном задании Series19, необходимо сравнивать соседние элементы, поэтому на каждой итерации требуется знать не только значение текущего элемента (B), но и значение предыдущего элемента (A). Кроме того, как и в задании Series17, следует использовать переменную-флаг F логического типа. Инициализируем переменную F значением True; если на какой-либо итерации цикла будет обнаружена пара соседних элементов, нарушающая упорядоченность по возрастанию, то флаг F следует положить равным False. Как только флаг F примет значение False, можно прервать цикл (вызвав процедуру break), так как в анализе оставшихся элементов последовательности в этой ситуации уже не будет необходимости:

program Series21;
uses PT4;
var
  A, B: real;
  N, I: integer;
  F: boolean;
begin
  Task('Series21');
  GetN(N);
  GetR(A);
  F := True;
  for I := 2 to N do
  begin
    GetR(B);
    if A >= B then
    begin
      F := False;
      break;
    end;
    A := B;
  end;
  PutB(F);
end.

Примечание 4. Заметим, что алгоритм решения задачи Series21 реализован таким образом, что при его выполнении не обязательно будут прочитаны все исходные данные (если при анализе очередного элемента будет обнаружено, что он нарушает упорядоченность по возрастанию, то остальные элементы последовательности вводить и анализировать не требуется). Как мы знаем, задачник Programming Taskbook контролирует количество введенных исходных данных (как и количество выведенных результатов), и если программа вводит не все исходные данные, то, как правило, это приводит к сообщению об ошибке «Введены не все требуемые исходные данные». Однако в тех случаях, когда для правильного ответа достаточно проанализировать только часть исходных данных, задачник учитывает это обстоятельство и не выводит сообщение об ошибке, если программа введет достаточно исходных данных для получения правильного ответа.

Минимумы и максимумы: Minmax1, Minmax12

Группа Minmax содержит различные задания, связанные с минимальными и максимальными элементами числовых последовательностей, поэтому она может считаться естественным продолжением группы Series.

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

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

program Minmax1;
uses PT4;
var
  A, Min, Max: real;
  N, I: integer;
begin
  Task('Minmax1');
  GetN(N);
  GetR(A);
  Min := A;
  Max := A;
  for I := 2 to N do
  begin
    GetR(A);
    if A < Min then
      Min := A;
    if A > Max then
      Max := A;
  end;
  PutR(Min);
  PutR(Max);
end.

Переменные Min и Max инициализируются значением первого элемента последовательности, поскольку для последовательности из одного элемента этот элемент является как минимальным, так и максимальным. Так как один элемент последовательности обрабатывается до цикла, параметр цикла I изменяется от 2 до N.

Напомним, что при использовании электронного задачника Programming Taskbook важно следить за тем, чтобы полученные данные были выведены в том порядке, который определен в формулировке задания. В нашем случае необходимо вначале вывести значение Min, а затем — значение Max. Если вывести результаты в другом порядке, то задачник выведет сообщение об ошибочном решении.

Minmax12. Дано целое число N и набор из N чисел. Найти минимальное положительное число из данного набора. Если положительные числа в наборе отсутствуют, то вывести 0.

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

Выясним, как надо модифицировать описанный ранее алгоритм нахождения «обычного» минимума, чтобы с его помощью можно было найти минимум среди всех положительных элементов последовательности. Очевидно, необходимо добавить соответствующее условие отбора в условный оператор цикла: переменную Min следует изменять, если одновременно выполняются два условия: A < Min и A > 0.

Однако этого исправления недостаточно. В самом деле, если предположить, что первый элемент последовательности не является положительным (например, равен -1), то после присваивания значения этого элемента переменной Min возникнет ситуация, при которой ни при каких возможных значениях A двойное условие (A < Min) and (A > 0) не будет истинным: если A неположительное, то ложным будет условие A > 0, а если A положительное, то, поскольку Min не является положительным, ложным будет условие A < Min. Таким образом, если переменная Min будет инициализирована неположительным числом, то ее значение при выполнении цикла уже не сможет измениться, и в результате будет выведено именно это неверное начальное значение.

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

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

Второй способ проще первого; он состоит в инициализации переменной Min значением, которое заведомо больше любого элемента, который может содержаться в исходной последовательности. Действительно, после такой инициализации первая часть сложного условия (A < Min) and (A > 0), проверяемого в цикле, будет истинной при любых значениях A, и поэтому как только в последовательности встретится первый элемент A, удовлетворяющий условию A > 0, станет истинным и все сложное условие. В результате начальное значение переменной Min заменится на значение первого элемента последовательности, удовлетворяющего требуемому условию.

Единственная проблема, возникающая при реализации второго способа, состоит в необходимости выбора значения, заведомо большего любого возможного элемента последовательности. Во многих случаях диапазон возможных значений можно определить, анализируя физический смысл элементов последовательности (например, если элементы последовательности содержат данные о росте некоторой группы людей в сантиметрах, то в качестве значения, гарантированно превосходящего любой элемент, можно взять число 300). Можно использовать максимальное возможное значение для данных требуемого типа. Например, в языке Паскаль предусмотрена константа MaxInt, содержащая максимальное возможное значение для типа integer (при этом минимальным значением для типа integer будет -MaxInt - 1); при обсуждении задания Begin3 в модуле 1 мы уже отмечали, что максимальным значением для типа real является число 1.7e308. При решении задач с использованием задачника Programming Taskbook можно выполнить несколько ознакомительных запусков программы и проанализировать предлагаемые исходные данные. Например, для задач группы Minmax исходные данные вещественного типа никогда не превосходят по модулю числа 10, поэтому вполне допустимо инициализировать переменные Min значением 10, а переменные Max — значением -10.

Итак, второй модификацией базового алгоритма нахождения минимума является новый способ инициализации переменной Min — с помощью значения, заведомо большего любого элемента исходной последовательности. Разумеется, при этом необходимо откорректировать диапазон изменения параметра цикла I, изменив его начальное значение на 1.

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

Приведем программу решения задачи Minmax12, содержащую все описанные выше модификации:

program Minmax12;
uses PT4;
var
  A, Min, Max: real;
  N, I: integer;
begin
  Task('Minmax12');
  GetN(N);
  Min := 10;
  for I := 1 to N do
  begin
    GetR(A);
    if (A < Min) and (A > 0) then
      Min := A;
  end;
  if Min = 10 then
    Min := 0;
  PutR(Min);
end.


Модуль 6. Обработка последовательностей

Учебные задания и указания к ним

Последовательности

Во всех заданиях данной группы предполагается, что исходный набор содержит ненулевое число элементов (в частности, число N всегда больше нуля). В заданиях на обработку нескольких наборов чисел (Series29–Series40) количество наборов K также всегда является ненулевым.

Series1. Даны десять вещественных чисел. Найти их сумму.

Series2. Даны десять вещественных чисел. Найти их произведение.

Series3. Даны десять вещественных чисел. Найти их среднее арифметическое.

Series4. Дано целое число N и набор из N вещественных чисел. Вывести сумму и произведение чисел из данного набора.

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

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

Series7. Дано целое число N и набор из N вещественных чисел. Вывести в том же порядке округленные значения всех чисел из данного набора (как целые числа), а также сумму всех округленных значений.

Series8. Дано целое число N и набор из N целых чисел. Вывести в том же порядке все четные числа из данного набора и количество K таких чисел.

Series9. Дано целое число N и набор из N целых чисел. Вывести в том же порядке номера всех нечетных чисел из данного набора и количество K таких чисел.

Series10. Дано целое число N и набор из N целых чисел. Если в наборе имеются положительные числа, то вывести true; в противном случае вывести false.

Series11. Даны целые числа K, N и набор из N целых чисел. Если в наборе имеются числа, меньшие K, то вывести true; в противном случае вывести false.

Series12. Дан набор ненулевых целых чисел; признак его завершения — число 0. Вывести количество чисел в наборе.

Series13. Дан набор ненулевых целых чисел; признак его завершения — число 0. Вывести сумму всех положительных четных чисел из данного набора. Если требуемые числа в наборе отсутствуют, то вывести 0.

Series14. Дано целое число K и набор ненулевых целых чисел; признак его завершения — число 0. Вывести количество чисел в наборе, меньших K.

Series15. Дано целое число K и набор ненулевых целых чисел; признак его завершения — число 0. Вывести номер первого числа в наборе, большего K. Если таких чисел нет, то вывести 0.

Series16. Дано целое число K и набор ненулевых целых чисел; признак его завершения — число 0. Вывести номер последнего числа в наборе, большего K. Если таких чисел нет, то вывести 0.

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

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

Series19. Дано целое число N (> 1) и набор из N целых чисел. Вывести те элементы в наборе, которые меньше своего левого соседа, и количество K таких элементов.

Series20. Дано целое число N (> 1) и набор из N целых чисел. Вывести те элементы в наборе, которые меньше своего правого соседа, и количество K таких элементов.

Series21. Дано целое число N (> 1) и набор из N вещественных чисел. Проверить, образует ли данный набор возрастающую последовательность. Если образует, то вывести true, если нет — вывести false.

Series22. Дано целое число N (> 1) и набор из N вещественных чисел. Если данный набор образует убывающую последовательность, то вывести 0; в противном случае вывести номер первого числа, нарушающего закономерность.

Series23. Дано целое число N (> 2) и набор из N вещественных чисел. Набор называется пилообразным, если каждый его внутренний элемент либо больше, либо меньше обоих своих соседей (то есть является «зубцом»). Если данный набор является пилообразным, то вывести 0; в противном случае вывести номер первого элемента, не являющегося зубцом.

Series24. Дано целое число N и набор из N целых чисел, содержащий по крайней мере два нуля. Вывести сумму чисел из данного набора, расположенных между последними двумя нулями (если последние нули идут подряд, то вывести 0).

Series25. Дано целое число N и набор из N целых чисел, содержащий по крайней мере два нуля. Вывести сумму чисел из данного набора, расположенных между первым и последним нулем (если первый и последний нули идут подряд, то вывести 0).

Series26. Даны целые числа K, N и набор из N вещественных чисел: A1, A2, …, AN. Вывести K-e степени чисел из данного набора:

(A1)K, (A2)K, …, (AN)K.

Series27. Дано целое число N и набор из N вещественных чисел: A1, A2, …, AN. Вывести следующие числа:

A1, (A2)2, …, (AN–1)N–1, (AN)N.

Series28. Дано целое число N и набор из N вещественных чисел: A1, A2, …, AN. Вывести следующие числа:

(A1)N, (A2)N–1, …, (AN–1)2, AN.

Series29. Даны целые числа K, N, а также K наборов целых чисел по N элементов в каждом наборе. Вывести общую сумму всех элементов, входящих в данные наборы.

Series30. Даны целые числа K, N, а также K наборов целых чисел по N элементов в каждом наборе. Для каждого набора вывести сумму его элементов.

Series31. Даны целые числа K, N, а также K наборов целых чисел по N элементов в каждом наборе. Найти количество наборов, содержащих число 2. Если таких наборов нет, то вывести 0.

Series32. Даны целые числа K, N, а также K наборов целых чисел по N элементов в каждом наборе. Для каждого набора вывести номер его первого элемента, равного 2, или число 0, если в данном наборе нет двоек.

Series33. Даны целые числа K, N, а также K наборов целых чисел по N элементов в каждом наборе. Для каждого набора вывести номер его последнего элемента, равного 2, или число 0, если в данном наборе нет двоек.

Series34. Даны целые числа K, N, а также K наборов целых чисел по N элементов в каждом наборе. Для каждого набора выполнить следующее действие: если в наборе содержится число 2, то вывести сумму его элементов; если в наборе нет двоек, то вывести 0.

Series35. Дано целое число K, а также K наборов ненулевых целых чисел. Признаком завершения каждого набора является число 0. Для каждого набора вывести количество его элементов. Вывести также общее количество элементов во всех наборах.

Series36. Дано целое число K, а также K наборов ненулевых целых чисел. Каждый набор содержит не менее двух элементов, признаком его завершения является число 0. Найти количество наборов, элементы которых возрастают.

Series37. Дано целое число K, а также K наборов ненулевых целых чисел. Каждый набор содержит не менее двух элементов, признаком его завершения является число 0. Найти количество наборов, элементы которых возрастают или убывают.

Series38. Дано целое число K, а также K наборов ненулевых целых чисел. Каждый набор содержит не менее двух элементов, признаком его завершения является число 0. Для каждого набора выполнить следующее действие: если элементы набора возрастают, то вывести 1; если элементы набора убывают, то вывести –1; если элементы набора не возрастают и не убывают, то вывести 0.

Series39. Дано целое число K, а также K наборов ненулевых целых чисел. Каждый набор содержит не менее трех элементов, признаком его завершения является число 0. Найти количество пилообразных наборов (определение пилообразного набора дано в задании Series23).

Series40. Дано целое число K, а также K наборов ненулевых целых чисел. Каждый набор содержит не менее трех элементов, признаком его завершения является число 0. Для каждого набора выполнить следующее действие: если набор является пилообразным (см. задание Series23), то вывести количество его элементов; в противном случае вывести номер первого элемента, который не является зубцом.

Минимумы и максимумы

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

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

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

Minmax2. Дано целое число N и набор из N прямоугольников, заданных своими сторонами — парами чисел (a, b). Найти минимальную площадь прямоугольника из данного набора.

Minmax3. Дано целое число N и набор из N прямоугольников, заданных своими сторонами — парами чисел (a, b). Найти максимальный периметр прямоугольника из данного набора.

Minmax4. Дано целое число N и набор из N чисел. Найти номер минимального элемента из данного набора.

Minmax5. Дано целое число N и набор из N пар чисел (m, v) — данные о массе m и объеме v деталей, изготовленных из различных материалов. Вывести номер детали, изготовленной из материала максимальной плотности, а также величину этой максимальной плотности. Плотность P вычисляется по формуле

P = m/v.

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

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

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

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

Minmax10. Дано целое число N и набор из N целых чисел. Найти номер первого экстремального (то есть минимального или максимального) элемента из данного набора.

Minmax11. Дано целое число N и набор из N целых чисел. Найти номер последнего экстремального (то есть минимального или максимального) элемента из данного набора.

Minmax12. Дано целое число N и набор из N чисел. Найти минимальное положительное число из данного набора. Если положительные числа в наборе отсутствуют, то вывести 0.

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

Minmax14. Дано число B (> 0) и набор из десяти чисел. Вывести минимальный из тех элементов набора, которые больше B, а также его номер. Если чисел, больших B, в наборе нет, то дважды вывести 0.

Minmax15. Даны числа B, C (0 < B < C) и набор из десяти чисел. Вывести максимальный из элементов набора, содержащихся в интервале (B, C), и его номер. Если требуемые числа в наборе отсутствуют, то дважды вывести 0.

Minmax16. Дано целое число N и набор из N целых чисел. Найти количество элементов, расположенных перед первым минимальным элементом.

Minmax17. Дано целое число N и набор из N целых чисел. Найти количество элементов, расположенных после последнего максимального элемента.

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

Minmax19. Дано целое число N и набор из N целых чисел. Найти количество минимальных элементов из данного набора.

Minmax20. Дано целое число N и набор из N целых чисел. Найти общее количество экстремальных (то есть минимальных и максимальных) элементов из данного набора.

Minmax21. Дано целое число N (> 2) и набор из N чисел — значений некоторой величины, полученных в N опытах. Найти среднее значение этой величины. При вычислении среднего значения не учитывать минимальное и максимальное из имеющихся в наборе значений.

Minmax22. Дано целое число N (> 2) и набор из N чисел. Найти два наименьших элемента из данного набора и вывести эти элементы в порядке возрастания их значений.

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

Minmax24. Дано целое число N (> 1) и набор из N чисел. Найти максимальную сумму двух соседних чисел из данного набора.

Minmax25. Дано целое число N (> 1) и набор из N чисел. Найти номера двух соседних чисел из данного набора, произведение которых является минимальным, и вывести вначале меньший, а затем больший номер.

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

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

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

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

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

Указания

В тексте указаний используется сокращенное обозначение для диапазона заданий, включающее имя темы, номер начального и номер конечного задания (например, диапазон заданий от Series1 до Series7 обозначается следующим образом: Series1–7).

Series1–7. Простейшие задачи на обработку последовательностей, использующие стандартные алгоритмы нахождения суммы и произведения. См. решение Series1, прочие задачи решаются аналогично. В Series5 для выделения целой части вещественного числа можно использовать либо функцию Int(X) (которая возвращает целую часть X в виде вещественного числа с нулевой дробной частью), либо функцию Trunc(X) (которая возвращает целую часть X в виде целого числа). В Series6 для выделения дробной части числа достаточно вычесть из данного числа его целую часть; можно также использовать специальную функцию Паскаля Frac(X), предназначенную для нахождения дробной части X. Для округления числа в Series7 используйте функцию Round(X), возвращающую округленное значение X в виде целого числа.

Series8–9. Задания на обработку элементов, удовлетворяющих некоторому условию. В Series9 для определения номера текущего элемента набора воспользуйтесь параметром цикла.

Series10–11. Задания на проверку наличия в наборе требуемых элементов. При обнаружении требуемого элемента цикл, в котором обрабатываются элементы, следует прервать, используя процедуру break.

Series12–16. Особенность этих заданий состоит в том, что перед началом ввода элементов набора не известно их количество: признаком завершения набора является число 0, расположенное после последнего элемента набора (подчеркнем, что число 0 в набор не входит). Для решения этих заданий следует использовать цикл с условием. См. решение Series15. Для получения решения Series16 достаточно в решении Series15 убрать процедуру break из цикла while.

Series17. См. решение этой задачи.

Series18–22. Для выполнения этих заданий необходимо на каждом этапе обработки исходного набора иметь доступ не только к текущему (только что введенному) элементу, но и к предыдущему элементу, поскольку их необходимо сравнивать между собой. См. решения Series19 и Series21, прочие задачи решаются аналогично.

Series23. Ср. с Series18–22. Удобно на каждом этапе обработки исходного набора иметь доступ к трем последовательным элементам A, B, C; в этом случае легко проверить, является ли средний элемент зубцом (достаточно сравнить знаки выражений B – A и B – C). После обработки текущей тройки элементов значение B необходимо переместить в переменную A, значение C — в переменную B, а очередной элемент набора ввести в переменную C.

Series24–25. Сложность этих заданий состоит в том, что при обработке элементов, расположенных в наборе после первого нуля, заранее не известно, надо ли включать их в требуемую сумму (поскольку мы еще не знаем, сколько нулей будет обнаружено в наборе). Опишем алгоритм решения Series24. Используем две переменные S и T, инициализируя их нулевыми значениями. Считываем начальные элементы исходного набора, пока не обнаружим первый нуль. После этого в цикле перебираем остальные элементы набора, причем если очередной элемент отличен от нуля, то он добавляется к сумме T, а если очередной элемент равен нулю, то текущее значение T записывается в S, а переменная T обнуляется. В результате после перебора всех элементов исходного набора в переменной S будет содержаться требуемая сумма. Алгоритм для Series25 имеет единственное отличие: при обнаружении очередного нуля текущее значение T должно добавляться к прежнему содержимому S. Для считывания начальных элементов набора (до первого нуля) можно использовать вспомогательный цикл с условием. Можно также использовать единственный цикл для считывания всех элементов набора, но в этом случае необходимо по-разному обрабатывать элементы, прочитанные до и после обнаружения первого нуля.

Series26–28. Используйте вложенные циклы: во внутреннем цикле вычисляются степени слагаемых, а во внешнем найденные степени добавляются к сумме. В Series27–28 дополнительно следует учитывать, что число итераций внутреннего цикла зависит от номера итерации внешнего цикла (например, в Series27 параметр J внутреннего цикла следует менять от 1 до I, где I — параметр внешнего цикла).

Series29–34. Задания на обработку нескольких числовых наборов одинакового размера. Используйте внешний цикл (с параметром, меняющимся от 1 до K) для перебора различных исходных наборов. Для обработки элементов очередного набора потребуется вложенный цикл, параметр которого будет меняться от 1 до N. В этих заданиях важно правильно определить место инициализации используемых переменных. Например, в Series29 переменная для хранения суммы элементов всех наборов должна инициализироваться нулем один раз перед началом выполнения внешнего цикла, а в Series30 переменная для хранения суммы элементов текущего набора должна принимать нулевое значение в начале каждой итерации внешнего цикла (перед выполнением вложенного цикла).

Series35–40. Задания на обработку нескольких числовых наборов различного размера. Перед началом ввода элементов очередного набора не известно их количество, поэтому в данном случае, в отличие от Series29–34, в качестве вложенного цикла следует использовать цикл с условием (см. указание к Series12–16). По поводу инициализации вспомогательных переменных см. указание к Series29–34. Ср. Series36 с Series21, Series39–40 с Series23. Алгоритм, описанный в указании к Series23, можно использовать и в Series37–38, если заметить, что ни один из внутренних элементов возрастающего или убывающего набора не может быть зубцом (элемент называется внутренним, если он имеет двух соседей: слева и справа). Таким образом, для решения Series37 достаточно подсчитать количество наборов, не имеющих внутренних зубцов. При решении Series38 для упорядоченных наборов требуется дополнительно выяснить «способ упорядоченности»: по возрастанию или убыванию. Для этого достаточно сравнить два последних элемента набора (эти элементы сохранятся во вспомогательных переменных после выхода из вложенного цикла).

Minmax1–3. См. решение Minmax1. В Minmax2–3 элементы набора, в котором ищется минимум/максимум, необходимо вычислять по имеющимся исходным данным.

Minmax4–11. В программе необходимо использовать не только переменные Min/Max для хранения самих минимальных/максимальных элементов (см. решение Minmax1), но и дополнительные переменные для хранения их номеров (например, NMin и NMax). В случае, когда имеется несколько минимальных/максимальных элементов и требуется найти номер первого или последнего из них, важно выбрать правильную операцию отношения (<, > или <=, >=) при сравнении исходных данных с переменной Min/Max.

Minmax12–15. Задания на нахождение условного минимума/максимума. См. решение Minmax12, прочие задачи решаются аналогично.

Minmax16–18. Решение сводится к нахождению номера требуемого минимального/максимального элемента (см. также указание к Minmax4–11).

Minmax19–20. Используйте переменную-счетчик для хранения количества найденных минимумов/максимумов. Этот счетчик необходимо корректировать в двух ситуациях: при изменении значения переменной Min/Max (содержащей значение наименьшего/наибольшего элемента из уже просмотренных — см. решение Minmax1) и при появлении элемента, значение которого совпадает с текущим значением Min/Max.

Minmax21. Поскольку заранее неизвестно, какой элемент набора окажется минимальным (максимальным), следует просуммировать все исходные элементы, одновременно определяя минимальный и максимальный из них. После обработки всех исходных данных достаточно вычесть из полученной суммы минимальный и максимальный элементы и разделить результат на N – 2.

Minmax22–23. Для решения Minmax22 каждый элемент исходного набора надо сравнивать не только с переменной Min1, в которой хранится значение наименьшего из уже просмотренных элементов, но и с переменной Min2, содержащей значение, следующее за наименьшим (из уже просмотренных). Более точно: следует проверять, в каком из промежутков (–¥, Min1), (Min1, Min2), (Min2, +¥) содержится очередной элемент исходных данных, и в зависимости от результата корректировать значения Min1 и Min2. Важно также позаботиться о правильной инициализации этих переменных (например, можно инициализировать обе переменные одним и тем же значением, которое заведомо больше всех элементов исходного набора). В Minmax23 следует использовать три вспомогательные переменные: Max1, Max2, Max3.

Minmax24–28. В этих заданиях основная трудность состоит не в реализации собственно алгоритма нахождения минимума/максимума, а в нахождении величин, из которых надо выбрать минимальное/максимальное значение. Если при решении задачи не использовать массив, то текущий (анализируемый) элемент исходных данных необходимо сохранять во вспомогательной переменной, которую в дальнейшем использовать при анализе следующего элемента (ср. с решением Series19).

Minmax29–30. В этих заданиях алгоритм нахождения минимума/максимума используется дважды: для отбора минимальных/максимальных элементов из исходного набора данных и для определения самой длинной/короткой последовательности таких элементов. Напомним, что требуемый результат надо получить после однократного просмотра исходного набора данных.


Модуль 6. Обработка последовательностей

Контрольные вопросы

Для каждого вопроса щелкните мышью на радиокнопке с номером варианта ответа, который, по вашему мнению, является правильным. После того как вы ответите на все вопросы, проверьте правильность ответов, нажав на кнопку «Проверка».

1. Какой оператор языка Паскаль предназначен для досрочного завершения текущей итерации цикла?

(1) | continue | (2) | break
(3) | exit | (4) | finally

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

(1) | Найти сумму положительных элементов последовательности (если положительные элементы отсутствуют, то вывести 0). | (2) | Найти номер последнего положительного элемента последовательности (вывести сообщение о том, что положительные элементы отсутствуют).
(3) | Вывести положительные элементы последовательности в обратном порядке. | (4) | Вывести True, если последовательность содержит положительные элементы, и False в противном случае.

3. Укажите выражение, позволяющее получить из вещественного числа x его целую часть (типа integer).

(1) | Int(x) | (2) | Round(x)
(3) | Frac(x) | (4) | Trunc(x)

4. Дано начало фразы:

Для правильного решения задачи с использованием задачника Programming Taskbook необходимо, чтобы …

Какой вариант продолжения этой фразы НЕ соответствует верному утверждению?

(1) | … были введены все исходные данные | (2) | … были выведены все результирующие данные
(3) | … был введен хотя бы один элемент исходных данных | (4) | … был выведен хотя бы один элемент результирующих данных

5. Укажите, какое из приведенных выражений позволяет определить минимальное значение для типа integer.

(1) | -MaxInt + 2 | (2) | -MaxInt + 1
(3) | -MaxInt | (4) | -MaxInt - 1

6. Укажите правильный фрагмент алгоритма, позволящего определить количество элементов целочисленной последовательности размера 10, которые меньше своего правого соседа (все использованные переменные имеют тип integer).

(1)
C := 0;
read(A);
for I := 1 to 10 do
begin
  read(B);
  if A > B then
    C := C + 1;
  A := B;
end;
writeln(C);
(2)
C := 0;
read(A);
for I := 2 to 10 do
begin
  read(B);
  if A < B then
    C := C + 1;
  A := B;
end;
writeln(C);
(3)
C := 0;
read(A);
for I := 1 to 10 do
begin
  read(B);
  if A < B then
    C := C + 1;
  B := A;
end;
writeln(C);
(4)
C := 0;
read(A);
for I := 2 to 10 do
begin
  read(B);
  if A > B then
    C := C + 1;
  B := A;
end;
writeln(C);


Модуль 6. Обработка последовательностей

Итоговое задание

Ввести с клавиатуры положительное целое число N (при вводе отрицательного или нулевого числа положить N равным 10). Сгенерировать с помощью датчика случайных чисел набор из N вещественных чисел, лежащих в диапазоне от –100 до 100. Вывести каждое из чисел на отдельной экранной строке, перед каждым числом вывести его порядковый номер (нумеровать числа от 1), а после числа — его квадрат и его округленное значение (как целое). Для вывода каждого из целых чисел использовать 5 экранных позиций; для вывода каждого из вещественных чисел использовать 10 экранных позиций, из которых 2 позиции отвести под вывод дробной части.

После вывода всех чисел вывести на экран следующие данные (для вывода чисел использовать минимальное необходимое число экранных позиций, для вещественных чисел указывать 2 цифры в дробной части):

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

При выполнении задания не использовать массивы.

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

N = 16
    1     13.31    177.22   13
    2    -52.74   2781.94  -53
    3     99.10   9820.18   99
    4    -65.60   4303.26  -66
    5     68.81   4734.86   69
    6     67.27   4525.23   67
    7     26.44    699.14   26
    8    -19.26    370.98  -19
    9     14.80    218.94   15
   10     99.73   9945.51  100
   11    -43.37   1880.88  -43
   12    -52.43   2748.97  -52
   13     10.19    103.90   10
   14     -7.88     62.15   -8
   15    -58.49   3420.64  -58
   16     16.15    260.91   16
Sum of all numbers: 116.03
Sum of positive numbers: 415.80
Count of negative numbers: 7
Maximal sequence of positive numbers begins with the number 5 and has length 3

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


Приложение. Вспомогательные процедуры задачника Programming Taskbook

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

Инициализация заданий, ввод-вывод данных

procedure Task(Name: string);

Процедура инициализирует задание с именем Name. Она должна вызываться в начале программы, выполняющей это задание (до вызова процедур ввода-вывода Get–Put). Если в программе, подключившей модуль PT4, не указана процедура Task, то при запуске программы будет выведено окно с сообщением «Не вызвана процедура Task с именем задания».

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

Имя задания Name должно включать имя группы заданий и порядковый номер в пределах группы (например, 'Begin3'). Регистр букв в имени группы может быть произвольным. Если указана неверная группа, то программа выведет сообщение об ошибке, в котором будут перечислены названия всех имеющихся групп. Если указан недопустимый номер задания, то программа выведет сообщение, в котором будет указан диапазон допустимых номеров для данной группы. Если после имени задания в параметре Name указан символ «?» (например, 'Begin3?'), то программа будет работать в демонстрационном режиме, который позволяет быстро ознакомиться с формулировками и вариантами исходных и контрольных данных для всех заданий выбранной группы.

Начиная с версии 4.8 задачника, процедура Task может также использоваться для генерации и вывода на экран html-страницы с текстом задания или группы заданий. Для этого необходимо указать в качестве параметра Name имя конкретного задания или группы заданий и символ «#», например, 'Begin3#' или 'Begin#'.

procedure GetB(var A: boolean);
procedure GetN(var A: integer);
procedure GetR(var A: real);
procedure GetC(var A: char);
procedure GetS(var A: string);

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

Используемая процедура ввода должна соответствовать типу очередного элемента исходных данных; в противном случае выводится сообщение об ошибке «Неверно указан тип при вводе исходных данных» (такое сообщение будет выведено, например, если очередной элемент данных является символом, а для его ввода используется процедура GetN).

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

В варианте задачника для среды PascalABC.NET ввод исходных данных можно выполнять с помощью стандартной процедуры Read, при этом один вызов процедуры можно использовать для ввода нескольких элементов исходных данных, перечисляя их через запятую, например, Read(a, b, c).

procedure PutB(A: boolean);
procedure PutN(A: integer);
procedure PutR(A: real);
procedure PutC(A: char);
procedure PutS(A: string);

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

В отличие от процедур группы Get, в качестве параметра процедур группы Put можно указывать не только переменные, но и выражения (в частности, константы соответствующего типа). Используемая процедура должна соответствовать типу очередного элемента результирующих данных, в противном случае выводится сообщение об ошибке «Неверно указан тип при выводе результатов».

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

В варианте задачника для среды PascalABC.NET вывод результатов можно выполнять с помощью стандартной процедуры Write, при этом один вызов процедуры можно использовать для вывода нескольких элементов результирующих данных, перечисляя их через запятую, например, Write(a, b, c).

Вывод отладочной информации

Описываемые далее отладочные средства появились в версии 4.9 задачника Programming Taskbook. С их помощью можно выводить отладочную информацию непосредственно в окно задачника (в специальный раздел отладки).

procedure Show(S: string);

Отображает текстовую строку S в разделе отладки окна задачника.

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

Строка S может содержать явные команды перехода на новую экранную строку. В качестве таких команд можно использовать или символ с кодом 13 («возврат каретки»), или символ с кодом 10 («переход на новую строку»), или их комбинацию в указанном порядке (#13#10).

procedure Show([S: string;] A: integer[; W: integer]);
procedure Show([S: string;] A: real[; W: integer]);

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

При вызове приведенных вариантов можно не указывать один или оба параметра, заключенные в квадратные скобки.

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

Числовой параметр A определяет выводимое число.

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

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

procedure ShowLine([S: string]);
procedure ShowLine([S: string;] A: integer[; W: integer]);
procedure ShowLine([S: string;] A: real[; W: integer]);

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

procedure HideTask;

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

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

procedure SetPrecision(N: integer);

Процедура предназначена для настройки формата вывода вещественных отладочных данных. Если параметр N положителен, то он определяет количество выводимых дробных разрядов; при этом число выводится в формате с фиксированной точкой. Если параметр N равен нулю, то число выводится в формате с плавающей точкой (экспоненциальном формате); при этом число дробных знаков для экспоненциального формата определяется шириной поля вывода (т. е. параметром W процедуры Show или ShowLine). При отрицательных значениях параметра N выполняется та же настройка, что и при N = 0.

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


Литература

  1. Абрамов С. А., Гнездилова Г. Г., Капустина Е. Н., Селюн М. И. Задачи по программированию. — М.: Наука, 1988. — 224 с.
  2. Абрамян М. Э., Михалкович С. С. Основы программирования на языке Паскаль: Скалярные типы данных, управляющие операторы, процедуры и функции, работа с графикой в системе PascalABC.NET. 5-е изд. — Ростов н/Д.: «ЦВВР», 2009. — 223 с.
  3. Бабушкина И. А., Бушмелева Н. А., Окулов С. М., Черных С. Ю. Практикум по Турбо Паскалю. — М.: АБФ, 1998. — 384 с.
  4. Гусева А. И. Учимся программировать: PASCAL 7.0. Задачи и методы их решения. — М.: Диалог-МИФИ, 1997. — 256 с.
  5. Дагене В. А., Григас Г. К., Аугутис К. Ф. 100 задач по программированию. — М.: Просвещение, 1993. — 255 с.
  6. Задачи по программированию / С. М. Окулов, Т. В. Ашихмина, Н. А. Бушмелева и др.; Под ред. С. М. Окулова. — М.: БИНОМ. Лаборатория знаний, 2006. — 820 с.
  7. Златопольский Д. М. Я иду на урок информатики: Задачи по программированию. 7–11 классы: Книга для учителя. — М.: «Первое сентября», 2001. — 208 с.
  8. Касьянов В. Н., Сабельфельд В. К. Сборник заданий по практикуму на ЭВМ. — М.: Наука, 1986. — 272 с.
  9. Пильщиков В. Н. Сборник упражнений по языку Паскаль. — М.: Наука, 1989. — 160 с.
  10. Программирование на языке Паскаль: задачник / Под ред. О. Ф. Усковой. — СПб.: Питер, 2002. — 336 с.
  11. Юркин А. Г. Задачник по программированию. — СПб.: Питер, 2002. — 192 с.