Математическая логика и теория алгоритмов


СРЕДНЕЕ ПРОФЕССИОНАЛЬНОЕ ОБРАЗОВАНИЕ
И. Г.СЕМАКИН, А. П. ШЕСТАКОВ

УЧЕБНИКДопущено
Министерством образования Российской Федерации
в качестве учебника для студентов
образовательных учреждений среднего профессионального образования
ACADEMA
3-е издание, стереотипное
Москва
Издательский центр «Академия»
2012
УДК 681.3.06(075.32) ББК22.18я723С30Рецензенты:
преподаватель спецдисциплин Московского государственного колледжаинформационных технологий, председатель цикловой комиссии
Я. В. Валиулина;
преподаватель цикловой комиссии «Вычислительная техника» Московского
колледжа железнодорожного транспорта А. А. Янушевская
Семакин И. Г.
С30Основы алгоритмизации и программирования : учебникдля студ. учреждений сред. проф. образования / И. Г. Семакин, А. П. Шестаков. — 3-е изд., стер. — М. : Издательский центр «Академия», 2012. — 400 с.ISBN 978-5-7695-8957-7Рассмотрены основы структурной методики построения алгоритмов и программирования на базе языка Паскаль (версия ТурбоПаскаль (7.0), а также основные понятия объектно-ориентированного программирования и его реализация на языке ТурбоПаскаль. Описана интегрированная среда программирования Delphi и рассмотрены визуальная технология создания графического интерфейса программ и разработка программных модулей в этой среде.
Для студентов учреждений среднего профессионального образования.
УДК 681.3.06(075.32) ББК 22.18я723Оригинал-макет данного издания является собственностью Издательскогоцентра «Академия», и его воспроизведение любым способом без согласия
правообладателя запрещается
Семакин И. Г.. Шестаков
2008
ISBN 978-5-7695-8957-7
© Образовательно-издательский центр «Академия», 2008 © Оформление. Издательский центр «Академия», 2008
ПРЕДИСЛОВИЕ
Программирование все в большей степени становится занятием лишь для профессионалов. Объявленный в середине 1980-х гг. лозунг «Программирование — вторая грамотность» остался в прошлом. В понятие «компьютерная грамотность» сегодня входит, прежде всего, навык использования многообразных средств информационных технологий. При решении той или иной информационной задачи сначала следует попытаться подобрать адекватное программное средство (электронные таблицы, системы управления базами данных, математические пакеты и др.), и только если эти средства не позволяют решить поставленную задачу, использовать универсальные языки программирования.
Различают программистов двух категорий: прикладных и системных. Системные программисты — это разработчики базовых программных средств ЭВМ (операционных систем, трансляторов, сервисных средств и т.д.), являющиеся профессионалами высочайшего уровня. Прикладные программисты разрабатывают средства программного обеспечения ЭВМ, предназначенные для решения задач в отдельных областях деятельности (науке, технике, производстве, сфере обслуживания, обучении и т.д.). Требования к качеству прикладных программ, так же высоки, как и к качеству системных. Любая программа должна не только правильно решать задачу, но и иметь современный интерфейс, быть высоконадежной, дружественной к пользователю и т.д. Только такие программы могут выдержать конкуренцию на мировом рынке программных продуктов.
По мере развития компьютерной техники развивались методика и технология программирования. Сначала возникли командное и операторное программирование, в 1960-х гг. бурно развивались структурное программирование, линии логического и функционального программирования, а в настоящее время широко распространяются объектно-ориентированное и визуальное программирование.
это освоение основ его структурной методики с
Задача, которую следует ставить в начале изучения программирования,
помощью языка Паскаль, который его автор — швейцарский профессор Никлаус Вирт — создавал именно для этого. Структурная методика до настоящего времени остается основой программистской культуры. Не освоив ее, человек, взявшийся изучать программирование, не имеет никаких шансов стать профессионалом.
3
Реализации языка Паскаль в версиях фирмы Borland для IBM, известные под названием Turbo Pascal, значительно расширили язык по сравнению с вариантом Н. Вирта. Начиная с версии 5.5 TurboPascal стал также и языком объектного программирования.
Содержание главы 2 настоящего учебника ориентировано на глубокое усвоение учащимися базовых понятий языков программирования высокого уровня в их реализации на языке Паскаль, что значительно облегчит изучение других языков программирования. В главе 4 излагаются основы объектно-ориентированного программирования на примере их реализации на языке Паскаль. Здесь же рассматривается язык программирования Delphi, являющийся объектно-ориентированным расширением языка Паскаль с реализацией технологии визуального программирования.
При подготовке к изучению данного курса желательно усвоение учащимися основ алгоритмизации в рамках школьного базового курса информатики. Обычно в школе алгоритмизация изучается с использованием учебных исполнителей, позволяющих успешно освоить основы структурной методики:
построение алгоритмов из базовых структур;
• применение метода последовательной детализации. Желательно также иметь представление об архитектуре ЭВМ на уровне машинных команд (достаточно на модельных примерах учебных компьютеров, изучаемых в школьной информатике, т.е. не обязательно знание реальных языков команд или ассемблера). Это позволяет усвоить основные понятия программирования (переменной, присваивания); «входить в положение транслятора» и не делать ошибок, даже не помня каких-то деталей синтаксиса языка; предвидеть те «подводные камни», на которые может «напороться» программа в процессе выполнения. По существу все эти качества и отличают профессионального программиста от дилетанта.
способность воспри
хорошо
программы. Неред
чувство
Еще одно качество профессионала мать красоту программы, т.е. получать
помогает интуитивно отличить неправильную программу от правильной. Однако основным критерием оценки программы должна быть, безусловно, не интуиция, а грамотно организованное тестирование.
Процесс изучения и практического освоения программирования подразделяется на три части:
изучение методов построения алгоритмов; изучение языка программирования;
изучение и практическое освоение определенной системы программирования.
Решению задач первой части посвящены главы 1 и 3 данног* учебника. В главе 1 даются основные, базовые, понятия и принци пы построения алгоритмов работы с величинами. В главе 3 излага
4ются некоторые известные методики полного построения алгоритмов, рассматриваются проблемы тестирования программ и оценки сложности алгоритмов.
Языки программирования ТурбоПаскаль и Delphi излагаются соответственно в главах 2 и 4 учебника. Однако подчеркнем, что анная книга — это, прежде всего, учебник по программированию, а не по языкам Паскаль и Delphi, поэтому исчерпывающего описания данных языков вы здесь не найдете, они излагаются в объеме, необходимом для начального курса программирования. Более подробное описание этих языков можно найти в книгах, указанных в списке литературы.
В данном учебнике нет инструкций по работе с конкретными системами программирования для изучаемых языков, с ними студенты должны познакомиться в процессе выполнения практических работ на ЭВМ, используя специальную литературу.
В главе 5 учебника содержатся задачи по программированию, которые можно использовать для организации практических и лабораторных занятий на любом из изучаемых языков.
ГЛАВА 1
ОСНОВНЫЕ ПРИНЦИПЫ АЛГОРИТМИЗАЦИИИ ПРОГРАММИРОВАНИЯАлгоритмы и величины
Этапы решения задачи на ЭВМ. Работа по решению любой задачи с использованием компьютера включает в себя следующие
шесть этапов:
Постановка задачи.
Формализация задачи.
Построение алгоритма.
Составление программы на языке программирования.
Отладка и тестирование программы.
Проведение расчетов и анализ полученных результатов.
Часто эту последовательность называют технологической цепочкой решения задачи на ЭВМ (непосредственно к программированию из этого списка относятся п. 3...5).
На этапе постановки задачи следует четко определить, что дано и что требуется найти. Важно описать полный набор исходных данных, необходимых для решения задачи.
На этапе формализации чаще всего задача переводится на язык математических формул, уравнений и отношений. Если решение задачи требует математического описания какого-то реального объекта, явления или процесса, то ее формализация равносильна получению соответствующей математической модели.
Третий этап — это построение алгоритма. Опытные программисты часто сразу пишут программы на определенном языке, не прибегая к каким-либо специальным средствам описания алгоритмов (блок-схемам, псевдокодам), однако в учебных целях полезно сначала использовать эти средства, а затем переводить полученный алгоритм на язык программирования.
Первые три этапа — это работа без компьютера. Последующие два этапа — это собственно программирование на определенном языке в определенной системе программирования. На последнем — шестом — этапе разработанная программа уже используется в практических целях.
Таким образом, программист должен уметь строить алгоритмы, знать языки программирования, уметь работать в соответствующей системе программирования.
6
Основой профессиональной грамотности программиста является развитое алгоритмическое мышление.
Понятие алгоритма. Одним из фундаментальных понятий в информатике является понятие алгоритма. Сам термин «алгоритм», заимствованный из математики, происходит от лат. Algorithmi написание имени Мухамеда аль-Хорезми (787—850), выдающегося математика средневекового Востока. В XII в. был осуществлен латинский перевод его математического трактата, из которого европейцы узнали о десятичной позиционной системе счисления и правилах арифметики многозначных чисел. Именно эти правила в то время называли алгоритмами. Сложение, вычитание, умножение «столбиком», деление «уголком» многозначных чисел — это первые алгоритмы в математике. Правила алгебраических преобразований и вычисление корней уравнений также можно отнести к математическим алгоритмам.
В наше время понятие алгоритма трактуется шире. Алгоритм это последовательность команд управления каким-либо исполнителем. В школьном курсе информатики с понятием алгоритма и методами построения алгоритмов ученики знакомятся на примерах учебных исполнителей: Робота, Черепахи, Чертежника и др. Эти исполнители ничего не вычисляют. Они создают рисунки на экране, перемещаются в лабиринтах, перетаскивают предметы с места на место. Таких исполнителей принято называть исполнителями, работающими в обстановке.
В разделе «Программирование» информатики изучаются методы программного управления работой ЭВМ, т.е. в качестве исполнителя выступает компьютер. Компьютер работает с величинами — различными информационными объектами: числами, символами, кодами и др., поэтому алгоритмы, предназначенные для управления компьютером, называются алгоритмами работы с величинами.
Данные и величины. Совокупность величин, с которыми работает компьютер, принято называть данными. По отношению к программе различают исходные, окончательные {результаты) и промежуточные данные, которые получают в процессе вычислений (рис. 1.1).
ми
корни уравнения х>, х2, а промежуточными данными
ди
Например, при решении квадратного уравнения ах2 + Ьх + с = 0 исходными данными являются коэффициенты а, Ь, с, результата
Ь2
4ас.
Исходные данные
Рис. 1.1. Уровни данных относительно программы
Результаты
7
скриминант уравнения D
Для успешного освоения программирования необходимо усвоить следующее правило: всякая величина занимает свое определенное место в памяти ЭВМ, иногда говорят — ячейку памяти. Термин «ячейка» для архитектуры современных ЭВМ несколько устарел, однако в учебных целях его удобно использовать.
Любая величина имеет три основных свойства: имяу значение и тип. На уровне команд процессора величина идентифицируется адресом ячейки памяти, в которой она хранится. В алгоритмах и языках программирования величины подразделяются на константы и переменные. Константа — неизменная величина, и в алгоритме она представляется собственным значением, например: 15, 34.7, k, True и др. Переменные величины могут изменять свои значения
Таблица 1.1
Тип
Значения
Операции
Внутреннее
представление
Целые
Целые положи- Арифметические тельные и отрица- операции с целыми
Формате фиксированной точкой
Основные типы данных
тельные числа в
числами: сложение,
некотором диапа- вычитание, умноже-
зоне, например: 23, -12, 387
Веществен
Любые (целые и Арифметические
Формате плава-
ние, целое деление и деление с остатком. Операции отношений (<, >, = и др.)
ные
дробные) числа в операции. Операции |ющей точкой некотором диапа- отношений зоне, например:
2.5, -0.01, 45.0,
Логические
True (истина) False (ложь)
Логические
ИЛИ
(or), НЕТ (подоперации отношений
1
о
True;
False
Символьные
Коды таблицы символьной кодировки, например: ASCII один символ
байт; Unicode один символ
байт
8
З.бх 109
в ходе выполнения программы и представляются в алгоритме символическими именами — идентификаторами, например: X, S2, cod 15 и др. Любые константы и переменные занимают ячейку памяти, а значения этих величин определяются двоичным кодом в этой ячейке.
Теперь о типах величин — типах данных — понятии, которое встречается при изучении в курсе информатики баз данных и электронных таблиц. Это понятие является фундаментальным в программировании.
В каждом языке программирования существует своя концепция и своя система типов данных. Однако в любой язык входит минимально необходимый набор основных типов данных: целые, вещественные, логические и символьные. С типом величины связаны три ее свойства: множество допустимых значений, множество допустимых операций, форма внутреннего представления. В табл. 1.1 представлены свойства основных типов данных.
Типы констант определяются по контексту (т.е. по форме записи в тексте), а типы переменных устанавливаются в описаниях переменных.
По структуре данные подразделяются на простые и структурированные. Для простых величин, называемых также скалярными, справедливо утверждение одна величина — одно значение, а для структурированных — одна величина — множество значений. К структурированным величинам относятся массивы, строки, множества и др.
ЭВМ — исполнитель алгоритмов. Как известно, каждый алгоритм (программа) составляется для конкретного исполнителя, т.е. в рамках его системы команд. О каком же исполнителе идет речь при изучении темы «Программирование для ЭВМ»? Ответ очевиден: исполнителем здесь является компьютер, а точнее говоря, комплекс ЭВМ + система программирования (СП). Программист составляет программу на том языке, на который ориентирована СП. Схематически это изображено на рис. 1.2, где входным языком исполнителя является язык программирования Паскаль.
Независимо от того, на каком языке программирования будет написана программа, алгоритм решения любой задачи на ЭВМ
Система программирования
на языке Паскаль

Программа на языке Паскаль
Рис. 1.2. Компьютер как исполнитель программ на языке Паскаль
9может быть составлен из следующих команд: присваивания, вво- а, вывода, обращения к вспомогательному алгоритму, цикла,
ветвления.
Далее для описания алгоритмов будут использоваться блок-схемы и учебный алгоритмический язык (АЯ), применяемый в школьном курсе информатики.
Линейные вычислительные алгоритмы
Основным элементарным действием в вычислительных алгоритмах является присваивание значения переменной величине.
Если значение константы определено видом ее записи, то переменная величина получает конкретное значение только в результате присваивания, которое может осуществляться двумя способами: с помощью команды присваивания и с помощью команды ввода.
Рассмотрим пример. В школьном учебнике математики правило деления двух обыкновенных дробей описано следующим образом:
числитель первой дроби умножить на знаменатель второй дроби;
знаменатель первой дроби умножить на числитель второй дроби;
записать дробь, числитель которой есть результат выполнения п. 1, а знаменатель — результат выполнения п. 2.
Алгебраическая форма записи этого примера следующая:
а с ad т b d be п
Теперь построим алгоритм деления дробей для ЭВМ, сохранив те же обозначения переменных, которые были использованы в алгебраическом выражении.
Исходными данными здесь являются целочисленные переменные а, Ь9 с, d9 а результатом — целые величины тип. Блок-схема алгоритма деления дробей приведена на рис. 1.3. Данный алгоритм на учебном алгоритмическом языке будет иметь следующий вид:
алг деление дробей
нач
цел а, Ь, с, d, m, n ввод а, b, с, d m := а х d
n := b х с вывод m, n
кон


Формат команды присваивания следующий:

Рис. 1.3. Блок-схема алгоритма деления дробей
переменная := выражение
Знак «:=» следует читать как «присвоить».
Команда присваивания означает следующие действия, выполняемые компьютером:
вычисляется выражение;
полученное значение присваивается переменной.
В приведенном алгоритме присутствуют две команды присваивания. В блок-схемах команды присваивания изображаются и прямоугольниках. Такой блок называется вычислительным.
При описании алгоритмов не обязатель- I ю соблюдать строгие правила записи выражений, это можно делать в обычной математической форме, так как это еще не язык программирования со строгим синтаксисом.
В рассматриваемом алгоритме имеется команда ввода:
ввод а, Ь, с, d
В блок-схемах команда ввода записывается в параллелограмме — блоке ввода-вывода. При выполнении этой команды процессор прерывает работу и ожидает действий пользователя. Пользователь должен набрать на устройстве ввода (клавиатуре) значения вводимых переменных и нажать клавишу ввода <Enter>. Значения следует вводить в том же порядке, в каком эти переменные расположены в списке ввода. Обычно с помощью команды ввода присваиваются значения исходных данных, а команда присваивания используется для получения промежуточных и конечных величин.
Полученные компьютером результаты решения задачи должны быть сообщены пользователю, для чего и предназначена команда вывода:
вывод m, п
С помощью этой команды результаты выводятся на экран или через устройство печати на бумагу.
Поскольку присваивание является важнейшей операцией в вычислительных алгоритмах, обсудим ее более подробно.
11
Рассмотрим последовательное выполнение четырех коман
а,
присваивания, в которых участвуют две переменные величины
Ь. В табл. 1.2 для каждой команды присваивания указаны значения переменных, которые устанавливаются после ее выполнения.
Этот пример иллюстрирует три основных свойства присваивания:
пока переменной не присвоено значение, она остается неопределенной;
значение, присвоенное переменной, сохраняется вплоть до выполнения следующего присваивания этой переменной;
новое значение, присваиваемое переменной, заменяет ее предыдущее значение.
X
1, Y
2, то после обмена должно стать X
2, Y
1.
Рассмотрим алгоритм, который часто используется при программировании. Даны две величины: X и Y. Требуется произвести между ними обмен значениями. Например, если сначала было
Этой задаче аналогична следующая ситуация. Имеются два стакана: один — с молоком, другой — с водой. Требуется произвести между ними обмен содержимым. Ясно, что в этом случае необходим третий стакан — пустой. Последовательность действий при обмене будет следующей:
перелить молоко из 1-го стакана в 3-й;
воду из 2-го стакана в 1-й;
молоко из 3-го стакана во 2-й.
Аналогично для обмена значениями двух переменных требуется третья дополнительная переменная. Назовем ее Z. Тогда задачу обмена значениями можно решить последовательным выполнением трех команд присваивания (табл. 1.3).
Таблица 1.2
Изменение значений переменных при выполнении команды
присваивания
Команда а ь
а := 1 1 —
b := 2 х а 1 2
а := b 2 2
b := а + b 2 4
12
Таблица 1.3
Обмен значениями между
переменными
Команда X Y Z
ввод X, Y 1 2 —
X
и « •
N 1 2 1
X := Y 2 2 1
1
X
• т и
N 2 1 1
Пример со стаканами не совсем точно характеризует ситуацию обмена между переменными, так как при переливании жидкостей один из стаканов становится пустым. В результате же выполнения команды присваивания (X := Y) переменная, стоящая справа (Y), сохраняет свое значение.
Алгоритм деления дробей имеет линейную структуру, т. е. в нем псе команды выполняются в строго определенной последовательности, каждая по одному разу. Линейный алгоритм состоит из команд присваивания, ввода, вывода и обращения к вспомогательным алгоритмам (что будет рассмотрено далее).
При описании алгоритмов с помощью блок-схем типы данных, как правило, не указываются (но подразумеваются). В учебных алгоритмах (на АЯ) для всех переменных типы данных указываются явно, и их описание производится сразу после заголовка алгоритма. При этом используются следующие обозначения: цел
целые, ве
вещественные, лит — символьные (литерные), лог
логические. В алгоритме деления дробей все переменные целого гипа.
Ветвления и циклы в вычислительных
алгоритмах
Составим алгоритм решения квадратного уравнения
ах2 + Ьх + с = 0.
Эта задача хорошо знакома из математики. Исходными данны
ми здесь являются коэффициенты а, Ь, с, а решением в общем случае — два корня (х, и х2), которые вычисляются по формуле
Все используемые в этой программе величины вещественного типа.
Алгоритм решения кваратного уравнения будет иметь следующий вид:
I
а, Ъ, с, d, xl, х2
алг корни квадратного уравнения
нач ввод а, Ъ, с
d := b2 - 4ас
xl := (-b + >/d) / (2а)
х2 := (-b - \/d)/(2a) вывод xl, х2
кон
Недостаток такого алгоритма виден «невооруженным глазом». Он не обладает важнейшим свойством, предъявляемым к качественным алгоритмам: универсальностью по отношению к исходным данным. Какими бы ни были значения исходных данных, алгоритм должен приводить к получению определенного результата и
13
О, с * 0, уравнение решений не имеет;
свойство в литературе по программированию называют результативностью алгоритма (получение какого-то результата в любом случае).
Для построения универсального алгоритма сначала требуется тщательно проанализировать математическое содержание задачи.
Решение квадратного уравнения зависит от значений коэффициентов ау by с.
Проанализируем эту задачу, ограничиваясь поиском только вещественных корней:
если а если а
0,ЬО, b
О, с
О, любое значение х — решение уравнения;
выполняться до конца. Результатом может быть числовой ответ, но может быть и сообщение о том, что при таких данных задача решения не имеет. Недопустимы остановки в середине алгоритма из-за невозможности выполнения какой-либо операции. Данное
если а = О, b * 0, это линейное уравнение, имеющее одно ре
с/Ь;
шение х
если а*0иб = Ь- 4ас > 0, уравнение имеет два вещественных
КОРНЯ Xi, Х2;
если а * 0 и d < 0, уравнение не имеет вещественных корней. Блок-схема алгоритма решения квадратного уравнения показана на рис. 1.4.
Этот же алгоритм на алгоритмическом языке будет иметь следующий вид:
а
b, cf d, xl, х2
алг корни квадратного уравнения
нач ввод а, Ъ, с
О
то
если
то
b
О
если с
О
если а

то вывод «Любое х — решение» иначе вывод «Нет решений»
иначе х := -с/Ь
вывод х кв
иначе d := b2 - 4ас
если d < О
то вывод «Нет вещественных корней» иначе xl := (-b + y/d) / (2а) ; х2 := (-b - y/d) / (2а)
вывод «х1 =», xl, «х2 =», х2
кон
14


Рис. 1.4. Блок-схема алгоритма решения квадратного уравнения
В данном алгоритме многократно использована структурная команда ветвления, общий вид которой в виде блок-схемы показан на рис. 1.5. На алгоритмическом языке команду ветвления можно записать в следующем виде:
если условие то серия 1 иначе серия 2 кв
В соответствии с приведенной блок-схемой команды ветвления сначала проверяется условие (вычисляется логическое выражение). Если условие истинно, то выполняется последовательность команд, на которую указывает стрелка с надписью «Да» (положительная ветвь) — «Серия 1». В противном случае выполняется отрицательная ветвь команд — «Серия 2».
НаАЯ условие записывается после служебного слова «если», положительная ветвь — после слова «то», а отрицательная — после слова «иначе». Буквами «кв» в такой записи обозначают конец ветвления.
Если на ветвях одного ветвления содержатся другие ветвления, значит, алгоритм имеет структуру вложенных ветвлений. Именно такую структуру имеет алгоритм решения квадратного уравнения (см. рис. 1.4), в котором для краткости вместо слов «Да» и «Нет» использованы соответственно знаки «+» и «-».
Рассмотрим следующую задачу: дано целое положительное число п. Требуется вычислить я! («-факториал). Вспомним определение факториала:
, f 1,если п = 0:
я! = (
[1х2х...хя, если п > 1.
На рис. 1.6 приведена блок-схема алгоритма вычисления я! с тремя переменными целого типа: п — аргумент, / — промежуточная переменная, F— результат. Для проверки правильности указанного алгоритма построим трассировочную табл. 1.4, в которой для конкретных значений исходных данных по шагам прослеживается изменение переменных, входящих в алгоритм. Данная таблица составлена для случая п = 3.
Приведенная трассировка доказывает правильность рассматриваемого алгоритма. Теперь запишем этот алгоритм на алгоритмическом языке:
алг факториал
цел п, i, Fиач ввод п
Нет
Рис. 1.5. Блок-схема команды ветвления

Рис. 1.6. Блок-схема алгоритма вычисления/й

Шаг п F i Условие
1 3 2 1 3 1 4 1 ^ 3, да
5 1 6 2 7 2 < 3, да
8 2 9 3 10 3 < 3, да
11 6 12 4 13 4 < 3, нет
14 вывод F := 1; i := 1 пока i < п, повторять
нц F := F X i i := i + 1 кц
вывод F
КОН,«iv
Данный алгоритм имеет циклическую структуру. В нем использована структурная команда цикл «Пока», или цикла с предусловием. Блок-схема команды цикла «Пока» показана на рис. 1.7. На АЯ она имеет следующий вид:
пока условие, повторять нц
серия
кц
Выполнение серии команд (тела цикла) повторяется пока условие цикла истинно. Когда условие становится ложным, выпол-
Условие
Нет
Да
Серия
I
Рис. 1.7. Блок-схема команды цикла «Пока»
пение цикла заканчивается. Служебные слова «нц» и «кц» обозначают соответственно начало и конец цикла.
Цикл с предусловием — это основная, но не единственная форма организации циклических алгоритмов: существует цикл с постусловием.
Вернемся к алгоритму решения квадратного уравнения, рассмотрев его со следующей позиции: если а = 0 — это уже не квадратное уравнение и его можно не решать. В данном случае будем считать, что пользователь ошибся при вводе данных, и ввод следует повторить (рис. 1.8). Иначе говоря, в алгоритме будет предусмотрен контроль достоверности исходных данных с предоставлением пользователю возможности исправления ошибки. Наличие такого контроля — еще один признак хорошего качества программы.
На АЯ алгоритм решения квадратного уравнения с контролем ввода данных будет иметь следующий вид:
алг квадратное уравнение
вещ а, Ъ, с, d, xl, х2
нач
повторять
ввод а, Ь, с до а * О
d := Ь2- 4ас если d > О
то xl := (-b + >/d)/(2a) х2 := (-Ь - >/d) / (2а) вывод xl, х2 иначе
вывод «Нет вещественных корней» кв
кон

Рис. 1.8. Блок-схема алгоритма решения квадратного уравнения с контролем ввода данных
Блок-схема структурной команды цикла с постусловием цикла «До» показана на рис. 1.9. На АЯ данную команду можно записать следующим образом:
повторять
серия
до условие
Здесь используется условие окончания цикла, т.е. когда оно становится истинным, цикл заканчивает работу.
Составим алгоритм решения следующей задачи: даны два натуральных числа М и N. Требуется вычислить их наибольший общий делитель — НОД (М, N).

Рис. 1.9. Блок-схема команды цикла «До»
Эта задача решается с помощью метода, известного под названием алгоритма Евклида. Идея этого метода основана на утверждении, что если М > N, то НОД (М, N) = НОД (М - N, N). Попробуйте доказать это самостоятельно. Другое утверждение,

лежащее в основе решения данного алгоритма, очевидно: НОД (М, М) = М. Для «ручного» выполнения этот алгоритм можно описать в форме следующей инструкции:
если числа равны, взять их общее значение в качестве ответа. В противном случае продолжить выполнение алгоритма;
определить большее из чисел;
заменить большее число разностью большего и меньшего значений;
вернуться к выполнению п. 1.
Блок-схема алгоритма Евклида приведена на рис. 1.10. На АЯ данный алгоритм можно записать следующим образом:
алг Евклид
цел М, N
нач ввод М, N
пока М * N, повторять нц если М > N
то М := М - N иначе N := N - М кв кц
кон
Алгоритм Евклида имеет структуру цикла с вложенным ветвлением. Выполните самостоятельно трассировку этого алгоритма для случая М= 18, N= 12. В результате должен получиться НОД = 6.
Логические основы алгоритмизацииПрямое отношение к программированию имеет дисциплина, называемая математической логикой, основу которой составляет алгебра логики, или исчисление высказываний. Под высказыванием понимается любое утверждение, в отношении которого можно однозначно сказать, истинно оно или ложно. Например, утверждение «Луна — спутник, Земли» — истинно, «5 > 3» — истинно, «Москва — столица Китая» — ложно, «1 = 0» — ложно. ИСТИНА и ЛОЖЬ являются логическими значениями. Логические значения приведенных утверждений однозначно определены. Другими словами, их значения являются логическими константами.
Логическое значение неравенства х< 0, где х— переменная, является переменным, т. е. в зависимости от значения х оно может быть либо истинным, либо ложным. Таким образом вводится понятие логической переменной. В описаниях алгоритмов, а также в программах на различных языках программирования, логические переменные могут обозначаться символическими именами, которым соответствует логический тип данных. Иначе говоря, если известно, что А, В, X, Y и др. — переменные логического типа, по означает, что они могут принимать только значение ИСТИНА или ЛОЖЬ.
Основы формального аппарата математической логики создал и середине XIX в. английский математик Джордж Буль. В его честь исчисление высказываний называется булевой алгеброй, а логические величины — булевскими.
Логическое выражение (логическая формула) — это простое или сложное высказывание. Сложное высказывание строится из простых с помощью логических операций (связок).
Имеются три основных логических операции: отрицание, конъюнкция (логическое умножение) и дизъюнкция (логическое сложение).
Отрицание обозначается в математической логике знаком «-1» и читается как НЕ. Это одноместная операция. Например, запись -'(х = у) читается следующим образом: НЕ (х равно у), т.е. значение будет истинным, если х не равно у, и ложным, если х равно у. Отрицание изменяет значение логической величины на противоположное.
Конъюнкция обозначается знаком & и читается как И. Это двухместная операция. Например, запись (х> 0) & (х< 1) означает, что данная логическая формула примет значение ИСТИНА, если хе [0,1], и значение ЛОЖЬ — в противном случае. Следовательно, результатом конъюнкции является ИСТИНА, если истинны оба операнда.
Дизъюнкция обозначается знаком v, который читается как ИЛИ. Например, запись (x=0)v(x=l) означает, что формула принимает истинное значение, если х — двоичная цифра (0 или 1). Следовательно, результатом дизъюнкции является ИСТИНА, если хотя бы один операнд имеет значение ИСТИНА.
Правила выполнения рассмотренных логических операций отражены в табл. 1.5, называемой таблицей истинности (здесь Aw В — логические величины, а буквами «И» и «Л» обозначены соответственно значения ИСТИНА и ЛОЖЬ).
Таблица 1.5
Таблица истинности
№ п/п А в НЕ А АИВ А ИЛИ В
1 и и л и и
2 и л л л и
3 л и и л и
4 л л и л л

Последовательность выполнения операций в логических выражениях определяется старшинством операций: отрицание, конъюнкция, дизъюнкция. Кроме того, порядок выполнения операции в логических формулах можно менять с помощью скобок.
(А И В) ИЛИ (НЕ А И В) ИЛИ (НЕ А И НЕ В)
Рассмотрим для примера вычисление значения логической формулы
НЕ ХИ ГИЛИ ХИ Z
при следующих значениях логических переменных: X = ЛОЖЬ, Y= ИСТИНА, Z= ИСТИНА.
Отметим цифрами порядок выполнения операций в заданном выражении:
® (D ® (D
НЕ X И Y ИЛИ X И Z.
Используя таблицу истинности, выполним вычисление по шагам:
НЕ ЛОЖЬ = ИСТИНА;
ИСТИНА И ИСТИНА = ИСТИНА;
ЛОЖЬ И ИСТИНА = ЛОЖЬ;
ИСТИНА ИЛИ ЛОЖЬ = ИСТИНА.
Значение рассмотренной логической формулы — ИСТИНА. Рассмотрим следующее утверждение: «Значение X находится в интервале от 0 до 1». Это утверждение можно записать в виде системы неравенств
0<Х< 1.
Соответствующее логическое выражение будет иметь вид
(Х> 0) И (Х< 1).
А теперь усложним задачу и запишем в виде логического выражения следующее утверждение: точка на плоскости с координатами (X, Y) находится в кольце с центром в начале координат, с внутренним радиусом, равным 1, и внешним радиусом, равным 2 (рис. 1.11). Это выражение будет иметь вид
(X1 + Y2 > 1) И (X2 + Y2 < 4).
Операция конъюнкции выполняется следующим образом: выбирается множество Рис. 1.11. Задание коль- точек, удовлетворяющих первому неравен- цевой области ству (X2 + Y2 > 1), и из полученного мно-жсстиа выделяется подмножество, удовлетворяющее второму неравенству (X2 + У2 < 4), что и будет окончательным результатом. Можно также сказать, что искомое множество есть пересечение двух множеств, первое из которых удовлетворяет первому неравенству, а второе — второму. Конъюнкция — логическое умножение, т.е. операция, вычисляющая такое пересечение.
Запишем в виде логического выражения следующее утверждение: точка на плоскости с координатами (X, Y) находится вне кольца с центром в начале координат с внутренним радиусом, равным 1, и внешним радиусом, равным 2 (см. рис. 1.11). Это выражение будет иметь вид
(X2 + Y2 < 1) ИЛИ (X2 + Y2 > 4).
Выполнение операции дизъюнкции происходит следующим образом: выбирается множество точек, удовлетворяющих первому неравенству (X2 + Y2 < 1), и к нему прибавляется множество, удовлетворяющее второму неравенству (Л"2 + Y2 > 4). Так проясняется смысл другого названия операции дизъюнкции — логическое сложение, т.е. сложение двух множеств.
Последнюю задачу можно было решить иначе. Соответствующее логическое выражение можно записать как отрицание первого логического выражения, поскольку точки, находящиеся вне кольца, — это точки, которые НЕ принадлежат кольцу:
НЕ (СX2 + Y2 > 1) И (X2 + Y2 < 4)).
Следовательно, справедливо равенство между двумя логическими выражениями:
НЕ ((X2 + Y2 > 1) И (X2 + Y2 < 4» = (X2 + Y2 < 1) ИЛИ
(X2 + Y2 > 4).
Из этого примера становится понятным следующее правило преобразования: операция отрицания, примененная к двум неравенствам, связанным конъюнкцией, изменяет знаки этих неравенств на противоположные, а конъюнкцию — на дизъюнкцию (или дизъюнкцию на конъюнкцию).
Рассмотрим пример алгоритма, в котором используется сложное логическое выражение. По длинам трех сторон а, Ь, с треугольника вычислим его площадь.
Для решения данной задачи используется формула Герона:
\1р(Р ~ о)(р - Ь)(р - с),
где р = (а + Ь + с)/2 — полупериметр треугольника.
Исходные данные должны удовлетворять основному соотношению для сторон треугольника: длина каждой из сторон должна быть меньше суммы длин двух других его сторон.
Алгоритм вычисления площади треугольника имеет ветвящуюся структуру. Условие в структурной команде ветвления запишем в виде сложного логического выражения, которое позволит «отфильтровать» все варианты неверных исходных данных:
алг Герои
вещ А, В, С, Р, S
нач ввод А, В, С
если (А > 0) И (В > 0) И (С > 0) И (А + В > С) И (В +С > А) И (А + С > В) то
Р := (А + В + С) /2
S := корень (Р * (Р - А) * (Р - В) * (Р - С)) вывод «Площадь =», S иначе вывод «Неверные исходные данные» кв
кон
Вспомогательные алгоритмы и процедурыВ теории алгоритмов существует понятие вспомогательного алгоритма, т.е. алгоритма решения некоторой подзадачи из основной решаемой задачи. При этом алгоритм решения исходной задачи называется основным.
В качестве примера рассмотрим следующую задачу. Требуется составить алгоритм вычисления степенной функции с целым показателем: у = хк, где к — целое число; х * 0.
В алгебре такая функция определена следующим образом:
1 при и = 0;
1
х~п при п < 0;
х" при п > 0.
В данной задаче в качестве подзадачи можно рассматривать возведение числа в целую положительную степень.
Учитывая, что 1/х~" = (1/х)~П, запишем основной алгоритм решения этой задачи:
алг степенная функция цел п; вещ х, у нач ввод х, п если п = 0
то у: =1 иначе если п > О
то СТЕПЕНЬ (х, п, у) иначе СТЕПЕНЬ (1/х, -п, у) кв кв
вывод у
кон
В основном алгоритме дважды повторяется команда обращении к вспомогательному алгоритму с именем СТЕПЕНЬ — ал- юритму возведения вещественного основания в целую положительную степень посредством его многократного перемножения. Величины, стоящие в скобках в команде обращения к испомогательному алгоритму, называются фактическими пара- метрами.
В учебном алгоритмическом языке вспомогательные алгоритмы оформляются в виде процедур. Запишем на АЯ процедуру СТЕПЕНЬ:
процедура СТЕПЕНЬ (вещ а, цел к, вещ z)
цел i
нач z := 1; i := 1
пока i < к, повторять
нц z := z х а i := i + 1 кц
кон
Заголовок вспомогательного алгоритма начинается со слова • процедура», после которого следуют имя этой процедуры и в скобках — список формальных параметров. В этом списке перечисляются переменные аргументы и переменные результаты с указанием их типов. В данном примере а, к — формальные параметры-аргументы, z — параметр-результат. Следовательно, процедура СТЕПЕНЬ производит вычисления по формуле z = ак.
В основном алгоритме вычисления степенной функции обращение к процедуре производится посредством указания ее имени и далее в скобках списка фактических параметров.
Между формальными и фактическими параметрами процедуры должны выполняться следующие правила соответствия:
по числу (сколько формальных, столько и фактических параметров);
по последовательности (первому формальному параметру соответствует первый фактический параметр, второму — второй и т.д.);
• по типам (типы соответствующих формальных и фактических параметров должны совпадать).
Фактические параметры-аргументы могут быть выражениями соответствующего типа.
Обращение к процедуре инициирует следующие действия:
значения параметров-аргументов присваиваются соответствующим формальным параметрам;
выполняется тело процедуры (команды внутри процедуры);
значение результата передается соответствующему фактическому параметру, и происходит переход к выполнению следующей команды основного алгоритма.
В процедуре СТЕПЕНЬ нет команд ввода исходных данных и вывода результатов. Здесь присваивание начальных значений аргументам (а, п) производится через передачу параметров-аргументов, а присваивание результата переменной (у) происходит через передачу параметра-результата (z).
Таким образом, передача значений параметров процедур является третьим способом присваивания (наряду с командами присваивания и ввода).
Использование процедур позволяет строить сложные алгоритмы методом последовательной детализации.
Основы структурного программированияПрошло уже более полувека со времени появления первой ЭВМ. Все это время вычислительная техника стремительно развивалась. Изменялась элементная база ЭВМ, росли их быстродействие и объем памяти, изменялись средства интерфейса человека с машиной. Безусловно, эти изменения сказывались самым непосредственным образом на работе программиста. Определенный общепринятый способ производства чего-либо (в данном случае — программ) называют технологией, поэтому далее будем говорить о технологии программирования.
Для первых ЭВМ с «тесной» памятью и небольшим быстродействием основным показателем качества программы была ее экономичность по занимаемой памяти и времени счета. Чем программа получалась короче, тем класс программиста считался выше. Такое сокращение программы часто требовало больших усилий. Иногда программа получалась настолько «хитрой», что могла «перехитрить» самого автора: возвратившись через некоторое время к собственной программе и желая что-то изменить, программист мог запутаться в ней, забыв свою «гениальную идею».
Очень сложный алгоритм всегда увеличивает вероятность ошибки в программе, как и вероятность выхода из строя сложного технического устройства больше, чем простого.
Ианы изготовления программного продукта программистом, • шлующис:
I М|юсктирование.
) Кодирование.
». Отладка.
Проектирование заключается в разработке алгоритма будущей мрофлммы, например блок-схемы. Кодирование — это составление текста программы на языке программирования. Отладка осуществляется с помощью тестов, т.е. производится выполнение программы с некоторым заранее продуманным набором исходных шитых, для которого известен результат. При этом чем сложнее программа, тем большее число тестов требуется для ее исчерпывающей проверки. Очень «хитрую» программу трудно протестирован. исчерпывающим образом, так как всегда остается возможность не заметить какой-то «подводный камень».
Г ростом памяти и быстродействия ЭВМ, с совершенствованием языков программирования и трансляторов с этих языков проблема экономичности программы становится менее острой. Нее более важными качественными характеристиками программ I 1ЛНОНЯТСЯ их простота, наглядность и надежность, а с появлением машин третьего поколения эти качества становятся основными.
И конце 60-х — начале 70-х гг. XX в. определяется дисциплина, получившая название структурного программирования. Ее появление и развитие связано с именами Э.В.Дейкстры, Х.Д.Милса, Д I'. Кнута и др. Структурное программирование до настоящего м|К’мени остается основой технологии программирования. Соблюдение его принципов позволяет программисту быстро научиться создавать ясные, безошибочные, надежные программы.
В основе структурного программирования лежит теорема, которая была доказана в теории программирования: алгоритм для решения любой логической задачи можно составить только из структур Следование, Ветвление, Цикл, называемых базовыми алгоритмическими структурами.
Ранее уже приводились эти структуры. По сути, во всех рассмотренных примерах программ использовались принципы структурного программирования.
Следование — это линейная последовательность действий (рис. 1.12).
Серия 1
Серия 2
Серия N
Каждая серия в такой последовательности может содержать в себе как простую команду, так и сложную структуру, но обязательно она имеет один вход и один выход.
Рис. 1.12. Линейная структура программирования Следование
Ветвление — это алгоритмическая альтернатива, которую можно записать в виде
если условие
то серия 1 иначе серия 2
кв
Управление в этой структуре передается на одну из двух ветвей (серий команд) в зависимости от истинности или ложности условия. Затем происходит выход на общее продолжение (см. рис. 1.5).
Неполная форма ветвления имеет место при отсутствии ветви «иначе»:
если условие то серия кв
Цикл — это повторение некоторой группы действий по условию. Различают два типа циклов. Первый тип циклической структуры — цикл с предусловием (см. рис. 1.7):
пока условие, повторять нц
Здесь пока условие истинное, выполняется серия, образующая тело цикла.
Второй тип циклической структуры — цикл с постусловием (см. рис. 1.9):
t
' I
повторять
серия
до условие
Здесь тело цикла предшествует условию цикла и повторяет свое выполнение, если условие ложное. Повторение заканчивается, когда условие становится истинным.
Теоретически необходимым и достаточным для построения любого циклического алгоритма является цикл с предусловием, т.е. это более общий вариант цикла, чем цикл с постусловием. В самом деле, тело цикла «До» хотя бы один раз обязательно выполнится, так как проверка условия происходит после завершения его выполнения, а для цикла «Пока» возможен вариант, когда тело цикла не выполнится ни разу. Следовательно, в любоми ii.ikc программирования можно было бы ограничиться исполь- юпннием цикла «Пока», однако в ряде случаев применение цикла -До* оказывается более удобным, и поэтому он используется.
Иногда в литературе структурное программирование называют программированием без GOTO (без оператора безусловного перехода). Действительно, при таком подходе к программированию нет места безусловному переходу. Неоправданное использо- шшие в программах GOTO лишает их структурности, а значит, и всех связанных с этим положительных свойств алгоритма: про- фачности и надежности. Хотя во всех процедурных языках про- I раммирования этот оператор присутствует, для обеспечения структурного подхода к программированию его употребления следует избегать.
Сложные алгоритмы состоят из соединенных между собой ба- ювых структур. Соединение этих структур может выполняться двумя способами: последовательным и вложенным. Это аналогично ситуации в электротехнике, где любую сложную электрическую цепь можно разложить на последовательно и параллельно соединенные участки.
Однако вложенные алгоритмические структуры не являются аналогом параллельно соединенных электрических проводников. Здесь больше подходит аналогия с матрешками, помещенными друг в друга. Если блок, составляющий тело цикла, сам является циклической структурой, это значит, что имеют место вложенные циклы. В свою очередь внутренний цикл может иметь внутри себя еще один цикл и т.д. В связи с этим введено понятие глубины вложенности циклов. Точно также и ветвления могут быть вложенными друг в друга.
Структурный подход требует стандартного изображения блок- схем алгоритмов. Каждая базовая структура должна иметь один иход и один выход. Нестандартно изображенная блок-схема алгоритма плохо читается и теряет свою наглядность.
Примеры структурных блок-схем алгоритмов приведены на рис. 1.13. Такие блок-схемы легко читаются и хорошо воспринимаются зрительно, при этом каждой структуре можно дать название.
В учебном алгоритмическом языке, предназначенном для описания структурных алгоритмов, команда безусловного перехода отсутствует. Использование этого языка при обучении способствует «структурному воспитанию» программиста.
Наглядность структурам алгоритмом на АЯ придает структуризация вида их текста. Основной используемый для этого прием — сдвиги строк, которые должны подчиняться следующим правилам:
• конструкции одного уровня вложенности располагаются на одном вертикальном уровне (т. е. начинаются с одной позиции в строке);

Рис. 1.13. Примеры структурных блок-схем алгоритмов:
а — вложенные ветвления с глубиной вложенности, равной единице; 6 — uni с вложенным ветвлением; в — вложенные циклы «Пока» с глубиной вложенш сти, равной единице; г — ветвление с вложенной последовательностью ветми ний на положительной ветви и с вложенным циклом «Пока» на отрицателын ветви; д — последовательность ветвления и цикла «До»; е — вложенные внешне цикл «Пока» и внутренний цикл «До»; У — условие; С — серия
• вложенные конструкции смещаются по строке на несколько 1КМИЦИЙ вправо относительно внешних для конструкций.
( труктуры текстов алгоритмов на АЯ для показанных на рис. 1.13 Пиок-схем приведены в табл. 1.6.
Структурная методика алгоритмизации — это не только форма описания алгоритма, но и способ мышления программиста. Следует ( I ремиться составлять алгоритм из стандартных структур. Исполь- •уи строительную аналогию, можно сказать, что структурная метлика построения алгоритма подобна сборке здания из стандар- I пых секций.
Таблица 1.6
Алгоритмы на АЯ, соответствующие схемам, представленным
на рис. 1.13
< чсма Алгоритм Схема Алгоритм
а если <У1> то если <УЗ> то <С1> кв
иначе если <У2> то <С2> иначе <СЗ> кв кв б пока < У1>, повторять нц
если <У2> то <С1> иначе <С2> кв кц
в пока <У1>, повторять нц
пока <У2>, повторять нц
<С>
КЦ
кц г если <У1> то если <У> то <С1> иначе <С2> кв
если <УЗ> то <СЗ> иначе <С4> кв
иначе пока <У4>, повторять <С5> кц кв
а если <У1> то <С1> иначе <С2> кв
повторять
СЗ
до <У2> е пока <У1>, повторять не повторять
<С>
до <У2> кц
Еще одним важнейшим технологическим приемом структурного программирования является декомпозиция решаемой задачи на подзадачи, т.е. более простые для программирования части исходной задачи. Алгоритмы решения таких подзадач называются вспомогательными. При этом возможны два подхода к построению алгоритма:
сверху вниз — сначала строится основной алгоритм, а затем — вспомогательные;
снизу вверх — сначала составляются вспомогательные алгоритмы, а затем — основной.
Первый подход к построению алгоритма также называют методом последовательной детализации, а второй — сборочным методом.
При последовательной детализации сначала строится основной алгоритм и в него вносятся обращения к вспомогательным алгоритмам первого уровня. Затем составляются вспомогательные алгоритмы первого уровня, в которых могут присутствовать обращения к вспомогательным алгоритмам второго уровня и т.д. Вспомогательные алгоритмы самого нижнего уровня состоят только из простых команд.
Метод последовательной детализации применяется при конструировании любых сложных объектов. Это естественная логическая последовательность мышления конструктора: постепенное углубление в детали. В программировании речь идет тоже о конструировании, но только не технических устройств, а алгоритмов. Достаточно сложный алгоритм другим способом построить практически невозможно.
Методика последовательной детализации позволяет организовать работу коллектива программистов над сложным проектом. Например, руководитель группы строит основной алгоритм, а разработку вспомогательных алгоритмов и написание соответствующих подпрограмм поручает своим сотрудникам. При этом участникам рабочей группы следует лишь договориться об интерфейсе (т. е. взаимосвязи) между своими программными модулями, а внуг ренняя организация программы — личное дело программиста.
Сборочный метод предполагает накопление и использование библиотек вспомогательных алгоритмов, реализованных в языках программирования в виде подпрограмм, процедур, функций.
Развитие языков и технологий программированияЯзык программирования — это способ записи программ реше ния различных задач на ЭВМ в «понятной» для компьютера фор ме. Процессор компьютера непосредственно служит для воспри
ниш языка машинных команд (ЯМК). Однако, программы на ЯМК шп|шГ>атывались лишь для ламповых ЭВМ первого поколения. 11|им риммирование на ЯМК — дело непростое. Программист должен знать числовые коды всех машинных команд и сам распредели и. память под команды программы и данные.
II 1950-х гг. появились первые средства автоматизации программирования — языки автокоды. Позднее языки этого уровня стали ми пн нать ассемблерами. Языки типа автокода и ассемблера облегчи и и работу программистов. Переменные величины стали изобразит. символическими именами. Числовые коды операций замени- ии мнемоническими (словесными) обозначениями, которые легчи ш помнить. При этом язык программирования стал понятнее ичи человека, удалился от языка машинных команд. Чтобы компь- miep мог исполнять программы на автокоде, требовался специ- 11ИМ1МЙ переводчик — транслятор, т.е. системная программа, пере поди щая текст программы на автокоде в текст эквивалентной программы на ЯМК.
Компьютер, оснащенный транслятором с автокода, понимает инткод. В этом случае можно говорить о псевдо-ЭВМ (аппаратура I транслятор с автокода), языком которой является автокод. Ми.1ки типа автокода и ассемблера являются машинно-ориенти- ропапиыми, т.е. они настроены на структуру машинных команд конкретного компьютера. Разные компьютеры с различными тиками процессоров имеют разный ассемблер. Языки программиро- ааниа высокого уровня (ЯПВУ) являются машинно-независимыми. г. е. одна и та же программа на таком языке может выполнятся па )ИМ разных типов, оснащенных соответствующим транслятором. Форма записи программ на ЯПВУ по сравнению с автокодом б а и ж с к традиционной математической форме и естественному ии.1ку. Например, программа на языке Паскаль почти такая же, как па школьном алгоритмическом языке. ЯПВУ легко поддаются и»учспию и хорошо поддерживают структурную методику про- фиммирования.
Первыми популярными языками высокого уровня, появившимися и 1950-х гг., были Фортран, Кобол (в США) и Алгол (в Гироне). Языки Фортран и Алгол были ориентированы на научно технические расчеты математического характера. Кобол — это а пак для программирования экономических задач, в котором сдайте развиты математические средства, однако хорошо развиты сред- I I на обработки текстов и лучше организован вывод данных в форме I ребуемого документа. Для первых ЯПВУ была характерна пред- мешая ориентация.
большое число языков программирования появилось в 1960— 1470 х гг. (за всю историю существования ЭВМ их было создано Понес т ысячи), однако распространились и выдержали испытания нрсмсием немногие.
В 1965 г. в Дартмутском университете был разработан язык Бейсик. По замыслу авторов это должен был быть простой язык, легко изучаемый, предназначенный для программирования несложных расчетных задач. Наибольшее распространение Бейсик получил на микроЭВМ и персональных компьютерах. На первых моделях школьных компьютеров программировать можно было только на языке Бейсик, однако это неструктурный язык, и поэтому он плохо подходит для обучения качественному программированию. Справедливости ради следует заметить, что более поздние версии Бейсика для персональных компьютеров (ПК), например QBasic, стали более структурными и по своим изобразительным возможностям приблизились к таким языкам, как Паскаль.
В эпоху ЭВМ третьего поколения большое распространение получил язык PL/1 (Program Language One), разработанный фирмой IBM. Это был первый язык, претендовавший на универсальность, т.е. на возможность решать любые задачи: вычислительные, обработки текстов, накопления и поиска информации. Однако PL/1 оказался слишком сложным языком. Для машин типа IBM 360/370 транслятор с языка PL/1 оказался недостаточно оптимальным, и содержал ряд не выявленных ошибок. Для мини- и микроЭВМ язык PL/1 вообще не получил распространения. Однако линия на универсализацию языков программирования была поддержана: были разработаны универсальные версии старых языков: Алгол-68 и Фортран-77.
Значительным событием в истории языков программирования стало создание в 1971 г. языка Паскаль как учебного языка структурного программирования.
Широкое распространение языку Паскаль обеспечили персональные компьютеры. Фирма Borland International, Inc (США) разработала систему программирования ТурбоПаскаль для ПК. ТурбоПаскаль — это не только язык и транслятор с него, но еще и интегрированная среда программирования, обеспечивающая пользователю удобство работы на языке Паскаль. ТурбоПаскаль вышел за рамки учебного предназначения и стал языком профессионального программирования с универсальными возможностями. Транслятор с ТурбоПаскаля по оптимальности создаваемых им программ близок к лидеру по этому качеству — транслятору с Фортрана. В силу своих достоинств Паскаль стал источником многих основных современных языков программирования, например Ада, Модула-2 и др.
Язык программирования Си (английское название — С) создавался как инструментальный язык для разработки операционных систем, трансляторов, баз данных и других системных и прикладных программ. Так же, как и Паскаль, язык Си — это язык структурного программирования, но в отличие от Паскаля в нем заложены возможности непосредственного обращения к некоторым машинным командам и к определенным участкам памяти к им м мотора.
Модула-2 — это еще один язык, предложенный Н. Виртом, чнинющийся развитием языка Паскаль и содержащий средства для • ошанин больших программ.
>ИМ будущего — пятого — поколения называют машинами ж к vi стенного интеллекта. Но прототипы языков для этих машин были созданы намного раньше их физического появления. )т тыки ЛИСП и Пролог.
11ерное упоминание о языке ЛИСП относится к 1958 г. Создан он па основе понятия рекурсивно определенных функций. А поскольку доказано, что любой алгоритм может быть описан с помощью некоторого набора рекурсивных функций, то ЛИСП по гуш является универсальным языком. Сего помощью на ЭВМ можно моделировать достаточно сложные процессы, в частности интеллектуальную деятельность людей. Парадигму программировании, реализованную в языке ЛИСП, называют функциональным щм, 'раммированием.
Язык Пролог разработан во Франции в 1972 г. также для решения проблем искусственного интеллекта. Этот язык позволяет в формальном виде описывать различные утверждения, логику рас- суждений и заставляет ЭВМ давать ответы на заданные вопросы. II языке Пролог реализована логическая парадигма программирования.
В конце XX в. новым значительным направлением в развитии программного обеспечения ЭВМ стал объектно-ориентированный подход. Объекты — это структуры, объединяющие в единое целое лянные и программы их обработки. Приобрели популярность объекто-ориентированные операционные системы (например, Windows), прикладные программы, а также системы объектно-ориентированного программирования (ООП).
11срвым языком с элементами объектно-ориентированной технологии программирования был язык Симула-67. Развитие языка Си привело к появлению его объектно-ориентированной версии под названием Си++. В ТурбоПаскале, начиная с версии 5.5, также появились средства ООП.
В последнее время возникло новое направление в технологии программирования — визуальное. Стали создаваться системы визу- ил ыюго программирования, работающие под Windows, использование которых, в частности, позволяет легко и быстро про- флммировать сложный графический интерфейс. Появились визуальные версии популярных языков программирования: Visual Basic, Delphi (развитие ТурбоПаскаля), Borland C++ Builder и др.
Способы трансляции. Реализовать тот или иной язык программирования на ЭВМ — это значит создать транслятор с этого языка для данной ЭВМ. Существует два принципиально различных метода трансляции — компиляция и интерпретация. Для объяснения различия этих методов можно предложить следующую аналогию: лектор должен выступить перед аудиторией на незнакомом ей языке. При этом возможны:
полный предварительный перевод, т.е. лектор заранее передает текст выступления переводчику, тот записывает перевод, размножает его и раздает слушателям (после чего лектор может и не выступать);
синхронный перевод, т.е. лектор читает доклад, а переводчик одновременно с ним слово за словом переводит выступление.
Компиляция является аналогом полного предварительного перевода, а интерпретация — аналогом синхронного перевода. Транслятор, работающий по принципу компиляции, называется компилятором, а транслятор, работающий по принципу интерпретации, — интерпретатором.
При компиляции в память ЭВМ загружается программа-компилятор. Она воспринимает текст программы на ЯПВУ как исходную информацию, которая называется исходным модулем, загружаемым из текстового файла. После обработки компилятором программы на ЯПВУ получают объектный модуль. Следующий этап обработки программы, называемый редактированием связей (или линкованием), выполняет специальная программа — редактор связей. Этот редактор подключает к исходной программе необходимые для ее работы программные модули: процедуры, функции и др., в результате чего получают загрузочный модуль — программу на языке машинных команд, готовую к выполнению. При этом в оперативной памяти остается только программа на ЯМК, выполнение которой и дает искомые результаты.
Интерпретатор в течение всего времени работы программы находится во внутренней памяти — оперативном запоминающем устройстве (ОЗУ), куда помещается и программа на ЯПВУ. Интерпретатор в последовательности выполнения алгоритма считывает очередной оператор программы, переводит его в команды и тут же выполняет эти команды, после чего переходит к переводу и выполнению следующего оператора. При этом результаты предыдущих переводов в памяти не сохраняются, т.е. при повторном выполнении одной и той же команды она снова будет транслироваться.
При компиляции исполнение программы включает в себя три этапа: компиляцию, линкование и выполнение. При интерпретации, поскольку трансляция и выполнение совмещены, обработка программы на ЭВМ проходит в один этап. Однако откомпилированная программа выполняется быстрее, чем интерпретируемая, поэтому использование компиляторов удобнее для больших программ, требующих быстрого счета. Программы на языках Паскаль, Си, Фортран всегда компилируются. Бейсик чаще всего реализу-
Min через интерпретатор. Некоторые языки имеют реализацию как через компилятор, так и через интерпретатор. В режиме ин- 1Т|Ч1ретации удобно отлаживать программу, а рабочие расчеты чучше осуществлять в режиме компиляции.
Структура и способы описания языков программирования высокого уровняНо всех языках программирования определены способы орга- UII ищи и данных и действий над данными. Кроме того, существу- ян hi с менты языка, включающие в себя множество символов (алфавит), лексемы и другие изобразительные средства программи- |кншмии. Несмотря на разнообразие языков программирования их изучение происходит приблизительно по одной схеме. Это обу- i uniutcHO общностью структуры языков высокого уровня (рис. 1.14).
Описание в данном учебном пособии языков Паскаль и Delphi Путч выполняться в соответствии с этой схемой.
('л сдует отметить сходство изучения естественных языков и М1ЫКОН программирования. Во-первых, для того чтобы читать и пиши» на иностранном языке, надо знать алфавит этого языка. Но» вторых, следует знать правила написания слов и предложений, г.е. синтаксис языка. В-третьих, необходимо понимать нмысл слов и фраз, чтобы адекватно реагировать на них. Например, в салоне самолета засветилось табло «Fasten belts!» (За- Uпн пите ремни!). Зная английскую грамматику, можно правиль-

Рис. 1.14. Структура языка программирования высокого уровня
но прочитать эту фразу, однако не понять ее смысл и, следовательно, не выполнить соответствующих действий. Из грамотно написанных слов можно составить абсолютно бессмысленную фразу. Смысловое содержание языковой конструкции называется семантикой.
Любой язык программирования образуют три основные составляющие: алфавит, синтаксис и семантика.
Соблюдение правил в языке программирования должно быть более строгим, чем в разговорном языке. Человеческая речь содержит значительное количество избыточной информации, т.е. не расслышав какое-то слово, можно понять смысл фразы в целом. Слушающий или читающий человек может додумать, дополнить, исправить ошибки в воспринимаемом тексте.
Компьютер же — это автомат, воспринимающий все «всерьез». В текстах программ нет избыточности и компьютер сам не исправит даже очевидной (с точки зрения человека) ошибки. Он может лишь указать место, которое «не понял» и вывести замечание о предполагаемом характере ошибки. Исправить же ошибку должен программист.
Для описания синтаксиса языка программирования также необходим какой-то язык, т.е. метаязык (надъязык), предназначенный для описания других языков. Наиболее распространенными метаязыками в литературе по программированию являются металингвистические формулы Бэкуса — Наура (язык БНФ) и синтаксические диаграммы. Далее мы будем использовать в основном язык синтаксических диаграмм, так как они более наглядны и легче воспринимаются. Однако, когда это будет удобно, будем применять и некоторые элементы языка БНФ.
В БНФ всякое синтаксическое понятие имеет вид формулы, состоящей из правой и левой частей, соединенных знаком «::=», смысл которого эквивалентен фразе «по определению есть». Левая часть формулы содержит имя определяемого понятия (метапеременную), заключенное в угловые скобки о, а правая часть — формулу или диаграмму, определяющую все множество значений, которое может принимать метапеременная.
Синтаксис языка создается посредством последовательного усложнения понятий, т.е. сначала определяются простейшие (базовые) понятия, а затем все более сложные, включающие в себя предыдущие понятия как составляющие.
В такой последовательности, очевидно, конечным определяемым понятием должна быть «программа».
При записи метаформул приняты определенные соглашения. Например БНФ, определяющая понятие «двоичная цифра», имеет вид
•Сдвоичная цифра> : := 0 |1
I'M. I 15. Синтаксическая диа- Рис. 1.16. Синтаксическая диаграмма
мшмма двоичной цифры
11м>»ичнпи цифрам
<Двоичный код>
<Двоичная цифра>
гдвоичного кода
Iiiiik «|» здесь эквивалентен слову «или» (либо).
• интаксическая диаграмма двоичной цифры показана на 1<иг 1.15.
II л их диаграммах стрелки указывают на последовательность Iпн положения элементов синтаксической конструкции, а кружками обведены символы, присутствующие в данной конструкции.
11опнтие «двоичный код» как непустая последовательность двоичных цифр в БНФ описывается следующим образом:
дмоичный код> ::= <двоичная цифра> | Сдвоичный
кодХдвоичная цифра>
Определение, в котором некоторое понятие определяется само и ре I себя, называется рекурсивным. Рекурсивные определения ха- римерны для БНФ.
< интаксическая диаграмма двоичного кода представлена на рис. 1.16. Здесь возвратная стрелка обозначает возможность мно- и.кратного повторения.
(Невидно, что синтаксическая диаграмма более наглядна, чем 1.НФ.
('интаксические диаграммы были введены Н. Виртом и исполь- M.iiaiibi для описания созданного им языка Паскаль.
Упражнения
Определить значение логического выражения НЕ {X > Z) И НЕ I \ Y) при следующих значениях переменных:
а)Х= 3, Y= 5, Z = 2;
Г.) Х= О, Y= 1, Z= 19;
и) X = 5, Y= О, Z = -8;
, ) X = 9, Y = -9, Z= 9.
Записать логические выражения (формулы), являющиеся истинными при следующих условиях:
а)точка с координатами (X, Y) принадлежит первой четверти единичного круга с центром в начале координат;
б)точка с координатами (X, Y) не принадлежит единичному кругу г центром в начале координат и принадлежит кругу с радиусом, равным 2, и е центром в начале координат (изобразите это графически).
Даны декартовы координаты трех вершин треугольника на плоско- ми. Составить алгоритм определения площади треугольника.
Дана скорость ракеты при выходе за пределы атмосферы Земли. Составить алгоритм определения движения ракеты после выключения двигателей. (Значения трех космических скоростей: 7,5 км/с; 11,2 км/с; 16,4 км/с.)
Даны три положительных числа. Составить алгоритм, определяющий, могут ли эти числа быть длинами сторон треугольника?
Пусть компьютер способен выполнять только две арифметические операции: сложение и вычитание. Составить следующие алгоритмы:
а)умножения двух целых чисел;
б)целочисленного деления двух чисел;
в)получения остатка от целочисленного деления двух чисел.
Построить алгоритм решения биквадратного уравнения, используя в качестве вспомогательного алгоритм решения квадратного уравнения.
Составить алгоритм нахождения НОД трех натуральных чисел, используя вспомогательный алгоритм нахождения НОД двух чисел.
ГЛАВА 2
ПРОГРАММИРОВАНИЕ НА ЯЗЫКЕ ПАСКАЛЬПервое знакомство с языком Паскаль< 'труктура программы на языке Паскаль. По определению стан- ||и|)|кого языка Паскаль программа состоит из заголовка и тела тюка), в конце которого следует точка — признак конца про- цыммы. В свою очередь, блок содержит разделы описаний и раздел операторов'.
Program <имя программы:»;
l.abal <раздел меток>;
Const <раздел констант>;
Тура <раздел типов>;
Var <раздел переменных:»;
Procedure (Function) <раздел подпрограмм>;
ttegin
1'.»здел операторов>
Mnd.
I’вздел операторов имеется в любой программе и является ос-
Разделы описаний могут не все содержаться в каждой
нрщрлмме.
И ТурбоПаскале, в отличие от стандартного языка, возможно:
отсутствие заголовка программы;
следование разделов Const, Type, Var, Label друг за другом в мюЬом порядке в разделе описаний и сколько угодно раз.
Примеры программ. Как уже говорилось, язык Паскаль разравнивался Н. Виртом как учебный язык. Основной принцип, замоленный в нем, — это поддержка структурной методики про- фяммирования. На этом же принципе основывается псевдокод, ьоюрый здесь будем называть алгоритмическим языком. По сути расхождение между АЯ и языком Паскаль заключается в следующем: АЯ — русскоязычный, Паскаль — англоязычный; синтак- I не языка Паскаль определен строго и однозначно, а синтаксис ЛИ сравнительно свободно.
taimcb программы на языке Паскаль похожа на английский перевод алгоритма, записанного на алгоритмическом языке. Срав-
m := a * d n := b * c вывод m,n
m := a * d; n := b * c;
алг деление дробей цел а, Ь, с, d, ш, п нач ввод a,b,c,d
Program Division;
Var a,b,с,d,m,n : Integer; Begin ReadLn (a, b, c, d) ;
KOH
WriteLn(m, n)
End.
ните алгоритм деления простых дробей, записанный на АЯ, с соответствующей программой на Паскале:

Здесь учтено следующее математическое равенство:
а с _ a- d
Эту программу можно понять даже не заглядывая в учебник языка Паскаль, особенно зная английский язык.
Заголовок программы начинается со слова Program (программа), за которым следует произвольное имя, придуманное программистом (Division — деление). Раздел описания переменных начинается со слова Var (variables — переменные), за которым следует список переменных. Тип указывается после двоеточия словом Integer (целый). Начало и конец раздела операторов программы отмечаются словами Begin (начало) и End (конец). В конце программы обязательно ставится точка.
Ввод исходных данных с клавиатуры производится с помощью процедуры ReadLn (read line — считывать строку). На клавиатуре набирают четыре числа, отделяемые друг от друга пробелами, которые отражаются строкой на экране дисплея, и нажимают клавишу ввода.
Операторы присваивания в Паскале записываются так же, как в АЯ. Знак умножения обозначается звездочкой (*).
Вывод результатов на экран дисплея производится с помощью процедуры WriteLn (write line — писать в строку), которая выводит в строку два целых числа шип. После этого курсор на экране переходит в начало следующей свободной строки, и работа программы завершается.
Необходимо строго соблюдать правила правописания — синтаксис программы. В частности, в Паскале однозначно определено назначение знаков пунктуации:
точка с запятой (;) ставится в конце заголовка программы, в конце раздела описания переменных, после каждого оператора. Перед словом End точку с запятой можно не ставить;
запятая (,) является разделителем элементов во всевозможных списках (списке переменных в разделе описания, списке вводимых и выводимых величин).
• ■ I рогий синтаксис в языке программирования необходим, him жт* всего, для транслятора. Транслятор — это программа, ко- •npmi исполняется формально. Если, допустим, разделителем в « писке переменных должна быть запятая, то любой другой знак в и» и будет восприниматься как ошибка. Если точка с запятой явим ни разделителем операторов, то транслятор в качестве опера- ■ м(ш воспринимает всю часть текста программы от одной точки с Minnow до другой. Следовательно, если не поставить точку с за- и»пой между какими-то двумя операторами, транслятор будет принимать их за один, т.е. неизбежна ошибка.
Основное назначение синтаксических правил — это придание одно тачного смысла языковым конструкциям. Если какая-то конст- pVMimi может трактоваться двусмысленно, значит, в ней есть ошибка. Поэтому лучше не полагаться на интуицию, а выучить правила языка.
Далее будет дано строгое описание синтаксических правил Пас- **ны, а пока для получения первоначального представления о языке ••арашмея еще к нескольким примерам программирования не- I ножных алгоритмов.
-Оттранслируем» алгоритм вычисления факториала (N\) на и макс Паскаль:
•лг факториал цел N,I,F
м*ч ввод(И)
К :=1
I :=1
покаI<=N
нцF:=F*I
I:=I+1
кц
вывод F кон
Program Factorial;
Var N, I, F: Integer; Begin ReadLn(N);
F := 1;
I := 1;
While I <= N Do Begin F := F * I;
I := I + 1
End;
WriteLn(F)
End.
Из этого примера, во-первых, видно, как записывается на Паскале оператор цикла с предусловием (цикл «Пока»):
While <условие выполнения> Do <тело цикла>
While — пока, Do — делать. Если тело цикла содержит последо- тиольность операторов, то говорят, что оно образует составной шн-ратор, в начале и конце которого надо писать Begin и End. I лужебные слова Begin и End часто называют операторными скобками, объединяющими несколько операторов в один составной. 1тли же тело цикла — один оператор (не составной), то опера- трнмх скобок не требуется. Тогда транслятор считает, что тело никла заканчивается на ближайшем знаке «;».
Во-вторых, из примера видно, что в Паскале нет специальных слов для обозначения начала цикла (нц) и конца цикла (кц). На все случаи есть служебные слова Begin и End.
Program Roots;
Var a,b,с,d,xl,х2 : Real; Begin {Ввод данных с контролем}
Repeat
WriteLn('Введите a, b, c; aoO') ;
ReadLn(a, b, c)
Until a о 0;
{Вычисление дискриминанта} d := b*b - 4*a*c;
If d >= 0
Then Begin {Есть корни} xl := (-b + sqrt (d) )/2/a) ; x2 := (“b - sqrt (d) )/2/a) ; WriteLn('xl =', xl,
'x2 = ■, x2);
End
Else WriteLn('Нет вещественных корней')
End.
иначе вывод «Нет вещественных корней» кв кон
алг корни;
вещ а, Ь, с, d, xl, х2 нач
повторять
вывод «Введите а,Ь,с;
а Ф О») ввод а, Ь, с до а Ф О d := ЬА2 - 4ас
если d > О то
xl := (-b + sqrt (d))/(2a) х2 := (-b - sqrt (d))/(2a) вывод xl, x2
Рассмотрим еще один пример программы решения квадратного уравнения:
В этой программе по сравнению с приведенными ранее, появилось много новых элементов. Имя вещественного типа данных в Паскале — Real.
Цикл с постусловием (цикл «До») программируется оператором
Repeat <тело цикла> Until <условие окончания>
Repeat — повторять, Until — до. Тело цикла может представлять собой как одиночный, так и составной оператор, однако употребления слов Begin и End не требуется, поскольку слова Repeat и Until сами выполняют роль операторных скобок.
Знак ф (не равно) в Паскале имеет обозначение о, а знак > (больше или равно) обозначается >=.
Правила записи арифметических выражений будут подробно рассмотрены немного позже. Используемая в формулах вычисления корней стандартная функция квадратного корня (Vx), в Паскале записывается в виде sqrt (х). Порядок выполнения операций в вы-
I ими'I ш и определяется скобками и старшинством операций. Стар- иннк I но операций определяется так же, как в алгебре. Операции MiuiMiiKoiibie по старшинству выполняются в порядке их записи (i im'iiii направо).
Нетление в Паскале программируется с помощью условного • тсрапшра, имеющего следующую форму:
1Г условие> Then <оператор 1> Else <оператор 2>
If если, Then — то, Else — иначе. Операторы 1 и 2 могут быть как одиночными, так и составными. Составной оператор следует интючагь в операторные скобки Begin и End.
I iik же, как и в алгоритмическом языке, возможно использо- «11 ти* неполной формы условного оператора:
If :условие> Then <оператор>
Характерной чертой данной программы является использова- ннг и тексте комментариев. Комментарий — это любая последова- м'лыккть символов, заключенных в фигурные скобки {...}. Можно hi* *е использовать в качестве ограничителей комментариев круг- чыг скобки со звездочками (*...*). Комментарий не определяет никаких действий программы, а является лишь пояснительным 1см тм. Он может даваться в любом месте программы, где можно IHNтаиить пробел. Программист пишет комментарии не для компьютера, а для себя, придавая тексту программы большую яс-
IHMII.
Хорошо откомментированные программы называют самодоку- мептрованными. В некоторых программах объем комментариев превышает объем вычислительных операторов.
Удачное использование комментариев — признак хорошего стиля программирования.
Для выполнения программы на ЭВМ ее следует ввести в память, оттранслировать и исполнить. Для этого на компьютере должны иметься специальные средства программного обеспечения, fcumpbic на ПК составляют систему ТурбоПаскаль.
Упражнения
•< > ггранслировать» с алгоритмического языка на язык Паскаль:
а) алгоритм Евклида;
гн алгоритм выбора большего значения из трех;
и) алгоритм определения существования треугольника с заданными шишами сторон;
I) алгоритм умножения двух целых чисел, ограничиваясь только операциями сложения и вычитания;
а > алгоритм вычисления частного и остатка от целочисленного деления.
Некоторые сведения о системе ТурбоПаскальНазвание ТурбоПаскаль имеет два смысловых значения:
диалект, представляющий собой расширение стандартного языка Паскаль;
система программирования ТурбоПаскаль, являющаяся совокупностью системных программ, предназначенных для создания, отладки и выполнения Паскаль-программ.
Далее будем рассматривать именно ТурбоПаскаль, так как он реализован на основных типах персональных компьютеров (IBM PC и совместимых с ними).
Во избежание терминологической путаницы договоримся, что название ТурбоПаскаль означает язык программирования, а стандартный Паскаль входит в ТурбоПаскаль как подмножество. Поэтому далее везде, где речь будет идти о расширенных возможностях турбоварианта по сравнению со стандартным, это будет оговариваться.
Система программирования ТурбоПаскаль, или турбосистема, обеспечивает удобную операционную обстановку для работы программиста. Ее назначение — предоставлять пользователю необходимые средства работы с Паскаль-программой.
Система ТурбоПаскаль (как язык программирования и как операционная оболочка) значительно изменилась за историю своего существования. Первый ее вариант фирма Borland выпустила в середине 1980-х гг. Впоследствии этой фирмой было создано шесть модификаций системы, известных как версии 3.0, 4.0, 5.0, 5.5, 6.0, 7.0. Каждая из них представляет собой усовершенствованную предыдущую версию. Все они создавались для семейства машин IBM PC и совершенствовались вместе с ними.
Версия 3.0 ориентирована на ПК малой мощности (IBM PC/XT). Разрабатываемые на ней программы имеют ограничение на длину (не более 64 Кбайт), в ней нет средств раздельной компиляции взаимосвязанных программ и ее операционная среда весьма несовершенна.
Большие изменения были внесены в версию 4.0. Появились современная диалоговая среда, средства раздельной компиляции программных модулей, мощная графическая библиотека.
Версия 5.0 отличается в основном дальнейшим усовершенствованием среды, к которой добавлен встроенный отладчик. В эту версию впервые были включены средства поддержки объектно- ориентированного программирования — современной технологии создания программ.
Главные отличия версии 6.0 — это наличие новой среды, ориентированной на работу с устройством ввода типа «мышь» и использующей многооконный режим работы, наличие объектно-ориентированной библиотеки TurboVision, а также возможности включения в текст программы команды ассемблера.
Мерсии 7.0 не содержит каких-то принципиальных новшеств ни t равнению с версией 6.0. В ней введены некоторые расширения к и.и а программирования, а также дополнительные сервисные возможности системной оболочки.
Программа на ТурбоПаскале проходит три этапа обработки:
создание текста программы;
компиляция;
исполнение откомпилированной программы.
И соответствии с этими функциями турбосистема включает в м ни три главных компонента: редактор текстов, компилятор и И) ноинительную систему.
< помощью встроенного в систему текстового редактора можно формировать в памяти любые тексты, а не только программы ни 11пскале. В частности, это могут быть исходные данные решаемой ылачи в текстовой форме. Текст программы, созданный реви мором, можно сохранить на диске в виде файла с именем сле- iniuiitero формата:
имя файла>.РАБ
PAS — это стандартное расширение имени файла, созданного «in гемным редактором. Имя файла задается пользователем.
(>бращение к текстовому редактору происходит по команде Edit.
Компилятор переводит программу с языка Паскаль на язык машинных команд. При этом осуществляется контроль правильном н написания программы, т.е. выполнения правил языка программирования (синтаксический и семантический контроль). При оПпаружении ошибки компьютер выдает о ней сообщение пользо- иаимно и прекращает работу. Программа, полученная в результате компиляции, может быть сохранена на диске в файле с именем • лгмующего формата:
имя файла>.EXE
Работа компилятора инициируется системной командой Сот
ри*
Исполнение откомпилированной программы производится по команде Run. При этом исполнение программы остается под кон- iponcM турбосистемы, которая, в частности, помогает обнаружим. ошибку в программе, если при исполнении произошел сбой. Нищ. шпателю сообщается причина сбоя и его место в Паскаль- нршрлмме, после чего происходит автоматический возврат в режим редактирования.
В более поздних версиях ТурбоПаскаля имеется система отладки (Debug), с помощью которой можно просмотреть на экране •hii'ii’iihc любой переменной, найти значение любого выражения, установить новое значение переменной. Можно также прерывать выполнение программы в указанных местах, называемых контрольными точками. Система отладки существенно облегчает программисту поиск ошибок.
Подробные сведения о работе с конкретными версиями Тур- боПаскаля можно найти в специальной литературе.
Элементы языка ТурбоПаскальАлфавит. Алфавит языка ТурбоПаскаль включает в себя буквы, цифры и специальные символы:
латинские буквы от А до Z (прописные) и от а до г (строчные);
цифры 0, 1, 2, 3, 4, 5, 6, 7, 8, 9;
шестнадцатеричные цифры 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, А, В, С, D, Е, F;
специальные символы +-*/ = <>[]. ,():;{} л @ $ #.
Следующие комбинации специальных символов являются едиными символами, которые нельзя разделять пробелами:
:=знак присваивания;
>=больше или равно;
<=меньше или равно;
оне равно;
(* *) ограничители комментариев (наряду с { });
(. .)эквивалент [ ].
Пробелы — это символ пробела (ASCII-32) и все управляющие символы кода ASCII (от 0 до 31).
К специальным символам относятся также служебные слова, смысл которых определен однозначно и которые не могут быть использованы для других целей. Для языка — это единые символы.
Служебные слова языка ТурбоПаскаль: absolute, and, array, begin, case, const, div, do, downto, else, end, external, file, for, forward, function, goto, if, implementation, in, inline, interface, interrupt, label, mod, nil, not, of, or, packed, procedure, program, record, repeat, set, shl, shr, string, then, to, type, unit, until, uses, var, while, with, xor.
Последние версии языка ТурбоПаскаль содержат также ряд служебных слов, относящихся к работе с объектами и встроенным ассемблером.
Идентификаторы. Идентификатором называется символическое имя определенного программного объекта: константы, переменные, типы данных, процедуры, функции, программы. С помощью синтаксической диаграммы идентификатор можно представить в виде, показанном на рис. 2.1.
Идентификатору ^ ► < Буква > ►< Цифра > Рис. 2.1. Синтаксическая диаграмма идентификатора
I’дешифровать диаграмму можно следующим образом: идентификатор — это любая последовательность букв и цифр, начинаю- шано1 с буквы. В ТурбоПаскале к буквам приравнивается также •ник подчеркивания.
< Тройные и прописные буквы в идентификаторах и служебных < ионах не различаются. Например: шах, МАХ, МаХ, тАх — одно и ш же имя.
Н ТурбоПаскале длина идентификатора может быть произвольной. но значащими являются только первые 63 символа.
Комментарии. Конструкции следующего вида представляют со- Оий комментарии и поэтому игнорируются компилятором:
Iмюбой текст, не содержащий символ «}» }
(+ любой текст, не содержащий символы «*)» *)
by к вы русского алфавита употребляются только в комментариях, литерных и текстовых константах.
( ipoxa, начинающаяся с символов «{$» или «(*$», является директивой компилятора. За этими символами следует мнемоника мнялилы компилятора.
Концепция типов данныхКонцепция типов данных является одной из центральных в ihoOom языке программирования. С типом величины связаны три *'«• гиойства: форма внутреннего представления, множество прими маемых значений и множество допустимых операций. Турбо- I Inc кадь характеризуется большим разнообразием типов данных (риг. 2.2).
В стандартном Паскале отсутствует строковый тип данных. Кроме юн», и ТурбоПаскале целые и вещественные — это группы типов дянных. В более поздних версиях ТурбоПаскаля существуют процедурный тип данных и тип данных «объект».
Каждый тип данных имеет свой идентификатор.
И табл. 2.1 представлена информация о простых типах данных, •>н|)сдсленных в ТурбоПаскале. Для вещественных типов данных в «м»г>ках указано количество сохраняемых значащих цифр мантис- «ы н десятичном представлении числа.

Рис. 2.2. Структура типов данных ТурбоПаскаля
Типы данных ТурбоПаскаля
Таблица 2.1
Идентификатор Длина, байт Диапазон (множество) значений
Целые
Integer 2 -32768..32767
Byte 1 0..255
Word 2 0..65535
Shortint 1 -128.. 127
Longint 4 -2147483648..2147483647
Вещественные
Real 6 2,9 10-39— 1,7 1038 (11 —12)
Single 4 1,5-1045—3,4-10» (7-8)
Double 8 5 10-324—1,7 10» (15 —16)
Extended 10 3,4 1<Н*»—1,1 104932 (19—20)
Логический
Boolean 1 True, False
Символьный
Char 1 Все символы кода ASCII
В стандартном Паскале из вещественных типов определен только тип Real, а из целых — Integer.
Типы данных Single, Double, Extended употребляются в Паскаль-программах только в том случае, если ПК снабжен сопроцессором «плавающей арифметики». (Для процессоров IBM PC, начиная с Intel-80486 и далее, это условие всегда выполняется.)
Тип данных называется порядковым, если состоит из счетного числа значений, которые можно пронумеровать. Отсюда следует, что для этого множества значений существуют понятия «следующий» и «предыдущий».
Описание переменных. Для всех переменных величин, используемых в программе, должны быть указаны их типы в разделе переменных. Структура раздела переменных показана на рис. 2.3.
Пример раздела переменных программы:
Var ш, n, k : Integer; х, у, z : Real;
Symbol : Char;
Константы. Тип константы определяется по контексту, т.е. по форме ее записи в программе.
Целые десятичные константы записывают в обычной форме целого числа со знаком или без знака. Например: 25, -24712, 376.
Целые шестнадцатеричные константы записывают с префиксом «$». Они должны находиться в диапазоне от $00000000 до SFFFFFFFF.
Вещественные константы с фиксированной точкой записывают в обычной форме десятичного числа с дробной частью. Разделителем целой и дробной частей является точка. Например: 56.346, 0.000055, -345678.0.
Вещественные константы с плавающей точкой имеют следующую форму:
<мантисса>Е<порядок>
Здесь <мантисса> — целое или вещественное число с фиксированной точкой, <порядок> — целое число со знаком или без знака. Например: 7Е-2 (7 -10'2), 12.25Е6 (12,25 106), 1Е-25 (10'25).
TOC \o "1-5" \h \z <Раздел переменных> ,,, _
■- Var —г—*- «Эписание переменных>
1о 1
«Эписание переменных>^_
► <Идентификатор> —►—► <Тип> —►
1О-1
<Описание константы>
тгы>^
► <Идентификатор> —► {^) —► <Константа> —►
Рис. 2.4. Структура раздела констант
Символьная константа — это любой символ алфавита, заключенный в апострофы. Например: 'W, Т, ’9\
Логическая константа— это слова: True, False.
Строковая константа — это строка символов, заключенная в апострофы. Например: TurboPascal*, ’Ответ: *, '35-45-79*. Максимальная длина строковой константы 255 символов.
Константе может быть поставлено в соответствие определенное имя, назначение которого производится в разделе констант программы. Например:
Const
Мах = 1000;
G = 9.81;
Cod = 1 Ошибка1;
Структура раздела констант показана на рис. 2.4. В ТурбоПаска- ле допустимо также употребление типизированных констант. Типизированная константа аналогична переменной, которой задается начальное значение. Причем происходит это на этапе компиляции. Например:
Const NumberCard : Integer = 1267;
Size
Symbol
12.67;
: Real : Char
Описание типизированной константы приведено на рис. 2.5.
В ТурбоПаскале имеется ряд имен, зарезервированных за определенными значениями констант, которые можно использовать без предварительного определения в программе (табл. 2.2).
Типы данных пользователя. Один из принципиальных моментов языка Паскаль состоит в том, что пользователю разрешается
< Раздел констант>
Const
«Описание константы>
<Типизированная константа>
< Константа >►
Рис. 2.5. Описание типизированной константы
Идентификатор Тип Значение
True Boolean ИСТИНА
False Boolean ЛОЖЬ
Maxlnt Integer 32767
Зарезервированные константы ТурбоПаскаля
определять свои типы данных. Причем типы данных пользователя всегда базируются на стандартных типах данных Паскаля.
Для описания типов данных пользователя в Паскале существует раздел типов, структура которого представлена на рис. 2.6.
Данные перечисляемого типа (рис. 2.7) задаются непосредственно перечислением всех значений, которые может принимать переменная данного типа.
Определенное имя типа данных затем используется для описания переменных. Например:
Type Gaz = (С, О, N, F);
Metal = (Fe, Со, Na, Си, Zn);
Var Gl, G2, G3: Gaz;
Metl, Met2: Metal;
Day: (Sun, Mon, Tue, Wed, Thu, Fri, Sat);
Здесь Gaz и Metal — имена перечисляемых типов данных, которые ставятся в соответствие переменным Gl, G2, G3 и Metl, Met2. Переменной Day назначается перечисляемый тип данных, которому не присвоено имени.
<Раздел типов>
Туре
«Описание типа>
— О —
«Эписание типа>
<Имя типа>
0<Тип>■
Значения, входящие в перечисляемый тип данных, являются константами. Действия над ними подчиняются правилам, приме-
< Перечислимый тип>
©< Идентификатор>
О —

Рис, 2.6. Структура раздела типов данных
< Интервальный тип>v/-ч
»- <Константа>►■- <Константа>
Рис. 2.8. Описание интервального типа данных
няемым к константам. Каждое значение в перечисляемом типе занимает в памяти 2 байт, поэтому число элементов не должно превышать 65 535.
Перечисляемый тип данных — упорядоченное множество. Его элементы пронумерованы, начиная от 0 в порядке следования в описании.
В программе, в которой имеется приведенное ранее описание, возможено наличие следующего фрагмента:
If Day = Sun Then WriteLn('Ура! Сегодня выходной!');
Данные интервального типа (рис. 2.8) задаются как упорядоченное ограниченное подмножество некоторого порядкового типа.
Порядковый номер первой константы не должен быть больше номера второй константы в данных соответствующего базового типа.
При исполнении программы автоматически контролируется принадлежность значений переменной интервального типа установленному диапазону. При выходе из диапазона исполнение программы прерывается. Например:
Type Numbers = 1..31;
Alf = 'А'..'Z';
Var Data: Numbers;
Bukva: Alf;
Арифметические операции, функции, выражения. Оператор присваиванияК арифметическим типам данных относятся группы вещественных и целых типов данных. К ним применимы арифметические операции и операции отношений.
Различают операции над данными унарные (применимые к одному операнду) и бинарные (применимые к двум операндам).
Унарная арифметическая операция одна — это операция изменения знака следующего формата:
—<величина>.
Бинарные арифметические операции стандартного языка Паскаль описаны в табл. 2.3, где I — данные целого типа, a R — вещественного.
Знак Выражение Типы операндов Тип результата Операция
+ А+В R, R R Сложение
I, I I I, R; R, I R - А-В R, R R Вычитание
I, I I I, R; R, I R * А* В R, R R Умножение
I, I I I, R; R, I R / А/В R, R R Вещественное
I, I R деление
I, R; R, I R div A div В I, I I Целое деление
mod A mod В I, I I Остаток от целого
деления
Бинарные операции Паскаля
К арифметическим величинам могут быть применены стандартные функции языка Паскаль. Структура обращения к функции представлена на рис. 2.9.
Функция в выражении выступает как операнд. Например, в операторе присваивания
X := 2 * sin(А)/1п(3.5) + cos(С - D)
операндами являются три функции: sin, In, cos, записываемые так же, как в математике. Аргументы называются фактическими параметрами, являются в общем случае выражениями арифметического типа и записываются в круглых скобках. Результатом вычисления функции является величина соответствующего типа.
<Функция> <Имя функции>-»- (V) I » <Фактический параметр>-г»- (Т)
то-Г'
Табл. 2.4 содержит описания стандартных математических функций ТурбоПаскаля.
Арифметическое выражение задает порядок выполнения действий над числовыми величинами. Арифметические выражения содержат арифметические операции, функции, операнды, круглые скобки. Одна константа или одна переменная — это простейшая форма арифметического выражения.
Например, математическое выражение
2а + у]0,5 sin(x + у)
2с - 1п(х - у)
записанное по правилам языка Паскаль будет иметь вид
(2 * А + sqrt (0.5 * sin(X + Y) ) ) / (0.2 * С - In (X - Y) ) .
Стандартные математические функции ТурбоПаскаля
Таблица 2.4
Обращение Тип
аргумента Тип
результата Функция
Pi — R Число л = 3.1415926536Е-ЙЮ
abs (х) I, R I, R Модуль аргумента х
arctan (х) I, R R Арктангенс х, рад
cos (х) I, R R Косинус х, рад
exp (х) I, R R ех — экспонента х
frac (х) I, R R Дробная часть х
int (х) I, R R Целая часть*
1п(х) I, R R Натуральный логарифм *
random R Псевдослучайное число в интервале [0, 1)
random (х) I I Псевдослучайное число в интервале [0, х)
round (х) R I Округление х до ближайшего целого
sin (х) I, R R Синус х, рад
sqr (х) I, R I, R Квадрат х
sqrt (х) I, R R Корень квадратный из х
trunc (х) R I Ближайшее целое, не превышающее х по модулю
Для верной записи арифметических выражений следует соблюдать определенные правила.
Все символы писать в строку, т.е. на одном уровне. Проставлять все знаки операций, не пропуская знак «*».
Не допускать записи двух знаков операций подряд, т. е. нельзя писать А + -В, следует писать А + (-В).
Операции с более высоким приоритетом выполняют раньше операций с меньшим приоритетом. Порядок убывания приоритетов операций следующий:
вычисление функции;
унарная операция смены знака (-);
*, /, div, mod;
+» -•
Несколько записанных подряд операций с одинаковым приоритетом выполняют последовательно слева направо.
Часть выражения, заключенная в скобки, вычисляется в первую очередь. (Например, в выражении (А + В) * (С - D) умножение производится после сложения и вычитания.)
Не следует записывать выражения, не имеющие математического смысла, например: деление на нуль, логарифм отрицательного числа и т.п.
Приведем пример. Арифметическое выражение, записанное по указанным правилам (цифрами в кружке указан порядок выполнения операций),
® © ® © ® 0 © © © © ©®
(1+у)*(2*х + sqrt(y) - (х + у))/(у + l/(sqrt(x) - 4))
соответствует следующей математической формуле:
(1 +у)2х*'Гу-[х*у).
В Паскале нет операции или стандартной функции возведения числа в произвольную степень. Для вычисления ^рекомендуется поступать следующим образом:
если у — целое значение, следует использовать умножение, например: хг -»х * х * х. Для больших степеней следует использовать умножение в цикле;
если у — вещественное значение, используется следующая математическая формула: ху = еу]п(х), запись которой на Паскале имеет вид
exp(Y * In(х))
—► <Арифметическое выражение> ►
Рис. 2.10. Структура арифметического оператора присваивания
Очевидно, что при вещественном типе у недопустимо нулевое или отрицательное значение х. Для у целого типа такого ограничения нет.!
Например, формула 1]а + 1 = (а + 1)^, записанная на Паскале будем иметь вид
ехр(1/3 * In(А + 1))
Выражение имеет целый тип, если в результате его вычисления получается величина целого типа. Выражение имеет вещественный тип, если результатом его вычисления является вещественная величина.
Арифметический оператор присваивания имеет структуру, представленную на рис. 2.10.
Например, это может быть запись вида
Y := (F * N — 4.5)/cos(X).
Порядок выполнения оператора присваивания рассматривался ранее. Следует только обратить внимание на следующее правило: типы переменной и выражения должны быть одинаковыми. Исключением является случай, когда выражение имеет целый тип, а переменная — вещественный.
Упражнения
1. Записать арифметические выражения на Паскале для следующих формул:,
а) а + bx + cyz\ б) [(ах- b)x + с]х- d\ в) + —;
Г) £±2_£г_; д) Ю4а-з1р;
а, х-у’5
е)
3 + ху Г
2. Записать математические формулы, соответствующие следующим выражениям на Паскале:
с ab
а)(р + q) / (г + s) - р * q/ (г * s) ;
б)1ЕЗ + beta/(х - gamma * delta);
в)a/b * (с + d) - (а - Ь)/b/с + 1Е - 8.
3. Почему в Паскале аргумент функции всегда записывают в скобках, например пишут 1п(5), а не In 5?
4. Записать соответствующие арифметические выражения на Паскале для следующих формул:
а) (1 + х)2; б) V1 + х2;
д) arcsin х; е)

Вычислить значения следующих выражений:
в) cos2*2;г) log2 j;
ж)з) ^ 1 + х;
а)trunc (6.9);
б)trunc(6.2) ;
в)20 div 6;
г)2 div 5;
д)round(6.9);
е)round(6.2) ;
ж)20 mod 6;
з)2 mod 5;
и)3 * 7 div 2 mod 7/3 - trunc(sin(1)).
Определить типы следующих выражений:
а)1 + 0.0;
б)20/4;
в)sqr (4) ;
г)sqrt (16);
д)sin (0) ;
е)trunc(-3.14).
Определить, какие из следующих операторов присваивания правильные, если у — вещественная переменная, а п— целая:
а)у := n + 1;
б)п := у - 1;
в)п := 4.0;
г)у := trunc (у) ;
д)у := n div 2;
е)у := у div 2;
ж)п := п/2;
з)n := sqr(sqrt (n)).
Поменять местами значения целых переменных х и у, не используя дополнительные переменные. Определить недостаток найденного алгоритма по сравнению с методом обмена значений через третью переменную. Можно ли применять данный алгоритм для вещественных чисел?
Присвоить целой переменной И значение цифры, стоящей в разряде сотен в записи положительного целого числа к (например, если к = = 28 796, то h = 7).
Присвоить целой переменной S значение суммы цифр трехзначного целого числа к.
И. Определить, какую задачу решает следующая программа:
Program Test;
Type Natur = l..MaxInt;
Var N : Natur;
X : Real;
Begin ReadLn(N);
X := 0;
While N > 0 Do
Begin
X := X + 1.0;
N := N - 1
End;
WriteLn(X)
End.
Указать, можно ли полученный результат получить более простым способом.
Ввод данных с клавиатуры и вывод на экранВвод данных — это передача информации от внешних устройств в оперативную память. Вводятся, как правило, исходные данные решаемой задачи.
Вывод данных — это передача данных из оперативной памяти на внешние носители (печать, дисплей, магнитные устройства и т.д.). Результаты решения любой задачи должны быть выведены.
Основными устройствами ввода-вывода персонального компьютера являются клавиатура и дисплей (экран монитора). Именно через эти устройства, главным образом, осуществляется диалог между человеком и ПК.
Процедура ввода с клавиатуры имеет следующий формат:
Read(<cnncoK ввода>)
Здесь <список ввода> — это последовательность имен переменных, разделенных запятыми, a Read (читать) — оператор обращения к стандартной процедуре ввода. Например:
Read(а, b, с, d)
При выполнении этого оператора работа компьютера прерывается, после чего пользователь набирает на клавиатуре значения переменных a, b, с, d, отделяя их друг от друга пробелами. При этом вводимые значения высвечиваются на экране. В конце набора нажимают клавишу <Enter>: Ввод значений должен выполняться в строгом соответствии с синтаксисом языка Паскаль. Например, при выполнении ввода в программе
Var T : Real;
J : Integer;
К : Char;
Begin
Read(T, J, K); на клавиатуре следует набрать
253.98 100 G [Enter].
Если в программе имеется несколько операторов Read, то данные для них вводятся потоком, т.е. после считывания значений переменных для одного оператора Read данные для следующего оператора до окончания строки считываются из той же строки на экране, что и для предыдущего затем происходит переход на следующую строку. Например, при выполнении ввода в программе
Var А, В : Integer;
С, D : Real;
Begin
Read(А, В);
Read(С, D);
на клавиатуре следует набрать
18758 34[Enter] 2.62Е-02 1.54Е+01[Enter].
Оператор ввода с клавиатуры также может иметь вид
ReadLn(ссписок ввода>)
Здесь ReadLn (от read line) — считать строку. В отличие от оператора Read после считывания последнего в списке значений для одного оператора ReadLn данные для следующего оператора ReadLn будут считываться с начала новой строки. Если в предыдущем примере заменить оператор Read на ReadLn, т.е. записать
ReadLn(А, В);
ReadLn(С, D);
ввод значений будет происходить из двух строк:
18758 34 [Enter]
2.62Е-02 1.54Е+01 [Enter]
Оператор вывода на экран (обращение к стандартной процедуре вывода) имеет следующий формат:
Write(ссписок вывода>)
Здесь элементами списка вывода могут быть выражения различных типов (в частности, константы и переменные), например:
Write(234);{Выводится целая кон
станта)
Write(А + В — 2);{Выводится результат
вычисления выражения)
Write (X, Suitima, Argl, Arg2) ; {Выводятся значения
переменных}
При выводе на экран нескольких чисел в строку они не отделяются друг от друга пробелами, об этом должен позаботиться программист. Пусть, например, I=1;J = 2;K = 3. Тогда при выполнении оператора
Write(I,'', J, '\ К);
на экране получим следующую строку: 1 2 3. Причем после вывода последнего символа курсор останется в той же строке, и следующий ввод на экран будет начинаться с этой позиции курсора.
Процедура вывода на экран также может иметь вид
WriteLn(<список вывода>)
Здесь WriteLn (от Write line) — записать строку. Действие этого оператора отличается от Write тем, что после вывода последнего н списке значения происходит перевод курсора в начало следующей строки. Оператор WriteLn, записанный без параметров, выполняет перевод строки.
Форматы вывода. Список вывода может содержать указатели форматов вывода (форматы). Формат определяет представление выводимого значения на экране и отделяется от соответствующего ему элемента двоеточием. Если указатель формата отсутствует, машина выводит значение по определенному правилу, предусмотренному по умолчанию.
Далее кратко в справочной форме приведем правила и примеры бесформатного и форматированного вывода величин различных типов. Для представления списка вывода используем следующие обозначения:
I, I', О — целочисленные выражения;
К выражение вещественного типа;
И выражение булевского типа;
< h символьная величина;
S строковое выражение; и цифра;
1 шах «+» или «-»; пробел.
Форматы процедуры Write
I выводится десятичное представление величины I, начиная • мо пщии расположения курсора:
Ылчсние I Оператор Результат
1 1-1 Write(I) 134
‘II / Write(I,1,1) 287287287
1:1’ — выводится десятичное представление величины I в крайнее правые позиции поля шириной Р.
tihi'icjiHe I Оператор Результат
1 14 Write (1:6) 134
\ 1 Write((I + I) : 7) 624
К в поле шириной 18 символов выводится десятичное пред- «1(пппч1ие величины R в формате с плавающей точкой (если Я> 0.0, in пользуется формат#.##########Е*##; если R<0.0, фор
ма) имеет вид _-#.##########Е*##):
tini'icnne R Оператор Результат
MS.<132 Write(R) 7.1543200000E+02
1.Ч19Е+01 Write(R) -1.9190000000E+01
И: Р — в крайние правые позиции поля шириной Р символов выводится десятичное представление значения R в нормализованном формате с плавающей точкой. Минимальная длина поля вывода для положительных чисел составляет семь символов, для нфинатсльных — восемь. После точки выводится по крайней мере o Hiii цифра:
R Оператор Результат
Write (R : 15) 5.110400000E+02
Write (-R : 12) -4.67800E+01
lllil'K'HHC
■.11.04 И,. /8
R:P:Q — в крайние правые позиции поля шириной Р символов выводится десятичное представление значения R в формате с фиксированной точкой, причем после десятичной точки выво дится Q цифр (0 < Q < 24), представляющих собой дробную часп. числа (если Q = 0, то ни дробная часть, ни десятичная точка нс выводятся; если Q > 24, то при выводе используется формат с плавающей точкой):
Значение R Оператор Результат
511.04 Write (R : 8 : 4) 511.0400
-46.78 Write (R : 7 : 2) 46.78
Ch: Р — в крайнюю правую позицию поля шириной Р выводится значение Ch:
Значение Ch Оператор Результат
'X' Write(Ch : 3) X
i i i Write (Ch : 2, Ch : 4) 1 1
S — начиная с позиции курсора выводится значение S:
Значение S Оператор Результат
'Day N' Write(S) Day N
'RRDD' Write (S,S) RRDDRRDD
S: Р — значение S выводится в крайние правые позиции поля шириной Р символов:
Значение S Оператор Результат
'Day N’ Write(S : 10) Day N
'RRDD' Write(S : 5, S : 5) _RRDD_RRDD
В — выводится результат выражения В (True или False), нами ная с текущей позиции курсора:
Значение В Оператор Результат
True Write(B) True
False Write(B, Not B) FalseTrue
В: Р — в крайние правые позиции поля шириной Р символов выводится результат булевского выражения:
Значение В Оператор Результат
True Write(B : 6) True
False Write(B : 6, Not В : 7) _FalseTrue
Управление символьным выводом на экранИспользование для вывода на экран только процедур Write и Wiiirl.n обеспечивает программисту очень мало возможностей по управлению расположением на экране выводимого текста. Печать и кс ш может производиться только сверху вниз, слева направо. При этом невозможны возврат к предыдущим строкам, стирание напечатанного текста, изменение цвета символов и т.д.
Дополнительные возможности управления выводом на экран мПггпсчивают процедуры и функции модуля CRT. Для установлении снизи пользовательской программы с этим модулем перед разменами описаний должна быть поставлена строка
CRT
Рассмотрим понятия, необходимые при работе с модулем CRT: Р* *имы экрана, координаты позиции на экране, текстовое окно, ihm'i фона и цвет символа.
Режимы экрана. Во-первых, вывод на экран может происхо- ии11. и текстовом или графическом виде (на графических дисплеем) Мы здесь будем говорить только о текстовом выводе.
Дисплеи могут бьггь монохроматическими (черно-белыми) и 1ННЧНЫМИ. Монохроматические дисплеи могут работать только в черно белом режиме, а цветные — как в черно-белом, так и в ihm'i мом. Кроме того, текстовые режимы различаются по числу • им вольных строк и столбцов, умещающихся на экране.
И модуле CRT каждый режим имеет определенный номер, за которым закреплено символическое имя (описанная константа). Ним установки режима экрана используется процедура
T«xtMode(<номер режима>).
11ри обращении к процедуре <номер режима> может задавать- I и мик числом, так и именем соответствующей константы. Например. эквивалентны следующие два оператора:
T>'XtMode (1) ;
т.-xtMode (СО40) ;
Кик правило, исходный режим экрана, устанавливаемый по умолчанию, — СО80 (на цветных дисплеях).
Координаты позиции. Каждая символьная позиция на текстовом >кране определена двумя координатами (X, У). Координата X— in * limn» в строке. Крайняя левая позиция в строке имеет координат .V I. Координата У— номер строки, в которой находится гнмппл. Строки нумеруются сверху вниз.
Например, в режиме 80 х 25 символ в верхнем левом углу экрана имеет координаты (1; 1), символ в нижнем правом углу экрана— (80; 25); символ в середине экрана — (40; 13).
Для установления курсора на экране в позицию с координатами (X, Y) в модуле CRT существует процедура
GoToXY(X,Y)
Здесь координаты курсора задаются выражениями типа Byte.
Приведем для примера программу, которая очищает экран и выставляет в центре экрана символ «*»:
Uses CRT;
Begin
ClrScr;
GoToXY(40,13);
Write ('*')
End.
Используемая здесь процедура ClrScr выполняет очистку экрана.
Текстовое окно. Прямоугольное пространство на экране, в которое производится вывод символов, называется текстовым окном. Положение этого окна определяется координатами верхнего левого и нижнего правого углов прямоугольника. Если окно занимает весь экран, то в режиме 80 х 25 его координаты (1; 1) и (80; 25). Это исходное окно, изменить положение и размер которого можно с помощью процедуры
Window (XI, Yl, Х2, Y2)
Здесь аргументы — величины типа Byte; (XI, Y1) — координаты верхнего левого угла окна; (Х2, Y2) — координаты правого нижнего угла окна.
После определения окна попытки вывода символов за его пределы окажутся безрезультатными. Повторное обращение к процедуре Window с новыми параметрами отменяет предыдущее назначение.
Управление цветом. На цветных дисплеях типа EGA, VGA и SVGA в текстовом режиме экрана можно использовать 16 цветов.
В модуле CRT объявлены константы, имена которых есть английские названия цветов, а соответствующие им значения — порядковые номера этих цветов.
Процедура назначения цвета фона
TextBackGround(Color)
Здесь аргумент — величина типа Byte, задающая номер цвета.
TextColor(Color)
Если цвет фона назначается до очистки текстового окна, то после очистки оно «заливается» этим цветом. Если фон устанавливается после очистки экрана, то чистое окно будет иметь черный цвет (по умолчанию), а назначенный цвет фона будет устанавливаться в тех позициях, в которые выводятся символы.
Для примера приведем программу, которая по очереди откроет четыре окна, и каждое из этих окон «зальется» разным фоновым цветом:
Uses CRT;
Begin
Window(1, 1, 40, 12);
TextBackGround(White) ; ClrScr;
Window(41, 1, 80, 12);
TextBackGround(Red); ClrScr;
Window(l, 13, 40, 25);
TextBackGround(LightRed) ; ClrScr;
Window(41, 13, 80, 25);
TextBackGround(Green) ; ClrScr;
End.
По следующей программе на белом фоне в середине экрана будут выведены номера первых пятнадцати цветов, и каждый номер будет того цвета, который он обозначает:
Uses CRT;
Var I : Byte;
Begin
TextBackGround(White);
ClrScr;
GoToXY(1, 12);
For I := 0 To 14 Do
Begin
TextColor(I);
Write(1:5)
End
End.
Кратко опишем еще несколько процедур управления текстовым экраном из модуля CRT, не имеющих параметров:
• процедура ClrEOL — стирает часть строки от текущей позиции курсора до конца этой строки в окне. При этом положение курсора не изменяется;
процедура DelLine — уничтожает всю строку с курсором. При этом нижние строки сдвигаются на одну вверх;
процедура InsLine — вставляет пустую строку перед строкой, в которой стоит курсор;
процедуры LowVideo, NormVideo, HighVideo — устанавливают соответственно режимы пониженной, нормальной и повышенной яркости символов.
Весьма полезной является функция KeyPressed из модуля CRT, при исполнении которой происходит опрос клавиатуры и определяется, не нажата ли какая-нибудь клавиша. В результате эта функция выдает логическое значение True, если нажата любая клавиша, и значение False — в противном случае. Часто данную функцию используют для организации задержки окна результатов на экране (после выполнения программы ТурбоПаскаль вызывает на экран окно редактора), для чего перед концом программы записывают следующий оператор:
Repeat Until KeyPressed;
Это пустой цикл, который «крутится на месте» до нажатия какой-либо клавиши. В это время на экране выведено окно результатов. После нажатия клавиши значение KeyPressed станет равно True, цикл завершится, исполнение выйдет на конец программы и на экран вернется окно редактора. Этот прием можно использовать для задержки выполнения программы в любом ее месте.
В приведенную ранее программу получения на экране четырех разноцветных окон внесем следующее дополнение: после установки четырехцветного экрана выполнение программы останавливается и изображение сохраняется, а затем после нажатия любой клавиши экран возвращается в исходное состояние (80x25, черный фон, белые символы). Для этого перед концом программы следует добавить следующее:
Repeat Until KeyPressed;
Window(1, 1, 80, 25);
TextBackGround(Black);
ClrScr;
Описание других процедур и функций модуля CRT приведено в специальной литературе по ТурбоПаскалю.
Упражнения
Определить, что будет напечатано следующей программой, если в качестве исходных данных заданы числа 1.0 и -2.0:
Program Roots;
Var В, C, D : Real;
Bagin
Read(B, C);
D := Sqrt(Sqr(B) - 4 * C) ;
WriteLn( 'xl = ',(-B + D)/2,
1 x2 = ',(—В - D) /2)
End.
Определить, что будет напечатано следующей программой при последовательном введении значений 3.4 и 7.9:
Program Less;
Var X : Real; T : Boolean;
Begin
Read(X);
T := X < Round(X);
Read(X);
T := T And (X < Trunc(X));
WriteLn(T)
End.
Определить, что будет напечатано следующей программой при последовательном введении значений 36, -6 и 2345:
Program АВС;
Var А, В : Integer;
Begin
Read(А, В, А);
WriteLn(А, В : 2, А : 5)
End.
Составить программу вычисления суммы двух целых чисел, которая будет вести диалог с пользователем в следующем виде (вместо отточий — вводимые и выводимые числа):
Введите два слагаемых
а =
b =
Результат вычислений: а + b =
Логические величины, операции, выраженияВ подразд. 1.4 уже говорилось о логических величинах, логических операциях, логических выражениях. Напомним, что величина логического типа может принимать всего два значения: ИСТИНА и ЛОЖЬ.
<Операция отношения>
<Выражение>
<3нак отношения>
□<Выражение>►
Рис. 2.11. Структура операции отношения
В Паскале логические значения обозначаются служебными словами False (F) и True (Т), а идентификатор логического типа Boolean.
Кроме величин (констант и переменных) типа Boolean, логические значения False, True принимают результаты операций отношения.
Операции отношения осуществляют сравнение двух операндом и определяют, истинно или ложно соответствующее отношение между ними.
Структура операции отношения представлена на рис. 2.11, где
<знак отношения> ::== (равно) | о (не равно) |
> (больше) | < (меньше) | >= (больше или равно) |
<= (меньше или равно).
Приведем примеры записи отношений:
х < у; а + b >= c/d; abs (m — n) <= 1.
и примеры вычисления значений отношений:
Отношение Результат
12 >= 12 True
56 > 10 True
11 <= 6 False
Логические операции выполняются над операндами булевского типа. Имеются четыре логические операции: Not — отрицание; And — логическое умножение (конъюнкция); Ог — логическое сложение (дизъюнкция). Кроме этих трех обязательных операций, в ТурбоПаскале имеется еще операция «Исключающее ИЛИ», обозначаемая служебным словом Хог. Это двухместная операция, которая в результате дает значение ИСТИНА, если оба операндп имеют разные логические значения.
Логические операции были перечислены в порядке убывании приоритетов. Результаты выполнения логических операций для различных значений операндов приведены в табл. 2.5.
Результаты выполнения логических операций

Операции отношения имеют самый низкий приоритет, поэтому если операндами логической операции являются отношения, их следует заключать в круглые скобки. Например, математическому неравенству 1 <х< 50 соответствует следующее логическое иыражение:
(1 <= х) And (х <= 50)
Логическое выражение — это логическая формула, записанная ни языке программирования. Логическое выражение состоит из логических операндов, связанных логическими операциями и круглыми скобками. Результатом вычисления логического выражения инлиется булевская величина (False или True). Логическими операндами могут быть логические константы, переменные, функции, операции отношения. Один отдельный логический операнд инлиется простейшей формой логического выражения.
Приведем примеры логических выражений, в которых d, b, v логические числа; х, у — вещественные; к — целая переменили:
1) х < 2 * у; 2) True;3) d;
Odd (к);5) Not Not d; 6) Not (x > y/2);
d And (x о у) And b;
(c Or d) And (x = y) Or Not b.
При d = True, b = False, c = True, x = 3.0, у = 0.5, к = 5 результаты пмчислений будут следующими:
False;2) True;3) True;4) True;
True;6) False;7) False;8) True.
В данном примере использована логическая функция Odd (х). 'Ото функция от целого аргумента х, которая принимает значение True, если значение х нечетное, и значение False, если оно четное.
<Логический оператор присваивания^
^Логическая переменная>
□—(J)—<Логическое выражение > —*-
Рис. 2.12. Структура логического оператора присваивания
Логический оператор присваивания имеет структуру, представленную на рис. 2.12.
Приведем примеры логических операторов присваивания:
d := True;
b := (х > у) And (ко 0);
с := d Or b And Not(Odd(к) And d).
Функции, связывающие различные типы данныхВ табл. 2.6 приведен список стандартных функций, обеспечивающих связь между различными типами данных.
Функции Ord, Pred и Succ применимы только к порядковым типам данных, т. е. из простых типов данных ко всем, кроме вещественных.
Функция Ord, применяемая к целому числу, дает его собственное значение. Например:
Ord(-35) = -35; Ord(128) = 128
Таблица 2.6
Стандартные функции, связывающие различные типы данных
Обращение Тип аргумента Тип результата Действие
Ord (х) Любой
порядковый I Дает порядковый номер значения х в его типе
Pred (х) То же Тот же, что ух Дает предыдущее по отношению к х значение в его типе
Succ (х) » Тот же, что ух Дает следующее по отношению к х значение в его типе
Chr (х) Byte Char Дает символ с порядковым номером х
Odd (х) I Boolean Дает True, если х — нечетное число, и False, если х — четное
Если аргумент целый, то, например, оператор у := Pred(x) эквивалентен у := х - 1, а оператор у := Succ(x) эквивалентен у := х + 1.
Для аргумента символьного типа эти функции дают соответственно предыдущий и следующий символы в таблице внутренней кодировки. Поскольку латинский алфавит всегда упорядочен по кодам, т.е.
Ord('a') < Ord('b') < ... < Ord('z')/ то, например, можно записать
Pred('b’) = 'a*; Succ(’b’) = 'с'.
То же относится и к цифровым литерам:
Pred('5') = '4'; Succ('5') = '6'.
Функция Chr (х) является обратной к функции Ord (х), если х — символьная величина. Например, для кода ASCII справедлива запись:
Ord('a’) = 97; Chr(97) = 'а'.
Эту их «взаимообратность», если х— символьная величина, можно выразить формулой
Chr(Ord(х)) = х.
В некоторых случаях возникает задача преобразования символьного представления числа в числовое. Например, получить из литеры ’5’ целое число 5 можно следующим образом:
N := Ord('5') - Ord('0').
Здесь N— целая переменная и использован тот факт, что код литеры '5' на пять единиц больше кода 'О'.
Булевский тип данных также является порядковым. Порядок расположения двух его значений следующий: False, True. Тогда справедливы следующие отношения:
Ord(False) = 0; Succ(False) = True;
Ord(True) = 1;Pred(True) = False.
Приведем интересный пример. Пусть х, у, z — вещественные переменные. Требуется определить, какую задачу решает следующий оператор:
Ответ: z = max(x, у), т.е. данную задачу можно решить без использования условного оператора if..then..else.
Упражнения
Вычислить значения следующих логических выражений:
а)К mod 7 = К div 5-1 при К = 15;
б)Odd(Trunc(10 * Р) ) при Р = 0.182;
в)Not Odd(n) при п = 0;
г) t And (Р mod 3 = 0) при t = True, Р = 10101;
д) (х * у о 0) And (у > х) при х = 2, у = 1;
е)a Or Not b при а = False, b = True.
Определить какое значение получит логическая переменная d при а = True и х = 1 после выполнения следующих операторов присваивания:
а)d := х < 2;
б)d := Not a Or Odd(x);
в)d := Ord(a) о x.
Написать оператор присваивания, в результате выполнения которого логическая переменная t получит значение Тше, если следующее утверждение истинно, и значение False — в противном случае:
а)из чисел х, у, z только два равны между собой;
б)х— положительное число;
в)каждое из чисел х, у, z положительное;
г)только одно из чисел х, у, z положительное;
д)р делится без остатка на q;
е)цифра 5 входит в десятичную запись трехзначного целого числа к.
Программирование ветвящихся алгоритмовАлгоритмическая структура ветвления программируется в Паскале с помощью условного оператора, имеющего вид
If <Условие> Then «Оператор 1> Else сОператор 2>;
Кроме того, возможно использование неполной формы условного оператора:
If <Условие> Then <Оператор>;
Строгое описание условного оператора в форме синтаксической диаграммы показано на рис. 2.13.
Условием в условном операторе является логическое выражение, которое вычисляется в первую очередь. Если его значение

Рис. 2.13. Синтаксическая диаграмма условного оператора
равно True, то будет выполняться <Оператор 1> (после Then), если же его значение равно False, будет выполняться <Опера- тор 2> (после Else) для полной формы или сразу оператор, следующий после условного, для неполной формы (без Else).
Пример 2.1. Требуется составить программу вычисления площади треугольника по длинам трех сторон а, Ь, с.
Для решения задачи используется формула Герона
у]р(р-а)(р-Ь)(р-с),
где р = (а + Ь + с) / 2 — полупериметр треугольника.
Исходные данные должны удовлетворять основному соотношению для сторон треугольника: длина каждой стороны должна быть меньше суммы длин двух других сторон.
Имея возможность в одном условном операторе записывать достаточно сложные логические выражения, можно сразу «отфильтровать» все варианты неверных исходных данных:
Program Geron;
Var А, В, С, Р, S : Real;
Begin
WriteLn('Введите длины сторон треугольника:'); Write('а = '); ReadLn(А);
Write('Ь = '); ReadLn(В);
Write('с = '); ReadLn(С);
If (А > 0) And (В > 0) And (С > 0) And (А + В > С) And (В + С > A) And (А + С > В)
Then Begin
Р := (А + В + С) /2;
S := sqrt(Р * (Р — А) * (Р — В) * (Р — С)); WriteLn('Площадь = ', S)
End
Else WriteLn('Неверные исходные данные')
End.
Пример 2.2. Требуется составить программу решения квадратного уравнения.
Алгоритм решения данной задачи подробно рассматривался в подразд. 1.3 (см. рис. 1.8). Алгоритм имеет структуру вложенных ветвлений. Его описание на алгоритмическом языке также приведено в подразд. 1.3. Программа на Паскале будет иметь вид
Program Roots;
Var А, В, С, D, XI, Х2 : Real;
Begin
WriteLn(введите коэффициенты
квадратного уравнения:1);
Write('а = '); ReadLn (А) ;
Write ('Ь = '); ReadLn(В);
Write('с = '); ReadLn(С);
If (А = 0)
Then If (В = 0)
Then If (С = 0)
Then WriteLn('Любое X — решение’)
Else WriteLn(1 Нет решений’)
Else
Begin
:= -c/b;
WriteLn(’X = ’, X)
End
Else
Begin d := b*b - 4 * a * c;
If (d < 0)
Then WriteLn(’Нет вещественных корней')
Else
Begin
:= (-b + sqrt(d))/2/a;
X2 := (-b - sqrt(d))/2/a;
WriteLn('XI = ', XI);
WriteLn('X2 =X2)
End
End
End.
Пример 2.3. Требуется составить программу перевода пятибалльной оценки в ее наименование: 5 — отлично, 4 — хорошо, 3 — удовлетворительно, 2 — неудовлетворительно.
Блок-схема алгоритма решения задачи приведена на рис. 2.14. Этот алгоритм имеет структуру вложенных ветвлений и соответствующую программу на Паскале можно записать следующим образом:

Рис. 2.14. Блок-схема алгоритма перевода пятибалльной оценки в ее
наименование
Program Marks-2;
Var N : Integer;
Begin
WriteLn(’Введите оценку:’); ReadLn(N);
If (N = 5)
Then WriteLn(’Отлично’)
Else If (N = 4)
Then WriteLn(’Хорошо’)
Else If (N = 3)
Then WriteLn(* Удовлетворительно’)
Else If (N = 2)
Then WriteLn(’Неудовлетворительно *); Else WriteLn(* Неверная оценка')
End.
Структуру вложенных ветвлений можно запрограммировать с помощью одного оператора выбора, имеющегося в языке Паскаль:
Program Marks;
Var N: Integer;
Begin
WriteLn(1 Введите оценку:1);
ReadLn(N);
Case N Of
5: WriteLn('Отлично ’);
4: WriteLn(1 Хорошо*);
3 : WriteLn(’ Удовлетворительно');
2 : WriteLn('Неудовлетворительно')
Else WriteLn(’Нет такой оценки’)
End;
Формат оператора выбора описывается синтаксической диаграммой, показанной на рис. 2.15, где <Селектор> — это выражение любого порядкового типа, <Константа> — постоянная величина того же типа, что и селектор, а <Оператор> — любой простой или составной оператор.
Выполнение оператора выбора происходит следующим образом: вычисляется выражение — селектор, затем в списках констант находится значение, совпадающее с полученным значением селектора, а далее исполняется оператор, помеченный данной константой. Если такой константы не найдено, происходит переход к выполнению оператора, следующего после Else*
< Оператор выбора> Qase
<Селектор>
Покажем на примере использование списка констант в операторе выбора. Следующая программа сообщает, сдал студент экзамен или не сдал, т.е. если он получил оценку 3, 4 или 5, то экзамен сдан, а если — 2, то экзамен не сдан:
<Оператор> —► End—►
Г
<Константа> -]♦ (7) —< Оператор >Else

-о-
Рис. 2.15. Синтаксическая диаграмма оператора выбора
Case N Of
3, 4, 5 : WriteLn('Экзамен сдан')
2 : WriteLn('Экзамен не сдан')
Else WriteLn('Нет такой оценки');
Так же, как условный оператор, оператор выбора может использоваться в неполной форме, т.е. без ветви Else.
Программирование циклических алгоритмовСуществует три типа циклических структур: цикл с предусловием, цикл с постусловием и цикл по параметру.
Цикл с предусловием. Рассмотрим синтаксическую диаграмму оператора цикла «Пока», или цикла с предусловием (рис. 2.16). Здесь сначала вычисляется <Логическое выражение?*. Пока его значение равно True, выполняется <Оператор> — тело цикла. При этом <Оператор> может быть как простым, так и составным.
Для примера приведем фрагмент программы на Паскале, вычисляющий с заданной точностью е сумму гармонического ряда
Суммирование прекращается, когда очередное слагаемое становится меньше е или когда целая переменная / достигает значения Maxlnt:
S := 0;
I := 1;
While (1/1 >= Eps) And (I < Maxlnt) Do Begin
S := S + 1/1;
I := I + 1 End;
Цикл с постусловием. Синтаксическая диаграмма оператора Цикла «До», или цикла с постусловием, приведена на рис. 2.17.
<Оператор цикла с предусловием?»
СЛогическое выражение>
Исполнение данного цикла повторяется до того момента, когда СЛогическое выражение> станет равным True.

- Do»- <Оператор> *-
Рис. 2.16. Синтаксическая диаграмма цикла с предусловием
«Эператор цикла с постусловием> _^
•а
Until
<Логическое выражение >
«-Repeat —► <Оператор>
Рис. 2.17. Синтаксическая диаграмма цикла с постусловием
Предыдущая задача с использованием цикла с постусловием решается следующим образом:
S := 0;
I := 1;
Repeat
S := S + 1/1;
I := I + 1
Until (1/1 < Eps) Or (I >= Maxlnt);
Summa =
0,
если М < N; если М > N.
Цикл по параметру. Рассмотрим задачу вычисления суммы целых чисел от М до N прямым суммированием. Данную задачу можно записать в виде
Блок-схема алгоритма решения этой задачи приведена на рис. 2.18, а соответствующую программу с использованием структуры цикла «Пока» можно записать следующим образом:
Program Adding;
Var I, M, N, Summa : Integer;
Begin
Write(*M = ’) ;
ReadLn(M);
Write('N =');
ReadLn(N);
Summa := 0;
I := M;
While I <= N Do Begin
Summa := Summa + I;
I := Succ(I)
End;
WriteLn(’Сумма равна Summa)
End.


Рис. 2.18. Блок-схема алгоритма суммирования целых чисел
Теперь введем новый тип циклической структуры, которая называется «цикл по параметру». Блок-схема алгоритма суммирования с использованием этой структуры приведена на рис. 2.19, а программу на Паскале для решения данной задачи можно записать следующим образом:
Program Summering_2;
Var I, M, N, Summa: Integer;
Begin Write('M = ');
ReadLn(M);
Write('N = ') ;
ReadLn(N);
Summa := 0;
Ввод М, N

Рис. 2.19. Блок-схема алгоритма суммирования с циклом по параметру
For I := М То N Do
Summa := Summa +1;
WriteLn(1 Сумма равнаSumma)
End.
Здесь целая переменная 1 принимает последовательность всех значений в диапазоне от М до N. При каждом значении I выполняется тело цикла. После последнего выполнения цикла при I = N происходит выход из цикла на продолжение алгоритма. Цикл выполнится хотя бы один раз, если М < N, и не выполнится ни разу при М > N.
В приведенной программе используется оператор цикла по параметру, синтаксическая диаграмма которого показана на рис. 2.20, где
Спараметр цикла> ::= <имя простой переменной порядкового типа>
Выполнение оператора For (в первом варианте То) происходит по следующей схеме.
I Вычисляются значения <Выражение 1> и <Выражение 2>, и|>ичгм только один раз при входе в цикл.
> 11араметру цикла присваивается значение <Выражение 1>.
I ' (качение параметра цикла сравнивается с значением <Выра- || mu* 2>. Если параметр цикла меньше или равен этому значению, го выполняется тело цикла, в противном случае выполне- ни< цикла заканчивается.
•I (качение параметра цикла изменяется на следующее значе- iuii м eio типе (для целых чисел — увеличивается на единицу) и «(«•исходит возврат к п. 3 данной схемы.
Оператор цикла For объединяет в себе действия, которые при in пользовании цикла While выполняют различные операторы: при- • и.кшапие параметру начального значения, сравнение с конечным значением, изменение значения на следующее.
Как известно, результат суммирования целых чисел не зависит «I порядка суммирования. Например, в рассматриваемой задаче •нала можно складывать и в обратном порядке, т.е. от N до М (N М). Для этого можно использовать второй вариант оператора никла For:
aimma := 0;
For I := N DownTo M Do
Mimma := Sununa + I;
DownTo буквально переводится «вниз до». В данном случае параметр цикла изменяется по убыванию, т.е. при каждом повторении цикла параметр изменяет свое значение на предыдущее (ра- иинсильно i :=pred(i)). Следовательно, цикл не выполнится ни ри iy, если N < М.
1’аботая с оператором For, следует учитывать следующие пра- ины:
параметр цикла не может иметь тип real;
и теле цикла нельзя изменять переменную—параметр цикла;
при выходе из цикла значение переменной —параметра цик- ■ы является неопределенным.
В следующем примере в качестве параметра цикла For исполь- wm символьную переменную. Пусть требуется получить на экра-
• >исратор цикла по параметру> __„s~\
—For —► <Параметр цикла> —►
Г~То_Г
^ DownTo-1
-DownTo-
Рис. 2.20. Синтаксическая диаграмма цикла с параметром
не десятичные коды букв латинского алфавита. Как известно, латинские буквы в таблице кодировки упорядочены по алфавиту. Фрагмент соответствующей программы можно записать следующим образом:
For С := * а1 То ' z' Do
Write (С,' - ', Ord(C));
Здесь переменная С типа char.
Теперь самостоятельно запрограммируйте вывод кодировки латинского алфавита в обратном порядке (от 'z* до 'а*)?
Упражнения
Составить на Паскале программу полного решения биквадратного уравнения.
Используя оператор выбора, составить программу, которая по введенному номеру месяца в году будет выводить соответствующее время года (зима, весна, лето, осень).
Используя операторы цикла While, Repeat и For, составить три варианта программы вычисления NJ.
Составить программу, по которой последовательность символов будет вводиться до тех пор, пока не встретится строчная или прописная латинская буква «z». Подсчитать, сколько раз среди вводимых символов встретится буква «W».
Вычислить сумму квадратов всех целых чисел, попадающих в интервал (In х; е*), где х> 1.
Вычислить число точек с целочисленными координатами, попадающих в круг с радиусом R (R> 0) и с центром в начале координат.
Напечатать таблицу значений функции sin х и cosх в интервале [0; 1] с шагом 0.1 в следующем виде:
X sin х COS X
0.0000 0.0000 1.0000
0.1000 0.0998 0.9950
1.0000 0.8415 0.5403
Напечатать в возрастающем порядке все трехзначные числа, в десятичной записи которых нет одинаковых цифр.
Дано целое п > 2. Напечатать все простые числа из интервала [2; п].
ПодпрограммыПонятие вспомогательного алгоритма уже рассматривалось в подразд. 1.5. В языках программирования вспомогательные алгоритмы называются подпрограммами. В Паскале различают два вида подпрограмм: процедуры и функции.
Рассмотрим следующий пример: даны два натуральных числа а и Ь. Требуется определить наибольший общий делитель трех величин: а + Ь, \а - А|, а ■ Ь. Запишем это в виде: НОД (а + b, \a-t\, а ■ Ь).
Идея решения данной задачи состоит в следующем математическом факте: если x,y,z — три натуральных числа, то НОД (х, у, z) = = НОД (НОД (х, у), z)- Иначе говоря, сначала следует найти НОД двух величин, а затем НОД полученного значения и третьего числа (попробуйте это доказать).
Очевидно, что вспомогательным алгоритмом для решения поставленной задачи является алгоритм получения наибольшего общего делителя двух чисел. Следовательно, эта задача решается с помощью известного алгоритма Евклида (см. подразд. 1.3), который запишем в форме процедуры на алгоритмическом языке:
процедура Евклид(цел М, N, К) ; нач
пока М о N
нц
если М > N •РО М := М - N иначе N := N - М кв
кц;
К := М кон
Здесь М и N являются формальными параметрами процедуры, т.е. это параметры-аргументы, а К — параметр-результат. Основной алгоритм решения исходной задачи следующий:
алг задача цел а, Ь, с нач ввод(а, Ь)
Евклид(а + Ь, |а - Ь|, с)
Евклид(с, а * Ь, с) вывод(с)
кон
Процедуры. В отличие от АЯ, где процедура является внешней по отношению к вызывающей программе, процедуры в Паскале описываются в разделе описания подпрограмм. Программа решения исходной поставленной задачи на ТурбоПаскале будет иметь следующий вид:
Program NODI;
Var А, В, С : Integer;
Procedure Evklid(M, N : Integer; Var К : Integer);
Begin
While M о N Do
If M > N
Then M := M - N
Else N := N - M;
К := M
End;
Begin
Write(* A =l);
ReadLn(A);
Write(1В = ') ;
ReadLn(B);
Evklid(A + B, Abs(A - В), C);
Evklid(С, A * В, C);
WriteLn(* НОД = ', C)
End.
В данном случае обмен аргументами и результатами между основной программой и процедурой производится через параметры (формальные и фактические). Существует и другой механизм обмена — через глобальные переменные, что будет рассмотрено далее.
Синтаксическая диаграмма описания процедуры показана на рис. 2.21.
Из диаграммы видно, что процедура может иметь параметры, а может и не иметь. Чаще всего аргументы представляются как параметры-значения (но они могут быть и параметрами-переменными), для передачи результатов используются параметры-переменные.
СОписание процедуры > ^^/Оу
<Заголовок>
Procedure
<Имя> ■
► <Заголовок процедуры>► (J)► <Блок>►
TOC \o "1-5" \h \z с© -► ССписок формальных параметров>^7^ -
«Нормальные параметры> ::= <Параметры-значения> | <Параметры-переменные>
< Параметры-переменные >^^
► Var —► < Список переменных> —► f : J —<Тип>-*-
< Параметры-значения >S~\^ ^
-► <Список значений> —► (J) —► <Тип> —
Рис. 2.21. Синтаксическая диаграмма описания процедуры
<Имя процедуры>
<Список фактических параметров> -

Рис. 2.22. Структура оператора обращения к процедуре
Процедура в качестве результата может передавать в вызывающую программу множество значений (в частном случае — одно), а может и не передавать ни одного значения. Теперь рассмотрим правила обращения к процедуре. Обращение к процедуре производится в форме оператора процедуры (рис. 2.22).
Если описана процедура с формальными параметрами, то и обращение к ней производится оператором процедуры с фактическими параметрами. Правила соответствия между формальными и фактическими параметрами следующие: соответствие по количеству, по последовательности и по типам.
Первый вариант взаимодействия формальных и фактических параметров называется передачей по значению: вычисляется значение фактического параметра (выражения) и это значение присваивается соответствующему формальному параметру. Второй вариант взаимодействия формальных и фактических параметров называется передачей по имени: при выполнении процедуры имя формальной переменной заменяется именем соответствующей фактической переменной (в откомпилированной программе имени переменной соответствует адрес ячейки памяти).
В рассмотренном примере формальные параметры М и N являются параметрами-значениями. Это аргументы процедуры, при обращении к которой первый раз им соответствуют значения выражений А + В и Abs(A - В), а второй раз — значения С и А В. Параметр К является параметром-переменной, в которой получают результат работы процедуры. В обоих обращениях к процедуре соответствующим фактическим параметром является переменная С, через которую основная программа получает результат.
Теперь рассмотрим пример программы, решающей исходную поставленную задачу с использованием процедуры без параметров:
Program NOD2;
Var А, В, К, М, N : Integer;
Procedure Evklid;
Begin
While M о N Do
If M > N
Then M := M - N
Else N := N - M;
К := M
End;
Begin
Write('A =');
ReadLn(A);
Write('B =');
ReadLn(B);
M := A+ B;
N := Abs (A - B);
Evklid;
M := K;
N := A * B;
Evklid;
WriteLn(' НОД равен К)
End.
Чтобы разобраться в этом примере, требуется рассмотреть понятие область действия описания.
Областью действия описания любого программного объекта (переменной, типа, константы и т.д.) является тот блок, в котором расположено это описание. Если данный блок вложен в другой (подпрограмма), то присутствующие в нем описания являются локальными и действуют только в пределах внутреннего блока. Описания же, стоящие во внешнем блоке, являются глобальными по отношению к внутреннему блоку. Если глобально описанный объект используется во внутреннем блоке, то на него распространяется внешнее (глобальное) описание.
В программе NOD1 переменные М, N, К —локальные внутри процедуры, а переменные А, В, С — глобальные. Однако внутри процедуры переменные А, В, С не используются. Связь между внешним блоком и процедурой осуществляется через параметры.
В программе NOD2 все переменные являются глобальными. В процедуре Evklid нет ни одной локальной переменной (нет и параметров), поэтому используемые в ней переменные М и N получают свои значения через оператор присваивания в основном блоке программы. Результат получают в глобальной переменной К, значение которой выводится на экран.
Использование механизма передачи значений через параметры делает процедуру более универсальной, независимой от основной программы. Однако в некоторых случаях оказывается удобнее использовать передачу значений через глобальные переменные, особенно для процедур, работающих с большими объемами информации. В этой ситуации глобальное взаимодействие экономит память ЭВМ.
функции. Теперь выясним, что представляет собой подпрограмма-функция. Обычно функция используется в том случае, если результатом подпрограммы должна быть скалярная (простая) величина. Тип результата называется типом функции. В ТурбоПас
кале допускаются функции строкового типа. Синтаксическая ди- аграмма описания функции представлена на рис. 2.23.
Как и у процедуры, у функции в списке формальных параметров могут иметься параметры-переменные и параметры-значения, которые являются ее аргументами. При этом если аргументы передаются глобально параметры в списке могут отсутствовать.
Программа решения исходной поставленной задачи с использованием функции будет иметь следующий вид:
Program N0D3;
Var А, В, Rez: Integer;
Function Evklid(M, N : Integer) : Integer;
Begin
While M о N Do
If M > N
Then M := M - N
Else N := N - M;
Evklid := M
End;
Begin
Write(’A = ’);
ReadLn(A);
Write(’B = ');
ReadLn(B);
Rez := Evklid(Evklid(A + B, Abs(A - B) ) , A * B) ;
WriteLn('NOD равен Rez)
End.
Из данного примера видно, что в отличие от процедуры в теле функции результат присваивается переменной с именем функции.
Обращение к функции является операндом в выражении и записывается в следующей форме:
<имя функции> (<список фактических параметров:»)
«Эписание функции>
<Заголовок>

<Заголовок>
Function
<Имя> ■
—<т>-1
<Блок>—►
—► <Тип>
Сф -► < Список формальных параметров>^7) -
Рис. 2.23. Синтаксическая диаграмма описания функции
Правила соответствия между формальными и фактическими параметрами у функции те же, что и у процедуры. Сравнивая рассмотренные программы, можно сделать вывод, что програм-
ма NOD3 имеет определенные преимущества перед другими. Функция позволяет получить результат посредством выполнения одного оператора присваивания. Здесь же показано, что фактическим аргументом при обращении к функции может быть эта же функция.
По правилам стандартного Паскаля возврат в вызывающую программу из подпрограммы происходит, когда выполнение подпрограммы доходит до конца (последний End). Однако в ТурбоПаска- ле имеется средство, позволяющее выйти из подпрограммы в любом ее месте. Это оператор-процедура Exit. Например, функцию определения наибольшего из двух заданных вещественных чисел можно описать следующим образом:
Function Мах(Х, Y : Real): Real;
Begin
Max := X;
If X > Y Then Exit Else Max := Y
End;
Еще раз об области действия описаний. В Паскале неукоснительно действует следующее правило: любой программный объект (,константа, переменная, тип и др.) должен быть описан перед использованием в программе. Иначе говоря, описание объекта должно предшествовать его первому появлению в других фрагментах программы. Это правило относится и к подпрограммам.
На рис. 2.24 схематически показана структура взаимного расположения описаний подпрограмм в некоторой условной программе. Попробуем, используя эту схему, разобраться в вопросе об области действия описаний подпрограмм.
Любая подпрограмма может использоваться лишь в пределах области действия ее описания. Например, область действия подпрограмм А и В — основная программа, поэтому из основной программы можно обратиться к подпрограммам А и 5. В свою очередь, в подпрограмме 5 могут быть обращения к подпрограмме А, однако из А нельзя обратиться к В, поскольку описание А предшествует описанию В. Подпрограммы А\ и А2 локализованы в подпрограмме А и могут использоваться только в ней, причем из А2 можно обратиться к Л1, а из Л1 в А2 нельзя.
Из подпрограммы В\ можно обратиться к подпрограмме А, поскольку ее описание является глобальным по отношению к В\, но нельзя обратиться к А\, поскольку область действия описания А1 не распространяется на блок подпрограммы В.
Из подпрограммы В22 можно обратиться только к подпрограммам 521, 51 и А. (Определите самостоятельно, почему.)
Если одно и то же имя описано во внешнем блоке (глобально) и внутреннем (локально), то последнее описание (локальное) пе-
Подпрограмма А Подпрограмма >41 Подпрограмма >42

Подпрограмма В
Подпрограмма В\
Подпрограмма В2 Подпрограмма В21 Подпрограмма В22 Рис. 2.24. Пример структуры программы
рекрывает первое в пределах внутреннего блока. Рассмотрим две программы:
Program Example2;
Var X : Integer; Procedure P;
Begin
WriteLn(1X = ', X) End;
Begin X := 1;
P
End.
Program Examplel;
Var X : Integer; Procedure P;
Var X: Integer;
Begin WriteLn('X = *, X) End;
Begin X := 1;
P
End.
В результате работы первая программа выдаст результат X = ..., где на месте отточия будет какое-то произвольное значение, соответствующее неопределенной величине х.
Вторая программа выдаст результат X = 1.
В первой подпрограмме переменная с именем X описана и глобально, и локально, но процедура выводит значение локальной переменной, которой ничего не присвоено. Здесь идентификатором X обозначены две совершенно разные величины, которым соответствуют две разные ячейки памяти.
Во второй программе переменная X одна на всю программу и описана глобально, поэтому значение 1, присвоенное ей в основной программе, передается и в подпрограмму.
Составить два варианта программы вычисления площади кольца по значениям внутреннего и внешнего радиусов: с процедурой и с функцией, используя подпрограмму вычисления площади круга.
По координатам вершин треугольника вычислить его периметр, используя подпрограмму вычисления длины отрезка между двумя точками.
Даны три целых числа. Определить, используя подпрограмму, у которого из них больше сумма цифр.
Определить площадь выпуклого четырехугольника по заданным координатам вершин, используя подпрограмму-функцию вычисления длины отрезка и подпрограмму-процедуру вычисления площади треугольника по формуле Герона.
Вычисление рекуррентных последовательностейРекуррентная последовательность. Понятие рекуррентной последовательности известно из курса математики. Вводится оно следующим образом: пусть известно к чисел: аи..., ак, которые являются началом числовой последовательности. Следующие элементы этой последовательности вычисляются по формулам:
&к+\ =••• >&к+2 =••• 1 &к+l)j &к+3 =&к+
где Д...) — функция от к аргументов.
Формула вида
Qi —1, Я/-2» ••• i&i-k)
называется рекуррентной, а величина к — глубиной рекурсии.
Другими словами, рекуррентная последовательность — это бесконечный ряд чисел, каждое из которых, за исключением к начальных, вычисляется через предыдущие.
Примерами рекуррентных последовательностей являются соответственно арифметическая и геометрическая прогрессии:
ах = 1,я2 = 3, д3 = 5, а4 = 7, я5 = 9, ...;(2.1)
ах - 1, д2 = 2, д3 = 4, д4 = 8, а5 = 16,...(2.2)
Рекуррентная формула данной арифметической прогрессии
а, = a,_i + 2.
Рекуррентная формула данной геометрической прогрессии
а, = 2ом.
о, =+ 2,
если / = 1; если / > 1,
Глубина рекурсии в обоих случаях равна единице (такую зависимость также называют одношаговой рекурсией). В целом рекуррентная последовательность описывается совокупностью начальных значений и рекуррентной формулой. Все это можно объединить в одну ветвящуюся формулу, которая для арифметической прогрессии будет иметь вид
а для геометрической —
_ Г1,если / = 1;
' [2а,_ьесли / > 1.
Числовая последовательность вида
1; 1; 2; 3; 5; 8; 13; 21; 34; 55 ...,
известная в математике под названием чисел Фибоначчи, в которой начиная с третьего элемента, каждое число равно сумме значений двух предыдущих, является рекуррентной последовательностью с глубиной, равной двум (двухшаговая рекурсия). Опишем ее в ветвящейся форме:
Г1,/ = 1, / = 2;U-.+/-2, /> 2.
Введение представления о рекуррентных последовательностях позволяет по новому взглянуть на некоторые уже известные нам задачи. Например, факториал от целого числа «! можно рассматривать как значение «-го элемента следующего ряда чисел:
Оо= 1; а, = 1!; а2 = 2\; а3 = 3!; а4 =4!; ...
Рекуррентное описание такой последовательности будет иметь вид
|1, / = 0;
Программирование вычислений рекуррентных последовательностей. С рекуррентными последовательностями связаны следующие задачи:
вычисление заданного («-го) элемента последовательности;
математическая обработка определенной части последовательности (например, вычисление суммы или произведения первых п членов);
подсчет числа элементов на заданном отрезке последовательности, удовлетворяющих определенным свойствам;
определение номера первого элемента, удовлетворяющего определенному требованию;
вычисление и сохранение в памяти заданного числа элементов последовательности.
Данный перечень, не претендуя на полноту, охватывает наиболее часто встречающиеся типы задач. В задачах 1 ...4 не требуется одновременно хранить в памяти множество элементов числового ряда: его элементы могут получаться последовательно в одной переменной, сменяя друг друга.
Пример 2.4. Требуется вычислить п-й элемент арифметической прогрессии (2.1).
Программа, решающая данную задачу, следующая:
Var N, I: O..MaxInt;
А : Real;
Begin
Write('N = ');
ReadLn(N);
A := 1;
For I := 2 To N Do
A := A + 2;
WriteLn (' A (', N: 1,A:6:0)
End.
Рекуррентная формула а, = o,_, + 2 перешла в оператор А := А + 2.
Пример 2.5. Требуется просуммировать первые п элементов геометрической прогрессии (2.2), не используя формулу для суммы прогрессии.
Программа решения данной задачи следующая:
Var N, I: O..MaxInt;
A, S : Real;
Begin
Write('N= '); ReadLn(N);
A := 1;
S := A;
For I := 2 To N Do Begin
A := 2 * A;
S := S + A
End;
WriteLn('Сумма равна S : б : 0)
End.
При вычислении рекуррентной последовательности с глубиной, равной двум, уже нельзя обойтись одной переменной, что видно из следующего примера.
Пример 2.6. Требуется вывести на печать первые п (п > 3) чисел Фибоначчи и подсчитать, сколько среди них четных чисел. Программа решения данной задачи следующая:
Var N, I, К, F, FI, F2 : O..MaxInt;
Begin
FI := 1; F2 := 1;
К := 0;
WriteLn('F(l) = ', FI, ' F(2) =F2);
For I := 3 To N Do Begin
F := FI + F2;
WriteLn('F(', I : 1,') = \ F) ;
If Not Odd(F) Then К := К + 1;
FI := F2; F2 := F
End;
WriteLn('Количество четных чисел в последовательности равно ', К)
End.
Для последовательного вычисления двухшаговой рекурсии требуются три переменные, поскольку для вычисления очередного элемента необходимо помнить значения двух предыдущих.
Пример 2.7. Для заданного вещественного х и малой величины е (например, е= 0,000001) требуется вычислить сумму ряда
. х2 х3 1 + Х+2! + 3!+-’
включив в нее только слагаемые, превышающие е.
Из математики известно, что сумма такого бесконечного ряда имеет конечное значение, равное е*, где е = 2,71828... — основание натурального логарифма. Поскольку элементы этого ряда представляют собой убывающую последовательность чисел, стремящуюся к нулю, суммирование следует производить до первого слагаемого, по абсолютному значению не превышающего е.
Если слагаемые в этом выражении обозначить
X2X3
= 1> Щ =^2 = 21 >= у | > •••>
то обобщенная формула для /-го элемента будет следующей:
Нетрудно увидеть, что между элементами данной последовательности имеется рекуррентная зависимость. Ее можно найти интуитивно, но можно и вывести формально. Правда, для этого требуется догадаться, что рекурсия — одношаговая, и что каждый следующий элемент получается посредством умножения предыдущего на некоторый множитель, т. е.
я, = Kdj_\.
Используя обобщенную формулу, запишем:
XL_ гг Х,-1 /!" (/-!)!’
откуда
у _ Xj/П _ х х,.,/(/-1)!/'
Действительно,
XX
Со = 1; а{ ~^; аз = а2 у •••
1,
если i = 0; если / > 0.
Следовательно, данная рекуррентная последовательность может быть описана следующим образом:
И, наконец, приведем программу, решающую поставленную задачу:
Var А, X, S, Eps : Real;
I : Integer;
Begin
Write('X = '); ReadLn(X);
Write('Epsilon = '); ReadLn(Eps);
A := 1; S :=0; I :=0;
While Abs(A) > Eps Do Begin
TOC \o "1-5" \h \z S:=S+A;
I:=I+1;
A:=A*X/I
End;
WriteLn('Сумма ряда равна ', S : 10 : 4) End.
Значения одношаговой рекуррентной последовательности здесь, как и прежде, вычисляются в одной переменной.
Каждое повторное выполнение цикла в этой программе приближает значение S к искомому (уточняет значащие цифры в его записи). Такой вычислительный процесс в математике называется итерационным процессом. Соответственно циклы, реализующие итерационный вычислительный процесс, называются итерационными циклами. Для их организации используются операторы While или Repeat.
Пример 2.8. Для заданного натурального числа N и вещественного х (х>0) требуется вычислить значение выражения

В этом случае рекуррентность не столь очевидна. Попробуем найти ее методом индукции. Будем считать, что искомое выражение есть N-й элемент последовательности вида

откуда видна следующая связь:

Теперь поставленную задачу решить очень просто:
Var А, X : Real; I, N : Integer;
Begin
Write('X = '); ReadLn(X);
Write('N = '); ReadLn(N);
A := Sqrt(X);
For I := 2 To N Do
A := Sqrt(X + A);
WriteLn('Ответ:A)
End.
Однако к решению всех приведенных задач можно подойти и иначе, используя возможность рекурсивоного определения функции в Паскале.
Подробно рекурсивные подпрограммы Паскаля рассматриваются в подразд. 2.17. Из описания арифметической прогрессии в форме рекуррентной последовательности непосредственно следует способ определения функции для вычисления заданного элемента.
Сделаем это для общего случая, определив арифметическую прогрессию с начальным значением а0 и разностью d:
_ (do, если i = 1;
1[a,_| + d, если i > 1.
Соответствующая подпрограмма-функция будет иметь вид
Function Progres(АО, D : Real; I : Integer): Real;
Begin
If I = 1
Then Progres := AO
Else Progres := Progres(AO, D, I - 1) + D
End;
Следующая программа выводит на экран первые 20 чисел Фибоначчи, значения которых вычисляет рекурсивная функция Fibon:
Var К : Byte;
Function Fibon(N : Integer) : Integer;
Begin
If (N = 1) Or (N = 2)
Then Fibon := 1
Else Fibon := Fibon(N - 1) + Fibon(N - 2)
End;
Begin
For К := 1 To 20 Do WriteLn(Fibon(K))
End.
Необходимо отметить, что использование рекурсивных функций ведет к замедлению счета. Кроме того, можно столкнуться с проблемой нехватки длины стека, в котором запоминается «маршрут» рекурсивных обращений.
Рекуррентные последовательности часто используются для решения разного рода эволюционных задач, т.е. задач, в которых прослеживается какой-то процесс, развивающийся во времени. Рассмотрим такую задачу.
Пример 2.9. Входе лечебного голодания масса пациента за 30 дней снизилась с 96 до 70 кг. Было установлено, что ежедневные потери массы пропорциональны массе тела. Требуется вычислить, чему была равна масса пациента через А: дней после начала голодания для к= 1,2,..., 29.
Обозначим массу пациента в /-й деньpt (/=0,1,2,..., 30). Из условия задачи известно, что р0 = 96 кг, = 70 кг. Пусть К — коэффициент пропорциональности убывания веса за один день. Тогда
Pt =р0- Кро = ( 1 - К)р0; р2 = (1 - К)РйРз = (1 - К)Ръ •••; Pi = (1 - ЮА-1.
т.е. имеем последовательность, описываемую следующей рекуррентной формулой:
если / = 0; если 1 < / <: 30.
Коэффициент К можно найти, используя условие д30 = 70 и выполнив «обратные» подстановки:
Ло = (1 ~ ЮР29 = (1 - К)2Р28 = (1 - КУр21 = ... =
= 0 - Ю30 А) = 0 - Аг)3096.
Из равенства (1 - А)30 96 = 70 находим:
Дальнейшее программирование становится очевидным:
Var I : Byte;
Р, Q : Real;
Begin
Р := 96;
Q := Exp(1/30 * Ln(70/96));
For I := 1 To 29 Do Begin
P := Q * P;
WriteLn(I, 1-й день - P : 5 : 3,'кг*)
End
End.
Упражнения
если / > 0.
если / = 0;
Рекуррентная последовательность определена следующим образом:
Для заданного натурального п получить значение ап.
Дана последовательность
если / > 1.
1,если / = 0, / = 1;
Вычислить произведение элементов с 1-го по 20-й.
Используя рекуррентный подход, вычислить сумму многочлена 10-й степени по формуле Горнера:
10х10 + 9х9+ 8х“ + ... + 2х2 + х=(((((((((10х+ 9)х+ 8)х+ ... + 2)х+ 1)х
где х — заданное вещественное число.
Для заданных вещественного х и натурального ^вычислить следующую цепную дробь:
х/( 1 + х/(2 + х/(3 + */(... /(N + х))...).
Вычислить и вывести все члены числового ряда

превышающие значение 10"5.
6. Функцию у = ~Jx можно вычислить как предельное значение последовательности, определяемой следующей рекуррентной формулой:

Здесь начальное значение у0 задается произвольно (желательно ближе к -Jx). За приближенное с точностью е значение корня берется первое ук, для которого выполняется условие \ук-ук.\\< е- Составить соответствующую программу вычисления.
Графические средства ТурбоПаскаляДо сих пор мы использовали экран компьютера только для вывода символьной информации — чисел, текстов. Однако Турбо- Паскаль позволяет выводить на экран рисунки, чертежи, графики функций, диаграммы, т.е. все то, что принято называть компьютерной графикой.
В стандартном Паскале графический вывод не предусмотрен. Однако на разных типах компьютеров, в разных реализациях Паскаля существуют различные программные средства графического вывода: специальные наборы данных, функций, процедур. При этом имеются общие понятия и средства, свойственные любому варианту реализации графики в любом языке программирования. Рассмотрим такие базовые средства.
Начиная с четвертой версии ТурбоПаскаля для IBM PC появилась мощная графическая библиотека, организованная в модуль Graph. В приложении 2 в справочной форме дано описание основных компонентов этого модуля. Для подключения модуля Graph в начале программы необходимо написать строку
Uses Graph;
Графические режимы экрана. Для вывода графических изображений необходимо перевести экран в один из графических режимов. В графическом режиме можно с помощью программы управлять состоянием каждого пиксела — точечного элемента экрана.
Графическое режимы отличаются:
размером графической сетки (Л/х N, где М— число точек по горизонтали; N— число точек по вертикали);
цветностью (числом воспроизводимых на экране цветов).
Допустимые режимы зависят от типа монитора и соответствующего графического драйвера, используемого на компьютере.
Для установки графического режима экрана существуют соответствующие процедуры. В модуле Graph процедура установки графического режима экрана имеет следующий заголовок:
Procedure InitGraph(Var Driver, Mode : Integer; Path :
String);
Здесь целая переменная Driver определяет тип графического драйвера, целая переменная Mode задает режим работы графического драйвера, a Path — выражение типа String, содержащее маршрут поиска файла графического драйвера.
Списки констант модуля Graph, определяющих типы драйверов и режимы, даны в приложении 2 (см. табл. П2.1 и П2.2).
Приведем пример программы, инициализирующей графический режим VGAHi для работы с драйвером VGA (монитор типа VGA):
Uses Graph;
Var Driver, Mode : Integer;
Begin
Driver : = VGA;{Драйвер}
Mode : = VGAHi;{Режим работы}
InitGraph(Driver, Mode, 'C:\TP\BGI');
Здесь указывается, что файл egavga.bgi с драйвером для VGA- монитора находится в каталоге C:\TP\BGI. Режим VGAHi сответ- ствует графической сетке 640 х 480 с палитрой из 16 цветов.
Возможны также автоматические определение типа драйвера и установка режима, что позволяет программе работать с разными типами мониторов, не внося изменений в текст:
Driver := Detect;
InitGraph(Driver, Mode, 'C:\TP\BGI');
При этом автоматически устанавливается режим с наибольшими разрешающей способностью и цветностью. После окончания
работы в графическом режиме следует вернуться в текстовый режим экрана.
В модуле Graph процедура возвращения в текстовый режим имеет заголовок
Procedure CloseGraph;
Цвет фона и цвет рисунка. На цветном мониторе можно изменять окраску экрана. Установленная окраска экрана называется цветом фона. Рисунок на этом фоне наносится с помощью разнообразных линий: прямых, окружностей, прямоугольников, ломаных и др. Цвета этих линий также могут меняться.
В табл. П2.3 приведены имена констант, определяющих 16 цветов палитры для мониторов типа EGA, VGA.
Заголовок процедуры установки цвета фона
Procedure SetBkColor(Color : Word);
Здесь Color — выражение целого типа, определяющее номер цвета фона.
Заголовок процедуры установки цвета линий
Procedure SetColor(Color : Word);
Заметим, что если в качестве номера цвета линии указан 0, то это всегда совпадает с цветом фона (невидимая линия).
При необходимости очистить графический экран (стереть рисунок) используется процедура очистки экрана, имеющая следующий заголовок:
Procedure ClearDevice;
В результате выполнения этой процедуры экран заполняется установленным цветом фона.
Графические координаты. Положение каждого пиксела графической сетки однозначно определяется указанием его координат.
ОХ640
о
Y
(X.Y)
480
Рис. 2.25. Система экранных координат
Расположение на экране графических осей координат показано на рис. 2.25. Горизонтальная ось X направлена слева направо, вертикальная ось Y — сверху вниз.
На рис. 2.25 указаны предельные графические координаты, соответствующие режиму VGAHi.
Можно определить максимальные координаты по осям, соответствующие данному драйверу, с помощью следующих двух целочисленных функций:
Function GetMaxX;
Function Ge tMaxY;
Графическое окно. Область вывода изображения может быть ограничена любым прямоугольником в пределах экрана. Такая область называется графическим окном. Существует процедура, устанавливающая положение графического окна на экране.
Заголовок процедуры назначения графического окна
Procedure SetViewPort(XI, Yl, Х2, Y2 : Integer; Clip :
Boolean);
Здесь (XI, Yl) — координаты левого верхнего угла окна; (Х2, Y2) — координаты правого нижнего угла окна; Clip — ограничитель фигур.
Если Clip = True, то все построения производятся только в пределах окна, в противном случае они могут выходить за его пределы.
После установки окна координаты точек внутри него отсчитываются от его верхнего левого угла.
Существует понятие графического курсора, который в отличие от символьного курсора он на экране не виден. Графический курсор указывает на текущую позицию на экране. При входе в графический режим координаты текущей позиции (0, 0).
Процедура назначения координат графического курсора:
Procedure MoveTo(X, Y : Integer);
Здесь X, Y — устанавливаемые координаты курсора, которые указываются относительно левого верхнего угла окна или (если окно не установлено) экрана.
Процедура поставить точку — основная процедура получения изображения, поскольку любой рисунок складывается из точек. Состояние светящейся точки определяется ее координатами на экране и цветом.
Заголовок процедуры выставления точки на графическом экране
Здесь X, Y — координаты точки; Color — цвет точки.
Пример 2.10. Программа, устанавливающая по центру экрана графическое окно размером 100 х 100, заливающая его желтым фоном и заполняющая синими точками, расположенными через четыре позиции, будет иметь следующий вид:
Uses Graph;
Var Driver, Mode : Integer;
X, Y, XI, Yl, X2, Y2, Xc, Yc : Integer;
Begin
TOC \o "1-5" \h \z {Инициализация графического режима}
Driver : = Detect;
InitGraph(Driver, Mode, 'C:\TP\BGI');
{Определение координат центра экрана}
Xc := GetMaxX Div 2;
Yc := GetMaxY Div 2;
{Определение координат графического окна}
XI ;= Xc - 50;
Yl := Yc - 50;
X2 := Xc + 50;
Y2 := Yc + 50;
TOC \o "1-5" \h \z {Установка графического окна}
SetViewPort(XI, Yl, X2, Y2, True);
{Установка цвета фона и очистка экрана}
SetBkColor(Yellow);1
ClearDevice;
{Расстановка точек в окне}
For X := 1 То 25 Do For Y := 1 То 25 Do
PutPixel(4 * X, 4 * Y, Blue);
{Задержка изображения на экране до нажатия
TOC \o "1-5" \h \z <Enter>}
ReadLn;
{Выход из графического режима в символьный}
CloseGraph;
End.v
Графические примитивы. Любое изображение можно построить из точек, однако программировать получение сложного рисунка или чертежа, используя только процедуру поставить точку, было бы слишком неудобно и громоздко. В любом графическом пакете существуют процедуры рисования основных геометрических фигур: прямых линий, окружностей, эллипсов, прямоугольников и т.д. Такие фигуры называют графическими примитивами.
Рассмотрим несколько основных процедур рисования графических примитивов, имеющихся в модуле Graph.
Линия с заданными координатами концов (XI, Y1) и (Х2, Y2):
Procedure Line(XI, Yl, Х2, Y2 : Integer);
Линия от текущей точки до точки с координатами (X, Y):
Procedure LineTo(X, Y : Integer);
Линия от текущей точки до точки с заданными приращениями координат (DX, DY):
Procedure LineRel(DX, DY : Integer);
Прямоугольник с заданными координатами верхнего левого угла (XI, Y1) и нижнего правого угла (Х2, Y2):
Procedure Rectangle(XI, Yl, Х2, Y2 : Integer);
Окружность с центром в точке (X, Y) и с радиусом R в пикселах:
Procedure Circle(X, Y : Integer; R : Word);
Дуга окружности с центром в точке (X, Y), с радиусом R, с начальным углом BegA и конечным углом EndA (углы измеряются в градусах против часовой стрелки от направления оси X):
Procedure Arc(X, Y : Integer; BegA, EndA, R : Word);
Эллипсная дуга с центром в точке (X, Y), с начальным и конечным углами соответственно BegA и EndA, с горизонтальным радиусом RX и вертикальным радиусом RY:
Procedure Ellipse (X, Y : Integer; BegA, EndA, RX, RY : Word);
Пример 2.11. Составим программу, рисующую голову робота (рис. 2.26).
Рисунок содержит два прямоугольника, две окружности, две дуги, эллипс, три прямые линии и две черные точки. Заранее определив все координаты и размеры элементов рисунка, запишем программу:
Usee Graph;
Var Driver, Mode ; Integer;

Begin
{Инициализация графического режима}
Driver := Detect;
InitGraph(Driver, Mode, 1C:\TP\BGI1);
SetColor(White); {Белый цвет рисунка}
SetBkColor(Black); {Черный цвет фона}
Rectangle(100, 100, 300, 300); {Голова}
Circle (150, 170, 30); {Левый глаз}
Circle (250, 170, 30); {Правый глаз}
Агс(150, 170, 45,135, 40);{Леваябровь}
Агс(250, 170, 45, 135, 40); {Правая бровь} Ellipse(200, 250,0, 359,10,20);{Нос}
Rectangle(130, 280, 270, 290); {Рот}
MoveTo(100, 300); {Установка вниз влево} LineTo(50, 350); {Три}
LineTo(350, 350);{Линии}
LineTo(300, 300);{Шеи}
PutPixel(150, 170, Black); {Левый зрачок} PutPixel(250, 170, Black); {Правый зрачок}
ReadLn;{Задержка}
CloseGraph; {Выход из графики}
End.
В приведенном примере все линии сплошные нормальной толщины. Модуль Graph позволяет управлять стилем линии (сплошная, пунктирная, точечная и др.) и ее толщиной, для чего существует процедура SetLineStile (см. табл. П2.4).
Закраски и заполнения. Среди графических примитивов существуют закрашенные области. Цвет закраски определяется процедурой SetColor. Кроме того, можно управлять рисунком закраски (типом заполнения). Это может быть сплошная закраска, запол-
пение редкими точками, крестиками, штрихами и т.д. В табл. П2.5 даны константы для указания типа заполнения.
Процедура определения типа заполнения (Fill) и цвета (Color) имеет следующий заголовок:
Procedure SetFillStyle(Fill, Color : Word);
Процедура заполнения прямоугольной области с заданными координатами углов;
Procedure Bar(XI, Yl, Х2, Y2 : Integer);
Процедура обведения линией (SetLineColor, SetLineStyle) и закраски (SetFillStyle) эллипса:
Procedure FillEllips(X, Y, RX, RY : Integer);
Процедура обведения линией и закраски эллипсного сектора:
Procedure Sector (X, Y : Integer; BegA, EndA, RX, RY
: Word);
Процедура обведения линией и закраски сектора окружности:
Procedure PieSlice(X, Y : Integer; BegA, EndA : Word);
Наконец, можно закрасить любую область, ограниченную замкнутой линией. Для этого нужно указать какую-нибудь точку внутри этой области (X, Y) и цвет граничной линии (Border). Соответствующая процедура имеет вид
Procedure FloodFill(X, Y : Integer; Border : Word);
Модуль Graph позволяет выводить на графический экран тексты. Не будем детально обсуждать эту проблему (необходимую информацию можно найти в специальной литературе), приведем лишь пример одной текстовой процедуры, с помощью которой выводится в графическое окно символьная строка (Txt), начиная с указанной позиции (X, Y):
Procedure OutTextXY(X, Y : Integer; Txt : String);
Например, чтобы вывести под рис. 2.26 строку ЭТО РОБОТ, следует в программу добавить оператор
OutTextXY(195, 400, 'ЭТО РОБОТ');
Построение графика функции. Одно из приложений компьютерной графики обеспечивает наглядное представление результатов математических расчетов. Нарисованный график функции, начерченные диаграммы, линии уровней распределения пространственных зависимостей и другие делают результаты расчетов обозримее, нагляднее, понятнее.
Рассмотрим сейчас лишь один простейший вариант математической графики — построение графика функции.
Решение задачи построения на экране дисплея графика функции y=F(x) удобно проводить в следующем порядке.
Определить границы значений аргумента, в пределах которых будет строиться график, обозначив их Xmin (нижняя граница) и Л'тах (верхняя граница).
Для данной области значений аргумента определить предельные значения функции: У^и Утах. Эти значения необязательно должны быть точными. Они могут быть оценочными.
Задать границы графического окна, в пределах которого будет рисоваться график:Xgmax],У&тах]* Поскольку в
графических координатах вертикальная ось направлена вниз, то Yg min ^ Yg max*
Таким образом, имеются две системы координат: (X, Y) — математические координаты (в литературе чаще используется термин «мировые координаты») и (Xg, Yg) — графические координаты.
Нетрудно получить формулы, связывающие графические и математические координаты:
^gmax
Y
. Лтах
Ygmxx
Y
L 1 max
•^5» Д§пнп Yg = Ygmin +
-^Tmin ! Y Y \ у \.*л л min) ^ min
%min /у v \ v v1 1minJ ■
Здесь квадратные скобки означают округление до целого значения (функция Round).
Построение графика функции может производиться либо точечным методом, либо кусочно-линейным. При точечном методе график строится как последовательность точек, расположенных максимально близко, т.е. производится «попикселный» перебор значений аргумента в интервале [2^^, Xg^ с выставлением точек с соответствующими У-координатами.
При кусочно-линейном методе задается математический шаг XX, рассчитывается последовательность значений (Xh Y):
Xi = Xmax+iAX; Yt = F(Xj);
/ = 0,1,..., n; n = Xmax ~Xmm ,
и график строится в виде отрезков прямых, проведенных через тонкий, П), (Xi+l, Yi+l).
Пример 2.12. Требуется составить программу построения графика функции у=sin х для х € [0; 2л], используя точечный метод.
Из условия задачи следует, что Xmin = 0, Хтах = 2л. В этих пределах функция sinх изменяется от -1 до 1, поэтому 7min = -l> 7max = 1.
Выберем следующие границы графического окна: XgmiTl = 10; Xg max = 200; y&nin = 140; 7gmax = 40.
График строится в виде последовательности точек со следующими математическими координатами:
Xi = XmiD + ih; Y, = sin(Jr,); / = 0,...,190.
Шаг h выбирается минимально возможным, соответствующим шагу графической сетки:
l _ Хтах — -Уmin _ 2л _ Я ~Xgmax-Xgmin 19095-
2я 40 -140
= 10 +
Xg = 10 + Yg = 140 +
200-10
(7 + 1)
'95'
я
= 90-[507].
Приведенные формулы пересчета математических координат в графические примут следующий вид:

Вместе с графиком функции строятся оси координат. Ось X имеет координату Yg= 90, а ось 7— координату Xg= 10. Программа построения графика следующая:
Uses Graph;
Var Driver, Mode : Integer;
X : Real; Xg, Yg, I : Integer;
Begin
{ Инициализация графического режима}
Driver := Detect;
InitGraph(Driver, Mode, 'C:\TP\BGI');
SetColor(White); (Белый цвет линий}
SetBkColor(Black); (Черный цвет фона}
Line(10, 90, 200, 90); (Ось X}
Line(10, 20, 10, 160); (Ось Y}
{Построение графика функции желтыми точкам}
X :=0;
For I := 0 То 190 Do
Begin Xg := 10 + Round(95/Pi * X);
Yg := 90 - Round(50 * Sin(X));
PutPixel(Xg, Yg, Yellow);
X := X + Pi/95 End;
TOC \o "1-5" \h \z {Разметка осей, запись функции}
OutTextXY(15, 30,'Y');
OutTextXY(205, 90,1Xf);
OutTextXY(130, 40, 'Y = Sin(X) '); Readln;{Задержка}
CloseGraph; {Выход из графики}
End.
Упражнения
Составить программу «Звездное небо»: расстановки в черном окне случайным образом белых точек, работа которой заканчивается нажатием клавиши.
Изменить программу «Звездное небо» таким образом, чтобы наряду с зажиганием новых звезд происходило угасание (закрашивание цветом фона) уже светящихся звезд.
В программу из примера 2.11 внести изменения, в результате которых робот окажется раскрашенным в разные цвета.
Используя линии и другие графические примитивы, составить программу, рисующую дом.
Составить программу рисования на экране шахматного поля.
Написать универсальную процедуру построения графика функции
y=F(x) точечным методом. Процедура должна иметь следующие параметры. Xmin, Хтах, Jniin> ^гпах»Д^тахэ ^min? I&max* ФУНКЦИЯ -/''(х) ОПИ-
сывается во внешней подпрограмме-функции.
а) У =
х + Г
х + 3. х-2’
ч 123
в) у = 1 + - + -J.
X XL
Исследовав область определения и выбрав расположение координатных осей, построить на экране, используя процедуру из предыдущей задачи, графики следующих функций:
Символьные строкиРассмотрим тип данных, относящийся к числу структурированных — строковый (строка). Следует заметить, что строковый тип данных есть в ТурбоПаскале и отсутствует в стандартном Паскале.
Строка — это последовательность символов. Каждый символ занимает 1 байт памяти (код ASCII). Количество символов в строке называется ее длиной. Длина строки может находиться в диапазоне от 0 до 255. Строковые величины могут быть константами и переменными.
Строковая константа — это последовательность символов, заключенная в апострофы. Например:
' Язык программирования ПАСКАЛЬ'
' IBM PC — computer',
' 33-45-12'.
Строковая переменная описывается в разделе описания переменных следующим образом:
Var <идентификатор> : String[<максимальная длина
строки>].
Например:
Var Name : String[20].
Длина строки может и не указываться в описании. В этом случае подразумевается, что она максимальна — 255 символов. Например:
Var Slovo : String.
Строковая переменная занимает в памяти на 1 байт больше, чем указанная в описании ее длина. Дело в том, что один (нулевой) байт содержит значение текущей длины строки. Если строковой переменной не присвоено никакого значения, ее текущая длина равна нулю.
По мере заполнения строки символами ее текущая длина возрастает, но она не должна превышать максимального по описанию значения.
Символы внутри строки индексируются (нумеруются), начиная с единицы. Каждый отдельный символ идентифицируется именем строки с индексом, заключенным в квадратные скобки. Например:
Name[5], Name[i], Slovo[k+1].
Индекс может быть положительной константой, переменной величиной и выражением целого типа. Значение индекса не должно выходить за границы описания.
Тип String и стандартный тип Char совместимы. Строки и символы могут употребляться в одних и тех же выражениях.
Строковые выражения строятся из строковых констант, переменных, функций и знаков операций. Над строковыми данными допустимы операции сцепления и операции отношения.
Операция сцепления (+) применяется для соединения нескольких строк в одну результирующую строку. Сцеплять можно как строковые константы, так и переменные. Например:
'ЭВМ'+' IBM'+' PC'.
В результате получится строка
'ЭВМ IBM PC' .
Длина результирующей строки не должна превышать 255 символов.
Операции отношений (=, <, >, <=, >=, о) производят сравнение двух строк, в результате чего получают логическую величину (True или False). Операция отношения имеет более низкий приоритет, чем операция сцепления. Сравнение строк производится слева направо до первого несовпадающего символа, и большей считается та строка, в которой первый несовпадающий символ имеет больший номер в таблице символьной кодировки.
Если строки имеют различную длину, но в общей части символы совпадают, считается, что более короткая строка меньше, чем более длинная. Строки равны, если они полностью совпадают по длине и содержат одни и те же символы. Например:
Выражение Результат
'cosml' < ' r cosm2' True
'pascal > 'PASCAL' True
1 Ключ ' о 'Ключ' True
fMS DOS' = 'MS DOS' True
• Функция Copy (S, Poz, N) — выделяет из строки S подстроку длиной N символов, начиная с позиции Poz. Здесь N и Poz — целочисленные выражения. Например:
Значение S Выражение Результат
'ABCDEFG' Copy(S, 2, 3) 'BCD'
'ABCDEFG' Copy(S, 4, 4) 'DEFG'
Функция Concat(Sl, S2,..., SN) выполняет сцепление (конкатенацию) строк S1,..., SN в одну строку. Например:
Выражение Результат
Concat('AA', 'XX', 'Y') 'AAXXY'
' test-5 *
'(А+В)*Cf
Length(S) Length(S)
6
7

• Функция Pos(Sl,S2)— обнаруживает первое появление в строке S2 подстроки S1. В результате получают целое число, равное номеру позиции, где находится первый символ подстроки S1. Если в S2 подстроки S1 не обнаружено, результат равен 0. Например:
Значение S2 Выражение Результат
* abcdef' Pos('cd’, S2) 3
'abcdcdef' Pos('cd', S2) 3
'abcdef * Pos (' k', S2) 0
• Процедура Delete (S, Poz, N) — удаляет N символов из строки S, начиная с позиции Poz. Например:
Исходное значение S Оператор Конечное значение
* abcdefgf 1abcdefg' Delete(S,3,2) Delete (S,2,6) * abefg' 'a*
В результате выполнения процедуры уменьшается текущая длина строки в переменной S.
• Процедура Insert (SI, S2, Poz) — вставляет строку S1 в строку S2, начиная с позиции Poz. Например:
Начальное S2 Оператор Конечное S2
'ЭВМ PC' Insert('IBM-',S2,5) 'ЭВМ IBM-PC
'Рис.' 2' Insert('N',S2,6) 'Рис. N2'
Пример 2.13. Программа получения из слова «ВЕЛИЧИНА» слова «НАЛИЧИЕ»:
Program Slovo_l;
Var Sll, S12 : String[10];
Begin
:= 'ВЕЛИЧИНА';
:= Copy(Sll,7,2) + Copy(Sll,3,4) + Sll[2]; ■WriteLn (S12)
End.
Пример 2.14. Программа получения из слова «СТРОКА» слова «СЕТКА»:
Program Slovo_2;
Var SI : String[10];
Begin
SI := 'СТРОКА';
Delete (SI,3,2);
Insert('E',SI,2);
WriteLn(SI)
End.
Пример 2.15. Программа, формирующая символьную строку, состоящую из N звездочек (где N — целое число, 1 < N < 255):
Program Stars;
Var А : String;
N, I : Byte;
Begin
Write ('Введите число звездочек');
ReadLn(N);
A := " ;
For I := 1 To N Do
A := A + ’*' ;
WriteLn(A)
End.
Здесь строковой переменной А сначала присваивается значение пустой строки (’'), а затем к ней присоединяются звездочки.
Пример 2.16. Программа подсчета в символьной строке числа цифр, предшествующих первому символу «!»:
Program С;
Var S : String;
К, I : Byte;
Begin
WriteLn('Введите строку');
ReadLn(S);
К := 0;
I := 1;
While (I <= Length(S)) And (S[I] о '!') Do Begin
If (S [ I] >= '0') And (S [i] <= '9')
Then К := К + 1;
I := I + 1 End;
WriteLn ('Количество цифр до символа "!" равно ', К) End.
В этой программе переменная К играет роль счетчика цифр, а переменная I — роль параметра цикла. Выполнение цикла закончится при первом же выходе на символ «!» или (если в строке такого символа нет) при выходе на конец строки. Символ S[I] является цифрой, если истинно отношение 'O' < S[I] < '9'.
Пример 2.17. Дана символьная строка вида: ’А ® В ='. Здесь А и В — десятичные цифры; знаком Ф обозначен один из знаков операций (+,*). Иначе говоря, дано арифметическое выра
жение с двумя однозначными числами и знаком равенства, например: '5 + 7 ='. Требуется, чтобы машина вычислила это выражение и после знака «=» вывела результат. Операция деления не рассматривается, чтобы иметь дело только с целыми числами.
Программа решения такой задачи называется интерпретатором. Интерпретатор должен расшифровать содержание строки и выполнить соответствующую арифметическую операцию. От исходной символьной информации он должен перейти к работе с числовой информацией.
Если предположить, что строка составлена только из четырех символов в соответствии с указанным форматом, то программа решения будет довольно простой:
Program Interpretator;
Var Str : String[4];
А, В : 0..9;
C : -100..100;
Begin
TOC \o "1-5" \h \z {Ввод исходной строки}
WriteLn('Введите выражение!');
WriteLn;
Read(Str);
{Преобразование цифровых символов в числа}
А := Ord(Str[1]) - Ord(’O');
В := Ord(Str[3]) - Ord('O');
(Выполнение арифметической операции}
Case Str[2] Of
С := А + В;
с := А - В;
с := А * В
TOC \o "1-5" \h \z End;
{Вывод результата}
WriteLn (C:2)
End.
В данной программе роль селектора в операторе выбора играет символьная величина Str [2]. Если она равна «+», выполним оператор С := А + В; если она равна «-», выполним оператор С := А - В; если она равна «*», выполним оператор С := А * В. Для любых
других значений Str [2] не выполним ни один из операторов присваивания, и значение переменной С остается неопределенным.
В этой программе использована неполная форма оператора Case, т.е. без ветви Else. Программа выдачи сообщения о получении неверного символа в Str [2] будет следующая:
Case Str[2] Of ' : С = А + В;
11 ' : С = А - В;
«* 1 ' : С = А * В
Else WriteLn(* Неверный знак операции *)
End;
Разберемся теперь в том, как будет выполняться программа Interpretator.
После ввода строки цифровые символы переводятся в соответствующие десятичные числа. Затем интерпретируется знак операции. В зависимости от этой интерпретации выполняется одно из трех арифметических действий. Далее результат выводится на экран после символа «=».
Упражнения
Составить программу получения из слова «дисковод» слова «воск», используя операцию сцепления и функцию Сору.
Составить программу получения слова «правило» из слова «операция», используя процедуры Delete и Insert.
В заданном слове заменить первый и последний символы на символ «*».
В заданном слове произвести обмен первого и последнего символов.
К заданному слову присоединить столько символов «!», сколько в нем имеется букв (например, из строки «УРА» получить «УРА!!!»).
В заданной строке вставить пробел после каждого символа.
Удвоить каждую букву введенного слова.
Перевернуть введенную строку (например, из строки «ДИСК» получить «КСИД»).
В заданной строке удалить все пробелы.
Составить программу перевода строки, представляющей собой запись целого числа, в соответствующую величину целого типа.
МассивыВ повседневной и научной практике часто приходится встречаться с информацией, представленной в табличной форме. Табл. 2.7 содержит среднемесячные значения температур за опре-
Линейная таблица температур
Месяц года 1 2 3 4 5 6 7 8 9 10 11 12
Температура, °С -21 -18 -7,5 5,6 10 18 22,2 24 17 5,4 -7 -18
деленный год. Такая таблица, представляющая собой последовательность упорядоченных чисел, называется линейной. Если требуется какая-то математическая обработка этих данных, то для их обозначения обычно вводят индексную символику. Например, Т{ обозначают температуру января (первого месяца), а Т5 — мая и т.д. В общем виде множество значений, содержащихся в таблице, обозначается следующим образом:
{Т,), /=1, ..., 12.
Порядковые номера элементов (1, 15, / и др.) называются индексами. Индексированные величины удобнее использовать при записи их для математической обработки. Например, для вычисления среднегодовой температуры используется следующая формула:
1 12
Теперь представьте, что требуется собрать информацию о среднемесячных температурах за 10 лет, например с 1981 по 1990 г. Используем для этого прямоугольную таблицу (табл. 2.8), в которой столбцы соответствуют годам, а строки — месяцам.
Удачно выбранная форма записи данных обеспечивает удобство и быстроту получения требуемой информации. Например, из
Таблица 2.8
Прямоугольная таблица температур
Год Месяц года
1 2 3 4 5 6 7 8 9 10 11 12
1981 -23 -17 -8,4 6,5 14 18,6 25 19 12.3 5,6 -4,5 -19
1982 -16 -8,5 -3,2 7,1 8,4 13,8 28,5 21 6,5 2 -13 -20
1983 -9,8 -14 -9,2 4,6 15,6 21 17,8 20 11,2 8,1 -16 -21
1990 -25 -9,7 -3,8 8,5 13,9 17,8 23,5 17,5 10 5,7 -14 -20
табл. 2.8 легко узнать, в каком году был самый холодный январь или в каком месяце был самым нестабильный температурный режим за указанное десятилетие.
Для значений, хранящихся в подобной таблице, удобно использовать двухиндексные обозначения. Например, Н{тл — обозначить температуру в феврале 1981 г. и т.д. При этом всю совокупность данных, составляющих таблицу, математически можно записать следующим образом:
{Ни}; /=1981... 1990; у=1...12.
Обработка таких данных производится с использованием двух- индексных величин. Например, средняя температура марта за 10 лет
11990
^ср.март = ТрГ ^ Я/,3,
1и (=1981
а средняя температура за весь десятилетний период
11990
^ср = То ^
1и 1=1981
1 12
11990 12
= ш х хя«-
/=1981 j=\
В Паскале аналогом таблиц является структурированный тип данных, который называется регулярным типом, или массивом. Как и таблица, массив представляет собой совокупность пронумерованных однотипных значений, имеющих общее имя. Элементы массива обозначаются как переменные с индексами. Индексы записываются в квадратных скобках после имени массива. Например:
Т[1], Т[5], T[i], Н[1981, 9], H[i, j]
Массив, хранящий линейную таблицу, называется одномерным, а прямоугольную — двухмерным. В программах могут использоваться массивы и большей размерности.
Тип элементов массива является его базовым типом. Очевидно, для рассмотренных массивов температур базовым типом является вещественный (Real).
Описание массивов. Переменная регулярного типа описывается в разделе описания переменных в следующей форме:
Var <идентификатор> : Array [<тип индекса>] Of <тип компонент^
Чаще всего в качестве типа индекса употребляется интервальный. Например, рассмотренный ранее одномерный массив среднемесячных температур можно описать следующим образом:
Var Т : Array [1..12] Of Real;
Описание массива определяет его размещение в памяти и правила дальнейшего употребления в программе. Последовательные элементы массива располагаются в последовательных ячейках памяти (Т[ 1 ], Т[2] и т.д.), причем значения индекса не должны выходить из диапазона 1..12. В качестве индекса может употребляться любое выражение соответствующего типа. Например, T[i + j], T[m div 2].
Тип индекса может быть любым скалярным порядковым типом, кроме Integer. Например, в программе могут присутствовать следующие описания:
Var Cod : Array[Char] Of 1..100;
L : Array[Boolean] Of Char;
В данной программе допустимы следующие обозначения элементов массивов:
Cod[’х']; L[True]; Cod[Chr(65)]; L[a > 0].
В некоторых случаях бывает удобно в качестве индекса использовать перечисляемый тип данных. Например, данные о количестве учеников в четырех десятых классах одной школы могут храниться в следующем массиве:
Type Index = (А, В, С, D) ;
Var Class_10 : Array[Index] Of Byte;
И если, например, элемент Class_ 10[А] равен 35, это означает, что в 10 А классе 35 человек. Такое индексирование делает программу более наглядной.
Часто структурированному типу данных присваивается имя в разделе типов, которое затем используется в разделе описания переменных:
Type Masl = Array [1..100] Of Integer;
Mas2 = Array [-10..10] Of Char;
Var Num : Masl; Sim : Mas2;
До сих пор речь шла об одномерных массивах, в которых типы элементов скалярные.
Многомерный массив в Паскале трактуется как одномерный массив, тип элементов которого также является массивом (массив массивов). Например, рассмотренную ранее прямоугольную таблицу можно хранить в массиве, описанном следующим образом:
Var Н : Аггау[1981..1990] Of Array[1..12] Of Real;
Приведем примеры обозначения некоторых элементов этого массива:
Н[1981] [1]; Н [1985] [10]; Н[1990] [12].
Однако чаще употребляется следующая, эквивалентная форма обозначения элементов двухмерного массива:
Н [1981, 1]; Н[1985, 10]; Н[1990, 12].
Здесь переменная Н[1981] обозначает всю первую строку таблицы, т.е. весь массив температур за 1981 г.
Эквивалентным вариантом приведенного описания двухмерного массива является также следующее:
Type Month = Array [1..12] Of Real;
Year = Array [1981..1990] Of Month;
Var H : Year;
Наиболее краткий вариант описания данного массива имеет вид
Var Н : Array[1981..1990, 1..12] Of Real;
Аналогично трехмерный массив можно определить как одномерный массив, у которого элементами являются двухмерные массивы. Например:
Var А : Array[1..10, 1..20, 1..30] Of Integer;
Это описание массива, состоящего из 10 • 20 • 30 = 6 000 целых чисел и занимающего в памяти 6000 ■ 2 = 12000 байт. В Паскале нет ограничения сверху на размерность массива. Однако в каждой конкретной реализации Паскаля ограничивается объем памяти, выделяемый под массивы. В ТурбоПаскале это ограничение составляет 64 Кбайт.
По аналогии с математикой одномерные числовые массивы часто называют векторами, а двухмерные — матрицами.
В Паскале не допускается употребление динамических массивов, т.е. массивов, размер которых определяется в процессе выполнения программы. Изменение размеров массива происходит через изменение в тексте программы и повторную компиляцию. Для упрощения таких изменений определяют индексные параметры в разделе констант:
Const Imax = 10; Jmax = 20;
Var Mas : Array[1..Imax, l..Jmax] Of Integer;
Теперь для изменения размеров массива Mas и всех операторов программы, связанных с этими размерами, достаточно отредактировать только одну строку в программе — раздел констант.
Действия над массивом как единым целым. Такие действия допустимы лишь в двух случаях:
присваивание значений одного массива другому;
в операциях отношений «равно», «не равно».
В обоих случаях массивы должны иметь одинаковые типы (тип индексов и тип элементов). Например:
Var Р, Q : Array[1..5,1..10] Of Real;
При выполнении операции присваивания
Р := Q
все элементы массива Р станут равны соответствующим элементам массива Q.
Как уже отмечалось, в многомерных массивах переменная с индексом может обозначать целый массив. Например, если в таблице Н требуется данные за 1989 г. сделать такими же, как за 1981 г. (девятой строке присвоить значение первой строки), то это можно сделать следующим образом:
Н[1989]:= Н[1981].
Поменять местами значения этих строк в таблице можно через третью переменную того же типа:
Р := Н[1989]; Н[1989] := Н[1981]; Н[1981] := Р;
Здесь Р описана следующим образом:
Var Р : Array [1..12] Of Real;
Обработка массивов в программах производится покомпонентно.
Приведем примеры ввода значений в массивы:
For I := 1 То 12 Do
ReadLn(Т[I]);
For I := 1 То IMax Do
For J := 1 To JMax Do ReadLn(Mas[I, J]);
Здесь каждое следующее значение будет вводиться с новой строки. Для построчного ввода используется оператор Read.
Аналогично в цикле по индексной переменной организуется вывод значений массива. Например:
For I := 1 То 12 Do Write(Т[I]: 8 : 4);
Следующий фрагмент программы организует построчный вывод матрицы на экран:
For I := 1 То Шах Do Begin
For J := 1 To JMax Do Write(Mas[I,J]:6);
WriteLn
End;
После печати очередной строки матрицы оператор WriteLn без параметров переведет курсор в начало новой строки. Следует заметить, что в последнем примере матрица на экране будет получена в естественной форме прямоугольной таблицы, если JMax не превышает 12 (самостоятельно объясните, почему).
Рассмотрим несколько примеров типовых программ обработки массивов.
Пример 2.18. Для заданного ранее массива среднемесячных температур Т[1...12] требуется вычислить среднегодовую температуру и ежемесячные отклонения от этого значения.
Программа решения данной задачи следующая:
Program Example;
Cont N = 12;
Type Vec = Array [1..N] Of Real;
Var T, Dt : Vec;
St : Real;
I : Integer;
Begin {Ввод исходных данных}
WriteLn('Вводите таблицу температур');
For I := 1 То N Do Begin
Write (I : 2,
ReadLn(T[I])
End;
{Вычисление средней температуры}
St := 0;
For I := 1 To N Do
St := St + T[I];
St := St/N;
{Вычисление таблицы отклонений от среднего}
For I := 1 То N Do
Dt[I]:= St - Т[I];
{Вывод результатов}
WriteLn('Средняя температура равна St : 6 : 2); WriteLn;
WriteLn('Отклонения от средней температуры:');
For I := 1 То N Do
WriteLn(1:1,':Dt[I]: б : 2)
End.
По этой программе можно рассчитать среднее значение и вектор отклонений от среднего значения для любого одномерного вещественного массива. Настройка размера массива осуществляется только редактированием раздела констант.
Пример 2.19. Требуется выбрать максимальный элемент из рассмотренного ранее массива температур, т. е отобрать самую высокую температуру и номер месяца, соответствующий ей.
Идея алгоритма решения этой задачи следующая: чтобы получить максимальную температуру в вещественной переменной ТМах, сначала в нее заносится первое значение массива Т[1]. Затем поочередно значение ТМах сравнивается с остальными элементами массива температур, и каждое значение, большее ТМах, присваивается этой переменной. Для получения номера самого теплого месяца в целую переменную NumMax следует засылать номер элемента массива температур каждый раз одновременно с занесением в ТМах его значения.
Программа решения данной задачи следующая:
ТМах := Т[1);
NumMax := 1;
For I := 2 То 12 Do If T[I] > Tmax Then Begin
ТМах := T[I];
NumMax := I
End;
Заметим, что если в массиве температур несколько значений, равных максимальному, то в NumMax будет получен первый номер из этих элементов. Для получения последней даты в операторе If следует заменить знак отношения «>» на «> =».
Пример 2.20. Требуется выполнить сортировку массива, т. е. в одномерном массиве X из N элементов требуется произвести пе
рестановку значений таким образом, чтобы они расположились по возрастанию: Х( й Х2 <... й XN.
Существует целый класс алгоритмов сортировки. Опишем алгоритм, называемый методом пузырька.
Производится последовательное упорядочивание смежных пар элементов массива: Х( и Х2, Х2 и Х3,..., XN _ \ и XN. В итоге максимальное значение переместится в XN. Затем ту же процедуру повторяют до получения XN_ ( и т.д., вплоть до получения цепочки из двух элементов X! и Х2. Такой алгоритм имеет структуру двух вложенных циклов, причем внутренний цикл будет переменной (сокращающейся) длины.
Программа решения данной задачи следующая:
For I := 1 То N - 1 Do
For К := 1 То N - I Do
If X [К] > X [К + 1]
Then
Begin
А := Х[К];
Х[К] := Х[К + 1];
Х[К +1]:= А
End;
Пример 2.21. Для описанного ранее двухмерного массива среднемесячных температур за 10 лет требуется определить, в каком году было самое теплое лето, т. е. в каком году была наибольшая средняя температура летних месяцев.
Идея алгоритма решения следующая: сначала в векторе S получить средние температуры летних месяцев за 10 лет, а затем найти номер наибольшего элемента в этом векторе. Это и будет искомый год.
Программа решения данной задачи:
Program Example_2;
Type Month = Array[1..12] Of Real;
Year = Array[1981..1990] Of Month;
Var H: Year;
S: Array[1981..1990] Of Real;
J, K: Integer;
Begin {Ввод данных с клавиатуры}
For I := 1981 To 1990 Do For J := 1 To 12 Do Begin
Write(J : 2,'.', I : 4, ' :');
ReadLn(H[I, J])
{Вычисление вектора средних летних температур}
For I := 1981 То 1990 Do Begin
S[I]:= 0;
For J:= 6 To 8 Do
S [I] := S[I] + H[I, J];
S[I] := S[I]/3
End;
{Определение года с самым теплым летом}
К := 1981;
For I := 1982 То 1990 Do
If S[I] > S[K] Then К := I;
WriteLn(1 Самое теплое лето было в К,1-м году1) End.
Упражнения
Дан вектор {^}, / = 1, ...» 50. Вычислить его длину:
L = ,/г,2 + z\ +... + 4>-
Вычислить полином 10-й степени по формуле Горнера: д10х10 + а9т? + ... + ахх + а0 = ((...(я10.х + а9)х + д8)х + ... + ах)х + а0.
Для вектора {*,}, /= 1, ..., 20 найти количество компонентов, значения которых лежат в интервале [0; 1].
Два заданных вектора {*/}, {у7}, /= 1, ..., 10, упорядоченных по возрастанию, слить в один вектор {г,}, /=1, ..., 20 таким образом, чтобы сохранилась их упорядоченность.
Для заданного массива, состоящего из 100 целых чисел, сначала вывести все числа, встречающиеся в нем несколько раз, а затем все числа, встречающиеся в нем только один раз.
Найти значение и индексы максимального элемента целочисленной матрицы размером 10x10 .
Определить номер строки с наибольшим количеством нулей двоичной матрицы размером 5x10.
Все строки вещественной матрицы размером 10x15 упорядочить по убыванию значений их элементов.
Транспонировать целочисленную матрицу размером 5x5, т.е. отразить ее относительно главной диагонали.
В двоичной матрице размером 10 х 10 найти совпадающие строки.
Рекурсивные подпрограммыРекурсия — это способ организации вспомогательного алгоритма — подпрограммы, при котором эта подпрограмма (процедура или функция) в ходе выполнения обращается сама к себе.
Рекурсивным называется любой объект, который частично определяется через самого себя.
Например, рекурсивным является следующее определение двоичного кода:
<двоичный код> ::= сдвоичная цифра> | сдвоичный код> <двоичная цифра>
<двоичная цифра> ::= 0 |1
В рекурсивном определении обязательно должно присутствовать ограничение, т.е. граничное условие, при выходе на которое дальнейшая инициация рекурсивных обращений прекращается.
Приведем примеры рекурсивных определений некоторых математических функций.
Классическим примером рекурсии является определение факториала. С одной стороны, факториал определяется в виде: п\ = = 1 • 2 • 3 •... • п, ас другой стороны, его можно определить следующим образом:
если п < 1; если п > 1.
, \1п\ = <
[(/!- 1)!я,
Граничным в данном случае является условие п < 1.
Рекурсивное определение функции К{п), возвращающей количество цифр в заданном натуральном числе п, имеет вид
fl,если л <10;
П {^(«/10) +1, если п > 10.
Рекурсивное определение функции S(n), вычисляющей сумму цифр заданного натурального числа, запишите самостоятельно по аналогии.
Рекурсивное определение функции С(т, и), где 0<т<п, для вычисления биномиального коэффициента С” по имеет следующий вид:
С
О _ г^п _ 1. Г'т _ г^т . Г'т-1 п “— ^„-1 ' ^Л_1 •
Обращение к рекурсивной подпрограмме ничем не отличается от вызова любой другой подпрограммы. При этом при каждом новом рекурсивном обращении в памяти создается новая копия подпрограммы со всеми локальными переменными. Такие копии будут создаваться до момента выхода на граничное условие. Очевидно, что в случае отсутствия граничного условия, неограниченный рост числа таких копий приведет к аварийному завершению программы, т.е. переполнения стека.
Порождение все новых копий рекурсивной подпрограммы до выхода на граничное условие называется рекурсивным спуском. Максимальное число копий рекурсивной подпрограммы, одно- вренно находящихся в памяти компьютера, называется глубиной рекурсии. Завершение работы рекурсивных подпрограмм, вплоть до самой первой, инициировавшей рекурсивные вызовы, называется рекурсивным подъемом.
Выполнение действий в рекурсивной подпрограмме может быть организовано одним из следующих способов:
Рекурсивный
подъем Рекурсивный
спуск Рекурсивный спуск и рекурсивный подъем
Begin Begin Begin
P; операторы; операторы;
операторы; P Р;
End; End; операторы
End;
Здесь Р — рекурсивная подпрограмма.
Действия в рекурсивной подпрограмме могут выполняться либо на одном из этапов рекурсивного обращения, либо на обоих сразу. Способ организации действий диктуется логикой разрабатываемого алгоритма.
Реализуем приведенные ранее рекурсивные определения в виде функций и процедур на Паскале.
Пример 2.22. Программные реализации рекурсивного определения факториала:
{Функция на Паскале}
Function Factrial (N : Integer) : Extended;
Begin
If N <= 1
Then Factorial := 1
Else Factrial := Factorial(N - 1) * N End;
{Процедура на Паскале}
Procedure Factorial (N : Integer; Var F : Extended); Begin
If N <= 1 Then F := 1 Else Begin
Factorial(N — 1, F);
F := F * N End
Пример 2.23. Программные реализации рекурсивного определения функции K(N), возвращающей количество цифр в заданном натуральном числе N:
{Функция на Паскале}
Function К(N : Longint) : Byte;
Begin
If N < 10 Then К := 1
Else К := К(N Div 10) + 1 End;
{Процедура на Паскале}
Procedure К(N : Longint; Var Kol : Byte)
Begin
If N < 10 Then Kol := 1 Else Begin
К(N Div 10, Kol);
Kol := Kol + 1 End
End;
Пример 2.24. Программные реализации рекурсивного вычисления биномиальных коэффициентов:
{Функция на Паскале}
Function С(m, n : Byte) : Longint;
Begin
If (m = 0) Or (m = n)
Then С := 1<
Else С := C(m, n - 1) + C(m - 1, n - 1)
End;
{Процедура на Паскале}
Procedure С(m, n : Byte; Var R : Longint);
Var Rl, R2: Longint;
Begin
If (m = 0) Or (m = n)*>•
Then R := 1 Else Begin
С (m, n - 1, Rl) ;
C (m - 1, n - 1, R2) ;
R := Rl + R2 End
End;
Пример 2.25. Вычисление суммы элементов линейного массива.
При решении данной задачи используем следующее утверждение: сумма равна нулю, если число элементов равно нулю, и равна сумме всех предыдущих элементов плюс последний, если число элементов не равно нулю.
Программа будет иметь следующий вид:
{Программа на Паскале }
Program Rec2;
Type LinMas = Array[1..100] Of Integer;
Var A : LinMas;
If N : Byte;
{Рекурсивная функция}
Function Sumrna(N : Byte; A : LinMas): Integer;
Begin
If N = 0
Then Summa : = 0
Else Summa := A[N] + Summa(N — 1, A)
End;
{Основная программа}
Begin
Write(* Количество элементов массива? 1);
ReadLn(N);
Randomize;
For I := 1 To N Do
Begin
A[I]:= -10 + Random(21);
Write(A[I]: 4)
End;
WriteLn;
WriteLn (’Сумма: f, Summa (N, A))
End.
Пример 2.26. Требуется определить, является ли заданная строка палиндромом, т. е. читается одинаково слева направо и справа налево. Граничное условие: строка является палиндромом, если она пустая или состоит из одного символа.
Идея решения данной задачи заключается в просмотре строки одновременно слева направо и справа налево и в сравнении соответствующих символов. Если в какой-то момент символы не совпадают, делается вывод о том, что строка не является палиндромом, если же удается достичь середины строки и при этом все соответствующие символы совпали, то строка является палиндромом.
t {Рекурсивная функция}
Function Pal(S : String): Boolean;
Begin
If Length(S) <= 1
Then Pal := True
Else Pal := (S[1 ] = S[Length(S)]) And Pal(Copy(S, 2, Length(S) - 2));
End;
Var S : String;
{Основная программа}
Begin
Write(1 Введите строку: f);
ReadLn(S);
If Pal(S)
Then WriteLn(1 Строка является палиндромом1)
Else WriteLn(1 Строка не является палиндромом1)
End.
Теперь, используя аналогичный подход, самостоятельно составьте программу определения, является ли заданное натуральное число палиндромом.
Подводя итог, заметим, что использование рекурсии является красивым приемом программирования. В то же время при решении большинства практических задач этот прием неэффективен, так как увеличивает время исполнения программы и зачастую требует значительного объема памяти для хранения копий подпрограммы на рекурсивном спуске. Следовательно, на практике разумно заменять рекурсивные алгоритмы на итеративные.
Упражнения
Привести собственные примеры содержательных задач, где для решения может быть использован рекурсивный вспомогательный алгоритм.
Определить, почему следующий алгоритм посимвольного формирования строки завершится аварийно:
Function Stroke : String;
Var С : Char;
Begin
Write(1 Введите очередной символ: '); ReadLn(С);
Stroka := Stroka + C
End;
На каком этапе выполняются действия в этом алгоритме?
Описать рекурсивную функцию pow(x, п) от вещественного х (х* 0) и целого п, вычисляющую величину хп по следующей формуле
1 при п = 0;
1 при п< 0;
X • Xя"1 при п > 0.
Даны натуральные числа пит. Найти НОД(я, /я), используя программу, включающую в себя рекурсивную процедуру вычисления НОД, основанную на соотношении НОД (л, т) = НОД(ш, г), где г— остаток от деления п на т.
МножестваОдним из фундаментальных разделов математики является теория множеств. Некоторые моменты математического аппарата этой теории реализованы в Паскале через множественный тип данных (множества).
Множеством называется совокупность однотипных элементов, рассматриваемых как единое целое. В Паскале могут быть только конечные множества. В ТурбоПаскале множество может содержать от 0 до 255 элементов.
В отличие от массива элементы множества не пронумерованы и не упорядочены. Каждый отдельный элемент множества не идентифицируется и с ним нельзя выполнять какие-либо действия. Действия могут выполняться только над множеством в целом.
Тип элементов множества называется базовым типом. Базовым может быть любой скалярный тип за исключением типа Real.
Конструктор множества. Конкретные значения множества задаются с помощью конструктора множества, представляющего собой список элементов, заключенный в квадратные скобки. Сами элементы могут быть либо константами, либо выражениями базового типа.
Приведем несколько примеров задания множеств с помощью конструктора:
[3, 4, 7, 9, 12] [1..100] [ 'а', 'Ь', 'с']
[ 'а'..'z']
множество из пяти целых чисел; множество целых чисел от 1 до 100; множество, содержащее три литеры а, Ь, с;
множество, содержащее все строчные латинские буквы, а также знаки ? и !.
Символом «[]» обозначают пустое множество, т.е. множество, не содержащее никаких элементов.
Не имеет значения порядок записи элементов множества внутри конструктора. Например, [1, 2, 3] и [3, 2, 1] — это эквивалентные множества.
Каждый элемент в множестве учитывается только один раз, поэтому множества [1, 2, 3, 4, 2, 3, 4, 5] и [1..5] эквивалентны.
Переменные множественного типа описываются следующим образом:
Var <идентификатор> : Set Of <базовый тип>.
Например:
Var A, D : Set Of Byte;
В : Set Of 'a'..'z';
C : Set Of Boolean;
Нельзя вводить значения в множественную переменную оператором ввода и выводить оператором вывода. Множественная переменная может получить конкретное значение только в результате выполнения оператора присваивания следующего формата:
<множественная переменная> ;= <множественное выражение>
Например:
А := [50,100,150,200];
В := ['m'j'n'j’k']; t
С := [True,False];
D := A;
Кроме того, выражения могут включать в себя операции над множествами.
Операции над множествами. В Паскале реализованы основные операции математической теории множеств: объединение, пересечение, разность. Во всех этих операциях операнды и результаты есть множественные величины одинакового базового типа.
Объединением двух множеств А и В называется множество, состоящее из элементов, входящих хотя бы в одно из множеств А или В. Знак операции объединения в Паскале — это «+».
На рис. 2.27, а схематически показан результат объединения двух множеств. Например:
+'[3,4,5, 6] -> [1,2,3,4,5, 6] .
Пересечением двух множеств А и В называется множество, состоящее из элементов, одновременно входящих и в множество А, и в множество В (рис. 2.27, б). Например:

абв
Рис. 2.27. Операции над множествами: а — объединение; б — пересечение; в — разность
* [3,4,5,б] ->• [3,4] .
Разностью двух множеств А и В называется множество, состоящее из элементов множества А, не входящих в множество В (рис. 2.27, в). Например:
- [3,4,5,6] -> [1,2]
[3,4,5,б] - [1,2,3,4] -> [5,6]
Очевидно, что операции объединения и пересечения перестановочные, а разность множеств — операция неперестановочная.
Множества можно сравнивать между собой, т.е. для них определены операции отношения. Результатом отношения, как известно, является логическая величина True или False. Для множеств применимы все операции отношения, за исключением «»> и «<».
В табл. 2.9 описаны операции отношения над множествами. При этом предполагается, что множества А и В содержат элементы одного типа.
Приведем несколько примеров выполнения операций отношения. Пусть переменная М описана в программе следующим образом:
Var М : Set Of Byte;
Таблица 2.9
Операции отношения над множествами
Отношение Результат
True False
А= В Множества А и В совпадают В противном случае
АоВ Множества А и В не совпадают То же
А<= В Все элементы А принадлежат В »
А>= В Все элементы В принадлежат А »
В разделе операторов ей присваивается значение
.М := [3,4,7,9];
Тогда операции отношения дадут следующие результаты:
М = [4, 7, 3, 3, 9,] — True;
М ■о [7, 4, 3, 9, ] — False;
[3, 4] <= М — True;
[] <= М — True;
М >= [1..10] - False;
М <= [3..9] — True.
Операция вхождения устанавливает связь между множеством и скалярной величиной, тип которой совпадает с базовым типом множества, т. е. если х — скалярная величина данного типа, а М— множество, то операция вхождения записывается в виде
х In м.
Результатом здесь будет логическая величина True, если значение х входит в множество М, и False — в противном случае. Для описанного ранее множества
In М — True,
In М — False.
Рассмотрим несколько задач, для решения которых удобно использовать множества.
Пример 2.27. Дана символьная строка. Требуется определить в ней количество знаков препинания (.— ,*:!?).
Программа для решения данной задачи:
Program Р1;
Var S: String; I, К: Byte;
Begin
ReadLn(S); К := 0;
For I := 1 To Length(S) Do
If S [I] In’!','?']
Then К := К + 1;
WriteLn('Число знаков препинания равно ', К)
End.
В этом примере использована множественная константа с символьным типом элементов. Однако задачу можно решить и без множества, записав в операторе If длинное логическое выражение (s[I] = '.') Or <s[I] = '-') и т.д. Использование множества сокращает запись.
Пример 2.28. Даны две символьные строки, содержащие только строчные латинские буквы. Требуется построить строку S3, в которую войдут только общие символы S1 и S2 в алфавитном порядке и без повторений.
Программа для решения данной задачи:
Program Р2;
Type Mset = Set Of 1 а *..1z *;
Var SI, S2, S3 : String;
MSI, MS2, MS3 : Mset;
C : Char;
Procedure SM(S : String; Var MS : Mset);
{Процедура формирует множество MS, содержащее все символы строки S}
Var I: Byte;
Begin MS := [];
For I := 1 To Length(S) DoMS := MS + [S [I]]
End;
Begin {Ввод исходных строк}
ReadLn(SI); ReadLn(S2) ;
{Формирование множеств MSI и MS2 из символов строк S1 и S2}
SM(S1, MSI); SM(S2, MS2);
{Пересечение множеств - выделение общих элементов в множество MS3}
MS3 := MSI * MS2;
{Формирование результирующей строки S3}
S3 := 1';
For С := 'а1 То 1z * Do
If С In MS3 Then S3 := S3 + С;
WriteLn('Результат: *, S3)
End.
Пример 2.29. Требуется составить программу, по которой из последовательности натуральных чисел от 2 до N (I < N < 255) будут выбраны все простые числа.
Существует алгоритм, известный под названием «Решето Эратосфена», суть которого состоит в следующем:
из числовой последовательности выбирают минимальное значение — простое число;
из последовательности удаляют все числа, кратные выбранному значению;
если после удаления всех кратных чисел последовательность не стала пустой, возвращаются к выполнению первого пункта.
Приведем пример работы такого алгоритма для N= 15 (здесь подчеркнуты выбранные простые числа):
2345 67 89 10 11 12 13 14 15 25 7 9 11 13 15 5 7 11 13 2 И 13 И 13 12
В программе решения данной задачи удобно использовать множественный тип данных:
Program Eratosfen;
Const N = 201;
{Возможно любое значение 1<N<256}
Var А, В : Set Of 2..N;
К, Р : Integer;
Begin
{Формирование исходного множества А; В — искомое множество простых чисел, сначала — пустое}
А := [2..N];
В := [];
Р := 2;
Repeat
{Поиск минимального числа в множестве А}
While Not (Р In A) Do Р := Р + 1;
{Включение найденного числа в множество В}
В := В + [Р];
К := Р;
{Исключение из А чисел, кратных Р}
While К <= N Do Begin
А := А - [К];
К := К + Р;
End
Until А = [];
{Вывод результата, т.е. всех чисел из множества В в порядке возрастания}
For Р := 2 То N Do If Р In В Then WriteLn(P)
End.
Это красивая программа. Но, к сожалению, ее нельзя использовать при N> 255 из-за отмеченного выше ограничения в Турбо- Паскале на максимальный размер множества.
Как уже говорилось, нельзя вводить значения непосредственно в множество. Однако такая потребность у программиста может возникнуть. В этом случае можно использовать процедуру INSET.
Для примера рассмотрим множество с символьным базовым типом, предполагая, что в основной программе глобально объявлен тип SetChar:
Type SetChar : Set Of Char;
Procedure INSET(Var M : SetChar);
Var I, N : Byte; C : Char;
Begin
Write('Укажите размер множества: '); ReadLn(N);
M := [];
For I := 1 To N Do Begin
Write(I:1,'-й элемент: '); ReadLn(C);
M := M + [C]
End;
WriteLn('Ввод завершен!')
End;
В основной программе для ввода значений в множество, например с именем SIM, достаточно записать оператор INSET(SIM). В результате произойдет диалоговый ввод значений.
Упражнения
В программе присутствуют следующие описания:
Var Р: Set Of 0..9; I, J : Integer;
Определить, какое значение получит переменная Р при выполнении следующих операторов присваивания, если /=3 и у=5:
а)Р := [I + 3, J Div 2, J..Sqr(I) - 3];
б)Р := [2*1. . J];
В) Р := [I, J, 2 * I, 2 * J]?
Вычислить значения следующих отношений:
а)[2]о[2,2,2];
б)['а',’b'] = [*Ь•,'а'];
В) [4,5,6] = [4,5,6];
г) ['с','Ь'] = ['с'..*Ъ'];
Д) [2,3,5,7] <= [1..9];
е)[3,6..8] <= [2..7,9];
ж)Trunc (3.9)In[1,3,5];
з)Odd(4) In [].
Вычислить значения следующих выражений:
а) [1,3,5] + [2,4];б) [1,3,5] * [2,4];
в) [1,3,5] - [2,4];г) [1..6] + [3..8];
д) [1..6] * [3..8]; ж) [] + [4]; и) [] - [4].
е) [1..6] - [3..8]; з) [] * [4];
Составить программу подсчета количества различных значащих цифр в десятичной записи натурального числа.
Составить программу, печатающую в возрастающем порядке все целые числа из интервала 1...255, представленные в виде п2 + т2, где п, т> 0.
Дана строка из строчных русских букв. Между соседними словами — запятая, за последним словом — точка. Составить программу, печатающую в алфавитном порядке:
а)все гласные буквы, которые входят в каждое слово;
б)все согласные буквы, которые не входят ни в одно слово;
в)все согласные буквы, которые входят только в одно слово;
г)все гласные буквы, которые входят более чем в одно слово.
ФайлыС термином «файл» вам уже приходилось встречаться. Прежде всего это понятие обычно связывают с информацией на устройствах внешней памяти.
В Паскале понятие файла имеет два значения:
поименованная информация на внешнем устройстве (внешний файл);
переменная файлового типа в Паскаль-программе (внутренний файл).
В программе между этими объектами устанавливается связь. Вследствие этого все, что происходит в процессе выполнения программы с внутренним файлом, дублируется во внешнем файле. С элементами файла можно выполнять только две операции: считывать из файла, записывать в файл.
Файловый тип переменной — структурированный тип, представляющий собой совокупность однотипных элементов, число которых заранее (до исполнения программы) не определено.
Структура описания файловой переменной имеет вид
Var <имя переменной> : File Of <тип элемента;»;
Здесь <тип элемента> может быть любым, кроме файлового. Например:
Var Fi:FileOfInteger;
Fr:FileOfReal;
Fc:FileOfChar;
Файл можно представить как последовательную цепочку элементов (Эл.), пронумерованных от 0, заканчивающуюся специальным кодом, называемым маркером конца (М.к.):
Эл. 0 Эл. 1 ... Эл. N М.к.
Число элементов, хранящихся в данный момент в файле, называется его текущей длиной. Существует специальная ячейка памяти, которая хранит адрес элемента файла, предназначенного для текущей обработки (записи или считывания). Этот адрес называется указателем, или окном, файла.
Для того чтобы начать запись в файл, его следует открыть для записи. Это обеспечивает процедура Rewrite(FV); (где FV — имя файловой переменной). При этом указатель устанавливается на начало файла. Если в файле до этого была информация, она исчезает.
Схематически выполнение процедуры Rewrite можно представить в следующем виде:
До: Эл. 0 Эл. 1 ... М.к.
Rewrite (FV); т
После: М.к. Т
Стрелкой снизу отмечается позиция указателя.
Запись в файл осуществляется процедурой Write (FV, V); (где V — переменная того же типа, что и файл FV). Запись происходит в том месте, на которое установлено окно (указатель файла). Сначала записывается значение, затем указатель смещается в следующую позицию. Если новый элемент вносится в конец файла, сдвигается маркер конца.
Схема выполнения данной процедуры следующая:
Эл. 0 Эл. 1 ... Эл. N М.к.
t
Write(FV, V);
Эл. 0 Эл. 1 ... Эл. N V М.к.
После:
Т
Пример 2.30. Требуется в файловую переменную Fx внести 20 вещественных чисел, последовательно вводимых с клавиатуры.
Программа решения следующая:
Var Fx : File Of Real;
X : Real; I: Byte;
Begin
Rewrite(Fx);
For I := 1 To 20 Do Begin
Write('? '); ReadLn(X);
Write(Fx, X)
End
End.
Для считывания элементов файла с его начала следует открыть файл для считывания, что выполняется процедурой Reset (FV). В результате указатель устанавливается на начало файла. При этом вся информация в файле сохраняется.
Схема выполнения данной процедуры следующая:
Эл. 0 Эл. 1 Эл. N М.к.
Reset(FV); т
Эл. 0 Эл. 1 Эл. N М.к.
До:
После:
Считывние из файла осуществляется процедурой Read (FV, V); (где V — переменная того же типа, что и файл FV). При этом значение текущего элемента файла записывается в переменную V, а указатель смещается к следующему элементу.
Схема выполнения данной процедуры следующая:
До:| Эл. о| Эл. 11 ... |Эл. к\ Эл. К+ l| ... |Эл. я|м!1с| [
Эл. 0 Эл. 1 ... Эл. К Эл. К+ 1 ... Эл. N М.к.
Read(FV, V);
После:
Эл. К
Т
Доступ к элементам файла может быть последовательным или прямым. В стандартном Паскале допускается только последовательный доступ к элементам.
Принцип последовательного доступа: для того чтобы прочитать п-ю запись файла, сначала следует прочитать все предыдущие записи с 1-й по (и - 1)-ю.
Пример 2.31. Требуется в переменной х получить 10-й элемент вещественного файла Fx.
Программа решения следующая:
Program А;
Var Fx : File Of Real;
X : Real;
Begin
Reset(Fx);
For I := 1 To 10 Do Read(Fx, X)
End.
Функция Eof(FV) проверяет маркер конца файла (end of file). Это логическая функция, которая получает значение True, если указатель установлен на маркер конца, и значение False — в противном случае.
Пример 2.32. Требуется просуммировать все числа из файла Fx, описанного в примере 2.31.
Программа решения следующая:
Reset(Fx);
Sx := 0;
While Not Eof(Fx) Do
Begin
Read(Fx, X) ;
Sx := Sx + X
End;
Также решить данную задачу можно с помощью цикла Repeat:
Repeat
Read(Fx, X);
Sx ;= Sx + X
Until Eof(Fx);
Во втором варианте возможна ошибка считывания, если файл Fx пустой. Первый вариант от такой ошибки застрахован, поэтому он предпочтительнее.
Внешние файлы. В ТурбоПаскале все внешние устройства (дисплей, клавиатура, принтер, диски и др.) трактуются как логические устройства с файловой структурой организации данных. Все немагнитные внешние устройства — однофайловые. Иначе говоря, с каждым из них связан один файл со стандартным именем, предназначенный для обмена с внутренней памятью ЭВМ текстовой (символьной) информацией.
Стандартные имена логических устройств определяются операционной системой, в среде которой работает Паскаль. В системе MS DOS определены следующие имена:
CON (консоль) — логическое устройство, связанное при вводе с клавиатурой, при выводе — с экраном;
PRN (принтер) — логическое имя файла, связанного с устройством печати;
AUX — логическое имя коммуникационного канала, который используется для связи ПК с другими машинами;
INPUT — стандартное устройство ввода, связанное с клавиатурой, причем вводимые с клавиатуры символы отражаются на экране дисплея;
OUTPUT — стандартное устройство вывода на экран.
Магнитный диск (МД) — многофайловое устройство. На нем могут храниться как стандартные (системные) файлы, так и файлы, создаваемые пользователем. На магнитном диске могут создаваться файлы любых типов. Файлы на МД могут использоваться как в режиме считывания, так и в режиме записи.
Список файлов на диске хранится в директории (каталоге) диска. Каталог вызывается на экран системной командой DIR. В полной форме каталог содержит идентификаторы файлов, объем занимаемой памяти, дату и время создания файла. Идентификатор файла состоит из имени и типа файла:
<имя файла>.<тип файла>
Имя файла содержит от одной до восьми латинских букв и (или) цифр; тип файла — необязательный элемент (от нуля до трех символов), указывающий на характер информации, хранимой в файле. Например:
PROGRAM.PAS — в файле текст программы на Паскале;
NUMBER.DAT — файл числовых данных;
NAMES.TXT — текстовый файл.
Для организации связи между файловой переменной и внешним файлом в ТурбоПаскале используется следующая процедура назначения:
Assign (<имя файловой переменной;»,
сидентификатор внешнего файла>).
Здесь <идентификатор внешнего файла> — строковая величина (константа или переменная). Например:
После выполнения процедур Assign и Rewrite создается новый внешний файл, имя которого заносится в директорию.
Если файл открывается для считывания (Assign и Reset), то в указанном каталоге уже должен содержаться указанный внешний файл. В противном случае будет обнаружена ошибка.
Работа с файлом в программе завершается его закрытием с помощью следующей процедуры:
Close (<имя файловой переменной;-);
Например:
Close(Fi).
Итак, последовательность действий при создании и заполнении файла:
описать файловую переменную;
описать переменную того же типа, что и файл;
произвести назначение (Assign);
открыть файл для записи (Rewrite);
записать в файл данные (Write);
закрыть файл (Close).
Пример 2.33. Требуется создать файл, содержащий среднесуточные температуры за некоторое количество дней. При этом не обязательно предварительно указывать количество чисел во вводимой информации. Можно договориться о каком-то условном значении, которое будет признаком конца ввода, например число 9999.
Программа решения следующая:
Program Taskl;
Var Ft : File Of Real; T : Real;
Begin
Assign(Ft, ’Temp.dat’); Rewrite(Ft);
WriteLn('Вводите данные. Признак конца - 9999');
ReadLn(Т);
While Т о 9999 Do
Begin
Write(Ft, T); Write('? '); ReadLn(T)
End;
WriteLn('Ввод данных закончен! ');
Close(Ft)
End.
В результате работы этой программы на диске будет создан файл с именем Temp.dat, в котором сохранится введенная информация.
Для последовательного считывания данных из файла требуется выполнить следующие действия:
описать файловую переменную;
описать переменную того же типа;
выполнить назначение (Assign);
открыть файл для считывания (Reset);
в цикле считывать из файла (Read);
закрыть файл (Close).
Пример 2.34. Требуется определить среднюю температуру для значений, хранящихся в файле Temp.dat.
Программа решения следующая:
Program Task2;
Var Ft : File Of Real;
T, St : Real; N : Integer;
Begin Assign(Ft, 'Temp.dat');
Reset(Ft);
St := 0;
While Not Eof(Ft) Do
Begin
Read(Ft, T) ;
St := St + T
End;
N := FileSize(Ft);
St := St/N;
WriteLn('Средняя температура за ',
N : 3,' суток равна', St : 7 : 2,' градусов');
Close(Ft)
End.
В этой программе использована следующая функция определения размера файла:
FileSize(<имя файловой переменной>);
Результат выполнения этой функции — целое число, равное текущей длине файла.
Примечание. Согласно стандартному языку Паскаль в файл, открытый оператором Rewrite, можно только записывать информацию, а файл, открытый оператором Reset, можно использовать только для считывания. В ТурбоПаскале допускается запись (Write) в файл, открытый для считывания (Reset), что создает определенные удобства для модификации файлов.
Текстовые файлы. Это наиболее часто употребляемая разновидность файлов. Как уже отмечалось ранее, немагнитные внешние устройства (логические) работают только с текстовыми файлами. Файлы, содержащие тексты программ на Паскале и других языках программирования, являются текстовыми. Различная документация и информация, передаваемые по каналам электронной связи, — все это текстовые файлы.
В программе файловая переменная текстового типа описывается следующим образом:
Var <идентификатор> : text;
Текстовый файл представляет собой символьную последовательность, разделенную на строки. Каждая строка символов (S) заканчивается специальным кодом — маркером конца строки (М.к.с.). Весь файл заканчивается маркером конца файла (М.к.ф.). Схематически это можно представить следующим образом:
S, S2 ... s« М.К.С. S, s2 ... S*2 M.K.C. М.к.ф.
При этом каждый символ представлен во внутреннем коде (ASCII) и занимает 1 байт. Однако не только делением на строки отличается текстовый файл от символьного: в текстовый файл можно записать, а также считать из него информацию любого типа. Если эта информация символьная, то в процессе считывания или записи происходит ее преобразование из символьной формы во внутреннюю, и обратно.
Текстовый файл можно создать или преобразовать с помощью текстового редактора, его также можно просмотреть на экране дисплея или распечатать на принтере.
В программах на Паскале для работы с текстовыми файлами наряду с процедурами Read и Write употребляются процедуры ReadLn и WriteLn.
Процедура, считывающая строку из файла с именем FV и помечающая прочитанное в переменные из списка ввода:
ReadLn(FV, Ссписок ввода>).
Процедура, записывающая в файл FV значения из списка вывода и выставляющая маркер конца строки:
WriteLn(FV, <список вывода>).
Функция Eoln (FV) используется для обнаружения конца строки в текстовом файле (end of line — конец строки). Это логическая функция, которая принимает значение True, если указатель файла достиг маркера конца строки, и значение False — в противном случае.
Употребление операторов Read и ReadLn без указания имени файловой переменной означает считывание из стандартного файла Input (ввод с клавиатуры). Употребление операторов Write и WriteLn без имени файловой переменной означает запись в стандартный файл Output (вывод на экран). Эти варианты операторов мы уже многократно использовали. Считается, что файлы Input и Output открываются соответственно для считывания и записи при работе любой программы.
При вводе с клавиатуры маркер конца строки обнаруживается при нажатии клавиши <Enter>.
Процедура ReadLn может использоваться без списка ввода. В этом случае происходит пропуск текущей строки в считываемом файле.
Употребление процедуры WriteLn без списка вывода означает вывод пустой строки (в файле выставляется маркер конца строки).
При записи в текстовый файл в списке вывода могут присутствовать форматы. Действия форматов уже рассматривались при описании вывода данных на экран (см. подразд. 2.6). Точно также форматы работают и при выводе в текстовые файлы, связанные с любыми другими устройствами.
Пример 2.35. Пусть файл с именем Note.txt содержит некоторый текст. Требуется определить количество строк в этом тексте.
Программа решения следующая:
Var Note : Text; К : Integer;
Begin
Assign(Note, 'Note.txt');
Reset(Note);
К := 0;
While Not Eof(Note) Do
Begin
ReadLn(Note);
К := К + 1
End;
WriteLn('Количество строк равно ', К);
Close(Note)
End.
Используемый здесь оператор ReadLn (Note) «пролистывает» строки из текстового файла Note, не занося их в какую-либо переменную.
Пример 2.36. Требуется в текстовом файле Note.txt определить длину самой большой строки.
Программа решения следующая:
Var Note : Text;
Мах, К : Integer; C: Char;
Begin
Assign(Note, 'Note.txt');
Reset(Note);
Max := 0;
While Not Eof (Note) Do
Begin
К := 0;
While Not Eoln(Note) Do
Begin
Read(Note, C);
К := К + 1
End;
If К > Max Then Max := K;
ReadLn(Note)
End;
WriteLn(1 Наибольшая строка имеет ', Max, 1 знаков’);
Close(Note)
End.
Здесь каждая строчка прочитывается посимвольно, при этом в переменной К работает счетчик числа символов в строке, а в переменной Мах отбирается наибольшее значение счетчика.
Пример 2.37, Требуется решить следующую задачу. Под действием силы F с начальной скоростью V в вязкой среде движется тело массой М. Сопротивление движению пропорционально квадрату скорости с коэффициентом К. Определить время прохождения пяти контрольных точек траектории движения, расстояние до которых от точки старта заданы.
Пусть с помощью текстового редактора в файле DATE.TXT исходные данные сформированы в виде следующей таблицы:
Исходные данные
М (кг) F (Н) V (м/с) К (кг/м)
36,3 2 000 50,5 0,5
Координаты контрольных точек (м)
ЗГ(1) Щ) *(3) т Х(5)
10 100 150 1000 3000
Следует ввести числовые данные в вещественные переменные М, F, V, К и массив Х[1..5], произвести расчеты, получить результаты в массиве Т[1..5], вывести их на экран, а также в текстовый файл на диске с именем Result.txt.
Приведем программу решения без расчетной части, показав только ввод исходных данных и вывод результатов:
Var М, F, V, К : Real; I : Integer;
Т, X : Array[1..5] Of Real;
FR, FD : Text;
Begin
Assign(FD, 'DATE.TXT'); Reset(FD);
Assign(FR, 'Result.txt'); Rewrite(FR);
TOC \o "1-5" \h \z {Пропуск первых трех строк}
ReadLn(FD); ReadLn(FD); ReadLn(FD);
{Ввод данных}
ReadLn(FD,M,F, V, K);
{Пропуск трехстрок)
ReadLn(FD); ReadLn(FD); ReadLn(FD);
{Ввод данных}
For I := 1 To 5 Do Read(FD, X[I]);
{РАСЧЕТНАЯ ЧАСТЬ ПРОГРАММЫ}
{Вывод результатов на экран и в файл FR}
WriteLn('Результаты '); WriteLn;
WriteLn(FR, ' Результаты'); WriteLn(FR);
WriteLn(' T(l) T(2) T(3) T(4) T(5)');
WriteLn(FR, ' T(l) T(2) T(3) T(4) T(5)');
For I := 1 To 5 Do
Begin
Write(T[I]:8:2); Write(FR, T[I]:8:2)
End;
Close(FD); Close(FR)
End.
Результаты будут сохранены в файле Result.txt. Их можно посмотреть на экране, распечатать на бумаге. При необходимости этот файл может стать входным для другой программы, если содержащаяся в нем информация будет являться исходной для решения другой задачи.
Упражнения
Дан файл вещественных чисел. Определить количество нулевых значений в этом файле.
Даны два файла целых чисел. Определить, являются ли они тождественными.
Даны два символьных файла одинакового размера. Произвести обмен информацией между ними.
Имеется внешний текстовый файл. Напечатать первую из самых коротких его строк.
Описать процедуру Lines (Т), которая построчно печатает содержимое непустого текстового файла Т, вставляя в начало каждой печатаемой строки ее порядковый номер, занимающий четыре позиции, и пробел.
В текстовом файле Т записана непустая последовательность вещественных чисел, разделенных пробелами. Описать функцию Мах(Т) для нахождения наибольшего из этих чисел.
Комбинированный тип данныхВсе структурированные типы данных, которые уже рассматривались, представляют собой совокупности однотипных величин.
Комбинированный тип данных— структурированный тип, состоящий из фиксированного числа компонент (полей) разного типа. Другое его название — запись.г
Обычно запись содержит совокупность разнотипных атрибутов, относящихся к одному объекту. Например, анкетные сведения о студенте вуза можно представить в виде информационной структуры, показанной на рис. 2.28, которая называется одноуровневым деревом. В Паскале эта информация может храниться в одной переменной типа Record (запись). Задать тип и описать соответствующую переменную можно следующим образом:
FIO : String[50]; {Поля}
Pol : Char; Dat : String[16]; {записи}
Adres : String[50]; Curs : 1..5; {или элементы}
Grup : 1..10; Stip : Real {записи}
End;
Var Student : Anketal;

Type Anketal = Record
Такая запись, как и соответствующее ей дерево, называется одноуровневой.
х К каждому элементу записи можно обратиться, используя составное имя, которое имеет следующую структуру:
<имя переменной>.<имя поля>
Например, Student.FIO; Student.Dat и т.д.
Если, например, полю «Курс» требуется присвоить значение 3, то это делается следующим образом:
Student.Curs := 3;
Поля записи могут иметь любой тип, в частности, сами могут быть записями. Такая возможность используется в случае, если требуется представить многоуровневое дерево (более одного уровня). Например, те же сведения о студентах можно отобразить двухуровневым деревом, показанным на рис. 2.29.
Такая организация данных позволит, например, делать выборки информации по году рождения или по городу, где живут студенты. В этом случае описание соответствующей записи будет иметь следующий вид:
Type Anketa2 = Record
FIO: String[50];
Pol: Char;
Dat: Record
God: Integer;
Mes: String[10];
Den: 1..31
End;
Adres: Record
Gorod: String[20];
UIDomKv: String[30];
End;
Curs: 1. . 5;
Grup: 1. .10;
Stip: Real End;
Var Student: Anketa2;
Поля такой записи, находящиеся на втором уровне, идентифицируются тройным составным именем. Например,
Student.Dat.God; Student.Adres.Gorod.
Структура описания комбинированного типа показана на рис. 2.30.

Рис. 2.29. Двухуровневое дерево
В программе могут использоваться массивы записей. Если на факультете 500 студентов, то все анкетные данные о них можно представить в массиве:
Var Student : Array[1..500] Of Anketal;
В этом случае, например, год рождения 5-го в списке студента хранится в переменной Student[5].Dat.God.
Любая обработка записей (в том числе ввод и вывод) производится поэлементно. Например, ввод сведений о 500 студентах можно выполнить следующим образом:
For I := 1 То 500 Do
With Student[I] Do
Begin
Write('ФИО: '); ReadLn(FIO);
Write('Пол (м/ж):'); ReadLn(Pol);
Write('Дата рождения: '); ReadLn(Dat);
Write('Адрес:') ; ReadLn(Adres);
Write('Курс: '); ReadLn(Curs);
Write('Группа:'); ReadLn(Grup);
Write('Стипендия (руб.):'); ReadLn(Stip)
End;
< Комбинированный тип>
<Список>
~гс
<Имя поля>
ООО<Тип>
► Record —► <Список> —► End —►
В этом примере использован оператор присоединения, имеющий следующий вид:
With спеременная типа запись> Do <оператор>;
Этот оператор позволяет, один раз указав имя переменной типа «Запись» после слова With, работать в пределах оператора с именами полей как с обычными переменными, т.е. не писать громоздких составных имен.
Тип «Запись» в Паскале может иметь переменный состав полей, который изменяется в ходе выполнения программы. Эта возможность реализуется с использованием так называемой вариантной части записи (подробнее см. в специальной литературе по языку Паскаль).
Работа с файлами записей. Чаще всего записи используются как элементы файлов, составляющих компьютерные информационные системы. Рассмотрим примеры программ, работающих с файлами записей.
Пример 2.38. Требуется сформировать файл FM.DAT, содержащий экзаменационную ведомость одной студенческой группы. Записи файла состоят из следующих элементов: ФИО; номер зачетной книжки; оценка.
Программа решения задачи:
Program Examen;
Type Stud = Record
FIO : String[30];
Nz : String[6];
Mark : 2..5 End;
Var Fstud : File Of Stud;
S : Stud;
N, I : Byte;
Begin
Assign(Fstud, 1FM.DAT *); Rewrite(Fstud);
Write(1 Количество студентов в группе? ');
ReadLn(N);
For I := 1 To N Do
Begin
Write (1:1,'-й, ФИО '); ReadLn(S.FIO) ;
Write('Номер зачетки: f); ReadLn(S.Nz);
Write(1 Оценка:1); ReadLn(S.Mark) ;
Write(Fstud, S)
End;
WriteLn('Формирование файла закончено!');
■Close(Fstud)
End.
Прежде чем перейти к следующему примеру, связанному с обработкой сформированного файла, рассмотрим еще одно средство работы с файлами.
Прямой доступ к записям файла. В стандартном языке Паскаль допустим только последовательный доступ к элементам файла. Одной из дополнительных возможностей, реализованных в Турбо- Паскале, является прямой доступ к записям файла.
Как уже отмечалось, элементы файла пронумерованы в порядке их занесения в файл, начиная с нуля. Задав номер элемента файла, можно непосредственно установить на него указатель, после чего можно считывать или перезаписывать данный элемент.
Установка указателя на заданный элемент файла производится процедурой
Seek(FV, п).
Здесь FV — имя файловой переменной, п — порядковый номер элемента.
Приведем пример использования этой процедуры.
Пример 2.39. Имеется файл, сформированный программой из примера 2.38. Пусть некоторые студенты пересдали экзамен и получили новые оценки. Требуется составить программу внесения результатов переэкзаменовки в файл, которая будет запрашивать номер студента в ведомости и его новую оценку. Работа заканчивается при вводе несуществующего номера (9999).
Программа решения следующая:
Program New_Marks;
Type Stud = Record
FIO : String[30]; Nz : String[6];
Mark : 2..5 End;
Var Fstud: File Of Stud;
S : Stud;
N : Integer;
Begin
Assign(Fstud, 'FM.DAT');
Reset(Fstud);
Write('Номер в ведомости? ');
ReadLn(N);
While N о 9999 Do
Begin
Seek(Fstud, N - 1);
Read(Fstud, S);
Write(S.FIO, ' оценка? ');
ReadLn(S.Mark);
Seek(Fstud, N — 1);
Write(Fstud, S);
Write(*Номер в ведомости? ');
ReadLn(N);
End;
WriteLn(1 Работа закончена!');
Close(Fstud)
End.
Данный пример требует некоторых пояснений. Список студентов в ведомости пронумерован, начиная с единицы, а записи в файле нумеруются с нуля. Следовательно, если п — это номер в ведомости, то номер соответствующей записи в файле равен п - 1. После прочтения записи номер п - 1 указатель смещается к следующей л-й записи. Для повторного внесения на то же место исправленной записи повторяют установку указателя.
Упражнения
Описать запись, содержащую сведения о рейсе самолета.
Описать массив записей, содержащий таблицу химических элементов Д. И. Менделеева. Составить программу заполнения массива.
Рассматривая комплексное число как двухэлементную запись, составить процедуры выполнения арифметических операций с комплексными числами.
Сведения о деталях, хранящихся на складе, содержат следующие атрибуты: название, количество, стоимость одной детали. Составить программы, решающие следующие задачи:
а)заполнить файл с информацией о деталях на складе;
б)вычислить общую стоимость деталей;
в)выяснить, какие детали имеются в наибольшем количестве и какие — в наименьшем;
г)вывести информацию о наличии на складе деталей данного типа и об их количестве;
д)внести изменения в файл после выдачи со склада определенного количества данного вида деталей. Если какой-то тип деталей полностью выбран со склада, уничтожить запись о нем в файле.
Указатели и динамические структуры данныхРанее рассматривалось программирование, связанное с обработкой только статических данных.
Статическими называются величины, память под которые выделяется во время компиляции и сохраняется в течение всей работы программы.
В Паскале существует и другой способ выделения памяти под данные — динамический. Динамическими называются величины, память под которые отводится во время выполнения программы.
Раздел оперативной памяти, распределяемый статически, называется статической памятью; динамически распределяемый раздел памяти называется динамической памятью.
Использование динамических величин предоставляет программисту ряд дополнительных возможностей. Во-первых, подключение динамической памяти позволяет увеличить объем обрабатываемых данных. Во-вторых, если потребность в каких-то данных отпала до окончания программы, то занятую ими память можно освободить для другой информации. В-третьих, использование динамической памяти позволяет создавать структуры данных переменного размера.
Работа с динамическими величинами связана с использованием еще одного типа данных — ссылочного.
Указатели. Величины, имеющие ссылочный тип, называют указателями.
Указатель содержит в динамической памяти адрес поля, в котором хранится величина определенного типа. Сам указатель располагается в статической памяти (рис. 2.31).
Адрес — это номер первого байта поля памяти, в котором располагается величина. Размер поля однозначно определяется типом.
Величина ссылочного типа (указатель) описывается в разделе описания переменных следующим образом:
Var <идентификатор> : <ссылочный тип>;
В стандартном Паскале каждый указатель может ссылаться на величину только одного определенного типа, который называется базовым для данного указателя. Имя базового типа указывается в описании в следующей форме:
<ссылочный тип> := А<имя типа>;
Статическая памятьДинамическая память
Указатель Величина
Адрес Значение
Приведем примеры описания указателей:
Type Massiv = Array[1..100] Of Integer;
Var PI : AInteger;
P2 : AChar;
Pm : AMassiv;
Здесь PI — указатель на динамическую величину целого типа; Р2 — указатель на динамическую величину символьного типа; РМ — указатель на динамический массив, тип которого задан в разделе Туре.
Сами динамические величины не требуют описания в программе, поскольку во время компиляции память под них не выделяется. Во время компиляции память выделяется только под статические величины. Указатели — это статические величины, поэтому они требуют описания.
Память под динамическую величину, связанную с указателем, выделяется в результате выполнения стандартной процедуры NEW. Формат обращения к этой процедуре следующий:
NEW(<указатель>);
Считается, что выполнение этого оператора создает динамическую величину, имя которой имеет следующий вид:
<имя динамической величины> ::= <указатель>А.
Пусть в программе, в которой имеется приведенное ранее описание указателя, имеются следующие операторы:
NEW(PI); NEW(Р2); NEW(РМ);
После их выполнения в динамической памяти оказывается выделенным место под три величины (две скалярные и один массив), имеющие соответственно идентификаторы Р1л, Р2А, РМЛ.
Статическая памятьДинамическая память

Например, Р1л — это обозначение динамической переменной, на которую ссылается указатель Р1.
На схеме, представленной на рис. 2.32, показана связь между динамическими величинами и их указателями.
Далее работа с динамическими переменными происходит точно так же, как со статическими переменными соответствующих типов, т.е. им можно присваивать значения, их можно использовать в качестве операндов в выражениях, параметров подпрограмм и т. д. Например, если переменной Р1Л требуется присвоить число 25, переменной Р2Л присвоить значение символа «W», а массив РМА заполнить по порядку целыми числами от 1 до 100, это делается следующим образом:
Р1Л := 25; Р2Л := 'W';
For I := 1 То 100 Do РМЛ[1] := I;
Кроме процедуры NEW значение указателя может определяться следующим оператором присваивания:
<указатель> := <ссылочное выражение>;
В качестве ссылочного выражения можно использовать:
указатель;
ссылочную функцию (т.е. функцию, значением которой является указатель);
константу NU.
Nil — это зарезервированная константа, обозначающая пустую ссылку, т. е. ссылку, которая ни на что не указывает. При присваивании базовые типы указателя и ссылочного выражения должны быть одинаковыми. Константу Nil можно присваивать указателю с любым базовым типом.
Ссылочная переменная до присваивания ей значения (с помощью оператора присваивания или процедуры NEW) является неопределенной.
Ввод и вывод указателей не допускается.
Рассмотрим пример. Пусть в программе описаны следующие указатели:
Var D, Р : AInteger;
К : лВоо1еап;
Тогда допустимыми являются операторы присваивания
D := Р; К := Nil,
поскольку должен соблюдаться принцип соответствия типов. Оператор К := D ошибочен, так как базовые типы правой и левой частей разные.
Если динамическая величина теряет свой указатель, она становится «мусором». В программировании так называют не нужную информацию, занимающую память.
Представьте, что в программе с описанными ранее указателями в разделе операторов записано следующее:
NEW(D); NEW(Р);
{Выделено место в динамической памяти под две целые переменные. Указатели получили соответствующие значения}
Da ;=3; Ра5;
{Динамическим переменным присвоены значения}
Р := D;
{Указатели PhD стали ссылаться на одну и ту же величину, равную 3}
WriteLn(PA, DA); {Дважды печатается число 3}
Таким образом, динамическая величина, равная 5, потеряла свой указатель и стала недоступной. Однако место в памяти она занимает. Это и есть пример возникновения «мусора». На рис. 2.33 показано, что произошло в результате выполнения оператора Р := D.
В Паскале имеется стандартная процедура, позволяющая освобождать память от данных, потребность в которых отпала. Ее формат
DISPOSE(<указатель>);
Например, если динамическая переменная Рл больше не требуется, оператор DISPOSE(P) удалит ее из памяти, после чего значение указателя Р станет неопределенным. Особенно существенный эффект экономии памяти получают при удалении больших массивов данных.
До выполнения оператора
После выполнения оператора
В версиях ТурбоПаскаля, работающих с операционной системой MS DOS, под данные одной программы выделяется 64 Кбайт памяти. Это и есть статическая область памяти. При необходимости работы с большими массивами информации этого может ока-
заться недостаточно. Размер динамической памяти намного больше (сотни килобайт), поэтому ее использование позволяет существенно увеличить объем обрабатываемой информации.
Следует отчетливо понимать, что работа с динамическими данными замедляет выполнение программы, поскольку доступ к величине происходит в два шага: сначала определяется указатель, а затем по нему — величина. Как это часто бывает, действует «закон сохранения неприятностей», т.е. выигрыш в объеме памяти компенсируется проигрышем во времени.
Пример 2.40. Требуется создать вещественный массив из 10000 чисел и заполнить его случайными числами в диапазоне от 0 до 1. Вычислить среднее значение массива. Очистить динамическую память. Создать целый массив размером 10000, заполнить его случайными целыми числами в диапазоне от -100 до 100 и иычислить его среднее значение.
Программа решения следующая:
Program Sr;
Const Шах = 10000;
Type Diapazon = l..NMax;
Maslnt = Array[Diapazon] Of Integer;
MasReal = Array[Diapazon] Of Real;
Var Plint : AMasInt;
PReal : AMasReal;
I, Midint : longlnt;
MidReal : Real;
Begin
MidReal := 0; Midint := 0;
Randomize;
NEW(PReal);
{Выделение памяти под вещественный массив) {Вычисление и суммирование массива)
For I := 1 То NMax Do Begin PRealA[I] := Random;
MidReal := MidReal + PRealA[I]
End;
DISPOSE(PReal);{Удаление вещественного массива) NEW(Pint); {Выделение памяти под целый массив) {Вычисление и суммирование целого массива)
For I := 1 То NMax Do Begin
PIntA[I] := Random(200) - 100;
Midint := Midint + PIntA[I]
End;
{Вывод средних значений)
WriteLn('Среднее целое равно:',MidInt Div Max);
WriteLn('Среднее вещественное равно:
(MidReal / NMax): 10: 6)
End.
Связанные списки. Рассмотрим теперь как в динамической памяти можно создать структуру данных переменного размера.
Разберем следующий пример. В процессе физического эксперимента многократно снимаются показания прибора (допустим, термометра) и записываются в компьютерную память для дальнейшей обработки. Заранее неизвестно, сколько будет произведено измерений.
Если для обработки таких данных не использовать внешнюю память (файлы), то разумно расположить их в динамической памяти. Во-первых, динамическая память позволяет хранить больший объем информации, чем статическая. Во-вторых, в динамической памяти эти числа можно организовать в связанный список, который не требует предварительного указания количества чисел подобно массиву. Что же такое связанный список? Схематически его можно представить следующим образом:
*1 Pi —> *2 Ръ *3 Ра —> *4 Nil
Каждый элемент списка состоит из двух частей: информационной (*[, х2,•••) и указателя на следующий элемент (р2, /»3,...). Последний элемент имеет пустой указатель Nil. Связанный список такого типа называется однонаправленной цепочкой.
В сформулированной задаче информационная часть содержит следующие вещественные числа: х\ — результат первого измерения; х2 — результат второго измерения; х3 — результат третьего измерения; х4 — результат последнего измерения. Связанный список обладает тем замечательным свойством, что его можно дополнять по мере поступления новой информации. Дополнение происходит присоединением нового элемента к концу списка, а значение Nil в последнем элементе заменяется ссылкой на новый элемент цепочки:
*1 Pi —> *2 Ръ —> *3 Ра —> *4 Ръ *5 Nil
Связанный список не занимает лишней памяти. Память расходуется в том объеме, который требуется для поступившей информации.
В программе для представления элементов цепочки используется комбинированный тип данных — запись. В нашем примере тип такого элемента может быть следующим:
Туре Ре = AElem;
Elem = Record
T : Real;
P : Pe End;
Здесь Ре — это ссылочный тип на переменную типа Elem. Этим именем обозначен комбинированный тип, состоящий из двух молей: Т — вещественной величины, хранящей значение температуры, и Р — указателя на динамическую величину типа Elem.
В данном описании нарушен один из основных принципов языка Паскаль, согласно которому на любой программный объект можно ссылаться только после его описания. В самом деле, тип Ре определяется через тип Elem, который, в свою очередь, определяется через тип Ре. Однако в Паскале существует единственное исключение из этого правила, связанное со ссылочным типом. Приведенный фрагмент программы является правильным.
Пример 2.41. Программа формирования связанного списка в ходе ввода данных:
Туре Ре - ЛТурЕ1ет;
TypElem = Record
Т : Real; Р : Ре End;
Var Elem, Beg : Ре;
X : Real; Ch : Char;
Begin
{Определение адреса начала списка и его сохранение} NEW(Elem);
Beg := Elem;
ElemA.P := Elem;
{Диалоговый ввод значений с занесением их в список
и организацией связи между элементами}
While ElemA.P о Nil Do
Begin
Write(’Вводите число: '); ReadLn(ElemA.T);
Write(* Повторить ввод? (Y/N) 1); ReadLn(Ch);
If (Ch = ' n') Or (Ch = 'N')
Then ElemA.P := Nil Else Begin
NEW (ElemA . P) ;
Elem := ElemA.P End
End;
WriteLn(1 Ввод данных закончен');
{Вывод полученной числовой последовательности)
WriteLn('Контрольная распечатка');
Е1еш := Вед;
Repeat
WriteLn(N,Е1ешЛ.Т : 8 : 3);
Elem := Е1ешл.Р
Until Elem = Nil
End.
Здесь ссылочная переменная Beg используется для сохранения адреса начала цепочки. Всякая обработка цепочки начинается с ее первого элемента. В программе показано, как происходит продвижение по цепочке при ее обработке (в данном примере при распечатке информационной части списка по порядку).
Однонаправленная цепочка — простейший вариант связанного списка. В практике программирования используются также двунаправленные цепочки (когда каждый элемент хранит указатель на следующий и предыдущий элементы списка) и двоичные деревья. Подобные структуры данных называются динамическими.
Одной из часто употребляемых в программировании динамических структур данных является стек. Стек — это связанная цепочка, начало которой называется вершиной и состав элементов которой постоянно меняется. Каждый вновь поступающий элемент устанавливается в вершине стека. Удаление элементов из стека также производится с вершины.
Стек подобен детской пирамидке, в которой на стержень надеваются кольца. Всякое новое кольцо оказывается на ее вершине. Снимать кольца можно только сверху. Принцип изменения содержания стека часто формулируют как «последним пришел — первым вышел».
Пример 2.42. Требуется составить процедуры добавления элемента в стек (INSTEK) и исключения элемента из стека (OUTSTEK), если эти элементы — символьные величины.
В процедурах используется тип данных Ре, который должен быть глобально объявлен в основной программе:
Туре Ре = ЛТурЕ1ет;
TypElem = Record
С : Char; Р : Ре End;
В приведенной далее процедуре INSTEK аргументом является параметр Sim, содержащий включаемый в стек символ. Ссылочная переменная Beg содержит указатель на вершину стека при входе в процедуру и при выходе из нее. Следовательно, этот параметр является и аргументом, и результатом процедуры. В случае когда стек пустой, указатель Beg равен Nil.
Procedure INSTEK(Var Beg : Pe; Sim : Char);
Var X : Pe;
Begin New(X);
XA.C := Sim;
XA.P := Beg;
Beg := X
End;
В приведенной далее процедуре OUTSTEK параметр Beg играет ту же роль, что и в предыдущей процедуре, т.е. после удаления последнего символа его значение станет равным Nil. Ясно, что если стек пустой, то удалять из него нечего. Логический параметр Flag позволяет распознать этот случай: если на выходе из процедуры Flag = True, это значит, что удаление произошло, а если Flag = False, это значит, что стек был пуст и ничего не изменилось.
Procedure OUTSTEK (Var Beg : Pe; Var Flag : Boolean);
Var X : Pe;
Begin
If Beg = Nil Then Flag := False Else Begin
Flag := True;
X := Beg;
Beg := BegA.P;
DISPOSE(X)
End
End;
Данная процедура не оставляет после себя «мусора», освобождая память от удаленных элементов.
Упражнения
В программе имеются описания.
Var Р, Q : АInteger; R : AChar;
Определить, какие из следующих операторов неправильные и почему:
а) Р :=Q;б) Q := R;в) Р := Nil;г) R := Nil;
д) Q :=РА;е) РА := Nil;ж) RA:=РА;з) QA := Ord(RA);
и) If RО Nil Then RA :=NilA; к)IfQ >Nil Then QA := PA;
Л) If P= QThen Write (Q);m)IfQ оR Then Read(RA).
В программе имеются описания
Туре А = AChar;
В = Record FI : Char; F2 : A End;
Var Р : ЛВ; Q: А;
Определить значения всех указателей и динамических переменных после выполнения следующих операторов:
NEW(Q); QA := 171;
NEW(Р); РЛ.Fl := Succ(QA); PA.F2 := Q;
Найти ошибки в следующей программе:
Program Example;
Var А, В : АInteger;
Begin If А = Nil Then Read(A);
AA := 5; В := Nil; BA := 2;
NEW(В); Read(BA); WriteLn(B, BA);
NEW(A); В := A; DISPOSE(A); BA:= 4
End.
Составить программу занесения в динамическую память вещественного массива из 10000 чисел, хранящегося в файле на магнитном диске, а также поиска в нем значения и номера первого максимального элемента.
Выполнить четвертое упражнение при условии, что размер числового массива заранее не определен (определяется размером файла: предполагается, что размер файла не превышает размера динамической памяти). Данные в динамической памяти организовать в виде связанного списка.
Связанный список представляет собой символьную цепочку из строчных латинских букв. Описать следующую процедуру или функцию:
а)определяющую, является ли список пустым;
б)заменяющую в списке все вхождения одного символа на вхождения другого;
в)меняющую местами первый и последний элементы непустого списка;
г)проверяющую, упорядочены ли элементы списка по алфавиту;
д)определяющую, какая буква входит в список наибольшее количество раз.
Составить тестовую программу, проверяющую правильность работы процедур INSTEK и OUTSTEK из примера 2.42.
Очередью называется динамическая структура (связанная цепочка), в которой действует принцип «первым пришел, первым вышел». Написать процедуры включения элемента в очередь и исключения элемента из очереди. Составить тестовую программу, проверяющую работу процедур.
Внешние подпрограммы и модулиСтандартный Паскаль не располагает средствами разработки и поддержки библиотек программиста (в отличие от Фортрана и других языков программирования высокого уровня), которые компилируются отдельно и в дальнейшем могут быть использованы не только самим разработчиком. Если программист имеет достаточно большие наработки и если те или иные подпрограммы могут быть использованы при написании новых приложений, приходится эти подпрограммы целиком включать в новый текст.
В ТурбоПаскале это ограничение преодолевается, во-первых, введением внешних подпрограмм, а во-вторых, созданием и использованием модулей. Рассмотрим оба способа.
Введение внешних подпрограмм. В этом случае исходный текст каждой процедуры или функции хранится в отдельном файле и при необходимости с помощью специальной директивы компилятора включается в текст создаваемой программы.
Проиллюстрируем этот прием на примере следующей задачи целочисленной арифметики: дано натуральное число п, требуется найти сумму первой и последней цифр этого числа.
Для решения задачи используем функцию, вычисляющую число цифр в записи натурального числа. Например:
Function Digits(N : Longlnt): Byte;
Var Kol : Byte;
Begin
Kol := 0;
While N о 0 Do
Begin
Kol := Kol + 1;
N := N Div 10
End;
Digits := Kol
End;
Сохраним этот текст в файле с расширением .inc (расширение внешних подпрограмм в ТурбоПаскале), например digits.inc.
Опишем также функцию возведения натурального числа в натуральную степень (а”):
Function Power(A,N:Longlnt):Longlnt;{файл power.inc}
Var I, St : Longlnt;
Begin
St := 1;
For I := 1 To N Do
St := St * A;
Power := St
End;
Теперь составим основную программу, решающую поставленную задачу с использованием описанных функций:
Program Examplel;
Var N, S : Integer;
{$1 digits.inc} {Подключение внешней функции из файла digits.inc, вычисляющей количество цифр в записи числа} {$1 power.inc} {Подключение внешней функции из файла power.inc, вычисляющей результат возведения числа А в степень N}
Begin
Write(1 Введите натуральное число: '); ReadLn(N); {Для определения последней цифры числа N берется остаток от деления этого числа на 10, а для определения первой цифры число N делится на число 10, возведенное в степень, на единицу меньшую, чем количество цифр в записи числа N (так как нумерация разрядов начинается с 0) }
S := N Mod 10 + N Div Power(10, Digits(N) - 1); WriteLn(1 Искомая сумма: ', S)
End.
Директива компилятора {$1 <имя файла>} позволяет в данное место текста программы вставить содержимое файла с указанным именем.
Файлы с расширением .inc можно накапливать на магнитном диске, формируя таким образом личную библиотеку подпрограмм.
Внешние процедуры создаются и внедряются в использующие их программы так же, как и функции в рассмотренной задаче.
Создание и использование модулей. Рассмотрим теперь структуру, разработку, компиляцию и использование модулей.
Модуль — это набор ресурсов (функций, процедур, констант, переменных, типов и т.д.), разрабатываемых и хранимых независимо от использующих их программ. В отличие от внешних подпрограмм, модуль может содержать достаточно большой набор процедур и функций, а также других ресурсов для разработки программ. В основе идеи модульности лежат принципы структурного программирования. Существуют стандартные модули ТурбоПаскаля (SYSTEM, CRT, GRAPH и др.), справочная информация по которым дана в приложениях 1...3. Модуль имеет следующую структуру:
Unit <имя модуля>; {Заголовок модуля}
Interface
{Интерфейсная часть}
Implementation
{Раздел реализации}
Begin
{Раздел инициализации модуля}
End.
После служебного слова Unit записывается имя модуля, кото- |юе (для удобства дальнейших действий) должно совпадать с именем файла, содержащего данный модуль. Следовательно (как принято в MS DOS), имя не должно содержать более восьми символов.
В разделе Interface объявляются все ресурсы, которые будут в дальнейшем доступны программисту при подключении модуля. Для подпрограмм здесь указывается лишь полный заголовок.
В разделе Implementation описываются все подпрограммы, которые были ранее объявлены. Кроме того, в нем могут содержаться свои константы, переменные, типы, подпрограммы, которые носят вспомогательный характер и используются для написания основных подпрограмм. В отличие от ресурсов, объявленных в разделе Interface, все, что дополнительно объявляется в Implementation, уже не будет доступно при подключении модуля. При описании основной подпрограммы достаточно указать ее имя, не переписывая полностью весь заголовок, а затем записать тело.
Раздел инициализации (зачастую отсутствующей) содержит операторы, которые должны быть выполнены сразу же после запуска программы, использующей модуль.
Приведем пример разработки и использования модуля. (Поскольку рассматриваемая далее задача достаточно элементарна, ограничимся распечаткой текста программы с подробными комментариями.)
Пример 2.43. Реализовать в виде модуля набор подпрограмм для выполнения над обыкновенными дробями вида P/Q (где Р — целое число, Q— натуральное число) следующих операций: сложения, вычитания, умножения, деления, сокращения, возведения в степень N (где N— натуральное число), а также функций, реализующих операции отношения (равно, не равно, больше или равно, меньше или равно, больше, меньше).
При этом дробь представить следующим типом:
Type Frac = Record
Р : Integer;
Q : 1..32767 End;
С использованием разработанного модуля решить две задачи.
Дан массив А, элементы которого — обыкновенные дроби. 11айти сумму всех элементов и их среднее арифметическое. Ответы представить в виде несократимых дробей.
Дан массив А, элементы которого — обыкновенные дроби. Отсортировать его в порядке возрастания.
Реализация набора подпрограмм в виде модуля:
Unit Droby;
Interface
Type
Natur = 1..High(Longlnt);
Frac = Record
P : Longlnt;
Q : Natur End;
Procedure Sokr(Var A : Frac);
Procedure Summa(A, В : Frac; Var C : Frac); Procedure Raznost(A, В : Frac; Var C : Frac); Procedure Proizvedenie(A, В : Frac; Var C : Frac); Procedure Chastnoe(A, B: Frac; Var C : Frac); Procedure Stepen(A : Frac; N : Natur; Var C : Frac); Function Menshe(A, В : Frac): Boolean;
Function Bolshe(A, В : Frac): Boolean;
Function Ravno(A, В : Frac): Boolean;
Function MensheRavno(A, В : Frac): Boolean; Function BolsheRavno(A, В : Frac): Boolean; Function NeRavno(A, В : Frac): Boolean;
{Раздел реализации модуля)
Implementation
{Наибольший общий делитель двух чисел - вспомогательная функция, ранее не объявленная) Function NodEvklid(A, В : Natur): Natur;
Begin
While А о В Do If A > В Then
If A Mod В о 0 Then A := A Mod В Else A := В
Else
If В Mod A о 0 Then В := В Mod A Else В := A;
NodEvklid := A
End;
{Сокращение дроби}
Procedure Sokr;
Var M, N : Natur;
Begin
If A.P О 0
Then
Begin
If A.P < 0
Then M := Abs(A.P)
Else M := A.P; {Совмещение типов, так как А.Р - Longlnt)
N := NodEvklid(M, A.Q);
A. P := A. P Div N;
A.Q := A.Q Div N
End
End;
Procedure Summa; {Сумма дробей}
Begin
{Знаменатель дроби}
C.Q := (A.Q * B.Q) Div NodEvklid(A.Q, B.Q); {Числитель дроби}
C.P := A.P * C.Q Div A.Q + B.P * C.Q Div B.Q Sokr(C)
End;
Procedure Raznost; {Разность дробей}
Begin
{Знаменатель дроби}
C.Q := (A.Q * B.Q) Div NodEvklid(A.Q, B.Q); {Числитель дроби}
C.P := A.P * C.Q Div A.Q - B.P * C.Q Div B.Q Sokr(C)
End;
Procedure Proizvedenie; {Умножение дробей} Begin
{Знаменатель дроби}
C.Q := A.Q * B.Q;
{Числитель дроби}
C.P := A.P * B.P;
Sokr(C)
End;
Procedure Chastnoe; {Деление дробей}
Begin
{Знаменатель дроби}
C.Q := A.Q * B.P;
{Числитель дроби}
C.P := A.P * B.Q;
Sokr(C)
End;
Procedure Stepen; {Возведение дроби в степень} Var I : Natur;
Begin
C.Q := 1;
C.P := 1;
Sokr(A);
For I := 1 To N Do
Proizvedenie(A, С, C)
End;
Function Menshe;{Отношение <«» между дробями}
Begin
Menshe := A.P * B.Q < A.Q * B.P End;
Function Bo1she; {Отношение «>» между дробями} Begin
Bolshe := A.P * B.Q > A.Q * B.P End;
Function Ravno; {Отношение «=» между дробями}
Begin
Ravno := A.P * B.Q = A.Q * B.P End;
Function BolsheRavno; {Отношение «>» между дробями} Begin
BolsheRavno := Bolshe(A, B) Or Ravno(A, B)
End;
Function MensheRavno; {Отношение «<» между дробями} Begin
MensheRavno := Menshe(A, B) Or Ravno(A, B)
End;
Function NeRavno; {отношение «о» между дробями} Begin
NeRavno := Not Ravno(A, B)
End;
{Раздел инициализации модуля}
Begin
End.
При разработке модуля рекомендуется следующий порядок:
спроектировать модуль, т.е. определить основные и вспомогательные подпрограммы и другие ресурсы;
описать компоненты модуля;
отладить каждую подпрограмму отдельно, после чего «вклеить» в текст модуля.
Сохраним текст разработанной программы в файле DROBY.PAS и откомпилируем модуль, используя внешний компилятор, поставляемый вместе с ТурбоПаскалем. Команда будет иметь вид ТРС DROBY.PAS. Если в тексте нет синтаксических ошибок, получим файл DROBY.TPU, иначе будет выведено соответствующее сообщение с указанием строки, содержащей ошибку. Другой вариант компиляции: в меню системы программирования Турбо- Паскаль выбрать Compile/Destination Disk, а затем — Compile/Build.
Теперь можно подключить разработанный модуль к программе, где планируется его использование.
Программа решения первой поставленной задачи суммирования массива дробей:
Program Sum;
Uses Droby;
Var A : Array[1..100] Of Frac;
I, N : Integer;
S : Frac;
Begin
Write(1 Введите количество элементов массива: ');
ReadLn(N);
S.P := 0; S.Q := 1; {Первоначально сумма равна нулю}
For I := 1 To N Do {Вводим и суммируем дроби}
Begin
Write('Введите числитель ', I, '-й дроби: ');
ReadLn(А[I].Р);
Write('Введите знаменатель I, '-й дроби: ');
ReadLn(A[I].Q);
Summa(А[I], S, S);
End;
WriteLn(1 Ответ:S.P,S.Q)
End.
Вторую поставленную задачу — сортировку массива — читателю предлагается решить самостоятельно.
Как видно из приведенного примера, для подключения модуля используется служебное слово Uses, после которого указывается имя модуля. Данная строка записывается сразу же после заголовка программы. Если необходимо подключить несколько модулей, они перечисляются через запятую.
При использовании ресурсов модуля программисту совсем не обязательно знать, как работают вызываемые подпрограммы. Достаточно знать назначение подпрограмм и их спецификации, т. е. имена и параметры. По этому принципу осуществляется работа со всеми стандартными модулями. Следовательно, если программист разрабатывает модули не только для личного пользования, ему необходимо выполнить полное описание всех доступных при подключении ресурсов.
Упражнения
Используя описанный в данном подразделе модуль Droby, решить следующую задачу. Дан массив А обыкновенных дробей. Найти сумму всех дробей и результат представить в виде несократимой дроби. Вычислить среднее арифметическое всех дробей и результат представить в виде несократимой дроби.
Используя описанный в данном подразделе модуль Droby, решить следующую задачу. Дан массив А обыкновенных дробей. Отсортировать его в порядке возрастания.
ГЛАВА 3
МЕТОДЫ ПОСТРОЕНИЯ АЛГОРИТМОВМетод последовательной детализацииВ соответствии с основами структурного программирования, метод последовательной детализации является приемом проектирования сложных алгоритмов. Суть этого метода (см. подразд. 1.6) заключается в следующем: сначала анализируется исходная задача, в ней выделяются подзадачи и строится иерархия таких подзадач (рис. 3.1). Далее составляются алгоритмы (или программы), начиная с основного алгоритма (основной программы), а затем — вспомогательные алгоритмы с последовательным углублением уровня, пока не будут получены алгоритмы (подпрограммы), состоящие из простых команд.
Вернемся к примеру 2.17, в котором приведена программа Interpretator для решения исходной символьной строки вида ’А + В =’.
Сформулируем требования к программе Interpretator, которые сделают ее более универсальной, чем вариант, рассмотренный в подразд. 2.15.
Операнды а и b могут быть многозначными целыми положительными числами в пределах Maxlnt.
Между элементами строки, а также в ее начале и конце могут быть пробелы.

^ПодзадачгГГ) (^ПодзадачаТ^ (^ПодзадачгГз

^ПодзадачаГГ^ (^ПодзадачаТ^) ^ПодзадачазР) (^Подзадача^32^Рис. 3.1. Иерархия подзадач
Должен осуществляться синтаксический контроль текста, который ограничивается простейшим вариантом: строка должна состоять только из цифр, знаков операций, знака «=» и пробелов.
Должен проводиться семантический контроль: строка должна быть построена по схеме 'а® b =’. Ошибка, если какой-то элемент отсутствует или нарушен их порядок.
Должен осуществляться контроль диапазона значений операндов и результата (значения не должны выходить за пределы Maxlnt).
Из приведенного перечня требований ясно, что программа будет непростой. Составлять ее будем, используя метод последовательной детализации. Начнем с представления в самом общем виде алгоритма как линейной последовательности этапов решения задачи.
Ввод строки.
Синтаксический контроль (определение, нет ли недопустимых символов).
Семантический контроль (определение, правильно ли построено выражение).
Выделение операндов, проверка их соответствия допустимому диапазону значений и перевод в целые числа.
Выполнение операции, проверка соответствия результата допустимому диапазону значений.
Вывод результата.
, Этапы 2...5 будем рассматривать как подзадачи первого уровня, соответственно назвав их (и будущие подпрограммы) Sintax, Semantika, Operand, Calc. Для их реализации потребуется решение и следующих подзадач: пропуск лишних пробелов (Propusk) и преобразование символьной цифры в целое число (Cifra). Кроме того, при выделении операндов потребуется распознавать операнд, превышающий максимально допустимое значение (Error). Обобщая все сказанное в схематической форме, получаем некоторую структуру подзадач, которой будет соответствовать аналогичная структура программных модулей (рис. 3.2).

Первый шаг детализации. Сначала наметим все необходимые подпрограммы, указав лишь их заголовки (спецификации). На месте подпрограмм запишем поясняющие комментарии (такой вид подпрограммы называют заглушкой). Затем напишем основную часть программы.
Program Interpretator;
Type Pozlnt = O..MaxInt;
Var Line : String;
A, В : Pozlnt;
Znak : Char;
Flag : Boolean;
Rezult : Integer;
Procedure Propusk (Stroka : String; M : Byte; Var N : Byte) ;
Begin
{Пропускает подряд стоящие пробелы в строке Stroka,
начиная с символа номер М. В переменной N получает номер первого символа, не являющегося пробелом}
End;
Function Cifra(C : Char): Boolean;
Begin
{Получает значение True, если символ С является
цифрой, и False - в противном случае}
End;
Function Sintax(Stroka : String): Boolean;
Begin
{Синтаксический контроль. Получает значение True,
если в строке нет других символов кроме цифр, знаков операций, знака ' = ' и пробелов. В противном случае - False}
End;
Function Semantika(Stroka : String): Boolean;
Begin
{Проверяет, соответствует ли структура строки
формату 'а 0 b = ' . Если соответствует, получает значение True, если нет - False}
End;
Procedure Operand(Stroka : String; Var A, В : Pozlnt;
Var Z : Char; Var Flag : Boolean);
Begin
{Выделяет операнды. Проверяет их на соответствие
допустимому диапазону значений. Переменная Flag получает значение True, если результат проверки положительный, и False — в противном случае. Преобразует операнды в целые положительные числа А, В. В переменной Z получает знак операции}
End;
Procedure Calc(A, В : Pozlnt; Znak : Char; Var Rez: Integer; Var Flag : Boolean);
Begin
{Вычисляет результат операции. Проверяет при
надлежность результата диапазону от - Maxlnt до Maxlnt. Flag — признак результата проверки. Результат операции
получается в переменной Rez}
End;
Begin {Начало основной части программы}
WriteLn(’Введите выражение: 1);
WriteLn;
Read(Line) ;
If Not Sintax(Line)
Then WriteLn(’Недопустимые символы’)
Else If Not Semantika(Line)
Then WriteLn(* Неверное выражение *)
Else Begin
Operand(Line, A, B, Znak, Flag);
If Not Flag
Then WriteLn(’Слишком большие операнды*) Else Begin
Calc(A,B,Znak,Rezult,Flag);
If Not Flag
Then WriteLn(’Большой результат') Else WriteLn(Rezult)
End
End
End.
Второй шаг детализации — составление подпрограмм:
Procedure Propusk (Stroka : String; M : Byte; Var N : Byte) ; Begin
N := M;
While (Stroka [N] = ' ’) And (N < Length (Stroka) ) Do N := N + 1
End;
Function Cifra(C : Char): Boolean;
Begin
Cifra := (C >= ’O’) And (C <= ’9’)
End;
Function Sintax(Stroka : String): Boolean;
Var I : Byte;
Begin
Sintax := True;
For I := 1 To Length(Stroka) Do
If Not ((Stroka[I] = '') Or Cifra(Stroka[I]) Or
(Stroka[I] = ' + ') Or (Stroka[I] =Or
(Stroka[I] = '*') Or (Stroka[I] = ' = ')) Then Sintax := False End;
Function Semantika(Stroka : String): Boolean;
Var I : Byte;
Begin
Semantika := True;
Propusk(Stroka, 1,I);
If Not Cifra(Stroka[I])
Then
Begin
Semantika := False;
Exit
End;
While Cifra(Stroka[I]) Do I := I + 1;
Propusk(Stroka, I, I);
If Not((Stroka[I] = ' + ') Or (Stroka[I] = •—1)
Or (Stroka[I] = '*'))
Then
Begin
Semantika := False;
Exit
End;
I := I + 1;
Propusk(Stroka, I, I) ;
If Not Cifra(Stroka[I])
Then
Begin
Semantika := False;
Exit
End;
While Cifra(Stroka[I]) Do I := I + 1;
Propusk(Stroka, I, I) ;
If Stroka[I] о Then
Begin
Semantika := False;
Exit
End;
I := I + 1;
Propusk(Stroka, I, I);
If I < Length(Stroka)
Then
Begin
Semantika := False;
Exit
End
End;
Procedure Operand(Stroka : String; Var A, В : Pozlnt; Var Z: Char; Var Flag : Boolean);
Var P, Q : String;
I : Byte;
Code : Integer;
Function Error(S : String): Boolean;
{Функция принимает значение True, если в строке S находится число, превышающее максимальное целое, и False — в противном случае }
Const Lim = 1327 67 *;
Var I: Byte;
Begin
If Length(S) > 5 Then Error := True Else If Length(S) < 5
Then Error := False Else Error := S > Lim
End;
Begin
Flag := True;
I := 1;
Propusk(Stroka, I, I);
Q := '
While Cifra(Stroka[I]) Do Begin
Q := Q + Stroka[I];
I := I +1
End;
If Error(Q)
Then
Begin
Flag := False;
Exit
End;
Propusk(Stroka, I, I);
Z := Stroka[I];
I := I + 1;
Propusk(Stroka, I, I);
P
. —»i.
• —t
While Cifra(Stroka[I]) Do Begin
P := P + Stroka[I];
I := I + 1
End;
If Error(P)
Then
Begin
Flag := False;
Exit
End;
Val(Q, A, Code);
Val(P, B, Code)
{Стандартная процедура Val преобразует цифровую строку в соответствующее число; Code - код ошибки) End;
Procedure Calc(А, В : Pozlnt; Znak : Char;
Var Rez : Integer; Var Flag : Boolean);
Var X, Y, Z: Real;
Begin
Flag := True;
Y := A;
Z := B;
Case Znak Of
+ ' : X := Y + Z;
: X := Y — Z;
*' : X := Y * Z
End;
If Abs(X) > Maxlnt
Then
Begin
Flag := False;
Exit
End;
Rez := Round(X)
End;
Обратите внимание на то, что функция Error определена как внутренняя в процедуре Operand, так как она используется только в данной процедуре. Другим программным модулям она не требуется.
Окончательно объединив тексты подпрограмм с основной программой, получим рабочий вариант программы Interpretator. Теперь ее можно вводить в компьютер.
Отладка и тестирование программы. Никогда нельзя быть уверенным, что написанная программа сразу будет верной (хотя такое и возможно, но с усложнением задачи становится все менее вероятным). До окончательного рабочего состояния программа доводится в процессе отладки.
Ошибки в программе могут быть «языковые» и алгоритмические. Первые, как правило, помогает обнаружить компилятор с Паскаля. Это ошибки, связанные с нарушением правил языка программирования. Их также называют ошибками времени компиляции, так как обнаруживаются они именно во время компиляции. Сам компилятор в той или иной форме выдает пользователю сообщение о характере ошибки и ее месте в тексте программы. Исправив очередную ошибку, пользователь повторяет компиляцию. И так продолжается до тех пор, пока не будут ликвидированы все ошибки этого типа.
Алгоритмические ошибки могут приводить к различным последствиям. Например, могут возникать невыполнимые действия: деление на нуль, корень квадратный из отрицательного числа, выход индекса за границы строки и др. Это ошибки времени исполнения, и они приводят к прерыванию выполнения программы. Как правило, имеются системные программные средства, помогающие в поиске таких ошибок.
Также могу возникать ситуации, когда алгоритмические ошибки не приводят к прерыванию выполнения программы. Программа выполняется до конца, выдаются какие-то результаты, но они не верные. Для окончательной отладки алгоритма и анализа его правильности производится тестирование, т. е. выполняется тест — вариант решения задачи, для которого заранее известны результаты. Как правило, один тестовый вариант не может доказать правильность программы. Следовательно, программист должен придумать систему тестов и соответственно план тестирования для исчерпывающего испытания всей программы.
Как уже говорилось, качественная программа ни в каком варианте не должна завершиться аварийно. Тесты программы Interpretator должны продемонстрировать, что при правильном вводе исходной строки всегда будут получаться правильные результаты, а при наличии ошибок (синтаксических, семантических, выхода за допустимый диапазон значений) — соответствующие сообщения. План тестирования нашей программы может быть, например, следующим:
№ п/п Что вводим Что должно получиться
1 25 + 73 = 98
2 5274- 12315 = -7 041
3 614*25 = 15 350
4 25,5 + 31,2 = Недопустимые символы
5 5 = 6- 1 Неверное выражение
6 72 315- 256 = Слишком большие операнды
7 32000* 100 = Большой результат
Правильное прохождение всех тестов — это необходимое условие правильности программы. Заметим, однако, что данное условие не всегда является достаточным. Чем сложнее программа, тем труднее построить исчерпывающий план тестирования. Опыт показывает, что даже в «фирменных» программах в процессе эксплуатации обнаруживаются ошибки, т.е. проблема тестирования программы — очень важная и одновременно очень сложная.
Рекурсивные методыСуть рекурсивных методов — это сведение задачи к самой себе.
Как уже говорилось, в Паскале существует возможность рекурсивного определения функций и процедур, реализацующих рекурсивные алгоритмы. Однако создать рекурсивный алгоритм решения задачи часто бывает очень непросто.
Рассмотрим классическую задачу, известную в литературе под названием «Ханойская башня» (рис. 3.3).
На площадке (назовем ее А) находится пирамида, составленная из дисков уменьшающегося от основания к вершине размера. Эту пирамиду в том же виде требуется переместить на площадку В. При выполнении этой работы необходимо соблюдать следующие ограничения:
перекладывать можно только по одному диску, взятому сверху пирамиды;
класть диск можно только или на основание площадки, или на диск большего размера;
в качестве вспомогательной можно использовать площадку С.
Название «Ханойская башня» связано с легендой, согласно которой в давние времена монахи одного ханойского храма взялись переместить по этим правилам башню, состоящую из 64 дисков. Монахи все еще работают и еще долго будут работать!
О

АВС
Рис. 3.3. Задача о ханойской башне
Нетрудно решить данную задачу для двух дисков. Обозначив перемещения диска, например с площадки А на площадку В как А => В, запишем алгоритм для этого случая:
А=>С; А=^В; С => В,
т.е. всего три хода.
Алгоритм решения задачи для трех дисков будет длиннее:
А^ В; А С; В С; А В; С ^ А; С ^ В; А => В, т.е. уже семь ходов.
Определить число ходов N для к дисков можно по следующей рекуррентной формуле:
N(l)= 1; N(k) = 2xN(k - 1) + 1.
Например, N(10) = 1 023, N(20) = 104 857, а N(64) = = 18 446 744073 709 551615, т.е. столько перемещений придется сделать ханойским монахам. Попробуйте прочитать это число.
Теперь составим программу, по которой машина рассчитает алгоритм работы монахов и выведет его для любого числа дисков N. Пусть на площадке А находится N дисков, тогда алгоритм решения задачи будет следующим:
Если N = 0, то ничего не надо делать.
Если N > 0, то следует:
переместить N - 1 дисков на С через В;
переместить диск с А на В (А => В);
переместить N - 1 дисков с С на В через А.
При выполнении второго пункта алгоритма последовательно будем иметь три этапа перемещения дисков, показанные на рис. 3.4.
Описание алгоритма имеет явно рекурсивный характер. Перемещение N дисков описывается через перемещение N - 1 дисков. А где же выход из этой последовательности рекурсивных ссылок алгоритма на самого себя? Он в первом пункте алгоритма, каким бы странным не казалось его тривиальное содержание.
А теперь построим программу решения рассматриваемой задачи на Паскале. В ней имеется рекурсивная процедура Hanoi, выполнение которой заканчивается только при N = 0. При обращении к этой процедуре используются фактические имена площадок, заданные соответственно их номерами: 1, 2, 3, поэтому на выходе цепочка перемещений будет описываться следующим образом:
1 => 2 1 => 3 2 => 3 и т.д.
Программа решения задачи будет иметь следующий вид:
Program Monahi;
Var N: Byte;
Procedure Hanoi(N: Byte; А, В, C: Char);

ABC Рис. 3.4. Три этапа перемещения дисков
Begin
If N > 0 Then
Begin Hanoi(N - 1, A, С, B);
WriteLn(A,B);
Hanoi(N - 1, С, B, A)
End
End;
Begin
WriteLn(1 Укажите число дисков: *);
ReadLn(N);
Hanoi(N,' 1','2','3')
End.
Это одна из самых удивительных программ! Попробуйте воспроизвести ее на машине. Проследите, как изменяется число ходов с ростом N, для чего можете сами добавить в программу счетчик ходов и в конце вывести его значение или печатать ходы с порядковыми номерами.
Методы перебора в задачах поискаРассмотрим некоторые задачи, связанные с проблемой поиска информации. Это огромный класс задач, достаточно подробно описанный в классической литературе по программированию.
Общий смысл задач поиска сводится к следующему: из данной информации, хранящейся в памяти ЭВМ, выбрать необходимые сведения, удовлетворяющие определенным условиям (критериям).
Подобные задачи мы уже рассматривали. Например, поиск максимального числа в числовом массиве, поиск необходимой записи в файле данных и т.д. Такой поиск осуществляется перебором всех элементов структуры данных и их проверкой на соблюдение условий поиска.
Перебор, при котором просматриваются все элементы структуры и который называется полным перебором, является «лобовым» способом поиска и, очевидно, не всегда самым лучшим.
Рассмотрим пример. В одномерном массиве X заданы координаты N точек, лежащих на вещественной числовой оси. Точки пронумерованы. Их номера соответствуют последовательности в массиве X. Требуется определить номер первой точки, наиболее удаленной от начала координат.
Легко понять, что это знакомая нам задача определения номера наибольшего по модулю элемента массива X, которая решается посредством полного перебора:
Const N = 100;
Var X : Array[1..N] Of Real; I, Number : 1..N;
Begin
{-Ввод массива X}
Number := 1;
For I := 2 To N Do
If Abs(X[I]) > Abs(X[Number])
Then Number := I;
WriteLn(Number)
End.
Здесь полный перебор элементов одномерного массива производится с помощью одной циклической структуры.
А теперь при тех же исходных данных определим пару точек, расстояние между которыми наибольшее.
Применяя метод перебора, эту задачу можно решить следующим образом: перебрать все пары точек из N заданных и определить номера тех из них, расстояние между которыми наибольшее (наибольший модуль разности координат). Такой полный перебор реализуется через два вложенных цикла:
Number1 := 1;
Number2 := 2;
For I := 1 To N Do For J := 1 To N Do
If Abs(X[IJ - X[J] > Abs(X[Numberl] - X[Number2])
Then
Begin
Number1 := I;
Number2 := J End;
Однако очевидно, что такое решение задачи нерационально. Здесь каждая пара точек будет просматриваться дважды, например при 1=1, J = 2 и 1 = 2, J=l. Для случая N = 100 выполнение циклов будет повторяться 100 х 100 = 10000 раз.
Выполнение программы ускорится, если исключить повторения. Исключить также следует и совпадения значений I и J. Тогда
число повторений цикла будет равно——, т.е. при N = 100
получится 4 950 повторений.
Для исключения повторений в предыдущей программе следует изменить начало внутреннего цикла с 1 на I + 1. Тогда программа примет следующий вид:
Numberl : = 1;
Number2 := 2;
For I := 1 To N Do
For J := I + 1 To N Do
If Abs (X[I] -X[J]) > Abs (X[Numberl] -X[Number2])
Then
Begin
Numberl := I/
Number2 := J End;
Рассмотренный вариант алгоритма назовем перебором без повторений.
Примечание. Конечно, эту задачу можно было решить и другим способом, но в данном случае нас интересовал именно переборный алгоритм. Для точек, расположенных не на прямой, а на плоскости или в пространстве, поиск альтернативы переборному алгоритму становится весьма проблематичным.
В следующей задаче требуется выбрать все тройки чисел без повторений из массива X, сумма которых равна десяти.
В этом случае алгоритм будет состоять из трех вложенных циклов, имеющих переменную длину:
For I := 1 То N Do
For J := I + 1 To N Do
For К := J + 1 To N Do
If X[I] + X[J] + X[K] = 10 Then WriteLn(X[I], X[J], X[K]);
А теперь представьте, что из массива X требуется выбрать все группы чисел, сумма которых равна десяти. Количество чисел в группах может быть любым, т.е. от 1 до N. В этом случае количество вариантов перебора резко возрастает, а сам алгоритм становится нетривиальным.
Казалось бы, ну и что? Машина работает быстро! И все же посчитаем. Число различных групп из N объектов (включая пустую) составляет 2N. При N = 100 это будет 2100« Ю30. Следовательно, компьютер, работающий со скоростью миллиард операций в секунду, будет осуществлять такой перебор приблизительно 10 лет. Даже исключение перестановочных повторений не сделает такой переборный алгоритм практически осуществимым.
Путь практической разрешимости подобных задач состоит в нахождении способов исключения из перебора бесперспективных с точки зрения условия задачи вариантов. Для некоторых задач это удается сделать с помощью алгоритма, описанного далее.
Рассмотрим алгоритм перебора с возвратом на примере задачи о прохождении лабиринта (рис. 3.5).
Дан лабиринт, оказавшись внутри которого необходимо найти выход из него. Перемещаться можно только в горизонтальном и вертикальном направлениях. На рис. 3.5, я... в показаны все варианты путей выхода из центральной точки лабиринта.
При создании программы решения этой задачи встают два вопроса: как организовать данные и как построить алгоритм?

абв
Рис. 3.5. Варианты (а...в) путей прохождения лабиринта
Информацию о форме лабиринта будем хранить в квадратной матрице LAB символьного типа, размером N х N, где N — нечетное число (чтобы иметь центральную точку). На профиль лабиринта накладывается сетка таким образом, чтобы в каждой ее ячейке находилась либо стена, либо проход. Матрица отражает заполнение сетки: элементами прохода соответствуют пробел, а элементам стены, — какой-нибудь символ, например буква «М». Путь движения по лабиринту будет отмечаться символами «+». Например, рис. 3.5, б соответствует следующему заполнению матрицы LAB:
м м м м м м м м м м м
м + + + м м м + м + м м м м
м + м + м м м м м
м м + м + м м
м м + м + + м м м м
м м + м м м м м м м м
м м + + + м
м м + м м м м м
м м м м + + + + + м
м м м м м + м м
Исходные данные для анализа — профиль лабиринта (исходная матрица LAB без крестиков); требуетмый результат — все возможные траектории выхода из центральной точки лабиринта (для каждого пути выводится матрица LAB с траекторией, отмеченной крестиками).
Алгоритм перебора с возвратом также называют методом проб, и суть его состоит в следующем:
Из каждой очередной точки траектории просматриваются возможные направления движения в одной и той же последовательности. Договоримся, что просмотр будет происходить каждый раз против часовой стрелки (справа—сверху—слева—снизу); шаг производится в первую же обнаруженную свободную соседнюю клетку; клетка, в которую сделан шаг, отмечается крестиком.
Если из очередной клетки дальше пути нет (тупик), следует возврат на один шаг назад и просмотр еще не испробованных путей движения из этой точки. При возвращении назад покинутая клетка отмечается пробелом.
Если очередная клетка, в которую сделан шаг, оказалась на краю лабиринта (на выходе), на печать выводится найденный путь.
Программу будем строить методом последовательной детализации. Первый этап детализации:
Program Labirint;
Const N = 11; {размер лабиринта N x N клеток}
Type Field = Array[1..N, 1..N] Of Char;
Var LAB : Field;
Procedure GO(LAB : Field; X, Y : Integer);
Begin
{Поиск путей из центра лабиринта до края - каждый найденный путь печатается}
End;
Begin
{Ввод лабиринта}
GO(LAB, N Div 2 + 1, N Div 2+1) {Начинаем с
середины}
End.
Процедура GO пытается сделать шаг в клетку с координатами (X, Y). Если эта клетка оказывается на выходе из лабиринта, выводится на печать пройденный путь, если же нет, то делается шаг в соседнюю клетку в соответствии с установленной ранее последовательностью. Если клетка тупиковая, делается шаг назад. Из всего сказанного следует, что процедура носит рекурсивный характер.
Запишем сначала общую схему процедуры без детализации:
Procedure GO(LAB : Field; X, Y : Integer);
Begin
If {Клетка (X, Y) свободна}
Then
Begin
{Шаг на клетку (X, Y)}
If {Дошли до края лабиринта}
Then {Печатается найденный путь }
Else {Попытка сделать шаг в соседние клетки в условленной последовательности} {Возвращение на один шаг назад}
End
End;
Для вывода найденных траекторий движения составляется процедура PRINTLAB.
В окончательном виде программа будет иметь следующий вид:
Program Labiгint;
Const N = 11; {Размер лабиринта NXN клеток}
Type Field = Array[1..N, 1..N] Of Char;
Var LAB : Field; X, Y : Integer;
Procedure PRINTLAB(LAB : Field);
{Печать найденного пути в лабиринте}
Var X, Y : Integer;
Begin
For X := 1 To N Do Begin
For Y := 1 To N Do
Write(LAB[X, Y]);
WriteLn
End;
WriteLn End; {Печати}
Procedure GO(LAB : Field; X, Y : Integer);
Begin
If LAB[X, Y] = '• {Если клетка свободна}
Then
Begin
LAB[X, Y] := ' + '; {Делается шаг}
If (X = 1) Or (X = N) Or (Y = 1) Or (Y = N) {Край} Then
PRINTLAB(LAB){Печатается найденный путь}
Else
Begin {Поиск следующего шага}
GO (LAB, X + 1, Y) ;
GO(LAB, X, Y + 1);
GO(LAB, X - 1, Y) ;
GO(LAB, X, Y - 1)
End;
LAB[X, Y] := '' {Возвращение назад}
End
End; {Процедуры GO}
Begin {Основной программы}
{Ввод лабиринта}
For X := 1 То N Do Begin
For Y := 1 To N Do
Read(LAB[X, Y]);
ReadLn
End;
GO (LAB, N Div 2 + 1, N Div 2 + 1) {Начинаем с середины} End.
Это еще один пример красивой программы с использованием рекурсивного определения процедуры.
Схема алгоритма данной программы типична для метода перебора с возвратом. По аналогичным алгоритмам решаются, например, популярные задачи об обходе шахматной доски фигурами или о расстановке фигур на доске таким образом, чтобы они «не били» друг друга, а также множество задач оптимального выбора (задачи о коммивояжере, об оптимальном строительстве дорог и т.д.)
Примечание. Из-за использования массива LAB в качестве пара- метра-значения в процедуре GO могут возникнуть проблемы с памятью при исполнении программы на ЭВМ. В этом случае следует перейти к глобальной передаче массива.
Методы сортировки данных и сложность алгоритмовСложность алгоритмов. Сначала обсудим проблему оценки сложности алгоритма. Традиционно принято оценивать степень сложности алгоритма по объему используемых им основных ресурсов компьютера: процессорного времени и оперативной памяти. В связи с этим вводятся понятия временной и объемной сложности алгоритма.
Временная сложность становится особенно важна для задач, предусматривающих интерактивный режим работы программы, или для задач управления в режиме реального времени. Часто программисту, составляющему программу управления каким-нибудь техническим устройством, приходится искать компромисс между точностью вычислений и временем работы программы. Как правило, повышение точности ведет к увеличению времени.
Объемная сложность программы становится критической, когда объем обрабатываемых данных оказывается на пределе объема оперативной памяти ЭВМ. Для современных компьютеров острота этой проблемы снижается благодаря росту объема их ОЗУ и эффективному использованию многоуровневой системы запоминающих устройств. При этом программе становится доступной очень большая, практически неограниченная область памяти (виртуальная память), и недостаток основной памяти приводит лишь к некоторому замедлению работы из-за выполнения обменов с диском. Существуют приемы, позволяющие минимизировать потери времени при таком обмене: использование кэш-памяти и аппаратного просмотра команд программы вперед, что позволяет заблаговременно переносить с диска в основную память необходимые значения. Из сказанного можно заключить, что минимизация емкостной сложности не является первоочередной задачей, поэтому далее мы будем интересоваться в основном временной сложностью алгоритмов.
Время выполнения программы пропорционально числу исполняемых операций. Разумеется, в единицах времени (с) оно также зависит и от скорости работы процессора. Для того чтобы показатель временной сложности алгоритма был инвариантен техническим характеристикам компьютера, его измеряют в относительных единицах. Обычно временная сложность оценивается числом выполняемых операций.
Как правило, временная сложность алгоритма зависит от исходных данных, причем как от величин, так и от их объема. Если обозначить значение параметра временной сложности алгоритма а символом Та, а некоторый числовой параметр, характеризующий исходные данные, буквой V, временную сложность можно представить как функцию T0(V). Выбор параметра V зависит от типа решаемой задачи или вида используемого для решения алгоритма.
Пример 3.1. Требуется оценить временную сложность алгоритма вычисления факториала целого положительного числа.
Программа решения:
Function Factorial(х : Integer) : Integer;
Var m, i : Integer;
Begin m := 1;
For i :=2ToxDom := m * i;
Factorial := m
End;
Подсчитаем общее число операций, выполняемых программой при данном значении х. Один раз выполняется оператор m := 1; тело цикла (в котором две операции: умножение и присваивание) выполняется (х - 1) раз; один раз выполняется присваивание Factorial := m. Если каждую из операций принять за единицу сложности, временная сложность всего алгоритма будет иметь вид 1 + 2(х - 1) + 1 = 2х, откуда понятно, что в качестве параметра V следует принять значение х. Функция временной сложности получится следующей:
T«(V) = 2V.
В этом случае можно сказать, что временная сложность линейно зависит от параметра данных — значения аргумента функции Factorial.
Пример 3.2. Требуется вычислить скалярное произведение двух векторов: А = (а,, а2, ..., ак), В = (Ь,, Ь2, ..., Ьк).
Программа решения:
АВ := 0;
For i := 1 То к Do АВ := АВ + A[i] * В[i);
В этой задаче объем входных данных п = 2к. Число выполняемых операций 1 + Зк = 1 + 3(п/2). Здесь можно принять V = к = п/2. Сложность алгоритма не зависит от значений элементов векторов А и В. Как и в примере 3.1, здесь можно говорить о линейной зависимости временной сложности от параметра данных.
С параметром временной сложности алгоритма обычно связывают две теоретические проблемы. Первая проблема состоит в поиске ответа на следующий вопрос: до какого предела значения временной сложности можно дойти, совершенствуя алгоритм решения задачи? Этот предел зависит от самой задачи и, следовательно, является ее собственной характеристикой.
Вторая проблема связана с классификацией алгоритмов по временной сложности. Функция T„(V) обычно растет с ростом V. Как быстро она растет? Существуют алгоритмы с линейной зависимостью Т„ от V (как в рассмотренных примерах), с квадратичной зависимостью и зависимостью более высоких степеней, которые называются полиномиальными. Существуют также алгоритмы, сложность которых растет быстрее любого полинома. Проблема, которую часто решают исследователи алгоритмов, заключается в следующем вопросе: возможен ли для таких задач полиномиальный алгоритм?
Постановка задачи сортировки данных. Существует традиционное деление алгоритмов на две категории: численные и нечисленные. Численные алгоритмы предназначены для математических расчетов: вычисления по формулам, решения уравнений, статистической обработки данных и т. п. В таких алгоритмах основным типом обрабатываемых данных являются числа. Нечисленные алгоритмы имеют дело с самыми разнообразными типами данных: символьными, графическими, мультимедийной информацией. К этой категории относятся многие алгоритмы системного программирования (трансляторы, операционные системы), систем управления базами данных, сетевого программного обеспечения и др.
Для программных продуктов второй категории наиболее часто используются алгоритмы сортировки данных, т.е. упорядочения информации по некоторому признаку. От эффективности этих алгоритмов, и прежде всего от скорости их выполнения, во многом зависит эффективность работы всей программы.
Различают алгоритмы внутренней сортировки — сортировки во внутренней памяти — и алгоритмы внешней сортировки — сортировки файлов. Далее будем рассматривать только внутреннюю сортировку.
Как правило, сортируемые данные располагаются в массивах. В простейшем случае — это числовые массивы. Однако для нечисленных алгоритмов более характерна сортировка массива. Поле, по значению которого производится сортировка, называется ключом сортировки и обычно имеет числовой тип. Например, массив сортируемых записей содержит два поля: наименование товара и количество товара на складе. В программе на Паскале его описание имеет следующий вид:
Const п = 1000;
Type Tovar = Record
Name : String;
Key : Integer end;
Var A : Array[l..n] Of Tovar;
Сортировка данных производится либо по возрастанию, либо по убыванию значения ключа A[i].key.
Далее во всех примерах программ предполагается, что приведенные ранее описания в программе присутствуют глобально и их область действия распространяется на процедуры сортировки.
Алгоритм сортировки методом «пузырька» рассматривался в подразд. 2.16. Теперь обсудим сортировку простым включением и быструю сортировку.
Алгоритм сортировки простым включением. Предположим, что на некотором этапе работы алгоритма левая часть массива с 1-го по (i - 1)-й элемент отсортирована, а правая его часть с i-ro по п-й элемент остается неотсортированной. Очередной шаг алгоритма заключается в расширении левой части массива на один элемент и соответственно сокращении правой части. Для этого берется первый элемент правой части (с индексом i) и вставляется на подходящее место в левую часть таким образом, чтобы ее упорядоченность сохранилась. Процесс начинается с левой части массива, состоящей из одного элемента А[1], а заканчивается, когда его правая часть становится пустой.
Программа сортировки простым включением следующая:
Procedure Straightlnsertion;
Var i, j : Integer; x : Tovar;
Begin For i := 2 To n Do
Begin x := A [i]; {В переменной x запоминается значение, которое необходимо поставить на свое место в левой части}
j := i — 1; {Правый край левой части}
While (x.key < A[j].key) and (j >= 1) Do Begin A[j + 1]:= A[j]; j := j - 1; {Продвиже
ние «дырки» в левой части массива справа налево до той позиции, в которую должен быть включен элемент А [ i ] }
End;
А[j + 1]:= х {Включение A[i] в «дырку» в левой
части)
End
End;
Теперь оценим сложность алгоритма сортировки простым включением. Очевидно, что временная сложность зависит как от размера сортируемого массива, так и от его исходного состояния, т. е. упорядоченности элементов. Временная сложность будет минимальной, если исходный массив уже отсортирован в требует- мом порядке значений ключа (в данном случае по возрастанию). Максимальное значение временной сложности соответствует противоположной упорядоченности исходного массива, т.е. в этом случае оно максимально, если исходный массив упорядочен по убыванию значений ключа. Обычно временная сложность алгоритмов сортировки оценивается числом пересылок элементов.
Оценим минимальную временную сложность алгоритма. Если массив уже отсортирован, тело цикла While не будет выполняться ни разу. Выполнение процедуры сведется к работе следующего цикла:
For i := 2 То n Do
Begin
x := A[i]; j := i - 1;
A[j +1]:= x
End;
Поскольку тело цикла For исполняется n - 1 раз, то число пересылок элементов массива M^n = 2(п - 1), а число сравнений ключей С™,, = п - 1.
Сложность алгоритма будет максимальной, если исходный массив упорядочен по убыванию. Тогда каждый элемент A[i] будет «прогоняться» к началу массива, т.е. устанавливаться в первую позицию. Цикл While выполнится один раз при i = 2, два раза при i = 3 и п - 1 раз при i = п. Таким образом, общее число пересылок записей
Mmax = 2(п -1) + £ (i -1) = 2(п - 1) + п(п - 1)/ 2 = I (п2 + Зп - 4).
i=2
Более приемлемой в реальной ситуации является средняя оценка сложности алгоритма. Для ее вычисления следует предположить, что все элементы исходного массива — случайные числа и их значения никак не связаны с их номерами. В этом случае результат очередной проверки условия x.key < A[j].key в цикле While также будет являться случайным.
Логично допустить, что среднее число выполнений цикла While для каждого конкретного значения i равно i/2, т. е. в среднем каждый раз приходится просматривать половину массива до тех пор, пока не найдется подходящее место для очередного элемента. Тогда формула для вычисления среднего числа пересылок (средняя оценка сложности) будет следующей:
Мср = 2(п -1) + X ± = 2(п -1) + (п - 2)(п -1)/4 = I (п2 + 9п - 10).
Максимальная и средняя оценки сложности алгоритма квадратичны (полином второй степени) по параметру п — размеру сортируемого массива.
Алгоритм быстрой сортировки. Этот алгоритм был разработан Э.Хоаром. В алгоритме быстрой сортировки используются:
разделение сортируемого массива на две части — левую и правую;
взаимное упорядочение двух частей (подмассивов) таким образом, чтобы все элементы левой части не превосходили элементов правой части;
рекурсия, при которой подмассив упорядочивается точно таким же способом, как и весь массив.
Для разделения массива на две части необходимо выбрать некоторое барьерное значение ключа. Это значение должно удовлетворять единственному условию: находиться в диапазоне значений для данного массива (т.е. между минимальным и максимальным значениями). В качестве барьерного можно выбрать значение ключа любого элемента массива, например первого, последнего или находящегося в его середине.
Далее следует сделать так, чтобы в левом подмассиве оказались все элементы с ключом, меньше барьера, а в правом — с ключом, больше «барьера». Затем, просматривая массив слева направо, надо найти позицию первого элемента с ключом, больше «барьера», а просматривая его справа налево, найти первый элемент с ключом, меньше «барьера». Поменяв эти значения местами, продолжить встречное движение до следующей пары элементов, предназначенных для обмена. Процесс необходимо продолжать пока индексы левого и правого просмотров не совпадут. Место их совпадения станет границей между двумя взаимно упорядоченными подмассивами. Далее алгоритм рекурсивно применяется к каждому из подмассивов (левому и правому). В итоге получим совокупность из п взаимно упорядоченных одноэлементных массивов, которые делить дальше невозможно. Эта совокупность образует один полностью упорядоченный массив, т.е. сортировка завершена.
Программа быстрой сортировки данных имеет следующий вид:
Procedure Quicksort;
Procedure Sort(L, R : Integer);
Var i, j, bar : Integer; w : Tovat;
Begin
i := L; j := R;
bar := A[(L+R)div2].key; {Установка барьера} Repeat
{Поиск элемента слева для обмена)
While A[i].key < bar Do i := i + 1;
{Поиск элемента справа для обмен)
While A[j].key > bar Do j := j — 1;
{Обмен элементов и смещение по массиву)
If i <= j Then Begin
w : = A[i] ; A[i] := A[ j ] ; A[j] :=w; i := i + 1; j := j - 1 End;
Until i > j;
{Сформированы взаимно упорядоченные подмассивы) {Сортировка левого подмассива}
If L < j Then Sort(L,j);
{Сортировка правого подмассива)
If i < R Then Sort(i,R);
End; {Sort}
Begin
Sort(1,n)
End; {Quicksort}
Исследование временной сложности алгоритма быстрой сортировки является очень трудоемкой задачей, поэтому здесь мы его приводить не будем. Дадим лишь окончательный результат этого анализа. Временная сложность Т как функция от п — размера массива — по порядку величины выражается следующей формулой:
T(n) = 0(nln(n)).
Здесь использовано принятое в математике обозначение О(х) — величина порядка х. Следовательно, временная сложность алгоритма быстрой сортировки есть величина порядка nln(n), что для целых положительных чисел п меньше, чем п2 (вспомним, что алгоритм сортировки простым включением имеет сложность порядка п2). И чем больше значение п, тем эта разница существеннее. Например:
п = 10,п2 = 100, nln(n) = 23,03;
п = 100, п2 = 10000, nln(n) = 460,52.
Даны декартовы координаты Сточек на плоскости. Составить программы решения следующих задач:
а)найти две самые близкие друг к другу точки;
б)найти две самые удаленные друг от друга точки;
в)найти три точки, лежащие в вершинах треугольника с наибольшим периметром;
г)найти две ближайшие точки, отрезок между которыми может служить радиусом окружности, заключающей внутри себя все остальные точки, и указать, какая из них является центральной.
Изменить программу Labirint таким образом, чтобы на печать выводился лишь кратчайший путь из центра лабиринта до края.
Составить программу, в соответствии с которой шахматный конь обойдет всю доску, побывав на каждом поле всего один раз.
Составить программу расстановки на шахматной доске восьми ферзей таким образом, чтобы они не угрожали друг другу.
ГЛАВА 4
ОБЪЕКТНО-ОРИЕНТИРОВАННОЕПРОГРАММИРОВАНИЕЧто такое объектно-ориентированное программированиеИстория ООП. Основоположниками объектного подхода в программировании считаются норвежцы Оле Джохан Дал и Кристен Нюгорт — авторы языка Симула. История Симулы началась в 1962 г. с проекта Simulation Language, предназначенного для программного моделирования метода Монте-Карло. В 1965 г. у авторов этого проекта возникла идея объединить данные с процедурами, их обрабатывающими. В язык были введены новые средства моделирования и имитации мультипроцессорной работы, а также термины «класс» и «объект». Тогда же возникла и технология наследования, т.е. создатели Симулы ввели в язык возможность использования разными классами общих свойств посредством указания названия класса в виде префикса.
Алан Кей ввел новую концепцию разработки программ, в соответствии с которой набор последовательно выполняющихся инструкций мог быть заменен на многомерную среду взаимодействия объектов, общающихся друг с другом посредством асинхронного обмена сообщениями. Эту идею он воплотил в новом языке SmallTalk, первоначально названном им Biological System и смоделированном на Бейсике, а затем реализованном на ассемблере. Термин «объектно-ориентированное программирование» впервые был применен именно по отношению к языку SmallTalk. Наиболее известна версия языка SmallTalk 80.
В 1980 г. Бьерн Страуструп дополнил язык процедурного программирования Си концепцией классов, а в 1983 г. дал этому новому продукту окончательное название Си++. С тех пор Си-н- стал наиболее популярным языком объектно-ориентированного программирования.
В дальнейшем возможности объектного программирования стали включаться и в другие языки. В ТурбоПаскале средства ООП появились с версии 5.5. Элементы ООП включены в Фор- гран, начиная с версии Фортран-90. Современными языками программирования, объединившими технологию ООП с визуальными методами программирования, являются Delphi, Visual Basic, Java.
Основные понятия ООП. Основополагающей идеей объектно- ориентированной парадигмы программирования является объединение данных и обрабатывающих их процедур в единое целое — объекты.
Объектно-ориентированное программирование— это методология программирования, которая основана на представлении программы в виде совокупности объектов, каждый из которых является реализацией определенного класса (типа данных особого вида), а классы образуют иерархию, основанную на принципах наследования. При этом объект характеризуется как совокупностью всех своих свойств и их текущих значений, так и совокупностью допустимых для данного объекта действий.
Несмотря на то что в различных литературных источниках делается акцент на те или иные особенности внедрения и применения ООП, три основных (базовых) его понятия остаются неизменными:
инкапсуляция (Encapsulation);
наследование (Inheritance);
полиморфизм (Polymorphism).
Эти понятия лежат в основе ООП.
При процедурном подходе к программированию требуется описать каждый шаг, каждое действие алгоритма для достижения конечного результата. При объектно-ориентированном подходе право решать, как отреагировать и что сделать в ответ на поступивший вызов, остается за объектом. Для этого достаточно в стандартной форме поставить перед ним задачу и получить ответ.
Объект состоит из трех частей:
имени;
состояния (переменных состояния);
методов (операций).
Можно дать обобщающее определение: объект ООП — это совокупность переменных состояния и связанных с ними методов (операций), которые определяют, как объект взаимодействует с окружающим миром.
Методы объекта — это процедуры и функции, объявление которых включено в описание объекта и которые выполняют действия. Возможность управлять состояниями объекта посредством вызова методов в итоге и определяет поведение объекта. Эту совокупность методов часто называют интерфейсом объекта.
Инкапсуляция — это механизм, который объединяет данные и методы, манипулирующие этими данными, и защищает и то и другое от внешнего вмешательства или неправильного использования. Когда методы и данные объединяются таким способом, создается объект.
Применяя инкапсуляцию, мы защищаем данные, принадлежащие объекту, от возможных ошибок, которые могут возникнуть при прямом доступе к этим данным. Кроме того, применение этого механизма очень часто помогает локализовать возможные ошибки в коде программы, что намного упрощает процесс их поиска и исправления. Можно сказать, что под инкапсуляцией подразумевается сокрытие данных, т. е. их защита. Применение инкапсуляции ведет к снижению эффективности доступа к элементам объекта, что обусловлено необходимостью вызова методов для изменения его внутренних элементов (переменных). Однако при современном уровне развития вычислительной техники эти потери в эффективности не играют существенной роли.
Наследование — это процесс, посредством которого один объект может наследовать свойства другого объекта и добавлять к ним черты, характерные только для него. В итоге создается иерархия объектных типов, где поля данных и методов «предков» автоматически являются и полями данных и методов «потомков».
Смысл и универсальность наследования заключается в том, что не надо каждый раз заново (с нуля) описывать новый объект, а можно указать «родителя» (базовый класс) и описать отличительные особенности нового класса. В результате новый объект будет обладать всеми свойствами «родительского» класса и своими собственными отличительными особенностями.
Например, можно создать базовый класс «Транспортное средство», который будет универсальным для всех средств передвижения на четырех колесах. Этот класс «знает», как движутся колеса, как они поворачивают, тормозят и т.д. Затем на основе этого класса можно создать класс «Легковой автомобиль». Поскольку новый класс унаследован от класса «Транспортное средство», то унаследованы и все основные черты этого класса, т.е. не надо в очередной раз описывать, как движутся колеса и т.д., а следует просто добавить те черты, особенности поведения, которые характерны для легковых автомобилей. В то же время можно, взяв за основу тот же класс «Транспортное средство», построить класс «Грузовые автомобили», описав их отличительные особенности, и на основании уже этого нового класса описать определенный подкласс грузовиков и т.д. Таким образом, сначала формируется простой шаблон, а затем посредством усложнений и конкретизации поэтапно создаются все более сложные шаблоны.
Полиморфизм — это свойство, которое позволяет одно и то же имя использовать для решения нескольких технически разных задач. Полиморфизм подразумевает такое определение методов в иерархии типов, при котором метод с одним именем может применяться к различным родственным объектам. В общем виде концепцией полиморфизма является идея «один интерфейс — множество методов», т.е. полиморфизм помогает снижать сложность программ, разрешая использование одного интерфейса для единого класса действий. При этом выбор конкретного действия в зависимости от ситуации возлагается на компилятор.
Например, пусть есть класс «Автомобиль», в котором описано, как должен передвигаться автомобиль, как он поворачивает, как подает сигнал и т. д. Там же описан метод «Переключение передач». Допустим, что в этом методе класса «Автомобиль» описана автоматическая коробка передач. Требуется описать класс «Спортивный автомобиль», у которого механическое (ручное) переключение скоростей. Конечно, можно было бы описать заново все методы для нового класса. Однако вместо этого можно указать, что класс «Спортивный автомобиль» унаследован от класса «Автомобиль», а следовательно, обладает всеми свойствами и методами, описанными для «родительского» класса. Единственное, что надо сделать — это переписать метод «Переключение передач» для механической коробки передач. В результате при вызове метода «Переключение передач» будет выполняться метод не родительского класса, а вновь созданного.
Механизм работы ООП в этих случаях можно описать примерно таким образом. При вызове того или иного метода класса сначала следует искать метод в самом классе. Если метод найден, он выполняется и поиск его завершается. Если же метод не найден, следует обратиться к «родительскому» классу и искать вызванный метод в нем. Если метод найден, он выполняется и поиск его также прекращается, а если не найден, поиск продолжается далее вверх по иерархическому дереву, вплоть до корня (верхнего класса) иерархии. Этот пример отражает так называемый механизм раннего связывания.
Объекты в ТурбоПаскалеОписание объектов. Инкапсуляция. Для описания объектов в ТурбоПаскале зарезервировано слово «object». Тип «Object» — это структура данных, которая содержит поля и методы. Описание объектного типа имеет следующий вид:
Туре Идентификатор типа объекта> = Object <поле>;
<поле>;
<метод>;
<метод>;
End;
Поле содержит имя и тип данных. Методы — это процедуры или функции, объявленные внутри декларации объектного типа, в том числе и особые процедуры, создающие и уничтожающие объекты (конструкторы и деструкторы). Объявление метода внутри описания объектного типа состоит только из заголовка (как в разделе Interface в модуле).
I
Пример 4.1. Опишем объект «Обыкновенная дробь» с методами «НОД числителя и знаменателя», «Сокращение» и «Натуральная степень»:
Type Natur = 1.. 32767;
Frac = Record Р : Integer; Q : Natur End;
Drob = Object A : Frac;
Procedure NOD(Var C : Natur);
Procedure Sokr;
Procedure Stepen(N : Natur; Var C : Frac); End;
Описание объектного типа собственно и выражает такое свойство, как инкапсуляция.
Проиллюстрируем далее работу с описанным объектом, реализацией его методов и обращение к указанным методам (при этом понадобятся некоторые вспомогательные методы):
Type Natur = l..MaxInt;
Frac = Record P : Integer; Q : Natur End;
{Описание объектного типа}
Drob = Object
A : Frac;
Procedure Vvod; {Ввод дроби)
Procedure NOD(Var C : Natur); {НОД} Procedure Sokr;
Procedure Stepen(N : Natur; Var C : Frac); Procedure Print; {Вывод дроби)
End;
{Описания методов объекта}
Procedure Drob.NOD;
Var M, N : Natur;
Begin M := Abs(A.P); N := A.Q;
While M о N Do If M > N
Then If M mod NO 0 Then M := M mod N Else M := N Else If N mod M о 0 Then N := N mod M Else N := M; С := M End;
Procedure Drob.Sokr;
Var N : Natur;
Begin
If A.P О 0 Then Begin
Drob.NOD(N);
A.P := A.P div N; A.Q := A.Q div N
End
Else A.Q := 1 End;
Procedure Drob.Stepen;
Var I : Natur;
Begin
C.P := 1; C.Q := 1;
For I := 1 To N Do
Begin C.P := C.P * A.P; C.Q := C.Q * A.Q End;
End;
Procedure Drob.Vvod;
Begin
Write(’Введите числитель дроби: 1); ReadLn(A.P); Write(’Введите знаменатель дроби: '); ReadLn(A.Q); End;
Procedure Drob.Print;
Begin WriteLn(A.P, ’/’, A.Q) End;
{Основная программа}
Var Z : Drob; F : Frac;
Begin
Z.Vvod; {Ввод дроби}
Z.Print; {Печать введенной дроби}
Z.Sokr; {Сокращение введенной дроби}
Z.Print; {Печать дроби после сокращения}
Z.Stepen(4, F); {Возведение введенной дроби в 4-ю степень}
WriteLn(F. Р, ’/' , F.Q)
End.
Прокомментируем отдельные моменты в рассмотренном примере.
Во-первых, реализация методов осуществляется в разделе описаний после объявления объекта, причем при реализации метода достаточно указать его заголовок без списка параметров, но с указанием объектного типа, к которому он относится. Еще раз отметим, что все это напоминает создание модуля, когда ресурсы, доступные при его подключении, прежде всего объявляются в разделе Interface, а затем реализуются в разделе Implementation. В действительности объекты и их методы реализуют чаще всего именно в виде модулей.
Во-вторых, все действия над объектом выполняются только с помощью его методов.
В-третьих, для работы с отдельным экземпляром объектного типа в разделе описания переменных должна быть объявлена переменная (или переменные) соответствующего типа. Из примера видно, что объявление статических объектов не отличается от объявления других переменных, а их использование в программе напоминает использование записей.
Наследование. Объектные типы можно выстроить в иерархию. Один объектный тип может наследовать компоненты другого объектного типа. Наследующий объект называется «потомком», а объект, которому наследуют — «предком». Если «предок» сам является чьим-либо «наследником», то «потомок» наследует и эти поля и методы. Следует подчеркнуть, что наследование относится только к типам, но не экземплярам объекта.
Описание типа «потомка» имеет отличительную особенность:
<имя типа потомка> = Object(<имя типа предка>),
Далее запись описания — обычная.
Следует помнить, что поля наследуются без какого-либо исключения, поэтому, объявляя новые поля, необходимо следить за уникальностью их имен, иначе совпадение имени нового поля с именем наследуемого поля вызовет ошибку. На методы это правило не распространяется, но об этом далее.
Пример 4.2. Опишем объектный тип «Вычислитель» с методами «Сложение», «Вычитание», «Умножение», «Деление» (моделирование некоторого исполнителя) и производный от него тип «Продвинутый вычислитель» с новыми методами «Степень», «Корень л-й степени»:
Type BaseType = Double;
Vichislitel = Object А, В, С : BaseType;
Procedure Init; {Ввод или инициализация полей} Procedure Slozh;
Procedure Vi deprocedure Umn ;
Procedure De1en
End;
NovijVichislitel = Object(Vichislitel)
N : Integer;
Procedure Stepen;
Procedure Koren
End;
Обобщая сказанное ранее, перечислим правила наследования:
информационные поля и методы «родительского» типа наследуются всеми его типами-«потомками» независимо от числа промежуточных уровней иерархии;
доступ к полям и методам «родительских» типов в рамках описания любых типов-«потомков» выполняется таким образом, как будто они описаны в самом типе-«потомке»;
ни в одном из типов-«потомков» не могут использоваться идентификаторы полей, совпадающие с идентификаторами полей какого-либо из «родительских» типов. Это правило относится и к идентификаторам формальных параметров, указанных в заголовках методов;
тип-«потомок» может доопределить произвольное число собственных методов и информационных полей;
любое изменение текста в «родительском» методе автоматически оказывает влияние на все методы типов-«потомков», которые его вызывают;
в противоположность информационным полям идентификаторы методов в типах-«потомках» могут совпадать с именами методов в «родительских» типах. При этом одноименный метод в типе-«потомке» подавляет одноименный ему «родительский», и в рамках типа-«потомка» при указании имени такого метода будет вызываться именно метод типа-«потомка», а не «родительский».
Вызов наследуемых методов осуществляется согласно следующим принципам:
при вызове метода компилятор сначала ищет метод, имя которого определено внутри типа объекта;
если в типе объекта не определен метод с указанием его в операторе вызова метода, то компилятор в поисках метода с таким именем поднимается выше к непосредственному «родительскому» типу;
если наследуемый метод найден и его адрес указан, следует помнить, что вызываемый метод будет работать так, как он определен и компилирован для «родительского» типа, а не для типа- «потомка». Если этот наследуемый «родительский» тип вызывает еще и другие методы, то вызываться уже будут только «родительские» или расположенные выше методы, так как вызов методов из расположенных ниже по иерархии типов не допускается.
Полиморфизм. Как уже отмечалось, полиморфизм (многообразие) предполагает определение класса или нескольких классов методов для родственных объектных типов таким образом, чтобы каждому классу отводилась своя функциональная роль. Методы одного класса обычно наделяются общим именем.
Пример 4.3. Пусть имеется «родительский» объектный тип «Выпуклый четырехугольник» (поля типа— «координаты вершин», заданные в порядке их обхода) и производные от него типы: «Параллелограмм», «Ромб» и «Квадрат». Описать для указанных фигур методы «Вычисление углов» (в градусах), «Вычисление диагоналей», «Вычисление длин сторон», «Вычисление периметра», «Вычисление площади».
Программа описания следующая:
Type BaseType = Double;
FourAngle = Object
xl, yl, x2, y2, x3, y3, x4, y4,
А, В/ C, D, Dl, D2,
Alpha, Beta, Gamma, Delta,
P, S : BaseType;
Procedure Init;
Procedure S t о г о n у;
Procedure Diagonali;
Procedure Angles;
Procedure Pe r ime t r;
Procedure Ploshad;
Procedure PrintElements;
End;
Parall = Object(FourAngle)
Procedure S t о г о n у;
Procedure Pe rime t r;
Procedure Ploshad;
End;
Romb = Object(Parall)
Procedure S tоrony;
Procedure Perimetr;
End;
Kvadrat = Object(Romb)
Procedure Angles;
Procedure Ploshad;
End;
Procedure FourAngle.Init;
Begin
TOC \o "1-5" \h \z Write(1 Введите координаты вершин заданного четырехугольника :1) ;
ReadLn(xl, yl, х2, у2, хЗ, уЗ, х4, у4);
End;
Procedure FourAngle.Storony;
Begin A:=Sqrt(Sqr(x2-xl)+Sqr(y2-yl));
В:=Sqrt(Sqr(x3-x2)+Sqr(y3-y2));
C:=Sqrt(Sqr(x4-x3)+Sqr(y4-y3));
D:=Sqrt(Sqr(x4-xl)+Sqr(y4-yl));
End;
Procedure FourAngle.Diagonali;
Begin
Dl := Sqrt(Sqr(xl - x3) + Sqr(yl - y3));
D2 := Sqrt(Sqr(x2 - x4) + Sqr(y2 - y4));
End;
Procedure FourAngle.Angles;
Function Ugol(Aa, Bb, Cc : BaseType): BaseType; Var VspCos, VspSin: BaseType;
Begin
VspCos := (Sqr(Aa) + Sqr(Bb) - Sqr(Cc))/ (2 * Aa * Bb);
VspSin := Sqrt(l - Sqr(VspCos));
If Abs(VspCos) > le-7
Then Ugol := (ArcTan (VspSin/VspCos) +
Pi * Ord(VspCos < 0))/Pi * 180 Else Ugol := 90 End;
Begin Alpha := Ugol(D, A, D2);
Beta := Ugol (A, B, Dl) ;
Gamma := Ugol(В, C, D2);
Delta := Ugol(C, D, Dl);
End;
Procedure FourAngle.Perimetr;
Begin P :=A+B+C+D End;
Procedure FourAngle.Ploshad;
Var Perl, Per2 : BaseType;
Begin Perl := (A + D + D2)/2; Per2 := (В + C + Dl)/2;S := Sqrt(Perl*(Perl - A) * (Perl - D) *
(Perl - D2)) + Sqrt(Per2 * (Per2 - B) *
(Per2 - C) * (Per2 - Dl))
End;
Procedure FourAngle.PrintElements;
Begin
WriteLn('Стороны:A:10:6, B:10:6, C:10:6, D:10:6,
'Углы: ', Alpha:10:4, Beta:10:4, Gamma:10:4, Delta:10: 4, 'Периметр: ', P:10:6, 'Площадь: ', S:10:6, 'Диагонали: ', Dl:10:6, D2: 10: 6)
End;
Procedure Parall.Storony;
Begin A := Sqrt(Sqr(x2 - xl) + Sqr(y2 - yl));
В := Sqrt(Sqr(x3 - x2) + Sqr(y3 - y2));
C := A; D: = В
End;
Procedure Parall.Perimetr;
Begin P := 2 * (A + B) End;
Procedure Parall.Ploshad;
Var Per : BaseType;
Begin
Per := (A + D + D2)/2;
S := 2 * Sqrt (Per * (Per - A) * (Per — D) * (Per - D2) ) End;
Procedure Romb.Storony;
Begin
A := Sqrt(Sqr(x2 - xl) + Sqr(y2 - yl));
В := A; C := A; D := A End;
Procedure Romb.Perimetr;
Begin P := 2 * A End;
Procedure Kvadrat.Angles;
Begin Alpha := 90; Beta := 90; Gamma := 90;
Delta := 90;
End;
Procedure Kvadrat.Ploshad;
Begin S := Sqr(A) End;
{Основная программа}
Var obj : Kvadrat;
Begin
obj.Init; obj.Storony; obj.Diagonali; obj.Angles; obj.Perimetr; obj.Ploshad; obj.PrintElements End.
Таким образом, вычисление соответствующего элемента в фигуре, если это действие по сравнению с другими является уникальным, производится обращением к своему методу.
Упражнения
Описать следующие объекты с указанием их методов:
а)«Телефонный звонок» — номер телефона, дата разговора, продолжительность, код города и т.д.;
б)«Поездка» — номер поезда, пункт назначения, дни следования, время прибытия, время стоянки и т.д.;
в)«Кинотеатр» — название кинофильма, сеанс, стоимость билета, количество зрителей и т.д..
Реализовать объявленные в объектном типе методы.
Дополнить объект Drob из примера 4.1 методами «Положительная дробь» (функция логического типа), «Правильная дробь» (функция логического типа), «Конечная десятичная дробь» (функция логического типа), «Период дроби» (существует, если соответствующая десятичная дробь не является конечной, в общем случае результат — «длинное» число). Реализовать и протестировать эти методы.
Описать объекты-«потомки» для объектов, указанных в первом упражнении. Реализовать объявленные в объектном типе методы.
Реализовать методы объекта «Вычислитель» из примера 4.2.
Дополнить набор объектов из примера 4.3 объектом «Прямоугольник», а также другими выпуклыми четырехугольниками, не являющимися параллелограммами (трапеция и т.д.), и реализовать соответствующие им методы.
Построить, последовательно применяя методы «Отобразить», «Сдвинуть», «Изменить размеры», «Спрятать», иерархии следующих объектов:
а)координаты — точка — горизонтальная линия — горизонтальновертикальное перекрестье;
б)координаты — точка — наклонная под углом 45° линия — наклонное перекрестье;
в)координаты — точка — окружность — дуга (процедура Arc);
г)координаты — точка — эллипс (процедура FillEllipse) — эллиптическая дуга (процедура Ellipse);
д)координаты — точка — окружность — сектор (процедура PieSlice);
е)координаты — точка — сектор (процедура PieSlice) — эллиптическая дуга (процедура Ellipse);
ж)координаты — точка — прямоугольник (процедура Rectangle) — трехмерная полоса (процедура Bar3D);
з)координаты — точка — заштрихованный эллипс (процедура FillEllipse) — заштрихованный сектор (процедура Sector);
и)координаты — точка — окружность — заштрихованный сектор (процедура Sector);
к)координаты — точка — окружность — эллиптическая дуга (процедура Ellipse).
Интегрированная среда программирования DelphiИстория и назначение Delphi. Delphi — интегрированная среда программирования, разработанная фирмой Borland, является результатом развития языка ТурбоПаскаль, который, в свою очередь, является результатом развития языка Паскаль. Изначально Паскаль был полностью процедурным языком. ТурбоПаскаль, начиная с версии 5.5, обладает средствами объектно-ориентированного программирования. Языком программирования в Delphi является объектно-ориентированный язык Object Pascal, в основу которого положены конструкции ТурбоПаскаля версии 7.0. В России Borland Delphi появился в конце 1993 г. и сразу же завоевал широкую популярность.
Среда программирования Delphi позволяет сравнительно легко и быстро создавать приложения операционной системы Windows, поэтому она получила название RAD (Rapid Application Development — среда быстрой разработки приложений).
Процесс разработки в Delphi предельно упрощен. И в первую очередь это относится к созданию интерфейса, на которое обычно приходится порядка 80 % времени разработки программы. Программисту необходимо просто поместить необходимые компоненты в окне Windows (в Delphi оно называется формой) и настроить их свойства с помощью специального инструмента — Object Inspector. С помощью данного инструмента можно связать события этих компонентов (нажатие кнопки, выбор мышью элемента в списке ит.д.) с процедурой обработки, и простое приложение готово. Причем разработчик имеет в своем распоряжении необходимые средства отладки (вплоть до пошагового выполнения команд процессора), удобную контекстную справочную систему, средства коллективной работы над проектом и т.д.
Delphi позволяет создавать распределенные Internet- и Intranet- приложения, используя для доступа к данным Borland DataBase Engine.
Язык Delphi Pascal (ранее — Object Pascal), используемый в Delphi, постоянно расширяется и дополняется компанией Borland, в полной мере поддерживая все требования, предъявляемые к объектно-ориентированному языку программирования. Как в строго типизированном языке, классы поддерживают только простое наследование, но зато интерфейсы могут иметь сразу несколько «предков». К числу особенностей языка следует отнести поддержку обработки исключительных ситуаций (exceptions), а также перегрузку методов и подпрограмм (overload). Имеются также открытые массивы, варианты и вариантные массивы, позволяющие размещать в памяти любые структуры данных.
В Delphi можно создавать свои собственные компоненты, импортировать их, а также разрабатывать шаблоны проектов и мастеров, создающих заготовки проектов. Delphi предоставляет разработчику интерфейс для связи приложений (или внешних программ) с интегрированной оболочкой Delphi (IDE).
Интерфейс. Вид среды программирования Delphi отличается от вида многих других сред, которые можно увидеть в Windows, так как она следует спецификации, называемой SDI (Single Document Interface — однодокументный интерфейс), и состоит из нескольких отдельно расположенных окон.
На рис. 4.1 показан вид среды программирования Delphi непосредственно после запуска программы. В верхней строке, как и в любом приложении Windows, находится меню. Слева расположены дерево компонентов формы и инспектор компонентов, отображающий их свойства и события, по центру — собственно фор-
шч
Ъф'в g а» |фф[1S^^lQ^AocaMtO^iCwfc*» •Сн..1||П^»»| ЮС Jill
1r7i;lT or % аргй^> .ai^-fia I
МеНЮ — f-н» в* ш» *«т<&****, оылш Totfc н»а<н*>» ***ж иц> |}f<Hwlp‘
Панель кнопок
1
Палитра компонентов
I
Компоненты
формы
Свойства
компонента
События
компонента
Форма
Рис. 4.2. Элементы интерфейса Delphi
Редактор кода

Сохранить рабочий файл
Открыть файл
Создать файл
рабочий модульыбрать рабочую форму
Г
включиться между формойюдулем
Создать новую форму
Добавить файл в проект
Удалить файл из проекта
.^Открыть справочник
Пройти подпрограмму
Зайти в подпрограммуОстановить программу
Создать проект и запустить программу


Рис. 4.3. Назначение кнопок панели инструментов
>зади формы — редактор кода. Ниже строки меню распола- панель инструментов и палитра компонентов, ге детально элементы интерфейса Delphi показаны на 1, а назначение некоторых кнопок панели инструментов етрис. 4.3.
ма. Имеет все признаки главного окна традиционных прило- Windows: размерную рамку, значок, заголовок, кнопки [Свер- Развернуть], [Закрыть] (рис. 4.4) и управляется мышью.
Заголовок
Кнопка
[Свернуть]
Кнопка
[Закрыть]
Кнопка [Развернуть]
Form!
udifxi
Размерная
рамка
Рис. 4.4. Элементы формы
Окно проектировщика форм (Form Designer) представляет собой заготовку, т.е. макет одного из окон разрабатываемого приложения. Форма является основным интерфейсным элементом в Delphi. Это визуальный компонент, присущий любой создаваемой в этой среде программе и исполняющий роль контейнера, который содержит другие компоненты, определяющие функциональность приложения.
Проектировщик форм позволяет во время разработки приложения выполнять следующие действия:
добавлять компоненты в форму;
модифицировать форму и ее компоненты;
связывать обработчики событий компонента с программой на Delphi Pascal, содержащейся в редакторе кода.
В общих чертах процесс разработки программы на Delphi можно представить следующим образом: из области Палитра компонентов с помощью мыши надо выбрать компонент (кнопку, надпись, редактор текста и т.д.), поместить его в форму и задать значения свойств в области Свойства. Среда Delphi проанализирует содержимое формы и создаст соответствующий программный код, а программисту останется только внести в него детали решения задачи — отклики на события.
Компоненты Delphi. Свойства компонентовКомпонент Delphi — это функциональный элемент, обладающий набором свойств, определяющих его внешний вид и состояние, а также набором методов и событий, определяющих его поведение. Концепция использования компонентов при разработке программ напрямую связана с методологией объектно-ориентированного программирования. В данном случае с помощью компонентов происходит визуализация объектов, т.е. отображаются стандартные диалоговые окна, кнопки, списки и др. При этом каждый компонент предполагает собственный набор действий.
Все компоненты Delphi являются производными от класса TComponent, в котором инкапсулированы самые общие свойства и методы компонентов.
Идентификатор компонента строится по тем же правилам, что и идентификаторы других объектов Delphi, а также переменных, констант и т.д. По умолчанию имя компонента задается средой программирования, однако возможно и его переименование на усмотрение программиста.
Все компоненты сгруппированы по некоторым признакам, а весь набор компонентов образует палитру компонентов. Каждой группе компонентов соответствует вкладка на палитре компонентов.
Для помещения компонента в форму необходимо выполнить следующие действия:
перейти к требуемой вкладке на палитре компонентов;
выбрать необходимый компонент;
отметить в форме место, где должен находиться компонент (при этом он туда помещается);
придать компоненту требуемые размеры, растягивая по высоте и ширине, и скорректировать его местоположение.
Основные компоненты интегрированной среды разработки. Набор и порядок компонентов на каждой вкладке могут настраиваться по желанию программиста с помощью контекстного меню.
Опишем некоторые компоненты вкладки Standard типовой комплектации. показанной на рис. 4.5.
1ПВ Frames — позволяет формировать на форме фреймы.
Щ TMainMenu — позволяет поместить главное меню в разрабатываемую программу. Создание меню включает в себя три шага:
помещение TMainMenu на форму;
вызов Дизайнера меню через свойство Items в Инспекторе объектов;
определение пунктов меню в Дизайнере меню.
TPopupMenu — позволяет создавать контекстные меню. У всех
видимых объектов имеется свойство PopupMenu, где и указывается требуемое меню. Создается аналогично главному меню.
Щ TLabel -
служит для отображения текста на экране.
031
TEdit — стандартный управляющий элемент Windows для
ввода. Может использоваться для отображения короткого фрагмента текста и позволяет пользователю вводить текст во время выполнения программы.
|ш| ТМето — другая форма TEdit. Подразумевает работу с большими текстами. Может переносить слова, сохранять в ClipBoard фрагменты текста и восстанавливать их, выполнять другие основные функции редактора. Имеет ограничения на объем текста — 32 Кбайт.
TButton — позволяет выполнить какие-либо действия при
нажатии кнопки во время выполнения программы.
Рис. 4.5. Вкладка Standard
TCheckBox — отображает строку текста и небольшое рядом
стоящее окошко, в котором можно поставить отметку, означающую, что что-то выбрано (объект выбора описывается указанной строкой текста).
TRadioButton — позволяет выбрать только одну опцию из нескольких.
TListBox — требуется для показа прокручиваемого списка.
ТСошЬоВох — аналогичен TListBox и кроме того позволяет
водить информацию в поле ввода поверх TListBox. Имеется несколько типов ТСошЬоВох, но наиболее популярен спадающий вниз.
TScrollbar— полоса прокрутки, появляющаяся автоматически в объектах редактирования при необходимости прокрутки текста для просмотра.
Вкладка Additional, показанная на рис. 4.6, содержит дополнительные компоненты создания пользовательского интерфейса. Приведем описание некоторых из них.
TBitBtn
кнопка, аналогичная TButton, однако на ней
можно разместить картинку (glyph). Имеет несколько предопределенных типов (bkClose, bkOK. и др.), при выборе которых принимает соответствующий вид.
TTabSet— горизонтальные закладки, обычно используемые вместе с TNoteBook для создания многостраничных окон.
|^| TNoteBook — используется совместно с TTabSet для создания многостраничного диалога, причем на каждой странице располагается свой набор объектов.
| TOutline — используется для представления иерархических отношений связанных данных (например, дерева директорий).
a awчла *тт т 4- ут * еядр g 9 оятан
Рис. 4.6. Вкладка AdditionalРис. 4.7. Вкладка System
Вкладка System, показанная на рис. 4.7, представляет собой набор компонентов для доступа к некоторым системным сервисам типа таймера, DDE, OLE и т.п.
Свойства компонентов и управление через свойства. Как уже отмечалось, свойства компонента определяют его вид и значения переменных его состояния. Очевидно, что перечень свойств многих компонентов, с одной стороны, повторяется, а с другой стороны, каждый компонент обладает собственным уникальным набором свойств.
Опишем свойства некоторых стандартных компонентов.
Компонент Форма (объект типа TForm) является основой программы. Свойства формы определяют вид окна программы (табл. 4.1).
Компонент Label предназначен для вывода текста на поверхность формы (табл. 4.2).
Компонент Edit представляет собой поле ввода-редактирования строки символов (табл. 4.3).
Компонент Button представляет собой командную кнопку (табл. 4.4).
Таблица 4.1
Свойства формы
Свойство Описание
Name Имя формы. Используется в программе для управления формой и для доступа к ее компонентам
Caption Текст заголовка
Top Расстояние от верхней границы формы до верхней границы экрана
Left Расстояние от левой границы формы долевой границы экрана
Width Ширина формы
Height Высота формы
ClientWidth,
ClientHeight Соответственно ширина и высота рабочей (клиентской) области формы, т.е. без учета ширины левой и правой границ
BorderStyle Вид границы, которая может быть обычной (bsSizeable), тонкой (bsSingle) или отсутствовать (bsNone). Если у окна обычная граница, то во время работы программы пользователь может с помощью мыши изменить его размер. Изменить размер окна с тонкой границей нельзя. Если граница отсутствует, то на экран будет выведено окно без заголовка, положение и размер которого во время работы программы изменить нельзя
Свойство Описание
Borderlcons Кнопки управления окном. Значение свойства определяет, какие кнопки управления окном будут доступны пользователю во время работы программы. Значение свойства задается посредством присвоения значений уточняющим свойствам: biSystemMenu, biMinimize, biMaximize и biHelp. Свойство biSysteinMenu определяет доступность кнопки [Свернуть] и кнопки системного меню, biMinimize — доступность кнопки [Свернуть], biMaximize — доступность кнопки [Развернуть], biHelp —доступностькнопки вывода справочной информации
Icon Значок в заголовке диалогового окна, обозначающий кнопку вывода системного меню
Color Цвет фона, который можно задать, указав его название или привязку к текущей цветовой схеме операционной системы. В последнем случае цвет определяется текущей цветовой схемой, выбранным компонентом привязки и изменяется при изменении цветовой схемы операционной системы
Font Шрифт, используемый по умолчанию компонентами, находящимися на поверхности формы
Canvas Поверхность, на которую можно вывести графику
Таблица 4.2
Свойства текста
Свойство Описание
Name Имя компонента. Используется в программе для доступа к компоненту и его свойствам
Caption Отображаемый текст i
Left Расстояние от левой границы поля вывода до левой границы формы
Top Расстояние от верхней границы поля вывода до верхней границы формы
Height Высота поля вывода
Width Ширина поля вывода
AutoSize Признак того, что размер поля определяется его содержимым
Wordwrap Признак того, что слова, которые не помещаются в текущей строке, автоматически переносятся на следующую строку (значение свойства AutoSize должно быть False)
Свойство Описание
Alignment Задает способ выравнивания текста внутри поля: по левому краю (taLeftJustify), по центру (taCenter) или по правому краю (ta RightJustify)
Font Шрифт, используемый для отображения текста. Уточняющие свойства определяют способ начертания символов (Font.Name), их размер (Font.Size) и цвет (Font.Color)
ParentFont Признак наследования компонентом характеристик шрифта формы, на которой он находится. Если значение свойства равно True, то текст выводится шрифтом, установленным для формы
Color Цвет фона области вывода текста
Transparent Управляет отображением фона области вывода текста. Значение True делает область вывода текста прозрачной (область вывода не закрашивается цветом, заданным свойством Color)
Visible Позволяет скрыть текст (False) или сделать его видимым (True)
Компонент Memo представляет собой элемент редактирования текста, который может состоять из нескольких строк (табл. 4.5).
Forml TForml jjJ
j PTopefties||Events|
Action A
AcbveControl Align alNone
AlphaBletvi Fake
AlphaB tendYalt .255
Щ Anchor* [akLefUfcTcp]
AytoScwl True Г"
AuloSize false
м BiDiMode bdLeftToRigh»
^Bofcteflcons (biSystorfWwu.
BordeiStyte bsSizeabte
SoTtJwWtAh 1 o’
; Caption ВЯТмУ!
ClentH eight [453
CSentWidth ] 1688
Color * PdNnFace
SOonetiamts < i(T SceConstf-ainl
сизо ' iTriie
Cursor jciDefauft *1
At shown -A
Рис. 4.8. Окно инспектораобъектов
Компонент RadioButton представляет собой зависимую кнопку (табл. 4.6), состояние которой определяется состоянием других кнопок группы. Если в диалоговом окне надо организовать несколько групп переключателей, то каждую группу следует представить компонентом RadioGroup.
Компонент CheckBox представляет собой независимую кнопку — переключатель (табл. 4.7).
Компонент ListBox представляет собой список, в котором можно выбрать необходимый элемент (табл. 4.8)
Компонент ComboBox дает возможность ввести данные в поле редактирования посредством набора на клавиатуре или выбора из списка (табл. 4.9).
Свойство Описание
Name Имя компонента. Используется в программе для доступа к компоненту и его свойствам
Text Текст, находящийся в поле ввода и редактирования
Left Расстояние от левой границы компонента до левой границы формы
Top Расстояние от верхней границы компонента до верхней границы формы
Height Высота поля
Width Ширина поля
Font Шрифт, используемый для отображения вводимого текста
ParentFont Признак наследования компонентом характеристик шрифта формы, на которой он находится. Если значение свойства равно True, то при изменении свойства Font формы автоматически изменяется значение свойства Font компонента
Enabled Используется для ограничения возможности изменить текст в поле редактирования. Если значение свойства равно False, то текст в поле редактирования изменить нельзя
Visible Позволяет скрыть компонент (False) или сделать его видимым (True)
Компонент BitBtn так же, как и компонент Button, является командной кнопкой. Однако он более универсален и главное может содержать картинку (табл. 4.10).
Компонент ScrollBar — полоса прокрутки, предназначенная для прокрутки содержимого окна и выбора значений из определенного интервала (табл. 4.11)
Свойства компонентов можно изменять на вкладке Properties в Object Inspector. На рис. 4.8 представлено изменение свойств компонента Form.
Демонстрация настройки свойств компонентов будет приведена далее в интегрированном примере.
События компонентов и определение процедур на основе событий. Как уже говорилось, события определяют поведение компонента во время работы программы. Предполагается, что реакцией на действия пользователя будет исполнение того или иного программного кода. Следовательно, при составлении сценария программы необходимо учесть все предполагаемые дей-
:твия пользователя и предусмотреть для каждого случая адек- (атную реакцию.
События компонента можно программировать на вкладке Events (Object Inspector. На рис. 4.9 представлено изменение реакции на юбытия для компонента Form.
Двойной щелчок левой кнопкой мыши инициирует редакти- ювание кода для соответствующего события. При этом шаблон метода создается автоматически.
Кроме собственно выполнения некоторого действия при обра- ютке события могут быть получены какие-то результаты, кото- >ые могут передаваться для дальнейшего использования любому >бъекту (компоненту) программы.
Программа на Delphi. Любая программа в среде Delphi состоит о файла проекта (файл с расширением .dpr) и одного или не- жольких модулей. Каждый из таких файлов составляет програм- лную единицу Delphi.
Таблица 4.4
Свойства командной кнопки
Свойство Описание
Name Имя компонента. Используется в программе для доступа к компоненту и его свойствам
Caption Текст на кнопке
Left Расстояние от левой границы кнопки до левой границы формы
Top Расстояние от верхней границы кнопки до верхней границы формы
Height Высота кнопки
Width Ширина кнопки
Enabled Признак доступности кнопки. Если значение свойства равно True, то кнопка доступна. Если значение свойства равно False, то кнопка не доступна, например в результате щелчка мышью на кнопке событие Click не возникает
Visible Позволяет скрыть кнопку (False) или сделатьее видимой (True)
Hint Всплывающая подсказка-текст, который появляется рядом с указателем мыши при позиционировании указателя на командной кнопке (чтобы текст появился, значение свойства ShowHint должно быть True)
ShowHint Разрешает (True) или запрещает (False) отображение подсказки при позиционировании указателя на кнопке
Name
Text
Lines
Lines. Count
Left
Top
Height
Width
Font
ParentFont
Свойство
Name
Caption
Checked
Left
Top
Height
Width
Font
ParentFont

Таблица 4.7
Свойства переключателя
ОСвойство Описание
Name Имя компонента. Используется для доступа к свойствам компонента
Caption Текст, который находится справа от флажка
Checked Состояние, вид флажка: если флажок установлен, то Checked = True; если флажок сброшен, то Checked = False
State Состояние флажка. В отличие от свойства Checked, позволяет различать установленное, сброшенное и промежуточное состояния. Состояние флажка определяет одна из констант: cbChecked (установлен); cbGrayed (серый, неопределенное состояние); cbUnChecked (сброшен)
AllowGrayed Определяет, может ли флажок быть в промежуточном состоянии: если AllowGrayed = False, то флажок может быть только установленным или сброшенным; если AllowGrayed = True, то допустимо промежуточное состояние
Left Расстояние от левой границы флажка до левой границы формы
Top Расстояние от верхней границы флажка до верхней границы формы
Height Высота поля вывода поясняющего текста
Width Ширина поля вывода поясняющего текста
Font Шрифт, используемый для отображения поясняющего текста
ParentFont Признак наследования характеристик шрифта «родительской» формы
Файл проекта для каждой программы имеет примерно одинаковый вид. Например:
Program Projectl;
Uses Forms, Unitl In 'Unitl.pas' {Forml};
{$R *.res}
Begin
Application.Initialize;
Application.CreateForm(TForml, Forml); Application.Run;
End.
Свойство Описание
Name Имя компонента. В программе используется для доступа к компоненту и его свойствам
Items Элементы списка — массив строк
Count Количество элементов списка
Sorted Признак необходимости автоматической сортировки (True) списка после добавления очередного элемента
Itemlndex Номер выбранного элемента (элементы списка нумеруются с нуля). Если в списке ни один из элементов не выбран, то значение свойства равно -1
Left Расстояние от левой границы списка до левой границы формы
Top Расстояние от верхней границы списка до верхней границы формы
Height Высота поля списка
width Ширина поля списка
Font Шрифт, используемый для отображения элементов списка
ParentFont Признак наследования свойств шрифта «родительской» формы
вУйЭГ ф-
; ер Fobbed I Т* FonCtoe ,
СЗ Vawbbt/Qratart»
ffl£3 Utm
procetare ТГoral.rornContextPopup(Sender: TOtoJect; BousePoe: j Ttr Handled! Boolean); lufU
.! end;
J
Ж
Рис. 4.9. Окно программного модуля для обработки события

В объекте Application собраны данные и подпрограммы, необходимые для нормального функционирования Windows-программы в целом. Delphi автоматически создает объект-программу Application для каждого нового проекта.
Содержание и функциональное назначение методов, вызываемых в программе, соответствует их названию. Так, метод Initialize инициализирует программу. Метод CreateForm объекта Application создает и показывает на экране окно главной формы, а метод Run реализует бесконечный цикл получения и об-
Таблица 4.9
Свойство ComboBox
Свойство Описание
Name Имя компонента. Используется для доступа к свойствам компонента
Text Текст, находящийся в поле ввода-редактирования
Items Элементы списка — массив строк
Count Количество элементов списка
Itemlndex Номер элемента, выбранного в списке. Если ни один из элементов списка не был выбран, то значение свойства равно -1
Sorted Признак необходимости автоматической сортировки (True) списка после добавления очередного элемента
DropDownCount Количество отображаемых элементов в раскрытом списке. Если количество элементов списка больше, чем DropDownCount, то появляется вертикальная полоса прокрутки
Left Расстояние от левой границы компонента до левой границы формы
Top Расстояние от верхней границы компонента до верхней границы формы
Height Высота компонента (поля ввода-редактирования)
Width Ширина компонента
Font Шрифт, используемый для отображения элементов списка
ParentFont Признак наследования свойств шрифта «родительской» формы
Свойство Описание
Name Имя компонента. Используется в программе для доступа к компоненту и его свойствам
Caption Текст, отображаемый на кнопке
Font Шрифт, который используется для отображения текста
Left Расстояние от левой границы формы до левой границы компонента
Top Расстояние от верхней границы формы до верхней границы компонента
Width Ширина поля компонента
Height Высота поля компонента
Enabled Признак доступности кнопки: кнопка доступна, если значение свойства равно True, и недоступна, если оно равно False
Visible Признак видимости кнопки на поверхности формы: если значение свойства равно True — кнопка отображается, в противном случае она невидима
Glyph Картинка, отображаемая на кнопке (файл изображения)
NumGlyphs Количество картинок в файле изображения, указанного в свойстве Glyph
Layout Определяет взаимоположение картинки и текста на кнопке. Может принимать следующие значения: blGlyphLeft — картинка располагается слева от надписи, blGlyphRight — справа, blGlyphTop — сверху, blGlyphBottom — снизу
Spacing Расстояние от картинки до надписи. Расстояние задается в пикселах
работки поступающих от Windows сообщений о действиях пользователя. Когда пользователь щелкнет мышью на кнопке Close, Windows передаст программе специальное сообщение, которое заставит программу прекратить работу и освободить назначенные ей системные ресурсы. Файл проекта полностью формируется самой средой Delphi и в большинстве случаев не
предназначен для редактирования (по крайней мере, в учебных задачах).
Несколько слов об отличии языка программирования Delphi от языка TurboPascal: к простым типам данных здесь добавляется тип дата-время (средства для работы с этим типом представлены в табл. П3.1), к сложным — процедурные типы, варианты и классы.
Особую роль в Delphi играют строки, и так как здесь для ввода- вывода (обмена данными между компонентами) чаще всего используется именно строковый тип данных, набор необходимых для работы соответствующих средств приведен в табл. П3.2.
Таблица 4.11
Свойства полосы прокрутки
Свойство Описание
Name Имя компонента. Используется в программе для доступа к компоненту и его свойствам
Enabled
i Признак доступности компонента. Прокрутка доступна, если значение свойства равно True, и недоступна, если оно равно False
Kind Определяет положение прокрутки: горизонтальное или вертикальное
Max Задает максимальное значение положения ползунка
Min Задает минимальное значение положения ползунка
Visible Признак видимости компонента на поверхности формы. Прокрутка отображается, если значение свойства равно True. В противном случае она невидима
LargeChange Указывает, на какое количество точек перемещается ползунок при щелчке мышью по полосе либо при нажатии клавиши [PageUp] и [PageDown]
Left Расстояние от левой границы формы до левой границы компонента
Top Расстояние от верхней границы формы до верхней границы компонента
Width Ширина поля компонента
Height Высота поля компонента
Событийно-управляемое программированиеВ Delphi программный код хранится в виде модулей. При этом структура модуля достаточно близка к аналогичной структуре в ТурбоПаскале, хотя имеются и некоторые отличия:
Unit <имя>;
Interface
<интерфейсная часть>
Implementation
Исполняемая часть>
Initialization
Инициализирующая часть>
Finalization
<завершающая часть>
End.
Здесь Unit — зарезервированное слово (единица), начинающее заголовок модуля; <имя> — имя модуля (правильный идентификатор); Interface — зарезервированное слово (интерфейс), начинающее интерфейсную часть модуля; Implementation — зарезервированное слово (выполнение), начинающее исполняемую часть; Initialization — зарезервированное слово (инициализация), начинающее инициализирующую часть модуля; Finalization — зарезервированное слово (завершение), начинающее завершающую часть модуля; End — зарезервированное слово, являющееся признаком конца модуля.
Таким образом, модуль состоит из заголовка и четырех составных частей, любая из которых может быть пустой.
Назначение первых двух частей модуля такое же, как в Турбо- Паскале, поэтому не будем останавливаться на них подробно. Инициализирующая и завершающая части модуля чаще всего отсутствуют вместе с начинающим их словами Initialization и Finalization. В инициализирующей части размещаются операторы, которые исполняются до передачи управления основной программе и обычно используются для подготовки ее работы. Например, в них могут инициализироваться переменные, открываться необходимые файлы и др. В завершающей части указываются операторы, выполняющиеся после завершения работы основной программы. Если несколько модулей содержат инициализирующие части, эти части выполняются последовательно друг за другом в порядке перечисления модулей в Uses главной программы. Если несколько модулей содержат завершающие части, эти части выполняются последовательно друг за другом в порядке, обратном перечислению модулей в Uses главной программы.
Рассмотрим использование некоторых стандартных компонентов.
Для примера разработаем программу, которая позволяет решать линейное уравнение вида ах+ Ь = 0.
Спланируем реализуемый проект. Очевидно, что форма для решения задачи должна содержать заголовок с текстом решаемой задачи. Кроме того, должны иметься текстовые поля ввода для значений а, Ь. Результат также должен выводится в определенное поле. Для получения результата после ввода данных необходимо на форме разместить соответствующую кнопку. Для инициализации переменных и очистки формы от ранее полученных результатов требуется кнопка сброса.
Примечание. Будем полагать, что пользователи вводят корректные данные. Отметим также, что в отличие от ТурбоПаскаля разделителем целой и дробной частей вещественного числа в русскоязычной версии Windows (если не выбрана другая настройка) является запятая.
Примерный вид окна программы решения указанной задачи показан на рис. 4.10.
Определим, какие компоненты необходимо помещать на форму. Для вывода сообщения «Программа решения линейного уравнения ах + b = 0», надписей «а», «Ь» и ответа используем компонент Label. Для ввода информации используем компонент Edit, и, наконец, для кнопок — компонент Button.
Итак, поместим все необходимые компоненты на форму, отрегулируем их размеры, установим значения свойств по умолчанию и переименуем задаваемые по умолчанию идентификаторы компонентов для лучшей читаемости кода программы.

Рис. 4.10. Форма интерфейса приложения
Идентификатор компонента для кнопки [Решить!] назовем Solution, для кнопки [Сброс] — Clear, поле вывода ответа — Answer. Остальные идентификаторы оставим неизменными.
Для всех компонентов установим необходимое значение свойства Caption для отображения запланированного текста.
Далее программируем реакцию на действия пользователя при работе программы. В нашем случае следует предусмотреть реакцию на нажатие кнопок [Решить!] и [Сброс].
Код для кнопки [Сброс]:
Procedure TForml.ClearClick(Sender : TObject);
Begin
Editl.Text := 'O';
Edit2.Text := 'O’;
Answer.Caption := 'Ответ:?';
End;
Код для кнопки [Решить!]:
Procedure TForml.SolutionClick(Sender : TObject);
Var a, b : real; x : real; s : String;
Begin
a := StrToFloat(Editl.Text) ;
b := StrToFloat(Edit2.Text) ;
If а о 0
Then Begin
x := -b/a;
s := 'Единственное решение: ';
End
Else If a = 0
Then If b = 0
Then s := 'Бесконечное множество решений’ Else s := 'Нет решений';
If aoOr.
Then Answer.Caption := 'Ответ: ' + s + FloatToStr(x)
Else Answer.Caption := 'Ответ: ' + s;
End;
Обратим внимание на приведение типов в последнем коде. В поле редактирования данные заносятся в текстовом формате, и для дальнейшей обработки требуется перевод их в числовой формат. Для вывода данных, наоборот, требуются только строковые величины.
Данная программа позволяет решать заданное линейное уравнение для любых вещественных данных. Для ее тестирования необходим набор, по крайней мере, из трех тестов, обеспечивающих проверку всех разветвлений.
Полный код модуля для реализуемого проекта имеет следующий вид:
Unit Unitl;
Interface__
Uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; Type
TForml = Class(TForm)
Label1 : TLabel;
Labe12 : TLabel;
Editl : TEdit;
Label3 : TLabel;
Edit2 : TEdit;
Solution : TButton;
Clear : TButton;
Answer : TLabel;
Procedure SolutionClick(Sender : TObject); Procedure ClearClick(Sender : TObject);
Private
{Private declarations}
Public
{Public declarations}
End;
Var Forml : TForml;
Implementation
{$R *.dfm}
Procedure TForml.SolutionClick(Sender : TObject); Var a, b : Real; x : Real; s : String;
Begin
a := StrToFloat(Editl.Text); b := StrToFloat(Edit2.Text) ;
If а о 0 Then Begin
x : = -b/a;
s := Единственное решение: ';
End
i( Else If a = 0
Then If b = 0
Then s := 'Бесконечное множество решений' Else s := 'нет решений';
If а о О
Then Answer .Caption := 'Ответ: ' + s + FloatToStr (x) Else Answer.Caption := 'Ответ: ' + s;
End;
Procedure TForml.ClearClick(Sender: TObject);
Begin
Editl.Text := ’O';
Edit2.Text :='0';
Answer.Caption :='Ответ:?';
End;
End.
Данная программа готова к работе. Компиляция осуществляется следующим образом:
выполнить команду Проект/Опции (Project/Option), после чего откроется диалоговое окно Опции проекта (Project Options);
выбрать вкладку Каталог/Условия (Directories/Conditionals);
задать в разделе Каталоги в строке Результат (Output directory) путь до папки с файлами проекта, в которой будет записан результирующий ехе-файл;
выполнить команду Проект/Компилировать проект (Project/ Build All).
Имя ехе-файла совпадает с именем файла проекта. Этот файл можно будет запустить вне среды Delphi. Если ехе-файл не требуется, то строку Результат (Output directory) следует очистить, в этом случае файл будет компилироваться в память.
В процессе отладки для запуска программы можно использовать кнопку у или клавишу F9.
Упражнения
На основе приложения для решения линейного уравнения разработать:
а)приложение для решения квадратного уравнения;
б)приложение для решения системы из двух линейных уравнений с двумя неизвестными.
Дополнить приложение для решения линейного уравнения и приложения из первого упражнения проверкой ввода данных.
Написать приложение для второго упражнения к подразд. 4.2 (для работы с обыкновенными дробями).
Технология создания приложений в DelphiОбъектно-ориентированный подход, так же, как любая парадигма программирования, подразумевает прохождение ряда этапов при разработке программного продукта. Ранее уже описывались этапы разработки программы при использовании структурного подхода к программированию, а также методика объектно-ориентированного проектирования. Безусловно, использование объектов определяет некоторую специфику в последовательности действий при создании приложения, хотя многое из того, что обсуждалось и использовалось ранее, остается в силе. Заметим, что написание учебного приложения — это моделирование действий по разработке «взрослых» программных продуктов, подразумевающее некоторое упрощение процесса с сохранением его основных черт. С этих позиций и будем рассматривать далее этапы разработки приложений в Delphi. Отметим также, что процесс создания программы чаще всего носит итерационный характер, т.е. сначала выполняются анализ, проектирование и реализация интерфейса или его части, а затем программа наращивается до получения окончательного варианта.
В разработанной в подразд. 4.5 программе большинство из этих этапов имеется. Остановимся на них подробнее.
Этапы разработки приложений. Упрощенное представление этапов разработки:
постановка задачи, изучение предметной области, построение модели (математической, информационной), проецирование построенной модели на разрабатываемое ООП-приложение;
проектирование ООП-приложения;
разработка интерфейса пользователя;
программирование приложения, тестирование и отладка программного кода;
разработка документации.
Не будем подробно останавливаться на первом этапе, поскольку его содержание, детально описанное при рассмотрении структурного подхода к программированию, не имеет принципиальных отличий при ОПП.
Более детально обсудим последующие этапы разработки ООП- приложения в визуальной среде.
Проектирование ООП-приложения. Результатом первого этапа разработки является информационная модель исследуемого процесса, явления (в нашем случае решаемой содержательной задачи). По сути, эта модель уже содержит, как минимум, набор объектов и связей между ними (т.е. для исходной системы выполнена декомпозиция). На этапе проектирования ООП-приложения каждому объекту необходимо дать уникальное имя (задать идентификатор). Здесь же принимается решение, какие из объектов требуют визуализации, т.е. в терминах Delphi, какие компоненты будут отображены на форме.
Для каждого выделенного объекта необходимо указать перечень характеристик (свойств) и действий над ним. Действия над объектом отображаются посредством набора методов. Далее будет показано, что чаще всего в качестве такого рода действий в ООП-приложе- нии, разрабатываемом для функционирования в операционной системе с графическим интерфейсом (например, Windows), выступают реакции на разного рода события как внешние, так и внутренние.
Разработка интерфейса пользователя. При разработке интерфейса пользователя необходимо отталкиваться от функционального назначения приложения. В Delphi особенность разработки интерфейса заключается в том, что многие его элементы (форма, компоненты и т.д.) уже присутствуют в среде программирования. Таким образом, интерфейс создается на базе имеющихся «кирпичиков» и адаптируется под запросы потенциального конечного пользователя.
При разработке интерфейса пользователя необходимо соблюдать ряд правил.
При проектировании окон (форм) ввода данных:
для команд всегда следует создавать клавишные эквиваленты (при этом необходимо там, где это уместно, сохранять привычные эквиваленты), не заставляя пользователя применять исключительно мышь;
расположение элементов на главной форме должно быть согласовано с задачами пользователя;
при вводе данных должна присутствовать заметная, но ненавязчивая связь с пользователем (например, синтаксический контроль и, если возможно, исправление ошибок и опечаток);
для нескольких разных форм ввода не следует использовать существенно отличающиеся интерфейсы.
При создании меню:
следовать стандартным соглашениям о расположении пунктов меню, принятым в Windows;
группировать пункты меню в логическом порядке и по содержанию;
для группировки пунктов в раскрывающихся меню использовать разделительные линии;
избегать избыточных меню;
использовать клавиатурные эквиваленты команд и «горячие» клавиши;
помещать на панель инструментов часто используемые команды меню.
При работе приложения в процессе ожидания следует информировать пользователя о ходе работы (например, с помощью индикатора состояния выполнения задания).
Естественными являются общие дизайнерские требования: сочетание цвета фона приложения и цвета выводимого на него текста, количество используемых цветов и др.
Программирование, тестирование, отладка. Как уже отмечалось, на этапе проектирования приложения выделяется функциональное назначение всех его элементов и возможные реакции на внешние и внутренние события.
Часть программного кода, которая касается интерфейса приложения, генерируется автоматически при помещении и настройке
свойств соответствующих элементов. Часть кода, касающуюся обработки событий, создает программист. Кроме того, программный код может содержать вспомогательные подпрограммы, необходимые для функционирования отдельных частей или приложения в целом. Размещение кода таких подпрограмм будет рассмотрено далее.
Очевидно, что каждый из разработанных методов и вспомогательных подпрограмм, а затем и комплекс в целом подвергаются процедуре тестирования. Приемы тестирования мало отличаются от приемов, применяемых для тестирования кода структурных программ. Для каждого метода или подпрограммы составляется столько тестов, сколько возможно вариантов прохождения данного метода, проверяются граничные и недопустимые состояния. При этом требования к тестовым наборам сохраняются. В коде программы необходимо предусмотреть верификацию данных при вводе.
Далее тестируется взаимодействие разных элементов программы и приложения в целом. Отметим, что тестовые наборы разрабатываются до начала процедуры тестирования. В общем случае они являются частью документации приложения. В настоящее время при разработке программного обеспечения используют системы автоматической генерации тестовых наборов, которые создаются на основе модели решаемой задачи. В учебном программировании тестовые наборы создаются «вручную».
Разработка документации. Любой программный продукт сопровождается документацией. При разработке ООП-приложения состав и назначение документации должен отвечать тем же требованиям, что и при разработке программного обеспечения для других парадигм программирования. Минимальный пакет документации составляют руководство программиста и руководство пользователя. Состав и структура документации в общем случае стандартизированы.
Важно отметить наличие самодокументирования программного кода, т.е. комментариев к его блокам в тексте программы.
При разработке учебных программ рекомендуется следующий состав отчетной документации:
описание постановки задачи;
описание модели;
описание проекта (количество элементов на форме, их функции, взаимодействие между собой, взаимодействие с другими приложениями) и инициализация свойств объектов;
тестовые наборы для каждого метода, вспомогательных подпрограмм, интерфейсной части и приложения в целом;
программный код с комментариями;
результаты работы программы (при выполнении расчетов или каких-либо других действий, предполагающих эти результаты).
Примеры разработки приложений DelphiРассмотрим примеры прохождения этапов разработки программного продукта.
Пример 4.4. Требуется запрограммировать калькулятор для выполнения действий с числами в системе счисления с основанием р (2<рй9).
Спланируем реализуемый проект и примерный интерфейс приложения. Форма будет содержать кнопки для набора цифр. Причем, если какие-либо цифры не входят в систему счисления с текущим основанием, они скрываются. Выбор основания системы счисления будем осуществлять из раскрывающегося списка, который имеется на форме. Результаты (как промежуточные, так и итоговые) выводятся в определенное поле. Еще четыре кнопки обозначим знаками четырех арифметических операций, также необходимы кнопка [=] и кнопка сброса [С].
Опишем предполагаемое функционирование приложения:
при нажатии цифровой кнопки очередная цифра отображается в записи текущего числа в поле результата;
при нажатии кнопки [С] в поле результата отображается нуль;
при нажатии кнопок со знаками операций текущее значение используется в качестве второго операнда (предполагается, что первый уже имеется в памяти или, по крайней мере, равен нулю) в той операции, которая была выбрана ранее, результат и текущая выбранная операция запоминаются, в поле результата индицируется нуль (поле готово к вводу следующего числа);
при нажатии кнопки [=] вычисляется окончательный результат в соответствии с последней выбранной операцией;
Рис. 4.11. Интерфейс приложения «Каль-кулятор»
• при выборе основания системы счисления значение в поле результата переводится в эту систему счисления.
Вид окна программы решения указанной задачи показан на рис. 4.11.
Приведем некоторые листинги (другие предлагается разработать самостоятельно по аналогии).
Код процедуры для события «Выбор основания системы счисления» (с использованием компонента ComboBox) следующий:
Procedure TCalculator.OsnovanieSelect(Sender: TObject);
Var a, p : Integer; s : String;
Begin
p := pOld;
_PTolO(Rezalt.Text, p, a); pOld := StrToInt(Osnovanie.Text);
_10toP(a, pOld, S) /
Rezalt.Text := s; Case StrToInt(Osnovanie.Text)
2: Begin _2.Visible : = False;
_3.Visible : = False;
_4.Visible : = False;
_5.Visible : = False;
_6.Visible : = False;
_7.Visible : = False;
_8.Visible : = Falser-
End; 3: Begin _2.Visible : = True;
_3.Visible : = False;
_4.Visible : = Falser-
_5.Visible : = False;
_6.Visible : = Falser-
_7.Visible : = False;
_8.Visible : = False;
End; 4: Begin _2.Visible : = True;
_3.Visible : = True;
_4.Visible : = False;
_5.Visible : = False;
_6.Visible : = False;
_7.Visible : = False;
8.Visible : = False;
2.Visible : = True;
_3.Visible : = True;
__4 .Visible : = True;
_5.Visible : = False
_6.Visible : = False
7.Visible : = False
_8.Visible : = False
End; Begin _2.Visible : = True;
_3.Visible : = True;
_4.Visible : = True;
_5.Visible : = True;
_6.Visible : = False
_7.Visible : = False
_8.Visible : = False
End; Begin 2.Visible : = True;
_3.Visible : = True;
4.Visible : = True;
_5.Visible : = True;
_6.Visible : = True;
7.Visible : = False
8.Visible : = False
End; Begin _2.Visible : = True;
3.Visible : = True;
_4.Visible ; = True;
_5.Visible : = True;
6.Visible : = True;
7.Visible : = True;
_8.Visible : = False
End; Begin _2.Visible : = True;
_3.Visible : = True;
4.Visible : = True;
_5.Visible : = True;
_6.Visible : = True;
7.Visible : = True;
8.Visible : = True;
End;
End;
End;

Щелчок мышью по кнопке с обозначением цифры на примере кнопки [0]:
Procedure TCalculator._0Click(Sender : TObject); Begin
If Rezalt.Text = f 0 1 Then Rezalt.Text :=_0. Caption Else Rezalt.Text := Rezalt.Text + _0.Caption End;
Щелчок мышью по кнопке со знаком операции на примере операции [+]:
Procedure TCalculator.PlusClick(Sender : TObject); Begin
Operation;
Znak := ' + ';
End;
Щелчок мышью по кнопке [=]:
Procedure TCalculator.ButtonlClick(Sender : TObject); Var s : String;
Begin
Operation;
Znak := f ';
_10ToP(a, POld, s);
Rezalt.Text := s; a : = 0;
End;
Приведем также реализацию вспомогательных процедур, которые непосредственно выполняют переводы из десятичной системы счисления в систему с основанием р, и наоборот, а также собственно выполнение арифметических операций:
Procedure _10ТоР(а, р : Integer; Var s : String); Begin
If a = 0 Then s :='0' Else s I22*1;
While a о 0 Do Begin
s := IntToStr(a mod p) + s; a := a div p
End;
End;
Procedure _PTolO(s : String; p : Integer; Var a : Integer);
Var i : Integer;
Begin
a : = 0 ;
For i := 1 To length(s) Do
a := a * p + StrToInt (s[i])
End;
Procedure Operation;
Var r : Integer;
Begin
_pTolO(Calculator.Rezalt.Text, POld, r);
If a = 0 Then a := r Else Case Znak Of
' + ': a := a + r;
: a := a - r;
: a := a * r;
1 /? : a := a div r End;
Calculator.Rezalt.Text := *0*;
End;
Указанные процедуры не входят в состав основных и присутствуют лишь в разделе реализации модуля проекта (Implementation).
Наконец, при запуске приложения инициализируются переменные (глобальные и некоторые поля компонентов):
Procedure TCalculator.FormCreate(Sender : TObject); Begin
_2.Visible := False;
_3.Visible := False;
_4.Visible := False;
_5.Visible := False;
_6.Visible := False;
_7.Visible := False;
_8.Visible := False; pOld := 2; a := 0;
End;
Пример 4.5. Требуется реализовать приложение, моделирующее следующую игру для младших школьников. На поле есть две коробки: для черных и для белых шариков, а также некоторое количество черных и белых шариков (от 2 до 10). Разложить эти шарики по коробкам и указать, каких больше — черных или белых.
При реализации требуемого приложения будем использовать специальный прием связывания программ с данными в Windows, который называется Drag&Drop (перетащи и отпусти). Использо- шние соответствующих событий и свойств данного механизма применительно к объектам Delphi опишем по ходу реализации.
Спланируем проект и примерный интерфейс приложения. Форма будет содержать две коробки (компоненты TLabel) и десять париков (компоненты TShape). При этом при каждом запуске пробам мы число шариков и их цвет будут задаваться случайным об- )азом.
Опишем предполагаемое функционирование приложения:
при запуске инициализируются необходимые свойства ком- юнентов и задаются число и цвет шариков, а лишние шарики три этом скрываются;
при перетаскивании шарика в «свою» коробку и отпускании снопки мыши шарик исчезает и счетчик числа шариков в короб- се увеличивается на единицу;
при перетаскивании шарика в «чужую» коробку его размеще- ше в ней запрещается и шарик остается на месте.
Примерный вид формы для создаваемого приложения показан та рис. 4.12.
Возможный результат работы этой программы показан на >ис. 4.13.
Опишем логику работы создаваемого приложения на основе трограммного кода.


Рис. 4.13. Окно приложения «Игра»
При запуске приложения необходимо инициализиро] свойства и разместить случайное число шариков на форм Программа данной процедуры следующая:
Procedure TForml.FormCreate(Sender : TObject Var i : Integer;
Begin
b := 0; w := 0;
Black.Height := 80; Black.Width := 80; Black.Hint :='b';
White.Height := 80; White.Width := 80; White.Hint :='w';
a[l] := ol; a[2] := o2; a[3] := o3;
a[4]:= o4; a[5]:= o5;
a [6]:= об; a [7]:= o7; a [8]:= 08;
a[9]:= o9; a[10]:= olO;
randomize;
n := random(9) + 2;
{Скрываем лишние шарики}
For i := n + 1 To 10 Do With a[i] Do Visible := False;
{Раскрашиваем в белый или черный цвет оставшиеся шарики} For i := 1 То n Do With a[i] Do Begin
If random(2) = 0
Then Begin
Brush.Color := clBlack;
Hint := 'b'
End
Else Begin
Brush.Color := clwhite;
Hint := 'w'
End;
DragMode := dmAutomatic End;
End;
Здесь b, w — соответственно счетчики черных и белых шариков, уже опущенных в коробки; Black, White — имена компонентов , т. е. «коробок» для хранения черных и белых шариков.
Установка свойства Hint осуществляется для того, чтобы у шарика, который можно разместить в данной коробке, данное свойство имело такое же значение.
Информацию о каждом из шариков (для удобства дальнейшего оперирования) размещаем в массиве.
Сгенерировав число отображаемых шариков, лишние скрываем, оставшиеся раскрашиваем в случайный цвет (черный или белый), устанавливаем для шарика определенного цвета соответствующее значение свойства Hint.
Свойство DragMode определяет, как будет выполняться весь комплекс действий, связанных с Drag&Drop. Если DragMode принимает значение dmManual, то все события перетаскивания должны определяться вручную (т.е. программистом по ходу выполнения программы), и начинается перетаскивание только после вызова специальных методов. Если DragMode принимает значение dmAutomatic, то все события перетаскивания определяются автоматически, а перетаскивание начинается сразу после нажатия кнопки мыши пользователем. В нашем случае устанавливается значение dmAutomatic.
Далее необходимо обработать события, связанные с перетаскиванием объектов.
Проверка готовности приемника принять перетаскиваемый объект происходит при обработке события OnDragOver.
Программа проверки следующая:
Procedure TForml.BlackDragOver(Sender, Source : TObject; X, Y : Integer; State: TDragState; Var Accept : Boolean);
Begin
If (Sender Is TLabel) And (Source Is TShape) Then Accept := ((Sender As TLabel).Hint = (Source As TShape).Hint)
End;
Параметр Sender указывает компонент, над которым перемещается объект. Параметр Source содержит информацию о компоненте-отправителе. В параметрах X и Y содержатся координаты указателя мыши, выраженные в пикселах, относительно компонента Sender. Параметр State указывает состояние перемещаемого объекта относительно компонента Sender. Параметр Accept сообщает, готов ли Sender принять перетаскиваемые данные. Если параметр имеет значение True, то Sender готов принять перетаскиваемый объект.
В данном примере обработка указанного события заключается в сравнении значений свойства Hint отправителя и приемника.
Обработка события реализована для объекта Black. В объекте White для соответствующего события сделана ссылка на этот же обработчик события.
При завершении перетаскивания (вне зависимости от того, приняты данные или нет) для перетаскиваемого объекта возникает событие OnDragEnd. Это событие происходит также при отмене перетаскивания, причем оно не является обязательным для выполнения. Операция перетаскивания может быть произведена и без обработки этого события.
Реализуем обработку для первого шарика (для остальных сделана ссылка на этот же обработчик события):
Procedure TForml.olEndDrag(Sender, Target: TObject; X, Y: Integer);
Var s: String;
Begin
If Target о Nil Then Begin
If (Target As TLabel).Name =’Black*
Then Begin b := b + 1; str(b, s) ;
(Target As TLabel).Caption := ’Черных* +#10 + #13 + s
End
Else Begin w := w + 1; str (w, s) ;
(Target As TLabel).Caption := ’Белых* +#10 +#13 + s
End;
(Sender As TShape).Visible := False;
End;
End;
При этом увеличим соответствующий счетчик принятых шариков на единицу и скроем сброшенный в коробку шарик.
Полный вариант программного модуля следующий:
Unit Ех_3;
Interface
Uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls; Type
TForml = Class(TForm)
White : TLabel;
Black : TLabel;
: TShape;
: TShape;
: TShape;
: TShape;
: TShape;
: TShape; ol : TShape;
: TShape;
: TShape;
: TShape;
Procedure FormCreate(Sender : TObject); Procedure BlackDragOver(Sender, Source : TObject; X, Y : Integer; State : TDragState; Var Accept : Boolean);
Procedure olEndDrag(Sender, Target : TObject; X, Y : Integer);
End;
Var Forml : TForml; n : Integer; a : Array[1..10] Of TShape; b, w: byte;
Implementation{$R *.dfm}
Procedure TForml.FormCreate(Sender: TObject);
Var i : Integer;
Begin b := 0; w : = 0;
Black.Height := 80;
Black.Width := 80;
Black.Hint := 'b*;
White.Height := 80;
White.Width := 80;
White.Hint := 'w'; a[1]:= ol; a[2]:= o2;
a[3]:= o3; a[4]:= o4;
a [5] := o5; a [6] := об; a [7] := o7; a [8] := 08; a[9]:= o9; a[10]:= olO;
randomize; n := random(9) + 2;
{Скрываем лишние шарики}
For i := n + 1 To 10 Do
With a[i] Do Visible := False;
{Раскрашиваем в белый или черный оставшиеся шарики}
For i := 1 То n Do With a[i] Do Begin
If random(2) = 0 Then
Begin Brush.Color := clBlack; Hint := fb' End Else
Begin Brush.Color := clwhite; Hint :=’w’ End; DragMode := dmAutomatic End;
End;
Procedure TForml.BlackDragOver(Sender, Source : TObject; X, Y : Integer; State : TDragState;
Var Accept: Boolean);
Begin
If (Sender Is TLabel) And (Source Is TShape)
Then
Accept := ((Sender As TLabel).Hint = (Source As TShape).Hint)
End;
Procedure TForml.olEndDrag(Sender, Target : TObject; X, Y : Integer);
Var s : String;
Begin
If Target о Nil Then Begin
If (Target As TLabel).Name =’Black1 Then Begin b := b + 1; str(b, s) ;
(Target As TLabel).Caption:=
'Черных’ +#10 +#13 + s
End
Else Begin w := w + 1; str(w, s) ;
(Target As TLabel).Caption := 'Белых' +#10 +#13 + s
End;
(Sender As TShape).Visible := False;
End;
End;
End.
Упражнения
Продолжить программу из примера 4.4, реализовав по аналогии процедуры для других цифровых кнопок и кнопок со знаками операций, и получить работающий калькулятор.
Дополнить форму к примеру 4.5 (см. рис. 4.12) кнопкой [Закрыть], которая появляется после того, как все шарики помещены в коробки. Обработать нажатие кнопки, по которому закрывается приложение.
Иерархия классовТерминология, касающаяся объектно-ориентированного программирования, принятая в Delphi, несколько отличатся от терминологии в ТурбоПаскале. Рассмотрим эту терминологию, а также способы реализации объектного подхода к программированию и основные его принципы, принятые в Delphi.
Классы в Delphi. Объявление класса, свойств и методов. То, что в ТурбоПаскале именовалось объектом, в Delphi принято называть классом. Классы в Delphi — это специальные типы, которые содержат следующие элементы: поля, методы и свойства. Как и любой другой тип, класс служит лишь образцом для создания конкретных экземпляров реализации, которые называются объектами. Данная терминология употребляется в C++, откуда и бьша заимствована.
Важным отличием классов от других типов является то, что их объекты всегда распределяются в неупорядоченной структуре (куче), поэтому объект «Переменная» фактически представляет собой лишь указатель на динамическую область памяти. Однако в отличие от других указателей при ссылке на содержимое объекта запрещается использовать операцию разыменования, т.е. символ «л» за именем объекта.
Все классы, используемые в Delphi (как библиотечные, так и разрабатываемые программистом), наследуются от класса TObject. При этом указывать данный класс при объявлении как «родительский» необязательно.
Формат описания нового класса следующий:
Туре Идентификатор типа класса> = Class Private сокрытые элементы класса>;
Protected сзащищенные элементы класса>;
Public Собщедоступные элементы класса>;
Published сопубликованные элементы класса>;
End;
Не все указанные в данном шаблоне секции могут присутствовать при объявлении класса. Поясним их смысл.
Секция Private содержит внутренние элементы, обращение к которым возможно только в пределах модуля, содержащего объявление класса.
Секция Protected содержит защищенные элементы, которые доступны в пределах модуля, содержащего объявление класса, а также внутри «потомков» класса.
Секция Public содержит общедоступные элементы, к которым возможно обращение из любой части программы.
Наконец, секция published содержит опубликованные элементы, доступ к которым осуществляется так же, как и элементам секции Public.
«Потомки» класса могут менять область доступности всех элементов «родительского» класса, за исключением объявленных в секции Private.
Если при объявлении элементов класса не указывать, к какой секции относится объявление, то доступ к данным элементам будет осуществляться как к объявленным в секции Public. В Delphi разрешается сколько угодно раз объявлять любую секцию, причем порядок следования секций не имеет значения и любая секция может быть пустой.
Приведем пример объявления класса. Опишем класс «Обыкновенная дробь» с методами «НОД числителя и знаменателя», «Сокращение», «Натуральная степень» (см. пример 4.1):
Type Natur = 1..32767;
Frac = Record Р : Integer; Q : Natur End;
Drob = Class
Procedure Vvod; {Ввод дроби}
Procedure Print; {Вывод дроби}
Procedure NOD(Var C : Natur);
Procedure Sokr;
Procedure Stepen(N : Natur; Var C : Frac);
Property A : Frac Read Print Write Vvod;
End;
Здесь объединение полей, методов и свойств в единое целое, как и в ТурбоПаскале, называется инкапсуляцией. Поля могут быть
любого типа, в том числе и классами. Инкапсулированные в классе процедуры и функции являются методами. Свойства — это специальный механизм классов, регулирующий доступ к полям. Объявляются свойства с помощью зарезервированных слов Property, Read и Write (слова Read и Write считаются зарезервированными только в контексте объявления свойства). Обычно свойство связано с некоторым полем и указывает те методы класса, которые должны использоваться при записи в это поле или при считывании из него.
Реализация методов, как и в ТурбоПаскале, осуществляется вне объявления класса, при этом по-прежнему требуется указывать метод какого класса реализуется. Например, при реализации метода Vvod из примера 4.1 заголовок будет иметь следующий вид:
Procedure Drob.Vvod;
Наследований. Любой класс может быть образован от другого класса. Для этого при его объявлении указывается имя класса- «родителя»:
<дочерний класс> = Class (<родительский класс>)
Образованный класс автоматически наследует поля, методы и свойства своего «родителя» и может добавлять новые. Принцип наследования обеспечивает поэтапное создание сложных классов и разработку собственных библиотек классов.
Все классы Delphi образованы от одного «родителя» — класса TObject, который не имеет полей и свойств, но включает в себя методы самого общего назначения, обеспечивающие весь жизненный цикл любых объектов — от создания до уничтожения.
Принцип наследования приводит к созданию ветвящегося дерева классов, постепенно разрастающегося при перемещении от класса TObject к его «потомкам». Каждый «потомок» дополняет возможности своего «родителя» новыми и передает их своим «потомкам».
В Delphi не реализовано множественное наследование, т. е. «дочерний» класс может иметь только одного «родителя».
В качестве примера приведем рассмотренный ранее класс «Вычислитель» (см. пример 4.2):
Type BaseType = Double;
Vichislitel = Class А, В, С : BaseType;
Procedure Init; {Ввод или инициализация полей} Procedure Slozh;
Procedure Vich;
Procedure Umn;
Procedure Delen;
End;
NovijVichislitel = Class(Vichislitel)
N : Integer;
Procedure S tepen;
Procedure Koren;
End;
Полиморфизм, перегрузка методов. В Delphi определение полиморфизма аналогично определению в ТурбоПаскале: полиморфизм — это свойство классов выполнять одинаковые по смыслу действия разными способами. Изменив алгоритм того или иного метода «потомков» класса, придадим им отсутствующие у «родителя» специфические свойства. Для изменения метода необходимо перекрыть его у «потомка», т.е. объявить у «потомка» одноименный метод и реализовать в нем необходимые действия. В результате объект «родитель» и объект «потомок» будут иметь два одноименных метода с разной алгоритмической основой, которые, следовательно, придают объектам разные свойства. В Delphi полиморфизм достигается не только с помощью механизма наследования и перекрытия методов «родителя», но и их виртуализацией, позволяющей «родительским» методам обращаться к методам своих «потомков».
Механизм перекрытия «родительского» метода одноименным методом «потомка» приводит к тому, что последний «не видит» перекрытый «родительский» метод и может обращаться к нему лишь с помощью зарезервированного слова Inherited. В Delphi введено зарезервированное слово Overload (перезагрузить), с помощью которого становятся видны одноименные методы как «родителя», так и «потомка».
Понятие объектно-ориентированного проектирования. Модели разрабатываемого программного обеспечения при объектном подходе основаны на предметах и явлениях реального мира, а также на описании требуемого поведения разрабатываемого программного обеспечения, т.е. его функциональности, которая связывается с состояниями элементов (объектов) конкретной предметной области.
Объектный подход к разработке программного обеспечения основан на использовании объектной декомпозиции, т.е. представлении разрабатываемого программного обеспечения в виде совокупности объектов, в процессе взаимодействия которых через передачу сообщений и происходит выполнение требуемых функций.
Однако при объектном подходе, как и при структурном, сразу можно выполнить декомпозицию только очень простого программного обеспечения. Поэтому сначала для объектно-ориентирован
ного программирования были разработаны соответствующие методы анализа и проектирования программного обеспечения, использующие различные модели и нотации.
В 1994 г. был разработан язык UML (Unified Modeling Language — унифицированный язык моделирования), который в настоящее время фактически признан стандартным средством описания проектов, создаваемых с использованием объектно-ориентированного подхода. (Подробное описание этого языка смотрите в специальной литературе.)
Упражнения
Описать следующие классы с указанием их методов:
а)«Телефонный звонок» — номер телефона, дата разговора, продолжительность, код города и т.д.;
б)«Поездка» — номер поезда, пункт назначения, дни следования, время прибытия, время стоянки и т.д.;
в)«Кинотеатр» — название кинофильма, сеанс, стоимость билета, количество зрителей и т.д..
Реализовать объявленные в классах методы. Описать объекты-«потом- ки» для указанных классов. Выполнить отладку и тестирование приложения.
Реализовать в виде класса пример 4.3. Дополнить набор классов классом «Прямоугольник», а также другими выпуклыми четырехугольниками, не являющимися параллелограммами (трапеция и т.д.), и реализовать соответственно их методы.
Реализовать в среде Delphi упражнение 6 из подразд. 4.2.
ГЛАВА 5
ЗАДАЧИ ПО ПРОГРАММИРОВАНИЮТема «Линейные программы»ФормулыВычислить значения по следующим формулам при действительных значениях всех переменных:
. Ъ + ylb2 + 4ас ,, ,
1.га*с + Ь~1\

„ sinx + cosy 3. —-т-^tgxy;
6.*-т + у;
2
4.
с d cd ’
х + у ху -12 у +134+ х ’
X3 X5

7. In (y-№ ( у 1
X ' 2 X2
X+T
^ A
5.
COS X- sin у З + е^-'
1 + х2 \у - tg х| ’
9.
8. (1 - tgx)ctgjc + cos(x - у);
13. cos* + 16х cos(xy) - 2;
lnlcosxl . ln(l + x2)’
1
11.1 +-у -12 х2у;
10.
12.
х +1
X — 1
/
х2 -7х +10
+ lSxy2;
п-2х15. 2ctg(3x) -
17. xlnx +—
1
12х2 + lx - 5 ’
х
cos X
3
х2 -8х + 12’
14. 2~х - cosx + sin(2xy);
16. lx2 — х31 — 7х ;
х3 -15х
18. sin Vx +1 - sin Vx -1;
19. ех -
у2 + 12ху-3х2.
18у-1
20.
1 + sin Vx + 1. cos(12y-4) ’

21. 2ctg(3x)- i^S4r;22. ex-x-2 + (l + x)x;
ln(l + x2)
25. x - 10sinx + cos(x - y);
26.
l + sin2(x + y)
2 +
x --
2x
+ x;
1 + X2y2
27. cos2
• П
sin— ;
. z)
cos2 xax2 +bx + c
28. —xyz + ■
SU1X
dx3 - f
23. 3х - 4x + (у - VW);24. x -10 sin x + lx4 - x5

Математические задачи
Вычислить периметр и площадь прямоугольного треугольника по длинам двух катетов а и Ь.
Даны координаты трех вершин треугольника (x^), (х2, у2), (х3, уз). Найти его периметр и площадь.
Вычислить длину окружности и площадь круга с заданным радиусом R.
Найти произведение цифр заданного четырехзначного числа.
Даны два числа. Найти среднее арифметическое кубов и среднее геометрическое модулей этих чисел.
Вычислить расстояние между двумя точками с заданными координатами (хь yi) и (х2,у2).
Даны два действительных числа х и у. Вычислить их сумму, разность, произведение и частное.
Дана длина ребра куба. Найти площади грани, полной поверхности и объем этого куба.
Дана длина стороны равностороннего треугольника. Найти площадь этого треугольника, его высоту, радиусы вписанной и описанной окружностей.
Известна длина окружности. Найти площадь круга, ограниченного этой окружностью.
Найти площадь кольца, внутренний радиус которого равен г, а внешний — заданному числу R (R> г).
Треугольник задан значениями углов и радиусом описанной окружности. Найти длины сторон этого треугольника.
Найти площадь равнобедренной трапеции с основаниями а и Ь и углом а при большем основании а.
Вычислить корни квадратного уравнения ах?+ Ьх+с = 0 с заданными коэффициентами а, b и с, если предполагается, что а#0 и что дискриминант уравнения неотрицательный.
Дано действительное число х. Используя минимальное число арифметических операций (только умножение, сложение и вычитание), вычислить значение 2Х4 - Зх3 + 4Х2 - 5х + 6.
Дано число х. Вычислить значения -2х+ Зх2 -4л3 и 1 + 2х + + Зх2 + 4*3, используя минимальное число операций.
Найти площадь треугольника со сторонами а и b и углом между ними у.
Дано число а. Используя только умножение, получить значения:
а)а8 за три операции;
б)а10 за четыре операции;
в)а4 за две операции;
г)а6 за три операции;
д)а9 за четыре операции;
е)а13 за пять операций;
ж)а15 за пять операций;
з)а21 за шесть операций;
и)а28 за шесть операций;
к)а64 за шесть операций;
л)а7 за четыре операции.
Вывести на экран первые четыре степени числа к.
Найти сумму членов арифметической прогрессии, если известны ее первый член, знаменатель и число членов прогрессии.
Найти (в радианах и градусах) все углы треугольника со сторонами а, Ь, с.
Перевести радианную меру угла в градусы, минуты и секунды. Решить обратную задачу.
Три резистора Л1, R2, R3 соединены параллельно. Найти сопротивление соединения. Решить обратную задачу: по известному общему сопротивлению соединения и двум из трех сопротивлений резисторов, найти третье.
Вычислить путь, пройденный лодкой, если ее скорость по
озеру в стоячей воде — v [км/ч], скорость течения реки — V\ [км/ч], время движения по озеру — Ц [ч], а время движения против течения реки — t2 [ч].<«.
Текущее показание электронных часов т часов (0 < т < 23), п минут (0 < я < 59), к секунд (0 <к< 59). Найти, какое время будут показывать часы через р часов q минут г секунд.
Вычислить высоты треугольника со сторонами а, Ь,<с.
Вычислить объемы цилиндра и конуса, имеющих одинаковую высоту Н и одинаковый радиус основания R.
Ввести любой символ, определить его порядковый номер и указать его предыдущий и последующий символы.
Дана величина А, выражающая объем информации в байтах. Перевести А в более крупные единицы измерения информации.
Даны натуральные числа М и N. Вывести старшую цифру дробной части и младшую цифру целой части числа M/N.
Дано натуральное число Т, представляющее собой длительность прошедшего времени в секундах. Вывести это значение длительности в часах, минутах и секундах в следующей форме: НН ч ММ мин SS с.
Дано действительное число R вида nnn.ddd (по три цифровых разряда в дробной и целой частях). Поменять местами дробную и целую части этого числа и вывести новое полученное число.
Даны два вектора с координатами (Х\, YUZ{) и (Х2, Y2,Zi). Определить угол между этими векторами.
Вычислить площадь и периметр правильного Л'-угольника, описанного около окружности с радиусом R (N— целого типа, R— вещественного типа).
Определить, во сколько раз площадь круга с радиусом R больше площади сегмента, отсеченного хордой длиной а.
Найти частное от деления произведений четных и нечетных цифр четырехзначного числа.
Дан вектор с координатами (х, у, z)- Найти углы наклона этого вектора к координатным осям.
Найти площадь круга, вписанного в треугольник с заданными сторонами.
Окружность вписана в квадрат с заданной площадью. Найти площадь квадрата, вписанного в эту окружность. Определить, во сколько раз площадь вписанного квадрата меньше площади заданного квадрата.
Представить комплексное число А + В\ (А, В — вещественные числа) в тригонометрической форме.
Треугольник задан значениями углов и радиусом вписанной окружности. Найти стороны этого треугольника.
С начала суток часовая стрелка повернулась на у градусов (0<у< 360, у — вещественное число). Определить число полных часов и полных минут, прошедших с начала суток. Сформулировать и решить обратную задачу.
Дана величина вида а, Ь(с), где а — целая часть вещественного числа; Ь— начало дробной части числа, с — период. Получить это число в виде обыкновенной дроби вида т/п, где т — числитель, п — знаменатель.
Вычислить площадь полной поверхности треугольной пирамиды с заданными ребрами.
Дан прямоугольный треугольник АВС (рис. 5.1), для которого определен набор характерных параметров: а, Ь, с — стороны треугольника; угол у =90°; а, р — острые углы треугольника (в градусах); А — высота, опущенная на гипотенузу с; S— площадь;
периметр. По двум следующим заданным параметрам вычис- нить все остальные:
а) а, Ь; б) а, с; в) а, А; г) Ь, а; д) А, Р; е) с, р.
Рис. 5.1. Прямоугольный треуголь-Рис. 5.2. Треугольник
46. Дан произвольный треугольник АВС (рис. 5.2), для которого определен набор характерных параметров: а, Ь, с — стороны треугольника; а, р, у — углы треугольника (в градусах); А — высота, опущенная на сторону с; S— площадь; Р— периметр. По трем следующим заданным параметрам вычислить все остальные:
а) а, А, с; г) А, с, А; ж) S, А, а; к) a, A, Р; н) S, с, а;
б) а, А, у; д) А, с, а; з) а, А, А; л) а, А, а; о) А, а, р;
в) с, а, Р; е) S, А, А; и) a, b, S- м) а, А, у; п) А, а, у.
ник

Логические выражения
Составить программы, печатающие значение True, если следующие указанные высказывания являются истинными, и значение False — в противном случае.
Сумма двух первых цифр заданного четырехзначного числа равна сумме двух его последних цифр.
Сумма цифр заданного трехзначного числа N является четным числом.
Точка с координатами (дс, у) принадлежит части плоскости, лежащей между прямыми х= т и х= п (т < п).
Квадрат заданного трехзначного числа равен кубу суммы цифр этого числа.
Целое число N является четным двухзначным числом.
Треугольник со сторонами а, Ь, с является равносторонним.
Треугольник со сторонами а, Ь, с является равнобедренным.
Среди чисел а, Ь, с есть хотя бы одна пара взаимно противоположных чисел.
Числа а и А выражают длины катетов одного прямоугольного треугольника, а с и d — другого. Эти треугольники являются подобными.
Даны три стороны одного треугольника и три стороны другого. Эти треугольники равновеликие, т.е. имеют равные площади.
Заданная тройка натуральных чисел а, Ь, с является тройкой Пифагора, т.е. с2 = а2 + Ь2.
Все цифры заданного четырехзначного числа ./V различны.
Заданные числа х, у являются координатами точки, лежащей в первой координатной четверти.
Координаты левой верхней и правой нижней вершин прямоугольника (хь yi) и (х2, у2). Точка А(х, у) принадлежит прямоугольнику.
Число с является средним арифметическим чисел а и Ь.
Натуральное число TV является точным квадратом.
Цифры заданного четырехзначного числа TV образуют строго возрастающую последовательность.
Цифры заданного трехзначного числа ТУ являются членами арифметической прогрессии.
Цифры заданного трехзначного числа TV являются членами геометрической прогрессии.
Заданные числа cud являются соответственно квадратом и кубом числа а.
Цифра М входит в десятичную запись четырехзначного числа TV.
Заданное четырехзначное число читается одинаково слева направо и справа налево.
Шахматный конь за один ход может переместиться с одного заданного поля на другое, если каждое поле задано двумя координатами — целыми числами от 1 до 8.
В заданном натуральном трехзначном числе N имеется четная цифра.
Сумма каких-либо двух цифр заданного трехзначного натурального числа N равна третьей цифре.
Заданное число N является степенью числа а, если показатель степени может находиться в диапазоне от 0 до 4.
Сумма цифр заданного четырехзначного числа TV превосходит произведение цифр этого же числа на 1.
Сумма двух последних цифр заданного трехзначного числа N меньше заданного К, а первая цифра больше 5.
Заданное натуральное число TV является двухзначным и кратно К.
Сумма двух первых цифр заданного четырехзначного числа N равна произведению двух последних.
Отрицательное целое число X делится на К без остатка.
Среди заданных целых чисел А, В, С, D есть хотя бы два четных.
Прямоугольник с измерениями А, В подобен прямоугольнику с соответствующими измерениями С, D.
Дробь А/В является правильной, если А, В — целые числа.
Шахматная ладья за один ход может переместиться с одного заданного поля на другое, если каждое поле задано двумя координатами — целыми числами от 1 до 8.
График функции у = ах2 + Ьх+ с проходит через заданную точку с координатами (т, п).
Величина d является корнем только одного из уравнений ох2 + Лх+с = 0 и тх+л = 0.
Среди первых трех цифр дробной части вещественного числа есть нуль.
Среди первых трех цифр целой части вещественного числа есть нуль.
Дано натуральное число N — некоторый год. Этот год является високосным.
Дано натуральное число N— некоторый год. Этот год является невисокосным.
Заданное натуральное число N не является двухзначным.
Точка с координатами (х, у) не лежит ни на одной из координатных осей.
Дано натуральное число N (N< 32). Двоичная запись этого числа состоит из одних единиц.
Площадь прямоугольника с измерениями А, В не превышает площади прямоугольника с измерениями С, D.
Шахматный слон за один ход может переместиться с одного заданного поля на другое, если каждое поле задано двумя координатами — целыми числами от 1 до 8.
Шахматный ферзь за один ход может переместиться с одного заданного поля на другое, если каждое поле задано двумя координатами — целыми числами от 1 до 8.
Шахматный король за один ход может переместиться с одного заданного поля на другое, если каждое поле задано двумя координатами — целыми числами от 1 до 8.
Среди первых трех цифр дробной части положительного вещественного числа есть нуль.
Трехзначное число кратно второй цифре.
Точка с координатами (х, у) принадлежит части плоскости, лежащей между прямыми у = т и у = п (т< п).
Только одно из чисел а, Ь, с кратно заданному к.
Заданный символ является русской буквой.
Заданный символ является цифрой.
Заданный символ не является латинской буквой.
Только один из двух введенных символов не является цифрой.
Два введенных символа не являются последовательно расположенными в кодовой таблице.
Введенные число и символ обозначают одну и ту же цифру.
Первые две цифры в дробной части заданного вещественного числа совпадают с записью заданного целого числа.
Заданы координаты трех точек плоскости. Эти точки не лежат на одной прямой.
Заданное натуральное число обозначает код введенного символа.
Целая и дробная части заданного вещественного числа одинаковые.
Объемы конуса и цилиндра с заданными измерениями совпадают.
В прямоугольном параллелепипеде с заданными измерениями площади каких-либо непротивоположных граней совпадают.
В треугольной пирамиде с заданными ребрами площади каких-либо граней совпадают.
Имеются две даты в формате число.месяц.год час:минута:се- кунда. Первая дата является более поздней.
Имеется дата в формате число.месяц.год час:минута:секунда. Это осенняя дата и время после полудня.
'Имеется дата в формате число.месяц.год час:минута:секуяда. Это весенняя дата високосного года двадцатого века.
Области, описываемые логическими выражениями
Составить программу, которая печатает True, если точка с координатами (х, у) принадлежит заданным закрашенным (заштрихованным) областям, показанным на рисунках в табл. 5.1, и False — и противном случае.
Таблица 5.1




21
22
У 1 :т::::о X
п г -А-
л- -jt _
--Г- L 23
24
у- “Г
i _ _ v / ч
:v::: 1 _ 5--- п — 1 0 .] 1 X
25
У
8
6
13 5
26
х



5.2. Тема «Ветвление»Текстовые задачи
Даны три действительных числа. Возвести в квадрат неотрицательные из этих чисел и в четвертую степень — отрицательные.
Даны две точки А(х{, >>[) и В(х2, у2). Составить алгоритм, определяющий, какая из этих точек находится ближе к началу координат.
Даны два угла треугольника (в градусах). Определить, возможен ли такой треугольник, и если возможен, будет ли он прямоугольным.
Даны действительные числа х и у, не равные друг другу. Меньшее из этих двух чисел заменить половиной их суммы, а большее — их удвоенным произведением.
На плоскости XOYзадана своими координатами точка А. Указать, где она расположена: на какой оси или в каком координатном угле.
Даны целые числа т, п. Если эти числа не равны, заменить меньшее из них большим исходных числом, а если равны, то заменить оба исходных числа нулями.
Найти количество отрицательных чисел в заданных числах а, Ь, с.
Определить количество положительных чисел в заданных числах а, Ь, с.
Подсчитать количество целых чисел в заданных числах а,
Ь,с.
Определить, делителем каких чисел а, Ь, с является число к.
Услуги телефонной сети оплачиваются по следующему правилу: за разговоры до А минут в месяц платится В рублей, а разговоры сверх установленной нормы оплачиваются из расчета С рублей за минуту. Вычислить плату за пользование телефоном для введенного времени разговоров за месяц.
На экране появляется следующий вопрос: «Кто ты: мальчик или девочка?» Соответственно ввести М или Д. В зависимости от ответа на экране должен появиться текст «Мне нравятся девочки!» или «Мне нравятся мальчики!».
Грузовой автомобиль выехал из одного города в другой со скоростью V] [км/ч]. Через время t [ч] в этом же направлении выехал легковой автомобиль со скоростью v2 [км/ч]. Определить, догонит ли легковой автомобиль грузовой через время tx [ч] после своего выезда.
Перераспределить значения переменных х и у таким образом, чтобы в х оказалось большее из этих значений, а в у — меньшее.
Определить правильность даты, введенной с клавиатуры (число — с 1 до 31, месяц — с 1 до 12). Если введены некорректные данные, сообщить об этом.
Определить результат гадания на ромашке: любит — не любит, взяв за исходное заданное число лепестков п.
Создать модель анализа пожарного датчика в помещении и вывода сообщения «Пожароопасная ситуация». Температура вводится с клавиатуры и должна быть больше 60 °С.
Рис расфасован едва пакета. Масса первого — т [кг], второго — п [id]. Определить, какой пакет тяжелее и какова масса более тяжелого пакета.
Проанализировать возраст человека, чтобы отнести к одной из четырех групп: дошкольник, ученик, работник, пенсионер. Возраст вводится с клавиатуры.
Определить, пройдет ли график функции у = ах2 + Ьх+ с через заданную точку с координатами (/и, п).
К финалу конкурса «Лучший специалист электронного офиса» бьши допущены трое: Иванов, Петров, Сидоров. Соревнования проходили в три тура. Иванов набрал в первом туре тх баллов, во втором — яь в третьем — ри Петров — соответственно т2, п2, р2, а Сидоров — т3, п3, р3. Определить, сколько баллов набрал победитель.
При нажатии любых клавиш на экран выводятся только буквы и цифры, и при этом указывается, что именно выводится: буква или цифра.
Для вещественных чисел х, у, z вычислить шах(х+ у + г) и max (xyz).
Для вещественных чисел х, у, z вычислить min2(x + y + z)/2+1 и пип2(хуг)/2 + 1.
Сравнить объемы двух прямоугольных параллелепипедов, заданных своими измерениями.
Даны вещественные числа р и q. Вычислить:
с =
d=c(p + q).

a=pq2; b=p2+pq;
а(а - Ь), если а > Ь; а3, если а = Ь;
Р-Я,
Найти сумму большего и меньшего из трех заданных чисел.
По длинам сторон имеющихся треугольников распознать прямоугольные. Если таковых нет, вычислить угол С.
Найти max{min(o, b), min(c, d)}.
Даны три числа а, Ь, с. Определить, какое из них равно d. Если ни одно из них не равно d, то найти шах(</ - a, d - b, d - с).
Даны четыре точки А^хиух), А2(х2, у2), Л3(х3,у3), А4(х4,у4). Определить, будут ли они вершинами параллелограмма.
Даны три точки А(хьу\), В(х2,у2) и С(х3, у3). Определить, будут ли они расположены на одной прямой. Если нет, то вычислить угол АВС.
Даны действительные числа а, Ь, с. Удвоить эти числа, если а> Ь> с, и заменить их абсолютными значениями, если это не так.
На оси ОХ расположены три точки а, Ь, с. Определить, какая точка b или с расположена ближе к точке а.
Даны три положительных числа а, Ь, с. Проверить, будут ли они сторонами треугольника. Если да, вычислить площадь этого треугольника.
Решить уравнение ах3 + Ьх= 0 для произвольных чисел а и Ь.
У1. Дан круг с радиусом R. Определить, поместится ли правильный треугольник со стороной а в этом круге.
Даны числа х, у, z. Найти значение выражения
ц _ шах2(х, у, z) - 2х min(x, у, z) sin 2х + max(x, у, z) / min(x, у, z)
Дано число х. Напечатать в порядке возрастания значения sin х, cos х, In х. Если при каком-либо х некоторые из этих выражений не имеют смысла, вывести сообщение об этом и сравнить значения, имеющие смысл.
Даны размеры А, В прямоугольного отверстия и размеры х, у, z кирпича. Определить, пройдет ли кирпич через это отверстие.
Перевести значения величин из радианной меры в градусы или наоборот, выполнив запрос, какой перевод следует осуществить.
Два прямоугольника, расположенные в первом квадранте, со сторонами, параллельными осям координат, заданы координатами своих левого верхнего и правого нижнего углов. Для первого прямоугольника это точки с координатами (хь у,) и (х2,0), для второго —(х3, Уз), (x*, 0). Определить, пересекаются ли данные прямоугольники, и вычислить площадь их общей части, если они пересекаются.
В небоскребе N этажей и всего один подъезд. На каждом этаже по три квартиры. Лифт может останавливаться только на нечетных этажах. Человек входит в кабину лифта и набирает номер необходимой ему квартиры М. Определить, на какой этаж лифт должен доставить пассажира?
По трем заданным числам определить, является ли сумма каких-либо двух из этих чисел положительной.
Известно, что одно из четырех чисел аи а2, а3 и а4 отлично от трех других, равных между собой. Присвоить номер этого числа переменной п.
Проверить, не приводит ли суммирование двух целых чисел А и В к переполнению (т.е. к результату больше, чем 32 767). Если переполнение будет, сообщить об этом, в противном случае вывести сумму этих чисел.
Определить по паролю степень доступности сотруднику секретной информации, если доступ к базе данных имеют шесть человек, разбитых на три группы по степени доступа и имеющих следующие пароли: 9 583, 1 747, обеспечивающие доступ к модулям А, В, С базы; 3 331, 7 922 — к модулям В, С базы; 9 455, 8 997 — к модулю С базы.
Реализовать эпизод применения компьютера в книжном магазине: компьютер запрашивает стоимость книг и сумму, внесенную покупателем, если сдача не требуется, печатает на экране «спасибо»; если денег внесено больше, печатает «возьмите сдачу» и указывает ее сумму; если денег недостаточно, печатает об этом сообщение и указывает размер недостающей суммы.
49.1 В ЭВМ поступают результаты соревнований по плаванию трех спортсменов. Выбрать лучший результат и вывести его на экран с сообщением, что это результат победителя заплыва.
Определить взаимное расположение точки с координатами (хо, Уо) и окружности с радиусом R и центром в точке (xi,yi).
По координатам вершин четырехугольника определить, выпуклый он или нет.
По номеру дня вычислить число и месяц невисокосного года.
Два круга заданы координатами своих центров и радиусами — соответственно уь г{ и х2, у2, г2. Определить, пересекаются ли эти круги.
Даны два целых числа: год и номер месяца. Определить: полугодие (первое или второе), квартал (первый, второй, третий или четвертый), время года (зима, весна, лето или осень), столетие, тысячелетие, високосный ли это год.
На плоскости заданы координаты вершин четырехугольника. Определить, является ли он ромбом, параллелограммом, прямоугольником, квадратом.
Определить, площадь полной поверхности какой из двух треугольных пирамид, заданных ребрами, больше и на сколько.
Даны действительные числа а, Ь, с(а> 0). Полностью исследовать биквадратное уравнение ахА + Ах2 + с = 0, т. е. если действительных корней нет, должно быть выдано соответствующее сообщение, в противном случае следует найти действительные корни и сообщить, сколько из этих корней являются различными.
Дана точка А(х, у). Определить, принадлежит ли она треугольнику с вершинами, имеющими координаты (хь у^, (х2,у2), (*з, 3>з)-
Определить, будут ли прямые Atx+ Bty + Q = 0 и А2х + В^у + + С2 = 0 перпендикулярны. Если нет, то найти угол между ними.
Наименьшее из трех попарно различных действительных чисел X, Y, Z, если их сумма меньше единицы, заменить полусуммой двух других. В противном случае заменить меньшее из чисел X, Y полусуммой двух оставшихся чисел.
Решить следующую систему линейных уравнений:
Q\X + t\y = с,,
а2х + 1>2У = с2.
Даны три положительных числа. Определить, можно ли построить треугольник с длинами сторон, равными этим числам. Если можно, ответить на вопрос, является ли он остроугольным.
(1 - sin 4А cos(A2 +18))2 ’

с = ah2 sin bh + АА3 cos ah.
Дано действительное число А. Определить, имеет ли уравнение ах2 + Ьх+с= 0 действительные корни, при
Найти действительные корни или сообщить об их отсутствии.
Даны координаты вершин прямоугольника: fo, у,), (х2, у2), (х3, уз), (х4, у4). Определить площадь части прямоугольника, расположенной в 1-й координатной четверти.
Найти координаты точек пересечения прямой у=кх+Ь и окружности с радиусом R и центром в начале координат. Определить, в каких координатных четвертях находятся точки пересечения. Если точек пересечения нет или прямая касается окружности, должно быть выдано соответствующее сообщение.
Дана точка А(х, у). Определить, принадлежит ли она прямоугольнику с вершинами, имеющими координаты (xi.yj), (х2,у2), (*з> Уз), (*4,У4>-
Вычислить значения следующих функций:
1. F(x) =
x2 - 3x + 9 при x < 3; 1
,x3 +6
при x > 3.
2. F{x) =
3. Fix) =
4. F(x) =
5. Fix) =
6. Fix) =
7. Fix) =
8. F(x) =
9. Fix) =
-x2 + 3x + 9 при x > 3;
x,
при x < 3.
x3-6 9 при x < -3; при x > -3.
lx2 +1
0 при х < 1;
1 . при X > 1.
х + 6 -Зх + 9 при х < 7; ^ при х > 7.
U-7 Зх - 9 при х < 7; * при х > 7.
х2 -4
х2 при 0 < х < 3;
4 при х > 3 или х < 0.
Гх2+4х + 5 при х < 2;
1
х2 + 4х + 5
при х > 2.
Xх -X
при 0 < х < 1;
10. Fix) =
х2 - sin ях2 при х > 1 или х < 0.
-х2 + х - 9 при х > 8;
1
х4-6
при х < 8.

F(x) =
F(x) =
F(x) =
F(x) =
F(x) =
F(x) =
/’(ж) =
F(x) =
F(x) =
F(x) =
f4x2 + 2x -19 при x > -3,5; 2x
-4x +1
при x < 3,5.
-x2 + 3x + 9 при x < 3; x
e2 +1
при x > 3.
-3x + 9 при x > 3; при x < 3.
lx2+8
-x3 +9 при x < 13; 3
x +1
при x > 13.
45x2 + 5 при x > 3,6; при x< 3,6.
10x2 +1 x4+9при x< 3,2;
54x4при x > 3,2.
-5x2 +7
1,2x2 - 3x - 9 при x > 3; 12,1при x < 3.
12х2 +1
x2 + 3x + 9 при x < 3;
sin x,
при x > 3
x2 -9
cos 2x + 9 при x > -4;
cosx. ,
при x < -4.
x - 9
lnx + 9 прих>0; x
~ x2 - 7
при x < 0.


-x2 — 1, Ijc + 9 при x < -3; ln(x + 3)
21. F(x) =
при > -3.
22. F(x) =
9-x4 sin3xx4 + l
при x > 1,1; при x < -1,1.
x2 +9

-x2 при x > 7;
23. F(x) =
при x < 7.
1 2~X
24. F(x) =
-x2 - 9
1_
. x2 +9
при x > 13; при x < 13.
x2 -9

Опри x < 0;
25. F(x) =
• x при 0 < х < 1; х4 при х > 0.
5.3. Тема «Оператор выбора»По заданному номеру дня недели (целому числу от 1 до 7) получить число уроков в классе в этот день.
По последней цифре заданного числа определить последнюю цифру квадрата этого числа.
По заданным году и номеру месяца т определить число дней в этом месяце.
Для каждой введенной цифры (0 — 9) вывести соответствующее ей название на английском языке. Например: 0 — zero, 1 — one, 2 — two и т.д.
По заданному числу (1 — 12) вывести название соответствующего месяца.
Получить словесное описание школьных отметок: 1 — плохо,
— неудовлетворительно, 3 — удовлетворительно, 4 — хорошо, 5 — отлично.
Пусть элементами круга являются: 1 — радиус, 2 — диаметр,
— длина окружности. По заданному номеру элемента выполнить запрос соответствующего значения и вычислить площадь круга.
Пусть элементами прямоугольного равнобедренного треугольника являются: 1 — катет а\ 2 — гипотенуза Ь; 3 — высота, опущенная из вершины прямого угла на гипотенузу Л; 4 — площадь S. По заданным номеру и значению соответствующего элемента вычислить значения всех остальных элементов треугольника.
По заданному номеру месяца получить название следующего за ним месяца. Например: при т = 1 получим февраль.
По введенному номеру времени года (1 — зима, 2 — весна, 3 — лето, 4 — осень) получить соответствующие этому времени года месяцы и число дней в каждом месяце.
В старояпонском календаре был принят двенадцатилетний цикл, годы внутри которого назывались соответственно: крыса, корова, тигр, заяц, дракон, змея, лошадь, овца, обезьяна, курица, собака и свинья. По введенному номеру некоторого года получить его название по старояпонскому календарю. (Для справки: 1996 г. — год крысы и начало очередного цикла.)
Для целого числа к от 1 до 99 напечатать фразу «Мне к лет», учитывая при этом, что при некоторых значениях А: слово «лет» надо заменить на слою «год» или «года». Например: 11 лет, 22 года, 51 год.
По введенному номеру единицы измерения (1 — дециметр, 2 — километр, 3 — метр, 4 — миллиметр, 5 — сантиметр) и длине отрезка L получить соответствующее значение длины отрезка в метрах.
По введенному числу от 1 до 11 (номеру школьного класса) получить соответствующее сообщение: «Привет, А-классник». Например: если к= 1, получить сообщение «Привет, первоклассник»; если к = 4 — «Привет, четвероклассник».
По введенному числу от 1 до 12 (номеру месяца) получить все приходящиеся на этот месяц праздничные дни. Например, если введем число 1, получим следующие праздничные дни: 1 января — Новый год, 7 января — Рождество).
Дано натуральное число N. Если оно делится на четыре, вывести на экран N= 4к (где к — соответствующее частное); если остаток от деления на четыре равен единице — N=4k+\\ если остаток от деления на четыре равен двум — N- 4А + 2; если остаток от деления на четыре равен трем — А=4А + 3. Например: 12 = 4-3, 22 = 4-5 + 2.
Имеется пронумерованный список деталей: 1 — шуруп, 2 — гайка, 3 — винт, 4 — гвоздь, 5 — болт. По номеру детали вывести на экран ее название.
По последней цифре заданного числа определить последнюю цифру куба этого числа.
Для любого натурального числа напечатать количество цифр в записи этого числа.
Даны два действительных положительных числа хну. Арифметические действия над числами пронумерованы: 1 — сложение, 2 — вычитание, 3 — умножение, 4 — деление. По введенному номеру выполнить соответствущее действие над этими числами.
По введенному номеру единицы измерения (1 — килограмм,
— миллиграмм, 3 — грамм, 4 — тонна, 5 — центнер) и заданной массе М получить соответствующее значение массы в килограммах.
Пусть элементами равностороннего треугольника являются: 1 — сторона а; 2 — площадь S; 3 — высота А; 4 — радиус вписанной окружности г; 5 — радиус описанной окружности R. По заданным номеру и значению соответствующего элемента вычислить значения всех остальных элементов треугольника.
Определить подходящий возраст кандидатуры для вступления в брак, используя следующее соображение: возраст девушки должен быть равен половине возраста мужчины плюс 7, а возраст мужчины должен определяться соответственно как удвоенный возраст девушки минус 14.
Определить произведение цифр заданного Ar-значного числа
(1 < к<4).
Прочитать натуральное число в десятичном представлении, а на выходе получить это же число в десятичном представлении и его словесное описание. Например: 204 — двести четыре.
Вычислить номер дня в невисокосном году по заданным числу и месяцу.
Робот может перемещаться в четырех направлениях (С — север, 3 — запад, Ю — юг, В — восток) и принимать три цифровые команды (0 — продолжать движение, 1 — повернуть налево, -1 — повернуть направо). Заданы исходное направление перемещения робота — С и команда — число N. Вывести направление перемещения робота после выполнения полученной команды.
Локатор ориентирован на одну из сторон света (С — север,
— запад, Ю — юг, В — восток), может принимать три цифровые команды (1 — поворот налево, -1 — поворот направо, 2 — поворот на 180°). Заданы исходная ориентация локатора — С и две команды — числа Nt и N2. Вывести ориентацию локатора после выполнения полученных команд.
Тема «Циклы»Циклы с заданным числом повторенийИмеется серия измерений элементов треугольника. В серии в произвольном порядке могут встречаться следующие группы элементов треугольника: 1 — основание и высота, 2 — две стороны и угол [рад] между ними, 3 — три стороны.
Запросить номер группы элементов, ввести соответствующие элементы и вычислить площадь треугольника. Вычисления прекратить, когда в качестве номера группы будет введен нуль.
Начав тренировки, спортсмен в первый день пробежал 10 км. Каждый день он увеличивал дневную норму на 10% от нормы предыдущего дня. Определить, какой суммарный путь пробежит спортсмен за S дней.
Одноклеточная амеба каждые три часа делится на две клетки. Определить, сколько амеб будет через 3, 6, 9, 12, ..., Ъп часов.
Около стены наклонно стоит палка длиной х [м]. Один ее конец находится на расстоянии у [м] от стены. Определить угол а между палкой и полом для значений х=к [м] и у, изменяющегося от 2 до 3 м с шагом h [м].
У гусей и кроликов вместе 64 лапы. Сколько может быть кроликов и сколько гусей (указать все возможные сочетания)?
Составить алгоритм решения следующей задачи: сколько можно купить быков, коров и телят, платя за быка 10 р., за корову — 5 р., а за теленка — 0,5 р., если на 100 р. надо купить 100 голов скота?
Доказать или опровергнуть гипотезу (перебором всех возможных сочетаний значений), что для любых величин А, В, С типа Boolean следующие пары логических выражений имеют одинаковые эквивалентные значения:
а)A OR В и В OR А;
б)A AND В и В AND А;
в)(A OR В) OR С и A OR С;
г)(A AND В) AND Си A AND (В AND С);
д)A AND (A OR В) и А;
е)A OR (A AND В) и А;
ж)A AND (В OR С) и (A AND В) OR (A AND С);
з)A OR (В AND С) и (A OR В) AND (A OR С).
Проверить утверждение о том, что результатами вычислений по формуле х2 + х+ 17 при 0 <х< 15 являются простые числа. Все результаты вывести на экран.
Проверить утверждение о том, что результатами вычислений по формуле х2 + х+41 при 0 < х < 40 являются простые числа. Все результаты вывести на экран.
<х< 28.
11. Создать простые числа на основе формулы
<х< 36.
Создать простые числа на основе формулы 2х2+29 при
при
22х+1 +13
Создать числа Пифагора а, Ь, с (с2 = а2 + Ь2) на основе формул а = т2 - п2, Ь = 2тп, с = т2 + п2 (где т,п— натуральные числа; 1 <т< к; 1 <п<к; к — заданное число). Результат вывести на экран в виде таблицы из пяти столбцов: т, п, а, Ь, с.
Покупатель должен заплатить в кассу сумму S рублей. У него имеются купюры достоинством 10, 50, 100, 500, 1000 и 5 000 р. Определить, сколько купюр разного достоинства отдаст покупатель, если начнет платить с самых крупных.
Ежемесячная стипендия студента составляет сумму А рублей, а расходы на проживание превышают стипендию и составляют сумму В рублей в месяц. Рост цен ежемесячно увеличивает расходы на 3 %. Рассчитать сумму, которую следует единовременно попросить у родителей, чтобы прожить учебный год (10 месяцев), используя только эти деньги и стипендию.
Напечатать таблицу умножения и сложения натуральных чисел в десятичной системе счисления.
Напечатать таблицу умножения и сложения натуральных чисел в шестнадцатеричной системе счисления.
Найти сумму всех w-значных чисел (1 < п < 4).
Найти сумму всех и-значных чисел, кратных А: (1 < п < 4).
Показать, что для всех п= 1, 2, 3,..., N
(15 + 25+ ... + я5) + (17 + 27 + ... + л7) = 2(1 + 2+ ... +л)4.
В следующем выражении заменить буквы цифрами таким образом, чтобы соотношение цифр оказалось верным (одинаковым буквам должны соответствовать одинаковые цифры, разным буквам — разные цифры):
ХРУСТ ГРОХОТ = РРРРРРРРРРР.
Запрашивать пароль (например, четырехзначное число) до тех пор, пока он не будет правильно введен.
Найти наибольшее значение отношения трехзначного числа к сумме его цифр.
Вычислить сумму кодов всех символов, которые в цикле вводятся с клавиатуры до нажатия клавиши ESC.
Вычислить количество точек с целочисленными координатами, находящихся в круге с радиусом R > 0.
Напечатать в возрастающем порядке все трехзначные числа, в десятичной записи которых нет одинаковых цифр, не используя операции деления и нахождения остатка от деления.
Вывести на дисплей календарь на 2000 год.
Составить алгоритм решения ребуса РАДАР = (Р+ А + Д)4 (здесь различные буквы означают различные цифры, а первая буква — не 0).
Составить алгоритм решения ребуса МУХА + МУХА + МУХА = СЛОН (здесь различные буквы означают различные цифры, а первая буква — не 0).
Составить алгоритм решения ребуса ДРУГ - ГУРД = 2727 (здесь различные буквы означают различные цифры, а первая буква — не 0).
Составить алгоритм решения ребуса КОТ + КОТ = ТОК (здесь различные буквы означают различные цифры, а первая буква — не 0).
Имеется некоторое значение функции косинус. Указать соответствующие этому значению аргументы, принадлежащие отрезку [а; Ь\.
Суммы и произведения числовых последовательностей
Дано натуральное число N. Вычислить
2 4 82"
1
1
1
Дано натуральное число N. Вычислить
sin 1 sin 1 + sin 2
sin 1 +sin 2 + -- +sin TV
Дано натуральное число N. Вычислить произведение первых N сомножителей выражения
-2462TV
^ = ТТ-Х...Х
3 5 7 2TV + 1
Дано натуральное число TV. Вычислить выражение
cosl cosl + cos2 cosl + cos2 + ... + cosTV
X х.
sin 1 sin 1 + sin 2sinl + sin2 + ... + sinTV
Дано действительное число x. Вычислить выражение
X3 Xs X7 X9 X11X13
*~ зУ + ~5\~7Т + 9Г~Тп + Тз!■
Даны натуральное число п и действительное число х. Вычислить
S= sin х + sin sin х + • • • + sin sin... sin x.
>- ^ ■>п раз
Даны действительное число а и натуральное число п. Вычислить
Р = а(а + 1)х...х(а + п-1).
Даны действительное число а и натуральное число п. Вычислить
Р = а(а - п)(а - 2п)х...х(а - и2).
Даны действительное число а и натуральное число п. Вычислить

Дано действительное число х. Вычислить выражение
(х - 1)(х - 3)(х - 7) х... х (х - 63) (х - 2)(х - 4)(х - 8) х... х (х - 64) ’
Вычислить выражение
(1 +sin0,l)(l + sin0,2)x...x(l + sinl0).
Даны натуральное число п и действительное число х. Вычислить выражение
sinx + sinx2 + ... + sinx".
Дано натуральное число п. Вычислить
5 = 1 • 2 + 2-3-4 + ... + п(п + 1)х...х2л.
Дано натуральное число п > 2. Вычислить

Дано натуральное число п. Вычислить

Дано натуральное число п > 1. Вычислить
5 = 1! + 2! + 3! + ... + я! .
Дано натуральное число п. Вычислить

Вычислить по схеме Горнера
у = х10 + 2х9 +3х8 + ... + 10х +11.
Числа Фибоначчи (f„) определяются формулами f0 =f{ = 1 и - fn-1 +Л-2 при п = 2, 3, ... Найти fp.
Дано натуральное число п. Вычислить у = 1 • 3 • 5 х... х (2л - 1).
Дано натуральное число я. Вычислить у = 2 • 4 • 6 х... х (2л).
Вычислить у = cosx + cosx + cos* + ... + cos*".
Вычислить у = sin 1 + sin 1,1 + sin 1,2 + ... + sin 2.
Даны натуральные числа л и к. Вычислить выражение
Jk + ^2к + • • • + у]к(п -1) + 4кп .
Дано натуральное число л. Вычислить выражение
234 л +1
—I—I—(- —I-.
123л
Среди первых к членов последовательности х„ = sin л + 3 cos 2л найти минимальный.
Итерационные циклы
Дан числовой ряд и некоторое число е. Найти сумму тех членов ряда, модуль которых больше или равен заданному числу е, если общий член этого ряда имеет следующий вид:
II
т б) 1
2л-1 г) /у —
а" " 2л ’ ап ~
(3 п-
о|*
II е) л!
а„ =
(2л)!
II
\|?- з) 2ял!
— п Пп
Зял!
S] — • к) п\
/7 — . •
Л"(2л)!’ " Зя” ’
л!
/7 — • м) 2я
""(г*)!’ в""(л-1
х2п+\
/7 — __ " (2л+ 1)!' 1
а)а„ = arctga„_ 1, а, = 0;
б)о„ = 2 + —, а, = 2;
ап-1
в)an=^tga„_{, о, =0,5;
(2л)2 ’
г> ап =
2 +а,
е) а„ = ~ ' ■" 1, О! =2;
2а,
Л-1
д) an=-cosa„_„ о, =0,5;

ж) Дя = а"~' *°л~2, а, =1,а2 = 2;
Я
In п
з)а« = /1
(In л)"
и)ап=е-в"-\ а, = 0;
к)а„=-4-, 01=*-
2a„_i
Найти для указанных последовательностей наименьший номер элемента, для которого выполняется условие М и вывести на экран этот номер и все элементы а, (где /= 1, 2, ..., л):
а)
б)
в)
г)
1Г 2 |
а„ = - а„_ 1 + , а, = 1, М: | а2 - 21< е;
Ч fl-'J588 п'М: !а"|<£5п\
°п = М: |ал| < £‘
Табулирование функций
Вычислить значения следующих функций F(x) на отрезке 1 а, Ь\ с шагом h, представив результат в виде таблицы, первый столбец которой — значения аргумента, второй — соответствующие значения функции:
7. F(x) = x sin x.
(\
9. F(x) - x cos —
1+2.
8. F(x) = sin
1
x
10. 2 sin2x+ 1.
+ 2.
J
F(x) = x - sinx.
F(x) = 2 cosx- 1 5. F(x) - ctgx+ 1.
F(x) = sin2x.
F(x) = tgx.
6. F(x) = sinx - cosx.
11. F(x) = -Jx cos2 x.
13. F(x) = cosx + ctgx.
15. F(x) = tg ^ + 2 cos x.
17. F(x) = -sin —+ 1.
4
19. F(x) = x2sin2x + 1
21. F(x) - sin2x - cos 2x. 23. F(x) = -cos 2x.
25. F(x) = sinx + 0,5cosx.
12. F(x) = sinx+ tgx.
14. F(x) = 2tg| + 1.
16. F(x) = ctg ^ ^ sin x.
2
18. F(x) = 2 cos \fx +0,5.
20. F(x) = ^ctg^ + 4.
22. F(x) = 7 sin2 x - ^ cos x.
2
24. F(x) = tg 2x - 3.
26. F(x) =
cosx
Ввод и обработка последовательностей
Найти сумму элементов последовательности.
Найти минимальный элемент в последовательности.
Найти второй по значению элемент в последовательности.
Определить, сколько раз в последовательности встречается заданное число.
Известно сопротивление каждого из элементов электрической цепи, все элементы которой соединены параллельно. Определить общее сопротивление этой цепи.
Найти произведение элементов последовательности.
Найти сумму модулей элементов последовательности.
Определить, сколько соответствующих элементов двух последовательностей с одинаковым числом элементов совпадают.
Вычислить сумму квадратов элементов последовательности.
Определить среднее арифметическое элементов последовательности.
Определить среднее геометрическое элементов последовательности, содержащей положительные числа.
Найти произведение модулей элементов последовательности.
Даны натуральное число п и вещественные числа ah а2,а„. Определить
а)а1 + аъ a-i + а3, ..., а„_\ + а„;
б)а, - а2 + аъ - ... + (-1)п+1а„;
.0\ ■ flj Х...Хfl/i-l ,v
в) —£— (где п __ четное число);
а2 аА х...хап
—flj ——,,, —
г) (где п— четное число).
&2 + Я4 +... + ап
Определить, сколько раз встречается минимальный элемент и последовательности.
Определить, сколько раз встречается максимальный элемент в последовательности.
Выбрать максимальный из модулей элементов последовательности.
Определить, сколько нулей в последовательности.
Осуществляя ввод элементов последовательности до тех пор, пока не будет введено заданное число, подсчитать их количество.
Напечатать True, если элементы последовательности упорядочены по возрастанию, и False — в противном случае.
В последовательности натуральных чисел подсчитать количество чисел, оканчивающихся заданной цифрой.
В заданной последовательности определить максимальное количество подряд идущих положительных чисел.
Найти сумму тех членов последовательности, которые оканчиваются на заданную цифру.
Найти сумму четных элементов последовательности целых чисел.
Определить количество нечетных отрицательных элементов и последовательности целых чисел.
Указать минимальный нечетный элемент в последовательности, содержащей целые числа.
Найти сумму номеров отрицательных элементов последовательности, в которой нумерация элементов начинается с единицы.
Определить количество ненулевых элементов последовательности.
Найти разность максимального и минимального элементов последовательности.
Определить, между какими степенями двойки расположены все положительные элементы последовательности.
Вывести на экран -1, если сумма элементов последовательно- т I и отрицательная, 1 — если положительная и 0 — если равна нулю.
Вводятся произвольные целые числа. Определить:
а)количество четных чисел, введенных до ввода числа, кратного к;
б)сумму первых к положительных чисел;
в)среднее геометрическое первых к положительных нечетных чисел.
Вводятся произвольные символы. Определить:
а)количество русских букв до появления первой латинской;
б)есть ли среди первых к введенных символов хотя бы одна цифра.
Найти наибольший общий делитель последовательности натуральных чисел.
Определить, сколько раз меняется знак в последовательности чисел, отличных от нуля.
Определить, сколько пробелов в заданной последовательности символов.
Тема «Целочисленная арифметика»
Уровень сложности А
Дано натуральное число л. Найти сумму первой и последней цифр этого числа.
Дано натуральное число л. Переставить местами первую и последнюю цифры этого числа.
Даны два натуральных числа m и п (т < 9 999, я < 9 999). Проверить, есть ли в записи числа т цифры, одинаковые с цифрами в записи числа л.
Дано натуральное число я (л < 9 999). Проверить, есть ли в записи этого числа три одинаковые цифры.
Дано натуральное число я < 99. Дописать в конце и в начале этого числа цифру к.
Даны натуральные числа пик. Проверить, есть ли в записи числа пк цифра т.
Среди всех л-значных чисел указать те из них, сумма цифр которых равна заданному числу к.
Даны три натуральных числа А, В, С, обозначающие число, месяц и год. Найти порядковый номер даты, начав отсчет с начала года.
Найти наибольшую и наименьшую цифры в записи заданного натурального числа.
Произведение я первых нечетных чисел равно р. Определить, сколько сомножителей взято для его получения и если введенное число я не является указанным произведением, сообщить об этом.
Найти в интервале [я; т\ натуральное число, имеющее наибольшее количество делителей.
Задумано некоторое число х < 100. Известны числа к, т,п — остатки отделения этого числа соответственно на 3, 5, 7. Найти х.
Игрок А объявляет двухзначное число от 01 до 99. Игрок В меняет местами цифры, объявленные игроком А, и прибавляет полученное число к сумме цифр его числа. Полученный результат он объявляет игроку А, который проделывает с этим числом ту же процедуру. Игроки продолжают поочередно объявлять двух- значеные числа, беря для этого остаток от деления каждого полученного результата на 100. Определить, какие числа может объявить игрок А на начальном шаге, чтобы игрок В в некоторый момент объявил число 00.
Дано натуральное число N. Найти и вывести все числа в интервале от 1 до N- 1, у которых сумма цифр совпадает с суммой цифр заданного числа. Если таких чисел нет, вывести слово «нет». Например: при N= 44 выводятся числа 17, 26 и 35.
Дано натуральное число N. Найти и вывести все числа в интервале от 1 до N- 1, у которых произведение цифр совпадает с суммой цифр заданного числа. Если таких чисел нет, вывести на экран слово «нет». Например: при N- 44 выводятся числа 18 и 24.
Дано натуральное число N. Определить количество восьмизначных чисел, сумма цифр в записи которых меньше, чем N. Если таких чисел нет, вывести на экран слово «нет».
Дано натуральное число N. Определить количество восьмизначных чисел, сумма цифр в записи которых больше, чем N. Если таких чисел нет, вывести на экран слово «нет».
Дано натуральное число N. Найти наибольшее число М> 1, на которое сумма цифр в записи числа ТУ делится без остатка. Если такого числа нет, вывести слово «нет». Например: N= 12 345, М= 5. Здесь сумма цифр числа N, равная 15, делится без остатка на 5.
Дано натуральное число N. Найти наименьшее число N<M<2N, которое делится на сумму цифр числа N без остатка. Если такого числа нет, вывести слово «нет». Например: N= 12 345, М= 12 360. Здесь число 12 360 делится без остатка на число 15.
Дано натуральное число N> 9. Определить количество нулей, идущих подряд в младших разрядах этого числа. Например: и числе N= 1 020 000 количество таких нулей — четыре.
Дано натуральное число N> 9. Определить количество нулей к старших разрядах этого числа. Например: в числе N = 10025 000, два нуля в старших разрядах.
Дано натуральное число N>9. Определить сумму цифр первой половины этого числа (старших разрядов). Например: в числе /V= 12345678 эта сумма 1 + 2 + 3 + 4=10.
Дано натуральное число N> 9. Определить сумму цифр во второй половины этого числа (младших разрядов). Например: в числе N= 12 345 678 эта сумма 5 + 6 + 7 + 8 = 26.
Дано натуральное число N. Если это число содержит три цифры, получить новое число М посредством перестановки его первой и последней цифр. Например: если 7V= 123, то Л/=321. Определить, при каком количестве цифр в числе М=К
Дано натуральное число N. Если это число содержит пять цифр, получить новое число Мпосредством исключения его средней цифры. Например: если N= 12 345, то М- 1 245. Определить, при каком количестве цифр в числе M=N.
Женщина шла на базар продавать яйца. Ее случайно сбил с ног мужчина, в результате чего все яйца разбились. Мужчина предложил оплатить убытки и спросил: сколько у нее было яиц? Женщина сказала, что точного числа не знает, но когда она брала яйца парами, то осталось одно яйцо. Одно яйцо останется также, если она будет брать по 3, 4, 5 и 6 яиц, но если брать по 7 штук, то в остатке ничего не останется.
Определить, какое минимальное число яиц могло быть в корзине.
Уровень сложности В
Дано натуральное число л. Проверить, все ли цифры в этом числе различные.
Найти целые корни уравнения ах3 + bx2 + сх+ d=0, где а, Ь, с, d— заданные целые числа, причем а*0 и d*0. (Целыми корнями могут быть только положительные и отрицательные делители коэффициента d.)
Дано натуральное число л. Поменять порядок следования цифр в этом числе на обратный или сообщить, что это невозможно в силу переполнения.
Найти все делители натурального числа л.
Натуральное число М называется совершенным, если оно равно сумме всех своих делителей, включая единицу, но исключая само это число. Напечатать все совершенные числа, которые меньше заданного числа N.
Натуральные числа а, Ь, с называются числами Пифагора, если выполняется условие а2 + Ь2 = с2. Напечатать все числа Пифагора, которые меньше N.
Дано натуральное число л. В ряду 1, ..., л найти числа, совпадающие с последними цифрами в записи их квадратов. Например: 62 = 36, 252 = 625.
По номеру дня в году вывести число и месяц в общепринятой форме. Например: 33-й день года — это 2 февраля.
Долгожитель в возрасте не менее 100 лет обнаружил однажды, что если к сумме квадратов цифр его возраста прибавить число дня его рождения, то как раз получится его возраст. Определить, сколько лет долгожителю.
Дано целое число п> 2. Напечатать все простые числа из интервала [2; л].
Найти наименьшее натуральное число л, которое можно представить в виде суммы кубов двух натуральных чисел.
Даны натуральные числа пит. Найти натуральные числа, меньше п, квадрат суммы цифр которых равен т.
В интервале [2; п\ определить число с максимальной суммой делителей.
Даны натуральные числа р и q. Получить делители числа q взаимно простые с числом р.
Для заданных натуральных чисел пик определить, равно ли число п сумме к-х степеней своих цифр.
Найти все и-значные числа, сумма квадратов цифр которых кратна М.
Найти все натуральные числа, не превосходящие заданного числа п, которые делятся на каждую из своих цифр.
Дано натуральное число п. Найти количество натуральных чисел, не превышающих и и не делящихся на числа 2, 3 и 5.
Пусть/, — это п-й член последовательности, определяемой следующим образом:
fn = ~fn-\ ~ Zfn-ъ Л - 1; h- ~1-
Показать, что 2"+1 - 7/л2_, есть полный квадрат.
Последовательность Хэмминга образуют натуральные числа, не имеющие других простых делителей кроме 2, 3 и 5. Найти:
а)первые N членов этой последовательности;
б)сумму первых N членов последовательности;
в)N-й член последовательности по заданному номеру N;
г)первый член, больший заданного числа М, а также номер •того члена в последовательности;
д)сумму всех членов последовательности от номера У до номера М.
В интервале [2, п) найти все натуральные числа, сумма цифр которых при умножении на число а не изменится.
Удалить из десятичной записи числа N единиц, сохранив порядок следования оставшихся цифр. Сформировать и напечатать полученное число.
Школа находится на одной стороне улицы с домом Петра. Однажды по дороге в школу он стал складывать номера домов, мимо которых проходил по своей стороне улицы, начиная с номера своего дома. При сумме номеров домов, равной 99, Петр перешел через поперечную улицу и начал складывать номера домов второго квартала. При сумме номеров домов, равной 117, он перешел еще одну поперечную улицу и стал складывать номера домов третьего квартала. Эта сумма оказалась равной 235, включая номер нома школы. Определить номер дома Петра и номер дома школы.
Дано натуральное число N. Определить количество цифр в ишиси заданного числа, имеющих наименьшее значение. Например: в числе /V=4 548 две цифры с наименьшим значением, т.е. дне цифры 4.
Дано натуральное число N. Определить количество цифр в записи заданного числа, имеющих наибольшее значение. Например: в числе N= 1 808 две цифры с наибольшим значением, т.е. две цифры 8.
Дано натуральное число N. Получить новое число М посредством замены последней цифры числа N наименьшей цифрой в его записи. Например: если N= 128 452, то М= 128 451.
Дано натуральное число N. Получить новое число М посредством замены последней цифры числа N наибольшей цифрой в его записи. Например: если N= 128452, то М= 128458.
Определить количество Л/-значных натуральных чисел, у которых сумма цифр, стоящих в нечетных разрядах, равна N. Например: если 1 < N< 30, то 0 < М< 5.
Вычислить сумму натуральных чисел в интервале [а; Ь], в запись которых входит цифра к.
Построить для заданного числа п > 1 последовательность Хейса следующим образом. Если число п четное, разделить его на 2, в противном случае умножить на 3 и прибавить 1. Если полученное при этом число не равно 1, то эти действия повторять до тех пор, пока не получится 1. Указать наибольшее число в полученной последовательности (вершину) и количество шагов.
Определить, входит ли заданная цифра р в десятичную запись числа, заданного в системе с основанием q (2 й q й 9).
Уровень сложности С
Дано натуральное число к. Напечатать А:-ю цифру последовательности 12345678910111213..., содержащую подряд все натуральные числа.
Дано натуральное число к. Напечатать к-ю цифру последовательности 149162536..., содержащую подряд квадраты всех натуральных чисел.
Перевести заданное натуральное число из десятичной системы счисления в двоичную.
Перевести заданное натуральное число п в шестнадцатеричную систему счисления.
Дано натуральное число п. Переставить его цифры таким образом, чтобы из них образовалось максимальное число.
Дано натуральное число п. Переставить его цифры таким образом, чтобы из них образовалось наименьшее число.
Для записи римских цифр используют символы I, V, X, L, С, D, М, обозначающие соответственно числа 1, 5, 10, 50, 100, 500, 1 000. Перевести запись любого заданного арабскими цифрами числа п < 3 999 в запись римскими цифрами.
Используя все цифры от 1 до 9 по одному разу в различных комбинациях и операции сложения и вычитания, получить в результате число 100.
Используя все цифры от 1 до 9 по одному разу и операции сложения и вычитания, получить в результате число 100 при условии, что цифры появляются в возрастающем или убывающем порядке. Например: 123 + 4 - 5 + 67 - 89 = 100; 9-8 + 76-5 + 4 + + 3 + 21 = 100.
Определить, является ли заданное натуральное число палиндромом.
Найти целые числа, при возведении в квадрат которых получают палиндромы. Например, 262 = 676.
Найти целые числа палиндромы, при возведении в квадрат которых также получают палиндромы. Например: 222 = 484.
Найти целые числа, при возведении в третью, четвертую или пятую степень которых получают палиндромы. Например: 113 = = 1 331.
Дано натуральное число п. Если это не палиндром, реверсировать его цифры и сложить исходное число с числом, полученным в результате реверсирования. Если полученная при этом сумма не палиндром, повторять указанные действия до тех пор, пока не получится палиндром. Например, для исходного числа 78 запишем: 78 + 87 = 165; 165 + 561 = 726; 726 + 627 = 1 353; 1 353 + 3 531 = 4 884.
Целое число можно представить как сумму его частей, называемых разбиениями. Например, число 4 можно представить следующим образом: 4; 3 + 1; 2 + 1 + 1; 2 + 2; 1 + 1 + 1 +1. Тогда, обозначив через Р(п) количество разбиений числа п, можно записать Р(4) = 5. Для заданного числа п выполнить его разбиения и определить Р(п).
Дано натуральное число к. Напечатать к-ю цифру последовательности 24681012141618202224262830..., содержащую подряд все натуральные четные числа.
Дано натуральное число к. Напечатать к-ю цифру последовательности 1123581321..., содержащую подряд все числа Фибоначчи.
Тема «Подпрограммы»Нерекурсивные процедуры и функцииУровень сложности А
Треугольник задан координатами своих вершин. Вычислить его площадь.
НОК(ДД)
А В
НОД(Л,Я)'
Найти наибольший общий делитель и наименьшее общее кратное двух натуральных чисел, если дана формула
Найти наибольший общий делитель четырех натуральных чисел.
Найти наименьшее общее кратное трех натуральных чисел.
Найти сумму большего и меньшего из трех чисел.
Вычислить площадь правильного шестиугольника со стороной а, используя подпрограмму вычисления площади треугольника.
На плоскости заданы координатами п точек. Определить между какими из пар заданных точек самое большое расстояние. (Координаты точек занести в массив.)
В массиве Л[7У] найти второе по значению число (т.е. вывести на печать число, которое меньше максимального элемента массива, но больше всех других его элементов).
Проверить, являются ли заданные три числа взаимно простыми.
Вычислить сумму факториалов всех нечетных чисел от 1 до 9.
А С
Даны две дроби — и — (где А, В, С, D — натуральные
В D
числа). Разделить дробь на дробь и получить ответ в виде несократимой дроби.
Дан массив D. Определить следующие суммы: D[\] + D[2\ + + Z)[3]; D[3] + Z>[4] + Z>[5]; D[4] + Z)[5] + D[6]. (Составить подпрограмму вычисления суммы трех последовательно расположенных элементов массива с номерами от к до т.)
А С
Даны две дроби — и — (где А, В, С, D — натуральные числа). Умножить дробь на дробь и получить ответ в виде несократимой дроби.
А С
Даны две дроби — и — (где А, В, С, D — натуральные
В D
числа). Вычесть из первой дроби вторую и получить ответ в виде несократимой дроби.
А С
Даны две дроби — и — (где А, В, С, D — натуральные числа). Сложить эти дроби и получить ответ в виде несократимой дроби.
На плоскости заданы координатами п точек. Создать массив размером п(п - 1), элементами которого являются расстояния от каждой из точек до п - 1 других точек.
Длины сторон четырехугольника заданы числами X, Y, Z, Т. Вычислить его площадь, если угол между сторонами длиной XviY прямой.
Сформировать массив X(N), N-й член которого определяется формулой X(N) =
Вычислить сумму факториалов всех четных чисел в интервале от от до я.
Заменить отрицательные элементы линейного массива их модулями, не используя стандартную функцию вычисления модуля. Определить число произведенных замен.
Дан массив A(N). Сформировать массив В(М), элементами которого являются большие из двух рядом стоящих в массиве А чисел. Например, если массив А состоит из элементов 1, 3, 5, -2, 0, 4, 0, элементами массива В будут 3, 5, 4.
Дан массив A(N), где N— четное число. Сформировать массив В(М), элементами которого являются средние арифметические соседних пар рядом стоящих в массиве А чисел. Например, если массив А состоит из элементов 1, 3, 5, -2, 0, 4, 0, 3, элементами массива В будут числа 2; 1,5; 2; 1,5.
Дано простое число. Составить функцию, которая будет находить следующее за ним простое число.
Составить функцию для нахождения наименьшего нечетного натурального делителя к * 1 любого заданного натурального числа л.
Написать процедуру перемножения двух многочленов, заданных массивами коэффициентов, результатом которой является многочлен, заданный массивом коэффициентов.
Уровень сложности В
Дано натуральное число N. Сформировать массив, элементами которого являются цифры числа N.
Определить, в каком из двух заданных чисел больше цифр.
Заменить заданное натуральное число числом, получаемым из исходного записью его цифр в обратном порядке. Например: задано число 156, требуется получить 651.
Даны натуральные числа Ки N. Сформировать массив А, элементами которого являются числа, сумма цифр которых равна К и которые не больше N.
Даны три квадратных матрицы А, В, С «-го порядка. Вывести на печать матрицу, имеющую наименьшую норму. (Нормой матрицы называется максимальное из абсолютных значений ее элементов.)
Два натуральных числа называются дружественными, если каждое из них равно сумме всех делителей другого, кроме самого этого числа. Например, числа 220 и 284. Найти все пары дружественных чисел, которые не больше заданного числа N.
Два простых числа называются близнецами, если они отличаются друг от друга на два. Например, 41 и 43. Напечатать все пары близнецов из интервала [я; 2л], где л — заданное натуральное число больше двух.
Для заданного числа л вычислить сумму
Z. 1 1_ ,нг1q 23"' л ’
р
причем дробь — должна быть несократимой (где p,q— натуральные числа).
Для заданного числа я вычислить сумму
1
я
. 1 1
1+-+-+2 3
р
Результат представить в виде несократимой дроби — (где р, q — натуральные числа).
Натуральное число, в записи которого л цифр, называется числом Амстронга, если сумма его цифр, возведенная в степень я, равна самому числу. Найти все числа Амстронга от 1 до к.
Найти и вывести на печать все четырехзначные числа вида abed, для которых выполняется следующее условие:
а) а, Ь, с, d — разные цифры;
б) ab-cd = a + b + c + d.
Найти все простые натуральные числа, не превосходящие заданного числа л, двоичная запись которых представляет собой палиндром, т.е. читается одинаково слева направо и справа налево.
Найти все натуральные л-значные числа, цифры в которых образуют строго возрастающую последовательность. Например: 1, 2, 3, 4, 5, 6, 7, 8, 9.
Найти все натуральные числа, не превосходящие заданного числа л, которые делятся на каждую из своих цифр.
Найти числа из интервала [М; N], имеющие наибольшее количество делителей.
Для последовательности а,= 1, ап+, = а. + - напечатать
1 +а„
к-й член в виде обыкновенной несократимой дроби. Например:
Дано натуральное число л. Определить, можно ли представить это число в виде произведения трех последовательных натуральных чисел.
Имеется часть катушки с автобусными билетами. Номер билета шестизначный. Определить количество счастливых билетов на катушке, если меньший номер билета — N, а больший — М. (Билет является счастливым, если сумма трех первых его цифр равна сумме трех последних цифр.)
Определить сумму я-значных чисел, содержащих только нечетные цифры. Найти, сколько четных цифр в этой сумме.
Из заданного числа вычесть сумму его цифр. Из полученного результата также вычесть сумму его цифр и т.д. Определить, сколько требуется выполнить таких действий, чтобы получить нуль.
Разложить заданное натуральное число на простые множители. Например: 200 = 23- 52.
Дано натуральное число я. Найти все числа Мерсена меньше числа я. (Простое число называется числом Мерсена, если оно может быть представлено в виде 2Р - 1, где р — тоже простое число. Например: 31 = 25- 1.)
Дано четное число я > 2. Проверить для этого числа гипотезу Гольдбаха, т.е. предположение, что каждое четное число я представляется в виде суммы двух простых чисел.
Даны натуральные числа я и к, причем я> 1. Напечатать к десятичных знаков числа 1/я, используя только целые переменные.
Дано натуральное число я > 1. Определить длину периода десятичной записи дроби 1/я.
Функция /с натуральными аргументами и значениями определена в следующем виде: /(0) = 0, /(1) = 1, /(2л)=/(я), /(2я + 1) = /(я) + /(я + 1). Вычислить /(я) по заданному я.
В интервале [100; jV], где 210 < N< 231, найти количество чисел, составленных из цифр а, Ь, с.
Рекурсивные процедуры и функции
Используя рекурсивную подпрограмму, решить следующие задачи:
Найти сумму цифр заданного натурального числа.
Найти количество цифр в заданном натуральном числе.
Описать функцию С(т, я), где 0 < я? < я, для вычисления биномиального коэффициента С” по следующей формуле: С® = = С„л = 1; С* = С”, + С£/ при 0 < т < я.
Описать рекурсивную функцию Root (а, Ь, е), которая методом деления отрезка пополам находит с точностью е корень уравнения Дх) = 0 в интервале [а; Ь]. При этом считать, что е > 0, а < b, Да) -ДЬ) < 0 и Дх) — непрерывная и монотонная в интервале [а; b].
Описать функцию min (А") для определения минимального элемента линейного массива X, введя вспомогательную рекурсивную функцию min (к), находящую минимум среди последних элементов данного массива, начиная с £-го.
Описать рекурсивную логическую функцию Simm^, /, J), проверяющую, является ли симметричной часть строки S, начинающаяся /-м и заканчивающаяся j-м ее элементами.
Вычислить наибольший общий делитель двух натуральных чисел.
Найти число, которое образуется при записи цифр заданного натурального числа в обратном порядке. Например: для заданного числа 1234 — это число 4 321.
Перевести заданное натуральное число в р-ичную систему счисления (2 < р < 9).
Дана символьная строка, представляющая собой запись натурального числа вр-ичной системе счисления (2<р<9). Перевести это число в десятичную систему счисления.
Вычислить сумму 1! + 2! + 3! + ... + я! при я < 15. (Тип значения функции Longlnt.)
Вычислить сумму: 2! + 4! + 6! + ... + п!, где я < 16 — четное число. (Тип значения функции Longlnt.)
Дано я различных натуральных чисел. Определить все возможные перестановки этих чисел.
Описать функцию, которая удаляет из строки все лишние пробелы. (Лишними считаются пробелы, если их более двух подряд, если они стоят в конце строки после последней точки после открывающегося парного знака препинания.)
Разработать функцию для вычисления определителя матрицы порядка я (1 < я < 20).2
Найти я-ю производную f(x) = е 2, построив для fin){x) рекуррентное соотношение.
Вычислить значение многочлена
Р„(х) = d0 + dxx + d2x2 + ... + d„ xn
с вещественными коэффициентами в комплексной точке х = с + id.
Тема «Одномерные массивы»Уровень сложности А
В массив .4[iV] включены натуральные числа. Найти сумму элементов массива, кратных заданному К.
В целочисленной последовательности есть нулевые элементы.
Создать массив из номеров этих элементов.i
Дана последовательность целых чисел аи а2, ..., а„. Определить, какое число встречается раньше: положительное или отрицательное.
Дана последовательность действительных чисел аь а2, ..., а„. Определить, будет ли она возрастающей.
Дана последовательность натуральных чисел аь а2, ..., а„. Создать массив из четных чисел этой последовательности. Если таких чисел нет, вывести соответствующее сообщение.
Дана последовательность чисел дь а2, ..., а„. Указать наименьшую длину числовой оси, содержащую все эти числа.
Дана последовательность действительных чисел аи а2,..., а„. Заменить все ее члены, которые больше заданного числа Z, этим числом. Определить количество выполненных замен.
Последовательность действительных чисел оканчивается нулем. Найти количество членов в этой последовательности.
Дан массив действительных чисел с размерностью N. Определить, сколько в нем отрицательных, положительных и нулевых элементов.
Дана последовательность действительных чисел аь а2,..., а„. Поменять местами наибольшее и наименьшее числа.
Дана последовательность целых чисел ah а2,..., а„. Вывести на печать только те числа, для которых о, > /.
Дана последовательность натуральных чисел аи а2, ..., а„. Указать те из этих чисел, у которых остаток от деления на Мравен L(0<L<M- 1).
В заданном одномерном массиве поменять местами соседние элементы, стоящие на четных местах, с элементами, стоящими на нечетных местах.
При поступлении в вуз абитуриенты, получившие два балла на первом экзамене, ко второму экзамену не допускаются. В массиве А[п] записаны оценки экзаменуемых, полученные на первом экзамене. Определить, сколько человек не допущено ко второму экзамену.
Дана последовательность чисел, среди которых имеется один нуль. Вывести на печать все числа до нуля включительно.
В первых элементах одномерного массива размещены значения аргумента, а в следующих — соответствующие им значения функции. Напечатать элементы этого массива в виде двух параллельных столбцов: аргумент и значение функции.
Пригодность детали оценивается по размеру В, который должен находиться в пределах значений от А - 5 до А + 5. Определить, имеются ли в партии из У деталей бракованные. Если имеются, найти их количество, в противном случае вывести отрицательный ответ.
Необходимо имеющиеся доллары выгодно обменять на рубли, если имеется информация о стоимости их купли-продажи в банках города и количестве банков — N.
Дан целочисленный массив с количеством элементов п. Вывести на печать те его элементы, индексы которых являются степенями двойки: 1, 2, 4, 8, 16, ...
Дана последовательность из 7V вещественных чисел. Определить, сколько в ней чисел меньше К, равно К и больше К.
Дана последовательность из N вещественных чисел. Вычислить
\Х,-М?
где М — среднее арифметическое заданной последовательности.
Дан массив (Var А : Array [1..N] Of ’0'..’9';). Определить, входит ли в него последовательность символов «1,2, 3». Если входит, то сколько раз и начиная с каких позиций (N> 3).
Дан массив действительных чисел. Определить, сколько раз изменяется знак в этой последовательности и отметить номера позиций, в которых происходит смена знака.
Дана последовательность из А вещественных чисел. Вычислить сумму чисел, порядковые номера которых являются простыми числами.
Дана последовательность из У вещественных чисел. Вычислить сумму чисел, порядковые номера которых являются числами Фибоначчи.
Дана последовательность из А вещественных чисел. Вычислить значение выражения
Дана последовательность из А целых чисел. Вычислить сумму элементов массива, порядковые номера которых совпадают с значениями этих элементов.
Заполнить массив из N элементов с начальным заданным значением А[0] *0 по принципу: A[I] = A[I div 2] + А[1- 1].
Определить количество членов последовательности натуральных чисел, кратных числу М и заключенных в интервале от L до N.
Определить, сколько процентов от всего количества членов последовательности целых чисел составляют нечетные члены.
Сформировать массив простых чисел, которые не больше заданного натурального числа N.
Сформировать массив простых множителей заданного числа.
Сформировать одномерный массив. Удалить из него К элементов, начиная с заданного номера, и добавить элемент с заданным номером.
Уровень сложности В
Дан одномерный массив А [Л^|. Найти
шах (аъ а4,..., а2к) + min (а,, а3,..., а2*+1).
Дана последовательность действительных чисел аи а2,..., а„. Указать элементы этой последовательности, находящиеся в интервале [с; </].
Дана последовательность целых положительных чисел. Найти произведение тех чисел этой последовательности, которые больше заданного числа М. Если таких чисел нет, то вывести соответствующее сообщение.
Последовательность ah а2, ..., ап состоит из нулей и единиц. Поставить в начало этой последовательности нули, а затем единицы.
Дана последовательность действительных чисел аи а2,..., а„, среди которых есть и положительные, и отрицательные. Заменить нулями те из них, которые по модулю больше максимального заданного числа, т.е. \а\ > тах{оь а2, ..., а„}.
Дана последовательность действительных чисел аи а2,..., а„. Найти
max (О) + а2п, а2 + а2п_i, ..., а„ + а„+1).
В последовательности действительных чисел аи а2,..., а„есть только положительные и отрицательные члены. Вычислить произведение Р\ отрицательных членов этой последовательности и произведение Р2 положительных ее членов. Сравнить Р2 с Рх и указать, какое из произведений по модулю больше.
Дан массив действительных чисел, среди которых есть равные. Найти первый максимальный элемент этого массива и заменить его нулем.
Вставить в заданную последовательность действительных чисел 0| < а2 < ... < а„ действительное число Ь таким образом, чтобы последовательность осталась неубывающей.
Дана последовательность целых положительных чисел аь а2, ..., а„. Найти в ней числа, являющиеся квадратами некоторого числа т.
Дана последовательность целых чисел а,, а2,..., а„. Создать новую последовательность, выбросив из заданной члены, равные min (а,, а2, ..., а„).
У прилавка магазина выстроилась очередь из п покупателей. Время обслуживания /-го покупателя равно /, (где / = 1, ..., п). Определить время Ct пребывания /-го покупателя в очереди.
Секретный замок для сейфа состоит из 10 расположенных в ряд ячеек, в которые вставляют игральные кубики. Замок открывается только в том случае, если в любых трех соседних ячейках сумма точек на передних гранях кубиков равна 10. (Игральный кубик имеет на каждой грани от 1 до 6 точек.) Разгадать код замка, если два кубика уже вставлены в ячейки.
В массиве целых чисел из п элементов найти наиболее часто встречающееся число. Если таких чисел несколько, определить наименьшее из них.
13. Каждый солнечный день улитка, сидящая на дереве, поднимается вверх на 2 см, а каждый пасмурный день опускается вниз на 1 см. В начале наблюдения улитка находилась в А см от земли на if-метровом дереве. Массив данных из 30 элементов содержит сведения о том, был ли соответствующий день наблюдения пасмурным или солнечным. Определить местоположение улитки к концу 30-го дня наблюдения.
Дан целочисленный массив из п элементов. «Сжать» этот массив, выбросив из него каждый второй элемент. (Дополнительный массив не использовать.)
Дан массив, содержащий несколько нулевых элементов. «Сжать» его, выбросив эти элементы.
Дан массив из элементов. Сформировать из него два массива: первый — из элементов исходного массива с четными номерами, а второй — из элементов с нечетными номерами.
Дана последовательность целых чисел at, а2,..., а„. Определить пары чисел ah aj, сумма которых а, + а, = т.
Дана последовательность целых чисел аь а2, ..., а„. Наименьший член этой последовательности заменить целой частью среднего арифметического всех ее членов. Если наименьших членов несколько, заменить последний из них по порядку.
Даны две последовательности целых чисел аь аъ ..., а„ и Ь\, Ь2, ..., Ьп. Преобразовать последовательность Ьи Ьъ ..., Ь„, используя следующее условие: если д, < 0, то Ь, увеличить в 10 раз, в других случаях 6, заменить нулем (/ = 1, 2, ..., п).
Дана последовательность действительных чисел аи а2,..., а„. Умножить все члены этой последовательности на квадрат ее наименьшего члена, если ак> 0, и на квадрат ее наибольшего члена, если ак< 0 (где 1 < к < п).
Даны координаты п точек на плоскости: (Х\, Y{),..., (Х„, Y„), где п < 30. Найти номера пары точек, расстояние между которыми наибольшее. (Считать, что такая пара единственная.)
Дана последовательность из п различных целых чисел. Найти сумму ее членов, расположенных между максимальным и минимальным значениями. (В сумму включить и оба этих числа.)
Японская радиокомпания получила ответы N радиослушателей на следующий вопрос: «Какое животное вы связываете с Японией и японцами?» Определить к наиболее часто встречающихся ответов и их долю в процентах.
Дан массив, состоящий из п натуральных чисел. Создать новый массив, элементами которого будут элементы исходного массива, оканчивающиеся на цифру к.
Дан массив целых чисел. Найти в этом массиве минимальный элемент т и максимальный элемент М. Определить в порядке возрастания все целые числа из интервала (т; М), которые не входят в данный массив.
Даны действительное число х и массив чисел А[п\. Найти в массиве два члена, среднее арифметическое которых ближе всего к числу х.
Даны две последовательности аь а2, .... а„ и Ьх Ь2, ..., Ьт (где т < я). В каждой из них члены различны. Определить, верно ли, что все члены второй последовательности входят в первую последовательность.
Входные данные — возраст и человек. Определить количество человек, возраст которых находится в интервале 10 лет, т.е. 0...9 лет, 10... 19 лет, 20...29 лет и т.д. Напечатать результаты расчетов в удобочитаемой форме.
Дан массив Л^УУ] целых чисел. Не используя других массивов, переставить его элементы в обратном порядке.
Коэффициенты многочлена хранятся в массиве Л[УУ] (где УУ— натуральное число, степень многочлена). Вычислить значение этого многочлена в точке х (т.е. я[УУ] • xN+... + а[1] • х+ а[0]) и найти его производную в этой точке.
В массивах А[К\ и B[L] хранятся коэффициенты двух многочленов степеней Кп L. Поместить в массив С[М\ коэффициенты произведения этих многочленов. (Числа К, L, М— натуральные; М- K+L; элемент массива с индексом / содержит коэффициент при х в степени /.)
Получить информацию о наибольшем, наименьшем и наименее удаленном от среднего арифметического членах последовательности вещественных чисел.
Дан массив чисел А. Определить значение к, при котором сумма \А[1] +А[2] +... +А[к] - (А[к+ 1] +... + Л[УУ])| минимальна (т.е. минимален модуль разности сумм элементов правой и левой частей, на которые массив делится этим к).
Уровень сложности С
В одномерном массиве все отрицательные элементы переместить в начало, а остальные — в конец с сохранением порядка следования, не используя при этом дополнительный массив.
Одномерный массив с четным количеством элементов (2УУ) содержит координаты УУ точек плоскости, которые располагаются в следующем порядке: хь у,, хъ у2, х3, уг и т.д. Определить:
а)минимальный радиус окружности с центром в начале координат, которая содержит все точки;
б)кольцо с центром в начале координат, которое содержит все точки;
в)номера точек, которые могут являться вершинами квадрата;
г)номера точек, которые могут являться вершинами равнобедренного треугольника;
д)номера наиболее удаленных и наименее удаленных друг от друга точек;
е)три точки, являющиеся вершинами треугольника, для которого разность точек вне его и внутри является минимальной.
Дан целочисленный массив размерности N. Определить, есть ли среди элементов этого массива простые числа, и если есть, вывести на экран номера этих элементов.
Дана последовательность целых чисел. Найти количество различных чисел в этой последовательности.
Дан массив из п четырехзначных натуральных чисел. Вывести на экран только те числа, у которых сумма первых двух цифр равна сумме двух последних.
Даны две последовательности целых чисел аь а2, ..., а„ и Ьи Ь2, ..., Ьп, все члены которых — различные числа. Определить, сколько членов первой последовательности совпадают с членами второй последовательности.
Дан целочисленный массив А[п\, среди элементов которого есть одинаковые. Создать массив из различных его элементов.
На плоскости п точек заданы своими координатами, а также задана окружность с радиусом Лис центром в начале координат. Указать множество всех треугольников с вершинами в заданных точках, пересекающихся с окружностью, и множество всех треугольников, содержащихся внутри окружности.
Некоторое число содержится в каждом из следующих трех целочисленных неубывающих массивов: х[1] < ...<*[/>]; у[1] <... <y\q\, г[1] < ... < гИ- Найти одно из таких чисел, при этом число действий должно быть порядка p + q + r.
Определить, есть ли одинаковое число в каждом из следующих трех целочисленных неубывающих массивов: х[ 1 ] < ...<х[р\, у[1] <... <y[q\, z[l] S... ^ z[r\- Найти одно из таких чисел или сообщить об отсутствии такого числа.
Дан массив целых чисел А[п\. Найти наименьшее число К элементов, которые можно исключить из этой последовательности, чтобы подпоследовательность осталась возрастающей.
Разделить заданный массив чисел на две части, включив в первую часть элементы, большие среднего арифметического их суммы, а во вторую — меньшие (части не сортировать).
Даны два одномерных массива с различным количеством элементов и натуральное число к. Объединить их в один массив, включив второй массив между £-м и (к+ 1)-м элементами первого и не используя при этом дополнительный массив.
Даны две последовательности а\ < а2 < ... < а„ и 6, < Ь2 <... < Ьт. Образовать из них новую неубывающую последовательность чисел, не используя дополнительный массив.
Дана последовательность чисел аи а2, ..., а„. Переставить ее элементы в порядке убывания. Для этого в массиве выбрать наибольший элемент (начиная с первого) и поставить его на первое место, а первый — на место наибольшего. Затем эту процедуру повторить, начиная со второго элемента. Записать алгоритм сортировки массива выбором.
Дана последовательность чисел а{, а2, ..., а„. Переставить ее элементы в порядке возрастания, для чего сравнить два соседних числа а, и ам. Если а, > а/+ ь выполнить перестановку. Процесс продолжать до тех пор, пока все элементы будут расположены в порядке возрастания. Записать алгоритм сортировки массива обменами (методом пузырька), подсчитывая при этом количество перестановок.
Дана последовательность чисел аи а2,..., а„. Переставить ее элементы в порядке возрастания следующим образом. Пусть аи а2,..., а, — упорядоченная последовательность, т.е. а, 5 а2<... <а(. Следующее число ам вставляется в последовательность таким образом, чтобы новая последовательность также была возрастающей. Процесс повторяется до тех пор, пока все элементы от / + 1 до п будут выбраны. (Место размещения очередного элемента в отсортированной части определить с помощью двоичного поиска, который оформить в виде отдельной функции.) Записать алгоритм сортировки массива вставками.
Записать алгоритм сортировки Шелла, основная идея которого заключается в сортировке элементов массива, отстоящих друг от друга на расстояние А. При этом каждая такая А-сортировка программируется как сортировка простыми вставками. Затем расстояние А уменьшается и сортировка повторяется. Процесс заканчивается, когда А уменьшается до 1.
Дан массив п действительных чисел, который требуется упорядочить по возрастанию, используя сравнение двух соседних элементов dj и ам. Если о, < о*], сдвигаются на один элемент вперед, если же о, > ам, сдвигаются на один элемент назад. Записать алгоритм такой сортировки.
Пусть даны неубывающие последовательности действительных чисел 0| < о2 < ... < о„ и А| < А2 < ... < Ьт. Требуется указать места вставки элементов второй последовательности в первую таким образом, чтобы новая последовательность оставалась возрастающей.
Даны дроби —, —,..., — (где ph qt — натуральные числа).
Я\ Я2 Яп
Привести эти дроби к общему знаменателю и упорядочить их в порядке возрастания.
Упорядочить последовательность ах, а2, ..., а„ по неубыванию с помощью алгоритма сортировки слияниями (алгоритма фон Неймана), заключающемся в следующем.
Сначала каждая пара соседних элементов сливается в группу из двух элементов, причем последняя группа может состоять из одного элемента, а затем каждая пара соседних двухэлементных групп сливается в одну четырехэлементную группу и т.д. При каждом слиянии новая укрупненная группа элементов упорядочивается.
Выполнить сортировку подсчетом, которая заключается в следующем. Сначала выходной массив заполняется значениями -1. Затем определяется место каждого элемента в выходном массиве посредством подсчета количества элементов, строго меньших заданного. При этом все одинаковые элементы попадают на одну позицию, за которой следует ряд значений -1, после чего оставшиеся в выходном массиве позиции с значением -1 заполняются копией предыдущего значения.
Выполнить «хитрую» сортировку, заключающуюся в следующем. Сначала из массива посредством однократного просмотра следует выбрать последовательность элементов, находящихся в порядке возрастания, перенести ее в выходной массив и заменить во входном массиве значением -1. Затем оставшиеся элементы включить в полученную упорядоченную последовательность методом погружения, т.е. очередной элемент посредством ряда обменов «погрузить» до требуемой позиции в уже упорядоченную часть массива.
Скомбинировать методы быстрой сортировки и сортировки вставками, т.е. когда длина разделенных подмассивов станет меньше некоторого т (1 <т<п), выполнять сортировку методом вставки. Найти значение т, минимизирующее общее время сортировки.
Реализовать улучшенный алгоритм сортировки методом пузырька, т.е. выполнить шейкер-сортировку, запоминая, производился ли при данной перестановке какой-либо обмен. Если нет, алгоритм можно закончить. Также улучшить алгоритм можно периодически изменяя направление сортировки, что устранит некоторую асимметрию метода пузырька.
Тема «Двухмерные массивы»5.8.1. Формирование массивов
1. Сформировать квадратную матрицу порядка л (где п — четное число) по заданному образцу:
а) 1 2 3 л
п л-1 л-2 1
1 2 3 л
п л-1 л-2 1
п л-1 л-2 1
б) 0 0 0 0 0 1 0 0 0 0 2 0 0 0 0 3 0 0 0 я-1 0 0 0 0 я 0 0 0 0 0 в) п 0 0 0 0 0 0 я — 1 0 0 0 0 0 0 я-2 0 0 0 0 0 0 0 2 0 0 0 0 0 0 1 г) 1-2 0 0 « 0 0
0 2-3 0 0 0 0
0 0 3-4 0 0 0
0 0 0 0 (я-1)я 0
0 0 0 0 0 я(я +1)
д) 1 1 1 1 1 1 1 0 0 0 0 1 1 0 0 0 0 1 1 0 0 0 0 1 1 1 1 1 1 1 е) 1
2 2 2 2 2 0
3 3 3 3 0 0
1
1
1
1
1
л-1 л-1 0 0 0 0
л 0 0 0 0 0
ж) 1 1 1 1 1 1 0 1 1 1 1 0 0 0 1 1 0 0 0 1 1 1 1 0 1 1 1 1 1 1 з) 1 0 0 0 0 1 1 1 0 0 1 1 1 1 1 1 1 1 1 1 0 0 1 1 1 0 0 0 0 1 и) л 0 0 0 0 0
л-1 л 0 0 0 0
л-2 л-1 л 0 0 0
2 3 4 л-1 л 0
1 2 3 л-2 л-1 л
К) 1 2 3 л - 2 л- 1 л 2 3 4 л - 1 л 0 3 4 5 л 0 0 л-1 л 0 0 0 0 л 0 0 0 0 0 л) 1 0 0 0 0 л 0 2 0 0 л-1 0 0 0 3 л - 2 0 0 0 2 0 0 л-1 0 1 0 0 0 0 л м) 1 2 3 л-2 л-1 л
2 1 2 л-3 л-2 л-1
3 2 1 л-4 л-3 л-2
л-1 л- 2 л - 3 2 1 2
л л-1 л - 2 3 2 1
2. Построить квадратную матрицу порядка 2л:
П П
1 1 .. 1 2 2 ... 2
1 1 1 2 2 ... 2
1 1 1 2 2 2 2
3 3 3 4 4 4
3 3 3 4 4 4
3 3 ., .. 3 4 4 ... 4
Дано действительное число х. Получить квадратную матрицу порядка я+1:
1 X X2 Xй-2 хй-‘ Xй
X 0 0 0 0 Xй-1
X2 0 0 0 0 Xй-2
X"-' 0 0 0 0 X
Xй Xй-1 хй-2 X2 X 1
Дана последовательность действительных чисел аи а2, ..., а„. Получить квадратную матрицу порядка п:
0\ а2 оз а„-2 ап 1 о„
а2 «3 а4 &п-\ ап-2 а\
аъ 04 % ап а\ 02
ап-\ о„ at ап-Л ап 3 &П-2
а2 ап-3 On- 2 &П-\
5. Получить следующую матрицу: 1 2 3 9 10 0 1 2 8 9 0 0 1 7 8 0 0 0 0 1 6. Получить следующую матрицу:
1 0 0 1
0 1 1 0
0 1 1 0
1 0 0 1
Заполнить квадратную матрицу порядка п натуральными числами 1, 2, 3,и2, записывая их по спирали.
Например, для п = 5 получим следующую матрицу:
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
Дана действительная квадратная матрица порядка 2п. Получить новую матрицу, переставляя ее блоки размером п х и по часовой стрелке, начав с блока в левом верхнем углу.
Дана действительная квадратная матрица порядка 2п. Получить новую матрицу, переставляя ее блоки размером п х п крест накрест.
Дан линейный массив хь хъ ... ,хп_ь хп. Получить действительную квадратную матрицу порядка п:
*1 *2 *л-1 х„
Г2
Х{ *22 Y2
“*71-1 х2
Лл

*1 *! Vя
Хп-1 Хп
Дан линейный массив хь х2, ..., х„_,, х„. Получить действительную квадратную матрицу порядка и:
1 1 1 1
*1 *2 •^л-1 „2
*2 V2
*л-1 х2 л,п
~л-1
*1 -уЛ—1 *2 -у-Л—1 *л-1 у.Л-1
лп
Получить квадратную матрицу порядка п:
1 2 л - 1 л
/1 + 1 я + 2 2л- -1 2л
2л+ 1 2л+ 2 Зл - -1 3 л
(л - 1)л +1 (л - 1)л + 2 л2- -1 л2
Получить квадратную матрицу порядка л:
0 0 0 0 0
0 1 0 0 0
0 0 2 0 0
0 0 0 0 л-1
Магическим квадратом порядка я называется квадратная матрица размером л х л, составленная из чисел 1, 2, ..., я2таким образом, что суммы чисел в каждом ее столбце, каждой строке и каждой из двух больших диагоналей равны между собой. Построить такой квадрат. Например магический квадрат третьего порядка имеет вид
TOC \o "1-5" \h \z 18
53
294
Сформировать квадратную матрицу порядка N по формуле
(/2-/2Х
A[I,J\ = sin ——— I и определить количество положительных элементов в ней.
Дана квадратная матрица порядка М. Повернуть ее в положительном направлении на 90, 180 и 270°.
5.8.2. Операции с элементами массивовВычислить сумму и число положительных элементов, находящихся над главной диагональю матрицы A[N, N\.
Дана вещественная матрица А размером л х т. Определить количество А: ее «особых» элементов, т.е. элементов, которые больше суммы остальных элементов столбца.
Дана квадратная матрица. Поменять местами строку с максимальным элементом на главной ее диагонали со строкой с заданным номером т.
Дана матрица B[N, М]. Найти в каждой строке этой матрицы максимальный и минимальный элементы и поменять их местами с первым и последним элементами этой строки соответственно.
Дана целая квадратная матрица «-го порядка. Определить, является ли она магическим квадратом, т.е. что суммы элементов во всех ее строках и столбцах одинаковые.
Элемент матрицы называется седловой точкой, если он является наименьшим в своей строке и наибольшим в своем столбце или наибольшим в своей строке и наименьшим в своем столбце. Для заданной целой матрицы размером яхт напечатать индексы всех ее седловых точек.
Дана вещественная матрица размером п х т. Переставляя ее строки и столбцы, добиться того, чтобы наибольший ее элемент (или один из них) оказался в верхнем левом углу.
Определить, является ли заданная целая квадратная матрица «-го порядка симметричной относительно главной диагонали.
Дана целочисленная квадратная матрица. Найти в каждой ее строке наибольший элемент и поменять его местами с элементом главной диагонали.
Упорядочить по возрастанию элементы каждой строки матрицы размером пхт.
Дана матрица размером яхт. Найти максимальный по модулю элемент этой матрицы и переставить ее строки и столбцы таким образом, чтобы он был расположен на пересечении &-й строки и к-го столбца.
Дана квадратная матрица /4[У, /V]. Записать на место отрицательных элементов этой матрицы нули, а на место положительных элементов — единицы. Вывести на печать нижнюю треугольную матрицу в общепринятом виде.
Дана действительная матрица размером пхт, все элементы которой различны. В каждой строке этой матрицы выбрать элемент с наименьшим значением, а затем среди них выбрать элемент с наибольшим значением. Указать индексы этого элемента.
Дана действительная квадратная матрица порядка N(где N— нечетное число), все элементы которой различны. Найти наибольший элемент главной и побочной диагоналей этой матрицы и поменять его местами с элементом, стоящим на пересечении этих диагоналей.
Для заданной квадратной матрицы сформировать одномерный массив из ее диагональных элементов. Найти след этой матрицы, суммируя элементы полученного одномерного массива. Преобразовать исходную матрицу, разделив четные строки на полученные значения, а нечетные строки оставить без изменения.
Дана квадратная матрица. Получить из нее транспонированную матрицу.
Квадратная матрица, симметричная относительно главной диагонали, задана верхним треугольником в виде одномерного массива. Восстановить исходную матрицу и напечатать ее по строкам.
Даны матрица порядка п и число к. Разделить элементы к-й строки матрицы на диагональный элемент, расположенный в этой строке.
Для целочисленной квадратной матрицы найти число элементов, кратных к, и определить наибольший из них.
Найти наибольший и наименьший элементы прямоугольной матрицы и поменять их местами.
Дана прямоугольная матрица. Найти ее строки с наибольшей и наименьшей суммой элементов. Вывести на печать эти строки и суммы их элементов.
В заданной действительной квадратной матрице порядка п найти сумму элементов строки, в которой расположен элемент с наименьшим значением. (Предполагается, что такой элемент единственный.)
В заданной действительной квадратной матрице порядка п найти наибольший по модулю элемент. Получить квадратную матрицу порядка п - 1, отбросив из исходной матрицы строку и столбец, на пересечении которых расположен найденный элемент.
Дана действительная квадратная матрица порядка п. Преобразовать эту матрицу, сделав строку с номером п столбцом с номером п, а столбец с номером п — строкой с номером п.
Дана действительная матрица размером п х т. Преобразовать эту матрицу, поэлементно вычитая значение последней строки из значений всех ее строк, кроме последней.
Определить номера строк целочисленной матрицы A[N, К], совпадающие с массивом D[K\. Если таких строк нет, выдать соответствующее сообщение.
Определить наименьший элемент каждой четной строки матрицы А[М, N],
Расположить столбцы матрицы D [М, 7V] в порядке возрастания элементов к-й строки (1 < к < М).
Определить номера строк матрицы R[M, N], в которых хотя бы один элемент равен с, и элементы этих строк умножить на d.
Матрица A \N, М] (где М — кратно четырем) разделена по вертикали на две половины. Определить сумму элементов каждого столбца левой половины этой матрицы и сумму элементов каждого четного столбца ее правой половины.
Дана квадратная целочисленная матрица порядка п. Сформировать результирующий одномерный массив, элементами которого являются суммы элементов тех строк, которые начинаются с А: идущих подряд положительных чисел.
Целочисленная матрица размером пхт содержит информацию об п учениках некоторого класса. В первом столбце этой матрицы указана масса [кг], во втором — рост [см], в третьем — успеваемость (средний балл) и т.д. (используйте свои дополнительные показатели). Ученик является среднестатистическим (уникальным) по к-му параметру, если для него характерен минимум (максимум) модуля разности среднего арифметического чисел из к-то столбца заданной матрицы и значения его к-то параметра. Ученик является самым уникальным (самым средним), если он окажется уникальным (среднестатистическим) по самому большому количеству указанных параметров. Определить по данной матрице самых уникальных и самых средних учеников класса.
Прямоугольное поле разбито на m х п квадратных клеток. Некоторые из этих клеток окрашены в черный цвет. При этом известно, что все черные клетки можно разбить на несколько непересе- кающихся и не имеющих общих вершин черных прямоугольников. Считая, что цвета клеток заданы в виде массива следующего типа: Array [l..m, l..n] Of Boolean, определить число черных прямоугольников. Причем число операций должно быть порядка тхп.
(Число прямоугольников определяется числом их левых верхних углов. Является ли клетка верхним углом, узнается по ее цвету, а также по цвету верхней и левой соседних клеток. Однако соседей может и не быть, если клетка крайняя.)
Даны квадратная таблица A[N, N] и число М< N. Для каждого квадрата размером Мх М в этой таблице вычислить сумму стоящих в нем чисел. При этом общее число действий должно быть порядка п2.
(Сначала для каждого горизонтального прямоугольника размером М х 1 следует вычислить сумму стоящих в нем чисел. При сдвиге такого прямоугольника по горизонтали на 1 надо одно число добавить и одно вычесть. Затем вычисляют полученные суммы в квадратах. При сдвиге квадрата по вертикали одна полоска добавляется, а другая полоска убавляется.)
Среди строк целочисленной матрицы, содержащих только нечетные элементы, найти строку с максимальной суммой модулей ее элементов.
Дана целочисленная матрица размером Nx N. Определить количество строк этой матрицы, являющихся перестановкой чисел 1, 2, ..., N, т.е. содержащих каждое из этих чисел только один раз.
Среди столбцов целочисленной матрицы, содержащих только элементы, модули которых не больше 10, найти столбец с минимальным произведением элементов.
Массивом chars [Л/] [ЛП кодируется поле, на котором расположено несколько прямоугольников. Каждый прямоугольник состоит из целого числа клеток, при этом разные прямоугольники не накладываются друг на друга и не соприкасаются. Разные прямоугольники могут состоять из разных символов, а один и тот же прямоугольник не может обозначаться различными символами. Пустые квадраты поля кодируются символом «.». Определить число прямоугольников разных типов. Например, для поля вида
###+ .
???....
???—;
???...####..
должен быть получен следующий ответ:
# прямоугольников — 2 ? прямоугольников — 3 + прямоугольников — 1 = прямоугольников — 2
Характеристикой столбца целочисленной матрицы является сумма модулей его отрицательных нечетных элементов. Переставить столбцы заданной целочисленной матрицы, расположив их в соответствии с ростом характеристик.
Для заданной квадратной матрицы найти значения к, при которых к-я ее строка совпадает с к-м столбцом.
Найти максимальный элемент среди упорядоченных либо по возрастанию, либо по убыванию строк заданной матрицы.
Расстояние между строками к и I квадратной матрицы А размером NxN определяется формулой
У=1
Указать номер строки, максимально удаленной от первой строки заданной матрицы.
Определить, является ли заданная матрица ортонормиро- ванной (т.е. что скалярное произведение каждой пары различных ее строк или столбцов равно нулю).
Определить среднее арифметическое элементов матрицы, находящихся на пересечении строк, номера которых кратны R, и столбцов, номера которых кратны S.
Определить номера строк заданной матрицы, в которых знаки элементов чередуются.
Каждый элемент матрицы А(3, 3) разделить на значение ее определителя.
Сформировать двухмерный массив и удалить из него все строки, в которых встречается заданное число.
Сформировать двухмерный массив и удалить из него все столбцы, в которых встречается заданное число.
В прямоугольной таблице определить номер строки, в которой находится самая длинная последовательность одинаковых элементов.
Даны две квадратные матрицы Ли В. Найти матрицу С, равную АхВ- ВхА.
Тема «Работа со строками»Дана строка, заканчивающаяся точкой. Определить, сколько слов в строке.
Дана строка, содержащая английский текст. Найти количество слов в этой строке, начинающихся с буквы Ь.
Дана строка. Подсчитать в ней количество вхождений букв г, k, t.
Дана строка. Определить, сколько в ней символов (*), (;), (:).
Дана строка, содержащая текст. Найти длины самого короткого и самого длинного слов в этой строке.
Дана строка символов, среди которых есть двоеточие (:). Определить, сколько символов ему предшествует.
Дана строка, содержащая текст, заканчивающийся точкой. Вывести на экран слова из этого текста, содержащие три буквы.
Дана строка. Преобразовать ее, удалив каждый символ (*) и повторив каждый символ, отличный от (*).
Дана строка. Определить, сколько раз входит в нее группа букв abc.
Дана строка. Определить количество букв к в последнем ее слове.
Дана строка. Определить, сколько различных символов встречается в ней. Вывести их на экран.
Дана строка. Определить в ней самую длинную последовательность подряд идущих букв «а».
Дана строка символов, среди которых есть одна открывающаяся скобка и одна закрывающаяся. Вывести на экран все символы, расположенные внутри этих скобок.
Дана строка, содержащая буквы латинского алфавита и цифры. Вывести на экран длину наибольшей последовательности цифр, идущих подряд.
Дан набор слов, разделенных точкой с запятой (;), который заканчивается двоеточием (:). Определить, сколько в нем слов, заканчивающихся буквой «а».
Дана строка. Указать слова в этой строке, содержащие хотя бы одну букву к.
Дана строка. Найти в этой строке слова, которые начинаются и оканчиваются на одну и ту же букву.
В заданной строке заменить все двоеточия (:) точкой с запятой (;). Определить количество выполненных замен.
В заданной строке удалить символ двоеточие (:) и определить количество удаленных символов.
В заданной строке между словами вставить вместо пробела запятую и пробел.
Удалить часть символьной строки, заключенной в скобки, вместе со скобками.
Определить, сколько раз в строке встречается заданное слово.
В заданной строке имеется точка с запятой (;). Определить количество символов в этой строке до точки с запятой и после нее.
Дана строка. Преобразовать ее, заменив точками все двоеточия (:), встречающиеся среди первых п/2 символов, и все восклицательные знаки, встречающиеся среди символов, стоящих после п/2 символов.
Строка содержит одно слово. Проверить, будет ли оно читаться одинаково справа налево и слева направо, т.е. является ли оно палиндромом.
В записке слова зашифрованы: каждое из них записано наоборот. Расшифровать сообщение.
Проверить, одинаковое ли число открывающихся и закрывающихся скобок в заданной строке.
Строка произвольного русского текста содержит не более 200 букв. Определить, какие буквы и сколько раз встречаются в этом тексте. (Ответ привести в грамматически правильной форме, например: а — 25 раз, к — 3 раза и т.д.)
Упорядочить заданный массив английских слов по алфавиту.
Даны две строки А и В. Проверить, можно ли из букв, входящих в строку А, составить строку В. (Буквы можно использовать не более одного раза, а также можно переставлять.)
Например: из строки А — ИНТЕГРАЛ — можно составить строку В — АГЕНТ — и нельзя составить строку В — ГРАФ.
Строка содержит произвольный русский текст. Определить, каких букв в этом тексте больше: гласных или согласных.
Двухмерный массив размером п х т содержит некоторые буквы русского алфавита, расположенные в произвольном порядке. Определить, можно ли из этих букв составить заданное слово S. (Каждую букву массива использовать не более одного раза.)
Результаты вступительных экзаменов представлены в виде списка из N строк, в каждой из которых записаны фамилия студента и его оценки по каждому из М экзаменов. Определить количество абитуриентов, сдавших вступительные экзамены только на «отлично».
Преобразовать заданные натуральные числа, записанные римскими цифрами, в десятичную систему счисления.
Из заданной символьной строки выбрать символы, встречающиеся только один раз, в порядке их расположения.
В символьном массиве хранятся фамилии и инициалы учеников класса. Напечатать список класса с указанием количества однофамильцев каждого ученика.
Дано число в двоичной системе счисления. Проверить правильность ввода этого числа (в его записи должны быть только символы 0 и 1). Если число введено неверно, ввод повторяют. При правильном вводе перевести заданное число в десятичную систему счисления.
В заданной строке удалить все лишние пробелы.
В заданном тексте определить длину содержащейся в нем максимальной серии символов, отличных от букв.
Расстояние между двумя словами равной длины — это количество позиций, в которых заключаются эти слова. В заданном предложении найти пару слов заданной длины с максимальным расстоянием.
Отредактировать заданное предложение, удалив из него слова, встречающиеся заданное число раз.
Напечатать слова, встречающиеся в каждом из двух заданных предложений.
Отредактировать заданное предложение, удалив из него все слова с нечетными номерами и перевернув слова с четными номерами.
44. Один из методов кодирования, называемый наложением гаммы, заключается в следующем. Берется некоторое случайное число в диапазоне от 127 до 255 — гамма, и код каждого символа заданной строки заменяется кодом, получающимся в результате выполнения операции
новый код = старый код XOR гамма.
Реализовать указанный метод кодирования для заданной строки и декодирование полученной строки при заданной гамме. (Входные данные — кодируемая строка, выходные — гамма и закодированная строка.)
Перекодировать строку из кодировки KOI в строку в кодировке Windows-1251 и обратно.
Дан текст, в котором встречаются структуры <i> и </i>. Заменить каждое вхождение <i> на <курсив>, а каждое вхождение </i> на <конец курсивах (Следует учесть, что буква «i» может быть как строчной, так и прописной.)
Дан текст, состоящий из предложений, разделяемых точками. Произвести следующее форматирование: после каждой точки в конце предложения должен быть хотя бы один пробел; первое слово в предложении должно начинаться с прописной буквы. (Текст может быть на русском и английском языках.)
Дан текст. Определить в нем процентное отношение строчных и прописных букв к общему числу символов.
Дан текст. Определить, каких букв в нем больше: строчных или прописных. Если больше прописных букв, заменить все строчные буквы прописными. Если больше строчных букв, заменить все прописные буквы строчными. Если количество прописных и строчных букв равно, текст оставить без изменения.
Дан текст на латинском языке, содержащий слова, разделенные пробелами. Определить, какие буквы в этих словах совпадают чаще: первые, последние или средние. Позиция средней буквы в слове определяется по следующей формуле:
поз_средн_буквы = длина_слова div 2+1
Дана строка из слов, разделенных пробелами. Удалить лишние пробелы. (Пробел считается лишним, если он стоит в начале строки, в конце строки или следует за пробелом.)
С клавиатуры введено целое число в десятичной системе счисления. Реализовать форматированный вывод этого числа, т.е. представить его с разделением на триады цифр. Например: введено число 100000, а выведено 100000; введено число 1000000, а выведено: 1000 000.
Для увеличения (уменьшения) значения целочисленной переменной на единицу в языках программирования можно использовать операцию сложения (вычитания) и операцию инкремент (декремент). Известно, что операция инкремент (декремент) выполняется гораздо быстрей, чем сложение (вычитание), поэтому ее использование часто предпочтительней. Дан массив строк, представляющий собой фрагмент текста программы на языке Паскаль, в котором используются только целочисленные переменные. В каждой строке — одна команда. Преобразовать заданный текст, заменив каждую строку вида
переменная := переменная + 1; на строку вида
Inc(переменная);
а каждую строку вида 316
на строку вида
Dec(переменная);
Например, дан следующий текст:
Begin
ReadLn(a, b);
TOC \o "1-5" \h \z а:=а+1;
с:=b+1;
b:=b-1;
WriteLn('a =a); WriteLn('b = b);
End.
Преобразованный текст будет иметь вид
Begin
ReadLn(a, b);
Inc(a);
c b + 1;
Dec(b);
WriteLn('a =a); WriteLn('b = ', b);
End.
В заданном массиве слов найти наибольшее слово.
Дана строка. Если она представляет собой запись целого числа—вывести 1, если вещественного (с дробной частью) — вывести 2, если строку нельзя преобразовать в число — вывести 0.
Дана строка из русских слов, разделенных пробелами (одним или несколькими). Вывести строку, содержащую эти же слова (разделенные одним пробелом), но расположенные в обратном порядке.
Дана строка-предложение. Закодировать ее, т. е. указать сначала все символы, расположенные на четных местах, а затем — в обратном порядке все символы, расположенные на нечетных местах. Например: строка «Программа» будет иметь вид «ргамам- роП». Решить обратную задачу.
Дана строка-предложение на русском языке. Преобразовать ее таким образом, чтобы каждое слово начиналось с прописной буквы.
Дана строка. Получить новую строку, в которой каждый символ исходной строки заменить кодом. (Если длина результирующей строки превышает 255 символов, ввести еще одну дополнительную строку.)
Тема «Длинная арифметика»Сравнить два многозначных числа.
Суммировать два натуральных л-значных числа при п > 20.
Вычислить степени чисел вида а”, если а > Maxlnt, при л > 10.
Вычислить число 2м- 1, сохранив в результате все цифры.
Вычислить 100!.
Извлечь точно квадратный корень из «-разрядного числа (л >40).
Выполнить умножение многозначных чисел.
Вычислить точное значение л! при л > 12.
Вычислить точное значение л" при л > 10.
Выполнить деление числа а на число Ь, если а, Ь— многозначные числа.
Вычислить 100! + 2100.
Вычислить 100! - 2100.
Вычислить 7123.
Определить, есть ли среди цифр числа 211213- 1 две подряд идущие девятки.
Вычислить 2-200.
Найти частное и остаток от деления /п-значного числа на л-значное (при т, п> 20).
Определить, какое из чисел ат или Ь" больше и на сколько (при а, b <40 000; т, л < 10).
Найти л знаков в десятичной записи числа yfm (при л > 50).
Найти количество делителей л-значного натурального числа (при л > 20).
Вычислить точное значение (л!)! (при л > 4).
Вычислить точное значение суммы 1! + 2! + 3! + ... + л! (при л > 10).

22. Вычислить точное значение суммы дробей+ тг; + тт + ■
1!2! 3!
(при л > 10). Ответ представить в виде несократимой дроби — (где
р, q— натуральные числа).^
Вычислить точное значение (лп)! при л > 3.
Вычислить точное значение суммы первых л членов последовательности 1, к, к2, к3, ..., к" (при л > Maxlnt).
Вычислить точное значение суммы первых л членов последовательности чисел, кратных заданному натуральному числу к (при л > Maxlnt).
Вычислить точное значение суммы 12+ 22+ 32+ ... + л2 (при л > 20000).
Вычислить точное значение суммы Iя + 2" + 3" + ... + л2 (при л > 10).
Найти первое простое число, которое больше 10".
Вычислить точное значение многочлена апхп + ал.|Хл_| +... + + в]Х + по (где ah х — целые числа больше 10").
Найти наибольший общий делитель и наименьшее общее кратное чисел тип (при т, п > 1011).
Проверить, являются ли числа тип (при т, п > 1011) взаимно простыми.
Доказать, что число 219936 (219937 - 1) является совершенным, т.е. что оно равно сумме всех своих делителей без самого себя.
Вычислить функцию Y=F(X), разложенную в степенной ряд, с заданной степенью точности е (при 10-1 <е< Ю'1000).
Массив хранит длинные числа. Найти их сумму и произведение.
Массив хранит длинные числа. Выполнить сортировку массива. Найти разность максимального и минимального значений его элементов.
Найти сумму значений элементов массива, содержащего длинные числа, в запись которых не входит заданная цифра.
Тема «Множества»Уровень сложности А
Три цветовода выращивают розы. Определить, какие из известных сортов роз «Анжелика», «Виктория», «Гагарин», «Ave Maria», «Катарина», «Юбилейная» имеются у каждого цветовода, есть хотя бы у одного из цветоводов и каких нет ни у одного из цветоводов.
Даны имена девочек. Определить, какие из этих имен встречаются во всех параллельных классах школы, какие есть только в некоторых классах и какие не встречаются ни в одном из классов.
Дан некоторый набор товаров. Определить, какие товары имеются в каждом из п магазинов, какие есть хотя бы в одном магазине и каких нет ни в одном из магазинов.
Имеется список учеников класса, в котором все имена различны. Определить, есть ли в классе человек, который побывал в гостях у всех учеников. (Для каждого ученика составить список из множества побывавших у него в гостях друзей, причем хозяина в этот список не включать.)
Имеется множество, содержащее натуральные числа из некоторого диапазона. Сформировать из него два множества, первое из которых содержит все простые числа, а второе — все составные числа.
На трех участках выращивают следующие сельскохозяйственные культуры: картофель, укроп, морковь, горох, капуста, редис. Определить, какие из этих культур имеются на каждом участке, имеются хотя бы на одном из участков и не имеются ни на одном участке.
Известны марки машин, выпускаемых в данной стране и экспортируемых в N заданных стран. Определить, какие марки машин были доставлены во все указанные страны, какие в некоторые из этих стран и какие не доставлены ни в одну из стран.
В озере водится несколько видов рыб. Три рыбака поймали рыб некоторых из имеющихся в озере видов. Определить, рыб каких видов поймал каждый рыбак и рыб каких видов, имеющихся в озере, не выловил ни один из рыбаков.
В N колхозах выращивают некоторые сельскохозяйственные культуры из имеющегося перечня. Определить культуры, выращиваемые во всех колхозах, и культуры, выращиваемые только в некоторых из них.
Дан список игрушек. Некоторые игрушки из этого списка имеются в N детских садах. Определить, каких игрушек из этого списка нет ни в одном из детских садов и какие есть в каждом из них.
Вычислить сумму элементов двухмерного массива, номера строк и столбцов которых принадлежат соответственно непустым множествам ^ и 52-
Даны множества М и Т одного типа. Определить, сколько членов из этих множеств совпадают.
Из диапазона целых чисел /я... п выделить множество чисел, делящихся без остатка или на к, или на / (где к, I — простые числа), и множество чисел, делящихся на произведение kl без остатка.
Создать два множества из символов, которые вводятся пользователем с клавиатуры. Напечатать элементы, которые содержатся в первом и втором множествах одновременно.
Множество содержит п целых случайных равномерно распределенных чисел из интервала [а; Ь\. Требуется:
а)напечатать все элементы множества, являющиеся простыми числами;
б)определить, сколько в данном множестве четных чисел из интервала [с; </];
в)определить, сколько элементов содержится в этом множестве;
г)определить, сколько чисел из интервала [а; Ь\ не попало в данное множество;
д)разбить полученное множество на два: множество, содержащее числа, в двоичной записи которых более к нулей, и мно- женство, содержащее все остальные числа.
Даны п множеств, заполненных произвольным количеством целых случайных равномерно распределенных чисел из интервала [о; Ь\. Требуется:
а)вывести все элементы, которые встречаются в каждом втором множестве (нумерация множеств выполняется с единицы);
б)вывести элементы, которые есть во всех множествах кроме последнего;
в)вывести элементы множеств с нечетными номерами, которых нет в множествах с четными номерами (нумерация множеств выполняется с единицы);
г)определить, какие из элементов не встречаются ни в каких множествах, кроме первого.
д)определить, какие из чисел интервала [а; Ь\ не встречаются ни в одном из множеств;
е)вывести элементы, встречающиеся только в к-м множестве (нумерация множеств выполняется с единицы).
Уровень сложности В
Дан текст из цифр и строчных латинских букв, после которых следует точка. Определить, каких букв, гласных (а, е, i, о, и) или согласных, больше в этом тексте.
Определить количество различных цифр в десятичной записи натурального числа.
Напечатать в возрастающем порядке все цифры, не входящие в запись заданного натурального числа.
Дан текст из строчных латинских букв, после которых следует точка. Напечатать все буквы, входящие в этот текст не менее двух раз.
Дан текст из строчных латинских букв, после которых следует точка. Напечатать все буквы, входящие в этот текст по одному разу.
Дан текст из строчных русских букв, после которых следует точка. В алфавитном порядке напечатать все строчные гласные буквы (а, е, и, о, у, ы, э, ю, я), входящие в этот текст.
Дан текст на русском языке. Напечатать в алфавитном порядке все гласные буквы, которые входят в каждое слово этого текста.
Дан текст на русском языке. Напечатать в алфавитном порядке все согласные буквы, которые не входят ни в одно слово этого текста.
Дан текст на русском языке. Напечатать в алфавитном порядке все звонкие согласные буквы, входящие в каждое нечетное слово и не входящие ни в одно четное слово этого текста.
Дан текст на русском языке. Напечатать в алфавитном порядке все звонкие согласные буквы, которые входят хотя бы в одно слово этого текста.
Дан текст на русском языке. Напечатать в алфавитном порядке все глухие согласные буквы, которые не входят хотя бы в одно слово этого текста.
Дан текст на русском языке. Напечатать в алфавитном порядке все согласные буквы, которые входят только в одно слово этого текста.
Дан текст на русском языке. Напечатать в алфавитном порядке все глухие согласные буквы, которые не входят только в одно слово этого текста.
Дан текст на русском языке. Напечатать в алфавитном порядке все звонкие согласные буквы, которые входят более чем в одно слово этого текста.
Дан текст на русском языке. Напечатать в алфавитном порядке все гласные буквы, которые не входят более чем в одно слово этого текста.
Дан текст на русском языке. Напечатать в алфавитном порядке все глухие согласные буквы, которые входят в каждое нечетное слово и не входят хотя бы одно четное слово этого текста.
Слова в тексте разделены пробелами. Напечатать буквы, которых нет в первом слове, но которые присутствуют во всех других словах этого текста.
Слова в тексте разделены пробелами. Напечатать в алфавитном порядке буквы, которые встречаются хотя бы один раз в четных словах.
Слова в тексте разделены пробелами. Напечатать в алфавитном порядке буквы, которые встречаются хотя бы один раз в нечетных словах.
Слова в тексте разделены пробелами. Определить, сколько разных букв встречается в этом тексте.
Слова в русском тексте разделены пробелами. Определить, сколько букв русского алфавита не встречается в этом тексте.
Слова в тексте с датами разделены пробелами. Определить, какие цифры содержатся в этом тексте.
Слова в тексте разделены пробелами. Определить, с каких букв начинаются слова этого текста.
Слова в тексте разделены пробелами. Определить, какие буквы есть в каждом слове этого текста.
Слова в тексте разделены пробелами. Определить, какие буквы встречаются только в одном слове этого текста.
В строке содержится запись арифметического выражения. Определить, какие арифметические операции использованы в этом выражении.
В строке содержится запись арифметического выражения. Определить, какие цифры есть в этом выражении.
В строке содержится запись арифметического выражения. Определить, каких цифр нет в этом выражении.
В строке содержится запись арифметического выражения. Определить, есть ли в записи этого выражения скобки.
Слова в тексте разделены пробелами. Определить, есть ли в этом тексте слова, начинающиеся с заданной буквы.
Тема «Записи»Распечатать список учеников, фамилии которых начинаются на букву «В», и указать даты их рождения.
Из имеющегося списка спортсменов распечатать данные о тех из них, кто занимается плаванием. Указать возраст и сколько лет они занимаются спортом.
Вычислить средний балл успеваемости учеников класса, если известны оценки каждого из них по математике, русскому языку и физике. Распечатать список учеников, имеющих средний балл выше среднего балла в классе.
Распечатать фамилии рабочих бригады, начинающиеся с букв «А» и «С», с указанием их месячной зарплаты.
Из ассортимента конфет, выпускаемых пермской кондитерской фабрикой, выбрать наименования, стоимость 1 кг которых составляет от 100 до 150 р. Указать срок годности этих конфет и номера магазинов, в которых они имеются в продаже.
Распечатать список учеников музыкальной школы, которые учатся играть на скрипке. Указать, сколько лет они занимаются музыкой и принимали ли участие в каких-либо конкурсах.
Найти фамилии работников данного предприятия, чья заработная плата за месяц ниже средней по этому предприятию, а также распечатать список проработавших здесь более 10 лет с указанием их фамилий, зарплаты, стажа работы и должности.
Распечатать фамилии учеников школы, не получивших ни одной «тройки» за последнюю четверть. Определить, в каких классах учатся эти ученики и каков средний балл их успеваемости.
Распечатать фамилии детей детского сада, которые родились в заданном месяце с указанием их возраста и группы.
Распечатать список учителей школы, которые преподают математику и информатику с указанием стажа их работы и недельной нагрузки.
Распечатать анкетные данные учеников, участвовавших в олимпиаде по информатике и получивших не менее 30 баллов.
Распечатать фамилии учеников класса, которые являются хорошистами и отличниками по итогам года. Указать, на сколько их средний балл отличается от среднего балла класса.
Имеются сведения об учениках класса. Определить среднюю массу мальчиков, средний рост девочек и кто из учеников класса самый высокий.
Результаты переписи населения хранятся в памяти ЭВМ. Напечатать фамилии, имена и определить общее число жителей, родившихся после 1990 г.
При поступлении в университет абитуриенты, получившие неудовлетворительную оценку на первом экзамене, ко второму экзамену не допускаются. Считая фамилии абитуриентов и их оценки после первого экзамена исходными данными, составить список допущенных ко второму экзамену.
Назначить стипендии студентам по результатам сессии, используя следующие правила:
а)если все оценки 5 баллов, назначается повышенная стипендия;
б)если оценки 4 и 5 баллов, назначается обычная стипендия;
в)если есть оценка 3 балла, стипендия не назначается.
В результате должны быть напечатаны список группы с оценками и средним баллом каждого студента и два списка студентов, которым назначены повышенная и обычная стипендии.
В таблице хранятся следующие данные об учениках: фамилия, имя, отчество, рост, масса. Вычислить средний рост учеников, а также рост самого высокого и самого низкого учеников. Определить, сколько учеников могут заниматься в баскетбольной секции, если рост баскетболиста должен быть больше 170 см.
В аптечном складе хранятся лекарства. В специальной ведомости содержатся сведения о лекарствах: наименование препарата, его количество, цена и допустимый срок хранения в месяцах. Определить, сколько стоят самый дорогой и самый дешевый препараты; сколько нименований препаратов хранится на складе, какой препарат имеет срок хранения более трех месяцев и сколько стоят все препараты, хранящиеся на складе.
В столовой предлагается N комплексных обедов, состоящих из Q блюд. Известны стоимость и калорийность каждого блюда. Определить, сколько стоят самый дешевый и самый дорогой обеды и сколько калорий содержит самое калорийное блюдо.
Торговый склад производит уценку хранящейся продукции: если продукция хранится на складе больше п месяцев, она уценивается в 2 раза, а если срок ее хранения превысил т месяцев (где т < п), но не достиг п, в 1,5 раза. Ведомость уценки должна содержать следующую информацию: наименование товара, количество товара, цена товара до уценки, срок хранения товара, цена товара после уценки, общая стоимость товара до уценки, общая стоимость товара после уценки. Определить максимальный и минимальный сроки хранения товаров на складе, а также максимальную и минимальную стоимость товаров до уценки и после уценки.
В соревнованиях принимают участие 7V спортсменов-многоборцев по М видам спорта. По каждому виду спорта спортсмен набирает определенное количество очков. Вычислить сколько очков в сумме набрал каждый спортсмен после окончания соревнований, а также разницу в очках спортсменов, занявших первое и последнее места.
Тестирование проходили N учеников по М тестам предмета. Определить, сколько очков набрал каждый ученик по всем темам, а также средний балл, полученный учениками, и разницу между лучшим результатом и средним баллом.
Описать переменную «служащий», включающую в себя имя, фамилию, отчество служащего, дату его рождения, сведения об образовании, профессии и домашний адрес. Определить имена служащих с высшим образованием и получить данные о служащих, имеющих указанную профессию.
Описать переменную «круг», содержащую все данные для построения круга в декартовой системе координат. Определить координаты центра, площадь и длину окружности круга с минимальным радиусом, содержащего внутри себя все заданные круги. Рассматривая окружности попарно, определить координаты точек пересечения или точки касания для каждой пары либо вывести сообщение об отсутствии общих точек.
Описать переменную «экзаменационная ведомость», содержащую следующие сведения: наименование предмета, номер группы, номера зачетных книжек, фамилии и инициалы студентов, а также их оценки по итогам текущей сессии. Определить, сколько в группе отличников, хорошистов, троечников и двоечников.
Создать записи, определяющие положение точки в декартовой и полярной системах координат. По заданному массиву координат точек в декартовой системе получить соответствующий массив координат заданных точек в полярной системе.
Дан массив квадратных трехчленов, каждый из которых имеет комплексные коэффициенты. Сформировать массив корней этих трехчленов и массив их значений в точке х= с + di.
Дан массив записей, содержащих дату (число, месяц, год) и время (час, минута, секунда). Упорядочить этот массив данных в порядке возрастания, т.е. от более ранних значений к более поздним.
Описать переменную «расписание», содержащую следующие данные: день недели, количество учебных пар в указанный день, время начала и конца каждой пары, название предмета, фамилию преподавателя. Вывести всю информацию о занятиях, относящихся к предметной области «Информатика».
В библиотеке имеются книги, газеты, журналы. Для каждого печатного издания указать: название; год выпуска (для книг) или дату выпуска (для газет и журналов); фамилии автора (для книги), редактора (для газеты) или членов редколлегии (для журнала); объем. Вывести информацию об изданиях, вышедших в заданном году.
Задать запись, содержащую информацию о движении электропоездов из указанного города: направление, время отправления, время нахождения в пути до конечного пункта, стоимость билетов по зонам. Вывести перечень электропоездов, следующих в заданном направлении.
Тема «Файлы»Типизированные числовые файлы
Заполнить файл последовательного доступа /целыми числами, полученными с помощью генератора случайных чисел. Получить в файле g компоненты файла /, являющиеся четными.
Записать в файл последовательного доступа N действительных чисел. Вычислить произведение компонентов файла и вывести их на печать.
Заполнить файл последовательного доступа / целыми числами, полученными с помощью генератора случайных чисел. Получить в файле g все компоненты файла/, которые делятся на т и не делятся на п.
Записать в файл последовательного доступа N целых чисел, полученных с помощью генератора случайных чисел. Определить количество пар противоположных чисел среди компонентов этого файла.
Заполнить файл последовательного доступа /целыми числами, полученными с помощью генератора случайных чисел. Из файла / получить файл g, исключив повторные вхождения чисел. Вывести файл g на печать.
Записать в файл последовательного доступа 7V произвольных натуральных чисел. Переписать в другой файл последовательного доступа числа, кратные К. Вывести полученный файл на печать.
Заполнить файл последовательного доступа действительными числами, полученными с помощью датчика случайных чисел. Найти сумму минимального и максимального чисел этого файла.
Записать в файл последовательного доступа N натуральных чисел: аи а2, ..., ат полученных с помощью датчика случайных чисел. Сформировать новый файл последовательного доступа с числами аи а{а2, а{а2а3, ..., а{а2а3 х ... х ап.
Записать в файл /последовательного доступа N натуральных чисел. Получить в другом файле последовательного доступа все числа файла/ кроме чисел, кратных К. Вывести полученный файл на печать.
Заполнить файл / целыми числами, полученными с помощью генератора случайных чисел. Найти количество удвоенных нечетных чисел среди компонентов этого файла.
Заполнить файл / натуральными числами, полученными с помощью генератора случайных чисел. Найти количество квадратов нечетных чисел среди компонентов этого файла.
Записать в файл прямого доступа действительных чисел. Найти наибольшее из модулей компонентов с нечетными номерами этого файла.
Заполнить файл / целыми числами, полученными с помощью генератора случайных чисел. Из файла / получить файл g, исключив повторные вхождения чисел. Порядок следования чисел сохранить.
Записать в файл последовательного доступа ./V действительных чисел. Найти разность первого и последнего чисел этого файла.
В файл / записать N целых чисел, полученных с помощью генератора случайных чисел. Заполнить файл g числами, которые являются произведениями соседних чисел файла /
Записать в файл последовательного доступа п элементов
последовательности Ь„ =
1 1__L
2! + 3! 4!+
. + (-1)"-'
1
п\
Вывести на
печать компоненты этого файла, для которых выполняется условие \Ь„\ > е (где е — заданное число).
Записать в файл последовательного доступа N действительных чисел ah а2, ..., а„. Создать новый файл последовательного
1*
доступа, элементы которого вычисляются по формуле Ь =—
Вывести полученный файл на печать.
Файлы записей
Багаж пассажира характеризуется количеством и общей массой вещей. Дан файл Bagazh, содержащий сведения о багаже нескольких пассажиров. Сведения о багаже каждого пассажира представляют собой запись с двумя полями: одно поле целого типа (количество вещей) и одно поле действительное (масса вещей в килограммах). Определить:
а)багаж, средняя масса одной вещи в котором отличается не более чем на т [кг] от общей средней массы одной вещи;
б)число пассажиров, имеющих более двух вещей, и число пассажиров, количество вещей которых превосходит среднее;
в)имеется ли пассажир, багаж которого состоит из одной вещи массой менее т [кг].
Дан файл Bibl, содержащий сведения о книгах. Сведения о каждой из книг включают в себя фамилию автора, название книги и год издания. Определить:
а)названия книг указанного автора, изданных с 1960 г.;
б)имеется ли книга с названием «Информатика». Если имеется, вывести на печать фамилию ее автора и год издания. Если таких книг несколько, вывести имеющиеся сведения обо всех этих книгах.
Дан файл Т, содержащий номера телефонов сотрудников учреждения с указанием их фамилий и инициалов. Найти номер телефона сотрудника по его фамилии и инициалам.
Дан файл, содержащий различные даты, включающие в себя число, месяц и год. Найти:
а)год с наименьшим номером;
б)все весенние даты;
в)самую позднюю дату.
Дан файл Tovar, содержащий сведения об экспортируемых товарах с указанием наименований этих товаров, стран-импорте- ров и объемов поставляемых партий в штуках.
Составить список стран, в которые экспортируется заданный товар, и общий объем его экспорта.
Дан файл Assort, содержащий сведения об игрушках: название игрушки, ее стоимость в рублях и возрастные границы (например, игрушка может предназначаться для детей от двух до пяти лет). Определить:
а)названия игрушек, цена которых не превышает 14 тыс. р. и которые подходят детям пяти лет;
б)стоимость самого дорогого конструктора;
в)названия наиболее дорогих игрушек (цена которых отличается от цены самой дорогой игрушки не более чем на 5 тыс. р.);
г)названия игрушек, которые подходят детям и четырех, и десяти лет;
д)можно ли подобрать игрушку (любую, кроме мяча), подходящую ребенку трех лет;
е)название самой дешевой игрушки;
ж)название самой дорогой игрушки для детей до четырех лет;
з)названия игрушек для детей от четырех до пяти лет;
и)название самой дорогой игрушки, подходящей детям от двух до трех лет;
л)стоимость самой дорогой куклы;
м)стоимость кукол для детей шести лет;
н)для детей какого возраста предназначается конструктор;
о)для детей какого возраста предназначены кубики и указать их среднюю стоимость.
Дан файл TV, содержащий сведения о программах телепередач на неделю: день недели, время, канал, вид и название телепередачи. Определить:
а)названия телепередач, которые идут в указанный день в указанный промежуток времени;
б)названия телепередач, которые идут в указанный день на указанном канале;
в)информацию об указанном фильме. Если этот фильм не указан в телепрограмме, вывести на экран сообщение «Такой передачи на данной неделе нет»;
г)на каком канале и в какое время будет транслироваться развлекательная передача «Поле чудес»;
д)есть ли передача, транслирующаяся больше одного раза в одно и то же время, и если есть, то какая;
е)названия телепередач, транслирующихся в указанное время на разных каналах;
ж)название самой продолжительной передачи в понедельник;
з)название передачи, завершающей эфир в каждый день недели.
Дан файл, содержащий сведения о безработных: специальность, опыт работы, образование, пол, возраст. Требуется:
а)подобрать кандидатов на должность врача с опытом работы не менее пяти лет;
б)найти работников с высшим экономическим образованием не старше 35 лет;
в)найти работников, имеющих опыт работы в сфере торговли;
г)получить полную информацию обо всех женщинах в возрасте от 20 до 40 лет;
д)определить средний возраст всех мужчин, ищущих работу;
е)выяснить, кого в базе данных больше с высшим образованием: женщин или мужчин;
ж)найти п самых молодых работников.
Текстовые файлы Уровень сложности А
Исходные текстовые файлы для следующих задач создаются с помощью какого-либо текстового редактора.
Дан файл, содержащий текст, набранный строчными русскими буквами. Получить в другом файле тот же текст, записанный прописными буквами.
Дан файл, содержащий произвольный текст. Определить, чего в нем больше: русских букв или цифр.
Дан файл, содержащий текст на русском языке. Определить, входит ли заданное слово в указанный текст, и если входит, то сколько раз.
Дан файл, содержащий текст на русском языке. В предложениях некоторые слова повторяются подряд несколько раз (предложения заканчиваются точкой или знаком восклицания). Получить в новом файле отредактированный текст, в котором удалены повторные вхождения слов в предложения.
Дан файл, содержащий текст, набранный прописными русскими буквами. Провести частотный анализ текста, т.е. указать (в процентах) сколько раз встречается та или иная буква.
Дан файл, содержащий текст на русском языке. Определить, сколько раз встречается в нем самое длинное слово.
Дан файл, содержащий произвольный текст. Проверить, правильно ли в нем расставлены круглые скобки (т.е. находится ли правее каждой открывающейся скобки закрывающаяся, и левее каждой закрывающейся — открывающаяся).
Дан файл, содержащий текст на русском языке. Составить в алфавитном порядке список всех слов, встречающихся в этом тексте.
Дан файл, содержащий текст на русском языке. Определить, сколько раз встречается в нем самое короткое слово.
Дан файл, содержащий текст на русском языке и два слова. Определить, сколько раз эти два слова входят в текст и сколько раз они располагаются непосредственно друг за другом.
Дан файл, содержащий текст на русском языке. Выбрать из него буквы, встречающиеся только один раз в порядке их расположения.
Дан файл, содержащий текст и арифметические выражения вида а <8> Ь, где ® — один из арифметических знаков (+, -, *, /). Выписать все арифметические выражения и вычислить их значения.
Дан файл, содержащий текст на русском языке и букву. Найти слою, в котором указанная буква содержится наибольшее число раз.
Дан файл, содержащий текст на русском языке и букву. Определить, сколько слов начинается с этой буквы.
Дан файл, содержащий текст на русском языке. Найти слово, встречающееся в каждом предложении этого текста, или сообщить, что такого слова нет.
Дан файл, содержащий текст, включающий в себя русские и английские слова. Определить, каких букв в тексте больше: русских или латинских.
Дан файл, содержащий текст. Определить, сколько слов в этом тексте и сколько цифр.
Дан файл, содержащий текст, включающий в себя русские и английские слова. Получить новый файл, заменив в исходном тексте все прописные буквы строчными, и наоборот.
Дан файл, содержащий зашифрованный русский текст, т.е. каждая буква исходного текста заменена следующей за ней буквой, а буква «я» заменена буквой «а». Получить в новом файле расшифровку заданного текста.
Даны два текстовых файла и /2. Файл /j содержит произвольный текст, слова в котором разделены пробелами и знаками препинания. Файл /2 содержит не более 30 слов, которые попарно разделены запятыми, причем каждое второе слово в паре является синонимом первого. Получить новый файл, заменив слова в файле f по возможности синонимами из файла f2.
Дан текстовой файл. Удалить из него все лишние пробелы, оставив не более одного пробела между словами. Результат поместить в новый файл.
Даны текстовой файл и слово. Напечатать строки файла, содержащие указанное слово.
Дан текстовой файл. Напечатать в алфавитном порядке все слова из этого файла, имеющие заданную длину п.
Текстовой файл содержит запись многочлена некоторой степени с одной переменной х. Коэффициентами этого многочлена являются целые числа. (Например, 5хЛ4-ЗхЛ3 + 15хл2-4.) Определить степень заданного многочлена и его коэффициенты. Дописать в данный файл таблицу значений указанного многочлена в интервале [а; Ь\.
Дан файл, содержащий текст на русском языке. Определить количество слов в этом тексте, начинающихся и заканчивающихся на одну и ту же букву.
Уровень сложности В
Исходные текстовые файлы создаются для следующих задач заполнением их с помощью датчика случайных чисел.
Дан файл, содержащий вещественные числа. Найти минимальное число.
Дан файл, содержащий натуральные числа. Найти число с максимальной суммой цифр.
Дан файл, содержащий целые числа. Определить число с максимальным произведением цифр.
Дан файл, содержащий натуральные числа. Получить новый файл, записав цифры каждого из заданных чисел в обратном порядке.
Дан файл, содержащий вещественные числа. Определиь интервал, которому принадлежат все числа этого файла.
Дан файл, содержащий натуральные числа. Определить количество чисел этого файла, оканчивающихся заданной цифрой.
В заданном файле определить максимальное количество подряд идущих положительных чисел.
Найти сумму элементов файла, содержащего натуральные числа, которые оканчиваются на заданную цифру.
Найти сумму четных элементов файла, содержащего целые числа.
Определить количество нечетных отрицательных элементов в файле, содержащем целые числа.
Определить минимальное нечетное число в файле, содержащем целые числа.
Дан файл, содержащий натуральные числа. Получить новый файл, приписав к каждому из чисел исходного файла цифру к.
Напечатать True, если заданный файл вещественных чисел упорядочен, и False — в противном случае.
Имеется упорядоченный файл. Вставить в него заданное число таким образом, чтобы упорядоченность сохранилась.
Прочитать из файла двухмерный массив чисел размером п х т, транспонировать его и записать полученную матрицу в новый файл. (В первой строке файлов записывается размер массива.)
Дан файл. Сравнить в нем количество положительных и отрицательных чисел. Если положительных чисел больше, дописать в конце этого файла I, если больше отрицательных чисел, дописать -1, а если их равное количество, дописать 0.
Дан файл, в котором имеется единственный элемент, нарушающий его упорядоченность. Удалить этот элемент.
Дан упорядоченный файл. Дописать в начале и конце этого файла по одному числу таким образом, чтобы упорядоченность сохранилась.
Сформировать из элементов данного файла матрицы второго порядка и указать среди них матрицу с наибольшим определителем. (Если для последней матрицы элементов файла недостает, дополнить матрицу нулями.)
Дан файл. Переписать его элементы в два новых файла: в один — элементы, которые меньше среднего арифметического всех компонентов заданного файла, а в другой — которые больше.
Используя вещественные величины из заданного файла как аргументы функции у = cos х, получить в новом файле эти аргументы и соответствующие им значения в виде двух столбцов.
Используя вещественные величины из заданного файла как аргументы функции y = cos х, определить, какому аргументу соответствует наименьшее значение этой функции.
Определить, какое количество элементов заданного файла входит в указанный интервал.
Дан файл натуральных чисел. Просуммировать числа этого файла, начинающиеся с указанной цифры.
Дан файл натуральных чисел. Найти среди чисел с указанным количеством цифр минимальное.
Определить, какое число в заданном файле целочисленных величин встречается чаще других.
Из файла /получить файл g, исключив повторные вхождения чисел и сохранив порядок их следования.
Дан файл вещественных величин. Заменить элементы в нем значениями, округленными до целых чисел.
Заменить элементы заданного файла абсолютными значениями и указать количество выполненных замен.
Дан файл. Дописать в конце этого файла первую цифру каждого из составляющих его чисел в порядке их следования.
Тема «Модули»Реализовать в виде модуля набор подпрограмм для выполнения следующих операций с комплексными числами:
сложение;
вычитание;
умножение;
деление;
модуль;
возведение в степень п (где п — натуральное число). Комплексное число представить следующим образом:
Туре Complex = Record R : Real; M : Real End;
Используя разработанный модуль, решить следующие задачи:
а)дан массив А комплексных чисел. Получить массив С, элементами которого будут модули сумм рядом стоящих комплексных чисел;
б)дан массив А [М] комплексных чисел. Получить матрицу B[N, Л/], каждая строка которой является результатом возведения в степень, равную номеру этой строки, заданного массива А.
Реализовать в виде модуля набор подпрограмм для выполнения следующих операций с обыкновенными дробями вида — (где
Р — целое число, Q — натуральное число):
сложение;
вычитание;
умножение;
деление;
сокращение;
возведение в степень п (где п — натуральное);
отношения (равно, не равно, больше или равно, меньше или равно, больше, меньше) в форме функции.
Дробь представить следующим образом:
Type Frac = Record
Р : Integer; Q : 1..32767 End;
Используя разработанный модуль, решить следующие задачи:
а)дан массив А обыкновенных дробей. Найти сумму всех дробей массива, и представить ответ в виде несократимой дроби. Вычислить среднее арифметическое всех дробей массива, и представить ответ в виде несократимой дроби;
б)дан массив А обыкновенных дробей. Отсортировать его в порядке возрастания.
Реализовать в виде модуля набор подпрограмм для выполнения следующих операций с квадратными матрицами:
сложение двух матриц;
умножение одной матрицы на другую;
нахождение транспонированной матрицы;
вычисление определителя матрицы.
Матрицу описать следующим образом:
Const NMax = 10;
Type Matrica = Array [l..NMax, l..Nmax] Of Real;
Используя разработанный модуль, решить следующие задачи:
а)систему линейных уравнений TV-го порядка (2 < TV < 10) методом Крамера;
б)отсортировать заданный массив величин типа Matrica в порядке возрастания значений определителей матриц;
в)найти матрицу С, равную А х В - В х А, если заданы величины А и В типа Matrica.
Реализовать в виде модуля набор подпрограмм для выполнения следующих операций с векторами:
сложение;
вычитание;
скалярное умножение;
умножение на число;
определение длины вектора.
Вектор представить следующим образом:
Type Vector = Record X, Y : Real End;
Используя разработанный модуль, решить следующие задачи:
а)дан массив А векторов. Отсортировать его в порядке убывания длин векторов;
б)с помощью датчика случайных чисел создать 2N целых чисел, если 7V пар этих чисел задают N точек координатной плоскости. Вывести на печать номера точек, являющихся координатами вершин треугольника с наибольшим углом.
Реализовать в виде модуля набор подпрограмм для выполнения следующих операций с натуральными числами в Р-ичной системе счисления (2 < Р < 9):
сложение;
вычитание;
умножение;
деление;
перевод из десятичной системы в Личную;
перевод из Личной системы в десятичную;
проверка правильности записи числа в Личной системе в виде функции;
отношения (равно, не равно, больше или равно, меньше или равно, больше, меньше) в виде функции.
Личное число представить следующим образом:
Type Chislo = Array [1..16] Of 0..9;
Используя разработанный модуль, решить следующие задачи:
а)возвести число в степень, основание и показатель которой записаны в Линой системе счисления. Ответ получить в Личной и десятичной системах счисления;
б)дан массив А чисел, записанных в Личной системе счисления. Отсортировать его в порядке убывания. Ответ получить в Личной и десятичной системах счисления.
Реализовать в виде модуля набор подпрограмм для выполнения следующих операций с натуральными числами в шестнадцатеричной системе счисления:
сложение;
вычитание;
умножение;
деление;
перевод из двоичной системы в шестнадцатеричную;
перевод из шестнадцатеричной системы в десятичную;
проверка правильности записи числа в шестнадцатеричной системе счисления в виде функции;
отношения (равно, не равно, больше или равно, меньше или равно, больше, меньше) в виде функции.
Используя разработанный модуль, решить следующие задачи:
а)возвести число в степень, основание и показатель которой записаны в шестнадцатеричной системе счисления. Ответ получить в шестнадцатеричной и десятичной системах счисления;
б)дан массив А чисел, записанных в шестнадцатеричной системе счисления. Отсортировать его в порядке убывания. Ответ получить в шестнадцатеричной и десятичной системах счисления.
Определим граф как набор точек, некоторые из которых соединены линиями, а подграф как граф или подмножество данного графа.
Реализовать в виде модуля набор подпрограмм, определяющих:
число точек в графе;
число отрезков в графе;
число изолированных подграфов в графе, т. е. подграфов, не соединенных линиями;
диаметр графа, т.е. длину максимальной незамкнутой линии в графе (длина каждого звена — 1);
граф — объединение двух графов;
подграф — пересечение двух графов;
подграф — дополнение заданного графа до полного (графа с тем же количеством вершин, что и в заданном, и с линиями между любыми двумя вершинами);
число отрезков, выходящих из каждой вершины графа;
При запуске должны инициализироваться следующие переменные: Full_Graph — полный граф с числом вершин NumberOfVertix; NuIl_Graph — граф без отрезков с числом вершин NumberOfVertix.
Граф представить как объект:
Const NumberOfVertix = 50;
Type Graph = Array[1..NumberOfVertix,
1.. NumberOfVertix] Of Boolean;
Используя разработанный модуль, найти все правильные графы из N вершин. (Граф является правильным, если из всех вершин выходит равное количество отрезков.)
Реализовать в виде модуля набор подпрограмм для выполнения следующих операций с длинными числами:
сложение;
вычитание;
умножение;
нахождение частного и остатка от деления одного числа на другое;
отношения (равно, не равно, больше или равно, меньше или равно, больше, меньше) в виде функции.
Длинное число представить следующим образом:
Type Tsifra = 0..9;
Chislo = Array [1..1000] Of Tsifra;
Используя разработанный модуль, решить следующие задачи:
а)возвести число в степень, основание и показатель которой — длинные числа;
б)дан массив длинных чисел. Упорядочить этот массив в порядке убывания.
Реализовать в виде модуля набор подпрограмм для выполнения следующих операций с многочленами от одной переменной (где первый многочлен степени т, второй — степени п):
сложение;
вычитание;
умножение;
деление с остатком;
отношения (равно, не равно);
возведение в натуральную степень к;
вычисление производной от многочлена;
вычисление значения в точке х$.
Многочлен представить следующим образом:
Type Mnogochlen = Array [1..500] Of Integer;
Используя разработанный модуль, решить следующие задачи:
а)найти наибольший общий делитель многочленов Р(х) и Q(x).
б)вычислить выражение Ps(x) - Qr(x).
Разработать способ представления множеств, содержащих более 255 элементов (до 2 000), и создать модуль, позволяющий выполнять следующие операции с элементами таких множеств:
объединение;
пересечение;
вычитания;
проверка принадлежности элемента множеству;
проверка, является ли данное множество подмножеством (надмножеством) другого в виде функции.
Используя созданный модуль, решить следующие задачи:
а)дан массив множеств. Упорядочить элементы этого массива в порядке возрастания количества компонентов соответствующих множеств;
б)ввести несколько множеств и выражение, операндами которого являются эти множества, с операциями объединения, пересечения и вычитания. Вычислить значение этого выражения и вывести результат.
Реализовать модуль для работы с базой данных определенной структуры (задать самостоятельно), хранящейся в файле. Предусмотреть следующие действия:
добавление записи в базу в конец файла;
удаление записи (записей) из базы по определенному критерию (заданному значению одного из полей);
сортировку записей в базе по одному из полей (т.е. разработку общего алгоритма сортировки с использованием нетипизиро- ванных параметров) и запись результата сортировки в новый файл;
выборку записей из базы по определенному критерию (заданному значению одного из полей) и запись их в другой файл;
добавление записи в отсортированную базу с сохранением упорядоченности по выбранному критерию.
Используя разработанный модуль, решить следующие задачи:
а)имеется две базы данных заданной структуры, упорядоченные по одному и тому же признаку. Добавить все компоненты второй базы в первую, сохранив ее упорядоченность;
б)выбрать и поместить в текстовый файл записи, отвечающие двум-трем критериям одновременно.
Разработать модуль для работы с обыкновенными дробями, числителем и знаменателем которых являются длинные числа.
При описании использовать следующие типы:
Type Dl_Ch = Array[1..1024] Of 0..9;
Drob = Record Chisl, Znam : Dl_Ch End;
В модуле должны быть представлены следующие операции:
сложение;
вычитание;
умножение;
деление;
сокращение;
выделение целой части;
отношения в виде логических функций.
Используя разработанный модуль, найти разность минимального и максимального элементов заданного массива обыкновенных дробей.
Разработать в виде модуля набор подпрограмм для выполнения следующих операций с числами, записанными в римской системе счисления:
перевод натурального числа из десятичной системы счисления в римскую;
перевод числа из римской системы счисления в десятичную;
сложение;
вычитание;
умножение;
целочисленное деление и нахождение остатка от деления;
отношения (всех шести) в виде логических функций.
Используя разработанный модуль, решить следующие задачи:
а)дан массив чисел, записанных в римской системе счисления. Выполнить сортировку этого массива и вывести ответ в десятичной и римской системах счисления;
б)даны два массива натуральных чисел. В одном из них числа записаны в десятичной системе счисления, в другом — в римской. Выписать числа, которые встречаются и в том, и в другом массиве, или сообщить об их отсутствии. В случае положительного ответа результат представить в римской и десятичной системах счисления.
Реализовать модуль, обеспечивающий работу стека — структуры данных, в которой доступным является единственный элемент, помещенный в эту структуру последним. (Здесь действует принцип «последний пришел, первый ушел». Указатель на доступный элемент называется вершиной стека.)
Стек описать следующим образом:
Type Stek = Record А : Array[1..1024] Of Integer;
Vershina : 0..1025 End;
Разработываемый модуль должен содержать следующие подпрограммы:
включение элемента в стек;
извлечение элемента из стека;
проверка стека на пустоту (вершина имеет значение 0);
проверка стека на переполнение (вершина имеет значение 1025);
проверка, равно ли число, на которое указывает вершина стека, заданному числу к.
Используя разработанный модуль, решить следующие задачи:
а)дан текстовый файл, в каждой строке которого содержится запись одного арифметического выражения в обратной польской записи. Вычислить значения каждого из этих выражений и в том же порядке дописать в конец файла;
б)перевернуть заданную строку, т. е. поместить в стек последовательно коды всех символов строки, а затем последовательно извлекать их и формировать новую строку.
Реализовать модуль для работы с длинными строками.
Длинную строку определить следующим образом:
Type LongString = Array[1..4] Of String;
Разрабатываемый модуль должен содержать подпрограммы, позволяющие:
вводить длинную строку;
выводить длинную строку;
выполнять операции с длинными строками (склеивания, отношения);
дублировать процедуры и функции, принятые для строки обычного типа String.
Используя разработанный модуль, решить следующие задачи:
а)отсортировать заданный массив длинных строк;
б)определить, сколько раз встречается заданная последовательность символов в длинной строке, воспользовавшись аналогом функции Pos.
Тема «Динамические структуры данных»х .
Вставить в список L новый элемент /за каждым вхождением элемента Е.
Вставить в список L новый элемент /'перед первым вхождением элемента Е, если Е входит в L.
Вставить в непустой список L, элементы которого упорядочены по неубыванию, новый элемент Е, сохранив упорядоченность.
Удалить из списка L все элементы Е, если они есть в списке.
Удалить из списка L за каждым элементом Е один элемент, если такой есть и он отличен от Е.
Удалить из списка L все отрицательные элементы.
Проверить, есть ли в списке L хотя бы два одинаковых элемента.
Перенести в конец непустого списка L его первый элемент.
Вставить в список L за первым вхождением элемента Е все элементы списка L, если Е входит в L.
Перевернуть список L, т.е. изменить ссылки в этом списке таким образом, чтобы его элементы оказались расположенными в обратном порядке.
В списке L из каждой группы подряд идущих одинаковых элементов оставить только один.
Сформировать список L, включив в него по одному разу элементы, входящие одновременно в списки Ц и L2.
Сформировать список L, включив в него по одному разу элементы, входящие в список Lu но не входящие в список L2.
Сформировать список L, включив в него по одному разу элементы, входящие только в один из списков: L{ или L
Многочлен Р(х) = а„хп + я„_1х"_| +- - + а1х + аъ с целыми коэффициентами можно представить в виде списка, причем если д, = 0, то соответствующее звено не включается в список:
=> п <*п => п- 1 => 1 Я1 => 0 До nil
Многочлен S(x) = 52Х40 - Зх8 + х можно представить в виде
=> 40 52 => 8 -3 => 1 1 nil
Описать на языке Паскаль тип данных, соответствующий такому представлению многочленов, и определить следующие процедуры и функции для работы с этими списками-многочленами:
а)логическую функцию Ravno(P, Q), проверяющую на равенство многочлены Р и Q;
б)функцию Znach (Р, х), вычисляющую значение многочлена Р в целочисленной точке х;
в)процедуру Diff(P, Q), строящую многочлен Q— производную многочлена Р;
г)процедуру Slozh(P, Q, R), строящую многочлен R— сумму многочленов Qu Р;
д)процедуру Print (Р, v), печатающую многочлен Р как многочлен от переменной, однобуквенное имя которой является значением литерного параметра v. Например, для указанного ранее многочлена S процедура Print (S, 'у') должна напечатать 52yt40 - - 3yt8 + у;
е)процедуру Vvod(P), считывающую из входного файла безошибочную запись многочлена (см. п. «д») (за ней пробел) и формирующую соответствующий список-многочлен Р.
Для заданного многочлена Р(х) степени п получить многочлен Р2(х).
Для заданного многочлена Р(х) степени п получить многочлен Р(х +1)- Р(х) и определить степень полученного многочлена.
Упорядочить в порядке возрастания элементы однонаправленного списка.
Заполнить список последовательностью случайных различных целых чисел и просуммировать элементы этого списка, расположенные между минимальным и максимальным элементами (если минимальный элемент предшествует максимальному).
Дан список, содержащий целые числа. Сформировать из его элементов, абсолютные значения которых являются простыми числами, новый список.
Дан список, содержащий натуральные числа. Удалить из него элементы, кратные заданному числу к.
Дан список, элементами которого являются следующие векторы:
(Const NMax = 200; Type Vector = Array [l..NMax] Of Real;) .
Сформировать список из длин этих векторов.
Элементами списка являются имена существительные, записанные в именительном падеже (строки длиной не более 15 символов). Добавить за каждым существительным все его падежи.
Дан список, содержащий целые числа. Определить количество различных элементов этого списка.
Даны упорядоченные списки Ц и Ь2. Вставить элементы списка L2 в список Lu не нарушая его упорядоченности.
Дан список, содержащий запись неотрицательных целых чисел в двоичной системе счисления. Заменить каждый элемент списка его записью в шестнадцатеричной системе счисления.
Дан список, содержащий обыкновенные дроби вида —,
(где Р— целое число, Q — натуральное число). Просуммировать модули этих дробей. Ответ представить в виде обыкновенной несократимой дроби.
Найти среднее арифметическое элементов непустого однонаправленного списка вещественных чисел, заменить в нем все числа х на число у, поменять местами первый и последний элементы и проверить, упорядочены ли числа в списке по возрастанию.
Дан список вещественных чисел. Описать следующие функции:
а)проверки, есть ли в списке два одинаковых элемента;
б)переноса в начало списка последнего элемента;
в)переноса в конец списка первого элемента;
г)вставки этого списка за первым входящим в него числом х.
Дан список строк. Написать следующие подпрограммы:
а)изменить ссылки в списке таким образом, чтобы его элементы оказались расположены в противоположном порядке (обращение списка);
б)оставить в списке только один из каждой группы подряд идущих элементов;
в)оставить в списке только первые вхождения одинаковых элементов.
Даны два списка Lx и L2 пар вещественных чисел. Написать подпрограммы возвращения нового списка L, включающего в себя:
а)пары списка Lx, первая координата которых встречается как вторая координата пар списка L2;
б)пары (х, у) списка Lx, встречающиеся в виде (у, х) в списке L2,
в)пары (х, у) списка Lx, в которых х<у.
Даны два списка Lx и Ь2 вещественных чисел. Написать подпрограммы возвращения нового списка L, который включает в себя по одному разу следующие числа:
а)входящие одновременно в оба списка;
б)входящие хотя бы в один из списков;
в)входящие только в один из списков: Lx или L2;
г)входящие в список Lx, но не входящие в список 1^.
Целое длинное число представляется строкой цифр. Упорядочить по неубыванию цифры этого числа.
Дан список слов, среди которых есть пустые. Написать следующие подпрограммы:
а)переставляющую местами первое и последнее непустые слова;
б)печатающую текст из первых букв непустых слов;
в)удаляющую из непустых слов первые буквы;
г)определяющую количество слов в непустом списке, отличных от последнего слова.
Описать следующие рекурсивные функции или процедуры:
а)определяющую, входит ли элемент Е в список L;
б)подсчитывающую число вхождений элемента Е в список L\
в)находящую максимальный элемент непустого списка;
г)печатающую в обратном порядке элементы списка;
д)заменяющую в списке L все вхождения элемента Е\ на Ег\
е)удаляющую из списка L первое вхождение элемента Е, если оно имеется;
ж)удаляющую из списка L все вхождения элемента Е;
з)создающую список Lx — копию списка L;
и)удваивающую каждое вхождение элемента Е в список L;
к)находящую среднее арифметическое значение всех элементов непустого списка Ц
л)преобразующую однонаправленный простой список L в кольцевой и возвращающую адрес минимального элемента этого списка;
м)переставляющую отрицательные элементы списка L в его начало, не меняя при этом их порядок;
н)удаляющую из целочисленного списка все элементы, имеющие цифру к.
Описать процедуру, которая в списке L заменяет первое вхождение списка Ц (если оно имеется) на список Ь2.
Пусть L обозначает кольцевой (циклический) двунаправленный список с заглавным звеном, а Е — элемент, входящий в список. Описать следующую функцию или процедуру:
а)определяющую, является ли список L пустым;
б)печатающую в обратном порядке элементы непустого списка L;
в)подсчитывающую количество элементов списка L, у которых имеются равные «соседи»;
г)определяющую, есть ли в списке L хотя бы один элемент, равный следующему за ним (по кругу) элементу;
д)переставляющую в списке L в обратном порядке все элементы между первым и последним вхождениями элемента Е, если Е входит в L не менее двух раз;
е)удаляющую из списка L первый отрицательный элемент, если такой элемент есть;
ж)удаляющую из списка L, содержащего не менее двух элементов, все элементы, у которых имеются одинаковые «соседи» (первый и последний элементы также считать «соседями»);
з)добавляющую в конец списка L новый элемент Е;
и)удваивающую в списке L каждое вхождение элемента Е\
к)создающую список L по однонаправленному списку Lx\
л)добавляющую в конец непустого списка L все его элементы, располагая их в обратном порядке. Например, получение по списку из элементов 1, 2, 3 списка из элементов 1, 2, 3, 3, 2, 1.
Тема «Графика»Черчение
В треугольной пирамиде построить сечение, параллельное основанию.
В треугольной пирамиде построить сечение, проходящее через боковое ребро и медиану основания.
В треугольной пирамиде построить сечение, проходящее через одну из сторон основания и середину противоположного ребра.
В треугольной пирамиде построить сечение, проходящее через среднюю линию боковой грани и противоположную вершину основания.
В треугольной пирамиде провести сечение, проходящее через сторону основания и наклоненное к нему под углом 30°.
В правильной четырехугольной пирамиде провести сечение, проходящее через диагональ основания и вершину пирамиды.
В правильной четырехугольной пирамиде провести сечение, проходящее через диагональ основания и середину бокового ребра.
В правильной четырехугольной пирамиде провести сечение, проходящее через диагональ основания и наклоненное к нему под углом 30°.
В правильной четырехугольной пирамиде провести сечение, параллельное основанию и проходящее через середину бокового ребра.
В правильной четырехугольной пирамиде провести сечение, проходящее через вершину пирамиды и перпендикулярное плоскости основания.
В правильной четырехугольной пирамиде провести сечение, проходящее через одну из сторон основания и середину ее высоты.
Основание четырехугольной пирамиды — ромб. Вершина пирамиды проектируется в центр симметрии ромба. Провести сечение через высоту основания, опущенную из тупого угла ромба, и боковое ребро, проходящее через эту же вершину.
Основание четырехугольной пирамиды — ромб. Вершина пирамиды проектируется в вершину острого угла ромба. Провести сечение, проходящее через вершину пирамиды и высоту ромба, опущенную из тупого угла.
В прямоугольном параллелепипеде провести диагональное сечение.
В прямоугольном параллелепипеде провести сечение, проходящее через сторону нижнего основания и противоположную сторону верхнего основания.
В прямой четырехугольной призме провести сечение, проходящее через диагональ нижнего основания и одну из вершин верхнего основания.
В прямой четырехугольной призме провести сечение, проходящее через сторону нижнего основания под углом 30° к нему.
В правильной шестиугольной призме провести сечение, проходящее через одну из сторон нижнего основания и противоположную сторону верхнего основания.
В прямоугольном параллелепипеде построить сечение, проходящее через одну из сторон нижнего основания и одну из вершин верхнего основания.
В прямоугольном параллелепипеде построить сечение, проходящее через одно из его ребер и точку пересечения диагоналей противолежащей этому ребру грани.
В правильной шестиугольной пирамиде построить сечение, проходящее через ее вершину и большую диагональ основания.
В прямом цилиндре построить осевое сечение.
В правильной шестиугольной призме построить сечение, проходящее через большую диагональ ее нижнего основания и одну из сторон верхнего основания.
РисованиеСоставить программу получения на экране рисунков, изображенных в табл. 5.2.
Таблица 5.2
Заданные рисунки
1 2 ЩР I


23
24
25
C03D
26
27
28
Г
• •
29
30
31

Г'
f
XJ
32
t

5.16.3. Построение графиков
Построить графики функций, приведенных в подразд. 5.2.2 и 5.4.4.

Тема «Объектно-ориентированное программирование»Спроектировать простое меню в одной строке экрана, которое обеспечивает перебор пунктов нажатием клавиши пробела, позволяет зафиксировать выбор нажатием клавиши <Enter> или отказаться от выбора нажатием клавиши <Esc>. После выбора одного из пунктов в программу должно возвращаться какое-то значение, связанное с этим пунктом, например какой-то символ, а при отказе от выбора — символы #27.
Перед началом работы следует передать меню названия пунктов и возвращаемые символы (которыми могут быть первые буквы пунктов или какие-то специальные символы), что можно сделать в форме строки вида
«Первое Второе Третье» или
«Первое (а) Второе (Ь) Третье (с)»
Здесь за названием пункта следует в скобках возвращаемый символ.
Состояние меню характеризуется его координатами на экране, номером отмеченного пункта, общим числом пунктов, перечнем названий пунктов и возвращаемых символов (во втором варианте представления).
Методами объекта являются:
Init — заполняет поле названий пунктов, подсчитывает число пунктов, делает выбранным первый пункт;
Select — позволяет выбрать пункт меню и возвращает символ выбранного пункта, а при отказе от выбора возвращает символы #27;
Draw — рисует меню, выделяя выбранный пункт цветом;
LeftBoard — возвращает начало названия данного пункта;
Len — возвращает длину названия пункта;
WhatSel — возвращает символ выбранного пункта.
Создать новый объект TNeatMenu — «наследника» TMenu, который в отличие от своего «предка» будет восстанавливать вид экрана. Для этого следует добавить новое поле Store, где будет храниться прежний экран во время действия нового меню, перекрыть метод Init и добавить метод Done, восстанавливающий состояние экрана.
Создать меню, изображающее себя в форме столбца. Для этого рационально использовать виртуальные методы, т.е. достаточно изменить метод Draw объекта TNeatMenu и объявить одноименные методы виртуальными.
Разместить объекты в динамической памяти, описав указатели на них.
Построить сложное иерархическое меню, в котором пробел будет открывать главное меню, а последовательным нажатием клавиш <Enter> и пробела будет разворачиваться подсвеченный пункт в подменю или, если пункт находится на нижнем уровне, клавиша <Enter> будет сворачивать подменю. Нажатием клавиши <Esc> работа программы должна заканчиваться.
Построить иерархическое меню, в котором пробел будет открывать главное меню, а нажатием клавиши <Enter> будет разворачиваться подсвеченный пункт в меню или, если пункт находится на самом нижнем уровне, нажатием клавиши <Enter> будет сворачиваться подменю. Нажатием клавиши <Esc> работа программы должна заканчиваться. Нижний уровень меню должен быть вертикальным.
Построить систему классов для описания плоских геометрических фигур: круга, квадрата, прямоугольника. Предусмотреть при этом методы для создания объектов, перемещения на плоскости, изменения размеров и вращения на заданный угол.
Построить описание класса, содержащего информацию о почтовом адресе организации. Предусмотреть при этом возможность раздельного изменения составных частей адреса, создания и уничтожения объектов этого класса.
Составить описание класса для представления комплексных чисел с возможностью задания вещественной и мнимой частей как числами типа double, так и целыми числами. Обеспечить при этом выполнение операций сложения, вычитания и умножения комплексных чисел.
Составить описание класса для работы с цепными списками строк (строками произвольной длины). Обеспечить при этом выполнение операций включения в список, удаления из списка элемента с заданным значением, удаления всего списка или конца списка, начиная с указанного элемента.
Составить описание класса для объектов-векторов, задаваемых координатами их концов в трехмерном пространстве. Обеспечить при этом выполнение операций сложения и вычитания векторов с получением нового вектора (суммы или разности), вычисление скалярного произведения двух векторов, длины вектора и косинуса угла между векторами.
Составить описание класса прямоугольников со сторонами, параллельными осям координат. Предусмотреть при этом возможность перемещения прямоугольников на плоскости, изменения их размеров, построения наименьшего прямоугольника, содержащего два заданных прямоугольника, и прямоугольника, являющегося общей частью (пересечением) двух прямоугольников.
Составить описание класса для определения одномерных массивов целых чисел (векторов). Предусмотреть при этом возможность обращения к отдельному элементу массива с контролем выхода за пределы индексов, задания произвольных границ индексов при создании объекта, выполнения операций поэлемеЫ тного сложения и вычитания массивов с одинаковыми граница/- ми индексов, умножения и деления всех элементов массива на скаляр, печати (вывода на экран) по индексам элементов массива и всего массива.
Составить описание класса для определения одномерных массивов строк фиксированной длины. Предусмотреть при этом возможность обращения к отдельным строкам массива по индексам, контроль выхода за пределы индексов, выполнения операций поэлементного сцепления двух массивов с образованием нового массива, слияния двух массивов с исключением повторяющихся элементов, печати (вывода на экран) элементов массива и всего массива.
Составить описание класса многочленов от одной переменной, задаваемых степенью многочлена и массивом коэффициентов. Предусмотреть при этом методы вычисления значения многочлена для заданного аргумента, операции сложения, вычитания и умножения многочленов с получением нового объекта-многочлена, печать (вывод на экран) описания многочлена.
Составить описание класса одномерных массивов строк, каждая строка которого задается длиной и указателем на выделенную для нее память. Предусмотреть при этом возможность обращения к отдельным строкам массива по индексам, контроля выхода за пределы индексов, выполнения операций поэлементного сцепления двух массивов с образованием нового массива, слияния двух массивов с исключением повторяющихся элементов, печати (вывода на экран) элементов массива и всего массива.
Составить описание объектного типа TMatr, обеспечивающего размещение матрицы произвольного размера, предусмотрев при этом возможность изменения числа строк и столбцов, а также вывода на экран подматрицы любого размера и всей матрицы.
Составить программу обработки двунаправленных связанных списков. (Связанный список данных состоит из указателей на его начало и конец, а каждый элемент такого списка представляет собой реализацию отдельного объекта.) При этом обеспечить возможность следующих операций:
создание связанного списка (выделение для него памяти);
уничтожение связанного списка (освобождение используемой памяти);
инициализация связанного списка;
деинициализация связанного списка;
вставка элемента в середину связанного списка перед существующим элементом;
присоединение элемента к концу связанного списка;
! • удаление элемента из связанного списка;
1 • возвращение первого элемента связанного списка;
, • возвращение последнего элемента связанного списка.
I 19. Определить объект TFish — аквариумная рыбка, имеющий координаты, скорость, размер, цвет и направление движения. Методами этого объекта являются:
Init — устанавливает значения полей объекта и рисует рыбку на экране методом Draw;
Draw — рисует рыбку в виде уголка с острием в точке Coord, направленным по ходу ее движения;
Look — проверяет несколько точек на линии движения рыбки, и если хотя бы одна из них отличается по цвету от воды, возвращает ей цвет и указывает расстояние до рыбки;
Run — перемещает рыбку в текущем направлении на расстояние, зависящее от ее текущей скорости. Иногда случайным образом изменяет направление движения рыбки. Если же на пути рыбки возникает препятствие, направление движения изменяется до тех пор, пока препятствие не исчезнет из ее поля зрения.
Определить объект TAquarium, который является местом обитания рыбок (см. задачу 19) и представляет собой область экрана, заполненную водой. Рыбки живут в аквариуме, поэтому экземпляры объекта TFish должны быть полями объекта TAquarium.
Методами этого объекта являются:
Init — включает графический режим, заполняет аквариум водой, скалами и рыбками.
Run — организует бесконечность цикла, в котором выполняется данный метод, для всех обитателей аквариума;
Done — выключает графический режим.
Определить объекты TPike и ТКагр, которые являются «наследниками» объекта TFish (см. задачу 19) и отличаются от него только тем, что по-разному изображают себя на экране: TPike — в виде зеленой стрелки, а ТКагр — в виде красного треугольника. Ипользовать виртуальные методы, т.е. вернувшись к определению объекта TFish, откорректировать его, сделав Draw пустым и виртуальным.
Объединить два вида рыб (см. задачу 21) в две разные стаи, где стая — это связанный список рыб в динамической памяти. Для связи добавить в объекты TPike и ТКагр поле Next — указатель на имеющихся в стае рыб. Запустить в аквариум не отдельных рыб, а две стаи, и позволить владельцу пополнять эти стаи, вводя рыб с клавиатуры.
Позволить щукам (см. задачу 21) поедать карпов, как только они их увидят, для чего следует установить, какого именно карпа
видит щука. Проблема решается просмотром всей стаи карпов и; определения того из них, чьи координаты близки к координатац' данной щуки. Найденного карпа удалить из стаи.
Составить программу для игры в шашки. Здесь шашки каж
дого цвета выступают в качестве отдельного объекта. Характеристиками шашек являются цвет и позиция на доске, а методами — перемещение. (Не забудьте об объектах «дамки».)(
Составьть программу для игры в домино. Здесь объектами являются кости домино, а методами — способы выставления той или иной кости.
Составить программу для игры в шахматы. Здесь каждая шахматная фигура является отдельным объектом и характеризуется цветом, положением на доске, способом перемещения. Предусмотреть возможность превращения пешки в ферзя.
27 — 30. Выполнить задачи 23—26 в графическом режиме.
31—45. Выполнить все задачи подразд. 5.14 в графическом режиме.
46. Определить структурированный тип данных и набор подпрограмм для работы с массивом структур. В структурированной переменной предусмотреть способ отметки ее как не содержащей данных (т.е. пустой). Подпрограммы должны работать с массивом структур или с отдельной структурой через указатели, а также при необходимости возвращать указатель на структуру. В перечень подпрограмм входят:
«очистка» структурированных переменных;
поиск свободной структурированной переменной;
ввод элементов (полей) структуры с клавиатуры;
вывод элементов (полей) структуры с клавиатуры;
поиск в массиве структуры с минимальным значением заданного поля;
сортировка массива структур в порядке возрастания заданного поля;
поиск в массиве структур элемента с заданным значением поля или с наиболее близким к нему значением;
удаление заданного элемента;
изменение (редактирование) заданного элемента;
выполнение вычисления с проверкой и использованием всех элементов массива по заданному условию и формуле. »
Перечень полей структурированной переменной:
а)фамилия, имя, отчество человека, дата его рождения, адрес;
б)фамилия, имя, отчество вкладчика, номер его счета, сумма на счете, дата последнего изменения счета;
в)номер страницы, номер строки, текст изменения строки, дата изменения;
г)название экзамена, дата экзамена, фамилия преподавателя, принимавшего экзамен, количество поставленных оценок, оценки;
д)фамилия, имя, отчество студента, номер его зачетной книжки, факультет, группа;
е)фамилия, имя, отчество читателя, номер его читательского 1билета в библиотеке, название взятой книги, срок ее возврата в библиотеку;
ж)наименование товара, его цена, количество, процент торговой надбавки;
з)номер рейса самолета, пункт его назначения, время вылета, дата вылета, стоимость билета;
и)фамилия, имя, отчество ученика, количество его оценок, оценки, средний балл;
к)фамилия, имя, отчество студента, дата его поступления, дата отчисления;
л)регистрационный номер автомобиля, его марка и пробег;
м)фамилия, имя, отчество телефонного абонента, количество состоявшихся переговоров, их даты и продолжительность;
н)номер телефона вызываемого абонента, дата разговора, его продолжительность, код вызываемого города;
о)номер поезда, пункт его назначения, дни следования, время прибытия, время‘стоянки;
п)название кинофильма, время сеанса, стоимость билета, количество зрителей в зале.
Тема «Визуальное программирование оконногоинтерфейса»Пересчитать скорость ветра, заданную в метрах в секунду, километрах в час. Рекомендуемый вид формы показан на рис. 5.3. Программа должна проектироваться таким образом, чтобы пользователь мог ввести в поле Скорость только целое положительное число.
Вычислить сопротивление электрической цепи, состоящей из двух резисторов, которые могут быть соединены последовательно или параллельно. Рекомендуемый вид формы показан на рис. 5.4. Если сопротивление цепи превышает 1 000 Ом, результат должен быть выведен в килоомах.
Вычислить стоимость поездки на автомобиле, например на дачу. Рекомендуемый вид формы показан на рис. 5.5.
Сформировать список городов, вводимых в строку пользователем. Примерный вид формы показан на рис. 5.6.
Составить анкету для студентов включающую в себя следующие вопросы:
• Сколько вам лет?
^ Программа пересчигьеает скорость иэ^ " vlWc” в ”км\ч**. Введите скорость и
<те на кнопке Пересчет. ,
Поле вводаEdit
Поле вводаLabel
дна
"перелет];
ИЙТПА _
^корость (м/с)
Ри ,21 Г. ФорЙ»^ццраммь1 £к6ростъветра' в
Рис. 5.3. Форма к задаче 1



На каком факультете вы учитесь?
В какой группе вы учитесь?
Нравится ли вам учиться?
Результат содержащий всю информацию, полученную при анкетировании, должен быть представлен сразу.
Получить в зависимости от введенного возраста соответствующую надпись [4]:
для возраста менее 17 лет — «Почему вы не в школе?»;
для возраста от 17 до 40 — «Молодым везде дорога!»;
для возраста от 40 до 60 — «Главное — побольше здоровья!»;
для возраста более 60 лет — «Почетный возраст».
Пересчитать массу из фунтов в килограммы (1 фунт = 453,59 г). Рекомендуемый вид формы показан на рис. 5.7. Программу спроектировать таким образом, чтобы кнопка [Пересчет] была доступна только после ввода пользователем исходных данных [9].

Рис. 5.7. Форма к задаче 7


Вычислить доход по вкладу. Программа л расчет простых и сложных процентов. (Прост ляются в конце срока вклада. Сложные про ежемесячно, прибавляются к первоначально следующем месяце проценты начисляются н;
Перевести число из одной меры весов в} мый вид формы показан на рис. 5.8.
Смешать цвета в формате RGB с него прокрутки. Рекомендуемый вид формы показ
Определить скидку на стоимость указан ходя из следующих данных:
• если возраст машины больше 10 лет — с

Рис. 5.9. Форма к задаче 10

9
Щ
Введите название машины и отметьте ее характеристики
• • • название машины • • ■
цена нового автомобиля •
1..„::г Старше 10 лет »• - •
Г Аварийная
Г Таможня
Г" Пробег по РФ ^—
ПодсчитатьI ; Добавить I || Проверить I \\ Удалить
Вычислить силу тока в электрической цепи, состоящей из двух резисторов, которые могут быть соединены последовательно или параллельно.
Используя закон Ома, вычислить силу тока, напряжение или сопротивление электрической цепи. (Во время работы программы в результате выбора переключателя Ток, Напряжение или Сопротивление текст, поясняющий назначение полей ввода, должен меняться.)
Вычислить площадь треугольника по длине его сторон. Рассмотреть прямоугольный, равнобедренный, равносторонний и произвольный треугольники.
Вычислить сумму покупки. Пользователь вводит название товара и его цену с учетом возможной скидки для сотрудника компании, постоянного клиента и покупателя, предоставившего дисконтную карту, а программа сформирует список товаров.
Вычислить путь, пройденный свободно падающим телом через t секунд. Программу составить таким образом, чтобы можно было вычислить пройденный телом путь при имеющемся начальном пройденном пути.
Усовершенствовать программу «Поездка на дачу» (см. рис. 5.5): сформировать поле с выпадающим списком автомобилей (здесь программно для каждого автомобиля известен расход топлива), при выборе в котором конкретного автомобиля автоматически подсчитывается стоимость поездки.
Усовершенствовать программу к задаче 23 за счет установки начального пройденного пути полосой прокрутки.
Вычислить объем правильной пространственной фигуры (тетраэдра, куба, четырехугольной пирамиды).
Проверить, сколько раз заданный символ вошел в заданный текст. Длина текста может быть более 256 символов.
Сформировать туристический маршрут, состоящий из пяти пунктов назначения, названия которых выбираются из выпадающего списка. Полный путь маршрута формируется в поле Memo.
Вычислить время, которое требуется, чтобы проплыть на лодке определенное расстояние. Программа должна вычислять время полного пути, т.е. туда и обратно.
Обеспечить отображение вводимого текста в окне и регулировку его размера полосой прокрутки.
Преобразовать введенный текст: все строчные буквы заменить прописными. Длина текста может быть более 256 символов.
Тема «Большие проекты»Задача «Волчий остров» [2].
Волчий остров размером 20x20 заселен дикими кроликами, волками и волчицами. Имеется по несколько представителей каждого вида. Кролики довольно глупы: в каждый момент времени они с одинаковой вероятностью 1/9 передвигаются в один из восьми соседних квадратов (за исключением участков, ограниченных береговой линией) или просто сидят неподвижно. Каждый кролик с вероятностью 1/5 превращается в двух. Каждая волчица передвигается случайным образом, пока в одном из соседних восьми квадратов не окажется кролик, за которым она охотится. Если волчица и кролик оказываются в одном квадрате, волчица съедает кролика и получает одно очко. В противном случае она теряет 0,1 очка. Волки и волчицы с нулевым количеством очков умирают.
В начальный момент игры все волки и волчицы имеют одно очко. Волк ведет себя подобно волчице до тех пор, пока в соседних квадратах не исчезнут все кролики; тогда если волчица оказывается в одном из восьми близлежащих квадратов, волк гонится за ней. Если волк и волчица окажутся в одном квадрате и там нет кролика, которого нужно съесть, они производят потомство случайного пола.
Создать соответствующую экологическую модель и проследить изменение популяции волков и диких кроликов в течение некоторого периода времени.
Задача «Инфекция стригущего лишая» [2].
Смоделировать процесс распространения инфекции стригущего
лишая по участку кожи размером пхп клеток (где п — нечетное число). Предполагается, что исходной зараженной клеткой кожи является центральная. В определенный интервал времени пораженная инфекцией клетка может с вероятностью 0,5 заразить любую из соседних здоровых клеток. По прошествии шести единиц времени зараженная клетка становится невосприимчивой к инфекции, в течение последующих четырех единиц времени действует возникший иммунитет, а затем клетка оказывается здоровой. В ходе моделирования описанного процесса следует выдавать текущее состояние моделируемого участка кожи в определенном интервале времени, отмечая зараженные, невосприимчивые к инфекции и здоровые клетки.
Задача «Построение фигур на плоскости с помощью циркуля и линейки».
Автоматизировать процесс построения фигур на плоскости с помощью циркуля и линейки. Программа должна уметь:
отмечать произвольную точку и обозначать ее;
строить прямую, проходящую через две точки;
строить произвольную прямую;
строить окружность с заданными центром и радиусом;
строить и обозначать точку пересечения двух линий.
Программа должна содержать 10... 15 стандартных задач на
построение из школьного курса геометрии, предлагать их для
1 • 7 1 7
2 10 2 13 2
5 12 13 5 7
3 3 3 11 3
4 12 4 13 12
(40)
(10)
(160)
(20)
(20)(50)(10)(10)(10) (160)
Рис. 5.11
решения, контролировать процесс построения и полученное решение.
Игра «Морской бой».
Составить программу, позволяющую играть в морской бой игроку с компьютером. Программа должна позволять расставлять корабли на поле 10 х 10 и контролировать правильность их расстановки, а также обеспечивать очередность ходов противников и выдавать соответствующие информационные сообщения. Так как в качестве одного из игроков выступает компьютер, программа должна анализировать предыдущие ходы и следующий ход делать на основе проведенного анализа.
Обучающе-контролирующая задача «Сложение и вычитание отрицательных чисел».
Составить программу, обучающую учеников 6-го класса сложению и вычитанию отрицательных чисел, предусмотрев серию заданий различной сложности для закрепления навыков действий с такими числами.
Итальянская игра «Математико».
Имеется квадратное поле из 25 клеток и набор из 52 карточек, на которых записаны числа от 1 до 13, причем карточки с каждым из этих чисел встречаются по четыре раза.
Разработать программу, которая позволит имитировать игру человека с компьютером: случайным образом извлекается какая- либо из имеющихся карточек и выдается записанное на ней число. Каждый игрок заносит это число в одну из клеток квадрата, и так продолжается до тех пор, пока не будут заполнены все клетки квадрата.
Пример заполнения заданного поля показан на рис. 5.11.
Комбинация чисел Количество очков при расположении одинаковых чисел
В ряду или столбце По диагонали
Два одинаковых числа 10 20
Две пары одинаковых чисел 20 30
Три одинаковых числа 40 50
Три одинаковых числа и два других одинаковых числа 80 90
Четыре одинаковых числа 160 170
Пять последовательных чисел, необязательно расположенные по порядку 50 60
Три раза 1 и два раза 13 100 110
Числа 1, 13, 12, 11 и 10, необязательно расположенные по порядку 150 160
Четыре 1 200 210
По окончании игры заполнение заполнение клеток поля оценивается определенным количеством очков. Цель игры — разместить числа в клетках таким образом, чтобы набрать наибольшее количество очков в соответствии с табл. 5.3.
Разработать для компьютера наиболее оптимальную стратегию заполнения квадрата.
Задача «Заполнение готовых форм с помощью информации из базы данных».
Имеется база данных, содержащая сведения о некоторой группе людей (каждая запись содержит до 10 полей). Составить программу, позволяющую заполнять некоторые документы (стандартные письма, приглашения, визитки, отчеты и т.д.) посредством нахождения необходимых сведений в базе данных и введения их в документ в соответствующей форме (падеже, лице, времени и т.д.).
Карточная игра «В дурака».
Составить программу, которая раздает игральные карты заданному числу игроков (одним из игроков является человек, а за остальных играет компьютер) и моделирует игру «В дурака». Причем программа должна играть случайным образом, без анализа уже вышедших карт, а число игроков не должно превышать шести.
Игра «Крестики-нулики».
Составить программу, позволяющую играть на бесконечном поле в «Крестики-нулики» игроку с компьютером, а также двум игрокам.
Если в качестве игрока выступает компьютер, программа делает первый ход. Делая очередной ход, программа анализирует ситуацию, просчитывая ее вперед на один-два хода противника.
Игра «Быки и коровы».
Составить программу, позволяющую играть в «Быки и коровы» игроку с компьютером, а также двум игрокам.
В этой игре каждый из противников задумывает четырехзначное число, все цифры которого различны, причем первая цифра не нуль. Необходимо отгадать задуманные числа, при этом выигрывает тот, кто отгадает первым. Противники по очереди называют друг другу различные числа и сообщают о количестве «быков» и «коров» в них («бык» — цифра, которая есть в записи названном числа и занимает в нем ту же позицию, что и в названном числе; «корова» — цифра, которая есть в записи задуманного числа, но она не занимает в ней ту же позицию, что и в названном числе).
Например, если задумано число 3 275 и названо число 1 234, имеется один «бык» и одна «корова». Очевидно, что задуманное число будет отгадано в случае если в названном числе будет четыре «быка».
Игра «Числовые головоломки».
Составить программу, которая предлагает игроку числовую головоломку типа ОДИН + ОДИН = МНОГО из некоторого набора таких головоломок (до 30), позволяет решить эту головоломку и контролирует правильность решения.
Задача «Построение графиков».
Составить программу, которая предлагает пользователю некоторый список функций для построения графиков, например, у - = ах? + Ьх + с\ у = asm х + b и т.д. (до 25 наименований). После выбора одной из функций, задания коэффициентов и отрезка, на котором выполняется построение, строится соответствующий график. При этом возможно изменение значений коэффициентов и положения графика с помощью клавиш управления курсором, после чего он перестроится и запишется обновленное уравнение кривой.
Игра «Две лисы и 20 кур».
На поле, форма которого показана на рис. 5.12, находятся две лисы и 20 кур. Куры могут перемещаться на одну клетку вверх, влево или вправо, но не назад и не по диагонали. Лисы могут перемещаться только на одну клетку вверх, вниз, влево и вправо. Лиса может съесть курицу, как в игре в шашки, т.е. если в горизонтальном или вертикальном направлении сразу за курицей следует свободная клетка. При этом лисы обязаны всегда есть кур, и обязательно как можно больше. При возможности съесть одинаковое число кур в разных направлениях, выбирается одно из них.
Составить программу, играющую за лис, а игрок будет перемещать кур, которые и начинают игру.
л л К к к к к к к
к к к к к к к
к к к к к к Рис. 5.12
Куры выигрывают партию, если девяти из них удается занять девять клеток, образующих верхний квадрат поля.
Лисы выигрывают, если им удается съесть 12 кур, так как в этом случае оставшихся кур недостаточно, чтобы занять девять верхних полей.
Головоломка «Игры со спичками».
Составить программу, которая предлагает игроку головоломку со спичками из некоторого набора таких головоломок (до 30 штук), позволяет решить эту головоломку, передвигая спички, и контролирует правильность решения.
Задача «Графика в ТурбоПаскале».
Составить программу, демонстрирующую все графические возможности языка ТурбоПаскаль и обучающую работе с основными графическими процедурами и функциями. Программа должна проконтролировать усвоение изученного материала (в виде теста или в какой-либо другой форме).
Игра «В слова».
Составить программу, позволяющую компьютеру и человеку играть в слова. Программа должна предварительно объяснять правила игры, а также позволять уточнить их в любой момент.
Тематику игры из предложенных компьютером не менее пяти вариантов (города, животные, растения и т.д.) выбирает человек. Для игры компьютер использует собственную базу данных (по каждой тематике свою), хранящуюся в виде текстового файла. Если названное человеком слово отсутствует в базе данных, уточняется, правильно ли оно названо. В случае правильности названного слова оно заносится в базу данных, а в противном случае — уто
чняется. Правила игры: один игрок называет слово, а другой — должен предложить слово, начинающееся с буквы, на которую слово, названное первым игроком, оканчивается.
Задача «Решение ребусов».
Для выбранного школьного предмета (информатика, математика и т.д.) подобрать ребусы и предложить их для решения. Программа должна обеспечить выбор того или иного ребуса, проконтролировать его решение и подвести итоги по завершении работы.
ПРИЛОЖЕНИЕ 1. ТУРБОПАСКАЛЬ. МОДУЛЬ CRT
Таблица П1.1
Константы режимов работы
Имя константы Номер режима Режим
BW40 0 Черно-белый, 40 символов, 25 строк
СО40 1 Цветной, 40 х 25
BW80 2 Черно-белый, 80 х 25
СО80 3 Цветной, 80 х 25
Mono 7 Монохромный, 80 х 25, для монохромных дисплеев
Таблица П1.2
Константы цветов
Имя константы Номер цвета Цвет
Black 0 Черный
Blue 1 Темно-синий
Green 2 Темно-зеленый
Cyan 3 Бирюзовый
Red 4 Красный
Magenta 5 Фиолетовый
Brown 6 Коричневый
LightGray 7 Светло-серый
DarkGray 8 Темно-серый
LightBlue 9 Синий
LightGreen 10 Светло-зеленый
LightCyan 11 Светло-бирюзовый
LightRed 12 Розовый
LightMagenta 13 Малиновый
Yellow 14 Желтый
White 15 Белый
Blink 128 Мерцание символа
Процедуры и функции
Интерфейс
Установка ре,
Procedure AssignCrt (File : Text);
Procedure ClrScr;
Procedure TextMode (Mode : Integer); Mode — номер текстового режима или соответствующая константа
Procedure Window (xl, yl, x2, y2 : Byte); (xl, yl) и (x2, y2) — координаты верхнего левого и нижнего правого углов окна
Управление цвете Procedure HighVideo;
Procedure LowVideo;
Procedure Norm Video;
Procedure Text Background (Color : Byte); Color — код цвета или соответствующая константа
Управление вы
Procedure ClrEol;
Procedure DelLine;
Procedure InsLine;
Работа с кл
Function KeyPressed : Boolean; Значение True, если нажата любая клавиша, и False, если не нажата
Интерфейс Назначение
Function ReadKey: Char;
Значение функции — код символа клавиши, нажатой на клавиатуре Считывает символ из буфера клавиатуры
Управление курсором
Procedure GotoXY (X,Y: Integer); X, Y — координаты курсора Перемещает курсор в указанные координаты окна вывода
Function WhereX : Integer;
Значение функции — координата X курсора Возвращает текущую координату X курсора
Function WhereY: Integer;
Значение функции — координата Y курсора Возвращает текущую координату Y курсора
Управление звуком
Procedure NoSound; Выключает динамик
Procedure Sound (Hz : Word); Hz — частота звука в герцах Включает звук динамика с заданной тональной частотой
Управление временем
Procedure Delay (Ms : Word);
Ms — значение задержки в миллисекундах Задерживает исполнение программы на заданное число миллисекунд
Имя
Detect
CGA
MCGA
EGA
EGA64
EGAMono
IBM8514
HercMono
ATT400
VGA
PC3270
CurrentDriver
Имя
АТТ400С0
ATT400C1
ATT400C2
ATT400C3
ATT400Med
ATT400Hi
CGACO
CGAC1
CGAC2
CGAC3
CGACHi

Имя Значение Размер поля Палитра Число страниц
EGALo 0 640 x 200 16 цветов 4
EGAHi 1 640 x 350 16 цветов 2
EGA64LO 0 640 x 200 16 цветов 1
EGA64Hi 1 640 x 350 4 цвета 1
EGAMonoHi 0 640 x 350 2 цвета 1 или 2
HercMonoHi 0 720 x 348 2 цвета 2
IBM8514LO 0 640 x 480 256 цветов 1
1ВМ8514Ш 0 1024 x 768 256 цветов 1
'MCGACO 0 320 x 200 СО 1
MCGAC1 1 320 x 200 С1 1
MCGAC2 2 320 x 200 С2 1
MCGAC3 3 320 x 200 СЗ 1
MCGAMed 4 640 x 200 2 цвета 1
MCGAHi 5 640 x 480 2 цвета 1
PC3270Hi 0 720 x 350 2 цвета 1
VGALo 0 640 x 200 16 цветов 4
VGAMed 1 640 x 350 16 цветов 2
VGAHi 2 640 x 480 16 цветов 1
Примечание. Палитра СО включает в себя цвета светло-зеленый, розовый и желтый, палитра С1 — светло-голубой, светло-фиолетовый и белый, палитра С2 — зеленый, красный и коричневый, палитра СЗ — голубой, фиолетовый и светло-серый.
Таблица П2.3
Константы цветов
Имя константы Номер цвета Цвет
Black 0 Черный
Blue 1 Темно-синий
Green 2 Темно-зеленый
Cyan 3 Бирюзовый
Red 4 Красный
Magenta 5 Фиолетовый
Brown 6 Коричневый
LightGray 7 Светло-серый
Имя константы Номер цвета Цвет
DarkGray 8 Темно-серый
LightBlue 9 Синий
LightGreen 10 Светло-зеленый
LightCyan 11 Светло-бирюзовый
LightRed 12 Розовый
LightMagenta 13 Малиновый
Yellow 14 Желтый
White 15 Белый
Таблица П2.4
Коды линий
Имя Значение Назначение
Коды типов линий {для процедуры SetLineStyle)
SolidLn 0 Сплошная
DottedLn 1 Пунктирная
CenterLn 2 Штрихпунктирная
DashedLn 3 Штриховая
UserBitLn 4 Заданная пользователем
Коды толщины линии
NormWidth 1 Нормальная
ThickWidth 3 Толстая
Таблица П2.5
Константы типа заполнения (для процедуры SetFillStyle)
Имя константы Значение Назначение
EmptyFill 0 Заполнение цветом фона
SolidFill 1 Однородное заполнение цветом
LineFill 2 Заполнение вида —
LtSlashFill 3 Заполнение вида ///
SlashFill 4 Заполнение вида /// толстыми линиями
BkSlash Fill 5 Заполнение вида \ толстыми линиями
LtBkSIashFill 6 Заполнение вида \
HatchFill 7 Заполнение клеткой
Имя константы Значение Назначение
XHatchFill 8 Заполнение косой клеткой
Interleave Fill 9 Заполнение частой клеткой
WideDotFill 10 Заполнение редкими точками
CloseDotFill 11 Заполнение частыми точками
UserFill 12 Определяется пользователем
Таблица П2.6
Процедуры и функции
Интерфейс Назначение
Управление графическим режимом
Procedure CloseGraph; Закрывает графический режим
Procedure DetectGraph (Var GrDriver, GrMode: Integer);
GrDriver — код драйвера, GrMode — код графического режима Определяет рекомендуемые к применению для данного компьютера графические драйвер и режим
Function GetDriverName : String; Значение функции — имя используемого драйвера Определяет имя файла с используемым графическим драйвером
Function GetGraphMode : Integer; Значение функции — код графического режима Определяет код используемого графического режима
Function GetMaxName