Министерство образования и науки Российской Федерации Государственное образовательное учреждение высшего профессионального образования «Омский государственный технический университет» Ю. П. Чернов, О. П. Шафеева ПРОГРАММИРОВАНИЕ в системе Pascal ABC Учебное пособие Омск Издательство ОмГТУ 2010 УДК 004.4 (075) ББК 32.973-018я73 Ч 49 Рецензенты: В. И. Стариков, канд. техн. наук, доцент ОГИС; С. С. Ефимов, канд. техн. наук, доцент ОмГУ им. Ф.М. Достоевского Чернов, Ю. П. Ч 49 Программирование в системе Pascal ABC: учеб. пособие / Ю. П. Чернов, О. П. Шафеева. – Омск: Изд-во ОмГТУ, 2010. – 100 с. ISBN 978-5-8149-0897-1 Пособие включает теоретический материал с описанием элементов языка и системы программирования Pascal ABC, а также примеры разработки алгоритмов и программ на языке Паскаль для задач разного уровня сложности. Рассмотренные схемы проектируемых алгоритмов позволяют облегчить усвоение материала студентами. Учебное пособие предназначено для изучения языка программирования высокого уровня Паскаль в дисциплинах «Информатика», «Основы алгоритмизации и программирования», «Алгоритмические языки и программирование», «Программирование на языке высокого уровня». Печатается по решению редакционно-издательского совета Омского государственного технического университета УДК 004.4 (075) ББК 32.973-018я73 ISBN 978-5-8149-0897-1 © ГОУ ВПО «Омский государственный технический университет», 2010 2 ВВЕДЕНИЕ Наиболее распространенным в настоящее время языком программирования для компьютеров серии IBM PC является Паскаль. Это язык высокого уровня, отличающийся простотой синтаксиса, структурированный и удобный для начального обучения программированию. Учебная система программирования Pascal ABC (автор С.С. Михалкович [1]) представляет собой диалект стандартного языка Паскаль. Система Pascal ABC предназначена для обучения программированию на языке Паскаль и ориентирована на студентов младших курсов. По мнению разработчиков этой системы, первоначальное обучение программированию должно проходить в достаточно простых и дружественных средах, в то же время эти среды должны быть близки к стандартным и иметь богатые и современные библиотеки подпрограмм. К достоинствам системы Pascal ABC следует отнести то, что она позволяет: – программировать на языке Паскаль, подобном Delphi Pascal, включая объектно-ориентированные расширения; – работать с графикой; – создавать событийные приложения. Система Pascal ABC основана на языке Delphi Pascal и призвана осуществить постепенный переход от простейших программ к модульному, объектно-ориентированному, событийному и компонентному программированию. Некоторые языковые конструкции допускают, наряду с основным, упрощенное использование, что позволяет использовать их на ранних этапах обучения. К важнейшим достоинствам пакета Pascal ABC относится соответствие стандартному Паскалю, быстрая компиляция программ, объединение компилятора с текстовым редактором, предупреждение об ошибках на уровне исходной программы, обширная библиотека подпрограмм и полезные расширения, упрощающие программирование. Начинающему программисту целесообразно начинать изучение языка и среды именно с этого пакета. Компилятор Pascal ABC является компилятором переднего плана (frontend). Это означает, что он не генерирует исполняемый код в виде .exe -файла, а создает в результате компиляции дерево программы в памяти, которое затем выполняется с помощью встроенного интерпретатора. В итоге скорость работы программы оказывается медленнее скорости работы этой же программы, откомпилированной в среде Borland Pascal или в среде Borland Delphi. Однако на современных компьютерах это практически не ощущается. 3 Название "Pascal ABC" относится к интерактивной системе программирования, состоящей из компилятора языка и объединенного с ним экранного редактора. Интерактивность системы проявляется в основном в удобстве редактирования и обработки ошибок, обнаруженных в исходных текстах программ. Запуск программ в этой системе происходит на уровне исходных текстов. Высокая скорость компиляции приводит к тому, что переход от исходного текста к исполняемой программе происходит очень быстро. Это значительно сокращает цикл трансформации программ от редактирования к компиляции и исполнению программ. Система Pascal ABC включает в себя как язык программирования, так и инструментальную среду, предназначенную для написания, отладки и исполнения программ. Язык характеризуется расширенными возможностями по сравнению со стандартом языка Паскаль и хорошо развитой библиотекой модулей, позволяющих использовать возможности операционной системы, формировать графическое изображение и т.д. Инструментальная среда программирования позволяет создавать тексты программ, компилировать их, находить ошибки и оперативно их исправлять, тестировать и выполнять отлаженную программу. Среда включает также большой объем справочной информации. В настоящем учебном пособии описаны синтаксические правила и основные возможности языка, работа в интегрированной среде. Практические приемы программирования продемонстрированы на примерах решения конкретных задач. Пособие подготовлено с учетом опыта чтения лекций и проведения авторами лабораторных занятий в компьютерном учебном центре ОмГТУ. В первую очередь пособие предназначено для студентов университета и представляет теоретическое руководство по программированию как в среде Pascal ABC, так и в средах Free Pascal и Turbo Pascal. 1. СИСТЕМА ПРОГРАММИРОВАНИЯ PASCAL ABC Процесс выполнения задачи на компьютере включает ряд обязательных этапов: набор текста программы и запись его в именованный файл на диске; компиляция программы с обнаружением и исправлением синтаксических ошибок; тестирование; устранение семантических и алгоритмических ошибок; непосредственное выполнение программы с заданием реальных значений и получением результатов. Максимальные удобства для подготовки и отладки программ при программировании на Паскале предоставляет специальная интегри4 рованная среда (совокупность взаимосвязанных сервисных программных средств, обеспечивающих всестороннюю поддержку процесса разработки программ) [1–3]. Умелое использование возможностей среды позволяет значительно упростить этапы проектирования, тестирования и отладки программ. Система программирования Pascal ABC представляет собой единство компилятора языка программирования Паскаль и инструментальной программной оболочки, называемой средой. Среда предоставляет необходимые сервисные услуги и способствует повышению эффективности процессов разработки, отладки и испытаний программ, что облегчает труд программиста. 1.1. Структура меню среды Управление средой осуществляется с помощью системы последовательно разворачивающихся меню. Меню фиксирует некоторое текущее состояние диалоговой среды и предлагает несколько альтернативных путей перехода из этого состояния. Каждое конкретное меню реализуется в виде окна с текстом. Содержащиеся в меню альтернативы команд называют опциями. Вызов системы производится запуском на исполнение файла PascalABC.EXE. После входа в среду в верхней строке экрана появляется главное меню (рис. 1): Файл Правка Вид Программа Сервис Помощь. Рис. 1 Главное меню включает оглавление разделов меню (подменю). В них сгруппированы близкие по своему роду команды, условное название раздела для которых находится в главном меню: Файл работа с файлами и выход из системы; Правка операции редактора текстов и поиска; Вид работа с окнами в системе; Программа выполнение и отладка программы; Сервис вызов вспомогательных функций; Помощь обращение к справочнику системы. 5 Выбор раздела главного меню может быть осуществлен указателем мыши либо перемещением к соседней кнопке с помощью горизонтальных стрелок на клавиатуре ПК. В каждом из случаев происходит вывод окна меню, содержащего опции раздела. Выбор опции меню производится аналогично выбору раздела главного меню (клавишами с вертикальными стрелками) и может привести к вызову подменю следующего уровня или окна диалога. В случае ошибочного выбора опции для возвращения на высший уровень меню необходимо нажать клавишу Esc или кнопку Отмена. Выбор опции из раздела главного меню может быть ускорен одновременным нажатием сочетания клавиш Ctrl и условной буквы меню в произвольный момент подготовки программы. Например, при выборе команды поиска достаточно ввести с клавиатуры Ctrl-F. Для ускорения процесса выбора часто используемых опций меню можно пользоваться специальными кнопками инструментальной панели. 1.2. Команды редактора Pascal ABC Для создания и редактирования текстов программ предназначен текстовый редактор системы Pascal ABC. Режим редактирования автоматически устанавливается сразу после загрузки Pascal ABC: в окне редактора появляется курсор. В нормальном режиме работы редактора (режим вставки) каждый вновь вводимый символ «раздвигает» текст на экране, смещая вправо остаток строки. Редактор также может работать в режиме наложения новых символов на существующий старый текст: в этом режиме новый символ заменяет символ, на который указывает курсор. Для перехода к режиму наложения необходимо нажать клавишу <Insert>. Повторное нажатие этой клавиши восстановит режим вставки. Все команды редактора условно можно разделить на команды перемещения курсора, команды удаления/вставки, команды работы с выделенными блоками. Среди команд перемещения курсора наиболее часто используются следующие: Pg Up на страницу вверх; Home в начало текущей строки; Pg Dn на страницу вниз; End в конец текущей строки; Ctrl-HOME в начало программы; Ctrl-END в конец программы. 6 Команды удаления и вставки INS – включить (отключить) режим вставки; Back space стереть символ слева от курсора; Del стереть символ справа от курсора или выделенный фрагмент; Ctrl-Y удалить строку, на которой располагается курсор; Ctrl-T удалить слово справа от курсора; Enter вставить новую строку. Для выделения текста блока применяются следующие команды: Shift-<стрелки> выделить фрагмент текста; Ctrl-A выделить всё. Редактор позволяет также обрабатывать выделенные фрагменты текста. Выделение текста выполняется обычными средствами: “мышью” или клавишами Shift со стрелками. Команды редактора находятся в меню Правка (рис. 2). Рис. 2 Для записи подготовленного текста на диск достаточно нажать клавиши Ctrl-S или обратиться к разделу меню Файл и опции Сохранить. Рекомендуемым способом загрузки файлов является выбор раздела Файл и затем опции Открыть. После этих действий на экране появляется диалоговое окно, в котором с клавиатуры необходимо задать имя файла и нажать клавишу Enter. Если файл с таким именем существует, то в редакционном окне появится содержимое данного файла для дальнейшего редактирования. Если файла с таким именем нет, то редакционное окно будет очищено и можно вводить требуемый текст, который при записи на диск (клавишами Ctrl-S) в дальнейшем будет занесен в файл с данным именем. Ускоренное создание нового файла реализу7 ется через раздел Файл (Ctrl-N) и опцию Новый. В этом случае файл не имеет имени и при записи его на диск запрашивается имя файла для сохранения. 1.3. Правила оформления программ Набор текста программы производится с клавиатуры. После заполнения очередной строки следует нажать на клавишу <Enter>, чтобы перевести курсор на следующую строку. Каждое предложение программы рекомендуется начинать с новой строки. Предложение можно продолжить в следующей строке (без введения каких-либо знаков переноса или продолжения). Предложение в языке Паскаль может начинаться с любой позиции строки, однако при наборе программы следует придерживаться единых для всех программ правил оформления текста. Признаком хорошего стиля программирования является применение отступов в строках при оформлении текстов программ, поскольку они делают программу более наглядной. Так, объявления (const, type, var и т.п.) и слова begin - end, определяющие тело главной программы, выравниваются по левому краю текста. Все предложения внутри любой пары операторных скобок begin - end записываются с отступом на определенное число позиций по отношению к первой букве слова begin (end). Предложения тела цикла обычно выравниваются по расположению управляющей переменной цикла в заголовке. В конструкции if-then-else с одинаковых позиций (в разных строках) записываются слова then и else, в операторных скобках слова begin и end. Предложения внутри подпрограмм записываются тоже с отступом от левого края текста программы. Программирование на языке Паскаль в соответствии с изложенными правилами именуется структурным программированием. Важными моментами при написании программы являются выбор имен (идентификаторов) и оформление полученных результатов. При введении обозначений следует отдавать предпочтение мнемоническим (смысловым) именам, а не именам типа х, y, z, которые совершенно не информативны. Результаты программы должны иметь наглядный вывод: сопровождаться заголовками и сообщениями, поясняющими смысл выводимых величин. Кроме того, сделать программу более наглядной позволяет включение в ее текст комментариев. Комментарии рекомендуется помещать в начало программы и в начало крупной программной единицы (подпрограммы, вложенных циклов и т.п.) и выделять пустыми строками или особо важные заключать в рамку. 8 1.4. Компиляция и исправление синтаксических ошибок После подготовки текста программы необходимо ее откомпилировать, связать с библиотекой стандартных процедур и функций, загрузить в оперативную память и передать ей управление. Компиляцией называется трансляция программы, записанной на исходном языке, в объектный модуль и создание в результате исполняемого файла. Вся эта последовательность действий называется исполнением программы и реализуется в разделе Программа командой Выполнить (F9). Вызов команды Выполнить приводит к компиляции и исполнению программного модуля, находящегося непосредственно в редакционном окне (рис. 3). Кроме этого система Pascal ABC позволяет выполнять пошаговую компиляцию и исполнение со входом в подпрограмму (F7) или без входа в подпрограмму (F8), а также исполнение программы вплоть до строки программы, в которой находится курсор, с помощью клавиши F4. Рис. 3 Этап компиляции позволяет определить наличие или отсутствие синтаксических ошибок в программе. При их обнаружении среда автоматически загружает в окно редактора исходный файл и помещает курсор в ту строку программы, при компиляции которой найдена ошибка. Во многих случаях такие ошибки возникают из-за неправильного набора текста на клавиатуре, пропуска запятых, двоеточий и т.п. Найденная ошибка исправляется программистом, и производится повторная компиляция программы. Если в программе нет синтаксических ошибок, то далее производится тестирование программы, в процессе которого выявляются семантические и алгоритмические ошибки [4, 5]. Тестирование включает подготовку тестов (спе9 циальным образом подобранных наборов входных данных, для которых заранее просчитан результат), его прогон и сравнение полученных результатов с эталонными (тестовыми). Число тестовых наборов должно быть достаточным для слежения за ходом выполнения программы по всем ее ветвям и проверки свойств, характеристик и функций (спецификаций) проектируемой программы. Кроме того, необходимы наборы, контролирующие допустимые значения для исходных данных и предельные значения для результатов. 1.5. Этапы подготовки и решения задач на компьютере Практика программирования показывает, что решение прикладных, инженерных, экономических и научных задач на ЭВМ сложный и трудоемкий процесс, состоящий из следующих этапов. 1. Постановка задачи состоит в четком изложении условия задачи и определении подзадач. 2. Физический и математический анализ. Анализируется, существует ли вообще решение данной задачи и единственно ли оно. Подбирается математический аппарат, и строится математическая модель для решения задачи. Выбирается метод или методика решения (составляются формулы, определяются правила, связывающие эти формулы). 3. Этап алгоритмизации. На основании выбранного метода и конкретных методик с учетом возможностей ПК разрабатывается алгоритм и строится его схема. Этот этап заключается в разложении вычислительного процесса на возможные составные части, описании содержания каждой такой части, установлении порядка их следования, которые определят структуру программы, т. е. разрабатывается укрупнённый алгоритм решения задачи и проверяется возможность реализации выбранного метода. Подобное расчленение алгоритма на составные части называется структуризацией. 4. Этап программирования. Выбирается язык и (или) система программирования, и в соответствии с алгоритмом разрабатывается программа на конкретном языке программирования. 5. Отладка программы и тестирование. Отладка программы состоит в обнаружении и исправлении ошибок, допущенных на всех этапах проектирования программы. Синтаксические ошибки обнаруживаются компилятором, который выдаёт сообщение об ошибке и её месте (в основном это ошибки в написании операторов) при компиляции. Алгоритмические ошибки или смысловые (семантические) обнаруживаются в результате тестирования. 6. Решение задач на компьютере. 7. Обработка результатов решения задач. Производится анализ результатов, строятся таблицы, графики, делаются выводы. 10 Дополнительно могут присутствовать такие этапы, как описание структуры программы, описание структур данных, оптимизация программы, этап документирования. Готовая программа в компьютере проходит следующие стадии: Компиляция Компоновка Исходный модуль Объектный модуль Загрузка Абсолютный (загрузочный) модуль Различают следующие системы подготовки и выполнения программы: 1) компилирующего типа (статистическая подготовка) (СИ, ПАСКАЛЬ); 2) интерпретирующего типа (динамическая подготовка). В системах компилирующего типа сначала для всей программы готовится загрузочный модуль, который затем выполняется, т.е. подготовка и выполнение разделены во времени. В системах интерпретирующего типа последовательно читается, транслируется и сразу же выполняется оператор за оператором (БЕЙСИК). 1.6. Словарь основных терминов Трансляция преобразование программы, представленной на одном языке программирования, в эквивалентную форму на другом языке. Компиляция трансляция программы с исходного модуля в объектный модуль (или на язык низкого уровня, близкого к машинному языку). Редактирование связей (компоновка) сборка программы с другими модулями и стандартными подпрограммами, приводящая к изменению порядка размещения, формата и содержимого данных. Загрузка пересылка программы с внешнего носителя данных в основную (оперативную) память и из основной в регистровую. Исходный модуль это текст программы, записанный на языке высокого уровня. Объектный модуль это программа после компиляции (в машинных кодах с относительными адресами). Абсолютный модуль это программа в машинных кодах с подсоединёнными к ней подпрограммами, настроенная на выполнение в заданной области оперативной памяти. Компилятор – программное средство, выполняющее компиляцию программы. 11 Транслятор программа или специальное технические средство, выполняющее трансляцию программы. Интерпретатор вид транслятора, осуществляющего пооператорную (покомандную) обработку и выполнение исходной программы. Редактор связей программа, предназначенная для построения одного загрузочного модуля из одного или более независимо транслируемых объектных или загрузочных модулей. Загрузчик обрабатывающая программа, выполняющая загрузку абсолютного модуля в основную память по установленным адресам. 2. НАЧАЛЬНЫЕ СВЕДЕНИЯ О ЯЗЫКЕ PASCAL ABC 2.1. Алфавит языка Алфавит языка включает буквы, цифры, шестнадцатеричные цифры, специальные символы и зарезервированные слова. 1. Буквы это прописные и строчные буквы латинского алфавита (они не различаются, если не входят в строковые или символьные выражения). 2. Арабские цифры это цифры от 0 до 9. 3. Шестнадцатеричные цифры, значения которых заключены в [0..15]: первые десять записываются цифрами от 0 до 9, остальные шесть латинскими буквами 10 – А, 11 – В, 12 – С, 13 – D, 14 – E, 15 – F (или a, b, c, d, e, f). 4. Символ подчеркивания. 5. Символ пробела. 6. Специальные знаки: а) знаки операций + - * / = > < <> := <= >= б) разделители и ограничители . " , ; ' ( ) [ ] @ $ # ^ в) составные символы (* *) (. .) .. Составные символы и составные знаки операций пробелами разделять нельзя. 7. Основные резервированные (ключевые) слова языка Паскаль: AND (логическая операция «И»), ARRAY (массив), BEGIN (начало), CASE (случай), CONST (константа), DIV (деление нацело), DO (делать), DOWNTO (уменьшая к), ELSE (иначе), END (конец), FILE (файл), FOR (для), FUNCTION (функция), GOTO (идти к), IF (если), IN (в), LABEL (метка), MOD (остаток от деления), NIL (пустая ссылка), NOT (логическая операция «НЕ»), OF (из), OR (логическая операция «ИЛИ»), PROCEDURE (процедура), PROGRAM (программа), RECORD (запись), REPEAT (повторять), SET (тип-множество), SHL 12 (сдвиг влево), SHR (сдвиг вправо), STRING (строка), THEN (то), TO (увеличивая к), TYPE (тип), UNIT (модуль), UNTIL (до тех пор пока), USES (использовать), VAR (переменная), WHILE (начало цикла с предусловием), WITH (оператор присоединения), XOR (логическая операция «исключающее ИЛИ»). 2.2. Константы В программе обрабатываются некоторые данные, которые представляют собой постоянные (константы) или переменные величины. В качестве констант в Pascal ABC используются целые, вещественные, шестнадцатеричные числа, логические константы, символы, строки символов, конструкторы множеств, признак неопределенного указателя. Целые константы записываются в естественной форме со знаком или без него, т.е. +1, 120, -35, 0 и т.п. Вещественные числа записываются в форме основной вещественной константы (естественная запись вещественного числа с десятичной точкой) или в экспоненциальной форме, когда число состоит из основной вещественной константы (или целой константы) и экспоненциальной части. Экспоненциальная часть начинается с символа Е(е), за которым следует десятичный порядок (целое число со знаком или без него). Например: 3.4; 5.56E4; -0.5Е-3; 3Е-1. Перед точкой и за ней должна следовать хотя бы одна цифра. Шестнадцатеричное число состоит из шестнадцатеричных цифр (0, 1, 2, ..., 9, А, В, С, D, E, F), перед которыми ставится признак шестнадцатеричного числа $. Например, $A5 (соответствует числу 165 в десятичной системе счисления). Логическая константа может принимать два значения: FALSE (ложь) и TRUE (истина). Символьные константы любой символ персонального компьютера, заключенный в апострофы. Для записи символа апострофа он удваивается (''''). Допускается записывать символы путем указания кода, которому предшествует знак #. Например, эквивалентными являются пары записей: #97 > 'а'; #67 > 'A'; #11 код перевода строки. Строковая константа это любая последовательность символов языка, заключенная в апострофы. Например, строковой константой является: 'Это строка'. Если две строковые константы отличаются типом букв (прописные или строчные), то такие константы считаются различными. В строке символов могут указываться коды символов, которым предшествует #. Например: #7'Ошибка' #7. Конструктор множества список элементов множества, заключенный в квадратные скобки ( [1, 2, 3, ... , 7, 8] , [ ], [TRUE] ). 13 2.3. Идентификаторы и типы данных Идентификаторы это имена констант и переменных, а также типов, объектов, процедур, функций, модулей, программ и полей в записях, которые объявляются в начале программы и затем в ней используются. Идентификатор описывается последовательностью латинских букв, цифр и знака подчеркивания, начинающейся с буквы. Он может иметь любую длину, но различимыми являются первые шестьдесят три символа (пробелы и специальные символы в идентификаторы не входят). Например, идентификаторами будут: x, z0, ALFA, x353, SENT_3_2010. В качестве идентификаторов в программе нельзя использовать зарезервированные слова и имена, которыми названы стандартные константы, файлы, функции, процедуры, типы Pascal ABC. Любые данные в программе (константы, переменные, значения функций или выражений) характеризуются своими типами. Тип определяет множество значений, которые может иметь данное, операции, применимые к нему, а также формат внутреннего представления. Любые данные до их использования должны быть предварительно объявлены с указанием их типа. Типы в Pascal ABC делятся на простые, структурированные, процедурные, указатели и строки. В свою очередь простые типы включают порядковые и вещественные данные, а структурированные делятся на массивы, записи, множества и файлы. Порядковые типы как стандартные, так и нестандартные, введенные разработчиком программы, отличаются тем, что каждый из них содержит конечное число возможных значений. Эти значения можно определенным образом упорядочить или перенумеровать. Для таких типов для каждой пары элементов можно всегда определить, какой из них предшествует другому. В Pascal ABC являются порядковыми типы integer, byte, char, перечислимый и диапазонный. Только значения этих типов могут быть индексами массивов, а также взяты в качестве выражения-переключателя в операторе выбора Case. К вещественным типам указанные функции применить нельзя, количество возможных значений вещественных типов очень велико, так что сопоставить с каждым из них число (его номер) невозможно. Для порядковых типов определены три специальные функции: ORD(X) возвращает порядковый номер значения выражения X; PRED(X) возвращает значение, предшествующее X в его типе, т.е. ORD( PRED(X) ) = ORD(X) - 1; SUCC(X) определяет следующее по порядку за X значение: ORD( SUCC(X) ) = ORD(X) + 1. 14 2.4. Переменные и именованные константы Переменная – это одно из основных понятий в программировании. Переменными называются величины, которые могут изменять свои значения в процессе выполнения программы. Для каждой переменной отводится отдельная ячейка памяти. Переменные имеют свои имена, называемые идентификаторами. Переменные объявляются в начале программы в разделе описания переменных, который начинается со служебного слова VAR, после которого следует описание переменных. Однако переменные могут быть объявлены в начале любого блока BEGIN . . . END таким же образом, как и в начале программы: VAR <имена_переменных> : <тип>; Имена переменных в списке перечисляются через запятую, через двоеточие указывается тип этих переменных, а в конце ставится точка с запятой. Например: VAR x, y : real; { переменные x, y вещественного типа} k, n : integer; { переменные k, n целого типа} Именованными константами называются константы, которым присвоены имена. Именованные константы объявляются в разделе описания констант, начинающегося со служебного слова CONST. Допустимы два способа объявления именованных констант – с указанием типа констант или без типа. Сначала пишется имя (идентификатор) константы, а затем за символом “равно” (=) записывается значение этой константы. Разделителем в списке констант служит символ “ ; ” например : CONST <идентификатор> = <значение> ; <идентификатор> : <тип> = <значение>; В отличие от переменных в системе Pascal ABC именованные константы в программе изменять нельзя. Именованные константы могут быть любого типа, кроме файлов. Примеры объявления именованных констант простых типов: {константа целого типа} {константа целого типа} { константа вещественного типа} { константа логического типа} { константа символьного типа} CONST d = 35; C1: integer = 311; C2: real = 3.14; C3: boolean = false; C4: char = 'A'; 15 В среде программирования Turbo Pascal константы с объявленным типом называются типизированными и фактически играют роль переменных с начальным значением. 2.5. Структура простой программы и комментарий Простая программа начинается с заголовка программы служебным словом PROGRAM, за которым пишется имя программы. После заголовка следует раздел объявления именованных констант CONST и раздел объявления переменных VAR. Далее следует основной блок программы, начинающийся ключевым словом BEGIN и заканчивающийся словом END с точкой в конце. Основной блок программы состоит из выполняемых операторов, в которых используются только те данные, что были объявлены в разделе описаний. В конце каждого оператора обязательно должен стоять символ “ ; “. Программа компилируется последовательно, поэтому все, что используется в программе или подпрограмме, должно быть определено выше. Приведем пример программы, преобразующей вещественные числа в целые: PROGRAM INTRЕAL; CONST Y= 5.7; VAR A, B, C: INTEGER; X, Y : REAL; BEGIN READ(X); {ввод числа с клавиатуры} A := TRUNС(X); {выделение целой части X} B := ROUND(Y); (* округление Y *) C := B - A; WRITELN( ' X= ' , X, ' A= ' , A , ' B= ' , B, ' C= ' , C); {вывод на экран монитора} END . Программа на языке Паскаль может содержать произвольные комментарии. Комментарий в Pascal ABC это произвольная последовательность любых символов, обрамленная фигурными скобками { и } или составными символами (* и *). С этой целью применяется также двойной слеш-символ //, после которого остаток строки воспринимается как комментарий. Комментарий разрешается вставлять в любое место программы, где по смыслу может стоять пробел. 16 3. ОПЕРАТОР ПРИСВАИВАНИЯ И ЧИСЛОВЫЕ ДАННЫЕ 3.1. Арифметические выражения В программах на Паскале обрабатываются выражения различных типов. Простое выражение представляет собой константу или переменную. Сложное выражение содержит константы и переменные, объединенные знаками операций, скобками и функциями. Данные, которые участвуют в операциях, называются операндами. Операциями называются действия, производимые над данными (т.е. операндами). Арифметическим называется выражение, содержащее операнды целого или вещественного типов и арифметические операции. Правило для определения типа арифметического выражения: если в выражении все операнды целые и отсутствует операция деления, то результат выражения получится целого типа (integer), в противном случае вещественного типа (real). В арифметических выражениях могут использоваться бинарные и унарные арифметические операции (табл. 1), а также стандартные функции. Таблица 1 Приоритеты операций в выражении № п/п 1 2 3 4 Арифметические Логические *, /, div, mod +, - NOT аnd, shl, shr, оr, xor Отношения Другие @ адресное преобразование <=, >=, <>,<,>,= in К бинарным относятся арифметические операции, применяемые к двум операндам: умножение ( * ), деление ( / ), целочисленное деление ( DIV), остаток от целочисленного деления (MOD), сложение (+) и вычитание ( - ). К унарным относятся арифметические операции, применяемые к одному операнду: операции + и – для целых вещественных чисел. При выполнении целочисленного деления операцией DIV результатом является целая часть частного (остаток отбрасывается), например: 15 DIV 4 = 3. В случае применения операции MOD результатом является остаток от деления левого на правый операнд (оба операнда целые), например: 11 MOD 3 = 2. Согласно общим правилам вычисления в первую очередь вычисляются выражения, заключенные в круглые скобки, а затем вычисляются значения функций, входящих в выражение. 17 В арифметических выражениях без скобок вычисления выполняются в соответствии с приоритетом операций (табл. 1), т.е. сначала выполняется унарная операция (унарный минус), затем операции умножения и деления ( *, /, div, mod) и в последнюю очередь операции сложения и вычитания ( +, - ) . 3.2. Оператор присваивания Как и во всех языках программирования, в Pascal ABC имеется оператор присваивания. Он служит для определения или переопределения значения переменной. В случае переопределения старое значение переменной стирается и записывается новое значение. Структура оператора присваивания имеет следующий вид: <идентификатор> := <выражение>; Для идентификатора (имени переменной) допускается использовать любой тип, за исключением файлового. При этом тип идентификатора и тип выражения в операторе присваивания должны быть совместимы [1–3], т.е. для арифметического выражения используется переменная арифметического типа, для логического выражения – переменная логического типа и т.п. С помощью этого оператора переменной, идентификатор которой стоит в левой части, присваивается значение выражения. Для обозначения операции присваивания применяется составной символ присваивания ( := ), слева от которого записывается имя переменной, а справа выражение, значение которого предварительно вычисляется перед выполнением присваивания. Пример арифметического оператора присваивания, где переменным присваиваются значения арифметических выражений: y := x*y + sin(x); x := 0; { VAR x, y: real ; } { VAR x: integer ;} Пример логического оператора присваивания, где переменной присваивается значение логического выражения: B := ( X<0 ) OR ( K>1 ); { VAR X, K: real; B: boolean;} . Пример оператора присваивания, где переменной присваивается символ: S := ' + '; { VAR S: char;} 3.3. Процедуры ввода-вывода Ввод данных осуществляется с клавиатуры с помощью процедур Read или ReadLn. При повторных вызовах процедура Read позволяет вводить данные в одной и той же строке, а ReadLn выполняет ввод каждый раз с новой строки. 18 Например, ReadLn(x); означает ввод одного значения для переменной х. При выполнении данной процедуры происходит приостановка выполнения действий в программе и переход компьютера в состояние ожидания. Для ввода данных необходимо при помощи клавиатуры набрать нужное значение для переменной х и затем нажать клавишу ввода “Enter”. Для процедуры ввода Read(x, y); необходимо будет ввести через пробел уже два значения: одно для переменной х, другое для переменной y. Вывод данных на экран монитора осуществляется при помощи процедур write или writeln. При повторных вызовах процедура write продолжает выводить данные в одной и той же строке, а writeln выводит данные каждый раз с новой строки. Например, процедура WriteLn(n:3); позволяет вывести на экран значение переменной n целого типа по заданному формату “ :3 ”. Согласно этому формату число позиций, отводимых под запись всего числа, включая его знак, будет равно 3. Процедура Write(‘ s = ’ , s:8:3); выводит на экран сначала комментарий в виде символов s =, а затем само значение вещественной переменной s по указанному формату “ :8:3”, где 8 будет задавать общее число позиций, отводимых под запись всего числа, включая его знак, а 3 определяет число цифр после десятичной точки в записи этого же числа. 3.4. Стандартные функции Pascal ABC В таблице 2 приведены стандартные функции языка Pascal ABC, которые можно использовать в программах. Таблица 2 Обращение 1 ABS(X) SQR(X) SIN(X) COS(X) LN(X) EXP(X) SQRT(X) ARCTAN(X) Выполняемые функции 2 |Х X2 Sin Xsin x Cos X cos x ln x eX x arctan x 19 Тип аргумента 3 целый или вещественный функции 4 целый или вещественный целый или вещественный вещественный Окончание табл. 2 1 TRUNC(X) ROUND(X) PRED(X) SUCC(X) ORD(X) CHR(X) ODD(X) Frac(X) Int(X) 2 Выделение целой части числа Округление Х до ближайшего целого Нахождение предшествующего значения (в его типе) Нахождение последующего элемента (значения, следующего за Х в его порядковом типе) Определение порядкового номера символа Х в наборе символов или его перечислимом типе Определение значения символа по его порядковому номеру Логическая функция проверки нечетности Дробная часть числа Целая часть числа 3 4 вещественный целый целый, целый, логический или символьный логический или символьный символьный целый целый символьный целый логический вещественный вещественный 3.5. Целые типы в Pascal ABC В Pascal ABC имеется три стандартных типа целых чисел: Byte, Integer и Word. Диапазон их возможных значений зависит от внутреннего представления числа, которое может занимать один, два или четыре байта. В таблице 3 приведены характеристики этих целых типов. Таблица 3 Классификация целых типов Длина, байт 1 2 4 Название BYTE WORD INTEGER Диапазон от 0 до 255 от 0 до 65535 от -2147483648 до +2147483647 20 Примечание Короткое целое без знака Целое без знака Целое со знаком Компилятор языка Pascal ABC определяет максимальное значение MAXINT для данных типа INTEGER. При этом справедливо будет соотношение: MAXINT <= K <= MAXINT Описание переменных целых типов производится в разделе описаний VAR: Var <имя переменной> : <целый тип>; где <целый тип > может быть определен как Byte, Integer или Word. Например: VAR K: INTEGER; I, J: BYTE; Для целых типов определены следующие операции: сложение, вычитание (имеют более низкий приоритет), умножение и деление DIV, MOD. К целым типам применимы функции из таблицы 4. Функции TRUNC(X) и ROUND(X) с вещественным аргументом также дают целый результат (см. табл. 2). Стандартные математические функции в случае задания целого аргумента всегда возвращают вещественные значения (см. табл. 2). При использовании процедур и функций с целочисленными параметрами следует руководствоваться правилом «вложенности» типов, т.е. везде, где в качестве аргумента используется тип WORD, можно применять тип BYTE. Для арифметических операций, если операнды относятся к разным целым типам, тип результата имеет максимальную мощность диапазона, т.е. для типов операндов Byte и Word в выражении тип результата будет Word. Таблица 4 Встроенные процедуры и функции для целых типов Обращение ABS(X) SQR(X) CHR(B)) ODD(L) Тип результата Как у аргумента Как у аргумента CHAR BOOLEAN RANDOM(W) Как у аргумента DEC(Х, [i] ) INC(Х , [i] ) Процедура Процедура Действие Возвращает модуль числа Х Возвращает квадрат числа Х Возвращает символ по его коду Возвращает значение TRUE, если аргумент – нечетное число, FALSE если четное Возвращает псевдослучайное число, равномерно распределенное на интервале 0<=X<=W Уменьшает Х на 1 [на i] Увеличивает Х на 1 [на i] 21 3.6. Вещественные типы В отличие от целых типов значения вещественных типов определяют число с десятичной точкой лишь с некоторой точностью, зависящей от внутреннего представления числа. Вещественное число в памяти ПК хранится в формате, состоящем из знака, мантиссы и порядка числа. Десятичная точка подразумевается стоящей перед левым (старшим) разрядом мантиссы (такая мантисса называется нормализованной). При выполнении операций десятичная точка сдвигается путем выполнения умножения мантиссы на E (символ экспоненты) с порядком. Например, запись числа в виде: <знак> <мантисса> Е <порядок> соответствует представлению числа <знак> <мантисса>*10 <порядок>. В Pascal ABC используются только два вещественных типа – REAL и COMPLEX , характеристики которых приведены в таблице 5. Таблица 5 Вещественные типы Длина, байт Название типа 8 16 REAL COMPLEX Значащие цифры мантиссы 15..16 15..16 Диапазон десятичного порядка -324 …+308 -324 …+308 Объявление переменных вещественных типов производится в разделе описаний переменных VAR аналогично переменным целых типов в виде: Var <переменная> : <вещественный тип>; где <вещественный тип > может быть задан только Real или Complex. Для работы с вещественными типами определены стандартные функции: sin, cos, arctаn, ln, exp, sqr, abs, sqrt (табл. 2), а также функции вещественного типа (табл. 6). Таблица 6 Встроенные функции вещественного типа Обращение Pi Frac(Х) Int(x) Random Randomize Тип параметра Тип результата Примечание вещественный вещественный вещественный вещественный вещественный вещественный Pi = 3,141592653 Дробная часть Х Целая часть x 0<x<1 случайное число Инициализация датчика случайных чисел 22 При этом операции +, -, *, / в арифметическом выражении дают вещественный результат, если хотя бы один из операндов вещественный. Переменные комплексного типа Данные комплексного типа (complex ) в программе записываются в скобках в виде (x,y), где x и y – выражения (константы, переменные) вещественного типа, представляющие собой вещественную и мнимую части комплексного числа. Если переменная c имеет тип complex, то обратиться к ее вещественной и мнимой частям можно как к полям записи: c.re и c.im. Например: const c1 = (0,1); var c: complex; ... c.re := 2*c.im; c := c1*c+(c.im, c.re); Для работы с переменными типа complex также используются стандартные функции: abs, sin, cos, exp, ln, sqrt . Кроме того применяется функция conj(C), возвращающая значение, комплексно сопряженное к C, и функция carg(C), возвращающая главное значение аргумента комплексного числа C, которое находится в числовом диапазоне (-Pi, Pi). 3.7. Примеры и задания к самостоятельному выполнению Ниже приводятся три простейшие программы линейной структуры, в которых используются оператор присваивания и процедуры ввода-вывода. Пример 1. Вычислить площадь прямоугольника по размерам сторон А и В. Обозначим площадь переменной S, тогда необходимо найти S = A*B. Программа набирается в окне редактора и исполняется клавишей [F9]: Program RECT ; {заголовок программы с именем RECT} const {заголовок раздела описания констант} A=2 ; B=3 ; {объявление констант А и В} var {заголовок раздела описания переменных} S: integer; {объявление переменной S целого типа} begin {начало основного блока программы} S := A*B; {оператор присваивания} write( ' Площадь прямоугольника = ' , S); {процедура вывода данных} end . {конец основного блока} В результате выполнения программы (Ctrl+F9) на экран выводится сообщение: Площадь прямоугольника = 6. 23 Пример 2. Найти площадь равностороннего треугольника. Начало Если стороны треугольника имеют размер А, Ввод А то его площадь S = A2 sin(π/3)/2. Схема алгоритма (СА) реализации этой задачи (рис. 4) выполнена по ГОСТ 19.701-90 (прил. 1). Текст программы: S Program TREUG ; var A, S: real; begin writeln( ' Введите A ' ); {процедура вывода текста} read(A); {процедура ввода исходных данных} S: = SQR(A) * sin (PI / 3) / 2; writeln (' Результат: S= ' , S: 6: 2 , ' для A= ' , A); end . А2 sin 2 3 Вывод S Конец Рис. 4 4 После выполнения программы на экран выводится сообщение Результат: S = 10.83 для А = 5. Предварительно рассчитанный на калькуляторе результат для А = 5 составил S = 10.8253, что подтверждает правильность работы программы. Пример 3. Вычислить функцию y сначала при х = 0 , а затем при х = 2: y a e cx c cos bx 1 , где A = 1.2, B = 0.5, C = 0.8 . Получаем следующий текст программы: Program Fun ; Const A = 2; B = 0.5; C = 0.8; var X : integer; // переменная X целого типа Y : real; // переменная Y вещественного типа Begin writeln( ' Введите Х ' ); {процедура вывода текста} read( X ); // введите значение переменной X Y := A*EXP(C*X) C*cos(B*X) +1; writeln( ' X= ' , X :3, ' Y= ' , Y:8:3); // вывод значений X и Y End. 24 Задания к самостоятельному выполнению (программа_1_1) Вычислить значение некоторой функции, зависящей от констант a, b, c и переменной X, два значения x1 и x2 для которой заданы в таблице. № 1 x1 2 x2 3 a 4 b 5 c 6 Вычислить 7 1 1 2 1.5 2 -0.7 w ae x cos(bx) c 5 2 1 2 0.7 - 2.1 y sin x c ln ax 2 2 1 а sin x 3 0 1.5 2 1.2 1 z a b esin x c - 3 2 x a cos 2 x w x a b sin 3 x 2 1.5 y bx2e ax a х 1.5 0.5 1.3 - 2 0.5 1 - -1 1 2.7 1.7 - y a 2 /( x 2)e bx ln( a bx) 0 π/2 2 0.7 0.5 z a 3 cos( bx sin 2 х) 3 c 1.5 ax 2 x cos(bx) w bx e x sin(bx) c 4 1 2 4.1 -2.3 5 -1 1 0.5 6 2 4 7 0 8 9 z 4 e aх х х 2 w e a хa х b x 1 e bx 3 x 1 2 10 1 0 0.5 11 1 2 1.5 -1.2 - y e ax 3 ax bsi n(2 x) 12 1 2 0.5 1.7 2 z e bx sin(сx b) bx a 13 -1 1 0.5 1.2 - w 2 x arctg ( x a) 3 bx cos(x b) 14 1 2 0.5 3.1 - 15 1 2 0.5 3.2 - 16 17 0 0 1 1 1 1 2.9 2 2 3 y ax sin 2 x e 2 x ( x b) z e2 x ln(a x) b3x lg(b x) w 4 x a a y - 25 x2 b 3 x x2 c b e x 1 a x 2 x tgx 1 2 3 4 5 6 18 -1 2 1 2 - 19 1 2 2 3 1 20 -1 1 2 π/6 0.5 7 z a cos( x b) x 4 / 2 sin 2 x w ln (b x ) (x y c ) a x2 / 4 a cos( x b) 2x c sin 2 x В следующих заданиях необходимо самостоятельно разработать алгоритмы решения и отладить программы (программа_1_2). 1. Идет k секунда суток. Определить, сколько целых часов (h) и целых минут (m) и секунд (s) прошло к этому моменту. 2. Определить площадь трапеции с основаниями а, b, высотой h и объем усеченного конуса, если считать а, b – площадями оснований. 3. Определить координаты центра тяжести трех материальных точек с массами m1, m2, m3 и координатами (x1, y1), (x2, y2), (x3, y3). 4. Вычислить по заданному радиусу R объем шара и площадь круга, найти соотношение между ними. 5. Вычислить медианы треугольника по заданным сторонам a, b, c. 6. Вычислить площадь поверхности и объем конуса по заданным радиусам и высоте h. 7. По заданному радиусу R найти объем шара и площадь его поверхности. 8. Вычислить, какая идет секунда суток при положении стрелок в h часов, m минут и s секунд, а также угол (в градусах) между положением часовой стрелки в начале суток и ее положением в указанный момент. 9. Ввести двузначное целое число х<15. Написать программу перевода его в восьмеричную систему счисления. 10. Ввести координаты двух точек (х1, y1), (x2, y2). Найти расстояние между ними. 4. ПРОГРАММИРОВАНИЕ РАЗВЕТВЛЕННЫХ АЛГОРИТМОВ 4.1. Логические выражения Как известно, логическая константа может принимать только два значения: FALSE (ложь) и TRUE (истина). Переменные логического типа объявляются ключевым словом BOOLEAN в разделе описания переменных VAR и также могут принимать только два значения FALSE или TRUE (FALSE<TRUE). 26 Для данных логического типа значению FALSE соответствует в компьютере число 0, значению TRUE – число 1, которые записываются в ячейку памяти длиной 1 байт [6, 7]. Для значений TRUE и FALSE справедливы следующие функции: ord (FALSE) = 0; ord (TRUE) = 1; succ (FALSE) = TRUE; pred (TRUE) = FALSE. Простым логическим выражением называется выражение, содержащее только логические операнды (константы или переменные типа Boolean). В сложных логических выражениях кроме логических операндов используются бинарные и/или унарные логические операции, а также стандартные функции (табл. 2) и операции отношений: <, <=, >, >=, =, <> . Операции отношения также относятся к операциям логического типа. Их можно использовать для проверки соотношений между переменными и константами типов real, integer, char, string. Например: a < b, x>=0, x=y и т.д. К бинарным операциям относятся логические операции: AND (логическое "И"), OR (логическое "ИЛИ"), XOR ("исключающее ИЛИ"), а к унарным операция NOT (отрицание "НЕ"). В логических выражениях без скобок согласно приоритету логических операций (см. табл. 1) сначала выполняется операция NOT, затем AND, после неё OR и XOR , а в последнюю очередь операции отношений. Логические операции используют понятия алгебры логики (булевой алгебры). Они применяются в задачах, когда нужно проверить какое-либо сложное условие. Операция конъюнкции and (логическое умножение) в логическом выражении A and B дает результат true (истина), если A и B имеют значение true, иначе во всех остальных случаях – false (ложь). Операция дизъюнкции or (логическое сложение) в логическом выражении A or B дает результат false, если A и B одновременно имеют значение false, во всех остальных случаях – true. Операция инверсии not (логическое отрицание) в логическом выражении not A дает результат true, если A = false и, наоборот, при A = true выражение not A примет значение false. Для переменных логического типа определена также операция присваивания. Пример: VAR С, D: REAL; X, Y, A, B: BOOLEAN; 27 BEGIN X :=A OR B; Y := (C>0) AND (C<D); … END. Логический результат дает стандартная функция ODD(x) проверки на нечетность числа x, функции EOLN (f) проверки конца строки и EOF(f) определения конца файла f. 4.2. Условный оператор IF Условный оператор позволяет проверить некоторое условие и в зависимости от результата проверки этого условия выполнить то или иное действие, т.е. создать ветвление в программе. Структура условного оператора в полной форме имеет следующий вид: IF <условие> THEN <оператор1> ELSE <оператор2>; (если) (то) (иначе) где <условие> это выражение логического типа, которое может принимать только два значения: TRUE (истина) или FALSE (ложь). Правило выполнения условного оператора. Вначале вычисляется значение <условия>, стоящего за IF. Если результат условия истинен (TRUE), то выполняется только <оператор1>, а <оператор2> пропускается и выполняется следующий оператор. В противном случае выполняется <оператор2>, а <оператор1> пропускается и выполняется следующий оператор в программе. Структура условного оператора в сокращенной форме следующая: IF <условие> THEN <оператор1>; Здесь в случае ложности <условия>, стоящего за IF, пропускается <оператор1> и выполняется следующий за ним оператор программы. В качестве <оператор1> или <оператор2> по синтаксису может выполняться только один оператор Паскаля. Для выполнения после THEN или после ELSE неcкольких операторов применяется составной оператор с операторными скобками ( BEGIN … END ) . Несколько условных опеpатоpов могут быть вложены друг в друга. Ниже приведен пример вложения для трёх условных опеpатоpов: IF <условие1> THEN IF <условие2> THEN IF <условие3> THEN <оператор3> ELSE <оператор4> ELSE <оператор2> ELSE <оператор1>; 28 4.3. Составной и пустой операторы Составной оператор используется в том случае, когда по правилам синтаксиса сложного оператора должен стоять только один оператор, а в алгоритме необходимо выполнить некоторую последовательность действий. Составной оператор объединяет эту последовательность в единый по синтаксису оператор путем заключения в операторные скобки begin и end. Например: ВEGIN <оператор1>; <оператор2>; ...; <операторN> END; Для составного оператора допускается любая глубина вложенности: BEGIN BEGIN ... BEGIN ... END; ... END; END ; Пустой оператор не выполняет никаких действий и может быть использован для передачи управления в конец составного оператора. Пустой оператор записывается в виде точки с запятой. Например, пустыми операторами будут следующие записи: 1) ; ; 2) <метка>: ; 4.4. Оператор безусловного перехода Оператор безусловного перехода позволяет изменить обычный последовательный порядок выполнения операторов и непосредственно перейти к нужному оператору, предварительно помеченному меткой. Структура такого оператора: GOTO <метка>; где GOTO ключевое слово, обозначающее перейти к <метке>, <метка> является произвольным идентификатором, который позволяет пометить любой оператор в программе и потом ссылаться на него. Оператор от 29 метки отделяется двоеточием. В языке Pascal ABC допускается использовать в качестве метки также целое число без знака. Пример: LABEL m1, loop; VAR a, b, c, d: word; BEGIN m1: a := b+c*d; ... goto m1; loop: END. Все использованные в программе метки должны быть описаны в разделе описаний программы с указанием ключевого слова “LABEL”. Описанные в этом операторе метки обязательно должны быть использованы в программе. Метки, описанные в функции или процедуре, локализуются только в ней, передача управления извне процедуры на метку внутри ее невозможна. С помощью оператора GOTO не рекомендуется осуществлять переход во внутреннюю часть сложного оператора (цикла, составного оператора). Запрещается переход с одной альтернативной части (ветви) сложного оператора на другую. Современная технология структурного программирования основана на принципе программирования без GOTO. Считается, что злоупотребление этими операторами затрудняет чтение программы, усложняет ее отладку. Тем не менее, в некоторых случаях использование оператора перехода может упростить программу. Обычно GOTO используется для досрочного выхода из любого сложного оператора или вложенных операторов цикла. 4.5. Пример и задания с оператором IF Пример. Вычислить значения функции y(x) в зависимости от интервала, в который попадает аргумент x. Для x [-10,5] 2 ax ln( x 1) y ax b ax1 cos bx e при 0 x 2 при x 0 при x 2 где а = 1.5, b = 0.5 ; Напишем программу, соответствующую схеме алгоритма (рис. 5): Program Lr2; Label m1, 10; 30 Const A = 1.5; B = 0.5; var x, y: real; // переменные вещественного типа Begin m1: read(x); // вводим значение переменной x IF (x < -10) or (x>5) then goto m1; IF x<0 then begin y:= a*x+b ; goto 10 end ; if (x >= 0) and (x<=2) then y :=A*SQR(x)*LN(x+1) ; if x>2 then y := EXP(A*x+1)*COS(B*x); 10: writeln( ' x= ', x :8:1 , ' y= ' , y :8:2); //вывод значений x и y End. Каждому условному оператору в программе соответствует символ “решение” в схеме алгоритма на рис. 5. Программу можно упростить, используя вложенные условные операторы. Например, если в первом и втором операторах IF добавить их альтернативные части ELSE, тогда в третьем IF условие упростится до вида (x <= 2) и не потребуется последний оператор IF. Начало Ввод x Нет -10<x<5 Да Да x<0 Нет Да 0≤x<2 Нет y=e ax+1 cos(bx) Вывод x,y Конец Рис. 5 31 y=Ax+b y = ax2 Ln(x+1) Задания к самостоятельному выполнению (программа_2_1) Вычислить значение функции в зависимости от интервала, в который попадает вводимый с клавиатуры аргумент: 1. Для t [0,3], где a = -0.5,b = 2 2. Для x [0,4], где а = 2.3 3. Для x [0,7], где a = -2.7,b = -0.27 4. Для i [7,12], где a = 2.2,b = 0.3. 5. Для x [0.9,5], где a = 1.5 6. Для t [-1.4], где a = 2.1,b = 0.37. z= при 1 t 2, при t < 1, eatcosbt при t > 2, х cos(x-a) при x 2, при 0.3 < x 2, при x 0.3, (a+b)/(ex+cosx) (a+b)/(x+1) ex+sinx при 0 x 2.3, при 2.3 x 5, при 7 х 5, ai4+bi tg(i+0.5) при I < 10, при I = 10, e2i+ a 2 i 2 x2-7/x2 ax3+7 x lg(x+7 x ) при I > 10, при x < 1.3, при 1.3 x 3, при x 3, 5 f= z= y= y= xa at 2 b sin t 1 z= 7. Для x [0,6], где a = 1.5. at2lnt 1 y= at+b при t < 0.1, при 0.1 t 2, at 2 b cos t 1 при t 2, a esinx+2.5 при x < 0.3, ecosx+a при 0.3 x < 4, (sin x)/(a+ex) при x 4, 8. Для x [1,2], a/x+bx2-c y= где a = 1.8,b = -0.5, c = 3.5 (a+bx)/ x 1 при x 1.2, при x > 1.2, 9. Для t [1,5], где a = 2.5 при t > a, при t = a, при t < a, z= t3 t a t sin at e-at cos at 32 10. Для x [0,4], где a = 1,b = 3 11. Для t [0.5,3], где a = 1.3, b = 6.5 12. Для x [0,2], где b = -2.9 13. Для x [0.5,2] где a = -0.8 14. Для x [1,2], где b = 1.3 15. Для x [-1,1], где a = 2.5,b = -0.9 y= e-bx sin bx сos bx e-ax cos bx при x < 2.3, при 2.3 x 3, при x 3, z= at2-b t 1 a-b a t2/3- 3 t 1 при t < a, при a t b, при t > b, y= |e-2x sin bx| cos bx e-x cos bx при x >1, при x = 1, при x < 1, z= sin (cos ax) tg ax a2 x при x >1, при x = 1, при x < 1, y= ln bx - 1/(bx+1) bx + 1 ln bx +1/(bx+1) при x < 1.3, при 1.3 x 1.7, при x > 1.7, z= ax2+bx2/3 a x2 b x2/3 при x < 0.1, при x = 0.1, при x > 0.1. 16. Ввести координаты точки (x, y). Напечатать, в каком квадранте или на какой оси координат находится эта точка. 17. Ввести радиусы R1, R2 и высоту. Вычислить объем усеченного конуса: h(S1 S1S2 S2 ) / 3 , где S – площадь оснований. Если R1 = R2 – объем и площадь цилиндра, если R1 = 0 или R2 = 0 – объем (hπr2) и площадь πr( r 2 h 2 ) поверхности конуса. 18. Ввести с клавиатуры цифру. Определить, какой системе счисления она может принадлежать. 19. Ввести число. Определить, делится ли оно нацело на два, три или на пять. 20. Ввести a, b, h. Если h = 0, вычислить площадь прямоугольника; при a = b, найти площадь квадрата; в противном случае подсчитать площадь трапеции. 33 4.6. Оператор выбора варианта CASE Оператор CASE позволяет в зависимости от значения какой-либо переменной или выражения порядкового типа выполнить те или иные действия. Его структура имеет следующий вид: CASE <ключ_выбора> OF <константа_выбора1>: <оператор1>; <константа_выбора2>: <оператор2>; ... <константа_выбораN>: <операторN> ELSE <оператор> END; где <ключ_выбора> переменная (или выражение) любого порядкового типа; <константа_выбора> константа того же типа, что и <ключ_выбора>; <оператор> произвольный оператор Pascal ABC. Принцип действия оператора. Сначала вычисляется <ключ_выбора>, затем в списке констант выбора отыскивается нужная константа, равная <ключу_выбора>, и выполняется стоящий за ней оператор. После этого оператор CASE завершает работу. Если в списке не найдена константа, совпадающая с "ключом", выполняется оператор, стоящий после ELSE. Заметим, что стоящая в конце часть ELSE <оператор> является не обязательной. При отсутствии в списке выбора нужной константы оператор выбора просто завершает свою работу. Любому из операторов <списка выбора> может предшествовать несколько <констант выбора>. В этом случае они разделяются запятыми или представляют собой диапазон значений. Пример: CASE <ключ> OF 1: <оператор1>; 2, 3: <оператор2>; 4 .. 6: <оператор3> ELSE <оператор> END; <Константа_выбора> не является меткой оператора, поэтому в разделе меток описывать её нельзя. 34 4.7. Примеры и задания с оператором CASE Пример 1. Выполнить арифметическую операцию в зависимости от введенного с клавиатуры символа. VAR operation: char; x, y, z: real; BEGIN read(x,y); read (operation); CASE operation OF '+': z:=x+y; '-': z:=x-y; '*': z:=x*y; '/': z:=x/y; ELSE write('нет опеpаций') END; WRITELN( ' z= ' , z ) END. Пример 2. Составить программу для начисления зарплаты согласно следующему правилу: если стаж работы сотрудника менее пяти лет, то зарплата равна 50$, при стаже работы от пяти до 15 лет – 100$, свыше 15 лет зарплата повыНачало шается с каждым годом на 10$, причем при стаже, превышающем 30 лет, она составВвод стажа ST ляет 300$. Для программирования решения этой ST задачи определим математическую формулировку задачи: 1..4 ZP = 50 50, если ST < 5; 5..15 100, если 5 ≤ ST 15; ZP = 100 ZP = 100 + (ST -15)*10 при 15 < ST ≤ 30; 16..29 ZP = 100+ 300, если ST > 30; + (ST-15)* 10 где ZP – зарплата, ST – стаж работы. ZP = 300 Реализация задачи для примера 2 представлена следующим алгоритмом Вывод (рис. 6) и программой: ZP Program zarplata; var ST: byte; {стаж (байтовый) тип)} Конец ZP: real; {вещественный тип} Рис. 6 35 begin writeln('введите стаж'); read(ST); {ввод стажа} case ST of {выбор из } 1..4: ZP:=50; 5..15: ZP:=100; 16..29: ZP:=100+(ST-15)*10 else ZP:=300 end; writeln(' Зарплата = ' , ZP:10:2,' $'); end. {вывод результата} Задания к самостоятельному выполнению (программа 2_2) 1. Определить остаток от деления на восемь введенного числа х и написать восьмеричную цифру прописью. 2. По цифре (0..9), введенной с клавиатуры, напечатать название этой цифры. 3. С клавиатуры ввести число k (1..30). Определить, какому дню недели оно соответствует, если первое число – понедельник. 4. Ввести число и номер месяца. Напечатать дату с названием месяца прописью. 5. Идет k секунда суток. Вычислить, сколько прошло часов и полных минут к этому моменту, при этом согласовать со значением слова (час, часа, часов, минута, минуты, минут). 6. В зависимости от номера (N) типа фигуры организовать ввод необходимых данных и вычислить при N = 1 – площадь круга, N = 2 – объем шара (4/3πR3), N = 3 – объем цилиндра, N = 4 – площадь поверхности сферы 4πr2. 7. Ввести число N (0 ≤ N ≤ 15). Определить и напечатать шестнадцатеричную цифру, ему соответствующую. 8. Для целого числа R (1…99) напечатать фразу « Мне R лет », при некоторых значениях R слово «лет» заменить словом «год» или «года». 9. В зависимости от заданного номера фигуры ввести необходимые данные и вычислить при к = 1 площадь прямоугольника, при к = 2 площадь параллелограмма, а при к = 3 площадь трапеции по формуле (a+b) h/2. Во втором случае напечатать: является ли фигура параллелограммом или ромбом. 10. Перевести введенное целое число 0 ≤ х ≤ 31 в шестнадцатеричную систему счисления. 36 5. ПРОГРАММИРОВАНИЕ АЛГОРИТМОВ ЦИКЛИЧЕСКОЙ СТРУКТУРЫ 5.1. Оператор счётного цикла В языке Pascal существует три разновидности операторов цикла: 1) счетный оператор цикла (оператор цикла со счётчиком); 2) оператор цикла с предусловием; 3) оператор цикла с постусловием. Для любого оператора цикла вход в цикл возможен только через его начало, выход осуществляется как вследствие естественного окончания цикла, так и путем выполнения оператора перехода GOTO или процедур выхода, содержащихся внутри цикла. Счетный оператор цикла FOR реализует циклический процесс с известным числом повторений. Этот оператор имеет две формы записи. Первая форма позволяет наращивать <параметр цикла> на единицу и имеет вид FOR <параметр_цикла> :=<min_значение> TO <max_значение>DO<оператор>; Параметром цикла называется переменная, служащая для управления циклом. Для оператора цикла FOR в качестве <параметра_цикла> используется переменная целого либо любого порядкового типа. Здесь <min_значение> и <max_значение> это константы (или выражения), определяющие соответственно начальное и конечное значения параметра цикла. Их типы должны быть совместимыми с типом параметра цикла. Вторая форма позволяет уменьшать на единицу значение параметра цикла: FOR <параметр цикла> := <max значение> DOWNTO <min значение> DO <оператор>; Пример. Вычислить Y = 1 + 1/2 + 1/3 + ... + 1/N. Для вычисления в программе необходимо многократно произвести сложение по “формуле суммы” Y =Y+1/I при изменении параметра I от одного до N. Реализация 1: Y:=0; FOR I:=1 TO N DO Y=Y+1/I; Реализация 2: Y:=0; FOR I:=N DOWNTO 1 DO Y=Y+1/I; 37 Значение параметра цикла в теле цикла может не использоваться, а лишь выполнять функцию счетчика. Например, пусть необходимо вычислить Y = Xn. Тогда фрагмент тела программы запишется в следующем виде: Y:=1; FOR I :=1 TO N DO Y=Y*X; Два других оператора цикла (с пpедусловием и постусловием) проверяют условия повторения или окончания цикла, но сами не изменяют значения параметра цикла. Они организуют выполнение цикла с неизвестным заранее числом повторений. 5.2. Примеры и задания для оператора цикла со счётчиком Пример 1. Вычислить сумму членов ряда: s = 1 +1/4 +1/9+ 1/16 + ... . Учитывая, что параметр знаменатель числового ряда – изменяется как квадрат натурального числа, определим алгоритм решения задачи в виде циклической структуры (pис. 7) и напишем соответствующую программу: PROGRAM summa; VAR s, r: REAL; i, N: INTEGER; Начало BEGIN s:=0; WRITELN('введите N'); Ввод N READ(N); FOR I :=1 TO N DO begin S=0 r := 1/sqr(i); s := s + r; end; i=1, N WRITELN( ' Сумма= ' , s:6:2 ); END. Вывод S r =1/i2 Конец S=S + r Pис. 7 38 Пример 2. Вычислить значения двух функций F1(x) = tg (x) и F2(x) = sin(x) в n точках, равномерно распределенных на интервале a ≤ x ≤ b, где a = -π/4, b = π. Для реализации данной задачи разработана схема алгоритма (pис. 8) и cледующая программа: Program Lab3; Const а = -pi/4; b = pi; Var F1, F2, x, dx: real; {dx – шаг изменения х} i, n: integer; {i – параметр цикла} Begin writeln ('введите число точек N'); read(n); dx: = abs(b-a)/(n-1); x:=a; writeln (' ___________________________'); writeln ('| I | X| F1 | F2 |'); writeln ('|---|------------|------------|------------|'); for I := 1 to n do {опеpатоp цикла} begin F2:= sin(x); F1:= F2/cos(x); {вычисление tg x} writeln('|', i:3,' |', x:8:3,'|', f1:8:4,' |', f2:8:4,' |'); x := x + dx; end; writeln( ' | ________________________| );. End. Начало Ввод a,b,N ax = | b-a | / (n-1), х=а i=1, N x=a F1=tgx, F2=sinx Вывод i,x,F1,F2 x = x + dx Конец Рис. 8 Задания к самостоятельному выполнению Задание 1 (программа_3_1) Для заданных с клавиатуры значений переменных x и n вычислить: 1. X = 1 + 1/2 + 1/3 + ... + 1/10. 2. Z = 2 4 6 8 ... 20. 3. Y = -x + 4x - 9x + ... - 81 x. 4. Y = x + x/3 + x/5 + ... + x/17. . 5. Y = n! = 1 2 3 ... n. 6. Y = 1 - 3 + 32 - 33 + . . . + 310. 20 7. Y= x2 / ( 2i-1). 8. Z = i 5 15 9. Y = x2/i. 10 1 2 ( x+i) / i. 10. Y = 1 + x/2 + x2/4 + x3/6 + ... + xi/2i + ... + x9 /18 . i 1 10 11. Y = 1 + x /1! + x /2! + x /3! + … + x /10! = 1+ x2i/i!. 2 4 6 20 i 1 39 12. Y = 1 - x + x3/3! - x5/5! + ... + (-1)n x2n-1/(2n-1)! + ... + x11/11!. 13. е = 1 + 1/1! + 1/2! + ... + 1/n! + ... (сравнить результат со значением функции EXP(1), определенной в Паскале). 14. π = 4(1 - 1/3 + 1/5 - 1/7 + … + (-1)n/(2n+1) + …) (результаты сравнить с определенным в языке Паскаль числом Pi). 15. Y = arctg x = x-x3/3 +x5/5- ... +(-1)n x2n+1/(2n+1)+ ... (|х|<1). 16. Z = LN(1+x) = x - x2/2 + x3/3 - ... + (-1)n-1 xn/n + ... (|x|<1). 17. S = x - x3/3! + x5/5! - ... +(-1)n x2n+1/(2n+1)! + ... . 18. Вычислить суммы положительных и отрицательных значений функции z = cos(nx+a) sin(nx-a), где n =1, 2, ... , 5, a и x вещественные числа. 19. Вычислить сумму четных и сумму нечетных чисел натурального ряда в диапазоне от 1 до N. 20. Найти сумму факториала M n i !. i 1 Задание 2 (программа_3_2) Вычислить значения двух функций в n точках, равномерно распределенных в диапазоне а ≤ x ≤ b. Результаты оформить в виде таблицы. № п/п 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 a 0 1 -1 -2 0 - -1 -4 1 1 0 - 0 1 2 2 0 1 3 1 b 2 2 5 5 3 4 3 4 2 2 4 4 5 3 n 20 18 15 14 16 20 20 12 15 20 20 18 16 12 10 16 18 20 15 18 F1(х) sin x cos x 1+2x+5 4e-|x|-1 | x+10|5 2 sin 2x +1 2-cos x 2x/10 x3e2x e x 1 1/(1+ x ) 5-3 cos x |sinx|+|cosx| e-x+cos2x e-x lg x 1 x cos x/2 x 2 lg x - 3x lg x 3-x/50 e2x 3 x - sin x 2x arctg x - 5 x 1 1,5arctg x 40 F2(х) sin x + cos x -1 (x-1)3 cos x e-(x+5) (x+5)3(1+sin2x) x4 4 20/(1+x2) ex sin x x ln2 x 2x/(1-4x) 1 sin 2 x |sin x| - |cos x| e -2x x + sin x 3 x + 2 e -x ctg x x e -x +ln x 10/(2+x2) e -ахx е2x lg x - 3ax 5.3. Оператор цикла с предусловием Оператор цикла с предусловием используется в случае, когда число повторений цикла заранее не известно. При этом цикл управляется условием, записанным в начале цикла, и поэтому действия в цикле при некотором условии могут ни разу не выполниться. Структура этого оператора имеет вид WHILE <условие> DO <оператор>; где <условие> – это любое логическое выражение для параметра цикла, истинность которого проверяется в начале каждой итерации (условие выполнения тела цикла), <оператором> может быть произвольный оператор языка, в том числе и составной. Правило выполнения оператора цикла с предусловием. Если <условие> истинно, то выполняется <оператор>, стоящий за ключевым словом DO, если <условие> ложно, то происходит выход из цикла и выполняется следующий оператор программы. После выполнения <оператора> вновь вычисляется и анализируется <условие>, и вновь, в случае его истинности, выполняется <оператор> в цикле. Эти действия повторяются до тех пор, пока <условие> не станет ложным. Поскольку параметр цикла используется для управления циклом, необходимо изменять этот параметр внутри составного оператора цикла. Пример. Вычислить Y = 1+1/2+1/3+...+1/N. Фpагмент пpогpаммы с применением оператора WHILE может быть составлен в следующем виде: Y:=0; I:=1; WHILE I<= N DO begin Y:=Y+1/I; I:=I+1 end; 5.4. Пример и задания для оператора цикла с предусловием Пример. Для трех значений а = 0.1, 0.2, 0.3 протабулировать функцию y = a.tg(x/4) при изменении аргумента x на интервале [0.5,0.9] с шагом, равным a. Для СА (рис. 9) решения данной задачи программа может быть следующей: 41 Начало Program a5; var a, x, y: real; а≤0,3;х=0 begin writeln('-------------------------'); writeln(' a | x | y |'); writeln('-------------------------'); a: = 0.1; while a<=0.31 do begin writeln(a:5:2); x :=0.5; while x<=0.91 do begin y :=a*sin(x/4) / cos(x/4); writeln(x:12:2,' | ', y:10:2); x :=x+a; end; writeln('-------------------------'); a:=a+0.1 end; end. а = 0,1 а ≤ 0,3; х = 0 х ≤ 0,9 y = atg( x/4) Вывод a, x, y х = х+а а = а+0,1 Конец Рис. 9 Задания для самостоятельного выполнения (программа_4_1) Начертите структурную схему алгоритма, напишите и отладьте программу для табуляции следующих функций: 1. S = ae-xsin ax+ ay a = 0.75, при -1 <= x <= 1 с шагом 0.2, 2. Z = 5 a x y 2 + 1,3 sin(x-a) a = 1.9, при 2 <= x <= 5 с шагом 0.5, 1 <= y <= 5 с шагом 1.5. -1 <= y <= 1 с шагом 0.5. t 1 e2 t ycos(t-a) a = -2.1, при 1<= t <= 2 с шагом 0.2, 2 <= y <= 3 с шагом 0.3. 4. Z = bx t b (tx+2.1) b = 3.5, при 1 <= x <= 2 с шагом 0.2, 0 <= t <= 1 с шагом 0.2. 3. S = 2 5. Z= x 2e x / 2 , ex 2 /a 1 если 0 <= x <= 2, если 2 < x <= 3.6, , 42 a = 0.5; 0.75, шаг dx = a/2. 6. Y= 2 2 sin ax - lg( a x ) , если 0.1 <= x <= 0.4, a cos2(px), 2 - sin ax, если 0.4 < x <= 1.2, если 1.2 < x <= 1.6, если 0 <= x <= 2, если 2 < x <= 3.6, ln(a+x2/ a ) , 7. Z = 2 e2x , a = 1.0; 1.5, шаг dx = a/5. a = 1.0; 1.3; 1.6, шаг dx = a/4. если 0.1 <= x < 0.5, если x = 0.5, если 0.5 < x <= 1.5, a = 2; 2.1, шаг dx = a/10. -a ex-3a, 9. Z = -a(1+ln(x-3a)), = если 0 < x <= 3, если 3 < x <= 4, a = 1; 1.5, шаг dx = a/2. - (x+3a)2 - 2a, 10. Y = a cos(x+3a) - 3a, a ex, если -1 <= x <= 0, если 0 < x < 1, если x = 1, a = 0.7; 1, dx = (a+0.2)/2. a(x-a)3/2, 11. Z = a/2(ex/a+e-x/a), если 1 <= x <= 2.5, если 2.5 < x <= 4, a = 0.5; 1.0, шаг dx = a/2. если 0.5 <= x < 1.5, если x = 1.5, если 1.5 < x <= 3, a = 0.1;0.2;0.3; шаг dx = 2a. (sin2x +a)2 ea sinX , 13. Z = tg(x/4), Я=Z = tg(a2 +sin px), 14.Y = a sin(p- cos px), lg x, если 0.1 <= x <= 0.5, если 0.5 < x <= 0.9, a = 0.1;0.2;0.3, шаг dx = a. ecos x -a sin2(px), 15. Z = a x2 - cos px, если 0.5 <= x <= 1.5 если 1.5 < x <= 2 a = 0.1;0.7;1.3, шаг dx= a/4. 1/x , 16. Y = ln(x2+ ax) , x2 , если 0.1 <= x <= 0.4 если 0.4 < x <= 1.2 если 1.2 < x < 1.6 a = 1.0; 1.5, шаг dx = a/5. 8. Z = a(ex+2a+e-(x-3a), sin x, a + a cos(x+3a), . 2 x a x 1 , 12. Y = a cos x, (a x2 + 1)x, если 0 <= x <= 1, если 1 < x <= 2, если 2 < x < 3, 43 a = 0.5; 0.75; 1; шаг dx = a/4. 17. Дана непустая последовательность различных натуральных чисел, за которой следует нуль (признак конца последовательности). Определить порядковый номер наименьшего из них и его значение. 18. Найти первый отрицательный член последовательности cos (ctg(n)), где n = 1, 2, 3, ..., x . Напечатать его номер и значение. Распечатать всю последовательность. 19. Вычислить наибольший общий делитель (k) натуральных чисел d и f. Оператор FOR не использовать. 20. Задан ряд неотрицательных вещественных чисел. Определить, сколько из них больше своих «соседей»: предыдущего и последующего чисел. Признаком окончания ряда чисел считать появление отрицательного числа. 5.5. Оператор цикла с постусловием Оператор цикла с постусловием производит проверку условия после выполнения операторов тела цикла. Поэтому тело цикла должно выполниться хотя бы один раз. Стpуктуpа оператора имеет следующий вид: REPEAT <оператор1>; ... <операторN> UNTIL <условие_выхода >; Правило выполнения оператора цикла. Выход из цикла происходит при истинности значения логического выражения <условие_выхода>, иначе операторы тела цикла повторяются. Изменение параметра цикла задается внутри тела цикла, а сам параметр цикла используется в <условии_выхода>. Здесь ключевые слова REPEAT и UNTIL выполняют также роль операторных скобок, поэтому точку с запятой перед словом UNTIL не ставят. Пример фрагмента программной реализации вычисления значения суммы Y = 1 + 1/2 + 1/3 + ... + 1/N с помощью оператора цикла с постусловием: BEGIN Y := 0; I :=1; REPEAT Y:=Y+1/I; I:=I+1 UNTIL I>N; END. 5.6. Процедуры прерываний циклов В циклах FOR, REPEAT и WHILE можно использовать процедуры прерываний BREAK и CONTINUE. Процедура BREAK осуществляет немедленный выход из цикла, не дожидаясь выполнения условия о выходе из него. Процедура CONTINUE позволяет начать новую итерацию цикла, даже если предыдущая еще не закончена. 44 Пример. Найти первое отрицательное число во входном потоке из вещественных чисел (не более 100). Program contine; Var i: Integer; a: Real; Begin For i:=1 to 100 do Begin read (a); If a >= 0 then сontinue; {пpи выполнении условия изменяется паpаметp цикла и цикл повторяется сначала} WriteLn ( ' Первое отрицательное число = ' , a); Break {выход из цикла} end end. 5.7. Примеры и задания для циклов с постусловием Пример 1. Вычислить 15 значений для двух функций: y1(x) = tg(x) и y2(x) = ctg(x) на интервале a ≤ x ≤ b, при a = 0.6*Pi, b = 0.7*Pi. Для вычислений функций разработана СА (рис. 10) и следующая программа: Program func; Const n = 14; a = 0.6*Pi; b = 0.7*Pi; Var x, y1, y2, dx: real; Begin dx:=abs((a-b)/n); x:=a; Repeat y1:=sin(x)/cos(x); y2:=1/y1; writeln('x=', x:6:4,' y1= ', y1:7:4,' y2=', y2:7:4); x:=x+dx Until x>b; End. Начало n = 14, a = 0.6π, b = 0.7π dx = | (a-b)\n |, x=a x y1 = tg x , y2 = ctg x Вывод x, y1, y2 x = x+dx, x>b Конец Рис. 10 45 Пример 2. Вычислить сумму s = 1+1/4+1/9+1/16 +... с точностью до E = 0.00001 (рис. 11). PROGRAM summa; CONST E = 0.00001; {точность} VAR s, r: REAL; { s – сумма, r – слагаемое} i: INTEGER; { i – счетчик слагаемых} BEGIN s:=0; i:=1; REPEAT r: = 1/sqr(i); {вычисление слагаемого} s := s + r; I := I + 1 {счет слагаемых} UNTIL r<E; {сравнение слагаемого с Е} WRITELN ( 'Сумма = ' , s:9:5); {вывод суммы} END. Начало E =10-5, s = 0, i = 1 i R = 1/i2 s = s+r, i = i+1 r≤E Конец Рис. 11 Задания для самостоятельного выполнения Задание 1 (программа_5_1) Модифицировать программу 3_2 для вычисления функций F1(x) и F2 (x) с применением оператора цикла с постусловием. Выполнить ее и сравнить результаты с полученными ранее. Задание 2 (программа_5_2) Начертить структурную схему алгоритма, написать и отладить программу для одной из следующих задач. 1. Вычислить приближенное значение z = arctg x и сравнить с x - x3/3 + x5/5 - ... + (-1)nx2n+1/(2n+1) + ... (|х|<1), прекращая вычисления, когда очередной член по абсолютной величине будет меньше eps = 0.00001. 2. Вычислить y = x - x2/2 + x3/3 - ... + (-1)n-1xn/n + ... с точностью eps = 0.00001, где |x|<1. Сравнить результат с вычисленным через стандартную функцию значением y = LN(1+x). 3. Вычислить y = 1 + x/1! + x2/2! + ... + xn/n! + ... с точностью eps = 0.00001 и сравнить результат с вычисленным через стандартную функцию значением y = ЕXP(x). 46 4. Вычислить y = sin x = x - x3/3! +x5/5! -...+ (-1)nx2n+1/(2n+1)!+... с точностью eps = 0.00001. 5. Вычислить y = 1 - x2/2! + x4/4! - ... + (-1)nx2n/(2n)! + ... с точностью eps = 0.0001 и сравнить результат с вычисленным через стандартную функцию значением y = cos (x). 6. Найти произведение цифр заданного натурального числа. 7. Определить число, получаемое выписыванием в обратном порядке цифр заданного натурального числа. 8. Определить номер первого из чисел sin x, sin(sin x), sin(sin(sin x)), ... , меньшего по модулю 10-3. 9. Дана непустая последовательность различных целых чисел, за которой следует нуль. Определить порядковый номер и величину наибольшего среди отрицательных чисел этой последовательности. 10. Вычислять периметры и площади прямоугольных треугольников по длинам катетов, пока один из заданных катетов не окажется нулевым. 11. Дана непустая последовательность положительных целых чисел, за которой следует отрицательное число (это признак конца последовательности). Вычислить среднее геометрическое этих чисел. 12. Дана непустая последовательность ненулевых целых чисел, за которой следует нуль. Определить, сколько раз в этой последовательности меняется знак. 13. Числа Фибоначчи (fn) определяются формулами f0 = f1 = 1; f n = f n-1 + f n-2 при n = 2,3,... . Вычислить сумму всех чисел Фибоначчи, которые не превосходят 1000. 14. Дана непустая последовательность положительных вещественных чисел х1, х2, х3,..., за которыми следует отрицательное число. Вычислить величину х1 + 2х2 + ... + (N-1)xN-1 + N хN, где N заранее не известно. 15. Вычислить длины окружностей, площади кругов и объемы шаров для ряда заданных радиусов. Признаком окончания счета является нулевое значение радиуса. 16. Определить, есть ли среди цифр заданного числа одинаковые цифры. 17. Определить, является ли заданное натуральное число палиндромом, т. е. таким, десятичная запись которого читается одинаково слева направо и справа налево. 18. Вычислить наименьшее общее кратное натуральных чисел a и b. 19. Дано число L. Определить первый отрицательный член последовательности х1, х2, х3,..., где х1 = L, xi = tg(xi-1). 20. Определить, является ли заданное натуральное число совершенным, т.е. равным сумме всех своих (положительных) делителей, кроме самого этого числа (например, совершенное число 6 = 1 + 2 + 3). 47 6. СТРУКТУРИРОВАННЫЕ ТИПЫ ДАННЫХ 6.1. Массивы данных Массивы – упорядоченная структура однотипных данных, хранящихся в памяти последовательно. Массив обязательно имеет размеры. Описывается в разделе TYPE или VAR следующим образом: Type <имя_типа> = array [диапазон_индексов] of <базовый_тип>; или Var <имя_переменной> : array [ диапазон_индексов] of <базовый_тип>; Отметим, что в разделе Type разделителем служит символ “=”, а в разделе переменных var – двоеточие “ : ” . Пpимер: TYPE array10 = array [1..10] of integer; array11 = array [11..22] of real; VAR V: array[-3..2] of char; {массив из 6 элементов}. В качестве индексов можно использовать любые перечислимые типы как встроенные, так и вводимые программистом. Индексы могут задаваться также диапазоном. Если диапазон соответствует всему типу, можно просто указывать имя этого типа. Например: TYPE DIAP = 1..100; VECTOR = array [DIAP] of real; При записи сложных массивов индексы разных диапазонов могут принадлежать разным типам. Например: VAR V: array [0..10 , 'A'..'C' ] of real; В качестве значений диапазона могут использоваться идентификаторы, если их значения определены выше. Например: CONST K=10; L=5; VAR A: ARRAY [1..K] OF INTEGER; B,С: ARRAY[1..K,1..L] OF REAL; Массивы хранятся в памяти как сплошные последовательности компонентов, причем быстрее изменяется дальний правый индекс. 48 Обращение к элементу массива в программе производится указанием имени массива и индексов, заключенных в квадратные скобки: <имя> [ <индексы> ]. Пример: A[1] := 1; B[8,5] := В[8,1] + B[8,2]; V[1,'B'] := 3.5; . В данном типе определена единственная операция присваивания. Можно присваивать целиком весь массив лишь массиву того же типа и размерности, например: B := С. Операции сравнения в массивах производятся только поэлементно. Обнуление одновременно всех элементов массива выполняется в цикле FOR I :=1 TO K DO A[I] := 0. Разрешается объявлять массивы, где базовыми элементами служат также массивы, например: TYPE VECTOR = array[1..5] of real; MATRIX = array[1..10] of VECTOR; что эквивалентно следующему способу описания: MATRIX = array[1..10] of array[1..5] of real; или MATRIX=array[1..10, 1..5] of real; Типизированные константы-массивы В качестве типизированных констант можно использовать массивы. В константах-массивах список констант разделяется запятыми и заключается в круглые скобки: CONST vector : array[0 .. 4] of byte = ( 0, 1, 2, 3, 4 ); массив символов может быть описан следующей записью: CONST vec : array[-1..2] of char = ( 'a' , 'b' , 'c' , 'd' ); При объявлении многомерных констант-массивов список констант, соответствующих каждому измерению, заключается в дополнительные круглые скобки и отделяется от соседних списков запятыми. Самый внутренний список констант связывается с изменением самого правого индекса массива. Например: CONST matr: array[1..2, 1..4] of byte = ((0,1,2,3),(4,5,6,7)); cub: array[0..1, 1..2,1..3] of byte = (((0,1,2),(3,4,5)), ((6,7,8),(9,10,11))); 49 6.2. Пример и задания для одномерных массивов Пример. Найти значение и номер наименьшего элемента в одномерном массиве. При задании элементов исходного массива типизированной константой СА решения задачи имеет вид (рис. 12, а) и используется следующая программа: Program lr6_1; const a: array[1..10] of integer = (5,2,7,1,8,3,4,5,6,6); var i, min, n: integer; begin min:=a[1]; n:=1; for i:=2 to 10 do if a[i]<min then begin min:=a[i]; n:=i end; writeln('минимальный элемент равен ',min, ' n=',n); end. Начало Начало Задание массива А Ввод а1 min = a1 , n=1 min = a1 , n=1 i = 2,10 i = 2,10 Нет ai < min Да Ввод аi Вывод min, n min > ai Конец Нет min = ai , n=i Да min = ai , n=i Вывод min, n Конец а) б) Рис. 12 50 Если элементы массива вводятся с клавиатуры, то СА имеет вид (рис. 12, б) и текст программы изменится: program lr6_2; var a: array[1..10] of integer; i, min, n: integer; begin read(a[1]); min:=a[1]; n:=1; for i:=2 to 10 do begin read(a[i]); if a[i]<min then begin min:=a[i]; n:=i; end; end; writeln('минимальный элемент равен ', min, ' n=',n); end. Задания для самостоятельного выполнения Задание 1 Начертить структурную схему алгоритма, написать и отладить программу для одной из следующих задач. В одной программе исходные массивы задать типизированными константами. В другой программе элементы исходных массивов ввести через оператор ввода. 1. Дан массив из N чисел (N > 8). Вычислить их среднее геометрическое значение. 2. Дан массив из N чисел (N > 10). Найти максимальное значение. 3. Дано 20 чисел. Найти их среднее арифметическое значение. 4. Дано 12 вещественных чисел. Найти порядковый номер того из них, которое наиболее близко к какому-нибудь заданному целому числу Х. 5. Дана последовательность из 15 целых чисел. Определить количество отрицательных чисел в ней и максимальное число подряд следующих отрицательных чисел. 6. Дано 15 целых чисел. Найти наибольшее из них. Определить, сколько из чисел принимает наибольшее значение. 7. Дано целое n > 1 и вещественные числа x1, x2, .., xn. Вычислить математическое ожидание и дисперсию по формулам: n M = xi n / n, D= i 1 51 i 1 ( xi M ) 2 /( N 1) . 8. Дан массив из N чисел (N > 10). Вычислить сумму элементов с нечетными индексами и их среднее арифметическое значение. 9. Даны два одномерных массива А и В. Вычислить элементы массива С по правилу: если аi и bi различны, то сi присвоить их сумму, при одинаковых аi, bi в сi переписать соответствующий элемент массива А. 10. Дано 10 вещественных чисел. Вычислить разность между максимальным и минимальным из них. 11. Дано 10 вещественных чисел. Определить, образуют ли они возрастающую последовательность. 12. Дан массив X из n чисел (n >10). Вычислить: y = x1 - x2 + x3 - ...- xn-1 +xn . 13. Дано 18 чисел. Определить количество элементов, отличное от последнего числа. 14. Дано 12 чисел. Напечатать сначала все отрицательные из них, а затем все остальные. 15. Сформировать одномерный массив из 15 простых чисел. 16. Дано восемь натуральных чисел. Найти их наибольший общий делитель. 17. Дана последовательность натуральных чисел. Вычислить сумму тех из них, порядковые номера (индексы) которых – простые числа. 18. Дан массив из 20 натуральных чисел. Вычислить сумму тех из них, порядковые номера которых - числа Фибоначчи, определяемые формулами f0 = f1 = 1; fn = fn-1 + fn-2 при n = 1, 2, 3, ... . 19. Дан массив X из n чисел. Вычислить: y = xn(xn+xn-1)(xn + xn-1 + xn-2)...(xn + ... + x1) . 20. Дано 24 целых числа. Распечатать их в обратном порядке по шесть чисел в строке. Задание 2 Модифицировать программу_3_2 для функций F1(x) и F2 (x) таким образом, чтобы результаты были сформированы в виде трех одномерных массивов. Выполнить ее и сравнить результаты с полученными в программах_5_1_и_3_2. 6.3. Ограниченный тип (диапазон) Через диапазон можно определить тип, который будет содержать значения только из ограниченного поддиапазона некоторого базового типа. Базовым ти52 пом может быть любой целочисленный тип, тип CHAR или любой из введенных программистом перечислимых типов. Определяется тип-диапазон в разделе TYPE указанием имени типа и границ диапазона, разделенных двумя точками: TYPE <ИмяДиапазона> = < НачальноеЗначение> . . <КонечноеЗначение>; Начальное значение при определении такого типа не должно быть больше конечного. Пример: TYPE TEST1 = (test1, test2, . . . ,test5 ); H= 1.. 20; {поддиапазон для типа Integer} LETERS = 'A' .. 'Я'; {базовый тип Char} TESTOD = test2 .. test5; {базовый тип TEST1} Определение переменных для диапазона производится в разделе VAR. Они могут принимать любые значения из указанного диапазона, включая граничные. При конструировании диапазона в описании типа можно использовать несложные арифметические выражения для вычисления границ. Но при этом надо следить, чтобы запись выражения не начиналась со скобки (скобка это признак начала перечисления). Пример: CONST N = 30; TYPE date = 1..31; kv2 = 3*N+1..6*N; VAR L, L1: date; k: kv2; BEGIN L:=2*10+5; ... L1:=2*10+60; {неверно, т.к. L1 выходит за пределы диапазона} END. Применение ограниченных типов усиливает контроль данных при выполнении программы. Значения переменных типа «диапазон» могут выводиться на экран и вводиться с клавиатуры только в том случае, когда диапазон взят из базового стандартного типа. 6.4. Пример и задания для двумерных массивов Пример. Вычислить суммы элементов в столбцах двумерного числового массива А размером [1..3,1..4]. 53 Начало Текст программы для СА (рис. 13): Program lr7_1; CONST a: array[1..3,1..4] of integer = ((1,2,3,4),(1,2,3,4),(1,2,3,4)); VAR i, j: integer; s: array[1..4] of integer; {массив сумм} BEGIN for j := 1 to 4 do begin s[j] := 0; for I := 1 to 3 do s[j] := s[j] + a[i,j]; write(' s[' , j, ']=' , s[j]) end END. Задание А(3х4) j=1, 4 sj =0 i=1,3 sj=sj +aij Вывод sj Конец Рис.13 Задания для самостоятельного выполнения Задание 1 1. Даны матрицы A,B: array [1..4,1..4] of real. Вычислить матрицу С поэлементным сложением соответствующих элементов матриц А и В. 2. Дана матрица B: array [1..5,1..5] of real. Найти для нее транспонированную. 3. Даны матрица A: array[1..4,1..4], содержащая вещественные числа, и константа k. Вычислить матрицу С = k*А . 4. Сформировать массив по правилу 1 0 0 ... 0 2 1 0 ... 0 3 2 1 ... 0 ... 10 9 8 ... 1 5. Даны натуральное N и элементы аij квадратной вещественной матрицы А пятого порядка. Вычислить N-ю степень каждого элемента этой матрицы по схеме (аij1 = аij, аij2 = аij*аij, аij3 = аij2*аij и т.д., где i, j = 1, 2, ..., 5). 6. Сформировать массив по правилу 54 0 0 0 ...0 0 1 0 ...0 0 0 2 ...0 … 0 0 0 ...9 . 7. Сформировать массив последовательностью натуральных чисел: 1 2 ... 10 11 12 ... 20 21 22 ... 30 . ... 91 92 ... 100 8. Сформировать двумерный массив: 12345 51234 45123 . 34512 23451 9. Дана матрица A: array [1..N,1..N] of integer. Сформировать вектор В из максимальных элементов каждой строки. 10. Дана матрица A: array [1..6,1..6] of integer и переменная x. Элементы нечетных строк матрицы А заменить на значение x. 11. Дана матрица B: array [1..5,1..5]. Получить массив С удалением (либо обнулением) n-й строки и k-го столбца из матрицы В. 12. Определить, является ли заданная квадратная матрица девятого порядка магическим квадратом, т.е. такой, в которой суммы элементов во всех строках и столбцах будут одинаковы. 13. Определить, является ли заданная целая квадратная матрица шестого порядка симметричной (относительно главной диагонали). 14. Дана вещественная матрица A: array [1..7,1..4]. Переставляя ее строки и столбцы, добиться того, чтобы наибольший элемент оказался в верхнем левом углу. 15. Дана вещественная матрица размером 4х8. Упорядочить ее строки по неубыванию сумм их элементов. 16. Для заданной целой матрицы размером 6х8 элементов напечатать индексы всех ее седловых точек. Элемент матрицы называется седловой точкой, если он является наименьшим в своей строке и одновременно наибольшим в своем столбце или, наоборот, является наибольшим в своей строке и наименьшим в своем столбце. 17. Дана матрица A: array [1..6,1..2] вещественных чисел. Рассматривая A [i,1] и A [i,2] как координаты точек на плоскости, определить радиус наименьшего круга (с центром в начале координат), внутрь которого попадают все эти точки. 18. Дан массив F: array [1..N,1..M] of byte. Определить количество «особых» элементов в нем. Элемент считается «особым», если он больше суммы остальных элементов своего столбца. 55 19. Дана матрица D: array [1..5,1..6] of integer. Упорядочить элементы строк в нем по убыванию. 20. Дан массив М координат точек на плоскости. Найти наибольшее расстояние между этими точками. Задание 2 Сформировать таблицу Пифагора для чисел натурального ряда. Задание 3 Модифицировать программу_3_2 (или 6_3) таким образом, чтобы значения X, F1 и F2 были представлены двумерным массивом, состоящим из трех строк. 7. СТРУКТУРНОЕ ПРОГРАММИРОВАНИЕ 7.1. Структура сложной программы Любая программная единица включает следующие разделы: <Объявление программной единицы> {Раздел описаний} BEGIN {Раздел исполняемых операторов} END. {символ конца программной единицы} <Объявление программной единицы> заголовок программы, процедуры или функции. Заголовок программы можно опускать, для процедур и функций наличие заголовка обязательно. <Cимвол конца программной единицы> это символ точки для программы или символ ";" для процедуры или функции. В разделе описаний объявляются идентификаторы типов, объектов, констант, переменных, а также метки, процедуры и функции. Каждый блок определяется своим ключевым словом. Тогда структура программы будет иметь вид PROGRAM <имя программы>; USES <список библиотечных модулей>; LABEL <список меток в основном блоке>; CONST < определение констант>; TYPE <определение типов>; VAR <определение глобальных переменных>; <определение процедур> <определение функций>; BEGIN 56 <основной блок программы> END. Директива USES выполняет подключение стандартных или написанных программистом модулей. Она должна обязательно стоять первой, если присутствует в программе. Например, строкой USES CRT; производится подключение модуля CRT. Модуль CRT содержит процедуры и функции для управления выводом текста на дисплей, звуковым генератором и чтением с клавиатуры. Блоки TYPE, CONST, VAR, LABEL в Паскале АВС могут следовать друг за другом в любом порядке и встречаться в разделе описаний сколько угодно раз. В блоке LABEL перечисляются через запятую метки, используемые в программной единице. Метка может содержать числовое значение либо являться идентификатором. Например: LABEL 1, 400, M1, EPS; Если метка описана в этом блоке, но в программе не встретилась, то выдается сообщение об ошибке. Метки не должны повторяться. Блок меток может находиться в любом месте, их может быть несколько, но все метки должны быть определены до начала основной программы. При отсутствии меток блок исключается. Блок CONST описывает константы двух видов: CONST <имя1> = <константа1>; <имя2> = <константа2>; ... или CONST <имяК>: <тип> = <константаK>; <имяR>: <тип> = <константаR>; ... Например: CONST NI = 100; f = -NI; d: real = 7.65432; Блок TYPE содержит определения вводимых программистом нестандартных типов в следующих формах: TYPE <идентификатор> = (<список_компонентов>); или TYPE <идентификатор> = <описание_типа>; Пример: TYPE FAMILY = (FATHER, MOTHER); 57 Когда в Паскале используются только стандартные типы (например: INTEGER, REAL), этот блок опускается. Блок VAR описывает имена переменных, а также имена массивов: VAR A1, A2, ..., An: <тип1>; B1, B2, ..., Bn: <типК>; ... <имя массива>: ARRAY[диапазон] OF <тип>; где буквами Ai, Bj указаны имена переменных, а <тип1>, <типК> – типы соответствующих переменных, [диапазон] указывает начальное и конечное значения индексов массива, <тип> задает тип элементов массива. Пример: VAR A, B, C: INTEGER; {объявлены три переменные целого типа} D, M: REAL; {объявлены две вещественные переменные} MASS1: ARRAY[1..10] OF REAL; {массив из 10 чисел} MASS2: ARRAY[-2..2] OF CHAR; {массив из пяти символов} В качестве значений диапазона могут использоваться идентификаторы любого порядкового типа, если их значения определены выше в разделе CONST. 7.2. Подпрограммы. Процедуры и функции Относительно самостоятельные фрагменты программы, оформленные определенным образом и снабженные заголовком, называются подпрограммами. С помощью подпрограмм любая программа может быть разбита на ряд формально независимых друг от друга частей. Подпрограммы делятся на два вида: процедуры и функции. Результатом исполнения операторов, образующих тело функции, всегда является единственное значение, поэтому ее имя может быть использовано в выражениях наряду с переменными и константами. Если в программе используются процедуры или функции, то их описание должно предшествовать основному блоку программы. Описание состоит из заголовка и тела процедуры (функции), которое обычно следует за заголовком. Заголовок процедуры с параметрами описывается строкой PROCEDURE <имя> (<список формальных параметров> ); Список формальных параметров записывается в скобках и содержит перечень параметров с указанием их типов. Перед выходными параметрами, которые возвращают результат в основную программу, указывается ключевое слово VAR, например: 58 PROCEDURE SUMMA(A1,A2:REAL; B1,B2:INTEGER; VAR S1,S2:REAL); Допускаются также процедуры без параметров: PROCEDURE <имя >; Они предполагают использование в подпрограмме только глобальных переменных, определенных в разделе описаний основной программы. За заголовком процедуры следует раздел описаний подпрограммы (меток, констант, типов, переменных, а также описаний вложенных процедур и функций) и блок операторов. Структура описания заголовка подпрограммы-функции имеет вид: FUNCTION <имя> (<список формальных параметров> ): <тип>; Формальные параметры записываются с указанием их типа, кроме того, указывается тип самой функции. За заголовком функции следует раздел описаний и блок выполняемых операторов. Пример FUNCTION STEP(x, y : REAL) : REAL; VAR a, b : real; BEGIN ... ... END; После описания блока процедуры или функции следует оператор END, за которым ставится точка с запятой. Отличие функции от процедуры состоит в том, что функция может возвращать одно значение в основную программу через свое имя, а процедура возвращает несколько значений через список параметров. Поэтому в разделе операторов функции должен быть оператор, который имени функции присваивает значение вида <имя функции> := <выражение>; например: STEP := <выражение вещественного типа>. Вызов подпрограмм производится указанием имени или имени со списком фактических параметров. Фактические параметры не указываются, если в подпрограмме используются только глобальные переменные и в заголовке программы отсутствует список формальных параметров. Если заголовок подпрограммы содержит формальные параметры, то при обращении к подпрограмме должен обязательно присутствовать список фактических параметров, которые записываются через запятую. Количество, тип и порядок перечисления фактических параметров должен обязательно соответствовать количеству, типу и порядку перечисления формальных параметров в описании подпрограммы. 59 7.3. Структура подпрограммы-функции Описание блока подпрограммы-функции в общем виде имеет следующую структуру: FUNCTION <имя> ( <формальные параметры> ) : <тип>; { раздел описаний: переменные, типы, метки} BEGIN { операторы функции } <имя> := <выражение> {имени функции присваивается значение} END; Функция передает в вызывающую программу единственное значение, которое хранится под ее именем. В качестве переменных могут использоваться параметры-переменные и параметры-значения. <Тип> функции должен соответствовать значению, которое вычисляется в данной подпрограмме (типу результата). В вызывающую подпрограмму передается значение функции данного типа. Вызов функции в программе производится не обособленно, как в процедуре, а в выражении указывается имя функции со списком параметров. 7.4. Примеры и задания с подпрограммой-функцией Пример 1. Вычислить вторую и N-ю степени числа Х. PROGRAM FUNC; VAR X: REAL; N: INTEGER; FUNCTION STEPEN(M: INTEGER; A: REAL): REAL; VAR P: REAL; I: INTEGER; BEGIN P := 1; FOR I :=1 TO M DO P := P*A; STEPEN := P; END; BEGIN READ(X,N); WRITELN(' X=', X, ' квадрат', STEPEN(2,X)); WRITELN(' X=', X, ' степень', STEPEN(N,X)); END. Пример 2. Даны три массива A (5), B (5), C (5). Найти среднее арифметическое значение наименьших элементов массивов. 60 До написания программы разрабатывается СА главной программы (рис. 14, а) и СА для подпрограммы нахождения наименьшего элемента в любом массиве (рис. 14, б). Отлаженная программа решения задачи имеет следующий вид: Program lr8; type mass = array[1..5] of integer; const a: mass = ( 5,2,7,1,8 ); {заданы массивы констант} b: mass = ( 3,4,5,6,6 ); c: mass = ( 3,8,5,2,6 ); var n: integer; sr: real; FUNCTION minim(d:mass) : integer; {заголовок функции} var i, min: integer; begin {начало блока операторов функции} min:=d[1]; for i:=2 to 5 do if d[i]<min then min:=d[i]; writeln('минимальный элемент равен ',min); minim := min {имени функции присваивается значение} end; {конец блока функции} BEGIN {блок основной программы} sr: = (minim(a) + minim(b) + minim(c)) /3; {три обращения к функции} writeln(' sr = ', sr:5:2); END. Начало minim (d) Задание массивов A,B,C sr = (minim(A)+ + minim(B) + + minim(C))/3 min = d1 i =2,5 Вывод min di < min minim = min Нет Вывод sr Да min = di Конец б) а) Рис. 14 61 Конец п/п Задания для самостоятельного выполнения Задание 1 Написать и отладить программы для задач из пп. 3.7 и 6.4 с применением подпрограммы-функции с параметрами. Вычисление функции (или обработку массива) выполнить в подпрограмме, а ввод исходных данных и вывод результатов в основной программе. Предусмотреть, по крайней мере, два обращения к функции с различными фактическими параметрами. Для отладки программ использовать средства системы Pascal ABC: пошаговое исполнение программы (трассировку) с контролем значений переменных в окне отладчика. Задание 2 1. По заданным вещественным массивам A [1..6], B [1..6] и C [1..6] вычислить (max B)/max A + (max C)/max(B+C) при min A < max B, max(B+C) + max C в противном случае. 2. Даны два двумерных массива целых чисел А [1…5], B [1…5]. Напечатать квадрат того из них, в котором наименьший след (сумма диагональных элементов), считая, что такой массив один. 3. Определить координаты центра тяжести трех материальных точек с массами m1, m2, m3 и координатами (x1,y1), (x2,y2), (x3,y3) по формулам xc = (m1x1+m2x2+m3x3)/(m1+m2+m3), yc = (m1y1+m2y2+m3y3)/(m1+m2+m3). Вычисление координаты оформить функцией с параметрами. 4. Вычислить все медианы для каждого из трех треугольников по заданным в массивах A, B, C сторонам: ma = 0.5 2b 2 2c 2 a 2 , mb = 0.5 2a 2 2c 2 b 2 , mc = 0.5 2a 2 2b 2 c 2 . Вычисление медианы оформить функцией. 5. Даны три одномерных массива вещественных чисел A [1..6], B [1..8] и С [1..7]. Найти общую сумму положительных элементов в массивах. Нахождение суммы элементов в массиве оформить функцией. 6. Даны два двумерных массива целых чисел с размерами (4х5) элементов. Подсчитать количество отрицательных элементов в каждом из них. 7. Даны два одномерных массива целых чисел A [1..8] и B [1..8]. Найти сумму их максимальных элементов. Для нахождения максимального элемента в массиве использовать функцию. 8. Даны два двумерных массива целых чисел по (5х5) элементов каждый. Подсчитать произведение элементов главных диагоналей в каждом из них. 62 9. Даны три одномерных массива вещественных чисел A [1..6], B [1..8] и С [1..7]. Найти среднее геометрическое значение положительных элементов для каждого. 10. Даны две матрицы целых чисел M [1..3,0..1], К [1..3,0..2]. Найти среднее арифметическое значение для каждой из них. 11. Даны три одномерных массива целых чисел A [1..6], B [1..8] и С [1..7]. Подсчитать количество неотрицательных элементов в каждом. 12. Даны две матрицы целых чисел S [1..3,0..2], К [1..3,0..2], в каждой из которых имеется по два одинаковых числа. Распечатать их значения. 13. Даны два одномерных массива целых чисел A [1..6] и B [1..8]. Вычислить значение Z = (min A[i] + min B[j]) / min (A[i]+B[j]). i j i, j 14. По заданным целым массивам X[0..7] и Y[8..15] вычислить 7 Z 7 xi при i 0 2 i 0 xi yi+8 > 0, 15 i 8 yi2 в противном случае. 15. Дана матрица целых чисел D [1..6,1..5]. Найти наименьшую из сумм неотрицательных элементов строк матрицы. Для вычисления суммы использовать подпрограмму (функцию). 16. Дана матрица целых чисел E [1..3,1..5]. Используя функцию, найти среднее геометрическое значение для каждого столбца матрицы. 17. Дана матрица целых чисел F [1..4,1..5]. Найти наименьшие значения элементов в каждой из строк матрицы с помощью функции. 18. Даны две квадратные вещественные матрицы шестого порядка. Напечатать квадрат той из них, в которой наименьший след (сумма диагональных элементов), считая, что такая матрица одна. 19. Сформировать двумерный массив: 1 2 3 4 5 1 4 9 16 25 1 8 27 64 125 ... … Найти правило и оформить функцией вычисление любой строки. 20. Даны две матрицы целых чисел V [1..2,1..3], W [1..3,1..2]. Найти суммы элементов строк и столбцов в этих матрицах. 63 7.5. Структура подпрограммы-процедуры Структура подпрограммы-процедуры с параметрами имеет вид PROCEDURE <имя> (<формальные параметры>); { раздел описания (метки, константы, типы, переменные ) } BEGIN { операторы подпрограммы } END; Обращение к процедуре производится по имени с указанием фактических параметров, согласованных с формальными параметрами, или без их указания. Возврат из подпрограммы в основную программу происходит к оператору, стоящему следующим за ее вызовом. Пример программы для вычисления второй и четвертой степеней числа: PROGRAM PROS; VAR X, Y, A, A2, A4: INTEGER; {A – исходная переменная, A2 - A2, A4 - A4 , глобальные переменные} PROCEDURE STEP24; {процедура без параметров} BEGIN A2:=A*A; A4:=A2*A2; WRITELN(A:5, A2:5, A4:6); END; BEGIN {основная программа} READ(Y, X); WRITELN('Число; квадрат; куб'); A := X; STEP24; {вызов подпрограммы} A := Y; STEP24; {вызов подпрограммы} END. Любой из формальных параметров процедуры может быть либо параметром-значением, либо параметром-переменной. Формальному параметру-значению (обычно для задания исходных данных) может соответствовать фактический параметр константа, переменная или выражение. Параметру переменной может соответствовать только переменная. Обычно параметры-переменные используются для передачи результатов в вызывающую программу. Параметрам-переменным в заголовке функции должно предшествовать слово VAR. 64 Пример: PROCEDURE P(Y, X: REAL; VAR Z1, Z2: REAL); где Y, X параметры-значения, Z1, Z2 параметры-переменные. Передачу результатов можно проводить и через глобальные переменные. Однако злоупотребление глобальными переменными делает программу запутанной и сложной в отладке. В связи с этим рекомендуется там, где это возможно передавать результаты с помощью параметров-переменных. С другой стороны, нежелательно описание всех формальных параметров параметрами-переменными. Чем меньше параметров объявлено параметрами-переменными и чем меньше используется глобальных переменных, тем меньше возможность получения непредвиденных программистом побочных эффектов в программе. При наличии одноименных переменных в программе и подпрограмме в подпрограмме будут доступны только локальные переменные. 7.6. Передача в подпрограмму массивов и строк Передача одиночных элементов массивов при вызове подпрограммы не отличается от передачи в неё простых переменных. При передаче всего массива рекомендуется предварительно определить его тип, поскольку он не является стандартным. Например: TYPE ATYPE = ARRAY[1..10] OF REAL; PROCEDURE R(A: ATYPE); Такое описание возможно в связи с тем, что в списке формальных параметров могут использоваться не только стандартные, но и ранее описанные типы. Однако объявить процедуру можно и следующим образом: PROCEDURE R(A: ARRAY[1..10] OF REAL); Передача в подпрограмму строки осуществляется аналогичным образом, поскольку строка является фактически массивом из её символов. Пример описания и передачи строковых переменных: TYPE INTYPE = STRING[10]; ONTYPE = STRING[30]; FUNCTION R(A: INTYPE): ONTYPE; 7.7. Рекурсия в программе Рекурсия это способ организации вычислительного процесса, при котором подпрограмма в ходе выполнения своих операторов обращается сама к себе. Пример. Пусть задано целое положительное число, выведите на экран дисплея цифры числа в обратном порядке. 65 PROGRAM REKURS; VAR N: INTEGER; PROCEDURE REVERS(M: INTEGER); BEGIN WRITE(M MOD 10); IF (M DIV 10)<>0 THEN REVERS(M DIV 10); END; BEGIN READ(N); REVERS(N); END. В ходе выполнения программы процедура рекурсивно обращается сама к себе и выводит на экран при каждом обращении очередную цифру. Рекурсия может быть прямой или косвенной. В первом случае модуль подпрограммы содержит оператор вызова этой же подпрограммы. Во втором случае один модуль (например, А) вызывается из другого модуля (например, В), а модуль В – из А. Поскольку по правилам языка каждый идентификатор перед объявлением должен быть описан, то необходимо выполнить опережающее описание подпрограммы В. Для этого объявляется заголовок процедуры В, за которым следует служебные слово FORWARD. Теперь из процедуры А можно обращаться к процедуре В. Например: PROCEDURE B(I:BYTE); FORWARD; PROCEDURE A(J:BYTE); BEGIN ... B(J); END; PROCEDURE B(I:BYTE); BEGIN ... A(I); END; 7.8. Вложенные подпрограммы В разделе описаний любой подпрограммы могут встречаться описания других подпрограмм, тогда говорят, что одна подпрограмма вложена в другую. Любые идентификаторы для описания переменных, констант, типов, а также процедур и функций, описанные внутри подпрограммы, локализуются только в ней и называются локальными для данного блока (подпрограммы). Такой блок подпрограммы вместе с выделенными в нем модулями называется 66 областью действия этих локальных имен. Локальные имена не являются формальными параметрами. Переменные, описанные в разделе описания основной программы, называются глобальными. Область действия глобальных переменных основная программа и ее подпрограммы. Имена называются нелокальными, если они описаны не в самой подпрограмме, а в охватывающем ее блоке (или во внешней подпрограмме). Все имена в пределах подпрограммы должны быть уникальными и не могут совпадать с именем самой подпрограммы. При входе в подпрограмму низшего уровня становятся доступными не только объявленные в ней имена, но и сохраняется доступ ко всем именам внешних уровней. Рекомендуется описывать имена в том блоке, где они используются, если это возможно. Если один и тот же объект (переменная или константа) используется в двух и более блоках, то их описание необходимо сделать в самом верхнем блоке, который содержит все остальные. Если переменная, используемая в подпрограмме должна сохранять свое значение до следующего вызова этой подпрограммы, то она описывается во внешнем блоке, содержащем данную подпрограмму. 7.9. Процедуры EXIT и HALT Процедура EXIT; осуществляет выход из программного модуля подпрограммы или основной программы. Из подпрограммы управление передается этой процедурой в вызывающую программу к следующему за ее вызовом оператору. В программе EXIT приводит к завершению ее работы. Процедура HALT(Cod); прекращает выполнение программы, вызывает в случае необходимости подпрограмму завершения и осуществляет выход в операционную систему. Cod необязательный параметр, определяющий код завершения программы. 7.10. Пример и задания с подпрограммой-процедурой Пример. Ввести два массива A [1..3], B [1..4] с помощью процедуры "ввод". Вычислить средние арифметическое и геометрическое значения элементов каждого из них, используя подпрограмму-процедуру. Для решения задачи pазpаботана СА (pис. 15), состоящая из основной программы (а) и двух процедур: одной для ввода элементов массива (б), другой – для определения средних арифметического и геометрического значений в массиве (в), а также написана пpогpамма для реализации алгоритма: Program lr7; type mass = array[1..5] of integer; 67 var ka, kb: byte; Sr, Sg: real; a, b: mass; PROCEDURE VVOD ( Var d: mass; Var k: byte ); {заголовок процедуры ввода} Var i: integer; Begin {тело процедуры} writeln(' введите число элементов'); read(k); writeln(' введите массив из ', k,' элементов'); FOR i:=1 to k do read(d[i]); end; {конец процедуры VVOD} Начало VVOD (А,ka) ka) SARR (ka,a,Sr,Sg)) SARR (k,f,s,p) VVOD(d, k) Ввод i = 1,k k Вывод Sr, Sg Конец VVOD (b, kb) SARR (kb,b,Sr,Sg) s = 0, p = 1 i = 1,k i=1,k s = s + fi Ввод di р = р · fi s = s/k; p = Конец п\п Конец п\п Вывод Sr,Sg Конец а) б) Рис. 15 68 k в) p PROCEDURE SARR (k:byte; f:mass; var s,p:real); {заголовок процедуры} var i: byte; begin s:=0 ; p:=1; for i:=1 to k do begin s := s+f [i]; p:=p*f[i] end ; s := s/k ; p := EXP(Ln(p)/k) End; {конец тела процедуры SARR} BEGIN {Блок основной программы} VVOD(a,ka); { ввод элементов массива А и его размера} SARR(ka,a,Sr,Sg); {вызов процедуры для обработки массива А} writeln( ‘ SrA= ’ , Sr:5:2 , ‘ SgA= ’ , Sg :5:2); VVOD(b,kb); SARR(kb,b,Sr,Sg); {вызов процедуры для обработки массива B} writeln( ‘ SrB= ’ , Sr :5:2, ‘ SgB= ’ , Sg :5:2); END. Задания для самостоятельного выполнения Задание 1 Написать и отладить программу для п. 6.4 с выделением алгоритма обработки или формирования массива. Организовать вызов процедуры с параметрами-массивами для двух наборов исходных данных. (Для ускорения отладки массив можно задать типизированной константой). Задание 2 1. Даны массивы A [1..6], B [1..6], C [1..6]. Получить A*B, B*С, A*C. Вычисление произведения массивов оформить процедурой. 2. Даны массивы A [1..5], B [1..6]. Получить новые массивы путем сдвига элементов в массиве А на один разряд, а в массиве В на два разряда вправо, освободившиеся слева элементы обнулить. Сдвиг элементов в массиве оформить подпрограммой. 3. Даны два одномерных массива А [1..6] и C [1..6]. Получить A2, С2, А*С. Перемножение массивов выполнить в подпрограмме. 4. Даны две матрицы целых чисел S [1..3,0..2], K [1..3,0..2], в которых имеется по два одинаковых числа. Найти и распечатать их значение и индексы. 69 5. Вычислить значение функции Z = x1+ex2, где x1, x2 – корни уравнения Aix2+Bix + Ci = 0, i = 1,2,..,N. Коэффициенты уравнения заданы в массивах A [1..N], B [1..N], C [1..N]. Для вычисления корней использовать процедуру. 6. Составить процедуру для перемножения двух квадратных матриц, с помощью которой вычислить вторую, третью и четвертую степени матрицы M [1..5,1..5]. 7. Даны массивы A [1..6], B [1..6], C [1..6]. Преобразовать их, каждому элементу массива присваивая значение соседнего с ним справа. Последнему элементу присвоить значение первого. 8. По заданным вещественным массивам A [1..6], B [1..6] и С [1..6] вычислить (minAi)/maxAi + (maxCi)/min(Ci) + max(B+C)i /min(B+C)i. 9. Даны массивы A [1..6], B [1..8]. Выбрать из них положительные элементы и записать соответственно в массивы A1 [1..k] и B1 [1..n], где k < 6, n < 8; из отрицательных элементов сформировать массивы A2 [1..6-k], B2 [1..8-n]. 10. Даны массивы A [1..6], B [1..6], C [1..6]. Переставить элементы в них таким образом, чтобы слева подряд были записаны отрицательные, а справа положительные элементы. 11. Даны две целые квадратные матрицы четного порядка. Элементы массивов с четными номерами строки и столбца заменить нулем (стереть). Напечатать полученные массивы. 12. Даны одномерные массивы A [1..6], B [1..8], C [1..10]. Записать их в виде матриц AA [1..3,1..2], BB [1..2,2..4], CC [1..5,1..2]. 13. Даны две целые квадратные матрицы шестого порядка. Распечатать элементы главных диагоналей каждой из них и определить симметричность каждой матрицы относительно главной диагонали. 14. По заданным 10 элементам вещественных массивов A, B и С вычислить max (bi )/max(a i ) max(ci )/min (b c)i , z max(b c)i min(ci ) , при min Ai min Bi при min Ai min Bi 15. Даны две матрицы целых чисел V (-1..2,0..3) W [1..3,0..2]. Сформировать из них одномерные массивы VV и WW, записывая элементы построчно. 16. Дана матрица чисел H [1..5,1..6]. Переставить столбцы матрицы таким образом, чтобы элементы первой строки матрицы были расположены в порядке возрастания их модулей. Перестановку двух столбцов матрицы реализовать процедурой. 17. Дана матрица чисел G [1..4,1..6]. Переставить элементы в матрице так, чтобы элементы каждого столбца матрицы были расположены в порядке возрастания их модулей. Перестановку элементов в столбце реализовать процедурой. 70 18. Даны массивы A [1..6], B [1..6], C [1..6]. Упорядочить элементы в них в порядке убывания их модулей. 19. Даны две матрицы целых чисел V [1..2,1..3], W [1..3,1..2]. Найти общие суммы элементов строк и столбцов, результаты сформировать в виде двух массивов. 20. Даны две целые квадратные матрицы шестого порядка. Определить, можно ли отражением относительно главной и побочной диагоналей преобразовать одну в другую. 8. ОБРАБОТКА СИМВОЛЬНЫХ ДАННЫХ 8.1. Символьный тип Символьный тип это тип данных, состоящих из одного символа (знака, буквы, цифры). Традиционная запись символьного значения представляет собой символ, заключенный в апострофы ('ж'). В Pascal ABC имеются альтернативные способы представления символов [1]. Значениями символьного типа является множество всех символов компьютера. Каждому символу приписывается целое число в диапазоне 0..255, которое служит кодом его внутреннего представления. Связь между символом и кодом устанавливается функцией ORD: <Код > = ORD ( <символ> ) . Переменные символьного типа объявляются в блоке VAR ключевым словом CHAR. Пример. VAR C1, C2, C3: CHAR; BEGIN C1 := 'A' ; C2 := 'B' ; C3 := chr(43); … END. Для кодирования символов используется код ASCII (AMERICAN STANDART CODE FOR INFORMATION INTERCHANGE Американский стандартный код для обмена информацией). Код ASCII имеет 7 бит, которые позволяют кодировать в стандарте основные 128 символов, включающие латинские пpописные и стpочные буквы, цифpы, pазделители и pяд служебных символов (с кодами 0..31). Служебные символы в тексте считаются пробельными и в операциях ввода-вывода имеют самостоятельное значение (табл. 7). 71 В Pascal ABC применяется восьмибитовый код, содержащий 256 символов. Кодировка символов с номерами [128..255] зависит от типа ПК и включает буквы русского алфавита, а также графические символы [3–5]. К символам типа char применимы операции присваивания и все операции логических отношений: <, >, <=, >=, =, <>. Примеры 'A' = 'A' (TRUE); 'A' <> 'a' (TRUE); 'A' < 'a' (TRUE); Таблица 7 Служебные символы Символ Код BEL HT LT VT FF CR SUB ESC 7 9 10 11 12 13 26 27 Назначение Звонок Табуляция горизонтальная Перевод строки с сохранением текущей позиции Табуляция вертикальная Прогон страницы Возврат каретки Конец файла Конец работы Символьный тип имеет следующие встроенные функции: ORD(С ) возвращает код типа byte для символа С:char; CHR( b) возвращает символ по коду аргумента b:byte; UPCASE(c) переводит в верхний регистр только букву латинского алфавита, оставляя любой другой символ без изменения, и возвращает символ c:char; PRED(C) возвращает символ, предшествующий С:char в таблице кодов; SUCC(C) возвращает символ, следующий за С:char в таблице кодов. Пример. Напечатать прописными только латинские буквы из двух заданных. Зададим буквы константами и применим функцию UpCase: Var c1, c2:char; Begin c1:= UPCASE( 'f' ); c2:= UPCASE( 'ф' ); writeln(c1, ' ' , c2, #7 ) {строка вывода: F ф } 72 End. {Вывод сопровождается звуковым сигналом} Символы также можно описывать указанием в функции CHR кода символа или с признаком # перед кодом. Например, считаются эквивалентными следующие записи: 'A' CHR(65) #65. 8.2. Задания для символьных данных 1. Дана строка из 20 символов. Вывести из нее на печать только строчные буквы латинского алфавита. 2. Вывести на печать все строчные, а затем все прописные буквы русского и латинского алфавитов. 3. В заданной строке подсчитать частоту появления букв «a», «b». 4. Дан текст из 60 литер. Напечатать только строчные русские буквы, входящие в этот текст. 5. Дана последовательность символов, содержащая символ «я». Определить порядковый номер символа «я» в последовательности. 6. Дана последовательность символов. Определить в ней символ, который по алфавиту предшествует другим. 7. Напечатать в алфавитном порядке все различные строчные буквы, входящие в заданный текст из 100 литер. 8. Определить, является ли заданная последовательность символов в строке симметричной: читается одинаково слева направо и справа налево. 9. Напечатать текст, образованный символами с порядковыми номерами 56, 89, 84 и 69, и текст с изменением регистра. 10. Даны две строки с1 и с2, содержащие до 5 цифр каждая. Преобразовать их к данным целого типа, используя процедуру VAL, вычислить арифметическое выражение с3 = (с1-с2)/(с1+с2). 11. Вычислить суммы кодов всех букв, входящих в слова SUM и ALFA. Сравнить слова и определить, какое из них больше. 12. Напечатать заданный текст с удалением из него всех букв b, непосредственно перед которыми находится буква с. 13. Имеется символьная переменная d, присвоить логической переменной T значение true, если значение d – цифра, и значение false в противном случае. 14. Если в заданный текст входит каждая из букв слова key, тогда напечатать «yes» , иначе – «no». 15. Написать программу, которая предварительно запрашивает ваше имя, а затем приветствует вас по имени. 73 16. Ввести вещественное число, преобразовать его в строку. Подсчитать количество разрядов в целой и дробной частях. Найти представление числа в виде мантиссы (по модулю меньшее единицы) и порядка. 17. Ввести строку, состоящую из нулей, единиц и десятичной точки. Преобразовать ее в десятичное число. 9. ОБРАБОТКА СТРОК ТЕКСТА 9.1. Строковый тип Строковый тип (String) используется для обработки текстовой информации. Строка-константа это произвольная последовательность символов, заключённая в апострофы. Отдельный символ совместим по типу с элементом типа CHAR. Для обработки текстовой информации используется тип динамических строк. Строка представляет собой цепочку символов. В программе строковая переменная может быть описана в блоках Type или Var. Например: CONST N=16; {N255} TYPE stroka: string[100]; VAR st: string; {строка может содержать не более 255 символов} str: string[10]; {строка может содержать не более 10 символов} st1: string[N]; {строка может содержать не более N =16 символов} st2: stroka; {строка может содержать не более 100 символов} Максимальная длина строки 255 символов. Строка имеет структуру, подобную одномерному массиву. Поэтому строка st1 трактуется как st1: array[0..N] of char. Отличие между строкой типа string и массивом состоит в том, что строка имеет переменную длину (количество символов) и нулевой элемент строки st[0] содержит информацию о длине строки. Длина строки может быть изменена путем заполнения строки новым элементом или путем изменения ее нулевого элемента. Текущая длина строки может быть определена значением ORD(st[0]). Строки можно присваивать и сравнивать. Операции отношения >, <, =, >=, <=, <> для строк выполняются посимвольно слева направо с учетом внутренней кодировки символов. Строки считаются одинаковыми, если они имеют одинаковую длину и одинаковые символы. Например: 'abcd' = ‘abcd' 'abcd' <> 'abcde' 'abcd' > ' abc' 'abcd' < ' ABC'. 74 К строкам применима операция сцепления (+) или конкатенации, например: st := 'AB' + 'BC'; st := st + 'CD'; {st содержит 'ABBCCD'} Если количество символов превышает максимально допустимую длину, то "лишние" символы справа отбрасываются. Отдельный элемент строки совместим с типом char. Пример: Var stt: string[2]; c: char; Begin stt := '123'; c := 'a'; writeln(stt); {stt = '12' , излишек отсекается } stt[2] := c ; {stt = '1a' } End. 9.2. Встроенные функции и процедуры для обработки строк LENGTH(s) функция выдает в байтах длину строки s:string, измеряемую в символах. Например, функция LENGTH(st), где St = 'ABBCCD' возвратит значение 6. CONCAT(s1,s2,...,sN) – функция осуществляет сцепление строк s1,s2, ..., sN:string и выдает результат в виде одной общей строки. Например: St := '1a'; S3 :=Concat(St, 'bc'); аналог S3 := St+'bc' S3 = '1abc'. COPY(S, Start, Len) функция выдает подстроку типа string из строки S:string длиной Len:integer, начиная с символа с номером Start:integer. Если Start >Length(S) (больше длины всей строки S), то функция вернет пустую строку; если Start>255, то возникает ошибка. Если Len больше, чем число символов от позиции Start до конца строки S, то вернется остаток строки S от Start до конца. Например, для выражения COPY('ABCDEF', 2, 3) результатом является строка 'BCD'. DELETE(S, Start, Len) процедура возвращает строку S:string, удаляя из неё подстроку длиной Len:integer, начиная с символа с номером Start:integer. После стирания подстроки ее оставшиеся части "склеиваются". Если Start=0 или превышает длину строки S, то строка не изменяется. Не изменит строку и значение Len=0. При Len большем, чем остаток строки, будет удалена подстрока от Start до конца S. Например, для Delete('aбвгде' , 4, 2); // результатом будет строка - “абве”. 75 INSERT(Subs, S, index) процедура возвращает строку S:string, вставляя в неё подстроку Subs:string, начиная с символа под номеpом index:integer; Если измененная строка S оказывается слишком длинной, то она автоматически укорачивается до объявленной длины S (при этом всегда теряются символы справа). Например, st := 'abcdef' ; Insert( '-***-' ,st, 4); // результат - строка: St = 'abc-***- de' POS(Subs, S) функция типа byte отыскивает вхождение подстроки Subs:string в строке S:string и выдает номер позиции, с которой начинается это вхождение. Если строка s не содержит данной подстроки, то функция POS выдает 0. Если в строке s несколько одинаковых подстрок subs, то функция выдает только номер первого вхождения. Например, для строки St = 'abcdef' результатом функций POS( 'de' , St); является значение 4, POS( 'k' , St); является значение 0. STR(x[:w[:n]], s) процедура преобразует числовое значение x в строковое s:string, возвращая строку s. Х может быть переменной или выражением целого или вещественного типа. Для переменной x может быть указана ширина поля w, которое она занимает, а также n количество знаков после десятичной точки. Параметры [:w[:n]] не обязательны. Если параметр n отсутствует для вещественного типа, то используется экспоненциальное представление. Если w больше, чем реальное количество знаков в числе, то производится выравнивание числа по правому краю. Для выравнивания по левому краю используется отрицательное значение w. Если в дробной части числа x знаков больше, чем указано в n, выполняется округление. Например: str(6.66:8:1, s); {результат: S= '6.7' c округлением} str(6.66:-8:2, s); {результат: S= '6.66'} VAL(S, x, ErrCod) процедура преобразует числовую строку S:string в числовую переменную x (типа Real или Integer) и формирует код ошибки ErrCod:Integer, возвращая x и ErrCod. Строка S не должна содержать незначащих пробелов, в том числе в начале и конце. ErrCod целочисленная переменная. Она равна 0, если преобразование выполнено. В противном случае (если преобразование невозможно) эта функция выдает код символа, на котором прекратилось преобразование, значение x в этом 76 случае не определено. Если в строке S имеется десятичная точка или символ E, то переменная x должна быть определена вещественной. Например: VAL( '1324' , x, Cod); // результат преобразования x = 1324, Cod=0; VAL( '13.24Е2' , x, Cod); // результат преобразования x = 1324, Cod=0; VAL( '25А3' , x, Cod); // результат не определен, Cod=3. 9.3. Пример и задания для обработки строк Пример. Ввести строку st1. Сформировать строку st2 перестановкой символов исходной строки в обратном порядке и заменой всех строчных латинских букв прописными. Program lr_10; Var i, j: byte; st1, st2: string; {эквивалентно string[255]} Begin writeln(‘введи строку’); readln (st1); writeln(‘исходная строка:’ , st1); j := LENGTH(st1); {максимальный индекс элемента в строке} for i:=1 to ord( st1[0] ) do begin st2[i] := UPCASE(st1[j]); j := j-1 end; st2[0] = st1[0]; {запись символа с кодом, равным длине строки} write(‘искомая строка: ’ , st2 ); writeln {перевод строки} END. Задания для самостоятельного выполнения 1. Дана строка, содержащая не более двадцати латинских букв. Все вхождения «max» в ней заменить на «min» и «макс» на «мин». Подсчитать число таких замен. 2. Дана строка, содержащая сорок латинских букв. Подсчитать все вхождения «abc» в строку и их удалить. Вывести на экран два варианта полученных строк, заполняя образовавшуюся «дыру» последующими буквами с добавлением в конце пробелов и оставляя на месте удаленных символов пробелы. 3. Определить сколько различных символов входит в заданный текст, содержащий не более 100 литер и оканчивающийся точкой. 77 4. Определить номера позиций гласных букв в заданном тексте. 5. Напечатать заданный текст из 60 символов, удалив из него повторные вхождения каждой литеры. 6. Дана строка, состоящая из слов, разделенных пробелами, в конце строки – точка. Определить, сколько в строке слов, содержащих четное число символов. 7. Дан набор слов на английском языке, разделенных пробелами, в конце точка. Выделить в последовательности нечетные слова прописными буквами. 8. Дан непустой текст из строчных букв, за которыми следует точка. Определить, упорядочены ли эти буквы по алфавиту. Напечатать результат проверки и исходный текст прописными буквами. 9. Дана последовательность от двух до восьми слов, в каждом из которых от одной до десяти строчных букв; между соседними словами – не менее одного пробела, за последним словом – точка. Напечатать слово с максимальной длиной. 10. Дано несколько слов, в каждом из которых от одной до семи строчных букв, между соседними словами – не менее одного пробела, за последним словом – точка. Напечатать эти слова в алфавитном порядке. 11. Дана последовательность, содержащая от одного до восьми слов, в каждом из которых от одной до пяти строчных букв; между соседними словами – запятая, за последним словом – точка. Напечатать эту же последовательность, удалив из нее повторные вхождения слов. 12. В заданном тексте (слова разделены пробелами) поменять местами первое и последнее слово. 13. Даны числа K и текст из слов, разделенных пробелами, в конце – точка. Определить количество слов в тексте, состоящих из K букв. 14. Дана последовательность, содержащая от двух до десяти слов, в каждом из которых от одной до восьми строчных букв; между соседними словами – не менее одного пробела, за последним словом – точка. Напечатать те слова, в которых буквы слова упорядочены по алфавиту. 15. Дана последовательность, содержащая от двух до десяти слов, в каждом из которых от одной до пяти строчных букв; между соседними словами – запятая, за последним словом – точка. Напечатать эту же последовательность слов, но в обратном порядке. 16. В заданный текст входят только цифры и буквы. Определить, является ли текст десятичной, шестнадцатеричной или двоичной записью целого либо вещественного числа (указать при выводе какого). 17. В заданном тексте найти и, если есть, напечатать все слова-палиндромы (слова, которые одинаково читаются слева направо и справа налево). 78 18. Дан текст из слов, разделенных пробелами, в конце – точка. Найти слово наименьшей длины (содержащее наименьшее количество букв). 19. Разработать программу шифровки – дешифровки текста путем замены каждой буквы текста другой буквой, с кодом на N больше (меньше) исходной. 20. Дана непустая последовательность слов, в каждом из которых от одной до шести букв; между соседними словами – запятая, за последним – точка. Напечатать те слова, у которых одинаковые «соседи». (Написать процедуру, которая вводит очередное слово и присваивает его литерной строке, а запятую или точку присваивает некоторой глобальной переменной). 10. ФАЙЛЫ Файл именованная область внешней памяти ПК. Файлом может называться логическое устройство, потенциальный источник или приемник информации. Файл характеризуется именем и содержит компоненты одного типа (может быть любой тип, кроме файлов). Длина вновь создаваемого файла не указывается при его объявлении. В Pascal ABC различают типизированные и текстовые файлы. Определяются файловые типы в блоке TYPE следующим способом: Type <имя> = FILE OF <тип>; {типизированный} <имя> = TEXT; {текстовый} где <имя> имя файлового типа (правильный идентификатор); FILE, OF зарезервированные слова (файл, из), TEXT имя стандартного типа для текстовых файлов; <тип> любой тип, кроме файлового. Например: TYPE FIL = file of char; {файл символов} text30 = file of string[30]; {файл строк } Вид файла определяет способ хранения информации в файле. Переменные файловых типов объявляются в разделе VAR: VAR f: FIL; ff: text30; а также f1: TEXT; {переменная для текстового файла } f2: file of real; {переменная файла вещественных чисел} т. е. сразу можно описывать файловые переменные без объявления типа, например: 79 VAR <имя_переменной>: TEXT; <имя_переменной>: FILE OF <тип>; Некоторые файлы могут только вводить информацию (клавиатура), другие только принимать ее (устройства печати), третьи позволяют и считывать, и записывать (файл на диске). Именно с помощью файловой системы осуществляется весь ввод и вывод информации в программе. Все файлы становятся доступными программе только после связывания ранее объявленной файловой переменной с именем существующего или вновь создаваемого файла, а также в указании направления обмена информацией: чтение из файла или запись в него. 10.1. Процедура связывания файлов Связывание выполняется стандартной процедурой ASSIGN: ASSIGN (<файловая_переменная> , <имя_файла); где <файловая_переменная> правильный идентификатор, объявленный как переменная файлового типа; <имя_файла> текстовое выражение, содержащее имя файла (заключается в апострофы). Пример. VAR f, f1, f2 : text; {объявление файловых переменных} Begin ASSIGN(f, ' nameF.txt '); // связывание с файлом nameF.txt <Имя_файла> это любое выражение строкового типа, которое строится по правилам определения имен в MS DOS: содержит до 8 разрешенных символов: прописные и строчные латинские буквы, цифры и следующие символы ! @ # $ % ^ & ( ) ' ~ - _ ; начинается с любого разрешенного символа; за именем может следовать расширение последовательность до трех разрешенных символов. Расширение, если оно есть, отделяется от имени точкой, например: Lab1.pas или date.txt. Имя физического файла должно быть корректным и уникальным. Нельзя вставлять символы шаблонов '*' и '?' в имя файла, но можно связывать файловые переменные с несуществующими пока на диске файлами (для их создания). Перед именем может указываться путь к файлу, имя диска и/или имя текущего каталога и имена каталогов вышестоящих уровней. Если имени каталога предшествует обратная косая черта, то путь к файлу начинается из корневого каталога, если черты нет – из текущего каталога, установленного в системе по умолчанию. 80 Имя диска это один из символов А: В: С: ... Z. При этом А: и В: относятся к дисковым накопителям на гибких дискетах, а С:, D: и другие – к жестким и виртуальным дискам. Если имя диска не указано, то по умолчанию подразумевается устройство, установленное в операционной системе перед началом работы программы. Максимальная длина имени пути с файлом 79 символов, например: VAR f1, f2: text; Begin ... Assign( f1 , 'd:\V-129\date.txt ' ) ; Assign( f2, name.dat); {файл в текущем каталоге} … Однажды установленная связь процедурой Assign между файловой переменной f и физическим файлом сохраняется до следующего вызова Assign с той же файловой переменной f. То есть можно проделывать различные операции с файлом, лишь один раз связав его с файловой переменной f. Для инициализации файла необходимо указать имя физического файла и направление передачи данных. В Pascal ABC можно открыть файл для чтения, записи, а также для чтения и записи одновременно. 10.2. Процедуры и функции для работы с файлами Следующие процедуры открывают логический файл с файловой переменной <ф.п.>, связанной ранее с уже существующим файлом: RESET(<ф.п.>) – для чтения, REWRITE(<ф.п.>) – для записи. Только после открытия файла становится возможным чтение и запись данных. При их выполнении переменная-указатель, связанная с файлом, будет указывать на начало этого файла, т.е. на компонент с номером нуль. Процедуры открытия могут применяться многократно к одному и тому же файлу. Если файл был до этого открыт, то он автоматически предварительно закрывается. Повторный вызов RESET переустановит последовательность чтения вновь на самый первый элемент файла (потеря данных исключена). Но повторное обращение в REWRITE сотрет текущее содержимое файла и подготовит файл к заполнению, начиная с первого элемента. Процедура CLOSE(f) закрывает открытый ранее логический файл f и обеспечивает сохранение всех записей и регистрацию файла на диске. Вызовы процедуры CLOSE необходимы для завершения работы с файлами. Также 81 необходимо закрывать открытые файлы перед их удалением (ERASE) или переименованием (RENAME). При этом связь файла с файловыми переменными сохраняется. Попытка закрыть уже закрытый файл или еще не открытый вызовет сбой в работе программы. Закрытие файлов выполняется автоматически по отношению ко всем открытым файлам при нормальном завершении программы. В таблице 8 сведены общие процедуры и функции для работы с файлами, наиболее применимые на практике. Таблица 8 Общие процедуры и функции для работы с файлами Процедуры и функции Выполняемые действия Assign (f, name ) Связывает <ф.п.> f с именем файла name типа string ReSet (f ) Открывает файл с логическим именем f для чтения ReWrite (f ) Открывает файл с логическим именем f для записи Close (f ) Закрывает файл с логическим именем f Erase (f ) Удаляет (стирает) физический файл, связанный с f, с диска. Стираемый файл должен быть закрыт ReName (f, NewName ) Переименовывает физический файл, связанный с <ф.п.> f, в файл с новым именем NewName EOF (f ) Функция логического типа возвращает значение TRUE, если достигнут признак конца файла или файл пуст, иначе возвращает FALSE При переименовании процедурой RENAME менять можно лишь имя файла, имя диска менять нельзя. Предварительно файл должен быть закрыт процедурой CLOSE. Функция EOF(f) тестирует конец файла. Если она возвращает TRUE, при записи очередной компонент будет добавлен в конец файла, при чтении файл считается исчерпанным. 10.3. Типизированные файлы Типизированные файлы позволяют организовать прямой доступ к каждой из компонент (по ее порядковому номеру), поскольку длина любого компонента типизированного файла строго постоянна. Описание файловой переменной для таких файлов выполняется в следующем виде: Var < ф.п.> : file of <тип компонент>; Перед первым обращением к процедурам ввода-вывода указатель файла стоит в его начале и указывает на компоненту с номером нуль. После каждого 82 чтения или записи указатель сдвигается к следующему компоненту файла. Переменные в списках ввода-вывода должны иметь тот же тип, что и компоненты файла. Если этих переменных в списке несколько, указатель будет смещаться после каждой операции обмена данными между переменными и дисковым файлом. Для работы с типизированными файлами определены следующие процедуры и функции (табл. 9). Процедуру SEEK и функции FILESIZE, FILEPOS нельзя использовать для текстовых файлов. Таблица 9 Процедуры и функции для работы с типизированными файлами Процедуры, функции Выполняемые действия READ(<ф.п.>, <список Процедура обеспечивает чтение очередных комввода>); понентов файла WRITE(<ф.п.>, Процедура используется для записи новых ком<список вывода>); понентов в файл; в качестве элементов вывода может стоять выражение. SEEK(<ф.п.>, Процедура смещает указатель файла к компоненту <номер_компоненты>) с указанным номером; <номер_компоненты> – выражение типа Integer FILESIZE(<ф.п.>); Функция возвращает количество компонент, содержащихся в файле FILEPOS(<ф.п.>); Функция возвращает порядковый номер компоненты файла, доступной для чтения или записи Чтобы переместить указатель в конец файла, можно написать, например: Seek(f, FileSize(f)); где f файловая переменная. Файловая переменная предварительно должна быть объявлена предложением FILE OF и связана с именем физического файла процедурой ASSIGN. Файл перед обращением к нему должен быть открыт. 10.4. Текстовые файлы Это файлы последовательного доступа. Они предназначены для хранения текстовой информации. Текстовые файлы связываются с файловыми переменными типа TEXT: Var <ф.п.> : TEXT; Текстовый файл в Pascal ABC трактуется как совокупность строк переменной длины. Доступ к каждой строке возможен лишь последовательно, начиная с первой строки. При создании текстового файла в конце каждой строки ставится специальный признак EOLN (End Of LiNe конец строки), а в конце 83 всего файла – признак EOF (End Of File – конец файла) c кодом 26. Тестируются эти признаки одноименными логическими функциями. Для доступа к записям текстового файла применяются процедуры READ, READLN, WRITE, WRITELN. В них можно использовать переменное число параметров, в качестве которых могут быть символы, строки и числа. Первым параметром в любой из перечисленных процедур может стоять файловая переменная. В этом случае осуществляется обращение к дисковому файлу, связанному с файловой переменной процедурой ASSIGN, и открытому процедурами RESET или REWRITE. 10.5. Процедуры ввода Процедура READ обеспечивает ввод символов, строки и чисел. Она имеет следующий формат: READ(<ф.п.>,<список_ввода>); или READ(<список_ввода>); где <список_ввода> последовательность из одной или более переменных типа CHAR, STRING или любого целого или вещественного типов, например: READ(Х); READ(f, x1, x2, x3); // ввод переменной Х с клавиатуры // ввод трех переменных из файла При вводе переменной типа CHAR выполняется чтение одного символа из файла и присваивается считанное значение переменной. Если перед чтением указатель файла достиг конца очередной строки, то считывается символ CR (код 13). Если достигнут конец файла то символ EOF. При вводе переменной типа STRING количество считанных символов равно максимальной длине строки, если раньше не встретились символы CR, EOF. В этом случае эти символы в строку не помещаются. Если количество символов во входной строке больше максимального размера строки, то «лишние» символы до конца строки отбрасываются, а новое обращение к READ возвращает пустую строку. Таким образом, READ не в состоянии прочесть последовательность строк: читается только одна строка, остальные окажутся пустыми. Для ввода последовательности строк символов применяется процедура READLN. При вводе числовых данных процедура READ сначала выделяет подстроку во входном потоке по следующему правилу: все ведущие пробелы, символы табуляции и маркеры конца строк пропускаются до первого значащего символа; и, наоборот, после первого значащего символа любой из перечисленных символов или символ EOF указывает на конец подстроки. Выделенная таким образом подстрока рассматривается как символьное представление числовой константы и присваивается переменной. Фактически весь файл рассматривается как одна длинная строка чисел. 84 Процедура READLN также обеспечивает ввод символов, строк и чисел: READLN( f, x); или READLN(f, x1, x2, ..., xN); Она идентична процедуре READ за исключением того, что после считывания последней переменной списка ввода оставшаяся часть строки до маркера EOLN пропускается, поэтому следующее обращение к READLN или READ начинается с первого символа новой строки. Эту процедуру можно вызвать без параметра <список ввода>: READLN(f); READLN; что приведет к пропуску всех символов текущей строки. Таким способом можно организовать ожидание нажатия клавиши ENTER при открытом окне результатов. При чтении с клавиатуры курсор помещается в начало следующей строки, в то время как в процедуре READ остается в текущей строке. 10.6. Процедуры вывода Процедура WRITE обеспечивает вывод информации в файл или на экран дисплея. Существует две формы обращения к процедуре: WRITE(<ф.п.>, <список_вывода>); или WRITE(<список_вывода>); где <список вывода> это последовательность, состоящая из одной и более переменных (или выражений) символьного, строкового, логического или любого целого или вещественного типа, например: WRITE(x); WRITE(f, x1, x2, xN); Файловая переменная, если она указана, должна быть предварительно описана типом TEXT и связана с именем файла процедурой ASSIGN. Если файловая переменная отсутствует, подразумевается вывод в стандартный файл – на экран дисплея. Вывод процедурой WRITELN отличается от WRITE тем, что выводимая строка завершается кодами CR (возврат каретки) и LT (перевод строки), т. е. добавляет маркер конца строки. При вызове WRITELN можно опускать <список_вывода>. В этом случае в файл передается признак конца строки EOLN, что при выводе на экран приводит к переводу курсора в начало следующей строки: WRITELN(f); WRITELN; Любой элемент X списка вывода для процедур WRITE/ WRITELN может быть представлен в следующем формате: X[:w[:d]], причем элементы, заключенные в квадратные скобки, могут отсутствовать. Здесь X имя переменной или выражение, w, d выражения целого типа WORD (0..65535). Если параметр 85 w присутствует, то он указывает минимальную ширину поля для записи значения X. При длине переменной X меньше w слева производится дополнение поля вывода пробелами, если Х больше w, то w игнорируется и выводится необходимое число символов (по умолчанию w = 23); если параметр w не указан, то значение соответствующей переменной выводится вслед за предыдущим без какого-либо разделения. Параметр d задает количество десятичных знаков в дробной части вещественного числа. Используется только для вывода значений выражений вещественных типов. Если параметр d не указан, то число выводится в экспоненциальной форме, в противном случае в формате представления с фиксированной точкой. Если d = 0, выводится только целая часть числа. Например: результаты вывода для числа Х = 3.22 будут следующие: WRITE(X:6:2); { 3.22} WRITE(X:6:0); { 3} WRITE(X:4:2); {3.22}. Для текстовых файлов также применимы следующие процедуры и функции (табл. 10). Таблица 10 Тексториентированные процедуры и функции Процедуры, функции Append( f ); EOLN(f); SeekEOLN(f); SeekEOF(f); Выполняемые действия Процедура открывает уже существующий файл f для дозаписи в его конец (для расширения) Функция возвращает значение TRUE, если во входном файле f достигнуты маркеры конца строки EOLN или конца файла EOF, и FALSE в противном случае Функция пропускает все пробелы и знаки табуляции до первого признака EOLN или первого значащего символа. Возвращает значение TRUE, если обнаружен маркер конца файла или конца строки Функция пропускает все пробелы, знаки табуляции и маркеры конца строк до маркера конца файла или первого значащего символа. Если маркер обнаружен, возвращает значение TRUE При выводе логических выражений в зависимости от значения выводятся подстроки TRUE и FALSE. Ввод логических констант процедурами READ и READLN не предусмотрен. 86 10.7. Примеры и задания для работы с файлами Пример 1. Написать программу, которая вводит с клавиатуры три вещественных числа и записывает эти числа и их сумму в файл FXD.DAT. PROGRAM FileFD; VAR y, x1, x2, x3: real; FD: TEXT; BEGIN ASSIGN(FD, 'FXD.DAT'); READ(x1, x2, x3); {ввод трех чисел} REWRITE(FD); {открыть файл для записи} y := x1 + x2 + x3; WRITELN(FD,' x1=',x1,' x2=',x2,' x3=',x3); {вывод в файл x1,x2,x3} WRITELN(FD,' сумма = ',y); {вывод в файл суммы} CLOSE(FD); {закрыть файл} END. Пример 2. Вычислить суммы элементов в столбцах двумерного числового массива А[1..2,1..4], заданного в файле FILE1.dat. Полученные значения поместить в файл FILE2.dat. Для решения задачи разработана СА (рис. 16) и программа: Начало Связывание f1,f2 c файлами Закрыть f1, Открыть f2 j =1,4 Открыть f1 Закрыть f2 Sj =0 i = 1,2 i = 1,2 j = 1,4 Sj = Sj+aij Ввод aij из файла f1 Рис. 16 87 Вывод Sj в файл f2 Program lr_11; Var a: array [1..2,1..4] of integer; s: array[1..4] of integer; i, j: integer; f1, f2: text; {объявление файловых переменных текстового типа} Begin ASSIGN(f1,’FILE1.dat’); {связывание f1 с физическим файлом} ASSIGN(f2,’FILE2.dat’); RESET(f1); {открыть файл для чтения} for i:=1 to 2 do for j:=1 to 4 do Read(f1, a[i, j]); {чтение из файла, связанного с f1 } CLOSE (f1); {закрыть файл, связанный с f1} REWRITE (f2); {открыть файл для записи} WRITELN (f2,’ 1 2 3 4 - столбцы’); {вывод в файл через f2} WRITELN (F2,’суммы по столбцам); {вывод в файл через F2} for j:=1 to 4 do begin s[j] := 0; for i:=1 to 2 do s[j] := s[j] + a[i,j]; write(f2, s[j]:3) {вывод в файл через F2} end; CLOSE(F2) {закрыть файл, связанный с F2} END. Файл результатов Исходный файл FILE2.dat FILE1.dat 1 2 3 4 столбцы 2234 суммы по столбцам 5234 7468 Задания для самостоятельного выполнения Задание 1 Выполнить задачу из раздела 7.10, считывая исходные данные из одного файла и записывая полученные результаты в другой текстовый файл. Файл с исходными данными должен быть подготовлен предварительно. 88 Задание 2 1. В текстовом файле Т1 записана последовательность целых чисел, разделенных пробелами. Написать программу, записывающую в текстовый файл Т2 все положительные числа из Т1. 2. В текстовом файле f1 записана последовательность чисел. Сформировать текстовый файл f 2, содержащий все числа в обратном порядке. 3. В текстовом файле Т1 записана последовательность чисел. Разработать программу, переписывающую в текстовый файл Т2 сначала все положительные числа из Т1, нуль, затем – все отрицательные числа. 4. В текстовом файле f 1 дана последовательность целых чисел, разделенных пробелами. Записать в текстовый файл F2 все положительные числа, а в файл F3 – отрицательные числа и нулевые элементы. 5. Сформировать файл из девяти строк, в первой из которых – одна единица, во второй – две двойки,…, в девятой – девять девяток. 6. Даны два файла F1, F2. Сформировать третий файл F, в который сначала записать все элементы файла F1, а затем – элементы файла F2. 7. Элементы каждого из заданных в двух файлах массивов X и Y упорядочены по возрастанию. Объединить элементы этих двух массивов в один файл F с упорядочением их по возрастанию. 8. В заранее подготовленном файле K задан массив из 15 целых чисел. Выделить в другой файл те элементы массива K, индексы которых являются степенями двойки. 9. В текстовом файле S1 записана последовательность из N*K чисел. Написать программу, формирующую в файле S2 матрицу из N строк по K чисел в каждой строке. 10. В файле W задан массив из девяти элементов. В новом файле WW сформировать массив, в котором каждому элементу будет присвоено значение соседнего с ним справа. Последнему элементу присвоить значение первого. 11. В файле D1 задана квадратная матрица вещественных чисел. Сформировать файл D2, в котором поменять местами первую и последнюю строки. 12. В текстовом файле F подготовить последовательность целых чисел, разделенных пробелами. Написать программу, записывающую в текстовый файл FF все различные значения, встречающиеся в файле F. 13. В файле X1 задана матрица целых чисел. Сформировать файл Х2, в котором все элементы с четными номерами строки и столбца матрицы заменить нулем (стереть). 14. В файле X задан массив из 20 чисел. Упорядочить его по возрастанию и занести в файл Y. 89 15. Задана в файле строка текста. Выполнить все циклические сдвиги слов в заданном тексте влево. Каждый полученный при этом текст вывести в другой файл. 16. В файле Y1 задана матрица вещественных чисел. Сформировать файл Y2, в котором строки матрицы упорядочены по убыванию элементов первого столбца. 17. В файле дан текст из 20 символов. Напечатать сначала все цифры, входящие в него, затем латинские буквы, далее русские буквы и все остальные литеры, сохраняя при этом взаимное расположение символов в каждой из четырех групп. Создать четыре новых файла, каждый из которых содержит свою группу символов. 18. Имеется текстовый файл BOOK. Написать программу, которая игнорирует исходное деление этого файла на строки, переформирует его, разбивая на строки так, чтобы каждая строка оканчивалась точкой либо содержала ровно 40 литер, если среди них нет точки. 19. Имеется текстовый файл T. Вывести в новый файл и напечатать первую из самых коротких его строк. 20. Имеется текстовый файл, содержащий фразу. Написать программу, которая считывает из файла литеры до первой точки и записывает их (без точки) в другой текстовый файл, формируя в нем строки по 20 символов (в последней строке литер может быть меньше). 11. КОМБИНИРОВАННЫЙ ТИП – ЗАПИСИ Запись описание комбинированного типа, состоящее из нескольких полей, каждое из которых имеет свой тип. Структура записи аналогична таблице. Записи состоят из фиксированного числа компонентов, называемых полями записи. В отличие от массива компоненты (поля) записи могут быть различного типа. 11.1. Структура данных типа записи Структура объявления типа "запись" имеет следующий вид: TYPE <ИмяТипа> = RECORD <поле1>: <тип поля1>; <поле2>: <тип поля2>; ... <полеN>: <тип поляN> end; 90 Если тип нескольких полей совпадает, то имена полей можно перечислить через запятую. <ИмяТипа> и поля являются правильными идентификаторами. Например: TYPE DENROGD = RECORD name: string; {фамилия или имя } den, mes: byte; {день, месяц} god: word {год} end; Определение константы – записи будет иметь вид <идентификатоp>: <тип_записи > = (<список_значений_полей>); Список значений полей представляет собой список из последовательностей вида: имя поля, двоеточие и константа. Поля должны указываться в той же последовательности, в какой они перечислены в объявлении типа. Например: TYPE POINT = record x, y: real; end; CONST p: POINT = (x:1; y:1); Объявление переменных производится в разделе VAR: VAR a, b: DENROGD; Доступ к каждой компоненте записи производится указанием составного имени: имени переменной и затем через точку имени поля. Например: a.name := ' MARINA'; a.god := 1991; a.den := 23; a.mes := 3; Таким образом, в типе "запись" определена операция присваивания. Кроме того, как и в массиве, все значения переменных типа "запись" можно присваивать другим переменным того же типа: B := A; . Над полями можно выполнять действия, разрешенные для базового типа: b.god := а.god + 1; {на год старше}. В качестве переменной может быть объявлен массив записей: VAR s: array[1..20] of STUDENT; 91 Пример. Разработать программу формирования списка студентов с указанием дат рождения. Распечатать список в алфавитном порядке. Program zapis; Type {определение нового типа} student = record {запись} name: string[15]; den, mes: byte; god: word end; Var Z: ARRAY [1..20] OF student; k, m, i, n: byte; r: string[15]; {вспомогательная строка для перестановки} BEGIN writeln('ВВЕДИТЕ КОЛИЧЕСТВО СТУДЕНТОВ'); READln(n); for i:=1 to n do begin writeLN('ВВЕДИТЕ имя ',i,' студента с прописной буквы'); readLN (z[i].name); WRITELN('ВВЕДИТЕ день рождения'); readLN(z[i].den); WRITELN('ВВЕДИТЕ месяц рождения'); readLN(z[i].mes); WRITELN('ВВЕДИТЕ год рождения'); readLN(z[i].god); end; for I := n downto 2 do {********* Упорядочение списка *********] begin {поиск "наибольшего" значения поля NAME} m:=1; for k:=2 to i do if z[k].name > z[m].name then m := k; r := z[i].name; {перестановка записей} z[i].name := z[m].name; z[m].name := r end; {**************************************} writeln(' Упорядоченный список '); for i:=1 to n do begin WRITE(z[i].name); WRITELN(' Дата рождения:', z[i].den, '.' ,z[i].mes, '.', z[i].god); end END. 92 11.2. Обработка полей записей Для упрощения доступа к полям записи может использоваться оператор присоединения. Структура оператора имеет вид WITH <переменная_Типа_Запись> DO <оператор>; где WITH, DO ключевые слова ( с, делать). Пример. WITH a DO // где a – запись, структуру см. в п. 11.1 begin name:='MARINA'; god:=1991; date:=23; mes:=3 end; Поле записи может иметь практически любой тип (массив, другая запись, множество). Доступ к вложенным элементам сложных структур, например к записи в записи, выполняется перечислением ряда полей через точку или оператор присоединения. Пример. Определим вложенную запись (запись в записи) TYPE STUDENT = RECORD name: string; DenRogden: RECORD den, mes: byte; god: word end; end; VAR z: STUDENT; Имя DenRogden в свою очередь тоже является записью, тогда обращение к вложенным полям выполняется в виде z.name := 'LIZA'; z.DenRogden.god := 1994; Используя оператор присоединения, к этим же полям можно получить доступ другими способами: WITH z DO begin name := 'LIZA'; with DenRogden DO god := 1994; end; 93 или WITH z DO name := 'LIZA'; WITH Z DO with DenRogden DO god := 1994; К полю GOD можно также обратиться и следующим оператором: WITH z.DenRogden DO god:=1994; Используя тип "запись", можно составить базы данных для разных назначений, а затем обрабатывать их с помощью программы [3–6]. При этом нужно следить, чтобы среди идентификаторов полей не было одинаковых. 11.3. Задания с обработкой записей Задание 1 1. Ввести оценки студента по 5 экзаменам. Определить средний балл и подсчитать количество удовлетворительных, хороших и отличных оценок. Напечатать название предмета, если есть «неуд». 2. Дан список студентов и оценка каждого на экзамене (оценки на N экзаменах). Подсчитать количество удовлетворительных оценок, хороших, отличных и средний балл в группе. Напечатать фамилии неуспевающих студентов. 3. Дан список студентов группы. Заполнить его следующими сведениями: фамилия, имя, отчество; имеет ли компьютер (если имеет, то какой и с какого года). Подсчитать сколько студентов имеют ПК. 4. Сформировать список студентов группы со следующими сведениями: фамилия, имя, отчество, знает ли языки программирования Pascal ABC, Cи (если да, где обучался и сколько лет). Подсчитать, сколько студентов знают язык Си, сколько – Pascal ABC, сколько – оба языка. 5. Сформировать список студентов группы, в котором указать фамилию (имя, отчество); город, в котором получил среднее образование (номер школы, если обучался в Омске). Подсчитать, сколько в группе иногородних студентов. 6. Сформировать запись «ключевые слова Pascal ABC»: слово и перевод. Подсчитать их количество. Организовать поиск: ключевое слово – перевод и наоборот. 7. Сформировать телефонный справочник. По номеру организовать поиск владельца, и наоборот. 8. Сформировать запись «Даты – праздники». Организовать в программе ввод дат, подсчитать число праздничных дней и рабочих. 9. Сформировать запись «английское слово – перевод». Вводя слово (английское или русское), найти перевод или выдать сообщение «нет в словаре». По возможности предусмотреть пополнение словаря. 94 10. Сформировать запись «операторы Pascal ABC»: оператор, действие. Подсчитать их количество и число операторов, имеющих повторяющиеся ключевые слова. 11. Сформировать запись «типы Pascal ABC»: имя, тип, операции, разрешенные в данном типе. Подсчитать количество разных операций и вывести списки типов для каждой операции. 12. Сформировать пополняемую базу данных «Континент – страны», в которой указать столицы, численность населения, крупные города. Организовать поиск страны по городу, стран или городов на континенте. 13. В файле задан список книг (автор, название, год издания). Разработать программу выбора книг, выпущенных ранее заданного года. 14. Сформировать список граждан, в котором указать фамилию, имя, отчество; адрес; профессию. Организовать в программе выборку и подсчет граждан с одинаковой профессией. 15. Сформировать список студентов группы, в котором указать фамилию, имя, отчество; день, число и месяц рождения. Организовать выборки по месяцу и году рождения. 16. Дан список студентов группы. Заполнить его следующими сведениями: фамилия, имя, отчество; день, число и месяц рождения. Распечатать список в порядке возрастания дат рождения. 17. Сформировать базу данных «Единицы измерения», в которой указать название единицы, обозначение, назначение, соотношение. Организовать поиск по любому полю. 18. Разработать базу данных «География. Реки», в которой указать название реки, местоположение, длину, глубину. 19. Разработать базу данных «Астрономия», в которой указать название звезды, величину, созвездие. 20. Разработать базу данных «Планеты солнечной системы», в которой указать название планеты, величину, удаленность, спутники. 21. Сформировать базу данных «Химические элементы», в которой указать название элемента, формулу, группу, организовать выборки. 22. Ввести сведения о человеке: фамилия, имя, отчество, пол, национальность, рост, вес, дата рождения. 23. Ввести сведения о гражданине: Ф.И.О., дата рождения, ИНН, № страхового свидетельства, № медицинского полиса. Запрограммировать поиск. 24. Сформировать справочник о спортивных командах: название, город, число сыгранных игр, число очков, количество игроков. 95 Задание 2 Дополнить программу для предыдущего задания заполнением и обработкой файлов. Имя файла вводить с клавиатуры в процессе работы программы. 12. Процедурные типы Для организации передачи в качестве фактических параметров процедур и функций в Pascal ABC применяются два процедурных типа: тип-процедура и тип-функция. При объявлении процедурных типов используется только заголовок процедуры или функции, например: TYPE Proc1 = Procedure(a, b, c: real; var d: real); Proc2 = Procedure(var b1, b2:byte); Proc3 = Procedure; Func = Function(x: real):real; Func2 = Function(s: string): string; Для объявления переменных процедурного типа используется запись: VAR pr: proc1; f: func; Пример применения параметра – функции : type Func = Function(x : real): real; Function F1(x: real): real; Begin ... end; Procedure FF(n:byte; F:Func); Var ...; Begin ... end; BEGIN ... FF(2,F1); ... FF(5,F1); END. 96 Библиографический список 1. Михалкович, С.С. Pascal ABC & Programming Taskbook ME / С.С. Михалкович, М.Э. Абрамян. [Электронный ресурс]. – Режим доступа – http://sunschool.math.rsu.ru/ 2. Ерёмин, О.Ф. Методическое пособие по программированию на языке Pascal ABC / О.Ф. Ерёмин. – Моздок, 2009. – 49 с. [Электронный ресурс]. – Режим доступа – http:// scholtro.narod.ru 3. Чернов, Ю.П. Программирование для начинающих. Turbo Pascal 7.0: учеб. пособие / Ю.П.Чернов, О.П. Шафеева. – Омск: Изд-во ОмГТУ, 2007. – 132 с. 4. Чернов, Ю.П. Практикум по программированию для начинающих: учеб. пособие / Ю.П.Чернов, О.П. Шафеева. – Омск: Изд-во ОмГТУ, 2000. – 128 с. 5. Фаронов, В.В. Турбо Паскаль. Начальный курс / В.В. Фаронов. – М.: Нолидж, 1997. – 616 с. 6. Марченко, А.И. Программирование в среде Turbo PASCAL. Базовый курс / А.И. Марченко, Л.А. Марченко. – Киев: ВЕК+, 1999. – 464 с. 7. Иванова, Г.С. Технология программирования / Г.С. Иванова. – М.: Изд-во МГТУ им. Баумана, 2006. – 336 с. 8. Мануйлов, В.Г. Разработка программного обеспечения на Паскале / В.Г. Мануйлов. – М.: ПРИОР, 1996. – 240 с. 9. Основы программирования в среде Турбо Паскаля: метод. указания / сост. О.П. Шафеева, Ю.П.Чернов. – Омск: Изд-во ОмПИ, 1999. – 48 с. 10. ГОСТ 19.701-90. Схемы алгоритмов, пpогpамм, данных и систем. Единая система программной документации. – М.: Изд-во стандартов, 1991. – 26 с. 11. Алгоритмизации и программирования. Турбо Паскаль : метод. указания / сост. О.П. Шафеева. Омск: ОмГТУ, 2004. – 48 с. 12. Методы проектирования программ: метод. указания к выполнению курсовой работы / сост. О.П. Шафеева. – Омск: ОмГТУ, 2004. – 32 с. 13. Кинг, Д. Создание эффективного программного обеспечения / Д. Кинг. – М.: Мир, 1991. – 287 с. 14. Камаев, В.А. Технологии программирования / В.А. Камаев, В.В. Костерин. – М.: Высш. шк., 2005. – 359 с. 97 Приложение Обозначения графические в схемах алгоритмов (ГОСТ 19.701-90) Символ Наименование Данные Назначение Определяет ввод или вывод на внешнее устройство или любой носитель данных Процесс Отражает обработку данных: выполнение отдельной операции или группы операций Предопределенный процесс Отображает предопределённый процесс, состоящий из одной или нескольких операций программы, которые определены в другом месте (подпрограмме, модуле) Подготовка Отражает инициализацию и модификацию параметра для управления циклом со счётчиком Решение Описывает проверку условия и выполняет переключение по одному из условий. Имеет один вход и два или более альтернативных выходов, один из которых активизируется после вычисления условия внутри символа Граница цикла Состоит из двух частей: начала и конца цикла. Обе части имеют один и тот же идентификатор. Изменение значения идентификатора, условия для выполнения или завершения помещаются внутри символов в начале или в конце цикла Соединитель Используется для обрыва линии и продолжения её в другом месте. Должен содержать уникальное обозначение Терминатор Определяет начало и конец структурной схемы алгоритма программы или подпрограммы Комментарий Используется для добавления пояснительных записей. Связывается с символом или группой символов, обведённых пунктиром Основная линия Отображает последовательность выполнения действий в алгоритме 98 СОДЕРЖАНИЕ Введение.................................................................................................................................. 3 1. Система программирования Pascal ABC ................................................................... 4 1.1. Структура меню среды .......................................................................................... 5 1.2. Команды редактора Pascal ABC ........................................................................... 6 1.3. Правила оформления программ ............................................................................ 8 1.4. Компиляция и исправление синтаксических ошибок ........................................ 9 1.5. Этапы подготовки и решения задач на компьютере ........................................ 10 1.6. Словарь основных терминов ............................................................................... 11 2. Начальные сведения о языке Pascal ABC ................................................................. 12 2.1. Алфавит языка ...................................................................................................... 12 2.2. Константы ............................................................................................................. 13 2.3. Идентификаторы и типы данных........................................................................ 14 2.4. Переменные и именованные константы ............................................................ 15 2.5. Структура простой программы и комментарий ................................................ 16 3. Оператор присваивания и числовые данные .......................................................... 17 3.1. Арифметические выражения............................................................................... 17 3.2. Оператор присваивания ...................................................................................... 18 3.3. Процедуры ввода-вывода .................................................................................... 18 3.4. Стандартные функции Pascal ABC .................................................................... 19 3.5. Целые типы в Pascal ABC .................................................................................... 20 3.6. Вещественные типы ............................................................................................. 22 3.7. Примеры и задания к самостоятельному выполнению .................................... 23 4. Программирование разветвленных алгоритмов..................................................... 26 4.1. Логические выражения ....................................................................................... 26 4.2. Условный оператор IF ......................................................................................... 28 4.3. Составной и пустой операторы ........................................................................... 29 4.4. Оператор безусловного перехода ....................................................................... 29 4.5. Пример и задания с оператором IF ..................................................................... 30 4.6. Оператор выбора варианта CASE ....................................................................... 34 4.7. Примеры и задания с оператором CASE ........................................................... 35 5. Программирование алгоритмов циклической структуры .................................... 37 5.1. Оператор счётного цикла .................................................................................... 37 5.2. Примеры и задания для оператора цикла со счётчиком .................................. 38 5.3. Оператор цикла с предусловием ......................................................................... 41 5.4. Пример и задания для оператора цикла с предусловием ................................. 41 5.5. Оператор цикла с постусловием ......................................................................... 44 5.6. Процедуры прерываний циклов.......................................................................... 44 5.7. Примеры и задания для циклов с постусловием ............................................... 45 6. Структурированные типы данных ........................................................................... 48 6.1. Массивы данных................................................................................................... 48 6.2. Пример и задания для одномерных массивов ................................................... 50 6.3. Ограниченный тип (диапазон) ............................................................................ 52 6.4. Пример и задания для двумерных массивов ..................................................... 53 7. Структурное программирование ................................................................................ 56 7.1. Структура сложной программы .......................................................................... 56 7.2. Подпрограммы. Процедуры и функции ............................................................. 58 7.3. Структура подпрограммы-функции ................................................................... 60 99 7.4. Примеры и задания с подпрограммой-функцией ..............................................60 7.5. Структура подпрограммы-процедуры ................................................................64 7.6. Передача в подпрограмму массивов и строк .....................................................65 7.7. Рекурсия в программе ..........................................................................................65 7.8. Вложенные подпрограммы. ................................................................................66 7.9. Процедуры EXIT и HALT ....................................................................................67 7.10. Пример и задания с подпрограммой-процедурой ...........................................67 8. Обработка символьных данных .................................................................................71 8.1. Символьный тип ...................................................................................................71 8.2. Задания для символьных данных .......................................................................73 9. Обработка строк текста ................................................................................................74 9.1. Строковый тип ......................................................................................................74 9.2. Встроенные функции и процедуры для обработки строк ................................75 9.3. Пример и задания для обработки строк .............................................................77 10. Файлы .............................................................................................................................79 10.1. Процедура связывания файлов ..........................................................................80 10.2. Процедуры и функции для работы с файлами .................................................81 10.3. Типизированные файлы .....................................................................................82 10.4. Текстовые файлы ................................................................................................83 10.5. Процедуры ввода ...............................................................................................84 10.6. Процедуры вывода .............................................................................................85 10.7. Примеры и задания для работы с файлами ......................................................87 11. Комбинированный тип – записи ...............................................................................90 11.1. Структура данных типа записи .........................................................................90 11.2. Обработка полей записей ...................................................................................93 11.3. Задания с обработкой записей ...........................................................................94 12. Процедурные типы.......................................................................................................96 Библиографический список .............................................................................................97 Приложение. Обозначения графические в схемах алгоритмов ......................................98 Редактор Е.С. Воронкова Компьютерная верстка О.Г. Белименко ИД № 06039 от 12.10.2001 Свод. темплан 2010 г. Подписано в печать 03.06.10. Формат 60х84 1/16. Отпечатано на дупликаторе. Бумага офсетная. Усл. печ. л. 6,25. Уч.-изд. л. 6,25. Тираж 100 экз. Заказ 398. Издательство ОмГТУ. Омск, пр. Мира, 11. Т. 23-02-12 Типография ОмГТУ 100