Текст
                    


А. И. Марченко Л. А. Марченко Программирование в среде Turbo PaSM1 ИЗДАНИЕ ШЕСТОЕ. СТЕРЕОТИПНОЕ. ЮБИЛЕЙНОЕ Киев “ВЕК+” 2000
ББК 32.973 01 МЗО УДК 681.3.06 л А И Марченко Л. А. л премирование в среде Turbo Pascal 7.0/ Марченко А. И , Марченко Л А. изо про'Р т.)п„„нко В П. - 6-е изд., стереотипное, юбилейное. — К . ВЕК+ Под ред. Тарасенко о ...-г, - 2000. - 464 с., ил. ISBN 966-7140-15-6 В книге описывается язык программирования Turbo Pascal версии 7.0 и программирование на этом языке. Книга построена на материалах лекции, практических и лабораторных занятий, проводи- мых на кафедре специализированных компьютерных систем факультета прикладной математи- ки Национального технического университета Украины "Киевский политехнический инсги- Tvf Ес можно рассматривать как учебное пособие по алгоритмизации и программированию вообще и как краткий справочник по процедурам и функциям языка Turbo Pascal 7.0. В книге, наряду с описанием всех синтаксических конструкций языка, детально рассматриваются такие общие для всех языков программирования темы как структуры данных, классические управ- ляющие конструкции, рекурсия, способы и механизмы передачи параметров, алгоритмы сорти- ровки и поиска Особое внимание уделено объектно-ориентированной методологии разработки программ и созданию динамически загружаемых библиотек (DLL). Рассмотрению стандартных приемов управления устройствами IBM-совместимых ПК посвящен отдельный раздел. Сделан акцент на нововведениях языка версии 7.0. Все вопросы рассматриваются на большом количе- стве примеров В приложениях приведено описание процедур и функций стандартных модулей и описание интегрированной среды разработки Turbo Pascal 7.0. Данное издание является стереотипным пятому, в котором была существенно расширена тема "Динамические структуры данных”, а также переработаны и дополнены контрольные вопросы и задания Книга может быть полезна всем, кто изучает и использует язык Turbo 2404010000-02 Без. объявл. 99 ББК 32.973-01 ISBN 966-7140-15-6 © А. И Марченко. Л Л Марченко. 2000 © Оформление ТОО "ВЕК+ ", 2000
ПРЕДИСЛОВИЕ РЕДАКТОРА Мировой и отечественный опыт подготовки специалистов в области компьютерной науки и компьютерной инженерии подтверждает целесооб- разность и эффективность такой концепции в организации профессиональ- ного компьютерного образования, когда основные учебные дисциплины, относящиеся к различным (программному, структурному, операционному, логическому и электрическому) иерархическим уровням процессов обработки информации, изучаются параллельно Общепринятым также стал такой подход к изучению программного уровня, когда его начала закладываются учебными дисциплинами “Программирование” и “Алгоритмы и структуры данных” Выпущенная в 1996 году книга “Программирование в среде Borland Pascal 7 0” и ее последующие издания, вышедшие в 1997 году (второе и третье издания), в 1998 году (четвертое издание) и в 1999 году (пятое изда- ние) под названием “Программирование в среде ТшЬо Pascal 7 0”, пред- назначалась, главным образом, для студентов вузов в качестве учебного пособия при изучении первой из вышеназванных дисциплин Построенная в стиле официальных сообщений ведущих мировых фирм о новых разработ- ках программно-языковых средств, она была снабжена необходимыми методическими дополнениями контрольными вопросами и могла служить не только дидактически строгим пособием, но и скрупулезно точным справочником Книга имела заслуженный педагогический и коммерческий успех что определило решение о ее очередном, шестом по счету, переиздании Настоящее издание является стереотипным пятому, которое было сущест- венно переработано в методическом плане пересмотрены и дополнены контрольные вопросы и задания Кроме того, значительно была расширена глава о работе с динамическими структурами данных, в частности использо- вание линейных списков различной конфигурации Авторы и редактор рассчитывают на благосклонное внимание читателей- пользователей и благодарны за конструктивную критику, которую можно направлять как в адрес издательства ‘ВЕК + ’ , так и в адрес кафедры СКС НТУУ КПИ” — 252056, Киев, пр Победы, 37 Редактор, доктор технических наук, профессор Тарасенко В П
ЧАСТЬ 1 ОБЗОР ЯЗЫКА TURBO PASCAL 7.0 ГЛАВА 1 УПРОЩЕННАЯ МОДЕЛЬ КОМПИЛЯТОРА 5 ГЛАВА 2 НАБОР СИМВОЛОВ, ЛЕКСЕМЫ РАЗДЕЛИТЕЛИ 10 ГЛАВА 3 СТРУКТУРА ПРОГРАММЫ 22 ГЛАВА4 ОПЕРАЦИИ И ВЫРАЖЕНИЯ 59 ГЛАВА 5 ОПЕРАТОРЫ 74 ГЛАВА 6 МОДУЛИ 92 ГЛАВА 7 ДИНАМИЧЕСКИ СВЯЗЫВАЕМЫЕ БИБЛИОТЕКИ 99
ГЛАВА 1 УПРОЩЕННАЯ МОДЕЛЬ КОМПИЛЯТОРА Перевод программ, написанных на языках программирования высокого уровня, к числу которых относится и язык Turbo Pascal, входящий в состав профессионального пакета разработки программ Borland Pascal with Objects 7 0 на язык машинных кодов, выполняемых компьютером, осуществляется специальными программами которые называются трансляторами По способу работы трансляторы делятся на компиляторы и интерпретаторы Трансляторы языка Pascal от самых ранних реализаций до последней версии ТшЬо Pascal 7 0 работают по компили- рующему принципу Для более глубокого понимания базовых конструкций языка Tuibo Pascal, кратко рассмотрим упрошенную модель компилятора, показанную на рис 1 1 Рис 1.1. Упрощенная модель компилятора 1.1. ЛЕКСИЧЕСКИЙ АНАЛИЗАТОР Исходная программа на языке высокого уровня (ЯВУ) представляет собой цепочку символов, образуемую последоватепьным сцеплением всех строк программы Среди допустимых для языка символов всегда выделяют несколько, так называ- емых символов-разделителей благодаря которым предложения исходной программы разбиваются на отдетьные слова Такие слова в теории компиляции называются гексемами Например предложение (оператор) for г 1 to -do Nr будет разбито на лексемы for t / to n do Ит/fe/n ( i )
„„jcic.uimcM используется символ "пробел" Олнако мо*,. I.ir ci. « коТорыми лексемами пробел не стоит. Это связано с тем ымеииь. ото межлУ м1Яющся разделителячи и поэтому для отделения их от других что ста ккссмыса. разделители использовать не обязательно, хотя и лексем специальны самое предложение без изменения смысла можно бЬИГ] допустимо Например, бы записать так for 2 = 1 to п do Uriteln ( 1 ); 4 Общее правило. ^ГаиГгпе может стоять один символ-разделитель, допускается любое коли- чество символов-разделителей Однако это правило не распространяется на лексемы-разделители, поскольку они несут определенную смысловую нагрузку 1.2. СИНТАКСИЧЕСКИЙ АНАЛИЗАТОР Синтаксический анализатор на основе синтаксических правил грамматики языка проверяет корректность записи предложений программы и переводит последовательность лексем в последовательность внутренних кодов компилятора Эта последовательность уже отражает порядок действий, которые должен выполнить компьютер, но еше не является окончательным машинным кодом В теории компиляции разработано несколько разновидностей внутренних кодов компилятора (триады, тетрады, ПОЛИЗ, деревья, атрибутированные деревья, p-код), однако их рассмотрение выходит за рамки упрошенной модели. 1.3. ГЕНЕРАТОР КОДА Генератор кода осуществляет перевод внутреннего кода компилятора в окончательный машинный код компьютера 1.4. ТАБЛИЦЫ В процессе работы все рассмотренные выше блоки компиляторарбрашаются к общему набору таблиц, куда помещается как постоянная для трансляции всех программ информация (например, таблица зарезервированных слов), так и инфор- тите,ЯдтоНДИВИД^а;1ЬНаЯ ЛПЯ кахдо^ программы (например, таблицы идентификаторов. 1.5. СТРУКТУРА ПРОФЕССИОНАЛЬНОЙ СРЕДЫ РАЗРАБОТКИ ПРОГРАММ BORLAND PASCAL WITH OBJECTS 7.0 Turbo P^cal состояли₽°ЛУКТЬ1 *"рчь| Borland для разработки программ на языке стандартных процедур И3 *0МПи;,ЯТ0Ра и набора модулей, содержащих библиотеки работала в интегриповт И ^нкиий Компилятор имел две версии, одна из которых в пакетном режиме (фаил°ТРГ Ле разработки (ИСР) (файл TURBO EXE), а другая - U EXE) Новый продукт — компилятор Borland Pascal
i4Ui! o i \ mecTiicHHO отличается от всех своих предшественников Ею 4трхкпрн.1Я схемп показана на рис 1 2 Можно заметить что гпаимосвти между Споками данной схемы достаточно сложны Однако в действительности гги всшмоспязн CIUC сложнее Например. из Program Manager оболочки Windows мод иг вызвать люб\ю из трех ИСР Ввиду перегруженности схемы (рис 1 2) различными обо течениями некоторые детали реализации были опушены Как видно из схемы компилятор Borland Pascal with Objects 7 0 имсел три ИСР (TURBO EXE, BP EXE BPW EXE) и две пакетные версии (ТРС EXE и ВРС EXE) которые можно сгруппировать следующим образом • версии компилятора работающие под управлением MS-DOS в реальном режиме процессора (TURBO EXE, ТРС EXE) • версии компилятора, работающие под управлением MS-DOS в защищенном режиме процессора (BP ЕХЕ и ВРС EXE), • версия компилятора, работающая под управлением Windows (BPW ЕХЕ) Для сравнения возможностей версий компилятора Borland Pascal with Objects 7 О приведем некоторые их характеристики по одинаковому плану Версии компилятора, работающие под управлением MS-DOS в реальном режиме процессора (TURBO.EXE, ТРС.ЕХЕ) 1 Версии компилятора а) версия компилятора, работающая в ИСР (TURBO EXE), б) пакетная версия компилятора (ТРС ЕХЕ) 2. Рабочая операционная среда компилятора MS-DOS в реальном режиме процессора 3. Операционные среды, поддерживаемые выходным кодом компилятора a) MS-DOS реальном режиме процессора 4 Типы выходных файлов ЕХЕ, TPU 5 Файл основных модулеи-библиотек TURBO TPL Версии компилятора, работающие под управлением MS-DOS в защищенном режиме процессора (ВР.ЕХЕ и ВРС.ЕХЕ) 1 Версии компилятора а) версия компилятора, работающая в ИСР (BP ЕХЕ), 6) пакетная версия компилятора (ВРС ЕХЕ) 2 Рабочая операционная среда компилятора MS-DOS в защищенном режиме процессора 3 Операционные среды поддерживаемые выходным кодом компилятора a) MS-DOS реальном режиме процессора, б) MS-DOS в защищенном режиме процессора, в) Windows 4 Типы выходных файлов ЕХЕ TPU ТРР TPW DLL 5 . Файл основных модулей библиотек ТРР TPL


л зммирование в среде Turbo Pascal 7 О 9 Версия компилятора, работающая под управлением Windows (BPW.EXE) 1 Версии компилятора а) версия компилятора, работающая в ИСР (BPW EXE), б) пакетная версия компилятора (отсутствует) 2 Рабочая операционная среда компилятора Windows 3 Операционные среды, поддерживаемые выходным кодом компилятора a) MS-DOS реальном режиме процессора, б) MS-DOS в защищенном режиме процессора в) Windows 4 Типы выходных файлов EXE, ТРО. ТРР, TPW, DLL 5 Файл основных модулей-библиотек TPW TPL Контрольные вопросы 1. Какие блоки входят в состав компилятора9 2. Что представляет собой исходная программа на языке высокого уровня с точки зрения компилятора9 3. Что такое лексема9 4. Что такое символ-разделитель9 5. Какие функции выполняет синтаксический анализатор9 6. Какие существуют разновидности внутренних кодов компилятора9 7. Какие функции выполняет генератор кода? 8. Какова структура профессиональной среды разработки программ Borland Pascal with Objects 7 О9 9. Какие версии компилятора входят в состав пакета Borland Pascal \Mth Objects 7 0?
ГЛАВА 2 Labop символов, лексемы, РАЗДЕЛИТЕЛИ 2.1. НАБОР СИМВОЛОВ Набор символов языка Turbo Pascal является подмножеством набопч кода ASCII. ₽ си™оло, . Прописные и строчные буквы латинского алфавита а такж подчеркивания, который используется наравне с буквами ' СИМВоЛ ABCDEFGHIJKLMNOPQRSTUVWXYZ I (коды ASCII от 65 до 90) abcdefghijklmnopqrstuvwxyz (коды ASCII от 97 до 122) (код ASCII 95) ♦ Арабские десятичные цифры. 0123456789 (коды ASCII от 48 до 57) • Специальные символы (в скобках указан код ASCII) # (35) S (36) (39) < (40) ) (41) * (42) + (43) (44) (45) (46) / (47) (58) 1 (59) < (60) (61) > (62) <а> [ 1 { I (64) (91) (93) (94) (123) (125) * Символ Пробела (Код ASCII 32) • Управляющие символы (коды ASCII от 0 до 31). л<:С11 и все символы расшиР^ Остальные символы основного набора кода Аэ ппименякугся * ного набора кодов ASCH (включая буквы кириллицы) использоваться построения лехсем. ни для их разделения Однако они мтаоиЯх. что позволь символьных и строковых константах, а также в комме реализовать диалог пользователя с komiha^-t на русском яз
г(\ ^рзммиро«лние в среде Turbo Pascal 7 0 2.2. ЛЕКСЕМЫ Лексемами называют минимальные значимые единицы текста программы. Строго говоря, в теории трансляции между терминами “символ" и “лексема”, как правило, различия не делают. Учитывая достаточно устоявшееся в литературе по программированию отношение термина “символ" к набору символов кода ASCII, в данной книге этот термин будет использоваться именно в таком смысле А при описании лексических единиц грамматики языка (идентификатор, зарезервированное слово и т.п.) будет использоваться термин “лексема". В языке Turbo Pascal можно выделить несколько категорий лексем, которые показаны на рис. 2.1. | лексемы"] —{специальные символы] __| зарезервированные (ключевые) слова ] __| идентификаторы] —| стандартные (предопределенные) идентификаторы |пользовательские идентификаторы] [десятичные] [шестнадцатеричные | —^комментарии] идентификаторы директив идентификаторы стандартных процедур и функций Рис. 2.1. Категории лексем 2.2.1. Специальные символы К специальным символам, представляющим собой лексемы, относят + -*/< = >[]()(}- Кроме того, следующие пары специальных символов (составные символы) также являются лексемами Лексема (* эквивалентна лексеме { Лексема *) эквивалентна лексеме } Лексема ( эквивалентна лексеме I Лексема ) эквивалентна лексеме |
2.2.2. Зарезер»"н~“-------------- --------- .«иные (ключевые) слова в языке Turbo Pascal имеют строго „„ 3ai>eiepeupoea н(_ может быть измерено. Поэтому описание пол, * ЛСН1КХ- назначение. идентичных зарезервированным словам, не допускаете,* тельских иденпщ ‘ ’овамИ1 записанными прописными и строчными бУк„я РаЗЛИ'^ижнем регистрах), в Turbo Pascal нс делается. Таким образом, <_„** (на верхнем Н program Program PROGRAM 4 г ,„„чать одно и то же зарезервированное слово. Указанное своие^ бУДУ^ится как к зарезервированным словам, так и ко всем идентификатор,* ИСП°Л пГечень ^резервированных слов языка Turbo Pascal приводится ниже. and goto program asm if record array iropl emen ta ti on repeat begin in set case inherited shl const inline shr constructor interface string destructor label then div library to do mod type downto nil unit else not until end object uses exports of var file or while for packed wi th function procedure xor В языке Turbo Pascal 7.0 по сравнению с предыдущей версией было; добавлено зарезервированное слово inherited, которое используется как псевдоимя для указания непосредственного предка (родителя) рассматри- ваемого объекта _ Отметим также, что другие лексические нововведения Turbo Pascal версии (функция Assigned, процедуры Break и Continue, стандартная директива Р -tie) зарезервированными словами не являются. Для подтверждения этого iipvTL М0*ГГ ®Ь|ТЬ нредложена следующая нехитрая программа, в которой указанньК 1 исполь,зуются как пользовательские идентификаторы. Program TestReserveWords uses Crt; Assigned, Break, public ; Byte- Ьедд.л yte' Assigned:=1. Continue: :"2- Writ»in («s’ ₽ubllc:=4; ------Ji^xgne^. break continue, ’ ' , public)
Writelnf Лексемы assigned break continue public ) Write-In ( HE являются зарезервированными словами ) end 2.2 3. Идентификаторы Идентификатором является последовательность букв цифр и ЗН1КО подчеркивания которая начинается с буквы или символа подчеркивания й не содержит пробелов Как и зарезервированные слова идентификаторы безразличны к регистру клавиатуры г идентификатор символ подчеркивания
, выступают в качестве имен констант, типов, ncpo^J Идентификаторы в, пррграмм „ „олей в записях. Идентификатор jW „ронсДУР. Ф>™ЦИ,’'п„ину однако значимыми явпяюгся только первые 63 сиМво^ „меть произвольную длину,----------------------------------, Правильные идентификаторы: MyVariable My_VariabIe _Stop Lab_12 _1_2_3_ Неправильные идентификаторы: MyVariable# — содержит недопустимый символ # My-Variable — содержит недопустимый символ - 1_2_3_ — начинается с цифры Пспбым случаем является ситуация, когда в разных модулях (см. главу Ь| нелны одинаковые имена. В такой ситуации используются так называем ХшХвругмые идентификаторы, в которых перед именем переменной стаж, идентификатор модуля, содержащего эту переменную^ Оба идентификатора пр, этом разделяются точкой. Квалифицируемые идентификаторы также называют уточненными Кроме указанного случая уточненные идентификаторы исполь работе с записями и объектами. г[0казано Какие из идентификаторов могут быть уточненными, а какие н на следующих диаграммах. идентификатор метки идентификатор константы идентификатор типа идентификатор переменной идентификатор процедуры идентификатор функции идентификатор программы идентификатор модуля идентификатор поля
npcwaMWipv*»™0 9 c^Wl3e Turb0 Pascel 70 _____________15 В Turbo Pascal есть две разновидное nt и китифик порог • и нпиршые (предопределенные) • ПОИ Ю1НТ(. тьскис Стандартными предопределенными идентификаторами являются hsjchi ocl\ встроенных в язык процедур и функции (Read Write Sin и др) типов (Integer Real Char и др ) и директив (absolute, forward, private, public и др ) Переопределение стандартных идентификаторов в принципе допускается однако нужно иметь в виду, что в этом случае их стандартное действие будет для данной программы утеряно Поэтому, такие переопределения считаются в программировании плохим стилем Некоторые из стандартных директив, учитывая специфику их применения называют также процедурными директивами Перечень стандартных директив Turbo Pascal 7 0 приводится ниже absolute assembler (процедурная директива) export (процедурная директива) external (процедурная директива) far (процедурная директива) forward (процедурная директива) index interrupt (процедурная директива) near (процедурная директива) private public resident virtual (процедурная директива) В отличие от предыдущих версии введена новая директива public которая обозначает начало раздела описания общей (интерфейсной) части объекта Эта директива используемая совместно с введенной в шестой версии Turbo Pascal директивой private позвотяет создать структуру объекта аналогичную струк- туре модутя 2.2.4. Метки Метки в Turbo Pascal бывают двух разновидностей числовые и символьные Чистовая метка представляет собой последовательность цифр в диапазоне от 0 до 9999 Начальные нули не являются значащими Числовые метки поддерживаются всеми реализациями языка Pascal Turbo Pascal как и некоторые др\гие расширенные реализации позволяет в качестве меток испотьзовать идентификаторы которые подчиняются вышеприведенным правилам записи Метка отделяется от оператора симвоюи двоеточия ( )
Набор сомаороа похспми 2.2.5. Числа ° Turbo Pascal используются целые десятичные числа, целые шестнад^ В Lira и вещественные десятичные числа Причем вещественные чад пч’т™‘ пХгавлены в двух различных формах записи, обычной и показательной М°^ Ниже приведены синтаксические диаграммы для записи чисел ЧИСЛО со знаком число без знака
чр -г чымируепни* и Turbo Pascal 7 О мзгш габный множитель последовательность Цифр последовательность Цифр последовательность шестнадцатеричных цифр Целые десятичные числа записываются стандартным образом и должны находиться в диапазоне от —2147483648 до 2147483647 35 77 -39 9 -6428 Для обозначения шестнадцатеричных целых чисел используется символ $, который ставится перед числом $0 S3E SFCB5434 SA10
,„,яион шестнадцатеричных чисел от JOOOOQooo Я допустимый Диа • минус) шестнадцатеричного числа onp^Ji SFFFFFFFF ?Тнси и зависит от значения старшего разряда двоичного самой формой зап славления числа записываются или в виде обычной десятичной Доик Вещественные ж основанием 10 При втором способе записи bS и в показательно» Ф буква Е (прописная или строчная). непосредственно*! кХойТказывается показатель степени.. 6 3 -1436.9456 7.9Е12 -34.83е7 0.2745е-10 ц тая С десятичными точками или показателем степени являются констану вешественного типа, остальные десятичные и шестнадцатеричные числа являк^ константами целого типа. 2.2.6. Строки Строка символов представляет собой последовательность символов и, расширенного набора символов кода ASCII, заключенную в одиночные кавычки Необходимо также, чтобы вся последовательность располагалась в одной строК( программы В случае если в состав строки необходимо включить символ одиночной кавычки, то этот символ печатается два раза подряд Если между кавычками нет ни одного символа, то такая строка считается пустой и ее длина приравнивается нулю ‘Turbo Pascal 7.0' ’Н.Вирт — автор языка Pascal’ 'Две водрвд кавычки " считаются в строке одним символом Управляющие символы в строке представляются в виде целого десятичного числа, непосредственно перед которым ставится символ # Указанное десятичное число должно быть кодом ASCH требуемого управляющего символа # 7 — символ "звонок'’ # 10 — символ "перевод строки" # 13 — символ "возврат каретки" В принципе, таким образом могут быть представлены не только управляют# символы, но и любой другой символ кода ASCII (Коды от 0 до 255) Кроме того, в строке допускается совмещать печатные и управляющие символы Если в строк) 1ит^ейСС*'ОЛЬКО Уг,РавляюШиХ символов, то между ними не должно быть разде ----печатных символов’#13#10’и управляющих’# 13# 10
Про премирование в среде Turbo Pascal 7 0 19 2.2.7. Комментарии Комментарий представляет собой фрагмент текста программы, ограниченный ciesa символом { или составным символом (*, а справа — символом } или составным символом *) Комментарии выполняют в программе чисто информационную функцию и служат для описания назначения отдельных подпрограмм типов, кон- стант, переменных и тп Комментарии игнорируются компилятором и не влияют на работу программы Следующие конструкции представляют собой комментарии { Комментарием может быть любая последовательность символов, ограниченная с двух сторон фигурными скобками, независимо от того, сколько строк она будет занимать. } (* Последовательность символов в круглых скобках со звездочками также является комментарием *) Особым случаем является комментарий, в котором непосредственно после открывающей скобки, { или ('. следует символ доллара $ Такой комментарий яв- ляется директивой компилятора {$N+} (*$R—*) {$1 MyFile.pas)
Набор символов лексемы 2.3. РАЗДЕЛИТЕЛИ в качестве разделителей лексем друг от друга во всех реализациях ЯЗЬ1|Ц Pascal применяются символы . пробел (код ASCII 32); . табуляция (код ASCII 09), составной символ перехода в начало следующей строки (пара символов “возврат й. ' р“™< (код ASCII 13) И “перевод строки (код ASCII 10)) В Turbo Pascal кроме этих “классических" разделителей, могут использовать^ любые управляющие символы набора кодов ASCII из диапазона от символа с кодом О ло символа с кодом 31. Например, показанная ниже программа вполне работоспособна В ней между лексемами program и Test стоит управляющий символ с кодом 24, меЧ) лексемами var и А стоит управляющий символ с кодом 25, а между лексемами begin и А стоит управляющий символ с кодом 21 programTles t ; variA:Integer; begin§A:=1; Wrxteln(A) end. Заметим, что хотя такие символы в текстах программ допустимы, их ис- пользование считается плохим стилем в программировании Между любыми двумя лексемами допускается произвольное количество символов-разделителей Кроме того, лексемы группы “специальные символы” (см рис 2 1) сами являются разделителями и, следовательно, отделение их от других лексем символами-разделителями не обязательно В предыдущем примере таковыми являются символы : , ( , ) и составной символ = Контрольные вопросы 1 2 3 4 5 6 7 8 9 10 И 12 13 14 15 На какие группы можно разделить набор символов языка Turbo Pascal9 Что такое лексема9 Какие категории лексем вам известны9 Допустимо ли использование в качестве пользовательских идентификаторов зарезервированных слов Turbo Pascal9 Что представляет собой идентификатор9 акая допустимая длина идентификатора9 чем заключается разница между идентификатором и валифицируемым (уточненным) идентификатором9 **Ис из идентификаторов могут быть уточненными9 к *е сушсствУ^ разновидности идентификаторов9 е идентификаторы являются стандартными9 К Пр?стаа1Яст собой метка9 Какой ^>₽МЫ Записи чисел используются в языке Turbo Pascal’ Чтл п мвол исг,ользуется для обозначения шестнадцатеричных чисел' Ч1о ВЛЯеТ СТР°“ символов’ ° п₽«<таияет собой комментарий’
программирование в среде Turbo Pascal 7 Q 1б Клкие символы используются в качестве разделителей лексем’ 17 Какое количество символов-разделителеи допускается между любыми двумя лексемами9 Контрольные задания I. Укажите неправильные идентификаторы a) Center б) Month-Week в) __Year г) Monday®Sunday д) __Thxs^a_Bad__Identxfxer__ е) 7Colors ж) 3 з) #5 и) _ 2. Укажите неправильные числа а) -51478е+20 б) 1,12 в) 1е12 г) 0е2 д) е7 е) 0 5 ж) 5. з) 4 и) $2 к) 100$
ГЛАВА 3 СТРУКТУРА ПРОГРАММЫ Синтаксические диаграммы обшей структуры программы на языке -ц Pascal имеют такой вид Неформально структуру программы можно показать следующим образом { Г Заголовок программы 1 program Имя_Программы, { II Раздел указания используемых модулей } uses Список_Испольэуемых_Модулей, ( III Раздел описаний } label Описания__Меток, const Описания Констант, type Описания_Типов var Описания^Пераменных, procedure | Описания__Процедур_и_Функций fиле ti on J exports ОписаниЯ—Экспортируемых Имен begrn Раздел операторов lОператорный блок) } Оператора; end 3.1. ЗАГОЛОВОК ПРОГРАММЫ версиях " Tllrbo PdScal 7 0 также, как и во всех предыДУш’“ же присутствует и ппл И ИСлользУстся в декоративных целях Однако, если он & грамме, то должен быть записан синтаксически корректно
।мми/чмммие в сроде Turbo Pascal 7 О 23 заголовок программы program )—и идентификатор параметры программы параметры программы список идентификаторов Примеры: program Simple; program Print (Output); program GetPut (Input, Output); program Complex (Input, Output, MyFile); Заметим, что вследствие необязательности заголовка, в Turbo Pascal используется, как правило, только первый из приведенных вариантов. 3.2. РАЗДЕЛ УКАЗАНИЯ ИСПОЛЬЗУЕМЫХ МОДУЛЕЙ (Предложение uses) Раздел указания используемых модулей начинается с зарезервированного слова uses Присутствие в программе предложения uses не обязательно. Оно описывается в случаях, если в программе используются константы, типы, переменные, процедуры или функции, определенные в стандартных модулях Turbo Pascal, кроме модуля System, или в модулях, созданных пользователем Синтаксис предложения uses имеет следующий вид ГI римеры:____________________________________ uses Crt, Graph, uses Crt, Graph, Mylib, Stack; Предложение uses в каждой отдельной программе может быть описано только однократно и должно располагаться непосредственно после заголовка программы Стандартный модуль System всегда используется по умолчанию и указывать его в предложении uses не нужно Этот модуль поддерживает такие средства, как файловый ввод-вывод, обработка строк, операции с плавающей запятой, динами- ческое распределение памяти Остальные стандартные модули Turbo Pascal, такие
11 ^Учае к ik Dos Crt Graph и другие автоматически не подключаются и зования обязательно указываются в предложении uses J ’“с При поиске кода требуемого модуля во время трансляции. комлилЯТп указанное в предложении uses имя модуля до первых восьми символов и расширение файла Если плевой платформой компиляции (см рис } 2 ] °%. DOS. добавляется расширение TPV Если целевая платформа — Winj^ расширение TPW Если целевой платформой является защищенный Ре то расширением файла будет ТРР Хотя имена файлов усекаются, в Лр Им uses должен указываться полный идентификатор модуля 3.3. РАЗДЕЛ ОПИСАНИЙ раздел описаний также как и предыдущие разделы является не обязателцп. Однако без его использования можно написать только самые примитивные граммы Подразделы описания констант (const), типов (type), переменных (Var процедур (procedure). функций (function) и экспорта (exports) могут повторяв многократно в рамках раздела описаний в любом порядке Необходимо следить^ за выполнением следующего правила Правило: ____________________________________________________ А Если в описании какого-либо элемента В (константы, типа, переменной F_JT процедуры функции списка экспорта) используется элемент А (констант, тип и т д ) то элемент А должен быть описан перед элементом В Подраздел описания экспорта exports поддерживается только версиям компилятора, использующими защищенный режим процессора те BP ЕХЕ ВРС EXE. BPW ЕХЕ (см рис 1 2 ) Многократное использование одинаковых подразделов описания применяете как в необходимых случаях, чтобы выполнить требования приведенного правила так и для улучшения структурированности описаний и повышения читабельности программы Например,
Программирование в среде Turbo Pascal 7 О 25 3.3.1. Описание меток Синтаксическая диаграмма описания раздела меток приведена ниже раздел описания меток Метки могут прет пустовать пюбому оператору программы и отделяются от операторов двоеточием ( ) Используются метки совместно с операторами перехода goto в которых метка записывается без двоеточия Например label 1 Quit goto 1 1 а = 1 goto Quit Quit end
26 меток без обращения к ним оператором goto бессмысленно Л “ Описание ме ОтМетим такжс что использование меток и опср’^ ошибкой не с™™е противоречит принципам структурного программна * • 9»е° в большинстве е прнменсни(, этих коНструкций „ програм^Ч • и поэтому рекомендуй , 3.3.2. Описание типов Синтаксис подраздела описания типов имеет вид раздел описания типов описание типа При дальнейшем изложении данного подраздела авторы не придерживались иерархии синтаксических правил, описывающих понятие “тип' Поэтому соответ ствуюшие ему синтаксические диаграммы приведены отдельно в конце подраздел! Множество типов языка Turbo Pascal можно разделить на две группы • стандартные (предопределенные) типы, • типы, определяемые пользователем (пользовательские типы) Имена стандартных типов являются предопределенными идентификаторами (не путать с зарезервированными словами’) и действуют в любой точке программы В действительности они описаны в стандартном модуле System который по умол- чанию подключается в список используемых модулей каждой программы и каждого пользовательского модуля независимо от того указан он в разделе uses или нет Также как и другие предопределенные идентификаторы имена стандартных типов могут быть переопределены в программе Однако и после этого остается возможность обращения к их первоначальному смыслу с помощью квалифицируемого идентификатора с указанием имени модуля System Например,________________________________________________ System Integer System Real System Char Пользовательские типы — это дополнительные абстрактные (простые к структурированные) типы характеристики которых программист-пользователь мо*^ определять самостоятельно Использование таких типов позволяет программист ясиее и точнее описывать поставленную задачу, а компилятору предоставляв инФ°рмации для проверки синтаксических ошибок и генерирования боч* эффективного машинного кода Стандартные типы к станОартным типам Turbo Pascal относят • тр>пп\ ЕешестТ^ПОВ (Short,nt Integer, Lon gull Byte, Word) иных типов (Single, Real, Double Extended Comp)
\\'['вммирование в среде Turbo Pascal 7 О 27 • группу булевских типов (Boolean, Byte Bool, Word Bool. LongBool). • символьный тип (Char); • строковые типы (String, Pcliar); • указательный тип (Pointer); • текстовый тип (Text). Типы ByteBool, WordBool, LongBool и PChar являются нововведением Turbo Pascal версии 7.0. Символьный тип, а также целые и булевские типы относят к. так называемым. порядковым типам. Порядковые типы характеризуются следующими четырьмя свойствами. • Множество допустимых значений любого порядкового типа представляет собой упорядоченную последовательность, каждый элемент которой имеет свой порядковый номер. Порядковый номер представляется целым числом. Первое значение любого порядкового типа имеет порядковый номер 0, следующее значение имеет порядковый номер 1 и так далее. Исключение составляют порядковые типы Integer. Shortint и Longint. Порядковым номером значений этих типов является само значение. • К любому значению порядкового типа можно применить стандартную функцию Ord. возвращающую порядковый номер этого значения. • К любому значению порядкового типа можно применить стандартную функцию Fred, возвращающую значение, предшествующее этому значению. Если эта функция применяется к первому допустимому значению любого порядкового типа, кроме булевских, то возвращается порядковый номер последнего значения. • К любому значению порядкового типа можно применить стандартную функцию Succ. возвращающую значение, следующее за указанным Если эта функция применяется к последнему допустимому значению любого порядкового типа, кроме булевских, то возвращается порядковый номер первого значения Свойства порядковых типов и работа функций! Pred и Succ демонстрируются следующей программой program TestStandardOrdinalTypes; uses Crt; var 1 Целые типы ) i: Integer; si: Shortint; 11: Longint; bt: Byte; w: Word; ( Булевские типы } b: Boolean; wb: WordBool; bb: ByteBool; lb: LongBool; ( Символьный тип I с : Char; begin ClrScr; i:®10; si:a0; li:e-30; bt:e255; w:=0; Writeln ('Integer: ',Pred(l):5, 1:5, Succ(1):5); Writein ('Shortint- • , Pred (si) • 5, si-5, Succ(si):5); Writeln ('Longint. ‘,Pred(li):5, 11:5, Succ(ll):5), Writeln ('Byte: ’,Pred(bt)’5, bt:5, Succ(bt):5): Writeln ('Word: ’,Pred(w) 5, w5, Succ (w) : 5) .
Г -True wb:=False; ЬЬ : =True; lb:=Falss, Mr,tain’('Boolean :', Pred(b).7, b:7, Succ(b) 7); ” t 1 /WordBool:', Pred(wb)-7, wb. 7, Succ(wb)-7), " ln ( ' ByteBool: , Pred(bb)-7, bb : 7 , Succ (bb) . 7) , wnteln ( ' LongBool: ' , Pred(lb)-7, lb : 7 , Succ(lb):7), c = 1 b ' Britain (’Char: -,Pred(c):5, c:5, Succ(c).S); Wrxteln; end _________ Результаты: Integer: 9 10 11 Shortint -1 0 1 Longint: -31 -30 -29 Byte: 254 255 0 Word: 65535 0 1 Boolean FALSE TRUE TRUE WordBool TRUE FALSE TRUE ByteBool FALSE TRUE TRUE LongBool TRUE FALSE TRUE Char: a b c Группа целых типов В Turbo Pascal включены пять типов для описания переменных и констант представляющих целые числа Их характеристики приведены в таблице 3 1 Таблица 31 Название типа Идентифи- катор Диапазон представления чисел Размер памяти Короткое целое со знаком Shortint -128 127 1 бант Целое со знаком Integer -32768 32767 2 байта Длинное целое со Жаком Longint -2147483648 2147483647 4 байга Короткое целое Жака Byte 0 255 1 бант 1 юе без Word 0 6553S 2 байта
Программирование в среде Turbo Pascal 7 О 29 Группа вещественных типов В группу вещественных типов входят пять типов, показанных в таблице 3 2 Таблица 3.2 Название типа Идентификатор Диапазон пред- ставления чисел Значащие цифры мантиссы Размер памяти Вещественное одинарной точности Single от 1 5- 10”4S до 3 4’ 1О’К 7 8 4 байта Вещественное Real от 2 9* 10 ” до 1 7- 1018 И 12 6 байтов Вещественное двойной точности Double от 5 0* 1 О-12** — 1 ,*> Т08 до 1 7*10 15 16 8 байтов Вещественное повышенной точное ги Extended от 3 4- 10 4“: ,ю 1 1 - 104’1: 19 20 10 байтов Целое в формате веществен ного Comp от — 2f,t + 1 до 2Ь - 1 или приблизительно от -9 2*10"* до 9 2* 10)Ч 19 20 8 байтов В зтой труппе необходимо выделить тип Comp, который является своеобразным гибридом” целого и вещественного типов С одной стороны, i и константы этого типа могут иметь только целые значения (свойств» ' С другой стороны, тип Comp, в отличие от целых типов, не являете,. , »м (свойство вещественных типов) Соответственно зтому, типу Comp не присущи нижеприведенные свойства порядковых типов и полому его относя г к группе вещественных типов Точность представления мантиссы каждым из типов может пить продемонстрирована следующей программой program TeatR«*lTyp«a, иааа Crt, r Raal, a Single, d Double • Extended, c Comp begin ClrScr
30 s d Структура npmp9t —?ЙМ012зПб7в90^-30 -Л^ИГ190123<56?990е-30 " 1 23,|«7М0123456-7в90о-30 = 1 23^aK7S901234567090е—30 Г 1 2345670901234567090о—30 writeln Writein Wrxteln Writein ( Single ( Real { Double {'Extended (1 Comp g 32) , 32) d 32) e 32) , 32) and . - — 1 1r^P^MC Tочности дробная константа высокой точност! каждого из вещественных типов присваивается после чего значения переменных выводяТСд на печать Результаты Single Real Double Extended Comp 1 23456792604715494E-0030 1 23456799012369172E-0030 1 23456789012345682E-0030 1 23456789012345679E-0030 0 oooooooooooooooooe+oooo Как видно из этих результатов сначала нарушается корректность представления константы для переменной типа Single затем для переменной типа Real н так далее Переменная же типа Comp окрупяет дробное число до ближайшего целого Turbo Pascal поддерживает две модели генерации кода для выполнения действия над числами вещественных типов • аппаратную (прн наличии сопроцессора 80x87), • программную (при отсутствии сопроцессора 80x87) Выбор соответствующей модели осуществляется с помощью директив компитятора $N и $Е В состоянии (SN-) которое устанавливается по умопчднию генерируется код который может выполнять вычисления только с одним вещественным типоч Rea! Причем вычисления в этом случае реализуются программно через вызов подпрограмм бибтиотеки времени выполнения В состоянии {$N+} генерируется код который выполняет все вычисления над вещественными типами с помощью чистового сопроцессора 80x87 Такая установка директивы позволяет испотьзовать все пять вещественных типов Pav»i Кр°?е нспосрсдствснной работы с сопроцессором 80x87 в языке Turbo ает ВОЗМОАМОСТЬ подключения библиотеки времени выполнения которая Подключением ^-ЛИРус1 Действии сопроцессора в случае если он отсутствует отметить что димк^^р0™" уПравляет Д»Р«тива компилятора $Е Следует Windows j икже ппи „ Не (мб<’гает ПРН генерации выходного кода в режиме В состоянии (SF + 1' иляини отдельных модулей без общей компоновки на компьютере сопроцесс КОМПНЛЯТОР Turbo Pascal сначала проверяет установлен ли ванный компилятором колб ЕсЛИ соп₽оисссоР присутствует то сгенериро- то выходной кот компипит УЗ' Т СГ° НС,,О1Ьювать Если сопроцессор не установлен В состоянии ИЕн₽ 3 ЙУЛСТ>МуЛ|1ро11‘"''е, о работу' сопроцессора «0x87 генерируется кот который нс поддерживает эмуляцию
jPMP,«Uu^«o * ‘ Turb° Pasca' 7 °---—-------------------------------- ПМС1НМ также некоторые особенности совместного испольюп <ни г гире» шн ( 5Е Гели установлены обе директивы {SN+ Е+), то для вычислений с менными вещественных типов будет сгенерирован наиболее быстродействующий одной код независимо от того, установлен в компьютере сопроцессор или нет Пои'установке {$N + , Е~}, компилятор подключит только библиотеку, которая выполняет вычисления непосредственно с сопроцессором 80x87 В состояниях С\- SE+1 и ($N“, $Е-} директива $Е игнорируется Группа булевских типов Все реализации языка Pascal, в том числе и Turbo Pascal вплоть до версии 6 0, содержали только один булевский тип Boolean, элементы которого могут принимать лишь два логических значения True (истина) и False (ложь) В Turbo Pascal версии 7 0 добавлены еще три булевских типа ByteBool. WordBool и LongBool Характеристики булевских типов приведены в таблице 3 3 Таблица 3 3 Идентификатор типа Значению False соответствует Значению Т)ие соответствует Размер памяти Boolean число 0 любое число отличное от 0 1 байт ByteBool чисто 0 1 байт WordBool число 0 в обоих байтах 2 байта LongBool число 0 во всех байтах 4 байта Отметим, что новые булевские типы были введены для обеспечения совместимости разрабатываемых программ с оболочкой Windows в которой значению False соответствует число 0 а значению True — любое число, отличное от 0 Результирующим типом операций сравнения и логических операций по прежнему остается тип Boolean Работа встроенных функций Ord. Pred и Succ с переменными как “старого типа Boolean, так и новых булевских типов демонстрируется следующими ДВ)МЯ программами program Testl_BoolTypes (Тест демонстрирует работу функций Ord, Pred и Succ с } (каждый из булевских типов при выводе значений, возвра-} (щаемых функциями, непосредственно процедурой Writeln } uses Crt < $R+} var b Boolean ЬЬ ByteBool wb WordBool, lb LongBool, procedure PrintBooleans, begin Writeln ('Boolean Pred(b) b Succ(b> ) Writeln ('Значение Predfb) 9 b 9 Succ (b) 9) Writeln (’Ord() ', Ord(Pred(b) ) 9 Ord(b) 9 Ord(Succ(b)) 9) Writeln ('ByteBool Pred(bb) bb Succ(bb)')
Структура,,,, Writeln Writeln Writeln Writeln :9) ; writein ('Значение:'. Prod(ЬЬ):9. ЬЬ : 9 , Succ(ЬЬ)9); Ordered (bbj ) :9.Ord(bb) : 9 , Ord (Succ (ЬЬ) ) , 'WordBool Pred(wb) wb Succ (wb) (Значение:'' Pred(wb):9, wb:9, Succ(wb) { ' Ord () •’ ’ ' Ord(Pred(wb)) : 9) , :9,Ord(wb):9, Ord(Succ(wb)) : 9) , Writeln Writeln Writeln (LongBool Pred(lb) lb Succ(lb)'); ('Значение; ' , Pred(lb):9, lb:9, Succ(lb):9) {'Ord() : ’ < Ord(Pred(lb) ) : 9, Ord (lb) : 9 , Ord (Succ (lb) ) : 9) ; end; begin ClrScr; b.-=False; wb:=False; bb:=False; lb:=False; Writeln ('Исходное значение : False'); PrintBooleans; Writeln ('Исходное значение : True'); b:=True; wb:=True; bb:=True; lb:=True; PrintBooleans; end. Результаты: Исходное значение False Boolean Pred(b) b Succ(b) Значение TRUE FALSE TRUE Ord() : -1 0 1 ByteBool Pred(bb) bb Succ(bb) Значение: TRUE FALSE TRUE Ord{) -1 0 1 WordBool Pred(wb) wb Succ(wb) Значение: TRUE FALSE TRUE Ord() : -1 0 1 LongBool Pred(lb) lb Succ(lb) Значение: TRUE FALSE TRUE Ord {) -1 o Исходное значение : True Boolean Значение: Ord{) ByteBool Значение. Ord() WordBool Значение: Ord() Pred(b) FALSE 0 Pred(bb) FALSE 0 Pred(wb) FALSE Q b TRUE 1 bb TRUE 1 wb TRUE Succ(b) TRUE 2 Succ(bb) TRUE 2 Succ(wb) TRUE LongBool Значение Ord() Pred(lb) FALSE 0 1 lb TRUE 1 2 Succ(lb) TRUE О
ммирование в среде Turbo Pascal 7 О 33 program Test2_BoolTypes (Тест демонстрирует работу функции Ord, Pred и Succ с ) (каждым из булевских типов при выводе значении, возвра-} (щаемых функциями, после присваивания этих значении не-} (ременным соответствующих типов ) uses Crt. ($R+) var pb,b,sb Boolean. pbb,bb,sbb ByteBool pwb.wb,swb WordBool plb,lb,slb LongBool procedure PrintBooleans begin pb =Pred{b). sb =Succ{b). Writeln (’Boolean Pred(b) b Succ(b)') Writeln (’Значение ’, pb 9, b 9, sb 9) Writeln (’Ord() Ord(pb) 9, Ord(b) 9, Ord(sb) 9), pbb =Pred(bb) sbb =Succ{bb) Writeln {'ByteBool Pred(bb) bb Succ(bb)') J Writeln {'Значение ’ pbb 9, bb 9, sbb 9), Writeln (’Ord() Ord(pbb) 9,0rd{bb) 9,0rd(sbb) 9) pwb =Pred(wb), swb =Succ(wb), Writeln {’WordBool Pred(wb) wb Succ(wb)') Writeln {'Значение ’, pwb 9, wb 9, swb 9)r Writeln (’Ord{) ' , Ord(pwb) 9,0rd{wb) 9,0rd(swb) 9), plb «Pred(lb) sib =Succ(lb) Writeln { LongBool Pred(lb) lb Succ(lb)1). Writeln {'Значение ', plb 9 lb 9r sib 9), Writeln (Ord{) , Ord(plb) 9,0rd{lb) 9,0rd{slb) 9) end Begin ClrScr b «False bb «False wb «False, lb =False, end Writeln {'Исходное значение False') PrintBooleans b =True bb «True, wb =True lb «True Writeln ('Исходное PrintBooleans значение True ) Результаты Исходное значение False Boolean Predfb) b Succ(b) Значение TRUE FALSE TRUE Ord() -lo 1 ByteBool Pred(bb) bb Succ(bb) Значение TRUE FALSE TRUE Or<W 10 1 WordBool Pred(wb) wb Succ(wb) Значение TRUE FALSE TRUE 5 - 4347
Ord(} ИСХОДНО® Booled Значение: Ord(} ByteBool Значение: Ord(} WordBool Значение: Ord{} LongBool Значение: Ord{} значение Pred(b) FALSE 0 Pred(bb} FALSE 0 pred{wb} FALSE 0 Pred(lb} FALSE 0 True b Succfb} TRUE TRUE 1 2 bb Succ(bb) TRUE TRUE 1 1 wb Succ(wb) TRUE TRUE 1 1 lb Succ(lb} TRUE TRUE 1 1 Из этих примеров видно, что функции Ord. Pred и Succ со всеми булевскими типами работают одинаково (первая программа). Причем функция Ord для значения False возвращает порядковый номер 0, а для значения Тте — десятичное значение числа, записанного в соответствующей булевской переменной Отличие новых булевских типов от классического Boolean проявляется после присваивания результата функций Pred и Succ переменным соответствующих типов (вторая программа) В этом случае для переменной типа Boolean при значении True функция Ord по прежнему возвращает десятичное значение числа, записанного в этой переменной А для переменных типов ByteBool. WordBool и LongBool при значении True функция Ord всегда возвращает значение 1. Заметим также, что при выполнении всех приведенных во второй программе присваиваний ошибка выхода за пределы допустимого диапазона значений не происходит ни при какой установке директивы компилятора SR Символьный ТИП Символьному типу соответствует стандартный идентификатор Char ^ременные и константы символьного типа могут принимать значения из множества символов кода ASCII (см. приложение 4). Значение кода требуемого символа можно получить при помощи функции Ord Обратные действия определения тип^Сь П° 3аЛаНН0МУ К°ДУ выполняются функцией Chr Кроме того, к значениям Pred ^Г’ И К значсниям ДРУГИХ порядковых типов, применимы также функции Строковые типы стандартны:ГтмппСИк1Я структуР Данных строковые типы, в отличие от други» использование croot яадяются структурными типами Однако, учитывая широкое типы String и PChar В программиР°вании. о Turbo Pascal для них введены стандартны* Я1ыка Turbo Pascal ^иППт*^к1СС П° тсксту Stnng-сгроки) реализованы во всех Еи-рсмях ' рслыдущмх версиях ° Uf°° 7 0 они ничем не отличаются от реализм
i,v> ^аммирование в среде Turbo Pascal 7 О [Строки типа PChar являются нововведением Turbo Pascal версии 7 0 | Тип PChar поддерживает формат представления строк, признаком конца которых служит символ с кодом 0 (нуль) и которые называются строками с завершающим нулем или ASCIIZ-строками Такие строки используются в Windows, и поэтому для облегчения создания программ, работающих под управлением Windows, ASCIIZ-строки были добавлены в Turbo Pascal Необходимо отметить, что хотя тип PChar введен для поддержки строковых структур данных, фактически он является указательным типом с описанием type PChar = ''Char; Переменные же этого типа (при установленной директиве компилятора (SX+1) обрабатываются как массив типа array [0..К] of Char; где К — количество символов в строке, не считая символа — признака конца строки Указательный тип Стандартный указательный тип имеет идентификатор Pointer Значениями переменных и констант указательного типа являются адреса оперативной памяти, состоящие из адреса сегмента (1 слово ~ 2 байта) и смешения (1 слово ~ 2 байта) Адрес сегмента хранится в старшем с юве. а смешение — в младшем слове полного адреса Элементы типа Pointer в отличие от опреде1яемых пользователем указатедьных типов могут содержать адрес переменной любого типа Текстовый тип Стандартный текстовый тип Text испотьзхется для описания текстовых файлов и рассмотрен в главе, посвященной файлам Пользовательские типы К пользовательским типам относят • перечисляемый тип ♦ интервальный тип, • указательные типы (крохк . , .1 । .м« , , u ,, ( • стРУктурированные типы, • процедурный тип Перечисляемый и интервальный типы являются порядковыми Соответственно *му им присущи описанные ранее свойства порядковых типов Остальные 'ьзоватетьские типы порядковыми не являются
Структура прогт Перечисляемый тип „„ния позволяют программисту описывать новые типы даннЬ|х Перечисления' я(_т сам программист. значения которы' Детого типа состоит из списка его элементов, заключенного . Описадие л'^(дь|й из элементов представляет собой уникальный идеи. круглые скобки тификатор________________________- type _ /Soring Summer, Autumn, Winter) ; (M°n- Hed- ThU- Fr±- Sat- Sun)-' - 6,ока, где объявлен перечисляемый тип, идентификаторы всех тав перечисляемого типа интерпретируются как константы Spring, Summer ’лем и winter представляют собой константы типа Season, a Mon, Tue, Wed' ThUIFn Sat и Sun - константы типа WeekDay Здесь необходимо обратить внимание а то что эти идентификаторы не являются строковыми константами и в кавычки не заключаются Поскольку идентификаторы перечисляемого типа являются константами для всего блока, где они объявлены, то описание одного и того *е идентификатора в разных типах считается ошибкой Так, при трансляции показанной ниже программы, будет выдано сообщение Error Duplicate identifier (Mon) program Duplicateldentifier, type WeekDay = {Mon, Tue, Wed, Thu, Fri, Sat, Sun) , WorkDay = {Mon, Tue, Wed, Thu, Fri) ; begin end Константы предопределенных типов нс могут быть значениями пере- числяемого типа Например, следующие описания некорректны type {константы числового типа} Digitals = 10,1,2,3,4,5,6,7,8,9) , п,„е (константы символьного типа) Orgsyinbola . WeekDay ^1*онстанты строкового типа) -_____1 ”°п’.’Tue', -Wed ' , Thu , Fri’ , Sat ’ , ’Sun) , они перечисленПСРеЧИСЛЯеМЫС тилы являются порядковыми, то. соответственно- Упорядочение КИСМ СВОИЧ ^лементов определяют упорядоченные наборы констант 6 которой пеоеч1<НСТаНТ В типс ВЬ|Полнястся в соответствии с последовательностью- чяемого типа оп СЛйЮтся идентификаторы Порядковый номер константы перечне Первая константаЛСЛЯеТСЯ Се позииией в списке идентификаторов при объявлен Тах Жс> * Спискс имеет порядковый номер 0. вторая - номер 1. и т л- исчисляемоготипИ * ПсРсменным других порядковых типов, к перемени ипаприменимы ИсГО^нпи,- гМ пиши С >rrl Prf-j и Suf С
Пгюгоэммиромние а среде Turbo Pascal 7 о Ord (Summer) = 1 Pred (Winter) = 2 Succ (Spring) = 1 Отметим одну “неприятную'* особенность перечисляемых типов К значениям этих типов не применимы ни арифметические операции, ии стандартные процедуры ввода-вывода Read Readln. Write, Writeln В следующей программе демонстрируется использование функций Ord, Pred и Succ для значений перечисляемого типа program TestEnumeratedTypes, type Season = (Spring, Summer, Autumn, Winter), var First,Curr Season, begin Curr = Spring; { Writeln(Pred(Curr), Ошибка, т к константы } ( Curr, перечисляемого типа ни } { Succ(Curr)), вводить, ни выводить ) { НЕДОПУСТИМО } Writeln(Ord(Pred(Curr)) 3, (Ошибки нет при любой ус- ) Ord(Curr) 3, (тановке директивы $R,t к ) Ord(Succ(Curr)) 3),(проверка диапазона выпол- } {няется при присваивании } First =Pred(Curr), { При директиве $R- ошибки нет, ) { при директиве $R+ будет ошибка) { времени исполнения ) { First =Pred(Spring), Ошибка при любой установке } ( директивы $R, т к константа } ( Spring предшествующей константы) ( не имеет } end Результаты -10 1 Интервальный тип Интервальный тип представляет собой диапазон (интервал) значений какого-тибо порядкового типа, называемого базовым При описании интервального гипа указываются наименьшее и наибольшее значения диапазона значении допус- тимых для этого типа Минимальное и максимальное значения интервала разделяются знаком (две точки) ________________________ 0 500 -1 1 -128 127 ’А' ' Z' МОП Fri
Структура про интервальною типа имеет все свойства переменных базовое Переменно' чение на этапе выполнения должно принадлежать указанной! типа однако ее MJ диапазону Указательные типы , илниЯМИ указательных величин являются адреса памяти В отличие й пго указательного типа Pointer, пользовательский указательный тип стандартно: у значений, которые указывают на динамические переменны. оХХного типа, называемого базовым типом /Тля описания указательных типов сделано одно исключение из общих правд, писания Указатель на какой-либо тип МуТуре может быть описан до объявлен», самого типа МуТуре Главное, чтобы н указательный тип, и тип, на величины которого он будет указывать, были описаны в одной и той же части объявления type PtrStack - ATStack, TStack = record Inf Real, Link PtrStack end, При работе с указательными типами используется стандартная константа ml, представляющая значение указателя, который ни на что не указывает Структурированные типы К структурированным типам языка Turbo Pascal относят • тип-массив ( array ) • тип-множество ( set ), • тип-запись ( record ), • файловый тип ( file ), • объектный тип ( object ) с посмотреть на типы языка Turbo Pascal не с точки зрения его синтаксиса а тяж» 4рсния5труктуРданнь’х используемых в программировании (каксдетанов отнести кЗССИфИКаЦИЯ данных”) то строковые типы также необходимо симвоиньХС™НРОВаННЬ1М типам Однако учитывая широкое использование синтаксически*30* В прогРаммиРовании, в Turbo Pascal строковые типы были отдельную категорию тип Диаграммь1 в к°ние подраздела "Описание типов ) в содержать^многпр°ааннь^с типы служат для описания данных которые могут ственио этому описяЧСНИИ’ а НС ТОДЬКо одно, как данные стандартных типов Соответ- чем сданными станлартнь1аННЫХ СТрУктурированнь1х ™пов н работа с ними сложнее, и, особенно по°смыглМО °™Стить объектный тип Этот тип и по синтаксису записи, типов Поэтому его зячяВОЙ Нагрузкс- гораздо сложнее других структурированных ст>ю выделяют в отдельную категорию типов
4-t Jc Turto F isc 1/ 39 Процедурный тип Процедурные типы позволяют объявлять переменные которым допуски.» ирис в inn тис имен процедур функции и методов а также передавать такие i I сменные и имена в качестве параметров Описание процедурных типов имеет практически такой же синтаксис как и объявление процедур функции и методов Отличительной особенностью процедурных типов является отсутствие идентификатора процедуры/функнии поскольку для типа конкретное имя процедуры не имеет значения Кроме того процедуры/функнии которые будут присваиваться переменным процедурных типов должны компилировать ся при включенной директиве дальнего вызова {SF+} Переменная процедурного типа представляет собой адрес памяти где размешается процедура и таким образом фактически является указательной переменной особого вида Приведем примеры описания и использования процедурных типов type TProcl = procedure ( var X У Real ) TFuncl = function ( X Integer ) Real TProc2 = procedure ( const A MyArray var Res Real ) TFunc2 = function ( I J Byte X У Char ) String program ProcTypesDemo type TMyFunc = function ( X Integer ) Real ($F+) function FirstFunc ( X Integer ) Real begin FirstFunc = SQR ( X ) end function SecondFunc ( X /2 Integer ) Real begin SecondFunc = SQRT ( X end ($F~} var MyFunc TMyFunc begin MyFunc = FirstFunc Writeln( MyFunc (16) )*2 7 2) ( Результат число 129 MyFunc — SecondFunc Writeln( MyFunc (16) 7 2) ( Результат - число 8 ) end
Синтаксические диаграммы описания типов простой тип вещественный тип порядковый тип перечисляемый тип список идентификаторов интервальный тип
чарование в среде Turbo Pascal 7 0 41 строковый тип указательный тип базовый тип структурированный
тип поля признака идентификатор порядкового типа список полей список файловый тип
шмирсшши# g среде Turbo Pascal 7 О 43 список методов наследование идентификатор типа объекта список компонент список методов заголовок метода
процедУРнЫИ тип —- I -Procedure) СПИСОК формальных параметров 3.3.3. Описание констант Синтаксис раздела описания констант имеет следующий вид раздел описания констант Простые константы Приведем синтаксические диаграммы описания простых констант описание константы —идентификатор константа ( Числовые константы I Length = 100, MxnNeg = -1; MaxKeg « -32670, Nuiab » 7 { Булевские константы ) Booll = True, Bool2 « False. 1 Символьные константы ) Char7 = ’7’ , СЪагСЯ » *13. 87е-3, Строковые жоиствиты ) 'Turbo'. Str2 . ' рввсв1.
ппогроммирование в среде Turbo Pascal 7 О 45 Кроме простых констант Turbo Pascal допускает использование константных выражений, которые могут быть вычислены во время компиляции программы Если предполагать, что нижеприведенные константы будут располагаться после вышеприведенных, то следующие объявления будут допустимыми const ChrLength = Chr(Length); Mean = (MaxNeg - MinNeg) div 2; BooLAnd = Booll and Bool2; CodeOfChar7 = 0rd(Char7); Name = Strl + Str2 + CharCR; Константные выражения описываются точно по таким же правилам, что и обычные выражения Однако перечень допустимых в константных выражениях стандартных функций ограничен следующими функциями. Abs, Chr, Hi, Length, Lo, Odd, Ord,Pred, Ptr, Round, SizeOf, Succ, Swap, Trunc Типизированные константы В отличие от простых констант, в описании типизированных указывается как значение константы, так и ее тип Типизированные константы фактически являются переменными со стати- ческим классом памяти То есть такими, которые получают описанное для них значение только один раз в начале выполнения программы, а при каждом новом входе в процедуру (функцию), где они объявлены, заново не инициализируются и сохраняют свое значение, полученное оо время предыдущего вызова процедуры (функции) Типизированные константы можно использовать точно так же, как и переменные того же самого типа, и они могут появляться в левой части оператора присваивания описание типизированной константы 1_^Гйдеитйфйкатор |---тиУ типизированная гонстанта
46 Структура с В1НЫХ константных выражений для задания значения ТИп KptX„™ используют также константные адресные выражения Ко„с^ ванной констан _ ЭТО выражение, значением которого является ’**' адресное ^":еменной типизированной константы, процедуры или фуЛ4рь глобальной 1 Р сное выражение не может ссылаться к локальным перем Константное и мическим переменным, поскольку их адреса нельзя вычи ""' процедур или к х* во №е“ к°"к типизированная константа фактически представляет собой инИ1, лизируемую переменную, то она не может использоваться в объявлениях Др* констант или типов Типизированные константы стандартных типов const Arr_Length . Integer = 100, Step Real = 0 001, Flag Boolean = False, LineFeed Char = #10, Newlxne String [2] = #13#10, Name String C14] = 'Turbo Pascal', var Buffer ‘ arrayfO 1023] of Byte, const BufferOfs Word = Ofs(Buffer); Bufferseg Word — Seg(Buffer) Ptr Pointer = @Buffer, Типизированные константы указательного типа type Ptr = А const Integer IntPtr Ptr = nil, Inti Integer = 0, IntiPtr Ptr einti, Типизированные константы структурированных типов стРУКтурированныхПт«;СвЖИВаСТ pd®OTi' с типизированными константами следу*®*1 • типа “массив" (array), • типа "множество” (set) • типа “запись” (record) ' ^ктного типа (object) Сс компонента соответств^*' СТрукт^РиР°ванного типа указываются значения нно определенным синтаксическим правилам
•„роаание е среде Turbo Pascal 7 О 47 Типизированные константы типа "массив” Константы типа “массив” описываются согласно следующим синтаксическим ,, ранним константа-массив При описании константы типа “массив" компоненты каждой размерности массива заключаются в отдельные скобки и разделяются запятыми. Компоненты, расположенные в самых внутренних скобках соответствуют последней (самой правой) размерности массива Примеры констант типа “массив”: • одномерный числовой массив const DxgVector : array [1..7] of Real = (0.1, 3.25, 21.32, 55, 11.99, 78.1, 4.5); • двумерный числовой массив const DxgMatrxx : array [1..3,1..4] of Integer = ( (1,2,3,4), (2,3,4,5), (3,4,5,6) ); В результате будет сформирована матрица такого вида 12 3 4 2 3 4 5 3 4 5 6 • трехмерный числовой массив const Dxg3D : array [1..4,1..3,1..2] of Byte= ( ((1,2) , (1,2) , (1,2) ) , ((1,2) , (1,2) , (1,2)) , ((1,2) , (1,2) , (1,2)) , ((1,2) , (1,2) , (1,2)) ) : • одномерный массив символов const CharVectl array [1 6] of Char = (1F,,,A',,S,,,C,,IA,,,L'); или более кратко CharVect2 array [1..6] of Char = 'PASCAL'/
_________________________________ 48 —------------ Типизированные константы типа ‘'множество' жене описания kOHUJHT пни 1 множество" определяется следу101ц правами константа- элемент константа Каждый компонент константы типа “множество” может представлять собок 1ибо отдетьную константу соответствующего типа, либо интервал значений, состоянии издву\ констант, разделенных символом .. (две точки) Примеры констант типа “множество” type Dxgxts = set CharDxg = set const DxgSetl DxgSet2 CharDxgSetl CharDxgSet2 CharSet of 0 9, of 101 '9'; Dxgxts = [0, 2, 4, Dxgxts = [1 3, 5 CharDxg = [10' , ' 2 1 , CharDxg = [’0' 3 ' set of Char = ['a' 6, 8] , 7] , ' 4 ’ , ’ 61 , '8, ' ] , , 'S' 17 1 ] , 'z1 , 1 A’ ' Z ' ] , Типизированные константы типа “запись" запил?ГИСаНИИ константь| типа "запись” указываются как значения всех поле» Диаграммам" ИХ ИЯен™Тикат0Рь1, соответственно нижеприведенным синтаксически» типа В ваоиантк^ВаНН1"1Х константах типа “запись” не допускаются поля файлового падей котовый констаитах'записях допускается указание только того вариан Поля указывают^??/?'а"°шснн™ предварительно константе поля-признака том же порядке, в котором они следуют в описании типа ЗДЛИСЬ
i о рчммирование в среде Turbo Pascal 7 О 49 Примеры типизировшних констант тип i зшись type Rec = record R Real В Boolean C Char end ArrayOfRec = array [1 3] of Rec RecOfArray = record Arrlnt array [1 3] of Integer ArrChar array [1 2] of Char end RecOfRec = record I Integer S Strxng Z Rec end const RecElem Rec = ( R 3 1415 В True C * ) ArrRec ArrayOfRec = R 3 1415 В True С R 0 0 В False С $ R 6 2832 В True С & RecArr RecOfArray = ( Arrlnt (1 2 3) ArrChar (1 2 ) ) RecRec RecOfRec = ( I 32767 S PASCAL Z ( R 3 1415 В True C * ) ) Типизированные константы объектного типа Описание констант объектного типа выполняется аналогично константim ипа запись Зна <ения полей объекта задаются точно так же а значения для методов югхт не указываться type Poxnt = object X Y Integer end Ract = object A В Poxnt procedure Inxt(XA YA XB YB Integer) procedure Copy(var R Ract) procedure Move(Dx Dy Integer) end const ZeroPoxnt Poxnt « (X 0 Y 0) ScreenRect Rect • (A (X 0 Y 0) В (X 80 Y 25)) Инициализация констант объектного типа содержащих виртуальные методы ьыпотняется автоматически на этапе компиляции
Типизированные константы процедурного типа „ процедурного типа должна указывать идентификатор Процеду К°НС^есгимь1й по присваиванию с типом константы. ₽Ь| ц процедура* К0ИСТ8ИТЭ (Exp (X) -Exp (-X) ) FuncType = Function (X ; Real); function SH( X: Real). Real, begin SH end; function CH( X: Real) : Real; begin CH := (Exp(X)+Exp(-X)) end; const CurrentFunc: FuncType = SH; / 2; 3.3.4. Описание переменных Синтаксис описания переменных имеет следующий вид. / 2 ; раздел описания переменных описание переменной описание переменной
-Угюграммироввние в среде Turbo Pascal 7 О 51 В качестве типа можно использовать или идентификатор типа, который был ранее определен в разделе описания типов, или самостоятельное новое опрсдспение типа согласно синтаксису описания типов type Colors = ( Red, Blue, Green ); Vector » array [1..100] of integer; var a, b, c : Real; i, j ' Integer; Flag : Boolean; Color : Colors; Digit : 0 .. 9; Season (Spring, Summer, Autumn, Winter); Vectl, Vect2 : Vector; Matrix : array[l.,5, 1. 10] of Byte; С помощью директивы absolute можно описать так называемые абсолютные переменные, которые будут располагаться в памяти по строго указанному адресу Каждая абсолютная переменная должна быть описана отдельно, то есть список идентификаторов в объявлении перед двоеточием должен состоять только из одного идентификатора Существует две формы описания абсолютных переменных* 1 • форма с указанием точного адреса расположения переменной; • форма с расположением двух переменных по одному адресу При первой форме указываются точные значения сегмента и смешения (то есть полный адрес), где должна быть размешена описываемая переменная CrtMode Byte absolute $0040 $0049; Первая константа определяет значение сегмента, а вторая — значение смешения внутри этого сегмента Обе константы не должны выходить за пределы диапазона от S0000 до SFFFF (от 0 до 65535) Вторая форма с директивой absolute используется для описания переменной, которая помещается “поверх" другой переменной, то есть по тому же самому адресу В объявлениях нижеприведенной программы указывается, что переменная Digits должна размешаться по тому же адресу, что и переменная ChDigits В результате, наложение массива типа Byte на строку символов присваивает элементам массива жачения кодов символов, из которых состоит строка * program TestAbsolute; cons t ChDigits . StringflO] = '0123456789’; var Digits . array [0 10] of Byte absolute ChDigits, i integer, begin Writein (' Коды символов от “0" до "9" '), for i:«l to 10 do Write( Digits[i], ' ' ): Writein end.
Результат: Коды символов от "О" до "9" 48 49 50 51 52 53 54 55 56 57 3.3.5. Описание процедур и функций выполняется описание процедур, функций, конструкторо нижеприведенным синтаксическим диаграммам. В этом разделе деструкторов согласно раздел описания процедур и функций
рымироеание в среда Turbo Pascal 7 О блок ASM ASM оператор . , ~ . оператор директива Inline —I и —> описание функции заголовок

пп^оа^ирование в среде Turbo Pascal 7 О 55 заголовок конструктора Процедуры и функции рассматриваются в главе И, а конструкторы и деструкторы — в главе 16 3.3.6. Описание экспорта Примечание' подраздел exports можно использовать только в программах, которые транслируются версиями компилятора BP ЕХЕ, ВРС ЕХЕ и BPW ЕХЕ (см. рис. 1 2.) Подразделы описания экспортируемых имен exports могут многократно встречаться в любом месте описательной части программы или динамически связываемой библиотеки (DLL) (см главу 7) Каждая запись в предложении exports задает идентификатор экспортируемой процедуры или функции При этом необходимо следить, чтобы эта процедура или функция была описана до указания ее имени в подразделе exports Кроме того, описание экспортируемой процедуры или функции должно содержать директиву export (без буквы "s” в конце ') В качестве экспортируемых имен могут выступать уточненные идентификаторы Ниже показан синтаксис описания подраздела exports Предложение exports —>(exports^——«| список экспорта^ х—«запись экспорта |— <ГИфИК8Г0р к т V \ целая константа
Структура^ *6 ---------- писаний exports перечисляются все процедуры и фу в подразделах 0П Т дандан программой или динамически свЯЗЫа^1 попью экспортируются дан программа может содержать пред, ** библиотекой^^"ктиГе это встречается достаточно редко Как праВИЛо X У№°Гвает« В DLL допускаюТся только во внешнем разделе 0„ у nPeiW0XeHpLL^ разделе описаний процедуры, функции и модуля использоваться нс,‘-'ОТСПОрТа может включать в себя ключевое слово ind Каждая запис м аиачение в диапазоне от I до 32767 Число ука^ которым следует и™2вегетане экспортируемой процедуре или функции специзд ' в index ставит в записи экспорта описание index отсутствует порядковое, значение автоматически пормл°?пись поедаожен™ exports может содержать ключевое слово „аив , Следует строковая константа Эта константа задает процедуре или функ1и„ которым следу экспортироваться Если описание паше в записи экспорт, Т “° то процедура или функция экспортируется со своим идентификатор» симвоть^которого преобразуются в верхний регистр Кроме того запись экспорта может включать в себя ключевое Ий ssident при указании которого информация об экспорте будет оставаться, оперативной памяти, пока DLL загружена Это позволяет существенно уменьшит время поиска подпрограммы в динамически загружаемой библиотеке по имени 3.4. РАЗДЕЛ ОПЕРАТОРОВ (ОПЕРАТОРНЫЙ БЛОК) Это единственный обязательный раздет в структуре программы Классически простейшая программа имеет следующий вид begin Writein('Hello, World') end Но, как отмечалось выше, без использования предыдущих разделов моли написать разве что, такие примитивные программы Синтаксис раздела операторов имеет вид Множество допустим,,v в данном разлете операюрон рассматривается в паве
n A |ММ paw L в среде Turbo Pascal 7 0 57 1 2 3 4 6 1 S 9 10 11 12 13 14 15 16 17 18 19 Контрольные вопросы Является ли обязательным заголовок программы в языке Turbo Pascal’ В каких случаях используется и где располагается в программе предложение uses7 Hi какие группы делится множество типов языка Turbo Рьса!7 Перечислите стандартные типы языка Turbo Pascal7 Какими свойствами характеризуются порядковые типы7 С помощью каких директив комли 1ятора осуществляется выбор модели генерации кода для чисел вещественных типов7 Какие новые булевские типы введены в языке Turbo Pascal версии 70’ Для каких целей были введены новые булевские типы7 Как получить значение кода требуемого символа7 Какая разновидность строк введена в язык Turbo Pascal версии 7 О7 Что представляют собой пользовательские типы7 Какие типы относятся к структурированным’ Каковы стандартные функции допустимые в константных выражениях7 Что представляют собой типизированные константы’ Поля какого типа не допускаются в типизированных константах типа запись 7 Что представляет собой типизированная константа процедурного типа7 Какие существуют формы описания абсолютных переменных7 Что описывается в предложении exports7 Где допустимо использование Предложения exports1 Контрольные задания 1 В каких программах содержатся ошибки >кьките их 1) program Pl procedure Subl begin end var A В Real type TV » array [1 10] of Integer const К • 20 label _L1 begin end
program P2, type TM = array [1..N] of Real; const Ы = 100; M = 50; var Sr T array [1. .20] of Byte; begin end. B) program P3; label 10; const M = 200; type TV = array [1..MJ of Char; var X : M; begin end. 2. Напишите примеры констант, принадлежащих одновременно каждому из следующих целых типов' a) Shortint/ Integer; б) Longint, Shortint; В) Byte, Word; г) Word, Shortint; 3. Напишите примеры констант, принадлежащих одновременно каждому из следующих вещественных типов a; Single, Comp, б) Double, Single; в I Real, Extended; D Real, Double, Extended, Comp; Л) Extended, Comp, 4. Напишите примеры констант булевскою, символьного, строкового и указательного типов 5. Напишите примеры описаний каждого из определяемых пользователе** типов и примеры констант для каждого из них
ГЛАВА 4 ОПЕРАЦИИ И ВЫРАЖЕНИЯ 4.1. ПОНЯТИЯ ВЫРАЖЕНИЯ, ОПЕРАЦИИ, ОПЕРАНДА Выражение в программировании служит для определения действий, которые в математике обычно описываются формулами Выражения состоят из операций и операндов По количеству операндов операции делятся на унарные и бинарные Унарные операции имеют только один операнд, перед которым располагается символ олерации Примеры. Выражение Результат —7 -7 -(-9) 9 not False True Большинство операций являются бинарными и содержат два операнда, между которыми ставится символ операции. Примеры. Выражение Результат 5+7 12 (4-2)*5+10 20 True or False True 4.2. ПРИОРИТЕТ ОПЕРАЦИЙ И ИХ КЛАССИФИКАЦИЯ 4.2.1. Приоритет операций Последовательность выполнения операций определяется тремя факторами • приоритетом операций, • порядком расположения операций в выражении. • использованием скобок По приоритету все операции делятся на четыре группы высшего) приоритета выполняются в первую очередь Операиии '|ГТВСЙð(™3“ ' приоритета выполняются в последнюю очередь Операиии с равным приоритетом
60 „„,„тся слева направо, хотя иногда компилятор для генерации В ,Щ,ого кода может переупорядочить операнды Скобки служат для измен*" TZX порядка обработки операций Подвыражение, заключенное в скобки, сн2* вычисляется как отдельный операнд, а затем его результат использ^тся выполнения операций, обрамляюших скобки * Приоритет операций Приоритет Операции Категория операций Первый (высший) + - not @ Унарные операции Второй * / div mod and shl shr Бинарные операции типа умножения Третий + or xor Бинарные операции типа сложения Четвертый (низший) in Бинарные операции отношения В Turbo Pascal приоритет операции отражен непосредственно в синтаксисе языка, что видно из нижеприведенных синтаксических диаграмм, описывающих выражение Примеры сложных выражений А * (((X - Y / Z) *3 + 5) / (0 + С) - D * Е) - 14 (А О В) and ((I < J) or (J < К) ) and (С in D) 4.2.2. Синтаксические диаграммы,описывающие выражение
раммироеание в среде Turbo Pascal 7 О Ы простое выражение ->|терм |-
константа без знака знак
lIp^psMMUpo^oHtie в среде Turbo Pascal 7 О 63 описатель множества группа элементов выражение ссылка на переменную
64 Операции и выражу. квалификатор индекс описатель поля идентификатор поля
•мшоование в среде Turbo Pascal 7 О 4.2.3. Классификация операций По характеру выполняемых действий операции можно разделить на следующие группы 1. Арифметические операции ♦ унарные +, - • бинарные +, *, /, div, mod 2. Операции отношения 3. Булевские (логические) операции not, and, or, xor 4 Поразрядные логические и сдвиговые операции not, and, or, xor, shl, shr 5. Строковая операция (конкатенация) т 6. Операции над множествами + , *, ш, < = , >— 7. Операция взятия адреса @ 4.3. ОПИСАНИЕ ОПЕРАЦИЙ В приведенных ниже таблицах содержатся сведения о действии операции, а также типах операндов и результата 4.3.1. Арифметические операции Суть действий, выполняемых операциями +, *, /, особых пояснений не ТГ ст Следует только помнить, что если операнды различных типов, то тип 5 - 4347
Операции и выражения 66 результата будет более охватывающим, а тип результата операции деления (/) всегда будет вещественным Результатом операции div будет целочисленное значение, равное целой части результата деления первого операнда на второй Результатом операции mod будет целочисленное значение, равное остатку от деления (но не дробной части) первого операнда иа второй Операция Действпе Типы операндов Тип результата Унарные + I Сохранение знака Целый Вещественный Целый Вещественный — I Отрицание | знака Целый Вещественный Целый Вещественный Бинарные + Сложение Целый Вещественный Целый Вещественный Вычитание Целый Вещественный Целый Вещественный Умножение Целый Вещественный Целый Вещественный / Деление Целый Вещественный Вещественный Вещественный div Целочисленное деление Целый Целый mod Остаток от деления Целый Целый Примеры Выражение Результат 7 div 3 2 7 mod 3 1 23 div 5 4 23 mod S 3 Действие 4.3.2. Операции отношения _____________ операций отношения соответствует их матемагич^гх имничипмп-' Результатом зтих операций является булевское значение (True, False) При использовании операций отношения для строковых значений, сравнение выполняется посимвольно слева направо согласно значениям кодов символов расширенного набора ASCII
L п„^мшироеание в среде Turbo Pascal 7 О 67 Все строковые значения независимо от длины считаются совместимыми Кроме того, значения символьного типа также считаются совместимыми со значениями строкового типа, и обрабатываются как строки длиной в один символ При сравнении операндов указательного типа допустимо использование только операций = и <>. Два указателя равны только в том случае, если они ссылаются на один и тот же объект Операция Действие Тип операндов Тип результата = Равно Совместимый простой, строковый ИЛИ указательный тип Булевский О Не равно Совместимый простой, строковый или указательный тип Булевский < Меньше Совместимый простой или Строковый тип Булевский > Больше Совместимый простой или строковый тип Булевский <= Меньше или равно Совместимый простой или строковый тип Булевский >= Больше или равно Совместимый простой или строковый тип Булевский Примеры Выражение Результат 4 = 3 False False <> True True АВС’ < ABD’ True АВС’ > А True 4.3,3. Булевские (логические) операции Булевские операции выполняются по правилам булевой алгебры. которые показаны ниже Операнды Опсрапии X В not A A and В 4 or В A xor В False False True False False False False True True False True True True False False False True True True True False True True False В Turbo Pascal при выполнении булевских операций в логических выражениях Поддерживаются две различные модели генерации кода вычисление по полной схеме, вычисление по короткой схеме
Операции и выражения 6в При использовании полной схемы всегда вычисляются все операнды и выполняются все операции выражения, даже если его результат будет известен уже после первой операции. При использовании короткой схемы вычисление операндов и результатов операций выполняется строго слева направо и прекращается, как только выполнение дальнейших действий перестанет оказывать влияние на конечный результат всего выражения Управление моделью вычисления осуществляется с помощью директиву компилятора $В По умолчанию установлено значение! SB-), которое соответствует короткой схеме вычислений Операция | Действие | Тип операндов | Тип результата' not Логическое отрицание Булевский Булевский 1 Бинарные and Логическое И Булевский Булевский or Логическое ИЛИ Булевский Булевский хог Логическое исключающее ИЛИ Булевский Булевский 4.3.4. Поразрядные (битовые) булевские и сдвиговые операции Поразрядные операции в Turbo Pascal могут иметь операнды тотъко петого типа Действие этих операций выполняется поразрядно (побитово) над двоичным Представлением операндов Результатом операции not будет целочисленное значение, равное десятичному числу, которое соответствует поразрядно инвертированному двоичному предстаачеиию исходного операнда Результатом операции and будет целочисленное значение, равное десятичному числу. которое соответствует двоичному представлению поразрядно выполненной над исходными операндами логической операции И Результатом операции or будет целочисленное значение, равное десятичному числу, которое соответствует двоичиому представлению поразрядно выполненной над исходными операндами логической операции ИЛИ Результатом операции хог будет целочисленное шачение. равное десятичному числу, которое соответствует двоичиому представлению поразрядно выполненной над исходными операндами логической операции исключающее ИЛИ Результатом операции A sni В будет целочисленное значение, равное десятичному числу, полученному в результате поразрядного сдвига влево двоичного представления операнда А на В рлпик.- о победившие с я яри этом разрл заполняются нулями
ммированив в среде Turbo Pascal ? О 69 PinnhriTOM операции Л shr В будет цепочно ichhoc шаченис равное ичномх числу полученному в результате поразрядного сдвига вправо двоичного । ншсния операнда А на В разрядов Освободившиеся при этом разряды няются нолями Операция | Действие Тип операндов । Тип результата Унарная not Поразрядное отрицание Целый Целый Бинарные and Поразрядное И Целый Целый or Поразрядное или Целый Целый xor Поразрядное исключающее или Целый Целый shl Поразрядный сдвиг влево Целый Целый shr Поразрядный сдвиг вправо Целый Целый Примеры Если операнды А и В будут иметь тип Byte то выполнение рассматриваемых операции при А=11 В=2 даст следующие результаты Десятичное значение Двоичное представление Операнд А 11 00001011 Операнд В 2 00000010 not А 244 11110100 A and В 2 00000010 A or В 11 00001011 А хог В 9 00001001 A shl В 44 00101100 A shr В 2 00000010 4.3.5. Строковая операция Для обозначения операции конкатенации (сцепления) двух строк или символов в Turbo Pascal используется такой же символ как и для операции сложения (+) Результатом этой операции будет строка состоящая из символов обоих операндов, в которой символы второго операнда пристыковываются в конец симвоюв первого операнда Если длина результирующей строки превышает 255 символов то она хсекается до 255 символов
Операции и пыражьу* Операция Действие Конкатенация (сцепление) Типы операндов. Строковый, символьный _ Тип результата Строковый Примеры Выражение 'Turbo*** Pascal* ’ABC’+’D* 'X'+’Z* Результат ’Turbo Pascal* АВСР' ~ ’XZ*_____ 4.3.6. Операции над множествами Операции над множествами выполняются по правилам теории множеств Результатом операции объединения двух множеств А * В будет множество С, включающее как все элементы множества А. так и все элементы множества В. Результатом операции разности двух множеств А — В будет множество С, состоящее только из тех элементов множества А, которые не входят в множество В. Результатом операции пересечения двух множеств А * В будет множество С, состоящее только из тех элементов, которые принадлежат как множеству А, так и множеству В. Если наименьшее порядковое значение, которое является результатом операции над множествами это X, а наибольшее Y. то типом результата будет set of X..Y Результатом операции сравнения А = В будет True, а операции А <> В будет False, только тогда, когда А и В содержат одни и те же элементы Результатом операции сравнения А <= В будет True, если множество А является подмножеством множества В Результатом операции сравнения А >= В будет True, если множество А включает в себя все элементы множества В. Результатом операции принадлежности X in А будет True, если значение X какого-либо порядкового типа Т является элементом множества А того же типа Т Примеры Выражение Результат (1,2,3,41 + [3,4,5,61 [1,2,3,4,5,61 [1,2,3,41 - 13,4,5,6] [1,21 [1,2,3,41 * 13,4,5,6] [3,41 [1,2,31 = [1,2,3,41 False 11,2,31 О [1,2,3 41 True [1,2,3] <= [1,2,3 41 [1,2,3] >= [2,3,4] 4 in [3,4,5,61 True False True ТИПЫ и
* среде Turbo Pascal 7 о ()пер»иня Действие Типы операндов Тип результата 4 Объединение Совместимые типы множеств Множество Разность * Пересечение = Равенство Булевский О Не равенство >= Является надмножест- вом < = Является подмножест- вом in Принадлеж- ность Левый операнд побои порядковым тип Т. Правый операнд- множество типа Т 4.3.7. Операция взятия адреса (получения указателя) Операция & является унарной операцией результатом выпсинения которой v г указатель на ее операнд Тип результата является совместимым с типом чзягеля их!, что позволяет присвоить результат любой указательной переменной В качестве операнда операции @ могут использоваться идентификаторы ременных, процедур, функций и методов Операция Действие Тин операнда 1 ин ре 1V 1ьтата а Получение указателя Идентификатор пере- менной. процедуры, функции и hi мето и > казатезь, совместимый С nil Контрольные вопросы Что представляет собой выражение7 Как делятся операции по количеству операндов'7 Какими факторами определяется последовательность выполнения операции7
Операции и пырыъни,. 5 На какие группы можно разделить операции по характеру выполняемых действий? 6 Какое различие между операциями / и div? 7 Какой тип результата имеют операции отношения? 8. Какие модели генерации кода поддерживаются в Turbo Pascal при вычислении логических выражений? 9 К операндам каких типов могут быть применены поразрядные операции? 10. Какова максимальная длина результирующей строки при выполнении строковых операций? 11. Какие типы операндов допустимы при выполнении операций над множествами? 12. Какой тип результата имеет операция взятия адреса? 13. Что может быть использовано в качестве операнда операции @? Контрольные задания 1. Запишите на языке Turbo Pascal следующие формулы: а) in(77Z77+x'”+z) 6) Y У”' , Х + 2 ^Y~2\+3 2IX + FI г)
ограммироввние в среде Turbo Pascal 7 О 73 2 Заданы описания var х 3 Integer х у Real a b Boolean с Char s Strxng Какие из следующих операторов содержат ошибки и почему9 1) X = X * у 2) 3 = x * у 3) X = 1/2 4) X = J dxv 2 5) X = у mod 2 6) X ~~ з mod x 7) 3 = х or 100 8) X = у and з 9) с = с + s 10) s = s + c 11) а = not (a and b) 12) b = ((x-y) < 2) = a
ГЛАВА 5 Опе„, предназначены дчя описания действий, которые будут выполнены при реализации алгоритма Как видно из синтаксической диаграммы любому оператору может предше- ствовать метка которая используется для передачи управления в эту точку программы с помощью операторов перехода goto Описание меток рассмотрено в главе 2 Согласно синтаксису операторы языка Turbo Pascal разделяются на две группы • простые операторы, • стр\кгурные операторы Операторы отделяются друг от друга символом “точка с запятой’ ( ) Точка с запятой не является частью оператора это разделитель операторов Поэтому после последнего оператора программы и после последнего оператора в составном операторе то есть перед ключевым сювом end, точку с запятой ставить не обязательно Если же в указанном случае символ все же поставлен, то считается что после него расположен пустой оператор и ошибкой не является Какие операторы включает каждая из указанных групп видно из следующих диаграмм простой оператор оператор присваивания оператор процедуры оператор перехода структурный оператор составной опера оператор цигла
пяммир^мше в среде Turbo Pascal 7 О 5.1. ПРОСТЫЕ ОПЕРАТОРЫ Простые операторы — это такие операторы, которые не содержат в себе других операторов 5.1.1. Оператор присваивания Оператор присваивания состоит из идентификатора переменной или пользовательской функции, символа присваивания “ =" и выражения Оператор присваивания, в левой части которого стоит идентификатор функции, может располагаться только в пределах тела функции Выполнение оператора присваивания приводит к вычислению значения, определяемого выражением, и присваиванию этого значения переменной, иден- тифицируемой именем, стоящим слева от символа присваивания В случае если слева стоит идентификатор функции, выполняется определение результата функции, то есть значения, возвращаемого функцией в точку вызова оператор _ присваивания ссылка на ^идентификатор функцйи|— Допускается присваивание значений не только простых, но и структхри- рованных типов, таких как массивы, записи и множества Обязательным является требование, чтобы тип выражения в правой части оператора и тип переменной или результата функции в левой части оператора были совместимы по присваиванию Примеры: var А, В, С Real 1, у, k Integer Flag Boolean, Vecl, Vec2 array [1 10] of Byte Reel, Rec2 record Ch Char X Real end, Setl, Set2 set of Char, Begin A = В * C i = j div к Flag = (i <> 1) and (В < C), Vecl = Vec2, Reel = Rec2, Setl = Set2, End
76 Or epampt 5 12 Оператор процедуры : s= — «* оператор процедуры Выполнение оператора процедуры приводит к активизации действии описанных в ее теле Указанные в операторе фактические параметры должны соответствовать описанным в заголовке процедуры формальным параметрам по типу котичеству и взаиморасположению Перед активизацией тела процедуры происходит передача фактических параметров соответствующим формальным параметрам Аналогичные действия выполняются при вызове методов описанных в объектных типа Примеры Summa (A m n Sum) Initialize Swap (X Y) метка 5 13 Оператор перехода 1 Оператор перехода состоит из ключевого слова goto после которого указывается Описание меток рассмотрено в главе 2 оператор перехода котопыи опе!>атоРа ^oto приводит к передаче управления на оператор перед который стоит указанная в операторе goto метка перехода ЯраГпол™адасьТт1мЯжТеРбпА^НИе ЧТ°бЫ М'ТКа Указаииая в операторе означает ио *в бпоке и™ моДуле что и сам оператор goto Это внутрь процедуры РфуНк°”и°П'Р"^а "'₽'хода “прещена передача управления НИИ) в окружающую ее среду передача управления из процедуры (Функ программир^>вания'™ТеЬтоЧиспол^1°и про™воРсчит принципам структурного опасным является применение о 8 програмчах ™ рекомендуется Особенно аначитетьио ослабив, по'Х™ТХР"°И ° ТиГЬ° “ К°ГОР°М на использование goto В < 00 сгамт1Р'том языка Pascal ограничения выдает сообщения об ошибка
t 4 tpote Turbo Pascal 7 0 77 jbpn передаче управления внутрь структурных операторов (например, оператор Efer). что зачастую приводит к непредсказуемым действиям пренраммы. Г Учитывая сказанное, можно порекомендовать вообще исключить использование sortefxiTopa перехода при написании программ. Тем более, что в Turbo Pascal включены предопределенные процедуры Break и Continue, которые специально предназначены , in ситуаций, в которых наиболее часто используется оператор goto. 5.2. СТРУКТУРНЫЕ ОПЕРАТОРЫ Структурные операторы включают в себя другие операторы и управляют последовательностью их выполнения. В Turbo Pascal структурными операторами являются: )) составной оператор; 2) условные операторы: - оператор альтернативы if; - оператор выбора case; 3) операторы цикла' - оператор никла с предусловием while, - оператор цикла с постусловием repeat; - оператор цикла со счетчиком for; 4) оператор для записей with. 5.2.1. Составной оператор Составной оператор объединяет группу операторов в единое целое, после чего они могут считаться одним оператором Составной оператор состоит из последовательности объединяемых операторов, которые располагаются между ключевыми словами begin и end. составной оператор Составной оператор используется в тех случаях, когда синтаксис языка Turbo Pascal допускает в определенной точке программы указание только одного оператора, а по алгоритму в этом месте необходимо выполнить группу операторов Как правило составной оператор используется совместно со структурными операторами Пример: While Л<>0 do begin Writein (•Введите число'); Readin (А); Writein (’Квадрат числа',А,• « А*А) end;
Оператор^ 78 5.2.2- Условные операторы R Turbo Pascal включены два условных оператора - if » case, каждый из В Turbo гаь формах: полной и неполной, что соответствует которых может^“ТЬ равляюшим конструкциям алгоритмов (см. главу 9) четырем o6o®me"”aJMa условного оператора имеет следующий вид. Синтаксическая Д Р по своей сути являготся условными, однако условный оператор исторически сложилось так, что оператором условия (условным оператором) называется оператор if, а оператор case называется оператором выбора или оператором варианта. В дальнейшем будем придерживаться этой исторической терминологии. Условный оператор if Условный оператор if, как отмечалось выше, может быть записан в полной и неполной формах, которые имеют следующий вид. Неполная форма if Выражение then Оператор Полная форма. if Выражение then Оператор! else 0лератор2 Синтаксическая диаграмма оператора if показана ниже. оператор if выражение оператор результат*1 ВЫПолнении Условного оператора сначала вычисляется выражение, от знач^и>Г^Т°РОГО может принимать только булевский тип, а затем, в зависимости Vi ->па 1сния результата /Тт» т* < ключевого слова 'Irue> baJse), выполняется нли Оператор!, стоящий после ключевого then (ссли Результат равен True), или 0ператор2, стоящий после в ^ае когдГ резмьтат равен False) False управление пе °Псратор ^записан в неполной форме, при значении результата if, а Оператор, стоя ся опеРатору, следующему непосредственно после оператора Начинающим ключевым словом then, пропускается ниже синтаксические осЗ^ММИСТам следУет обратить внимание на рассматриваемые ооенности оператора if.
Turbo Pascal 7 О Напомним, что n Turbo Pascal операторы разделяются симной (наст. что внутри любого структурного оператора символ встречаться не должен, тс нес что стоит посте него, будет считаться уже другим оператором 1римср С ошибкой: if А > В then С : = А I; 1 4----------------------------ошибка 1 else С : = В; 1—1 В показанном выше примере точка с запятой, стоящая перед ключевым словом else заканчивает текст оператора if. А это приводит к синтаксической ошибке, поскольку оператора, начинающегося с ключевого слова else в Turbo Pascal нет Чтобы не допускать таких ошибок целесообразно запомнить такое правило; Перед ключевым словом else символ никогда не ставится. По синтаксису (см. диаграмму) после ключевых слов then и else может стоять всего лишь один оператор. Если же в какой-либо из ветвей альтернативы (then или else} или сразу в обоих требуется выполнить несколько операторов, то следует воспользоваться составным оператором __________________ begin end который позволяет интерпретировать группу операторов как один оператор. Заметим, что операторы, расположенные между ключевыми словами begin .. end, также как и везде, должны разделяться точкой с запятой Обобщенные формы простейшего случая оператора if приведены в таблице 5-1 Еще одна синтаксическая сложность корректного использования оператора if возникает при написании вложенных операторов if. В случае, если вложенный оператор if располагается в пределах составного оператора, больших проблем не возникает, так как ключевые слова begin и end точно ограничивают область каждой альтернативы Например: if выражение then begin оператор; if выражение then оператор else оператор; оператор end else begin оператор; if выражение then оператор end
Оператор^ Таблица 5-1 один else один несколь ко несколько один несколько несколько "обобщенная форма оператора if if выражение then оператор else оператор if выражение then begin оператор, оператор, оператор end else оператор____ if выражение then оператор else begin оператор, оператор; оператор end________ if выражение then begin оператор оператор оператор end else begin оператор, оператор оператор end . Однако если вложенный оператор if является единственным оператором в ветви альтернативы то может возникнуть неоднозначность какому if соответств}ст ветвь else В Например ___________________ if выражение then if выражение then оператор else оператор таких стучаях следует помнить правило Ключевое слово else связывается с ближайшим стоящим перед «им зючевым словом if, которое еще не было сяязано с каким-либо ключевым словом else.
тгмооввни# в среде Turbo Pescal 7 О 81 Сели в предыдущем примере более четко обозначить структуру вложенности 1в else на одном уровне с then которому оно соответствует то получим такой (| । и мент if выражение then if выражение then оператор else оператор Оператор выбора case Рассмотренный условный оператор if позволяет выбирать только одно из двух возможных действий в зависимости от логического выражения Оператор выбора case является обобщением оператора if — он дает возможность выполнить одно из нескольких действий в зависимости от значения переключателя В качестве переключателя используется выражение которое располагается между ключевыми словами case и of Результатом этого выражения может быть только значение порядкового типа общее количество элементов которого не превышает 6553а Синтаксические диаграммы оператора выбора имеют следующий вид ветвь else оператор
___________________________ 82_______ —----------------------------------- 06u,yR1 структуру оператора выбора в полной форме можно представ,. TJKIIM обраюм case переключатель of Список констант!: Оператор!, Список констант2: Оператор2, Список константЫ: ОператорИ else ОператорЕ end________________________________ Одной фразой логику работы оператора выбора можно описать так- вычисленное значение Переключателя определяет. какой из операторов должен быть выполнен Если переключатель принимает одно из значений СпискаКонстант1, то выполняется оператор!, а остальные Операторы пропускаются. Если Переключатель принимает одно из значений СпискаКонстаят2, то выполняется 0ператор2. Аналогично будут выполняться операторы от ОператораЗ до ОператораК ОператорЕ будет выполняться в том случае, если значение переключателя не совпало ни с одним из значений СписковКонстант ОТ 1-ГО до N-TO, В неполной форме оператора case альтернативная всем предыдущим вариантам выбора ветвь else отсутствует В этом случае, если значение пере- ключателя не совпадает ни с одним из значений констант выбора, не выполняет- ся ни один из операторов, описанных в case, и управление передается оператору, стоящем) непосредственно после ключевого слова end, замыкающего оператор case Ниже показаны примеры, демонстрирующие наиболее характерные способы использования оператора case Примеры: var Arrow : Char; Position: record X,Y : Word end; begin with Position do case Arrow of #72 : Y:=Y-1; #80 : Y=Y+1; «75 : X:-X-l; «77 x =X+1 end end var Symbol Char ---------------------------- begin case Symbol of a' z. writeln (‘Это цифра’); ‘--------yrxteln ( Это строчная буква ' ) ;
л мл fI/рование в среде Turbo Pascal 7 О 83 end 'А'..'Z' wrxteln ('Это прописная буква'); #10,#13,#26: writein ('Это управляющий символ') else wrxteln (‘Это другой символ1) end. var Year : Integer; begin case Year of -500..-400: wrxteln ('Древнегреческий абак'); 480..500 : begin wrxteln('Первые записи в десятичной '); wrxteln(’системе счисления, которые '); writein(1 были сделаны в Индии.’) end; 1642 : wrxteln ( ‘ Суммирующая машина Б. Паскаля.’); else writeln(’H прочее, прочее, прочее.,.’) end; end. 5.2.3. Операторы повторения Операторы повторения языка Turbo Pascal поддерживают напрямую три из четырех классических управляющих конструкций повторения (см. главу 9). цикл с предусловием ( while ). цикл с постусловием ( repeat ) и цикл со счетчиком ( for ). оператор цикла оператор for Оператор цикла с предусловием while Оператор while вместе с оператором case являются самыми универсальными “равляюшими конструкциями (см главу 9) С помощью операторов case можно -'писать условие разветвления произвольной сложности, а с помощью оператора *hiie можно записать любое циклическое действие Упрощенно общую структуру оператора цикла с предусловием можно вообразить одним из двух следующих способов
Ес.™ тело иикля COCT,,H1 одного оператора^ Khile Условие do Оператор Если тело цикла включает пл тсс одного оператора while Условие do begm Оператор; Оператор; Оператор end Оператор while позволяет многократно выполнять одни и те же действия в зависимости от некоторого Условия, которое записывается между ключевыми словами while и do и должно быть выражением булевского типа, то есть Принимать толЬк0 значения True или False. Опишем работу' никла while более подробно. Сначала, при входе в цикл, вычисляется условие. Если оно равно False, то вход в цикл не выполняется и управление передается оператору, следующему непосредственно за Операторами тела цикла. Если же Условие равно True, то происходит вход в цикл и однократное выполнение Операторов его тела. Как только достигнут конец тела цикла, управление снова передается на его заголовок, где снова вычисляется Условие. Если значение Условия все еще равно True (что зависит от изменения значений переменных во время предыдущего выполнения Операторов цикла), то тело пикта выполняется еше один раз. и гак далее. Как только очередное вычисление Условия цикла дает значение False, работа цикла завершается. С целью сравнения свойств операторов цикла while, repeat и for при описании работы каждого из них рассмотрим как с их помощью записывается один и тот же фрагмент программы, вычисляющий сумму элементов массива размерностью в п элементов Пример: begin Summa := Q: х : * * 1: ( Должны быть начальные установки 1 ( переменных, стояадсх в условии цикла ) *111.1 • х <= n do begin Summa := Summa + А (х ] ; 1 : - 1 * 1: ( Как минимум в одном операторе } ( тала цикла должно быть измене') ( нив переменных условия цикла, } ( приводящее в итоге к ложности ) ( условия } enrf •nd.
iMMi/poeaHue g среде Tu/bo Pascal 7 Q Оператор цикла с постусловием repeat Оператор цикла с постусловием состоит из ключевого слова repeat, за которым следуют операторы тела цикла, и замыкающего ключевого слова until, после которого указывается условие окончания цикла Упрощенно общую структуру оператора repeat можно представить так repeat Оператор, Оператор, Оператор until Условие Заметим что в отличие от while, оператор repeat не требует использования составного оператора, когда в его теле необходимо записать более одного оператора Кроме того, оператор repeat является не столь универсальным, как оператор while, поскольку его Условие располагается в конце тела цикла и операторы его теза будут, в отличие от цикла while, всегда выполняться как минимум один раз Это означает, что оператор repeat не годится для записи циклов, в которых может возникать ситуация, когда тело цикла не должно выполняться ни разу Выражение, используемое в качестве Условия окончания цикла, должно давать результат булевского типа Обшии принцип работы цикла repeat такой же, как v цикла с предусловием, но в отличие от while Условие проверяется не перед выполнением тела цикла, а после него, и управление циклом repeat прямо противоположно управлению циклом while То есть цикл продолжается пока условие равно False и заканчивается, когда Условие становится равным True Пример Const п = 20, begin Summa = 0, i=l ( Должны быть начальные установки } ( переменных, стоящих в условии цикле 1 repeat Summa » Summa * A[i] , i = i + 1, ( Как минимум в одном операторе } ( тела цикла должно быть измене-} { кие переменных условия цикла, ) ( приводящее в итоге к ложности ) ( условия ) until 1 > п end
86 О„вр.~Р -Я» ~ енетмиквм (о п.р.м.тром) циклических *Ра,м“™ша повторений цикла Это обусловливает его менее широкую конечное значения счет и иверсальных операторов while и repeat Однако сферу пРимен“™’ его иСПОТЬзование возможно, оператор for. благодаря своей в°ысокоСйУн“лялности, имеет несомненное преимущество перед операторами цикла с условиями оператор for идентификатор переменной управляющая переменная исходное значение выражение конечное значение выражение J—► одним из и^Хшт^п^боТ^' °ПераТОра иикла с° ci'<™kom можно представить 1) Если счетчик при выполнении никла наращивает свое значение for Переменная •= НачальноеЗначениеСчетчи' to ^онечноеЗначениеСчетчик, _______________Оператор ДОЛЖНО быть не больше « ИЛСЯ Хотя бы ОЛИН раз НачальноеЗначениеСчетчика "шс ,ем КонечноеЗначекиеСчетчика 2)цикла уменьшает свое значение РвИвН"аХ>>пГеНакаЛЬНОвЭиачв'*иеСчвтии’'а "° Конвч«°еЗ"ачекиеСчвтчика ----------в_____ а° Оператор ««а ДОЛЖНО быть ne°Memm.0;,4™C!1 <0ТЯ бы ОЛИН ₽'’ НачальноеЗначекиаСчат- 'СМ КонечяоеЗкачаинеСчетчика
лпннимрумние fl среде Turbo Pascal 7 О 87 P- begin Summa ;= 0; for X := 1 to n do Summa ;= Summa + A[i]; end. R Заметим, что для оператора for, в отличие от whiie и repeat, установка начального значения счетчика циклов (i:=l) выполняется не перед заголовком К цикла, а прямо в заголовке. Кроме того, после окончания тела цикла наращивание/ f уменьшение значения счетчика происходит автоматически. Таким образом, специальный h оператор для увеличения значения счетчика (i:=i+l) не требуется Более того, такой 1 оператор приведет к неправильной работе цикла. Пример с ошибкой. В большинстве реализаций языка Pascal изменение значений переменных, используемых в заголовке цикла for, запрещено и приводит к выдаче сообщения об ошибке на этапе компиляции. В реализации Turbo Pascal этот запрет снят, однако икие действия в рамках никла for, как правило, приводят к его непредсказуемому поведению и считаются плохим стилем программирования. В Turbo Pascal, также как и во всех других реализациях языка Pascal, оператор for имеет два существенных ограничения 1) Шаг изменения счетчика циклов может быть только или +1 (если используется ключевое слово to), или ~1 (если используется ключевое слово downto) 2) Переменная, выступающая в роли счетчика циклов, может быть только порядкового типа и должна быть локальной для того блока, в котором находится оператор for
88 аторов while» repeat и for Сравнение раб°Т^'ннос11| хор(Ш1его стиля работы с рассмотрен,,Ы| „„^'кооператорами __________ Цао с „радслопаем ( „ока условие истинно ) ТГло начала никла должно? Цикл С постусловием repeat ( до истинности условия) "ыть сделаны начальные установки переменных', гтпс, с-пппг-ХТНОГО входа В ЦИКЛ----------------- давляюшщ^^ изменяющие переменные 2» В теле пи"*™ ^некоторое число итерации завершился ifU^TjwfcSeT пока условие ис 3) Цикл работает пока условие ложно (пока False) 4) Цикл завершается, когда условие гтянниится ложным (до False) 4) Цикл завершается, когда условие становится истинным (до True) 5) Цикл может не выполниться пи ра зу. если исходное значение условия 5) Цикл обязательно выполняется как минимум один раз 6) Если в теле цикла требуется более одного оператора, то необходимо использовать составной оператор 6) Независимо от количества операто- ров в теле цикла использование состав- ного оператора не требуется Цикл со счетчиком for 1) Начальная установка переменной счетчика циклов до заголовка нс требуется 2) Изменение в теле никла значении переменных, стоящих в заголовке инки, не допускается 3) Количество итераций цикла неизменно и точно определяется значениями нижней и верхней границ и шага цикла 4) Нормальный ход работы цикла может быть нарушен оператором goto или процедурами Break и Continue 5) Цикл может не выполниться ни разу, если шаг цикла будет изменять значение счетчика от нижней границы в направлении, противоположном верхней границе Для наглядности сравнения записи циклоп while repeat и for сс' воедино рассмотренные для них примеры S: «0 ; 1: »1: *hile к«п do begin S • «S+А [ i ] _• i “1+1. •nd S »0, i =1 repeat x:«1+1. until i>n S : "0 ; for i.! to n do S-S+A(x];
аииироевние e среде Turbo Pascal 7 0 89 Оператор присоединения with Оператор присоединения with предназначен для упрощения доступа к полям записей ( record ) и имеет таком синтаксис оператор присоеди немея ссылка на переменную____ LL г , -----и ССЬ1Лка на переменную -> типа запись или объект | I Если оператор with не использовать то при обращении к полям записей необходимо указывать полное квалифицируемое имя поля состоящее из цепочки идентификаторов разделенных точками Например если сделано описание type T_Rec = record A record В record X Char Y Byte end C Real end D String and var Rec T__Rec то для присваивания полю Y значения 0 а полю С - значения 1 1415 необходимо записать ________________________ Rec А В Y =0 Rec АС « 3 1415 В простейшем случае оператор присоединения позволяет сократить имена записи следующим образом with Rec do begin A В Y =0 AC =3 1415 and Et m *.e испотьзовать не один а два оператора with. то можно эаписать with Rec do with A do begin BY = 0 C = 3 1415 end
Поспелммй фрагмент можно записать более указа») имена Rec и А и одном списке ссылок I with Rae, A do | кимпакпи» одним оиср.ппрпм begin B.Y C 0; 3.1415 Если требуется J end______________ J доступ только К полям X И «th Rec,А,в do begin X : = ' * ' ' Y := 0 end ______ Y. то можно записать Контрольные вопросы i 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 Какие функции выполняют операторы в языке программирования? Что является разделителем операторов в языке Turbo Pascal? На какие группы делятся операторы языка Turbo Pascal? Какие операторы называются простыми? Как работает оператор присваивания? Какие действия выполняет оператор процедуры? Возможна ли передача управления внутрь процедуры (функции) посредством оператора перехода goto и почему? Почему не рекомендуется использование в программах оператора goto9 Какие операторы языка Turbo Pascal являются структурными? Что такое составной оператор и какие функции он выполняет? Ках происходит работа условного оператора if? Может ли встречаться символ внутри любого структурного оператора и почем/' Какие особенности существуют при написании вложенных операторов х/’ Какой оператор позволяет выполнить одно из нескольких действий в завис» мости от результата вычисления выражения? Turbo рПРа^я,Ошис конструкции повторения поддерживаются в языке Как работает оператор цикла while9 В IEM заключается различие между операторами repeat и while9 ^ис ограничения накладываются на использование оператора for9 repelt^f ССТ>В",К>Т °ТЛИЧИЯ и ос°бенности при работе с операторами whiia- го предназначен и как выполняется оператор присоединения 1
.те/мирование в среде Turbo Pascal 7 О 91 f Контрольные задания I Задана кусочно-непрерывная функция у = f(x) Вычислить значения пньли п в областях существования, в противном случае вывести на печать сооб д п отсутствии решения х е [5,+°о) -2л, хе [-20,0) те (20,40] ' х/2 + 5 х2 + \/х. те I-15 1]U(15,3O)I те [5,10]U(40,+~)J 2 Напишите программы, вычисляющие нижеприведенные формулы используя три н( личных вида циклов (vftxle, repeat, for) для вычисления каждой из фо[ п 1
ГЛАВА 6 МОДУЛИ ModvAu предназначены для поддержки принципов модульного программи- пования при разработке программ, основным из которых является принцип СКРЫТИЯ информации (^formation hiding) Согласно этому принципу взаимовлияние логически независимых фрагментов программы должно быть сведено к минимуму Принцип скрытия информации, поддерживаемый модулями, позволяет создавать надежно работающие и легко модифицируемые программы В языке Turbo Pascal модули используются преимущественно для создания библиотек процедур, функций и объектов, которые затем могут использоваться в программах, разрабатываемых пользователем Синтаксис модуля имеет следующий вид модуль заголовок модуля интерфейсный раздел раздел заголовков процедур и функций
<«.< a cpeoe Turbo Pascal ? о ря щгп реллитацми j Используя модули важно правильно указывать их имена Г При подключении стандартных модулей достаточно корректно записать их рнтификаторы в предложении uses При разработке собственных модулей необходимо помнить некоторые обе нн ости • не допускается одновременное использование модулей с одинаковыми именами, г • идентификатор модуля, указанный в заголовке (unit), должен совпадать с именами файлов, содержащих исходный { PAS) и объектный (TPU ТРР, TPW) код (см рис 1 2 ), • если идентификатор модуля длиннее восьми символов, то он должен совладать с именами файлов по первым восьми символам Ниже показана обшая структура модуля, дополненная комментариями, ‘ясняюшими смысл и назначение каждого раздела модуля unit Идентификатор Модуля, ( Интерфейсный раздел } interface ( В этом разделе описывается взаимодействие } ( данного модуля с другими пользовательскими } ( и стандартными модулями, а также с главной ) { программой Другими словами — взаимодей- } { ствие модуля с "внешним миром" )
Спхсок импорт» »ят«р»<й£££Е° раздала ) “S®S «ооез запятые перечисляются t r ч'гом списке через s идентификаторы модулей, информация интер- ; фейсных частей которых должна быть дос- ( тупяа в данном модуле. ( Здесь целесообразно описывать идентифика- торы только тех модулей, информация из ( которых используется в описаниях раздела ( interface данного модуля } У } } } ) } ) Список экспорта интерфейсного раздела^ ) const ( Список экспорта состоит из лодраз- } type ( делов описания констант, типов, } var ( переменных, заголовков процедур и } procedure{ функции, которые определены в дан- ) function ( ном модуле, но использовать кото- } { рые разрешено во всех других моду- } ( лях и программах, включающих имя ) ( данного модуля в своей строке uses ) ( Для процедур и функций Здесь опи- ) ( сываются только заголовки, но с ) { обязательным полным описанием фор- ) ( мальных параметров ) ( Раздел реализации ) implementa ti on ( В этом разделе указывается реализацией- } < ная (личная) часть описаний данного моду- } ( ля, которая недоступна для других модулей ) ( и программ Другими словами — "внутренняя ) ( кухня" модуля ) ( Список импорта раздела реализации ) uses { В этом списке через запятые перечисляются } ( идентификаторы модулей, информация интер- } < Фейсяых частей которых должна быть дос- ) ( тупна в данном модуле j < Здесь целесообразно описывать идентифика- } ( торы всех необходимых модулей, информа-} ция ИЗ которых не используется в описани- } ях раздела interface данного модуля и об ) , ^Чольэовании которых не должен знать ми} ( ОДИН Другой модуль J 1.1,ьТ°ДРа^Л^Д' для ходуля опирания ) _ . этих подразделах описываются мет-) t КИ' ^н^аиты, типы, переменные, ) УР^ < процедуры и функции которые описи-}

01ГЬМОДУ№ глобальных олисаиии ) interface const ben = 100 typs „ - srrav [1 len] of Integer T Vector » array lj- implements tion end unit VectorService ( модуль, включая сервисные ---------И функции ДЛЯ работы с одномерными ( процедуры_____________ ( массивами длиной до 100 элементов interface { Список импортируемых модулей } uses Globals ( Достаточно указать только модуль } { Globals т к в описаниях раздела } ( interface информация из других } ( стандартных и пользовательских мо } ( дулей не используется Модули ) ( описанные в interface будут дос } { тупны также и в implementation 5 ( Список экспортируемых процедур } procedure Vect_Max (Vect Т Vector N Byte} { Процедура нахождения и печати максимального } { элемента массива} procedure VecC_Min (Vect т Vector N Byte) ( Процедура нахождения и печати минимального) ( элемента массива} procedure Vect_Inverse (var Vect T_vector N Byte) ( Процедура переворота элементов массива } ( в обратном порядке } implementation ( Список uses Crt ( ( ( < ( { < ( ( ( < ( ( личного импорта модуля ) Для рассматриваемого примера здесь ) необходимо указать только модуль Crt } Хотя информация из модуля Globals мс ) пользуется в implementation указы- } ать его в этом списке недопустимо } т к каждым модуль может быть указан } только одни раз - или в interface } или a i^ylementation } Модуль Crt вместо implementation ) можно было бы описать в interface ) яиакс> это считается плохим стилем } написания модуЛеи т ж информация I ИЭ в описаниях interface ие ис- ) пользуется }
рояаниа в среде Turbo Pascal 7 О 97 procedure PrintVect (Vect T_Vector N Byte) ( Внутренняя для модуля процедура выполняющая } ( печать элементов вектора Заголовки внутренних } ( процедур х функции описываются всегда полностью } ( (с параметрами) } var х Byte begin wrxteln( Элементы вектора ) for i = I to N do wrxte (Vect[xJ 5 ) wrxteln end ( ’’’ Заголовки процедур и функции которые уже } ( t *’ описаны в разделе interface в разделе } ( '* 1’ реализации можно указывать без параметров } procedure Vect_Max var Max Integer x Byte begin Max = Vect[l] for x =2 to N do if Vect[xJ > Max then Max = Vect[xJ ClrScr PrxntVect (Vect N) wrxteln( Максимальный элемент вектора Max) end procedure Vect_Mxn var Mxn Integer i Byte begin Mxn = Vect[I] for i = 2 to N do if Vect[x] < Man then Man = Vect[x] ClrScr PrxntVect (Vect N) writeln( Минимальный элемент вектора Mxn) end procedure Vect_Inverse var Temp Integer i Byte
98 Модули begin writeln( Be-°P до переворота > PrintVect^Vect 2 Vect[N-i+H = TamP writeln{ Вектор после переворота ) PrintVect (Vect N) end { Раздел инициализации отсутствует ) end program Main ( Главная программа ) uses Crt Globals VectorService var A T_Vector i N Byte begin ClrScr writeln( Введите длину массива <= 100 ) readin{ N ) writeln( Введите элементы массива ) for i = 1 to N do read( A[i] ) readln Vect_Max (A N) readln ( Задержка результата на экране } ( до нажатия Enter } Vect_Min (A N} readln ( Задержка результата на экране ) ( до нажатия Enter } Vect_Inverse (A N} Контрольные вопросы I 2 3 4 S 6 7 8 9 В чем состоит основной принцип модального программирования0 Что обеспечивает принцип скрытия информации0 В каком разлете программы указывается подключение мо I) «и Какие существуют осоосиности при разработке собственных v i *- В чем состоит оттичие сферы иИствия переменных в модуте и процедуре Из каких разлетов состоит модуль0 Чго описывается в разлете interface0 Что опииыяается в разделе inpleoantetion Что описывается в разделе инициал нации''
ГЛАВА 7 ДИНАМИЧЕСКИ СВЯЗЫВАЕМЫЕ БИБЛИОТЕКИ Динамически связываемые библиотеки — Dynamically Linked Libraries (DLL) — Ьредоставляют прикладным программам дополнительные возможности при работе в Кипишенном режиме DOS и в режиме Windows и могут быть созданы только версиями Компилятора ВР.ЕХЕ, ВРС.ЕХЕ, BPW.EXE (см. рис. 1.2.) Помимо использования Кгандартных DLL, разработанных фирмами производителями программного Обеспечения, Borland Pascal with Objects позволяет программистам писать собственные )LL. которые впоследствии можно использовать наряду со стандартными. |Г Первоначально динамически связываемые библиотеки использовались в оболочке Windows. Borland Pascal with Objects предоставил возможность разрабатывать DLL также и для защищенного режима DOS. Ценность библиотек DLL состоит в том, что они после загрузки в оперативную память мог>т совместно использоваться несколькими прикладными программами. Хотя DLL для DOS работают в защищенном режиме DOS, однако они полностью Совместимы с DLL для Windows. Это свойство позволяет разработчикам создавать Программы работающие как в DOS, так и в Windows 1 Кроме того, DLL поддерживают “многоязыковые" проекты: в программах, написанных на языке Borland Pascal with Objects допускается использование DLL, созданных на других языках, а в программах, написанных на других языках, допускается использование DLL, созданных на Borland Pascal with Objects. Синтаксис описания динамически связываемой библиотеки имеет следу- ющий вид: библиотека заголовок библиотеки Языковая конструкция "динамически связываемая библиотека с одной стороны является продолжением и развитием конструкции ‘'модуль", а с другой стороиы имеет г "рые ограничения по сравнению с ней Особенности DLL заключаются в следующих отличиях • компоновка модулей с главной программой выполняется статически во время компиляции. a DLL — динамически, во время исполнения программы Это позволяет для нескольких одновременно работающих программ держать в оперативной памяти только по одной копии процедур и функции, используемых в каждой из них; • код и ресурсы DLL, в отличие от модуля, не компонуются с использующем ее программой, а находятся в отдельном выполняемом файле с расширением DLL который должен быть доступным при выполнении программы
100 Динамически связыеаоми ь Процедуры и функции DLL, вызываемые программой, связываются с ней динамически сравнению с модулями состоит в том, что мОдули . ограниченноD чные языковые единицы (типы, константы могут экспорт р а DLL только процедуры и функции Хотя DLL 2ожетесНоНдержать переменные, однако модули не смогут импортировать их да «пользования Любой доступ к переменным DLL должен осуществляться чепез пооцедурный интерфейс, пни запуске созданной пользователем программы на компиляцию. используемые ' В ней DLL автоматически не компилируются как модули DLL требуется компилировать отдельно 7 1 СОЗДАНИЕ ДИНАМИЧЕСКИ СВЯЗЫВАЕМЫХ БИБЛИОТЕК Как видно из вышеприведенного синтаксиса динамически связываемой библиотеки, ее структура практически такая же, как и структура программы Отличие состоит только в том, что в заголовке вместо ключевого слова program записывается ключевое слово library Это слово указывает компилятору, Что требуется создав выполняемый файл динамически связываемой библиотеки, который должен им расширение DLL, а не EXE В качестве примера оформим действия, выполняемые модулем из главы Ь виде DLL library Vector, uses Globals,Crt, procedure PrxntVect (Vect T_Vector, N Byte) , var i , Byte, begin writein(’Элементы вектора ') for 1 = 1 to N do write (Vect(x] .5, ' ) ; wrxteln, end, procedure Vect_Max (Vect T Vector, N Byte) export var Max Integer; 1 Byte, begin Max = Vect(l], for i = 2 to N do i-f Vect[x] > Max then Max = Vect(il, ClrScr, PrintVect (Vect, N), e„dWriteln<'Ma'C“"aJ'bHU* элм»"’ вектора , Max)
< w я среде Turbo Pascal " О 101 Г procedure Vect^Min (Vact T_Vector N Byte) export var Min Integer i Byte begin Min ~ Vect[l] fox i -2 to N do x£ Vect[i] < Min then Min = Vect[x] ClrScr PrxntVect (Vect N) wrxteln( Минимальным элемент вектора Min) end procedure Vect_Inverse (var Vect T Vector N Byte) export var Temp Integer i Byte begin ClrScr wrxteln ( Вектор до перепорота ) PrxntVect (Vect N) for i = 1 to N div 2 do begin Temp = Vect[i] Vectfi] = VectfN i+l] vect[N-i+l] = Temp end wrxteln ( Вектор посла переворота ) PrxntVect (vect N) end exports Vect Max index 1 VectJMin index 2 Vect Inverse index 3 begin { Раздел инициализации отсутствует } end В описании динамически связываемых библиотек важная роль приндддежит редложению exports (с буквой s в копие) которое рассмотрено в паве 1 и гРоцед\рнои директиве export (без буквы s в конце) которая указывается в оголовках экспортируемых из создаваемой DLL процедур и функции Директива export принудительно использует дтя процедуры или функции дальний тип ызова и подготавливает ее для экспортирования генерируя для процедуры/фхнкции пениальным код входа и выхода Однако фактический экспорт процедуры/функции Нс произойдет до тех пор пока она не будут указана в предложении exports °иисываемой библиотеки Операторы раздета инициализации выполняются как и у модуля однократно Но не при запуске лрограх»мы а при лервона тальной загрузке библиотеки Для зения потребности нахождения DLL в оперативной памяти саужит так мыи счетчик использования DLL Для каждой DLL устанавливается свой ислоэьзоваяия DLL который показывает скотько программ в данный
102 4ииими icchj ^ч»2Ь1Г}пемыо ЬиЬпиг)гт„, „K3V.0T Динамически связываемая библиотек по ее использую/ ес счетчИк использования больше Хэки “хранится в лам’Хмь7 иХьзуюшие DLL заканчивают работу, Знач^ Когда все прикладные пр Ханов ится нулевым и DLL удаляется из памяти Если Хика ее использоватья ста начинаст „спользовать еще одна програ ^^ю-Л1°„Сл3ьзХии» увеличивается, а операторы раздела инициалиэации потторно не выполняются 7.2. ИМПОРТ ПРОЦЕДУР И ФУНКЦИЙ ИЗ DLL „ модули написанные на языке Borland Pascal wnh 0bJe„ могут " ФУНКШШ И3 DLL ТР6МЯ СПОСОбаМИ ] По имени 2 По новому имени 3 По порядковому номеру Факт импортирования процедуры или функции указывается описанием ее заготовка в соответствующих разделах объявлений программы или .модуля Заголовки импортируемых из DLL процедур и функций при этом должны удовлетворять следующим требованиям • должна использоваться процедурная директива external, • имя DLL указывается после директивы external, v • должна использоваться дальняя модель вызова, установленная проиед\рнЗк директивой far или директивой компилятора ($F+) Ч 7.2.1. Импорт по имени Импорт процедуры или функции по ее собственному имени (идентификатору) б\дет выпотняться в том случае, если в описании ее заголовка отсутствуют директивы index и паше Например, procedure MyProc, external 'MYLIB’, 6ибтаотХмх'1'гп1НИИ ,,₽оисаура МуРгос импортируется из динамически связываемой MYLIB по своему собственному имени MYPROC 7.2.2. Импорт по новому имени Если в заголовке пг>п 5>зет имлортиоовэмп У едуры или функции указана директива пате Например, * ° свосму имени, а по имени, указанному в пате Procedure МуРгос external ’MYLIB1 лаве 'NEWNAME'
жирование в среде Turbo Pascal 7 0 103 В этом описании процедура МуРгос импортируется из динами <ески свя-пнт мои библиотеки MYLIB не по своему собственному имени MYPROC а по новому имени NEWNAME В качестве нового имени допускается любое строковое выражение константа 7.2.3 Импорт по порядковому номеру Если в заголовке процедуры или функции указана директива .index то она будет импортирована не по своему имени а по указанному в xndex порядковому значению которое может быть любым целочисленным выражением константой Такое импортирование позволяет уменьшить время загрузки модуля так как отпадает необходимость поиска имени в таблице имен DLL Например, procedure МуРгос external 'MYLIB' xndex 7 В этом описании процедура МуРгос импортируется из динамически в I ываемои библиотеки MYLIB по индексу 7 7.2.4. Модули импорта Модхпи импорта создаются с цепью улучшения структурирования программы □провождения после разработки Такой модуль представляет сооои заключенный кпр} модуля перечень импортируемых из DLL процедур и функции а также ния всех типов и констант необходимых для интерфейса с DLL Модули рта не обязательны для интерфейса с DLL но они значительно упрощают Г Pjootkv программ использующих DLL В качестве примера рассмотрим объединение в модуль MyVector процедур ртирчемых из вышеописанной динамически связываемой библиотеки которая пся в файле с именем VECTOR DLL unit MyVector interface uses Globals pmr’odnra Vect Max (Vect T_Vector N Byte) procedure Vect Min (Vect T__Vector N Byte) procedure Vect Inverse (var Vect T__Vector N Byte) impl amen ta ti on procedure Vect_Max procedure Vect Min procedure Vect_Inverse external external external VECTOR VECTOR VECTOR index 1 index 2 index 3 end Для проверки работы этого модуля и библиотек кспользоваиа например такая программа
Т ,чамически Связываемые Q'^nuorn^j ^XTcTt^obals. «У—; var А т Vector, 1, N . Byte, begin ClxScx; wrxteln ('Введите длину массива <= readin( N ) ; write In ('введите элементы массива. for x .= 1 to N do read ( A[i] ) ; readin; Vect Max (A, readin, Vect_Mxn (A, readin, Vect Inverse N) , N) , (A, N) end 7.3. ОБЛАСТЬ ДЕЙСТВИЯ ПЕРЕМЕННЫХ В DLL Как указывалось выше. DLL, по сравнению с модулями, имеет более ограниченные возможности взаимодействия с вызывающими ее программами и модулями DLL располагается в собственном сегменте данных, и любая описанная в ней переменная будет локальной для этой DLL Кроме того, DLL не может ни получить доступ к переменным, описанным в вызывающих се модулях, ни эм. портировать переменные в другие модули Все взаимодействия DLL с вызывающими модулями должны быть реализованы только через процедурный интерфейс. 7.4. DLL, СОВМЕСТНО ИСПОЛЬЗУЕМЫЕ В ЗАЩИЩЕННОМ РЕЖИМЕ DOS И В WINDOWS Совместно используемые DLL совместимы на уровне двоичного коД® компиляции такой DLL в качестве целевой платформы требуется установить Windows Такая установка выполняется в интегрированной оболочке с помолы0 команды Target в меню Compile DLL, скомпилированная для защищенного ре****4 DOS, выполняться под управлением оболочки Windows не может так как библиотека исполняющей системы защищенного режима DOS использует отдельные фуикиио- налызые рн • f- DPMI, которые следует избегать в Windows Кроме того. DLL может взаимодействовать с операционной систем0И WAP), который включает функции, являющиеся обшимИ 4M3 ППС u U/.~J......................- совмести, - ТОЛЬКО 4CV . __м, для защищенного режима DOS н Windows
„дарование в среде Turbo Pascal 7 о 105 t: 10 Контрольные вопросы Какие возможности предоставляют программисту DLL9 Для каких операционных сред возможна разработка DI I 9 g чем состоит отличие DLL от модуля9 В чем состоит отличие структуры DLL от структуры программы9 Для чего предназначен счетчик использования DLL9 Какими способами может быть осуществлен импорт процедур и функции из DM ’ При каких условиях может быть осуществлен импорт процедуры по ее собственном1- вмени9 В каком случае осу ществляется импорт процедуры по новому имени9 В чем состоит преимущество импорта по порядковому номеру9 Что представляет собой модуль импорта9 Какая область действия переменных в DLL9
ЧАСТЬ 2 СТРУКТУРЫ ДАННЫХ и РАБОТА С НИМИ СРЕДСТВАМИ ЯЗЫКА TURBO PASCAL ГЛАВА 8 КЛАССИФИКАЦИЯ СТРУКТУР ДАННЫХ 107 ГЛАВА 9 ОБОБЩЕННЫЕ УПРАВЛЯЮЩИЕ КОНСТРУКЦИИ АЛГОРИТМОВ И ИХ РЕАЛИЗАЦИЯ СРЕДСТВАМИ ЯЗЫКА Turbo Pascal 112 ГЛАВА 10 РАБОТА С ДАННЫМИ СТАТИЧЕСКОЙ СТРУКТУРЫ 117 ГЛАВА 11 ПРОЦЕДУРЫ И ФУНКЦИИ 151 ГЛАВА 12 РЕКУРСИЯ ... 1 оо ГЛАВА 13 ФАЙЛЫ 182 ГЛАВА 14 РАБОТА С ДИНАМИЧЕСКИМИ СТРУКТУРАМИ ДАННЫХ 'i
ГЛАВА 8 КЛАССИФИКАЦИЯ СТРУКТУР ДАННЫХ Структуры данных наряду с алгоритмами являются основными составными частями создаваемых программ. Одну из своих книг профессор Н Вирт буквально гзк и назвал “Алгоритмы + Структуры данных = Программы" [6] Используемые в программировании данные можно разделить на две большие Группы Данные статической структуры — это такие данные, взаиморасположение и взаимосвязи э icmchtob которых всегда остаются постоянными Данные динамической структуры — это данные, внутреннее строение которых формируется по какому-либо закону, но количество элементов, их взаиморасполо- жение и взаимосвязи могут динамически изменяться во время выполнения программы согласно закону формирования | а Классификация структур данных в этой гпаве рассматривается в обще- v/ft теоретическом плане безотносительно к какому-либо языку программи- * < рования Поддержка или отсутствие поддержки тех или иных структур ------даниых в Turbo Pascal будет уточняться особо _________________________ 8.1. ДАННЫЕ СТАТИЧЕСКОЙ СТРУКТУРЫ Ниже показана классификация данных статической структуры
Кпоссифихаци» структур 108
, в среде Turbo Pascal 7 О I lll)lhic статической структуры могут быть простыми (скалярными) и ^сггыы>ымн (агрегативными), которые формируются из простых структур по ^омх-.кбо ^кону. Простым данным в языках программирования соответствуют стандартные к/прсД0ПРедеЛСПИЫ^С^ типы„ даннь,х’ к которым, как правило, относят арифметиче- ские (натуральный, целый, вещественный, комплексный), символьный, булевским . уклатсльныи (ссылочный) типы В Turbo Pascal включены натуральные типы gyte Word, целые типы Integer, Shortint, Longint, вещественные типы Real, Single, Double. Extended, Comp, булевские типы Boolean, ByteBool, WordBool, LongBool, C[j\u e 11.НЫ11 тип Char и указательный тип Pointer Вещественные типы Turbo d могут быть Представлены как с фиксированной, так и с плавающей точкой Стандартные типы для представления комплексных чисел в Turbo Pascal отсутствуют Кроме того, некоторые языки программирования (первым таким языком был язык Pascal) позволяют программисту описывать собственные скалярные типы путем перечисления всех допустимых для них значений или указания поддиапазона значении другого скалярного типа В Turbo Pascal такие возможности поддерживаются в виде перечисляемых и интервальных типов соответственно Данные составной структуры бывают однородными, то есть такими, у которых все элементы одинакового типа, и неоднородными (комбинированными), которые объединяют в единое целое разнотипные элементы К данным однородной структуры принадлежат массивы, строки и множества, а к данным неоднородной (комбини- ованной) структуры — простые записи, вариантные записи, объединения и объекты Массивы можно классифицировать по двум разным признакам • по количеству размерностей массивы разделяются на одномерные массивы (векторы), двухмерные (матрицы) и многомерные (трех-, четырехмерные и так далее); • по типу элементов массивы разделяются на массивы простых данных, массивы однородных структур данных, массивы неоднородных структур данных и массивы файлов Что касается реализации неоднородных структур данных в Turbo Pascal заметим шее Простые и вариантные записи в Turbo Pascal поддерживаются отдельными сическими конструкциями Объекты по своей структуре аналогичны записям, но в отличие от них опт включать поля не только простых и составных типов, но и процедурных чпов, что существенно повышает их мощность как структуры данных В связи этим объекты иногда выделяют на более высоком уровне классификации наряду простыми н составными структурами данных. Работа с данными статической структуры рассматривается в 10-й главе 8.2. ДАННЫЕ ДИНАМИЧЕСКОЙ СТРУКТУРЫ К данным динамической структуры относят файлы. несвязанные и связанные ^иамические данные Заметим что файлы в данной классификации, в отличие от классификации авторов отнесены к динамическим структурам данных Это сделано исходя ЬЬ|шеприведенного определения. Хотя удаление и вставка элементов в середину ^ла не допускаются, зато длина файла в процессе работы программы может ^Меняться - увеличиваться или уменьшается до нуля А это уже динамическое ®оист»о файла как структуры данных
Кпассификация структур дамииг 110 Классификация данных динамической структуры показана ниже Реализация файлов в Turbo Pascal рассматривается в главе 13 а Р^алиаацц несвязанных н связанных динамических данных в 14-й главе
( шмирование в среде Turbo Pascal 7 О Контрольные вопросы । [li какие группы можно разделить используемые в программировании данные9 2 В чем состоит основное отличие между данными статической и динамиче- скои структуры’ 3 Какие данные относят к данным статической структуры9 4 Какие данные относят к однородным9 5 Какие данные относят к неоднородным9 6 По каким признакам могут быть классифицированы массивы9 7 Как реализованы строки в Turbo Pascal9 8 Какие неоднородные структуры данных реализованы в Turbo Pascal9 9 Какие данные относят к данным динамической струкгуры9 Ю Какие существуют разновидности связанных динамических данных9
ГЛАВА 9 ОБОБЩЕННЫЕ УПРАВЛЯЮЩИЕ КОНСТРУКЦИИ АЛГОРИТМОВ И ИХ РЕАЛИЗАЦИЯ СРЕДСТВАМИ ЯЗЫКА Turbo Pascal За время схшсспювани i программирования пя записи алгоритмов были разработаны так называемые управляющие конструкции алгоритмов С течением времени и развитием языков про)раммирования управляющие конструкции совершенствовались предлагались новые и к настоящему времени их состав фактически стандартизирован и стал классическим Все современные процедурные языки программирования (такие как Pascal С Modula 2 Ada и другие) имеют наборы операторов которые поддерживают функции всех классических управляющих конструкции Различие состоит только в синтаксисе записи этих конструкции и некоторых особенностях их реализации Хорошее понимание и владение управляющими конструкциями в большой степени определяет профессиональный уровень программиста Можно сказать что хмение программировать (для процедурных языков) — это в первую очередь умение пользоваться наиболее общими для всех языков конструкциями и структурами данных Презиленту фирмы Microsoft Биллу Гейтсу принадлежат следующие слова Если человек хочет стать великим программистом то язык имеет второ степенное значение их можно выучить сколько угодно Для человека хорошо знающего язык С перейти на Pascal не составит большого труда (21] Биллу Гейтсу довольно своеобразно и остро вторит основоположник структурного Программирования Эдсгер Деикстра Заметим что фраза Деиксры была сказана во времена примитивных версии языка Basic когда его операторы не отражали классических управляющих конструкции и не поддерживали структурных принципов разработки программ Итак Дейкстра сказал [ 16 | Невозможно научить хорошо программировать студентов ориентированных t ерноначально на Basic Как потенциальные программисты они умственно оболванены оез надежды на исцеление Ведущие ученые программисты 70 х голов теоретически доказали что побои цгоритм пронзвогьной сложности может быть реализован с использованием тотько двух управляющих конструкций конструкции выбора и конструкции цикла С предусловием Здесь следует отмстить что хотя такое написание азюоитмов возможно оно получается достаточно громоздким и не наглядным Позтомх кпасси «ескии состав включает значительно большее количество конструкции которые взаимно пересекаются по своим функциям и во многих сл чаях могут оыть заменены одна другой * В языке Turbo Pascal используется смешанный подход * , u к реализации vправзяюших конструкций — некоторые конструкции реализованы cttjvktv •ператорами языка а другие — стандартными процедурами ктурн Рассмотрим набор классических управляющих конструкций и их релизах ю в
|WM I панно в сроде ГигЬо Pascal 7 О 113 9 1 Конструкции условия (разветвления) D условная копор>кцИИ рапвонпп п пик структурного oncparopi if I If l< pH 11 П1Ч I___________ if выражение then оператор ») Полная условная конструкция также реализован» в апле чруктурною опериор» ‘f I II крнпнвои if выражение then оператор also оператор И Паю ни» конструкция выбора (переключения) рсциювш» в виде оруктурного puopi case Осз UbTcpHrtTllBbl case Переключатель of Список констант! Оператор! Список констант2 Оператор? Список константЗ Оператор? Список константЫ Операторы and 4' Полная конструкция выбора (переключения) рс ми гоним в виде структурного puopi case». LilRpHitHHOU case Переключатель of * Список констант! Оператор! Список констант2 Оператор? Список константЗ Оператор! Список константЫ Операторы else ОператорЕ end 9 2 Конструкции повторения (цикла, итерации) Комиржцин цикла с предусловием реалнзовш 1 в виде структурного оператор» while while Условие do begin Оператор Оператор Оператор end к"«чр»м(и< шил* с оостуаюшхх рг
управляющие констру* * (,, <оритЛ1П 114- ~ ~ гереаt Оператор Оператор Оператор until Условие 3) Конструкция цикла со счетчиком (с параметром) в полном виде не поддерживается ни одной из реализаций языка Pascal включая и Turbo Pascal В полном виде этой конструкции предполагается возможность задавать любой шаг изменения счетчика определяемый положительной или отрицательной десятичной дробью В Turbo Pascal в виде структурного оператора цикла far реализовано подмножество управляющей конструкции цикла со счетчиком в котором разрешено задавать только два значения шага цикла или +1 или 1 С шагом +1 for Переменная = НачальноеЗначениеСчетчика to КонечноеЗначениеСчетчика do Оператор С пл] ом -I far Переменная = НачальноеЗначениеСчетчика downto КонечноеЗначениеСчетчика do Оператор 4) конструкция безусловного (бесконечного) цикла непосредственно не реализова на ни операторами ни стандартными процедурами Turbo Pascal Однако она легко моделируется с помощью циклов while или repeat while True do оператор repeat until False 9.3. Конструкции переходов 1) Конструкция безусловного перехода пня к^'1гг^кция противоречит принципам структурного программнрова- * Ж 1^ия и ес нспо «ьювание не рекомендуется.
а среде Turbo Pascal 7 О 115 goto Метка 2) Одно^овнсвая конструкция выхода из цикла Эта конструкция выполняет переход на первый оператор расположенный непосредственно за циклом В Turbo Pascal версии 7 0 она реализована в виде стан лртнои процедуры Break В предыдущих версиях Turbo Pascal реализована не была while Условие do begin Оператор if выражение then Break Оператор end 3) Многоуровневая конструкция выхода из цикла Эта конструкция выполняет переход аналогично одноуровневой но сразу на зхазанныи уровень вложенных циклов Она не является строго структурной и в Turbo Pascal не реализована 4) Одноуровневая конструкция продолжения цикла Эта конструкция выполняет переход на новую итерацию цикла В Turbo Pascal версии 7 0 она реализована в виде стандартной процедуры Continue В пре дыд\ших версиях Turbo Pascal реализована не быта while Условие do begin Оператор if выражение then Continue Оператор end 5) Многоуровневая конструкция продолжения цикла Эта хони.тр\кция выпозняет переход аналогично одноуровневой но сразу на указанный уровень вложенных циклов Она не является строго структурной и в Turbo Pascal нс реализована 6) Одноуровневая конструкция выхода из блока Эта конструкция завершает выпотнение активного 61ока и передает управ Ление в точкх вызова В Turbo Pascal версии 7 0 также как и в предыдущих верен ях * Pascal она реализована в виде стандартной процедуры Exit procedure ExaiapleExi t begin Оператор if выражение then Exit i Оператор * end
Управляющие конструкции алеориуь 1} Многоуровневая конструкция выхода из блока 7) MHOWPO нс ция полняет переход аналогиЧНО одноуровневой, но сразу Hj указанный уровень вызовов блоков Она не является строго структурной и в Turt)0 Pascal не реализована Подводя итог рассмотрению управляющих конструкции заметим следуЮЩее С появлением в Turbo Pascal конструкций Break и Continue в программистской популярной литературе стало встречаться высказывание, что они были заимствованы из языка С Это неверно, поскольку все рассмотренные управляющие конструКцИи были известны до появления языка С Правильно будет говорить, чго язык С заимствовал эти конструкции из теории проектирования языков раньше, чем язык Turbo Pascal Контрольные вопросы 1. С помощью каких двух управляющих конструкций может быть реализован алгоритм произвольной сложности9 2. В состоит отличие чем между полной и неполной условными конструкциями9 3. Как реализована конструкция выбора9 4. Чем отличаются циклические конструкции с предусловием и с постусловием9 5. С какими ограничениями реализована конструкция цикла со счетчиком в Turbo Pascal9 6. Какое значение может принимать шаг цикла оператора for в Turbo Pascal9 7. С помощью каких операторов Turbo Pascal может быть смоделирован бес- конечный ЦИКЛ9 8. Почему не рекомендуется использование конструкции безусловного перехода9 9. С помощью какой процедуры в Turbo Pascal реализована одноуровневая конструкция выхода из цикла и в чем состоит ее отличие от многоуровневой конструкции выхода из цикла9 10. Как работает конструкция продолжения цикла’ II. Какая процедура Turbo Pascal соответствует конструкции выхода из блока’
ГЛАВА 10 F работа с данными статической II ____________________структуры 10.1. РАБОТА С ДАННЫМИ ПРОСТЫХ ТИПОВ 10.1 -1 - Ввод-вывод значений переменных простых и строковых типов Стандартный ввод в языке Turbo Pascal осуществляется встроенными РР' сдурами |Read (имя файловой переменной, список переменных) и I Readin (имя файловой переменной, список переменных), а стандартный вывод — процедурами Write (имя файловой переменной, список элементов вывода), и Writein (имя файловой переменной, список элементов вывода). Стандартный ввод выполняется из предопределенного текстового файла с именем Input, который связан с клавиатурой, а стандартный вывод выполняется в предопределенный текстовый файл с именем Output, который связан с дисплеем В случае стандартного ввода-вывода имя файловой переменной в процедурах Read, Readln. Write, Writein указывать не обязательно, так как по умолчанию для ввода принимается имя Input, а для вывода — имя Output. Таким образом, фрагменты Readln (Input,А,В); Wrxteln (Output,'А=',А,’В»',В); Readln (А,В); Wrxteln (’А=’,А,*В=',В), будут эквивалентными Во всех реализациях и версиях языка Pascal используется концепция так и аемого поэлементного ввода-вывода То есть значения переменных структура- 'ИЫ-с типов не могут быть введены (или выведены) одной процедурой ввода (вывода) ‘вода (вывода) таких переменных необходимо использовать операторы цикла ючение составляют переменные типа String, поскольку этот тип в Turbo I выделен в отдельную категорию “строковый тип При написании фрагментов стандартного ввола-вывола необходимо также ‘'ЧИНИТЬ, что • процедурами Read и Readln допускается чтение значений только цегых. вещественных, символьного и строкового типов, • процедурами Write и Wnteln допускается запись значений только целых, вещественных, символьного, строкового и булевских типов
работа с данными статической структур 11В Ввод знамений вышеуказанных типов процедурами Read и Readin выполняется с учетом следующих правил Ввод символьного типа Программа var А(В,С Char Read (А) ( А будет равно $ } Read (В) , (В будет равно пробелу Read (С) ( С будет равно 7 } клавиатура end Процедура Read считывает из файла один символ и присваивает его переменной Если перед выполнением процедуры Read функция Eof (конец файла) принимала значение True, то переменной присваивается символ с ASCH-кодом 26 Если функция Eoln (конец строки) имеча значение True то соответствующей переменной присваивается символ с ASCII-кодом I3 (символ возврата каретки) Счедуюшая операция Read начнется со следующего символа в файле 2 Ввод значения в переменную целого или вещественного типа Программа var А,В Integer ХЛ Real, begin Read (А) , ( А будет равно 77 } Readin (В) , ( В будет равно -34 24 } Read (X), ( X будет равно 5 87е-5 ) Readln (Y) ( Y будет равно 555 ) end Исходный файл или клавиатура 77 -34 24 5 87е-5 555 образующих'uein<-Ruпожидас1 поступления последовательности символов Х^иТилТ^иХГкХТХ ЧГ°со знаком Лю6ыс п₽о6слы’зиаки пропускаются Выаелеии» ,К иа Строки, предшествующие чистовой строке симвоча табуляции поиз числа выполняется до обнаружения первого пробела выделенная послеловате^ы^Д?^^2 строки или признака конца файла Ести Происходит ошибка ввода-вывола водо“ ие соответствует числовым форматам то пробела символа и" " с1'™ошои процедуры Read начнется с чтение предыдущим оператором 1 КОТОРОМ остановилось 3 Ввод значения в Переменную и„. ну зевой базой (array (О NJ of Chari к >ВоГ г типа (Siring) или в массив символ0 *-
1Ммироо 1ние в среде Turbo Pascal 7 О 119 Программа Исходным файл или клавиатура ($Х+1 var A array [0 5] of Char, SI, S2, S3 String [10], heaxn Read (A), ( А Судет равно 1AAAAA' } Read (SI) { Si будет равно 'BBBBBBB’ } Read (S2), ( S2 будет равно пустой строке ) Readln { переход на новую строку ) Read (S3), (S3 будет равно 'ABCDEFGHIJ'} end АААААВВВВВВВ ABCDEFGHIJ Процедура Read считывает столько символов исходных данных, сколько указано оортлеиии строковой переменной Пробел при этом разделителем, как при чтении ювые переменные, не считается Если в текущей строке исходных данных v HX.I. символов меньше чем требуется по описанию переменной то будут риппны только наличные в этой строке символы Выполнение следующей pout ix рь» Read начинается с метки конца строки которой завершилась предыдущая гр< Ki То есть процедура Read при чтении строковой переменной переход на новую 1 рокх ие делает Такой переход может быть выполнен только процедурой Readln Испопьзование процедур Read и Readln для ввода значений в символьные utauibt с нулевой базой допускается только при включенном расширенное! синтаксисе щрекпии 1$\+}) Завершающий н^ль-енмвол NULL (код ASCII 0) добавляется ВТОМ 1ТИЧССКИ Отличие работы процедуры Readln от процед>ры Read состоит в том что она ск it выполнения действий процедуры Read осуществляет переход на следующую Греку исходных данных и в том что вызов Readln без параметров приводит к ерсмешению текущей позиции чтения исходных данных в начало следующей *** nut имо от и сличил отсутствия тайных в текущей строке Вывод Kikjijh j icmcht вывода процедуры Writeln имеет вид Expr ( MinField ( DecDigits )) Гхрг — нывошмое выражение которое может быть символьное Ииесгвснного сорокового им ' MmField - выражение щнимальную ширину пан 1 т»>рая должна быть its — выражение целою nnia задающее число десятичных знаков nt печ rn после пссятмчиой точки - ... ни .«• «члн Ехрг имеет вещественный 1егся, то число выводится в tv в формате с плавающей
Работе с донными стати 120 Формат вывода с фмххированной точкой Г<пробелы>1 C-J <цифры> С <знаки~дроб части>] Формат вывода с плавающей точкой I [-] <цифра> <знаки_дроб части> Е Г+-<покаЗатель_степени>j J Процедура Wnteln является расширением процедуры Write ддя файлов которая после выполнения действий процедуры Write записып ТеКст°вЫх конца строки (символы “возврат каретки" и “перевод строки’) пСТ Признак Wntetii без параметров, в файл записывается только признак конца строки* еЫз°ие Пример program TestWrxte, uses Crt, const x Integer - 12345, r Real » -123 1234567, C Char = ' $ 1 , b Boolean = True, s String = ’Turbo Pascal’ , begin ClrScr, Wrxteln (‘Печать без форматирования 1>, Wrxteln (x, r, c, b, s), Writein, Формате’
f i ч -uni в среде Turbo Pascal 7 О |y IbT «П Печать без форматирования ~ ------- 12345-1 23123456700007E+0002$TRUETurbo Pascal Форматированная печать 12345 -123 123 $ TRUE Turbo Pascal печать вещ чисел в фиксированном формате -123 -123 123 -123 123 -123 1234567 -123 12345670 -123 12345670 Печать вещ чисел в плавающем формате -1 2Е+0002 -1 2Е+0002 -1 23Е+0002 -1 23123457Е+0002 -1 2312345670000650Е+0002 10.1.2. Основные встроенные процедуры и функции для работы со значениями простых типов Арифметические типы f Функция Abs — возвращает абсолютное значение аргумента Ф> иия Aretan — возвращает арктангенс аргумента Ф иия Cos — возвращает косинус аргумента <( шя Схр — возвращает экспоненту аргумента Ф 1ия Frac — возвращает дробную часть аргумента 1 ИЯ Int — возвращает целую часть аргумента Ф j ия Ln — возвращает натуральный логарифм аргумента <1 ИИЯ Pl — возвращает значение числа Pi — (3 141592653897932385) Ф । ия Sin — возвращает синус аргумента Ф ния Sqr — возвращает аргумент в квадрате Ф шя Sqrt — возвращает квадратный корень аргумента Г| i> pa Dec rvpa Inc ния Odd Порядковые типы — уменьшает значение переменной — увеличивает значение переменной — проверяет является ли аргумент нечетным числом — возвращает предшествующее значение аргумента — возвращает его пос тезу юшее значение Указательные типы — возвращает адрес заданного объекта — возвращает смешение для заданного объекта — преобразует адрес базового сегмента и смещение в значение типа Pointer — возвращает адрес сегмента для задтн “ г° • ь'т 1
Работа с данными статической сгпру», 122 10.1.3. Особенности работы с пользовательскими простыми типами К пользовательским простым типам относят перечисляемый гип тип-диапазон Работа с переменными типов-диапазонов осуществляется таМе как и сих 'родительскими” типами, но с учетом их меньшего диапазона допустимых значений Использование в программах переменных перечисляемых типов conpflAej.I0 со следующими особенностями • перечисляемые типы являются порядковыми, а следовательно к их значениям применимы все процедуры и функции, допустимые для порядковых типов, • значения перечисляемых типов в качестве аргументов процедур Read, Readln Write. Wnteln не допускаются, • единственной группой операций, которые допустимо использовать с операндами перечисляемых типов, является группа операций отношения Ни складывать, ни умножать, ни вычитать, ни выполнять какие-либо другие действия с переменными перечисляемых типов не допускается, • переменные перечисляемых типов разрешено использовать в операторах присваивания а также в качестве индексов массивов и границ оператора for Приведем примеры, демонстрирующие некоторые из допустимых для перечисляемых типов действия Объявление перечистяемого типа type Days = (Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday) , var Yesterday, Today, Tomorrow Days, Использование переменных и значений перечисляемого типа в выражениях и операторе присваивания if Today = begin Yesterday Tomorrow end, Saturday then = Friday, = Sunday, выбора Использование переменной и значений перечисляемого типа в оператор) case Today of Sunday Monday Tuesday Wednesday Thursday Friday Saturday end, Wrxteln Wrxteln Wnteln Wrxteln Wrxteln Wrxteln Wrxteln ('Сегодня (1 Сегодня ( 'Сегодня ('Сегодня ('Сегодня ('Сегодня воскресенье ') , понедельник') вторник'), среда 1) четверг‘) пятница‘) суббота') спецификации оп"ратора₽ии“а Xr” ™аЧенИЙ перечисляемого т.п ТосиУ - Monday to Friday do begin 2 end
мИрррдние в среде Turbo Pascal 7 О 123 I (pjHMiilfl Ord функция Round функция Trunc 10.1.4. Стандартные функции преобразования типов и СЬг возвращает символ, заданный целым числом которое пред- ставляет код ASCII — возвращает порядковый номер значения перечисляемого типа — округляет значение вещественного типа до значения, имеющего длинный целый тип — усекает значение вещественного типа до значения, имеющего длинный целым тип 10.2. РАБОТА С СОСТАВНЫМИ ДАННЫМИ ОДНОРОДНОЙ СТРУКТУРЫ 10.2.1. Массивы Синтаксические диаграммы описания данных типа “массив" приведены в конце подраздела описания типов в главе 3 Массив — это структура данных, которая представляет собой однородную, ^фиксированную по размеру и конфигурации совокупность элементов простой или Составной структуры, упорядоченных по номерам Массив определяется именем (идентификатором) и количеством размерностей (координат), необходимых для указания местонахождения требуемого элемента массива Имя массива является единым для всех его элементов г Поскольку конфигурация элементов массива фиксирована то к отдельному [элементу можно обращаться с помощью одного или нескольких индексов в [зависимости от количества размерностей массива В качестве индексов могут |испотьзоваться константы и переменные порядковых типов Элементами массивов (ыогут быть как простые переменные любых типов, так и переменные составных типов ^(массивов строк, записей и т д ) При решении задач, как правило, используются одномерные двухмерные и •трехмерные массивы Массивы большей размерности на практике встречаются ^>сдко f Схематично одно- двух- и трехмерные массивы можно представить таким образом Одномерный массив (вектор) Направление изменения индекса 12 3 4 5 6 п ft I I II I I । I Д I------------------------------> А[6] или А[1] (если 1'6) исание const п = 100, var A array (1 nJ of Real
Работа с данными статической гтру^, 124 const п = 100 Rector = array [1 n] of Real vac A T Vector Двухмерный массив (матрица) Направление изменения второго индекса const m = 30 n =50 type T_Matr = array [1 ml n] of Real vac A TMatr Трехмерный массив Направление изменения второго индекса А[1.),к] (если 13 j 7 k 1)
е1 игС в среде Turbo Pascal 7 О 1([1кЛ1|ИС__________________________ const ' ' -— ш = 30; п =50; р = 20 var Л array .„.j р] „f Real const m = 30, п =50; p = 20; type T_Array = array [1..m,1..n,1..p] of Real; var к : T_Array ; Классическими примерами для демонстрации возможностей массивов являются [задачи сортировки и поиска г 10,2.2. Сортировка массивов При решении задачи сортировки обычно выдвигается требование минимального .пользования дополнительной памяти, из которого вытекает недопустимость ",1менения дополнительных массивов । Для оценки быстродействия алгоритмов различных методов сортировки, как |правило, используют два показателя" • количество присваиваний, • количество сравнений Все методы сортировки можно разделить на две большие группы • прямые методы сортировки; • улучшенные методы сортировки Прямые методы сортировки по принципу, лежащему в основе метода, в --о очередь разделяются на три подгруппы I) сортировка вставкой (включением), 2) сортировка выбором (выделением), 3) сортировка обменом (“пузырьковая" сортировка) Улучшенные методы сортировки основываются на тех же принципах, что и прямые, но используют некоторые оригинальные идеи для ускорения процесса сортировки Прямые методы на практике используются довольно редко, так как .Имеют относительно низкое быстродействие Однако они хорошо показывают суть .основанных на них улучшенных методов Кроме того, в некоторых случаях (как правило, при небольшой длине массива и/или особом исходном расположении ромеитов массива) некоторые из прямых методов могут даже превзойти улучшенные Сортировка вставкой Принцип метода: Массив разделяется на две части отсортированную и неотсортированную J ‘'-нты из неотсортированной части поочередно выбираются и вставляются в Тированную часть так чтобы ие нарушить в ней упорядоченность элементов ' работы алгоритма в качестве отсортированной части массива принимают
Работе с данными статической стру^ 126 только мин первый элемент, а в качестве неотсортированной части - все ост^ элементы^ а^ритм будет состоять из п-1-то прохода ( л - размеру массива), каждый из которых будет включать четыре действия: • взятие очередного /-го неотсортированного элемента и сохранение его # дополнительной переменной; • поиск позиции / в отсортированной части массива, в которой присутстви взятого элемента не нарушит упорядоченности элементов; е • сдвиг элементов массива от /-/-го до /-го вправо, чтобы освободить най денную позицию вставки; • вставка взятого элемента в найденную/~ю позицию Для реализации данного метода можно предложить несколько алгоритмов которые будут отличаться способом поиска позиции вставки. Рассмотрим схе реализации одного из возможных алгоритмов. Схематично описанные действия образом’ одного прохода можно представить следуюшиь ф - Сохранение © * Поиск места вставки ф - Сдвиг ® - Вставка Схема сортировки методом вставки Слева в кружке указан номер прохода Результат I 2 3 4 5 П=б»
127 гпаммировэние В среде Turbo Pascal 7 о ||р ,Р1ШП реализующая рассмотренный щ.оритм будет иметь слелук тин „и program InsertionSort uses Crt const n = 20 ( длина массива ) type TVector = array [1 n] of Real var Vector TVector В Real 13k Integer begin ClrScr Writeln ( Введите элементы массива ) for 1 = 1 to n do Read (Vector[i]) Readln (------------------------------------------------ ) for 1 = 2 to n do begin В = Vector[i] ( Взятие неотсортиро- ) ( ванного элемента ) ( Цикл поиска позиции вставки ) ^/3=1 while (В > Vector[j]) do 3 =3+1 { После окончания цикла индекс ) ( 3 Фиксирует позицию вставки ) ( Цикл сдвига элементов для освобождения ) ( позиции вставки } for k =i-l downto 3 do Vector[k+1] = Vector[k] ( Вставка взятого элемента на найденную позицию ) Vector[3] = В end (---------------------------------------------- -) Writeln( отсортированный массив ) for 1 = 1 to п do Write (Vectorti] 8 2) Writeln end Сортировка выбором Принцип метода Находим (выбираем) в массиве элемент с минимальным значением на ° «с от 1 го элемента до я го (последнего) элемента и меняем его местами с элементом На втором шаге находим элемент с минимальным значением зиле от 2 го до я го элемента и меняем его местами со вторым элементом гак далее для всех элементов до я-/ го смотрим схему алгоритма прямого выбора
работа с данными статичоскои струит* 128 1 2 । 3 4 5 6 7 ,п~8| @ ежен® ^Звпнп 1 2 3145 6 7 П=8 *S=4 "nun 1 2 3 4 15 б 7 n=? © шжнЦиж S = 5=m»n 12 3 4 516 7 пх% © р||2|3|4|5 7|11]9] S=6=m>n 1 2 3 4 5 617 п=г © |1 |2|3|4 |5|7W9] S=7 min Результат 1 2 3 4 5 6 7 |п=8 |1 |2|3]4 |5|7|9р1] Пз=п=8 Программа, реализующая метод выбора, будет иметь следующий вид. progr‘am Selectionsort; uses Crt; const n = 20; { длина массива ) type TVector = array (l..n) of Real; var Vector : TVector; Min Real; Imin, S Integer; i • Integer; begin ClrScr; Writeln ('Введите элементы массива:1 ); for i 1 to n do Read (Vector [i]); Readln; ) for S := 1 to n-1 do begin ( Поиск минимального элемента в диапазоне } ( от S-ro элементе до п-го } Min :• Vector[S]; Imxn :« S; for 1 s+1 to n do If Vectorfl] < Min then begin Min Vector(i), lain « i •nd. ( обман иес,«м мюешального M „.ro , Vector I lam) - vector [S) ; Vectorts) - Mln. •nd, L _ —
цм/ровзиие в среде Turbo Pascal 7 о 129 Wrxteln('Отсортированный массив ) for I » 1 to n do Write (Vector[i] 8 2) Writein end Сортировка обменом (“пузырьковая” сортировка) принцип метода. Слева направо поочередно сравниваются два соседних элемента, и если их ,аИМорасположение не соответствует заданному условию упорядоченности то они Меняются местами Далее берутся два следующих соседних элемента и так далее до юнца массива Посте одного такого прохода на последней л-ой позиции массива будет стоять максимальный элемент (“всплыл” первый “пузырек") Поскольку максимальным лсмент уже стоит на своей последней позиции то второй проход обменов зыпотняется до л-7-го элемента И так далее Всего требуется п-1 проход Рассмотрим схему алгоритма сортировки методом прямого обмена по сбыванию © |1 |3; 2|415 jТ]9]гП *"з ‘ ' 1 2 3 4 5 6 7 |п=2 © |51317]1 |4 j2]9|гП Гз ТТ---- ТТЛ 4 7’Т О |~3|5|1 |4 ; 2|7[э |11| © ГЗjl |4[2|5|т|9|11! Уз" YT к-s' © И |21 з|4 15 17191111 1 2 । 3 4 5 67 п=2 © |Г|2|3|4|5|7|9!11| Резулыа1 1 I 2 1 |П=$, [ 3 j 415 17 j 91111 Программа, реализующая метод обмена (“пузырька ’) будет иметь стедую program BubbleSort use* Crt const n • 20 ( длина массиве I type TVector « array tl nJ of Raal var Vector TVector В Real i k Integer _____________.
Рабств с данными статически 130, begin ClrScr Writein (’Введите элементы массива 'j for i a 1 to n do Head {Vector [i]) Headin »ВоХ.кяме "оХАкого Аксиального элем.»,a , ( на k-ю позицию ) -i - 1 to k-1 do £oC A . ___4.^T-ri+il then begin В = vector[л] Vector[ij = v В end Writein( отсортированный массив ) , £or i = 1 to n do Write (Vector[i] 8 2) Writein end Сравнение прямых методов сортировки Теоретические и практические исследования алгоритмов прямых методов сортировки показали, что как по числу сравнений, гак и по числу присваиваний оии имеют квадратичную зависимость от длины массива п Исключение составляет метол выбора который имеет число присваиваний порядка п*1п(п) Это свойство алгоритма выбора полезно использовать в задачах сортировки в сложных структурах данных когда иа одно сравнение выполняется большое число присваивании В таких задачах метод выбора успешно конкурирует с самыми быстрыми улучшенными методами сортировки Есзи сравнить рассмотренные прямые методы между собой, то в среднем методы вставки и выбора оказываются приблизительно эквивалентными и в несхотько раз (в зависимости от длины массива) лучше чем метод обмена ( пузырька ) 10,2.3, Двоичный поиск < (бинарный поиск, поиск делением пополам) Алгоритм двоичного поиска допустимо использовать для нахождения элемента только в упорядочемньсх. массивах Рассмотрим ею иа примере упорядоченного по неубыванию (Vector!:! <= Vector(»+11) Принцип двоичного поиска: спедн1”1 Исходный массив делится пополам и для сравнения выбирается диИН лемент Если он совпадает с искомым то поиск заканчивается Если же коМого элемент меньше искомого то все элементы левее его также будут меньше тО1Ьхо Стедоватезьно их можно исключить из зоиы дальнейшего поиска, осга0ИноГО то правую часть массива Аналогично если средний элемент больше иск отбрасывается правая часть, а остается левая
На втором этапе выполняются аналогичные действия над оставшейся половиной „«пи в Р“Ультаге после вт°Р°го этапа остается 1/4 часть массива И так далее пока или элемент будет найден или длина зоны поиска станет а,нои нулю В послеянсм олучае искомый элемент найден не будет рассмотрим схему алгоритма двоичного поиска Искомым элемент X 0 Исходный массив Vector | 1 | 4 | 7 111114| 18|20 |@| 25| 29| 32|37|41| 4б|49| 53| L=1 t R=n=16 Ll = (L+R) div 2 = 8 Vector [i]> X 4 L=1 t R=7 \ I—I = (L+R) div 2= 4 Vector!i]< x u —r L = I + 1 = 5 —I (L+R) div 2 B 5 Vector [ I ] * u Искомым эпеиеи! май*»" помин* 5
Работа с данными статической cmpywff^ 132 Один ид возможных вдридтов программы, реализующей метод /июц.1Нор поиска, имеет следующий вид г° program BinSearch; uses Crt; const n = 20,- { длина массива } type TVector « array [1.. n] of Real; r; ( Исходный массив ) ( Искомый элемент } ( Текущие границы Зоны поиска Vector : TVector; X : Real; ( LR : Integer, • Integer, begin ClrScr, Writeln ('Введите : for i = 1 to n do Write ('Введите искомый элемент Readln (X}; элементы массива 1}; > Read (Vector [11 } ,’ Readln, В := п; L <= R ) do { Пока не пересекутся границы begin i = (L + R} div 2, { Индекс среднего элемента if Vector(i) = X then Break ( Выход из цикла поиска } { т.к элемент найден ) else X then L := i + 1 end; { while ) if Vector[i] = X then Writeln {'Искомый элемент найдем на позиции ' ,i else Writeln ('Искомый элемент не найден'} . and 10.2.4. Примеры работы с двумерными массивами (матрицами) Задача I Дан двухмерный массив (матрица) размерности т*л, цементами которого являются целые числа Выполнить ‘’зеркальное отображение” эчемент матрицы относительно вертикальной оси симметрии (поменять местами алеман первого столбца с последним, второго с предпоследним и так далее)
П 1Гр3ммирование а сред6 Turbo Pascal 7 О 133 program VertMirrow; uses Crt; const m = 10; { число строк } n = 15,- { число столбцов ) type TMatr = array n) of Int„ var Matr TMatr; ( Исходная матрица } Finp : Text; { Файл исходных данных } В : Integer; х, 3 : Integer; procedure PrintMatr, var 1,3 : Integer; begin for i .= 1 to m do begin for 3 := 1 to n do Write { Matr[i,j]•5 ) , Writein; end; Writein; end; begin ClrScr; { Чтение исходных значении матрицы ) Assign {Finp,'FINP.DAT’J ; Reset {Finp); for i : = 1 to m do begin for з := 1 to n do Read (Finp, Matrix,3)). Readln(Finp); end ; (--------------------------------------------------) Writein {'Исходная матрица:’}. PrintMatr, (--------------------------------------------------) { "Зеркальное отображение” матрицы относительно ) { вертикальной оси симметрии } for з = 1 to n div 2 do { Берем столбцы от 1~го ) { до среднего } for 1 ,= 1 to a do { Меняем местами симметрия-) begin { ные столбцы ) В ;= Matrix,з]; Matrix,31 -® Matrix,п-з+1). Matr[х,п-з+1] •» В end. ---------------------------------------------------> Wrxteln {‘преобразованная матрица '), PrintMatr, end _______________—________________
работа с данными статической стл Задачи 2 Дана квадратная матрица порядка п, элементами кото - целые числа Вывести значения элементов на печать, выполнив обход °И Яаля,Отг; "спирали ”, как показано на следующем рисунке д МатРицЬ) . ! Рассмотрим схему, показывающую закономерности изменения индексов для выполнения обхода по “спирали л=6 - размерность матрицы р - номер текущего витка " спирали “ рограмма соответствующая приведенной схеме будет иметь следующий вил program 3piralWrite usea Crt, const n « 10, ( Порядок квадратной матрицы > type TMatr array [1 n,l n] of Integer; var Matr TMatr, ( Исходная матрица I Flap Text. ( Файл исходных данных I i ]. p integer.
135 ,ммнр* среде Turbo Pascal Г procedure PrintMatr var i J Integer begin for i = 1 to n do begin for J = 1 to n do Write ( Matrix n] S ) Wrxteln end Wrxteln end begin ClrScr { Чтение исходных значении матрицы } Assign (Finp FINP DAT ) Reset (Finp} for i = 1 to n do begin for з =1 to n do Read (Finp Matrfi j]} Readln(Finp) end (-------------------------------------------------} Writeln ( Исходная матрица ) PrintMatr (-------------------------------------------------} ( Выписывание элементов матрицы по спирали ) for р = 1 to (п+1) div 2 do begin { Выписывание элементов верхней строки р-го витка } for з = р to п-р+1 do Write (Matrfp j] 4) ( Выписывание элементов правого столбца р~го витка ) for 1 = р+1 to n-p+1 do Write (Matr[i п-р+1] 4} ( Выписывание элементов нижнем строки р-го витка } for з = п~р downto р do Write (Matr[n-p+l у] 4) { Выписывание элементов левого столбца р-ro витка } for 1 = п~р downto р+1 do Write (Matr[i р] 4} end (-------------------------------------------------} end 10 2.5 Строки Строка представляет собой особую форму одномерного массива символов которая имеет существенное отличне Массив символов имеет фиксированную длину (количество элементов) которая определяется при описании Строка имеет Две разновидности длины * общая длина строки которая характеризует размер памяти выделяемый строке при описании * текущая длина строки (всегда меньше или равна обшей длине) которая показывает количество смысловых символов строки в каждый конкретным момент времени В языках программирования используется два способа реализации строк Рассмотрим их
Pabome с данными статический стр^^ 136 Первый способ реализации строк текущая длина строки указывается в иуЛСВп, В первом способе В этот элемент записывается симво, (то есть имеющем индекс, 0) эле^ даины Нулевой элемент сгрэди код которого Ршняет“ пользователя, однако использовать его в программа, этом сделан «евидиМ“^Дть из него информацию) хотя не рекомендуется, но , (записывать в него и извлек каждый символ занимает один байт памяти, то принципе допускаете текущей длины, максимально допустимая длина строк, при таком способе указан г значением, которое можно записать в один баи будет ограничена мак ная даина строки может бь1ть не у памяти ю сию СИМ°0Такой способ указания текущей длины впервые был введен в языке Ти* Pascal в аше предопределенного типа Stnng, и. соответственно, строки, реализовать, по такому принципу часто называют Turbo-строками или String-строками Преимуществом такого способа представления строк является чрезвычайно просто доступ к значению текущей длины строки, что позволяет эффективно выполнят работу со строками Недостаток состоит в ограничении на максимальную длин строки 77=14 8 9 18 И 12 13 14 р-п 5 0 1 2 В О R Й N D —> символ, код которого равняется 7 п - фиксированная обцая длина строки, Р - текуцая длина строки В Turbo Pascal версии 7 0, также как и во всех предыдущих версия^ рассмотренному способу реализации строк соответствует предопределенный тиг скобках пРеделяемая ПРИ описании общая длина строки указывается в квадратны) Примеры si S2 SMax String [Ю] , String [128] ; String, Функция Concai Функция Сору Процедура Delele Процедура Insert Ф-нкиия Length Функция Pos Процедура Sir Процедура Vai максимальная длина равная 255 символам аСТСЯ’ ™ П° умолчанию пРинимаеТС' процедуры и функцииТР°КаМИ типа ^1пп8, в Turbo Pascal используются следую1ии ^ыполняет конкатенацию ( сцепление ) последовательности — удаляет и7 КОЛИЮ подстРоки из заданной строки - строки подстроку - " " СТроку подстроку - ХХХХГУ СТРОКИ - строковое прежние разует строковое значение в его ч,ь »•«>« представление
. u p ma»cpw Turbo Pascal 7 о 13? Второй способ реализации строк I Bl лором способе реализации строк текущая длина строки фиксируется I „пьИЫМ символом признаком который ставится после последнего СМЫСЛОВОГО IсГе оп строки В Turbo Pascal в качестве такого признака используется символ с кодом который называется нуль символ и обозначается или NULL q Такои способ указания текущей длины практически не ограничивает сцмально допустимую длину В IBM совместимых компьютерах ограничение м<зк е имеется и установлено размером в один сегмент памяти (65534 байт) ради справедливости заметим что максимальную длину Turbo строки также мнительно несложно можно было бы довести до 65533 байт если для хранения С чения текущей длины выделить не один байт а два Однако в существующих Низаниях языков это еще не сделано ,Ре Строки с завершающим нулем называют также ASCIIZ строками Р 1 п 14 1 2 3 4 5 fi 7 8 Э 10 11 12 13 14 В 0 R L A N D \0 -> нуль символ Строки с завершающим нулем хранятся в виде символьных массивов с нулевой оазо1 (то есть нижняя граница которых равна нулю) const Len = 511 type TStr9 = array[0 9] of Char TStr0O = array[0 80) of Char TStrLen = array[0 Len] of Char Кроме того в Turbo Pascal имеется предопределенный тип PChir который представляет собой указатель на строке с завершающим нулем и определяется та образом type PChar = AChar При установленной директиве расширенного синтаксиса ($Х+) (она прини мается по умолчанию) символьный массив с нулевой базой совместим с типом PChar Кроме того строковые константы также совместимы по присваиванию с : типом PChar Например uses Crt CO"SStr0O array to BOJ of Char - Строха типа PChar var P PChar begin ClrScr P = Строка типа PChar Wrxteln(P) P = StrBO Wrxteln(P) end _______________________
Оплоте С Данными стагличпскуй СТ0| 138 ——' „ооковых констант в качестве фактичад^ Допускается такхе^^сгр^^ етрв. имеют тап Рс,,аг Ь, параметров, если соответс У ------ I const „лъяг = 'Turbo Pascal , Name = ptna . pchar) ; procedure Test (str begin end; begin Test (Name) ; , тГТотТтйпизированные константы типа PChar допускаются, однак a таА как и типизированных констант типа Stnn6, 255”° Переменные типа PChar допускается индексировать аналогично символу массиву с нулевой базой-—------------------------ ' —— ООХв0 : array[0--80] of Char = 'Turbo Pascal'; var P: PChar; begin P := Str80; Writeln('Str80 [5] = ', StrBO [5]); С Эти два оператора} \ Writeln('P [5] = ', P [5]) ; { печатают один и } end. { тот же символ ’п' } Turbo Pascal при включенной директиве {$Х+} позволяет использовать для работы с указателями типа PChar дополнительные операции. Операции суммирования (+) и вычитания (-) могут использоваться для увеличения и уменьшения смещения указателя на заданную величину. Кроме того, операцию вычитания можно использовать для вычисления разности смолений двух указателей типа PChar Strl, Str2, Res 1, 3 : Word; begin - PChar; Res .= strl Res := Str2 Strl Str2;{ •nd. Res будет указывать на i символов дальше, чем Strl ) Res будет указывать на х символов ближе, чем Str2 } 3 будет равняться числу символов, Расположенных между символами, «а которые указывают strl и Str2. I tri и Str2 должны указывать на 1 Дин и тот же символьный массив 1 включенной директиве (SX+й „ неРавенство Расширенный синта определять только их „„^„VTB0 (при включенной директаве ($x+,j —“"w гасширеннып — — ускает К значениям типа PChar применяв*’
ииние и П rbo PMCal ? О 139 ! । ранни 4 4 ч“ и v* Нп прн w iohuii т in। <i и iii । mii\ хкиателя *|Щ1 ' H ’ ° lUM H ,41T *e Mftcc,1h vhmbojioii lit и ' i и рккн опор ишй <0 и рок im ii i t luepui uouuim h\ km n к мтект Ml I I’lbo I 1м ll 0»И l»K It ' 1CH Н01П 1И v I It I l ip I Hl 111 MO l\ 41 St I UH. 1 II] Hill I M N ”KO< OBH ’»’>»< ф\НК|Ш|| МЧМ1 Ml I IKS ИНКН1 ми 1! фонон I s,l< u' IKUII I SU\ I ' ф\ икни i Sil Him фхПКННЧ Sill X ф\цкпич Sul mi lonmiMii tm i| MkK inn i|ii il ki > i mpi lit и 1 X к I I |l\ H Hl P< l\ II 1 llp\ к lll\ 10 L IpOKX ipiutuintei uk itpoKii SI и S2 Ek tu SI <. S2 торе n n i iiom ox ter oipitti ue twice Min. to еслн SI ~ S3 ro pv iy imutom Gv tei икю ришос 0 скчн si x s2 ro pets тьтпгом Gwt положи теп ное uk to MMiiiput uiHKitik о тон к ipoMf и др\ n to Возвр.иц1ет \KI ИХ и HIH14LIO|X X иопрхкчти KTpOkH хин подает upokj рищч и кнпхю pnki < помощью } химии» StrNexx nipxer течение otuoil нрокн n ipxixM Во врши Ktin-etb hi конец рез\ иинрхюшсй игроки их прutt let XKHitvtb ut tuepiii iwiuHrt «.трокх нхювой CH M LUM <httiUtM4 strlGunp * к XIII l И — сравнивает дне игроки шпмцчно StrComp но оеч рв лнчпм региктра кнмвлюв upuctx пинает нкмдднхю строку к концу целевой к троки и »гом обскпсчнваеткч что дтнна реахтьгнрхкчцей 'кп не превышает кишного мхкхимхмт Возвращается i чпелк н i к троку рептьтнг uuuituer inc sтроки к лианной маккнмлтьной длиной iv-to uisukvtob нт 1Кчадной строки it MMBpAuiier хказатетъ на pe~ *т лчпнх ктрокн н 1 К> чЦХ *о V 1М П*М 1НОЙ к mt це I о
Раоота с данными статической стру^.^ 140 Ф\нкШ<я StrScan функция SirUpper ппп.нает указатель па первое вхождение указанного " символа в строку, или ш/, если символ в строке Отсугствуст _ преобразует строку в верхний регистр и возвращает уКаза гель на нее 10.2.6. Множества Синтаксические диаграммы описания данных типа “множество» прИведены „ конце подраздела описания типов в главе 3 Термин “множество” в программировании используется аналогично его математическому пониманию Отличие состоит в том что в Turbo Pascal множества могут включать элементы только порядковых типов Элементы какого-либо конкретного множества (переменной или типизированном константы) Д01Л:Ны принадлежать одному типу, который называется базовым типом Максимальное количество значений базового типа множества называется его мощностью В Turbo Pascal в качестве базовых могут использоваться порядковые типы, мощность которых не превышает 256 ти значений Кроме того порядковые значения верхней и нижнеи границы базового типа не дочжны выходить за пределы диапазона от 0 до 255 Поэтому в качестве базовых типов множеств не могут использоваться Shortlm Integer Longint Word Операции допхетимые для работы с множествами и типы их операндов рассмотрены в главе 4 Для лучшего понимания материала приведем таблицу с графическим пояснением каждой из операции Математическое обозначение Обозначение о Borland Pascal Действие Пример П * Пересечение /д о\ С=АПВ <52^ с=А*в Тип результата множество и + Объединение Тип результата множество \ - Разность с=АХ8 IjLJy с'А-8 Тип результата множество € tn Принадлеж- ность (элемента множесгоу) бТХ- хбА X. 7 if X tn A then Тип результата boolean с (5) э!?| Является подмножест 8ОМ Включает подмножест во операнды множества АЭВ(ВСА| А> В (В< А| Тип результата boolean _ множества представляют собой гибкий и иапядныи механизм Я1 & многих задач В частности их удобно использовать при обработке строк и качестве примера рассмотрим следующую задачу
Р,->«лмке в среде Turbo Pascal 7 О 141 рш Подсчитать в ickctobom файле отдельно число цифр и латинских буки program Testsets; uses Crt; type CharSet = set of Char; const Digits : CharSet = ['0 Letters: CharSet = [a' . . ’z’ , 1 A' . . 'Z'] ; CountDig, CountLet : Word; Finp : Text; Ch : Char; begin ClrScr; Assign (Finp, 'TESTSETS.DAT'); Reset (Finp); while not eof (Finp) do begin Read ( Finp, Ch ); if ch in Digits then CountDig ". = CountDig + 1; if Ch in Letters then CountLet := CountLet + 1; end; Writein ('Число цифр = ', CountDig 5); Writein ('Число букв = ', CountLet : 5) end. Используемое в программе множество Letters при необходимости может получено из двух других множеств SmallLetters = ['а'. 'z']; BigLetters = ['А'..’Z']• ей сложения (объединения) Letters := SmallLetters + BigLetters; '-□можно также и обратное действие из множества Letters получить 'ers и BigLetters с помошью операции разности множеств SmallLetters = Letters - [ -A’ . . ‘ Z ] ; BigLetters = Letters - [ a' . . • x • ] ;
Pdoome с данными итатичпсхой cmpyKt 142 . —--- г^тл г СОСТАВНЫМИ ДАННЫМИ 3 РНЕОЯНО₽ОДНОИ СТРУКТУРЫ файлов, является составное множество или файл всегда 10.3.1. Записи Синтаксические диаграммы описания данных типа “запись приведен, конце "°я₽с7е™ХиНеИот”ма°ссивГовВ множеств и структурой данных Если°™“ь”°п“Я™зЙаписи могут объединять в единое вдвое лТ^ХХ-ных других типов простых переменных, массивов множен записей ржса] различЕиот фиксированные (обычные) и вариантные записи Фиксированные записи Обычная фиксированная запись состоит из одного или нескольких полей для каждого из которых при объявлении указывается имя (идентификатор) и тип В качестве примера приведем запись, описывающую личную карточку успеваемости сп лента Пример type String? = String [7] String20 = String [201 TStudentCard = record SurName String20 { Фамилия } Name String20 { Имя } FatherName String20, { Отчество } Year Integer, { Год рождения } И ядеAdriтess String, { Домашний адрес } GroupCode string? { Шифр группы } MathAnal Byte { Мат анализ } LinAI Byte { Лин алгебра } Prog Phys end Byte Byte { Программирование { Физика } одинаковую^мы3с^в^на7п°,зВкхП^^дНО|Й ,3аПИСИ есть гР>™а полей, несущи» повышения читабельности * MathAnal, LinAI, Prog, Phys) С точки зрения такие потя целесообразно <Лг/?и2'МЬ1 ” удо®ства выполнения групповых операций В результате тип TSiudcniCarri пп ЯТЬ В ОТЛС'’1ЬНУЮ структуру данных типа “запись —______________'^eno-arg примет такой вид type TstudentCard = SurNane Father»*»., Зегхпдго ( «аиилхя ) StrxnqZO. ( StrxngJQ ( Groupcod® String? Имя } Отчество ) Г°Д рождения ) Домашний адрес } { *ифр группы }
в среде Turbo Pascal 7 О 143 Marks record MathAnal Prog Phys end; end : Byte; { • Byte; { • Byte; { • Byte; { Мат. анализ } Лин. алгебра } Фявяка } \ еше лучше записать следующим образом type TMarks = record MathAnal : Byte; { Мат. анализ } LinAl : Byte; ( Лин. алгебра ) Prog : Byte; ( Программирование } Phys : Byte; ( Физика } end; TStudentCard = record SurName : String20; { Фамилия } Name String20, { Имя ) FatherName String20; { Отчество ) Year Integer; ( Год рождения } HomeAddress: String; ( Домашний адрес } GroupCode String?, ( Шифр группы ) Marks TMarks { Оценки за последний ) { семестр } end: Обращение к полям записей выполняется с помощью квалифицируемых »чненны\) идентификаторов, в которых указывается вся цепочка имен от иденти- □тора переменной типа "запись"' до идентификатора требуемого поля Имена полей инфицируемого идентификатора разделяются точками Пусть будут описаны г.юшие тип и переменные Гуре TGroup = array [1 25] of TStudentCard, var Group_KB51, Group_KB52 TGroup, В jtom случае корректными будут такие операторы и обращения к полям Group_KB51 L1}.Name 'B Sergey’. 3roup_KB51 [IJ.Year “ 1978; Group_KB51 [1] Marks.Prog :» 5; Group_KB51 [1] .Marks = Group_KB52 [1] Marks Group_KB51 15} Group_KB52 [7] : Group_KB51 = Group__KB52, Д-чя упрощения работы с записями и придания программе большей наглядности urbo Pascal имеется специальный оператор присоединения with (см главу 5)
Работав сданными статической rmpy*rnytu, 144 ОТО оператора вышеприведенные операторы буду, , ,„исаиЬ| р С „спотьзовтнием этого оператор таком виде ________________________—- with Group__KB51 [И do begin Name Year Marks Prog Marks end Group_KB51 [5] Group__KB51 •Sergey' 1978 5 Group_KB52 [1] Marks = Group_KB52 [7] = Group__KB52 Пои заполнении информацией структур данных типа запись необходимо помнить что из текстовых файлов (клавиатуре также соответствует текстовый фаит "°"?) допускается вводить данные только некоторых стандартных типов (см начало главы) Поэтому в операторах Read и Readln могут располагаться идентификаторы только самых внутренних полей которые имеют допустимый для ввода из файла тип Вариантные записи Рассмотренный тип TStudentCard включает только четыре оценки за один^ семестр Но в следующих семестрах будут выноситься на экзамен другие дисциплины Возникает проблема в записи TStudentCard нас интересуют (для нашего примера) оценки только за последним семестр но в каждом семестре сдаются другие предметы Если испотьзовать обычные фиксированные записи то придется в тио TStudentCard включать поля для всех изучаемых за время обучения дисциплин Это приведет к избыточности информации в типе TStudentCard и снижению читабельности программы Кроме того будет неэкономно использоваться память поскотьку для каждого студента память будет выделяться под поля всех ею оценок а фактически (в нашем рассматриваемом случае) будут использоваться только иескотько потей описывающих опенки за последний семестр В таких случаях целесообразно использовать вариантные записи в которых также как и в фиксированных описываются поля для всех возможных случаев однако альтернативные группы полей разграничиваются более наглядно и память выделяется только под конкретный необходимый в данный момент вариант вариантной X™ “ расшиРить опенками за второй семестр то в форме вариантной записи он примет такой вид и type TMarksSeml = record MathAnall LinAl Progl Phy» end TMarkaSeai2 " Byte Byte Byte Byte Мет анализ ) Лин алгебра у Программирование У ♦иэиха ) record MathAnal2 Electron ₽rog2 DrgAutoe and Byte Byte Byte Byte И** Анализ } ЭлегтроКика j пРограмиирование } Теория циф автоматов }
звание в среде Turbo Pascal 145 )ОГ«Х TStudentCard = record ( Фиксированная часть записи } SurName : String20; { Фамилия ) Name String20; { Имя } FatherName : Stnng20; ( Отчество } Year Integer; ( Год рождения ) HomeAddress: String; ( Домашний адрес } GroupCode ; String?; ( Шифр группы } ( Вариантная часть записи } case Semestr : Byte of 1 ( Marksseml TMarksSeml ) ; ( Оценки за первый } ( семестр } 2 : ( MarksSem2 ; TMarksSem2 ) { Оценки за второй } [ семестр } and; g Вариантные записи включают две части: первая часть — обычная фик- I 1л сированная запись: вторая часть — вариантная, состоящая из поля признака и одной или нескольких вариантных компонент Вариантные компоненты включаются в конкретный элемент типа "запись" по альтерна- тивному принципу, в зависимости от значения поля признака В типе TVarStudentCard поле Semestr является полем признака, а поля irksSeml и MarksSem2 — альтернативными вариантами данной записи Если объявить как показано выше переменные Group_KB5l и Group_K.B52, заполнение информацией за первый семестр экземпляра карточки одного сту- па, имеющей порядковый номер 3, может иметь, например, такой вид1 with Group__KB51 [3] do begin ( Заполнение фиксированной части записи } SurName := 'Иванов*; Name := 1 Иван' ; FatherName := 'Иванович'; Year := 1978; HomeAddress:= 'г. Киев, ул. Иванова, д 12, кв.63*; GroupCode •= 'КВ-51*; ( Заполнение вариантной части записи } Semestr := 1; ( Установка признака первого семестра I with Marksseml do ( Оценки за первый семестр } begin MathAnall » 5; LinAl •» 4 ; Progl « 5; Phys = 3; end; and; ——‘ • ___________________________________________________________ & заключение отметим одно неудобство применения вариантных записей В байтных компонентах таких записей не допускается использование одинаковых кНТиФикаторов. '434?
Ргоста с данными статической Например в следующем примере оО.) альтернативных вари)МГ1 предмет Мп анализ" содержат одинаковый идентификатор М)1Ьд,ПИСИ^ предмета Программирование очинаковыи идентификатор рГое u Па1 а Дл8 ' ° яМ’етс’ некорректным Пример е оииюками TStuden.Card = записи { Фиксированная { Вариантная часть записи case Sentestr Byte of 2. ( MathAnai Byte LinAI Byte Prog Byte Phys Byte ) 2 { MathAnai Byte Electron Byte Prog Byte DigAutom Byte ) { Мат анализ } ( Лия алгебра ) ( Программирование J ( Физика } ( Мат анализ } ( Электроника } ( Программирование ) ( Теория циф автоматов ) 10.4. СОВМЕСТИМОСТЬ ТИПОВ Lobmcl 1ь типов оываег дв\\ р uhoi и тнсктси • совместимость в выражениях. иов'-1с<'гнм<х.ть по присваиванию 10.4,1. Совместимость в выражениях При выполи-нп • операций в выражениях могхт встречаться рация имеет свои набор доп}стммых для нее комомнадн - , „ис для операций типы операндов приведены r riatw - “м6инаиии ринотапных операндов определяются с • ТИПЫ • типы типами * тип O0UVO г • типы ТИП к 'Тимаковыми. •’И 1Ч1цеитьсннк WO и того
^M|,r '' 1 "1 о Pascal 7 О • hi обоих операндов являются идентичными указательными типами .. 1ЬКО При директиве {$Х+|); . н.пы обоих операндов являются процедурными типами, которые описывают процедуры (функции) с одинаковым числом и соответствием параметров а l i'i функций также идентичными типами результатов. 10.4.2. Совместимость по присваиванию I Правила совместимости по присваиванию являются менее строгими, чем ’рлвкла совместимости в выражениях и допускают более широкий спектр автома- пческнх преобразований типов. Компилятор применяет правила совместимости о присваиванию при обработке операторов присваивания и при передаче значений араметров. Значение результата выражения типа Т2 является совместимым по присваива- ло с переменной А типа Т1, стоящей в левой части оператора присваивания, то есть рн описаниях var А : Т1; В : Т2; допустим оператор I А := В + В; | если выполняется одно из следующих условий: • и и Т2 являются тождественными типами, которые не могут быть файловыми или структурными, опирающимися на файловый; • и и Т2 являются совместимыми порядковыми типами, и диапазон значений типа Т2 является поддиапазоном возможных значений типа Т1, • Т1 и Т2 являются вещественными типами, и диапазон значений типа Т2 является поддиапазоном возможных значений типа Т1; • и является вещественным типом, а Т2 является целочисленным типом, • Т1 и т2 являются строковыми типами; • Т1 является строковым типом, а Т2 является символьным типом (Char) • Т1 и 12 являются совместимыми множественными типами, и все члены значения типа Т2 попадают в диапазон возможных значений Т1, • Т1 и т2 являются совместимыми указательными типами, • Т1 — тип PChar, а Т2 — строковая константа (только при директиве ($Х+)) • Т1 — тип PChar, а Т2 — символьный массив с нулевой базой (только при директиве ($Х+)), • Т1 И Т2 являются совместимыми процедурными типами, • Т1 представляет собой процедурный тип, а Т2 — процедура или функция с идентичными типом результата, числом параметров и соответствием между . типами параметров, К • объектный тип т2 совместим по присваиванию с объектным типом Т1, если I Т2 является потомком Т1,
ОЧНЫМИ CWWn US ,,ы1111юшп» па ООЬСК! типа Т2 совместим п„ чкакпетч ?1. сказывающим па объект »х, ™ „„синю с гопом ,1 потомком Т1 Контрольные вопросы „ропсдхр осхшестатяется стандарты» Ы'од в чзыке 2. С помощью каких проис ТУР Turbo Pascal' 3. В чем заключается рачнчие .чмиесиччекч стандарты» вывел в ЯЗЬПк МСЖЛЗ процедурами Write и Wincin'1 4 Каким обратом необходимо выпшичта виол-вывод при р.юоге е переМсн нымп егр\ котированных типов и почем' Значения каких типов мот быть прочитаны ироне прамн Ке.,д и Residin' Значения каких типов moim быть записаны щхчкдхрлмн Wine н \\ nieln1 Как выполняется процедура Read' В чем особенное!и ьвода значений строкового типа* Какое с\шес!К\ет ралшчне между процедурами Read и Readln при чтении строковых переменных' Как происходит выпапненне процедуры Wnteln' Какие типы относятся к пользовательским простым типам ' Какие особенности использования переменных перечислимых типов' Какие действия можно выполнял» im церемонными перечислимых типов' 1*К Допустимо ш нспо.ль.1ов.1нме переменных перечислимых типов в качестве индексов массивов и цмнни оператора fox' 15. Что предстанет соСхч! массив как структура данных' 16. Камю данные мопт выступать и качестве индексов и элементов о 17. Какие помзаге.ти неплтьз'ются ли оценки быстродействия : МС1ОДОВ сортировки' 18. В чем состоит принц,метод., соршроики вставкой > I»- В чс.м состоит принцип метода знаковой" сортировки’ ’ !бмена”ТОИТ ПрС11!',>шест|)о “'”*> выбор» перед методами ,, 21 в чем заключается принцип И- Кдх,> 6. 7. 8. 9. 10. 13. И- Как, 15. Что 10. Дли 17. Каке I». В к . Как 10 к .. ДВОИЧНОГО Пон.кд о строками'1 " вторым способом редлн 1.11П1.
.„„гч-фпммс * и^де Turbo Pascal 7 о Контрольные задания 1 I К, >.тонным вещественным а, Ь {а>Ь) и целому лпя значении аргумента п (п>0) вычисшть значения л, = а + i • А, Л = (i-a)/n, 1 = 012 п о = 0, 4 = 2л л = 30 а- , з 1 Jl (л) - — sin(x)cos(x) ш = 7777 г f . т' + Д — 10 ЛО) =------------- т+3 Результаты вывести на печать в виде таблицы с прорисовкой всех пиний, показано ниже Арг\ мент Функция х SIN(x)COS(x)/2 SQRT(SQR(SQR(\))+4) (SQR(\)+\-10)/(x+3) Ч f|(xo> хп f,<Xn) G(x„) fl(Xn) 2. Задан вектор (одномерный массив) целых чисел Определить число эле- ентов в самой длинной цепочке рядом расположенных нулевых элементов векто- 1 а также индексы первого и последнего элементов этой цепочки 3. Задана прямоугольная матрица (двумерный массив) вещественных чисел Сформировать вектор, содержащий максимальные элементы каждого столбца матрицы 4. Задана квадратная матрица (двумерный массив) целых чисел Упорядо- ить элементы побочной диагонали матрицы по неубыванию методом а) вставки б) выбора, в) обменов 5 Задана прямоугольная матрица (двумерный массив) целых чисел Опреде- гь методом двоичного поиска наличие заданного целого числа X в каждой стро- ЧатРиць] в отдельности 6. Задана строка символов длиной я Заменить каждый символ обозначаю 11 иифр^ ца символ, обозначающий следующую по значению пифру (‘0’>’Г. Т>’2\ Ч'>'У ) Символ 9’ заменить на символ ‘0’ 7 Заданы пять множеств символьного типа А, В С. D. Е Найги элементы ги*сства X которое определяется по формуле
150 статической если условие f=uus)n (сит^я (ЛЛЗ)с с истинно, и по формуле х = A\J(Br\C)\J(Dr\E-) в противном случае. 8. Описать массив записей, содержащий оценки студентов группы за три последних семестра. Определить фамилии студентов, сдавших все три сессии щ отлично
ГЛАВА 11 ПРОЦЕДУРЫ И ФУНКЦИИ 11.1. СТРУКТУРА ПРОЦЕДУР И ФУНКЦИЙ При создании программы для решения сложной задачи выполняется декомпо- (разделение) этой задачи на подзадачи, подзадач - на еще меньшие подзадачи * к далее, до легко программируемых элементарных подзадач. Г,[ Turbo Pascal имеет различные средства для деления программы на части. На нем уровне деления (больших задач) — это модули (См. главы 6. 15). на нижнем ' Хвне (элементарных подзадач) — это чаще всего процедуры и функции. QptcMHO-ориентнрованная методология охватывает как верхний, так и нижний разработки программ. 1 Процедуры и функции являются важным средством в большинстве языков I программирования. С их помощью можно скомпоновать группу операторов для выполнения некоторого единого действия. Процедуру/функцию можно вызывать [ из различных мест программы, она может возвращать вычисленные результаты, и 1 ей можно передавать информацию, которую она использует для выполнения !вычислений. Для того чтобы процедура/функния начала работу, ее нужно вызвать (активизировать). Процедуры и функции состоят из операторов, локальных данных и внутренних процедур и функции. Структура описания процедуры и функции имеет следующий вид procedure Имя (Список Формальных Параметров); label const type var Описание локальных меток, констант, типов и переменных procedure function begin end ; i i ! Описание внутренних процедур и функции Операторы function Имя (Список Формальных Параметров) : Тип результата label --------- const _______ Описание локальных меток, type констант, типов и переменных var ---------- procedure ----1 Описание внутренних function Г------процедур и функции begin end : Операторы, среди которых должен выть хотя вы один, который присваивает имени функции значение результата. °тличия В описании функции и процедуры касаются только заголовка и операторов что отмечено непосредственно на приведенных рисунках Для пчп, чю uiMtitn г одной задачи, одно из которых “драниц этих отличий приведем два решения одной зад . л н и|Нено с помощью процедуры, а второе — с помошн
152 чоруры и ф 11й массив размерностью « элементами ко(0рого ,п^ Злыча Д ‘н одномерным ма Р। вектора ПР°ЦеДУРУ ИМееТ СЛСДУ'°"1ИЙ "И| “program PSums^T eons t n = 20 type TVector { длина массива } = array [1 n] of Real, var Vector TVector, Integer , №<- TVector Len Integer, Name String } procedure Summa { Vec TVector var i Integer S Real begin S = 0 for i = 1 to Len do S = S + Vec [i] Wnteln ('Сумма элементов вектора ' , Name, end ' , S 7 2 } begin Writein (’Введите элементы массива '} , for i = 1 to n do Read (Vector [i] J, Readin, {---------------------------------------------------} ( Вызов процедуры выполняется отдельным оператором’ } Summa ( Vector, n, 'Vector } (---------------------------------------------------} end Программа использующая для решения функцию имеет следующий вид program FSumma const n = 20 ( длина массива } type TVector = array [1 n] of Real var Vector TVector Sum Real x Integer function Sunnna ( Vec var TVector Len Integer ) Real S begin S = 0 Integer Real S Summa 1 to Len do S + Vec (i) S { end { Присваивание имамм * < Результата «алеете,ЗНаЧения ' I операторе» а твлв >
^^ированио в српдв ПнЬо Pn-rOf 7 р~ ^wrxteln ('Введите элементы массива fori =_^^_d^!!^J_VeCtor[1l Readln, BU3OP “°«ет выполняться там, где лопускае,;ся , давить «фа»»™, в частности, в правой части опе- ратора присваивания Sum ~ Sununa Vector, п } ’ Htiteln ('Сумма элементов вектора Vector = ', Sum 7 2 ) непосредственно как элемент вывода процедура, Wnteln ) Hriteln ('Сумма элементов вектора Vector = Summa ( Vector, n } ) end 11.2. ОБЛАСТЬ ДЕЙСТВИЯ (СФЕРА ВИДИМОСТИ) ИДЕНТИФИКАТОРОВ ПРИ ИСПОЛЬЗОВАНИИ ПРОЦЕДУР И ФУНКЦИЙ Областью действия (сферой видимости) идентификатора называется часть ^ограммы, где он может быть испотьзован Область действия идентификаторов определяется местом их объявления Если кнтяфикаторы допускается использовать только в рамках одной процедуры или НМ1ИИ то такие идентификаторы называются локальными Если действие интификаторов распространяется иа нескотько вложенных Сие менее одной) зоиедур и/или функций, то такие идентификаторы называются глобальными Заметим что понятия глобальные' и “локальные" следует понимать отно- сительно - по отношению к конкретной процедуре или функции Integer, Integer Integer Продемонстрируем ^то следующим примером ----program Scope — аг АО, ВО, СО ---- procedure Pl var Al Bl, Cl r— । — procedure P2 , var A2, B2, C2 begin Допустимо испольном**6 как глобальных АО,ВО СО Al Bl С1 так и локальных А2 В2 С2 -------- end, begin Л Допустимо нспольаоеаиме как глобальных АО,ВО,СО так и локальных А1 » — end ' Ь*я1а «„«ьжо ло.во.со Допустимо ислольвовамие end & Даином примере АО.ВО.СО г к,Уемых в программе , ПГМН1 IVp И функции
154 Д'^кМурыиф^ П|С, .4lvT гюЛ1».НЫм.1 VN всех процедур п Функций, описзд^ в„уГ₽,;\'р™ед'РЫ н ... данной примере процедуры Р2). и ОЯНоврем^ К’К'11 дХГе В1 СЛ оХиенные » самой внутренней Процедуре Р2. ПИ“"е. правила определения области действия для идентиф1,Ка^ процедур >1 функций • действуют все идентификаторы, определенные внутри пР°иеДУры/фуц)СЩп( • действуют все идентификаторы окружающего контекста, если их ИМ(/ отличаются от имен, объявленных внутри процедуры, функции; • локальные идентификаторы процедуры функция во внешнем окру*еНи действовать не будут никогда; ' м • в случае совпадения имен глобального и локального ндентификдто действовать будет только внутренний локальный идентификатор. Р08 Если первых три правила поясняются рассмотренным примером То пояснения четвертого приведем еше один пример ‘и,; — proijram EqualNames; ———---------------- var А,В,С : Integer.- . — procedure Fl • ------------ var А В.С : Real; r ...... procedure P2:------------- var А В.C : Char• begxn A,B,C доступны, как символьные переменные L- end: —- — begin A,B,C доступны, как действительные переменные end-_______________ А В,С доступны как целые переменные хние во внутренней процедуре данных с илеит г sm с данными внешних процедур, отменяет лей». , . . зводит свон локальные описания, недавней' ruin, или нет Локальные данные создаются при вызове процедуры-’фун’М**и только во время ее выполнения Выделение памяти для лояаль****^ з происходит чвтаматмчесжн в начале выполнения процедуР^»ЛрГ^ с ~ 'ой памяти — как только выполнение процедз^*4^1 г .папоженные^,,^^^^^ ......................................................................... ^«обо^иннем
, не в среде Turbo Pascal О 155 -11 3 КЛАССИФИКАЦИЯ СПОСОБОВ ПЕРЕДАЧИ ПАРАМЕТРОВ При активизации процедуры/функции ей можно передавать параметры При m необходимо следить чтобы в операторе вызова были указаны все параметры е щные В заголовке процедуры/функции napJMeTPbI указываемые в заголовке процедуры/функции при ее описании льются формальными параметрами 13 П1раметРы указываемые при вызове процедуры/функции называются тическими параметрами Корректность передачи параметров основывается на их порядке перечне пения в заголовке процедуры и совместимости по присваиванию между соответствующими фактическими и формальными параметрами Сфера действия имен параметров такая же как и локальных данных Многие процедуры имеют несколько параметров Задача программиста — селиться что параметры которые он указывает при вызове (фактические пара (егры) соответствуют по смыслу формальным параметрам Компилятор может проверить только очевидные случаи — неправильное число параметров или несо вместимость типов Рассмотрим классификацию способов передачи параметров реализация которых возможна в языках программирования Обратим внимание читателя что это общая классификация а не классификация параметров в Turbo Pascal Введенные для класси фикации обозначения alj^ add j. cj*- в Turbo Pascal не используются_______________________________________ Параметры различаются 1 По механизму передачи а) передача по значению ( value } 6} передача по адресу (по ссылке) ( addr } - По взаимодействию вызывающей и вызываемой нроцедур/ф\нкции а) только как входной параметр ( in } 6) только как выходной параметр ( out } в) как входной так и как выходной параметр ( xnout ) Соответственно этим ртзти в<ям теоретически возможны 6 способа» передо PQ метров —---— 1} value in 2) value out 3} value inout 4) addr in 5) addr о«£ 6) addr input______ 1Ц1 Несмотря на то что возможны /“"таующих языках пр- " -„„оазния как правило ' способов
Процедур ,1/ПОНй (value четвертый (a<idr . П1 1 1 CV Собы пёгсп >и параметре» " u.e.ro.uaddr xnoue) способь « ШСС™ С'™СОб°В "'Р'"41’ ”'РДМетро, PHvW>n>«« ^1ТКО C'?DcXau>n’ « >-'№М ',нб° >1Ь1С Пр0Г(’ 1мчиРовани 31Ми»м «о пр» конкретиюД олнсаННОго могут быть Некоторые от 11 3 1 Параметры value in (в Turbo Pascal реализованы) I 2 3 При вызове ^“^"^’'„Тпамяти под формальные параметры и токал а) выполняется вы*’е»ие Mb(|C„ области памяти мя локальных данных) б) вТполн еВтсяе копирование значении факти . екик и.раметров в паЧять выдоенную 1тя формальных параметров а? Х—%наХ^^ не 0ЫЗЬ,ВаеТ НИКЖОГО м™™> нт содержимое я «.ск памяти фактических параметров Пои окончании проиед\ры/ф\нкции а?память выделенная под формальные параметры и локальные данные очищается б) новые значения формальных параметров полученные в процессе работы процедуры теряются вместе с очисткой памяти 113.2 Параметры value out 1 При вызове процед)ры/ф\нкшш а) выпозияется выдезение памяти для значении формальных параметров локальных данных а также для сохранения адресов фактических параметров^ (в стеке или в специальной области памяти для зональных данных) б) выпозняется копирование адресов (но не значении’) фактических параметров в выдезеннхю для них пах5ять в) значения формальных параметров непосредственно после вызова не определены г) использовать в качестве факги «еских параметров константы запрещено 2 Во время работы процедуры/функции а) запрещается использовать значения формальных параметров до тех пор пои не будет выполнено первоначальное присваивание какого либо значения б) изменение значении формальных параметров не вызывает одновременного изменения соответствующих фактических параметров 3 При окончании процедхры/функции а) сначала используя скопированные адреса фактических параметров вылолияегс» запись результирующих значении формальных параметров в ячейки паи™ фактических параметров б) память выделенная для работы процедуры/фуикции очищается 113 3 Параметры value inout При вызове процедуры/фхньшш а) ------ б» выпозияется выделение тиот.. локальных данных а также для сом Зн',ченин Ф°₽' ' naMeTpv. (в стеке или в специхтьной Хс™ адреѰ *актическн’< П.аР выполняется копирование как '? локальных данных) значении в ПыдеЛе.ХХИхХ?ь Ч**™™ ™Р">"Р<" использовать в качестве фактически (ТЫ 3 .П| г
л* в среде Turbo Разсв/ 7 о 157 мя работы процедуры/функции как использовать, гак и изменять значение „ени.пс значений формальных параХ"параметров ' „ ,мснения соответствующих фактических параметров ‘ т олно“реме"ного „ , окончании процедуры/функции ’ с||ачача аналогично параметрам value out используя скопированные адреса ф.ктнчсских параметров выполняется запись результирующих значений формальных параметров в ячейки памяти фактических параметров б) память, выделенная дзя работы процедуры/фхнкнии, очищается 11.3.4. Параметры addr ш (в Turbo Pascal реализованы) При вызове процедуры/функции а) выполняется выделение памяти только для локальных данных и для сохранения адресов фактических параметров (в стеке или в специальной области памяти для токальных данных), б) выполняется копирование адресов (но не значении') фактических параметров в выделенную для них память, Во время работы процедуры/функции а) запрещено изменение значений формальных параметров, б) использовать значения формальных параметров разрешено только в качестве исходных данных, в) значения формальных параметров, используя скопированные адреса выбираются непосредственно из памяти фактических параметров При окончании процедуры/функции а) влияние вызываемой процедуры/функции на вызывающую через такие пара метры отсутствует, б) память, выделенная для работы процедуры/функции очищается 11.3.5. Параметры addr out При вызове процедуры/функции а) выполняется выделение памяти только для локальных данных и для сохранения адресов фактических параметров (в стеке или в специальной области памяти для локальных данных), б) выполняется копирование адресов (но не значении1) фактических параметров в выделенную для них память, И значения формальных параметров непосредственно после вызова нс определены. О использовать в качестве фактических параметров константы запрещено время работы процедуры/функцин а) опрощается использовать значения формальных параметров до тех пор пока г не будет выполнено первоначальное присваивание какого-либо значения б| изменение значений формальных параметров используя скопированные ^реса выполняется непосредственно на ячейках памяти соответствующих Фактических параметров, п°“'“'ании процедуры/функции , резущгат сра.у Специального копирования резучыи’ » г поучается в ячейках памяти фактических паР®М€Тр”® пим11мется б,"амять вывезенная тли работы процедуры/функции. очищается
11 3 6. Параметры addr inout (в Turbo Pascal реализованы) 1 При вызове проиедуры/функции- только для локальных данных и для сохранен,, а) <в стеке или в специмьной облаети б) в^пЕяТтся коп"ие адресов (но не значений!) фактических парал,е1ш в в) ,Хе^ХТкачестве фактических параметров константы запрещено 2 ТнгХиТо7ра^ параметров данною вида „с 6) изменение значений формальных параметров, используя скопированные адреса, выполняется непосредственно на ячейках памяти соответствующие фактических параметров. 3. При окончании процедуры/функции: а) специального копирования результата не требуется, поскольку все действия с формальными параметрами выполнялись непосредственно над ячейками памяти фактических параметров; б) память, выделенная для работы процедуры/функции, очищается. 11.4. ПЕРЕДАЧА ПАРАМЕТРОВ В Turbo Pascal В Turbo Pascal реализовано три из вышеописанных шести способов псршЛ параметров: 1. Параметры вида value in. В Turbo Pascal такие параметры называются параметрами-значениями. При описании заголовков процедур/функций перед идентификаторами парамет- ров-значений дополнительные ключевые слова не ставятся. 2 Параметры вида addr inout. В Turbo Pascal такие параметры называются параметрами-переменными рн описании заголовков процедур/функций перед идентификаторами параметров-переменных ставится ключевое слово var 3 Параметры вида addr in Pascal такие параметры называются параметрами-константами. При метпов Jn загс,Ловков пР°иедур/функцнй перед идентификаторами nJPa' метров-констант ставится ключевое слово const % лХиятГ разновидн°с™ параметров (параметры-з^^" и ^epXзы«aПe^Hт'e, Я8ЛЯЮТСЯ ^артными для всех реализации являются новппао 03 Т₽етья разновидность (параметры-конс/паит Turbo Pascal версии 7 0 _____
• среде Turbo Pascal 7 0 11.4.1. Параметры-значения ,.„„|OIU>K процедуры с Описанными параметшми » I трами значениями имеет такой pi'-i-----------------------------------.--------------------- Pocedura MyProc ( Pari, раг2 . ; Механизм работы параметров-значений упрощенно можно представить такой VU‘MOII Фактический параметр В ячейки памяти формального Нормальный параметр параметра передается копия фактического и обратно не возвращается В качестве фактического параметра-значения могут использоваться как временные, так и константы различных типов Не допускаются только файловые типы и типы, опирающиеся на файловый. 11.4.2. Параметры-переменные Заголовок процедуры с описанными параметрами-переменными имеет такой вид: procedure МуРгос ( var Pari, Раг2 : Type); var РагЗ, Раг4 : Туре2 ); Механизм работы параметров-переменных упрощенно можно представить такой схемой: Фактический параметр Передается адрес фактического параметра S Формальней параметр По иненценуся адресу изменяется содержимое ячеек памяти фактич- еского параметра, т.е. выполни- ется возврат результата. В качестве фактического параметра-переменной могут использоваться пере -иные любых типов, включая файловые и опирающиеся на файловый, но зато •чопьзование констант не допускается 11.4.3. Параметры-константы оголовок процедуры с описанными параметрами-константами имеет [procedure МуРгос ( const РТгТ Раг2~ ТуреГ^<: Par3’ Раг4 : Type2-2iJ ' ”, ,..т НПО можно представить ’еханизм работы параметров-консь хе мои
ЛродоОуры u Передается адрес фактического параметра > Формальный параметр Фактическим параметр По имеющемуся адресу разрешено только брать значение фактичес а изменять его значение запрещено, т.е. обратного влияния нет В качестве фактического параметра-константы могут использоваться ка В качестве фа _ различных типов Не допускаются только файле»? тПипы'иНтипьГопираюшиеся на файловый Кроме того запрещается вь,г101н“' присваивания формальных, параметрам-константам и формальные параметры констан™ не могут передаваться в качестве фактических параметров др^, пР°иеДПар^^ыК-консганты целесообразно использовать в случаях, если требуется передавать структуры данных, занимающие большой размер памяти, но изменять исходные значения параметров с алгоритмическом точки зрения недопустимо В результате экономно используется оперативная память и одновременно гарантируеп, целостность исходных данных 11.4.4. Бестиповые параметры Бестиповые параметры могут передаваться тснько по адреса то V параметры-переменные «пи как параметры-константы Главной особен) 1 бестиповых параметров является отсутствие указания типа параметра в зато „ процедхры Заготовок процедхры с описанными бестиповыми параметрами при различных способах передачи имеет такой вид procedure МуРгос ( var Pari, Par2; const Par3,Par4 ), ] В качестве пр универсальные пром размерности, элемент) типа Byte При этом каж 1 ему требуется Однако следует помнить что вследствие отсутствия типа нельзя испольх'вать бестиповые формальные параметры так же как и типизированные Перед испоив какому-листину ВЬ'П0,1НИТЬ nPHBCJen»c формального бестипового параметра к огветственностьЫС11П>РаМеТРЫ б°Ле' Гибки в Работе типизированные, И» “ V°~ ,=S5=S=.- ,м программу, н которой ’ и сортировки одномерных м и1ь любого типа* являющегося jio и*1 ‘Иимает в памяти ровно столько места, ска»*0 ровки массивов типТсь может с успехом использоваться Л1’ £<*J значений типа Byte II \SCII не выходят за n|*Lrf не подходят потому лог для символьных масс ‘.“од-вывод число. ОД ВЫВОД символов
. > ого ! urbo Pascal 7 о 1 = 7; m = 10; n « 15; pe ч-axVect = array [ 1..Maxint ] of Byte • -VectorByte ~ array [1..Ц of Byte; ;Vectofl00 = array [l..m] of 1,.iqq. TVectorChar = array [1. n] Of Char; ByteVector : TVectorByte; VectorlOO • TVectorlOO; CharVector . TVectorChar; : Word; zcedure SortVector ( var Vector; Len : Word }, М1П Imin Byte ; Word ; Word; *cr i : = 1 to Len-1 do begin Min := MaxVect (Vector} [i] , ( Приведение параметра } ( Vector к типу MaxVect } Imin ;= i; for з := i+l to Len do if MaxVect (Vector) [3] < Min then .begin Min •= MaxVect (Vector)[j], Imin •= з end; MaxVect (Vector}[Imin] .= MaxVect (Vector)[i], MaxVect (Vector)[i] = Min, end, -edure InpVector ( var Vector Len Word, I. String } Word;
162 procedure var ( var Vector Len Word ) , begin Word Writeln (ОТсо₽^аи»й«= for 1 ~ Writeln, Writeln Readln, 1 to ban do Write ( MaxVect (Vector) (Ц 8) , (’Нажмите Enter end, begin InpVector SortVector Printvector ByteVector, 1 ByteVector, 1 ByteVector, 1 , 1 Byte' InpVector ( VectorlOO, m , SortVector ( VectorlOO, m ) PnntVector ( VectorlOO, m ) 100 ) , массив *), ( Charvector[i] 8), ClrScr Writeln ('Введите n 3,' элементов типа Char '), for i = 1 to n do Read ( Charvector[i] ) Readln SortVector ( CharVector, Writeln ('Отсортированный for i = 1 to n do Write Writeln Writeln ('Нажмите Enter Readln end 11.4.5. Открытые параметры-массивы щим образом™^ проиедУрЬ| открытые параметры-массивы описываются следую procedure OpenVector ( Vector: array of Typevector ); [ коиста^ойЬи^Ипараме^омМДСерИеВмен^о^ ПаРаметРон'значением типом TypeVector параметры должны по типу совпадать с описанным переменной типа TvpeVectnr3MepHOC™ они МОГУТ быть различными как простои Гибкость примем™ '“ " Массивом любой размерности единообразия представления эт^И° различной Размерности получена за сч формальные открытые паты»™ массивов как формальных параметров В описываются как массивы с В рамках процедуры автоматичен в заготовке типа улсвой базой (нулевой нижней границей) указанного «-1 ] of Typ.v.ctoi- где N - число элементов я ---------- Другими -X и*иКн™;'СК°М параметрс параметра-массива отображается / диапазон изменения индекса фактическо диапазон изменения индекса от 0 до N
163 aKU0 в среде Turbo Pascal 7 Q я определения характеристик переданного фактического параметра-массива цСдуры используются стандартная функция Low, которая всегда возвращает «•ле пР°тная функция High, которая возвращает индекс последнего элемента в сГ‘1НД,1Р м параметре-массиве, и функция SizeOf, которая возвращает размер ! Какого параметра-массива • лаКТиче оМОщью открытых параметров-массивов можно решать проблемы, С Пые рассмотренной в предыдущем примере Однако открытые параметры- Зцалогйчн Задают меньшей гибкостью, чем бестиповые параметры, поскольку в |1ассивЫ в качестве фактических параметров могут быть массивы только ^НН°М сЛУ ^ного аВненИя с использованием бестиповых параметров, приведем для ДлЯ аметоов-массивов такую же программу, как в предыдущем примере -------------------------------------------------------- program Sort; uses Crt; const hi = 10; n = 15; TVectorl = array [l..m] of Byte; TVector2 = array [l..n] Of Byte; Vectorl : TVectorl; Vector2 : TVector2; procedure SortVector ( var Vector : array of Byte } ; var Min : Byte; Imin . Word; 1,3 : Word; begin for 1=0 to High (Vector) -1 do begin Min .= Vector[i] ; Imin := 1; for з := i+i to High (Vector) do if Vector[3] < Min then begin Min .= Vector[3]. Imin •= 3 end; Vectorflmin] » Vector(i) . Vector(i) :« Min; end, end; ----------------------------------------------------- procedure InpVsctor ( var Vector. array of Byte > . 1 : Word, begin Clrscr, Writeln for 1 = Raadln.
2 <----------------------- procedure PrintVector ( var Vector array of Byte ) var x Word begin Writein ('Отсортированный массив ') , for i •= 0 to High (Vector) do Write (Vectorfxi Writein, J Writeln ('Нажмите Enter '), Readln , end, bagin TwpVeator ( Vectorl ) ; SortVector ( Vectorl )r PrintVector ( Vectorl ), InpVector ( Vector2 ), SortVector ( Vector2 ), PrintVector ( Vector2 ), end 11.5. ПРОЦЕДУРНЫЕ ДИРЕКТИВЫ 11.5.1. Директивы near и far Директивы near и far указывают компилятору согласно какой модели ныкЯ процедур — ближней (near) или дальней (far) — требуется генерировать выходной код При ближней модели вызов выполняется быстрее, при дальней — медленнее Однако область действия ближних вызовов ограничена рамками только того модуля, в котором описана вызываемая процедура Директивы near и far указываются в описании процедхры/фхнкции перед ее отоком function SH( X Real) Real, SH = (Exp(X)-Exp(-X)) / 2, end, Управлять генерацией выходного кода согласно указанным моделям вызов можно также директивой компилятора (SF+) Процедуры и функции, компилируем в состоянии (SF+), всегда будут иметь дальний тип вызова (far), а в состоя (SF-) компитятор автоматически выбирает корректнхю ’ По хмозча используется директива (SF-) 11.5.2. Директива forward Директива forward испотьзхется для, так называемого. опере*а|ОШе™ описания процедур и функций, которое используется для реализации взаимно» рекурсии двух процедур, а также для улучшения структурированности текст» повышения его читабельности и *
165 в среде Turbo Pescni / procedure Rael (x Byte) procedure Rac2 (x Byte) begin Writeln (' рекурсия ’} Reel (1} end, procedure Reel, begin if i > 0 then begin Write (’Взаимная '}, Rec2 (1'1} end end, begin ClrScr, Reel (5) end forward Результат Взаимная Взаимная Взаимная Взаимная Взаимная рекурсия рекурсия рекурсия рекурсия рекурсия 11.5.3, Директива interrupt Директива interrupt служит для описания процедур прерывания В заголовке процедуры прерывания в качестве параметров должны быть описаны имена регистров procedure Intrpt (Flags, CS, IP, AX, BX CX, DX SI, DI, DS, ES, BP Word} interrupt Ес1и некоторые из параметров в процедуре не используются, то они могут опущены Однако изменять взаимораспочоженис имен регистров в списке паРаметров не допускается 11.5.4. Директива export Директива export описывает процедуру или функцию как экспортируй ю директива и экспортируемые процедуры описаны в главе 7 11.5.5. Директива external Директива external предназначена для связывания отдельно скомпитиро- ",,их процедур и функций которые написаны на языке ассемблера а также для с"Сания процедур импортируемых из динамически компонуемых библиотек с ассемблерными процедурами рассмотрена а главе посвященной ассемблерным KdM а импорт из библиотек ~ в главе 7
'P^o/pbl и фу,4Я1 166 Ц.5.6. Директива assembler , пкже как и директива external используется ад, Директива assembler • ’ в отличие от нее директива asse№1 —компонуемых библиотек 11.5.7. Директива inline Директива mlane предоставляет программисту возможность записывать Кттапрск^Та^ В ГЛаВС посвяшеняои ассемблерным вставкам Контрольные вопросы 1. Какой вид имеет структура описания процедуры и функции’ 2 В чем состоит отличие описания процедуры и функции 3 Что такое область действия идентификаторов9 4 Каковы основные правила определения области действия для идентифика- торов процед\р и функций9 5. Какие параметры называются формальными и какие — фактическими9 6 По каким признакам различаются параметры9 7 Какие способы передачи параметров теоретически допустимы9 8 Какие способы передачи параметров реализованы в Turbo Pascal9 9 Каковы правила передачи параметров-значений9 10. Каковы правила передачи параметров-переменных9 11. Каковы правила передачи параметров-констант9 Ж 12. В чем особенности бестиповых параметров9 Л 13. В чем различие открытых параметров-массивов и бестиповых параметров9 14. Для чего предназначены директивы near и far9 15. В чем особенности использования директивы forward9 16. Какая директива предназначена для описания процедур прерывания’ Какие директивы используются для описания процедур на языке ассемблера’ 18. Что позволяет директива inline’’ Контрольные задания .— иижепРиведенных задачах повторяющиеся части алгоритма (bboj цементов массива выпп™.., " повторяющиеся части алгоритма <»” В виде процедур или функций 11™™”“' яейств"й вывоя результатов) различные способы передачи параметров Cd””” проиеяУР и Функций испольхям В|20|, С|15) Найти мамимадш^>МСрнь1х масс11вя> вещественных чисел *1^1 -емент среди найденных максь.мазХ""^^^ из массивов и максимальны11 н . 2- Даиы три вектору ,,, Найти сумму элементов, р 4 массива) целых чисел A(m] В|п1 нулевой элемент присутсл ' 40 |,сРв<>го нулевою элемента (хоть оД* п'4 ~ введение элементов, расположенны
167 ^е среде Turbo Pascal 7 О — Три матрицы вещественных чисел A|m,n| B(n pj, С[рр| Определить 3 Дань кажаой строки для каждой из матриц ы три квадратные матрицы целых чисел A[m,m|, B[n,n|, С|рр| 4. Дан_ Каждую из матриц относительно побочной диагонали цсПОННРО ‘ Тг —и матрицы вещественных чисел A(m,n], B[p,q], C[s,t] Упорядочить 5. Дань1 * из МДТрци методом по невозрастанию ,л столбец ка^ь" а) вставки, б) выбора, 0) обменов
ГЛАВА 12 12.1. ПОНЯТИЕ РЕКУРСИИ И ОСНОВНЫЕ ОПРЕДЕЛЕНИЯ Рекурсивным называется объект, который частично определяется через самого СебЯ' Идеи рекурсии известны людям издавна Рекурсивные определения как мощный аналитический аппарат используются во многих областях науки, особенное математике . Рассмотрим функцию факториала п! Как правило, ее определяют как произведение пер вых п целых чисел.___ П! =1*2*3* ... *п Такое произведение конечно можно легко вычислить с помощью итеративных конструкций, например, оператора цикла for Однако используется program Factorial; var Fact Longint; n, i Integer; begin Write (’Введите число n: ') ; Readin ( n ), Fact •« 1; ^or i .=1 to n do Fact := Fact * i; Writeln ('Факториал n’ = Fact); end существует также другое определение факториал рекуррентная формула и которое имеет такой вид 1, В котором (1) О' - I 12> ДЛ" п > 0 п- = П . (П - 1) . рекурсивным»1 ление мо*ст определе^я^иИИЕсли0д°я1^^кТо^има™епвФОРМУ1 иио, и называют показаться проще, то для чисел Фибоначчи oTJ”"^ВН°С) °ПреД' И) vid - а, (2) F<2) - 1, ~Я * 2 F(n> - Г In-1) + F(n-2) выглядит для вычислений лучше, чем^^^
tt среде Turbo Pascal 7 0 Г69 Похожие рекуррентные формулы есть также и иля многих других математи определении Понятно что организовать вычисления по рекуррентным чеСК*,Х ни можно и без использования рекурсии Однако при этом встает вопрос о ф°Рм' программы и доказательстве ее эквивалентности начальным формулам качеств ме рекурсии позволяет легко (почти дословно) запрограммировать по рекуррентным формулам Например программа использующая ВЬ1Ч,,С <внмо функцию для вычисления факториала п’ имеет следующий вид picogram Factorial var n Integer function Fact ( x begin if 1 = 1 then else end Integer ) Fact = 1 Fact = 1 Longint * Fact ( 1-1 ) begin Writ© Readln Wn teln end 'Введите число n n ) ( Факториал n1 = ) Fact ( n )) ичзнач Одерлание и мощность рекурсивного определения а также его павнос пр сние состоит в т°м что оно позволяет с помощью коне шого выражения бесконечное множество объектов Аналогично с помощью конечного "t 01 ИВНого алгоритма можно определить бесконечное вычисление причем алгоритм ^содержать повторении фрагментов текста Of '1Ля с°здания рекурсивных алгоритмов необходимо и достаточно наличие озй пР°иедуры или функции Это вытекает из того что процедуры и функции топ ЛЭТЬ л1°бой последовательности действий (операторов) имя с помощью {_° можно будет эту последоватезьность действии вызывать ‘^пример сзедующач процедура будет бесконечно печатать известные всем EndXessl procedure PopeAndDogl begrn Wrxteln ( У попа была собака ои ее любил ) Wrxteln( Ома съела кусок мяса ои ее убил ) Wrxteln( похоронил и надпись написал ) PopeAndDogl end b©gxn PopeAndDogl end
— _____________ 170 Однако если операюр вызова процедуры поставить перед выводом как пока юно ниже._____________________________________________ Program EndLess2, procedure PopaAndDog2; begin PopeAndDog2; Writein ('У попа была собака, он ее любил. ); Writeln('Она съела кусок мяса, он ее убил,'); Writein ('похоронил и надпись написал: ') ; end; begin PopeAndDog2 end. _________________ то такая программа ничего не напечатает, хотя и будет работать также бесконечно, как и первая. Это объясняется тем, что оператор вызова процедуры стоит первым и, соответственно, вызов новой копии Процедуры PopeAndDog2 произойдет раньше, чем вывод текста. В следующей копии процедуры будут сделаны аналогичные действия, и так далее. В результате Произойдет бесконечный вызов процедуры PopeAndDog2 без какого-либо вывода текста, хотя оператор вывода в процедуре присутствует В действительности При исполнении на компьютере такой бесконечны!1 вызов приводит к переполнению стека и возникновению ошибки времени исполнения Программы, в которых используются рекурсивные процедуры отличаются простотой, наглядностью и компактностью текста. Такие качества рекурсивных алгоритмов вытекают из того, что рекур процедура указывает что нужно делать, а нерекурсивная больше тирует внимание на том, как нужно делать. Однако за эту простоту приходится расплачиваться неэкономным исполъзо ванием оперативной памяти, так как выполнение рекурсивных процедур требуй значительно большего размера оперативной памяти во время выпотнения чем нерекурсивных При каждом рекурсивном вызове для локальных переменных. ‘ также для параметров процедуры, выделяются новые ячейки памяти Таким образом, какой-либо локальной переменной А на разных уровня) рекурсии будут соответствовать различные ячейки памяти которые могут имен разные значения н 7 'Л Поэтому, воспользоваться значением пер^^ А ,.го yDoe^- курсии можно находясь только на этом ьм уро^и^ Дадим некоторые определения, имеющие отношс Максимальное число рекурсипш происходит во время выполнения про Число рекурсивных вы юйов и ► текущим уровнем рекурсии ние * рекурсии РЫ без возвратов, когор01' ' Шубиной рекурсии |(>мент времени, называть
171 cpeov у- Уу - 12 2. ФОРМЫ РЕКУРСИВНЫХ ПРОЦЕДУР ем случае любая рекурсивная Процедура Rec включает в себя некоторое В риторов S и один или несколько операторов рекурсивного вызова Р ?ло показано выше безусловные рекурсивные процедуры приводят к 11 кук бы ессаМ ц на эту проблему нужно обратить особое внимание так ,Н11М ' использование процедур с бесконечным самовызовом невозможно , ^’,4Ltb°HOCTb вытекает из того что для каждой копии рекурсивной процедуры Aq нево-}Мб* *‘ , дополнительную область памяти а бесконечной памяти не ВЫД tbs ет —,------------—- Следовательно главное требование к рекурсивным процедурам заключает ся в том что вызов рекурсивной процедуры должен выполняться по усло- вию которое на каком-то уровне рекурсии станет ложным ~условие истинно то рекурсивный стек продотжается Копа оно пожным> то спуск заканчивается и начинается поочередный рекурсивным * нз всех вызванных на данный момент копии рекурсивной процедуры Структура рекурсивной процедуры может принимать три разных формы I Форма с выполнением действии до рекурсивного вызов, (с выполнением действии на рекурсивном спуске} procedure Rec begin S if условие then Rec end *Форма с выполнением действий после рекурсивного вызова (с выполнением действии ^курсивном возврате} procedure Rec begin if условие then Rec S end ________________ u с выполнением действий как до так и после рекурсивного вызова Ягнением действии как ни рекурсивна* спуске тал и на р*к\р^ивно* procedure Rec begin if условие Rec S2 end procedure R®c begin then xf усл©»“* begin 91 Rec 52 end end_______—------
172 Все форм,, рекурсивных процедур н"одаТ М1^ задачи в том числе вычисление факториала бе .разли шы тому какая исподу' форма рекурсивной процедур i Однако есть классы задач при решении которых программисту^^ ся сознательно управлять ходом работы рекурсивных процедур и ф ции Такими в частности являются задачи использующие списковые и дрее<г видные структуры данных______________.____ I Например при разработке трансляторов широко применяются пк называемые атрибутированные деревья разбора работа с которыми требует от программиста умения сознательно направлять ход рекурсии одни действия можно выполнить только на спуске а другие — только на возврате Поэтому глубокое понимание рекурсивного механизма и умение управлять им по собственному желанию являете» необходимым качеством квазифицированного программиста Первые две формы рекурсивных подпрограмм рассмотрим на примере вычисления факториала (п‘) третью форму — на примере реверсивном гг вводимом строки 12.2 1 Выполнение действий на рекурсивном спуске Для pcLiHJdfiMM универе шыгог о алгоритма вычисления факториала, виИ таюшего на спуске в рекурсивную функцию требуется дополнительно ввесяЯ параметра Mult - для выполнения до рекурсивного вызова (то есть на спуске) операции умножения накапливаемого значения факториала на очередной множитель program Factorial Down ----’----------------—______________ function begin Mult Fact_Dn ( Mult Longint i “ Mult • then Integer ) Longint *.«то₽„м. стоит ДО , Сл,лот0ра ₽**yPCM,«or,o вы,ова ) “чиел.ни. ВЫПОл-> "Летел иа спусиа , -Оп • Mult ' •nd beg; * №d 'тори ал t_Un ( i л ) , J
173 1>м ,\м**ue e оре<4 Генfro Pascet ~ о рации выполняемых функцией Fac. Dn лссшин .тиведем ' ...... ’"У™’1" « п<Ф««тГов по уровням ^екур£ . В "той г Ьто.и !( конкретный случай для п= 5 малице 1СК? шнй ipORCUb Рекурсивный cu? ск Рекурсивный возврат Вво t in-5) Muh =kl (П, Mult =1-2 (2\ Mult ^2-3 (bl. Mult - o-4(24\ Mult =24-5 (120), 1=4 Fact Г>щ 1,2,5\ Tact Пщ23,5\ Fact l>ufr,4 5). Fact Пп ~ 120, Вывод n'= 120 Fact^Dn ~ 120, Faction =120 Fact^Dn = 120, 12.2.2 . Выполнение действий на рекурсивном возврате • Рассмотренная в начале главы программа Factorial. использующая рекурсивную ^унчиню Fact, выполняет вычисление факториала на возврате Но это нс совсем учен* ню, поскольку б функции Fact рекурсивный вызов и операция умножения Совмещены в одном операторе присваивания Для более понятной демонстрации |воо м на возврате, приведем программу Factonal_Up. использующую функцию Fix I - в которой рекурсивный вызов и оператор накопления факториала разделены |ы. и ооразоу! Factorial_Up: Integer . —notion Fact_Up Integer ) Longint xx’ x = 1 then Mult :« 1 else Mult :» Fact_Up < 1-1 > -- - Uo = Mult * 1 ( Накопление факториал* стоит после > . оператора рекурсивного аиэоаа I . Слелоаателино вычисление натолки- 1 ( етсл на воаврате ’ Ьедхп Write ('Введите число п '> Readln ( п ) Writein (♦•хторижл п' • ‘ Fact_Cp < '» end ировки по .1Х.Ю.Я» ревмкии. днлтогичи.ю rXvw.te
174 Текущий уровень Рекурсивный спуск Рекурсивным вошрат о Ввод (п=5); Fact Up(5) Вывод: n’= 120 I I i=5; MuIt:=Fact_Up(4); Fact_Up;=24*5 (120)~ 2 1=4; MuIt:=Fact_Up(3); Fact_Up:=6*4 (24); 3 т MuIt:=Fact_Up(2); Fact_Up:=2*3 (6); 4 I i=2; MuIt:=Fact_Up(l); Fact_Up:~1*2 (2); 5 i=I; Fact_Up:=l*l (I); H 12.2.3 . Выполнение действий как на рекурсивном спуске, так и на возврате Третью форму рекурсивных подпрограмм покажем на примере следующей задачи Задача Вывести на печать символы введенном строки 'HELLO' в обратном направлении Решение этой задачи выполнено в виде показанной ниже программы Reverse_Stnng, испотьзующеи рекурсивную процедуру Reverse Напомним, что функция eoln возвращает значение, равное False, если строка еще не окончилась и значение равное True, когда считывается последний символ строки
л,.им1(г « ерем f urbo Pascal 7 о 175 12.3. ЗАДАЧА О ХАНОЙСКИХ БАШНЯХ ^ХСо ХанХ^бХяГ^™15^ в -гори™» покажсм на »р">|Спадача Даны ТРИ столбика — А. В, С На с „дыре диска Разного диаметра, пронумерована?^ А °ДИН На др;’дом иахо- ^гаются так' что Каждь,й меньший диск н»одится „Хашем "Р"4™ °Н“ Требуется переместить эти четыре диска на столбик С, сохранив их взаимо- расположение Столбнк В разрешается использовать как вспомогательный При решении за один шаг допускается перемешать только один из верхних дисков ^кого-либо столбика Кроме того, больший диск никогда не разрешается класть илкк меньшего диаметра Для определения подхода к решению поставленной задачи рассмотрим ooiee общий случай с п дисками Если мы сможем сформулировать решение для п исков в терминах решения для п-1 диска, то поставленная проблема была бы решена поскольку задачу для п-1 диска можно будет, в свою очередь, решить в терминах п-2 дисков и так далее до тривиального случая одного диска А для итучая одного диска (п=1) решение получается элементарным Нужно просто переместить один-единственный диск со столбика А на столбик С Таким образом, если сформулировать решение для п дисков в терминах п-1 диска то мы фактически получим алгоритм рекурсивной процедхры с помошью которой можно легко достичь цели поставленной задачи Рассмотрим словесное описание такого алгоритма ( then ) Переместить этот единственный диск на столбик С и остановиться со столбика А 2 столбика А на вспомогательный со столбика А Переместить верхние п-1 диск со столбик В, используя столбик С как Переместить оставшийся нижний лис на столбик С столбика В на столбик С переместить п-1 вспоиогатель>ши используя столбик А как 3 -------------------------------------- „,еДоватетьность действий даст о-*но с уверенностью сказать, что та „Ь|Текаег из следующего Если ™°С решение для любого значения п стт имеем решение ° адРректиость очевидна Если п-2. т° мь ссл„ -к, . нова имеем ’ч« (n-l).ro диска, которое равно 1 Анало™
17S ass* павно " Подобным образом можно показу решение апя 1,,CNJ , ? 4 5 и ка>.ого-1и6о другого а что это решение работает для n । • • ш решает поставленную задан. Приведем программ; Hanoi 1 were, к помошъю рек'рошноН процедуры More Di Byte Source, Dest, Tmp Char на столбике Source ( Source { Dest { Trap begun program Hanoi__Towers. uses Crt var n Integer, procedure Move__pisks ( n - Число диско© - Исходный столбик - Столбик, на который нужно переставить диски - Вспомогательный столбик Wri = 1 then , .teln(’Переставить диск номер 1 co столбика Source, ' на столбик ’, Dest} else begin Переставляем п-1 верхних дисков с исходного столбика на ~ ) вспомогательный, используя целевой диск как промежуточный ) Move_Disks ( n-1, Source, Tmp, Dest }, Writeln (’ Переставить диск номер ’ , п 1, ’со столбика ', Source, ’ на столбик 1, Dest), Переставляем все п-1 диск, расположенные на вспомогательном ) { столбике, на целевой используя исходный диск как промежуточный ) Move Disks { n-1, Trap, Dest, Source) , end end begin ’y, ClrScr, Write (’Введите число дисков ’), Readln(n) Writeln в Writeln (’Последовательность инструкций для решения задачи 1), Wrxteln Move__Disks (nA С ’В’) end Результат работы программы Hanoi_Towers для числа исходных дисков ю стотбикеА, равного 4 будет таким Введите число дисков 4 Последовательность инструкции Переставить диск номер 1 со Переставить диск номер 2 со Переставить диск номер 1 со Переставить диск номер 3 со Переставить диск номер 1 со Переставить диск номер 2 со Переставить диск номер 1 со для решения задачи столбика А на столбик В столбика А на столбик С столбика В на столбик С столбика А на столбик В столбика с на столбик А столбика С на столбик В столбика А на столбик В
-^зние в среде Turbo Pascal 7 О 177 переставить ДИСК номер 4 со столбика А на столбик переставить диск номер 1 со столбика В на столбик Переставить диск номер 2 со столбика В на столбик Переставить диск номер 1 со столбика с на столбик переставить диск номер 3 со столбика в на столбик переставить диск номер 1 со столбика А на столбик -еростаэить диск номер 2 со столбика А на столбик переставить диск номер 1 со столбика В на столбик с с в с с Подводя итоги рассмотренной задачи следует отметить аналогию между методом итическои индукции и рекурсивным методом программирования Действительно, ><аТС' 6faWO сформулировано решение для одного диска Потом было предположение ^^твования решения для (п-1) го диска и на основе этого предположения CVU1C еиД проиедура перемещения п дисков которая вызывает сама себя Указанная П°СГР /я показывает мощность рекурсивных методов программирования так как с их ^'шью удается в естественном стиле программировать решения как алгоритмов я°м оенных по рекуррентным формулам так и алгоритмов более общего характера как задача о Ханойских башнях 12.4. БЫСТРАЯ СОРТИРОВКА Реализация метода быстрой сортировки массива валяется прекрасным примером использования рекурсии Этот метод был разработан в /962 г профессором Оксфордского университета КХоаром Принцип метода* 1 Выбираем центральный элемент массива А и записываем его в переменною В Злеч элементы массива просматриваются поочередно слева направо и справа налево При движении слева направо ишем элемент A[i| который будет больше или равен В и запоминаем его позицию При движении справа налево ишем элемент A(j] который fr-дет меньше или равен В и также запоминаем его позицию Найденные элементы меняем местами и продолжаем встречный поиск по указанным условиям Найденные цементы меняем местами и так далее пока при очередной итерации поиска встречные индексы । и j не пересекутся 5-1 Je6 После этого первый эта( Диого массива окажутся рззл нты которые ме> и я индексов t и 4 шъся справа от гра*,. 1 Лается отсортированным, ио
178 2. На втором этапе повторяются действия первого этапа_для те вой и nWBo частей массива в отдельности В резу тътате массив окажется разбитым уже на четщги иеперссекаюшнеся по сортировке части, которые можно упорядочивать по отдел* мости На третьем этапе повторяются действия первого этапа в отдельности для ках^' из четырех частей и так далее, пока длина сортируемых частей не станет равной одному элементу и. следовательно, все элементы массива будут уже упорядочены Поскольку иа каждом этапе повторяются одни и те же действия, но в разных индексных рамках массива, то их удобно оформить в виде самовьпьь ваюшейся рекурсивной процедуры, которая используется в следующей программе 1
179 pofo Turbo Pascal 7 о utviini"i PuSoT1’ P процедуры OSort nnn, M P продемонстрируем елшощеи QSort (1, Ю ) Первый уровень рекурсии Исходный массив QSort(1,5) QSort (6,10) Второй уровень рекурсии 12 13 4 5 1=1 [~2~[4~ ~4| 1 | 6~|r=5 Г-2 1=4 L=6 6 7 8 Э I 10 [ 7 | 8|l2| 9 10| TB = 12' f R=10 QSort (1,2) «QSort (4, 5)/ QSort(6,9) J=9 1=10 ызов не выполняется Третий 1 2 L~l| 2 I ] |r=2 >21 1=1 1=2 1=1 — i=R Вызов не выполняется рекурсивны» / _ возврат уровень 5 Вызов не выполняется рекурсии L=6 6 7 8 9 18 ю| 9 | р=8 R=9 в =8 1=6 рекурсивный возврат ~ Четвертый уровень рекурсии Вызов не выполни ется QSort(8 9). i-9 l^=== »-R Вызов не выполняется рекурсивным возврат
180 Контрольные вопросы 1 К1КОИ объект называется рекурсивным9 2 В чем состоит мощность рекурсивных определений7 3 Что необходимо для реализации рекурсии в программе7 4 В чем преимущества н недостатки использования рекурсивных процедур По сравнению с нерек\рсиаными7 5 Что называется глубиной рекурсии7 6 Что называется текущим уровнем рекурсии7 7 В чем заключается главное требование к рекурсивным процедурам9 8 Какие формы может принимать структура рекурсивной процедуры7 Контрольные задания 1. Вычислить следующие формулы, используя для решения реьлреивяр» процедуру ити функцию нуь а) где к — ifечая константа б) г()е аип 1^Ь1е положительные числа ' кор; 2 (“I)1 (l 4-1) Опредс urn, наибольший общий дечитель (НОД) двух чисе- (А>0,В?0,А/ В) по алгоритму Евклид?

ГЛАВА 13 ФАЙЛЫ 13.1. ПОНЯТИЕ ФИЗИЧЕСКОГО И ЛОГИЧЕСКОГО ФАЙЛА У понятия файл есть две стороны С одной стороны, файл - это именованная область внешней памяти содс жащая какую-либо информацию Файл в гаком понимании называют фи,аЧЮаи1 файлом, то есть существующим физически на некотором материальном Носите^ информации С другой стороны, файл ~ это одна из многих структур данных используемых в программировании Файл в таком понимании называют логическим файлом, то есть существующим только в нашел» логическом представлении при написаний программы В программах логические файлы представляются файловыми переменными определенного типа 13.1.1. Структура физического файла Структура физического файла представляет собой простую Последовательность байт памяти носителя информации — жесткого магнитного диска (ЖМД) шли гибкого магнитного диска (ГМД) байт байт бант байт байт байт 13.1.2. Структура логического файла Структура логического файла — это способ восприятия файла в программе1 Образно говоря это “шаблон” (“окно") через который мы смотрим на физическую структуру файла В языках программирования таким “шаблонам” соответствуют типы данных, допустимые в качестве компонент файлов Образное представлена некоторых из “шаблонов* языка Turbo Pascal показано на следующих рисунках file of Byte fzl& байт байт байт байт Eof of Char код код код символа символа _симвоаа код символа
< * У* ****>• 18J * te b Char c : Tntagar •nd.' I K" "CJW I I SWt «» ‘ ««« I символа co знаком I I________символа co знаком I Lot ч ч гтр\кт\ра фзйла в принципе очедь похожа ча чтрххг*’". х - м м кх-апом и файлом заключаются в следующем х кошчесгео лтементо» фнкснрх^тся в момент ржлреле. ком jxk полагается б оперативной памяти Нумерация элемент < «ч о соответственно нижней н верхней границам указанным при его кс'нчеспю атсментов б процессе рюоты прюгртммы может изменяться >.с1\ч на внешних ^мч^пммтм Нхмепашгя элементов к* «лева нлп ментов АаЙла б к \sC11 с кодом -Р 1КГп--£) Кроме тс«< ч е часто требуемые оперши» можно v < тхчдлртных процедур и фунэдн^и преамонкенных J» рзсюгы <. файлами 2 КЛАССИФИКАЦИЯ ФАЙЛОВ В Turbo Pascal с Fiscal хл.кспфииирук'тс ч » .чей <тр\ктхре> • "о метод* лостуш к ^'ементлм файла
164 „вменения методов доступа к каждой разновидное* Допустимость применен по типу покажем такой схемой 13.3. НАЗНАЧЕНИЕ, ОТКРЫТИЕ И ЗАКРЫТИЕ ФАЙЛОВ Для работы с каким-либо физическим файлом находящимся на ЖМД ши ГМД, необходимо первоначально связать его с файловой переменной (логическим файлом) с помощью которой б>дет осуществляться доступ к этому физическому файлу Связывание логического и физического файлов выполняется процедурой Assign которая может использоваться только для закрытого файла Первым пара метром этой процедуры является файловая переменная, а вторым параметром - строковая константа или идентификатор строковой переменной, значением которых дотжно быть имя физического файла, указанное согласно правилам залижи идентификаторов в MS-DOS Assign (f, 'MyFile Dat') В приведенном примере выпозняется связывание логического файла fW физическим файлом Мх File Dat, при условии, что он находится в текущем каталоге активного диска MS-DOS Если же требуется чтобы действие процедуры Assign не зависело от текущих устройств MS-DOS то записывается полное имя файла с указанием диска пути каталогов и имени фанза например Name = 'а \MyFiles\MyFxle Dat' Assign (f, Name) файлыд^Хта^тк^^4’™60 °ПСраЦНЙ ~ в проиеХ“с"оуеФаИЛОВ °Ы"~" процедурами Reset и Rente а закрытие- Reset (f) Rewrite (f) Процедура Reset открывает evince-™. ... КмЗ связан с фанзовой переменной f Есл f Юшии Физический файл. который о** только для чтения при последовдтс,.,,,” ~ текстовый файл, то он будет доступ' ный файл то он будет открыт и для ЛОС1упс к элементам, если f — типизирован пня и для записи как при последовательно**
705 „.^.int/е в cp&te Turbo Pascal 7 О V^>* 1 1 ж л при прямом При открытии указатель юкушсй иоишии фшл i vci» 'iOl н ct о начало ни । фи инкский файл с указанным именем отсутствует то возникло! Iй 1КМени исполнения, которую можно подгнить выключением директивы ,|})i*'K 1 ‘J I При такой установке директивы можно проанализировать результат \и1 операции открытия файла с помощью функции lORcsult, которая 1 ’-г значение 0, если операция завершилась успешно, п ненулевой код 11 1 в противном случае цмкра ReWMte создает новый физический файл, имя которого связано с *пепемснной f Если такой физический файл уже существует то он удаляется файл0®01 сТС создается новый пустой файл При открытии указатель текущей “1,1 С1° в файле устанавливается в его начало n0,,,UEuie одной функцией используемой Практически но всех программах, является функция Eof (£) возвращает значение True если указатель текущей позиции вфлые t находится за последним элементом файла или если файл пест В противном епчас она возвращает значение False В качестве примера рассмотрим задачу вычисления суммы этсмешов фши Му Fili Dat program FSumma uses Crt, var f file of Integer, X Integer Summa Longint, begin ClrScr, ($1-) Assign (f, 'MyFile Oat'), Reset(f) il-H if lOResult <> 0 then begin Writeln ('Ошибка открытия файла’) Halt (1) end ( Вычисление суммы ) Summa = О *hil© not Eof(f) do begin Read (f X) Summa e + X end Writeln ('Сумма элементов файла равна Close (f) end Summa)
186 13.4. ОБЩИЕ СРЕДСТВА ДЛЯ РАБОТЫ С ФАЙЛАМИ 13.4.1. Процедуры и функции модуля System Напомним, что процедуры и функции модуля System доступны для вызои всегда и подключения дополнительных модулей не требуют Кроме выше рас- смотренных процедур и функций этот модуль для работы с файлами содержит еще процедуры переименования, удаления файлов н процедуры работы с каталогами Процедуры работы с каталогами Для работы с каталогами в модуль System включены процедуры ChDir, MkDir, RniDir и GetDir, которые по смыслу аналогичны командам MS-DOS В качестве примера использования этих процедур приведем следующую программу program DirectoriesDemo; uses Crt, var S : String; begin Clrscr; ( Установить текущим корневой каталог диска Е: } ChDir( 'Е : \ ' ) ; ( Показать текущий диск и каталог ) GetDir(0,S) , Writein('Текущий диск и каталог: S); ( Создать подкаталог MyDir ) MkDir ( 'MyDir ' ) ; ЛВИ ( Перейти в подкаталог MyDir } ChDir (’MyDir') ; vM ( Показать текущий диск и каталог ) лИ GetDir(0,S) , Writein('Текущий диск и каталог: S), { Установить текущим корневой каталог диска Е• } ChDir('\'), { Удалить подкаталог MyDir ) RmDir('MyDir'J , ( Показать текущий диск и каталог ) GetDir(O,S) ; Writein(Текущий диск и каталог S} ; end Процедуры переименования и удаления файлов >===s - а затем удаление атото ф 1ь “нис фаил‘‘ MyFile Dat a Kc.ull.Dat.
187 program RenDelDemo; var f : file: begin Assign(f,'MyFile.Dat'); Rename (f, 'Resuit.Dat') ; Действия с переименованным файлом end. 13.4.2, Константы, типы, процедуры и функции модуля Dos Программы» использующие файловые средства, предоставляемые модулем рей должны включать предложение uses с указанием идентификатора Dos program Example; uses Dos; begin end. Типы для работы с файлами TFxleRec = record Handle: Word; Mode: Word; RecSize: Word; Private: array(1••26] of Byte; UserData: arrayfl. .16] of Byte; Name: arrayf0..79] of Char ; end; PTextBuf = ATTextBuf; TTextBuf = array[0..127] of Char; TTextRec s record Handle: Word; Mode: Word; BufSize: Word; Private. Word; BufPos Word; BufEnd; Word; BufPtr: PTextBuf; OpenFunc: Pointer- InOutFunc: Pointer. FluahFunc Pointer, Buffer TTextBuf; end; _______
188 „ vnr для птизировонных 'ИЛИзик. Тип TFileRec >’^b3Rec - только дая текстовых ванных Файлов а тип ТГ^|КСС _________________________ Sa"nReCarXtrd2U of Byte, Attr Byte, Time Longint, Size Longint Name String[12], end _________________ Переменные типа SearcliRec используются в процедурах FindFnst и FmdNen для просмотра каталогов файлов DateTime = record Year,Month,Day,Hour, Min,Sec Word, end, Тип DateTixie используется в процедурах UnpacKTiMe и РаскТше для анализа упаковки и построения четырехбайтового значения, содержащего дату и время Это четырехбаитовое значение использ>ется затем в процедурах GetFTiMe SetTiMe FindFirst и FmdNext Строковые типы ComStr PathStr, DirStr, NameStr, ExtStr модуля Dos используются для работы с именами файлов и маршрутов при вызове строковой процедхры FSpht Константы для работы с файлами fmClosed = $D7B0 fmlnput = $D7B1 fmOutput = $D7B2 fmlnOut = $D7B3 и закрытииТайз^в SX’ fm'n₽Ut' fmOutPut- используются при открытии перем₽ХИх^Г^ЖГи7ыХеНИЙ П°ЧЯ -«ия-записи)» Readonly Hidden SysFile VolumeId Directory Archive AnyFile $01 $02 $04 $08 $10 $20 $3F только чтение } спрятанный" файл ) системный файл ) тома ) каталог } архивный файл } проиэвольний файл > используются Константы Readonly Hidd ьзутотся для установки атРиб£овфайловУО|"теЮ Dlreclor>' Archlve
U Ьи P»*Q*i f Q 189 Процедуры и функции для работы с файлами шраипет тагу и время посчедней записи файла гпчавливает время и дату последней записи файла Pilkli преобразует запись DateTiMe во внутренний код представле ния даты и времени типа Longint который используется проиеду рои SetFTiMe । npitkTiMC — преобразует внутренний код представления даты и времени типа Longint возвращаемого процедурами GetFTiMe FmdFirst FmdNext в р ^пакованную запись DateTiMe expand воспринимает имя файла и возвращает полное уто шейное имя (диск каталог расширение) FSearth — ищет файл в списке каталогов fiudFirst — производит поиск в заданном (нли текущем) каталоге записи содержимое которой совпадает с заданным именем файла н атри бутами Г d\c\t — возвращает следующую запись нмя файла и атрибуты в которой совпадают с теми которые были заданы при предыдущем обрате нии к процедуре FindFirst С (ГАПг — возвращает атрибуты файла s ГАпг — х станавливает атрибуты файла Кроме того при работе с файлами (особенно при создании новых файлов) знь Т1кже еше две функции модуля Dos Г Fret. — возвращает число свободных байт на диске в заданном дисководе Г Size — возвращает полный объем в бантах заданного диска 13 5 ТИПИЗИРОВАННЫЕ ФАЙЛЫ Все элементы типизированного файла должны быть одного типа Типизиро- ванные файлы могут быть любого типа кроме файлового и опирающегося на файловый Г 1 р недопустимых объявлении type TF1 = file of file TFR - record A Integer F file of Real end TF2 file of TFR Типизированные файлы допускают как последовательный так и прямой доступ Работая с прямым доступом следует помнить что элементы типизированных фаллов всегда нумеруются начиная от нупя--------
190 I3 51. Процедуры и функции для работы с типизированными файлами ния/записи может бь.ть только переменная того же топа что „ файла------------------------------------------------------——— Процедура Read для типизированных файлов имеет следующий формат Read (имя файловой переменной, список переменных) При считывании в каждую переменную из списка процедуры Read, указатец, текущей позиции в файле перемешается на следующий элемент Если указате1ь текущей позиции файла находится за последним элементом то есть в конце файл (Eof(0 = True), то выполнение процедуры Read приводит к ошибке времени выполнения Процедура Write для типизированных файлов имеет такой формат Write (имя файловой переменной, список переменных) Выполняя запись в файл следует помнить, что при записи каждой переменнЯ указатель текущей позиции в файле, также как и при чтении, перемешается Л следующий элемент Если указатель текущей позиции файла находится за последний элементом то есть в конце файла (Eof(f) = True), то при выполнении процедуры Write файл расширяется Для работы с прямым доступом предназначены следующие процедуры и функции FilePos FileSize Seek Truncate возвращает номер текущей позиции указателя в факте (позиции нумеруются от т гя ') те от^еКУШИЙ ₽a3Vep фаи1а (число элементов фанта при сче ным номеЩаСТ/!?:а3аТеЛЬ текуше1”' позиции в файле на элемент с задай ным номером (при счете от ну 1Я ') женные'по^М^^ейЛпоз° ТеКуЩРЙ позии>|» Все элементы располо Фаиле -нови^Хон —ПМИШ“ файла рассмотрим программу^сотетмрячым достУПом к элементам типизироваяи°д' ! пузырька , (см гтаву У “жировки ф;Л,а рабагаюшую по методу обмен-
t^upoeJ>HUCl в Среде Turbo Pascal 7 о 191 end ClrScr Writein ('Исходный файл for 1 = 1 to FileSxze (f) do begin Read ( f, X ) Write (X 8 } end Writein, Close (f), I-------------------------------------------------} Reset ( f ), for i = FileSxze(f)-1 dovnto 1 do ( 'Всплывание" очередного максимального элемента } ( на i-ю позицию ) for з ~ 0 to i-l do begin Seek ( f, 3 }, Read ( f, X, Y }, if X > Y then begin Seek ( f, з ) Write ( f, Y, X ) end end Close (f} Reset ( f ) Wnteln ('Отсортированный файл ') for i = 1 to FileSxze (f) do begin Read ( f, X ) , Write (X 8 ) end । Close (f) [__end _____________ _________ , , г 1|Л Jci собой 'шаблон P Упомним, что тип типизироваиног к его ‘ГНо ' который мы накладываем на (ЬЗуя I чм т п. ’ д „ ' жно 1 J прочИ! 'В файл Char «тиьиыи.Р«п
192 И„..ИЧ«КИ1< файл открывается как файл типа Byt символов. 3 затем этот At J^J{I Ь.ппь( ASCII, записанных в него символов program CharToByte r uses Crt; var FC : file of char; FB : file of Byte; Ch : Char; В : Byte; begin Clrsar; Assign ( FC. 'Test.Dat' >: Rewrite ( FC ) ; for Ch := '0' to ’ 9’ d° Write ( Fc' Ch ); for Ch := ’A' to 'J' do Write ( FC, Ch ); Close ( FC ) ; Assign ( FB/ 'Test.Dat' ) ; Reset ( FB ) ; while not Eof (FB) do begin Read ( FB, В ) ; Write ( В : 8 ) ; end; Close ( FB ) end. Результат: 48 49 50 51 52 53 54 55 56 57 65 66 67 68 69 70 71 72 73 74 13.6. ТЕКСТОВЫЕ ФАЙЛЫ 13.6.1. Структура текстового файла Особый вид файлов Представляют собой текстовые файлы, которые в Turt» rascal являются разновидностью файлов типа file of Char Д.ЛЯ описания текстовых файлов используется прелоппелепенныи тип Text var TextFxle : Text; В текстовых файлах помимо признак конца строки Eoln Признак FoT™ K°"Ua фа<и|а Eof НСПп;|ьз>'еТС’' из двух символов кода ASCII - символа с ко₽п'ЯС1?зВЛЯеТ собой последователь с кодом 10 (“перевод строки”) 3 (‘возв₽ат каретки ) и симе Текстовый файл можно образно предстаимтк v-e, й коНИ* каждой строки /тпит £о}п Рсдставить как страницу книги, в
/93 Напомним, что стандартные файлы ввода-вывода Input (ввод с клавиатуры) и Output (вывод на дисплей) являются текстовыми Использование процедур Read, Readin, Write, Wnteln при стандартном вводе-выводе было описано в главе 10 и для текстовых файлов будет практически таким же Отличие состоит в том, что первым параметром этих процедур должна быть указана файловая переменная Read (f, А, В); Write (g, ’А=’ , А, ’В=' , В) , Readin (f, С, D); Writein (g, 'О’, С, ’D=’, D) ; 73.6.2, Отличия текстового файла от file of char ' Автоматическое преобразование числовых данных в цепочку символов при записи значений в файл, и обратное преобразование символов, являющихся числами, в 'истовое значение при выполнении операции чтения в переменные соот ьетствуюших числовых типов - Текстовые файлы не имеют прямого доступа ’ Писывать в текстовый файл и читать из текстового файла разрешается переменные тотько некоторых стандартных типов (см главу 10) ! Наличие признаков конца строки „„решено использование процедур -Ья чтения из текстовых фаГьлов и записи в них разР6 попускаются Readln и Wnteln, которые для остальных типов файлов н Д 73.6.3. Процедуры и функции для работы с текстовыми файлами «л.ним допускается использование Для текстовых файлов дополнительно к -^ющих процедур и функций
I lush Readln ScekEof SeekEoln SetTextBuf Wnteln ОЖРЫП.К, ишигчюшинфанпи" -сбрасывает для текстового файла буфер вывода - паботаст так же как и Read, но дополнительно выполняет пропуск всех оставшихся элементов текущей строки н переводит указатель текущей позиции файла в начало следующей строки текстовою файла - возвращает для текстового файла состояние Eof (конец файла) - возвращает для текстового файла состояние Eoln (конец строки) - назначает для текстового файла буфер ввода-вывода — работает так же, как и Wnte, но после записи указанных в процедуре значений, дополнительно записывает в текстовый файл признак конца строки Eoln 13.7. НЕТИПИЗИРОВАННЫЕ ФАЙЛЫ При объявлении нетипизированного файла указывается только ключевое слово file, например Нетипизированные файловые переменные предназначены для низко^ИИИМ работы с файлами С их помощью можно обратиться к файлу любого типа и логической стру^И аналогично тому как выполнялось обращение к символьному файлу посредстЧ файловой переменной типа Byte Отличие состоит в том, что нетипизированнь файл не имеет жестко установленной единицы чтения/записи, как тилизированн! файлы В нетипизированных файлах за одно обращение считывается/записывает число байт, приблизительно равное величине буфера ввода/вывода. что способств> увеличению скорости работы с файлами В качестве буфера ввода/вывода нетипизир ванных файлов может выступать любая переменная 1 3.7.1. Процедуры и функции для работы с нетипизированными файлами Для работы с нетипизированными файлами можно применять почти все процедуры и функции, что и для типизированных Исключение составляет то что вместо процедур Read и Write используются процедуры BlockRead и BlockWnie, а процедуры Resei и Rewrite могут иметь второй параметр типа Word, который определяет размер записи, используемый при передаче данных Если этот параметр ол\шем, то размер записи принимается по умолчанию равным 128 байтам I 2 3 4 5 Контрольные вопросы Что называется файлом7 фаЧйла7а2ЛИЧИе МСЖДУ ^РУКтурой логического и структурой физического В чем состоит сходство и различие между массивом и файлом'’ Чтп признакам классифицируются файлы в Turbo PascalВ 9 Что необходимо выполнить для открытия файла9
„iwpi”*"1'* * T’u'feo Pascal 7 о ----------------------------------------------------------------------»» 9 7 » 9 Id. 11 12 13. 14. 15. 16. 17. 18 19 20. Мкис процедуры предназначены для открытия файлов и как они работают’ рУ! MVI0 предназначена процедура Close7 какие процедуры предназначены для работы с каталогами9 Какие действия выполняют процедуры Rename к Erase9 /l(j(x типов допускаются описания типизированных файлов9 Как нумеруются элементы типизированных файлов9 plo каким правилам выполняется чтение из типизированных файлов9 Какой формат имеет процедура Write для типизированных файлов9 Кгкис процедура и функции предназначены для прямого доступа к эле- мента» типизированным файлам9 В чсм состоят особенности текстовых файлов9 3 чем отличие пользовательских текстовых файлов от файлов Input и Output9 В чем отличие текстового файла от fxie of char9 Как объявляется нетнпизированкый файл’ g <се\1 отличие нетилиэированных файлов от типизированных9 Кжие процедуры и функции используются для работы с нетилизиро- ванными файлами0 Контрольные задания 1. Создать типизированный файл f. элементы которого вычисляются по формуле /=^ + 4i (/« 1,2, ,л), где л — целое Положительное число Определить число элементов файла, делящихся на 4 2. Создать типизированный файл f, элементы которого вычисляются по на зе Л ~ З/2 - 2i + 6 (/ = 1,2, , л), где л - целое положительное число Получить два новых файла g и Л, в один из которых записать четные эле- ты файпа/ а в другой - нечетные 3, Задан текстовый файл / и строковая переменная з Переписать в новый 5 g все строки файла / содержащие значение переменной з в качестве подстроки 4, Даны два текстовых файла/"и g Определить совладают ли эти файлы il1 нет - определить номер строки и номер позиции, с которой начинается различие один из файлов повторяет начальную часть другого - выдать соответствующее йшение j,!?a ' о?лать типизированный файл действительных чисел Если элементы "яакеП°РЯД0ЧСНЬТ По НсУбыванию, то перезаписать его элементы в обратном • используя прямой доступ к элементам файла Издать неупорядоченный типизированный файл действительных чисел 3>я прямой доступ упорядочить элементы файла по неубыванию методом а> вставки, 6} выбора, в? обменов
ГЛАВА 14 РАБОТА С ДИНАМИЧЕСКИМИ СТРУКТУРАМИ ДАННЫХ Классификация данных динамической струны была рассмотрена в глаа s 14.1. РАСПРЕДЕЛЕНИЕ ПАМЯТИ При объявлении данных динамической структуры в разделе описании указывается не сама переменная какого-либо типа, а указатель (ссылка) на нее В результате указатель будет обычной переменной, а переменная на которую он указывает - динамической. Р :AChar; РА: Char; [адрес -|-->| 'V | var Pi^Char: begin Р-'*•:= 'ж'; end. Wte Использование идентификатора указателя в программе означает обращсИ к адресу ячейки памяти, на которую он указывает Чтобы обратиться к содержммД ячейки, на которую указывает указатель, требуется после его идентификатора постяЯ символ л. Эта операция называется операцией разыменования Выделение и освобождение памяти под динамические переменные выполняла! стандартными процедурами New, Dispose, GetMem, FreeMem, Mark, Release во время работы программы Указательная переменная Р может быть в трех состояниях 1 Содержать адрес какой-либо переменной, память под которую уже выделена Р Р‘ |адрес»[----J I 2 -черл-ль специальный пустой адрес nil Р I nil •! 3 Находиться н н< м состоянии Р ДО первого присваивания ему или L_ • j--------- ? В неопределенном состоянии .им "" и укамт'Ль бывает в начале работы прогр3*®^ также после освобождения облДти °НкретноГо адреса, или пустого адреса »&• ласти памяти на которую он тка.ывает
197 ^^юрс>?^нис 0 -pgd- Turbo Pascal 7 о ,,^ „.-«I, eocs. nii „ ,1етре<1ы„11ыи mc i P1 P2 P1 I nil •]-1 I-1* nil I I Г-1 [—1 ?--m 14.2. ПРОСТЕЙШИЕ ДЕЙСТВИЯ С УКАЗАТЕЛЯМИ Действие Результат — 1 Объявление type pint = л integer; var a,b: Pint; а | ? k ? Ь | ? k ? 2. Выделение памяти New(a); New(b); а | адрес! J а- b |адрес2»| | ь- 3. Занесение информации a*:=1; b~:=2; а | адрес!»] >| у | а- Ь |адрес2г] 2 | Ь' < Копирование информации а* := b*; а |адрес!»] >| СГ2 | а* Ь |адрес2»| >[ 2 ' | Ь" аА - Ь~ а<> b 5. а) Копирование адреса а b; а |адрес2»|—| I . 2 । b |адрес2»| »| 2 | з” _ ЬА а - b 5.b) Dispose (а); а .'= b; а |адрес2»| j Ь |адрес2»| —*[ 2 | ь- Б. b ;= nil; а |адрес2»| -*| 2 | а" ь | mi —т =• ь~ n пймята соответственно тому типу, который Процедура New(A) выделяет область ""'"™й памя1Н в указатель «сан для указателя А и записывает адрес памяти, иа которую указывает Процедура Dispose(A) освобождает об „о,„, , 1Я распределения Патель А. после чего эта область памяти становится дос л°з другие динамические переменные
Робе 198 "" 14.3. НЕСВЯЗАННЫЕ ДИНА Несвязанные динамические данные КД статические (см главу 8). и работег с н™” свойства несвязанных динамических а могут “появляться" и “исчезать" во время работ таких данных заключаются в двух аспектах. . в разделе кате объявляется не переменная тре . перед использованием необходимо вызва зования — процедуру Dispose. В качестве примера приведем таблицу статическими и несвязанными динамическим* ma c птр^тур^ ДИ МИЧЕСКИЕ ДАННЫЕ 1 ассмфицируются точно также, ед 1 олняется аналогично Динамичен * | выражаются только в том, чт0 , ! ы программы Отличня использовав 1 эуемого типа, а указатель на этот тип ть процедуру New, а после исполь- сравнения работы с аналогичными данными I Структура данных Обычные переменные Динамически© " переменные 1. Простая переменная type Tint = 1-.100; var X : Char; Y : Tint; begin X := '* '; Y := 3; end. type Tint = 1. . 100; var PX : AChar; PY ; ATInt; begin New (PX); New (PY) ; PXA .= PYA := 3; Dispose (PX); Dispose (PY); end. I 2. Массив type Vect = array[1..3] of Byte; var X : Vect; 1 : Byte; begin for 1: = 1 to 3 do Read ( X[i] ) ; end. type Vect = array[1.. 3j of Byte; var PX : AVect; i t Byte; begin New (PX); for n=l to 3 do Read ( PXA[i] ); Dispose (PX); end. 3 Запись type Pec = record A : Char; S : Byte end; var X ; Rec; begin X.A := 1••, X.B ~, type Rec = record A : Char; । В : Byte । end; । var PX ; t о ; . r, endysk;se ; j
199 ' Turt>o 7 0 14д связанные динамические данные 14 4.1 Основные определения г иные списки это данные динамическом структуры которые представ (М совокспность линейно связанных однородных элементов и хтя кото нютны бедующие действия pb*\Pvpt кчеНпе элемента в начало (голову) списка * ^Гниение элемента в конец (хвост) списка • эпемента междх дв\мя любыми другими элементами списка • виГ пе пюбого как крайнего так и среднего элемента списка • списки — это такие же данные как и линейные списки но имеющие кольцевые иннптънхю СВЯЗЬ между последним и первым элементами списка Очередь — частный спхчаи линейного односвязного списка для которого (чцкны только два действия добавление элемента в коней, (хвост) очереди и пенне элемента из начат (головы) очереди Стек — частный случаи линейного односвязного списка для которого „.решено добавлять или удалять элементы только с одного конца списка который называется вершиной (головой) стека Деревья — это динамические данные иерархической структуры произвольной кэдфнгтрлиии Элементы дерев! называются вершинами (узлами) Пирамидон (упорядоченным деревом) называется дерево в котором значения в связанных 14 4 2 Организация взаимосвязей динамических данных ,1рмягриь » ЭТО ДСХ-ГН з ,пи » «х»"
Работа с динамическими структурами дангл... 200 программы и возможности установить связь между любыми двумя элементу t "’"Тя’Х’Хи связей между элементами динамической структуры Дан„ь„ разнородные элементы В простейшем случае элемент динамической структуры данных долм? постоять из двух полей информационного и указательного, Схематично такую структуру данных можно показать следующим образом Соответствующие ей объявления будут иметь такой вид Гуре TPtr = ATElem, TElem = record Inf Real Link TPtr end Правило последовательности описаний в Turbo Pascal требует, чтобы кала идентификатор был описан прежде чем он будет использоваться для дру1 объявлений Однако в приведенном примере как бы ни располагались описа! типов указателя TPtr и элемента TElem это правило выполнено не будет Поэта din описания типов лементов динамических структур данных еде юно исключение Тип указателя на элемент динамической структуры данных может и [должен быть описан перед описанием типа этого элемента 14.4.3. Работа с очередью создания очереди и работы с ней необходимо иметь как минимум Л»* начало очереди (возьмем идентификатор BegQ), конец очереди (возьмем идентификатор EndQ) Для указателя • на • на Т0Г° осво^ОЖЛСНия памяти удаляемых элементов требуется дополни <«°^ем идентификатор Р) Дополнительный - — устся в других ситуациях для удобства работы с «черед
,1110с состояние Создание очереди j ВыЖ1ен11С памяти под первый элемент очереди New (Р), несение информации в первый элемент очереди BegQ EndQ Р* Inf = 3, Р* Link .= nil; * гановка указателей BegQ и EndQ на созданный первый элемент EndQ ВедО BegQ := Р, EndO •= Р; Inf Link 3 Добавление элемента очереди -'одное состояние
Работе с динамическими структурами Дц^. 202 ...мни и внесение н него информации 2 ВЫЛС1СННС 11.1МЯ1И под повыв Н1СМЧП И лчке 3 Установка связи между последним элементом очереди и новым, а также перем шеиис указателя конца очереди EndQ на новый элемент EndQMink := Р; EndQ := Р; Удаление элемента очереди I Исходное состояние 2 Ihnie-iuuu информ.пши из удаляемого элемента в переменную Vai и хстановка на него вспомогательного указателя Р Vai : = BegQMnl; Р:= BegQ; 3 Пере очсреяи Вс«° ^«уюший элемент, иснользу» Р’< чраиигия в первом элементе После этого освобожлМ*** ’сди, используя дополнительный указатель R
срвде Turtx> Pascal 7 о 203 BegQ = р' Link; Dispose ( P ) , ачестве примера приведем программу создания и удаления очереди из В *ментов В ней для работы с очередью используются две процедуры десяй* 1 * * * э > Vpa Add El, которая в зависимости от состояния очереди создает У пи добавляет очередной элемент в конец очереди, первыи и _оцедура GetDelEl, которая извлекает информацию из начального элемента Доследующим освобождением его памяти program Queue; uses Crt; type TPtr ~ ATElem; TElem = record Inf : Real, Link : TPtr end, ?ar BegQ, EndQ • TPtr; Value : Real ; 1 • Byte, procedure AddEl (Vai Real) , var P TPtr, regir New (P) ; PA Inf := Vai; ₽A Link := nxl; if EndQ = nxl { если создается первый элемент очереди } then BegQ := р { если создается очередной элемент очереди } else EndQA link = Р, 2ndQ = р ^'isdure GetDelEl ( var Vai Real), ? TPtr, -?1п = SegQA Inf, ~ BegQ, ’ PA Lxnk, lf BegQ = nxl ( если удаляете последний м-я" очереди ) _ then EndQ = nil. ;-sPose (p)
204 Ълдт ClrScr ( Начальны* установки указателей I BegQ • nil EndQ » nil { Создание очереди из 10-ти элементов } for 1 1 to 10 do AddEl |i} , ( Удаление очереди с распечаткой значений ее эле кЫЛе BegQ О nil do begin GetDelEl {Value}, Writeln { 'Value = ', Value 5 2 } end end Результат работы этой программы будет таким Value = 1 00 Value = 2 00 Value = 3 00 Value = 4 00 Value = 5 00 Value = 6 00 Value = 7 00 Value = 8 00 Value = 9 00 Value = 10 00 14.4.4. Работа co стеком П Дтя работы co стеком о оттнчие от очереди необходимо иметь один > указатезь hi вершину стека (возьмем идентификатор Тор) и один дополни। временный указать (возьмем идентификатор Г1} который используется дл* выделения и освобождения памяти элементов стека Создание стека I lk\oinoe состояние

206 Работа с динамическими структур^ 2 Выделение памяти под новый элемент стека Тор 3 Внесение значения в информационное поле нового элемента и установка связи .межа} ним и '‘старой” вершиной стека Тор Р Р“.1пГ= Vai; {Vai = 10) P“.Link •- Top;
। ° cPede Turb° Pascel 7 О ”еРШИНЫ CTCKa Т°Р на н°вый элемент р 207 Тор := р Удаление элемента стека viHoe состояние Vai Тор
а*лотя с винамичпскими к„„>,чиионного поля вершины стека Тор „ _ 2 Извлечение информации из инф°Р огатсльното указателя I' ’*4. шло Vai и установка на вершину стека 3 Перемещение указателя вершины стека Тор на следующий элемент и освоби В качестве примера Привел™ п ТИ элементов В ней для раб^ы еГстХ^'7 СОадани>* - уд-хк,,.,,, — И’'** 1) процедура Push, котовая » ” ИСпользУ>°тся Две процедуры первый или добавляет очередной элемент вСИМ°СТИ от состоянии стека со3" снт в вершину стека
209 мцее среде ПгЬеРеесвПО____________________________ -- оиедУРа P°P’ котоРая извлекает информацию из вершины стека с 2) пр м оСВОбождением ее памяти. I м Ч7О в отличие от процедур AddEl и GetDelEl для очереди, в про- ' Заме 1 и pop не потребовалось особо выделять случаи создания первого и 1 цеДУР3* ^оследнего элементов стека, так как при исходном значении Тор = ml даЯсНИЯ П соответствуют такие же последовательности операторов, как и для 'цМ сЛучаЯ“ „ддления очередного элемента стека ----------------------- type TPtr = TElem = inf Link • TPtr 1 end; I var Top Value ATElem; record : Real; : TPtr; : Real; : Byte; procedure Push (Vai • Real) ; var P : TPtr; begin New (P) ; PA.Inf : = Vai; PA .Link := Top; Top .* P end; procedure Pop (var Vai : Real) ; var P : TPtr; begin Vai Top*.Inf; P •» Top; Top :• P* Link, Diepoee (P) •nd. Ь«у4л ClrScr; ( Намалыше уетамоаки умматеаей ) - nil, Соадамхм Top Pu*h № /д*л«»о<е стажа с распе^атжо^ while Тор <> nil d^ be^ln Pop (Value) > Writein ( ‘Value - •nd •«4 •jtMteevo» )
работе с динлми^с^и Г -.той программы будет таким Результат работы этой пр Value = Value = Value = Value = Value = Value = Value = Value = Value = Value = 10 оо 9 00 8 00 7.00 6.00 5.00 4 00 3.00 2 00 1 00 14.4.5. Работа с линейным односвязным списком Как уже отмечалось в п 14 4 I. очередь и стек являются частными случаями общего понятия “линейный список” А В списке в отличие от очереди и стека, разрешено производить действий над любыми элементами, а не только крайними менять местами элементы! удалять любой элемент, вставлять элемент в любую точку списка] Линейный односвязный список может быть двух разновидностей 1) прямой линейный односвязный список, 2) обратный тинейный односвязный список в прямом списке связь устанавливается от i-ro к (>+1)-му элементе' Очередь является частным civ В обратном списке связь vcraHotV прямого линейного односвязного списМ Устанавливается от ,-то к (,-П-му элементу
-рвде Turbo Pascal 7 n . к пишется частным случаем обратного Н трудно заметить, что разделение на прямой'пТ °ЛНОС№ного списка 10ВНЫМ и зависит оттого, какую сторону списка ° Р ™ЫЙ спис01< является u 1Итать началом, а какую — lllt работы с линейным одт„Ш1 списком требуются I) указатель на начало списка (возьмем идентификатор BegLX ’) указатель на конец списка (возьмем идентификатор EndL), О указатель на Л-й элемент списка, где будут ппП1™„. , ;0 (ИЛИ перед которым) будет вставлен элемент или же котовый"0™™ ,возьмем идентификатор Рк); ' " которь,и следует уда- 4) временный указатель для выделения памяти под добавляемые элементы , освобождения памяти удаляемых элементов (возьмем идентификатор Р) рассмотрим основные операции над линеиными односвязными списками. Создание линейных односвязных списков Создание (т.е. внесение первого элемента) линейного односвязного списка няется точно так же, как и создание очереди Причем это касается как прямого, обратного линейного односвязного списка, невзирая на то, что обратный >ныи односвязный список является обобщенным случаем стека, а не очереди о мается именно из-за того, что обратный линейный односвязный список — 'мшенный вид стека, у которого есть начхпо и конец, как у очереди, а не о вершина, как у стека VI Поскольку как уже отмечалось выше, разделение линейных односвязных J списков на прямые и обратные является достаточно условным все । действия будем рассматривать на примере прямого линейного — | связного списка___________________________________________________ •"тное состояние' BegL fa I ? BegL := nil; EndL - nil:
212 Робота с динамическими структурами данны> 2 Выделение памяти пот первый элемент списка BegL EndL New (Р); 3 Занесение информации в первый элемент списка EndL BegL 4 Установка указателей BegL и EndL иа созданный первый элемент BegL := Р> EndL:-Р; Добавление элемента в конец списка Добавление элемента в конец прямого списка выполняется аналогично избавлению элемента в конец очереди, а добавление элемента в коней обратного иска выполняется аналогично добавлению элемента в вершину стека Схема добавления для прямого линейного одиосвяэного списка будет зующей
qp»<4 Р.,с 7 0 - Выдсчение памяти пол новый элемент и занесение в него информации New(Р); P\lnf := 5; P'.Link := nil; 3 Установка связи между' последним элементом списка и новым, а также перемещение •дззтеля конца списка EndL на новый элемент: EndL Р EndLMJnk := Р; EndL:= Р; Добавление элемента в начало списка Добавление элемента в начало прямого списка выполняется аналогично e-nf-j з’ечеита в вершину стека, а добавление элемента в начато обратного алогично добавлению элемента в коней очереди ’я элемента для прямого линейного односвяз
Рлбота с диномичаскими структур - - _ 2 Выделение памяти под новый элемент и занесение в него информации New(Р); PMnf := 5; 3. Установка связи между новым элементом списка и первым, а также перемещение указателя начала списка BegL на новый элемент Вставка элемента в середину списка после заданного к~го элемента Будем считать, что адрес Ar-го элемента уже известен и храниня и \клъгте ie Pi
.. .^•KirtCfloitTMboPeKtno к СЦ-'ТОЯНИС - Hulk ichiic памяти под новый элемент и занесение в него информации New(P); PLInf :=7; 3. Установка связи между новым и (1Ь-1)-м элементом (Р Link — Pk' Link) а также перестановка связи Л-го элемента на новый элемент <Pk’ Link = Р p-.Link := Pk*.Linlc Pk'.Link := Р:
Работа с динамическими Вставка элемента в середину списка перед 1 заданным k-м элементом I Естественно, если мы имеем адрес (A-l)-ro элемента, то требуемое дейи, ] можно выполнить как показано выше Но, если имеется адрес только к-т элеМс11"' то задача усложняется Такая ситуация может быть, например в случае, когда указа,., устанавливается на к-й элемент, но действия над ним будут определяться дальнейщ? ходом алгоритма, то есть предварительно не известно, что нужно будет делать с элементом (вставлять после, вставлять до, удалять его или же вообще ничего не делал,) В этом случае вместо того, чтобы еще раз от начала списка искать (А-1)-й элемент значительно лучше выполнить вставку перед к-м элементом следующим образ0м Сначала описанным выше способом произвести вставку нового элемента после k го элемента, затем поменять местами значения информационных полей А-го н нового элементов и, наконец, переставить указатель Рк на новый вставленный элемент который уже содержит значение А-го элемента То есть к приведенным выше трем этапам вставки элемента добавляется еще один, четвертый 4.0бмен местами значений информационных полей А-го и нового элементов и перестановка указателя Рк на новый элемент PIC .Inf := P“.lnf; P“.lnf := Tmp; Pk:= P; Переменная Tmp должна иметь такой же тип, как и информационное поле элемента списка Inf Удаление элемента из начала списка Удаление элемента нз начала прямого списка выполняется аналогично уда лению элемента из очереди и из стека (обратим внимание, что удаление элемента из очереди и стека выполняется по сути одинаково) Удалению элемента из начала обратного списка (или из конца прямого спи- ска) нет аналога среди действий с очередью и стеком (это будет рассмотрено в сле- дующем подзаголовке) Схема удаления элемента из начала прямого списка будет следующей
}Ubtup(*MU9 в сред* Turbo Pnscnl 7 О 217 l^xo ihoc состояние 2 Извлечение информации из удаляемого элемента в переменную Vai на него вспомогательного указателя Р и установка 3 Перестановка указателя начала списка BegL на следующий элемент используя эшчсние поля L»nk, которое хранится в первом элементе После этого освобождается л 1мять начального элемента списка, используя дополнительный указатель Р BegL := P“.Linkz Dispose ( Р ) ; Удаление элемента из конца списка Удаление элемента из конца прямого списка не имеет аналогов среди действий с очередью и стеком, а удаление элемента и) конца обратного списка выполняется анало1ично удалению из очереди или из стека, как показано выше
Работа с биномическими сггсшпг 218 Схема удаления элемента из конца прямою списка будет следующей 1. Исходное состояние Обратим внимание, что если просто удалить последний элемент, на который указывает EndL то разрушится целостность списка, так как мы не сможем перс ставить EndL на предыдущий элемент, ввиду отсутствия его адреса в какой тибо переменной Поэтому сначала нужно найти адрес этого предпоследнего элемента списка Как это можно сделать будет описано в специальном подпункте ниже 2. Нахождение адреса предпоследнего элемента и занесение его в >казатель Р 3. Извлечение информации из постеднего этемента в переменную Vai и освобо ждение его памяти Vai := EndLMnf Dispose (EndL) ;
; ,мм»роааниу s upcue Tuibo Pascal 7 Q 219 4. yci,топка указателя конца списка EndL на предпоследним элемент (теперь ужс последний) и установка связи этого элемента в нН (то есть фиксация конца списка) EndL = Р; EndL".Link := nil; Удаление элемента, стоящего после заданного k-го элемента Такое действие можно выполнить без предварительного поиска, так как доступ ко всем адресам, необходимым для перестановки связей можно получить с помощью попя Link к-го и (к+1)-го элементов 1. Исходное состояние Удаляемый элемент
Работа с динамическими структурами^. 220 2 Установка дополнительного указателя Р иа удаляемый злсмент cn„CR„ извлечение из него информация Р := Pk*.l ink; Vai := P".lnf; 3. Установка связи между k-ы и (*+2)-м элементами и освобождение памяти удаляемого (АН-1 )-го элемента PlT.Link := P-.Link; Dispose ( Р ) ; Удаление fc-ro элемента списка Удаление fc-ro элемента, конечно, можно выполнить также, как и следую- щего за ним (&+1)-го (как описано выше), если мы будем иметь (или найдем) адрес (Л-!)-го элемента списка Однако так же. как и в случае вставки нового элемента перед Л-м. можно обойтись и без дополнительного поиска Для этого необходимо предварительно скопировать значение поля Inf «нужного* (к+1 )-го элемента в поле Inf •‘ненужного'' *-го и удалить (*-Н)-й элемент вместо *-го Соответствующая схема имеет следующий пит I. Исходное состояние
оаммирование в среде Turbo Pascal 7 О Ь установка .дополнительного указателя Р на (А-+1) и Информации из удаляемого /t-го элемента и копирование из (А+1) го элемента в А-й элемент элемент полезной 221 извлечение информации Vai := PkA.lnf; PkA.lnf := PA.lnf; 2 Установка связи между к-ч и (Л+2)-м элементами и освобождение памяти (A-l)-ro элемента который мы удаляем вместо к го Pk*.Unk:= P*.Linfc Dispose ( Р) ; Установка указателя на k-й элемент линейного односвязного списка Невозможно установить указатель одним оператором непосредственно на какой-либо средний А-й элемент списка, поскольку имеются адреса только первого и последнего элементов Поэтому чтобы выполнить требуемое действие, необходимо отсчитать к этементов от готовы списка, последовательно передвигая вспомогательный указатель от элемента к элементу
222 Работе с динамическими структурами данных Итак, в простейшем случае цикл установки гказатетя на заданный А-и -’ll- мент будет иметь такой вид Р = BegL, {Установка указателя Р на 1-й элемент J for l * 2 to k do {Последовательная установка указателя Р} Р = рА Link, {на 2-й, 3-й, ,к-й элементы} Однако этот цикл не учитывает случая, если в списке находится меньше элементов, чем заданное к То есть испотьзовать его можно тогда и тотько тогда, когда гарантированно известно, что в списке имеется не меньше к элементов Если же брать общий случай, то необходимо в рамках цикла дополнительно проверять не достигли ли мы кониа списка
\ , > iih’Hlul Vhrt,rt’p,'H li I < ИОДНИН ЭП0МРН1 ПрПМОЮ ОДНИ* i......ни t ||И( к 1 I I Нн»ЛПША| Ч I И •>> 11 in IН» 11 Hi Jill. Hid <i Hi I ill! i И ...(им mi umuiu , ю hii'Mi'HIii Н|Н|МН1Н Hilthii ни пнин i Hili kn мп! iqtv 41 цц w hi Hi II J'h'MiHii ii|himhih uni ни ни ним и > hih *h hu\h ........ <i ртшм M * Hilt kil. HiUhlKH М1НП1.1 \l HUhiniHU Hll Ill’ll' \ kil liHP'll. 1ЦЧ1М1Н1Н 'I и Illi III м (I HI HllHlIHll I Kill k‘l, 1ИЧ hiVlI.h'i I lul hi MPilH ‘'H‘Ml'll HIMil lhlll|iiU»l» нм II m ii'I'HlII I li ppiHMI ♦i IHH' llu I lllli KV HMIHUIIUIPIVH ll|K»iH kill. OhMlB |lih I MH|P**IIH Ul'lUH ill lll’lll' >01 НИИ |I«||I.I>H II \I 'HHHIII HKiillHtllllHI H'HI'MI Ihiill.lHimi HUHIU V» inililhl Mn*i i иыiь mid Mil > 11)1 IH41IM llhl 11 « |I ihll Hid И III 1 1 Hit ► i | I ll l 11 111 111 и II Mil 1111 II|>< Il llfit ЛГЦНИЙ ini Ml HI ( * I'" Illi P* link I * I hJ I mH 1
работа с динамическими структурами Даннк,- 224 Влрн.шт 2 Поскольку указатели EndL и РА Link указывают на один и тот же элемент (те содержат один и тот же адрес) то следовательно указатели EndLA Link и РА LinkA Link также содержат один и тот же адрес и указывают на nil |EndL|A Link = nil t |pA Link|A Link = nil P = BegL while PA LinkA Link <> nil do P - PA Link ( После окончания цикла P будет указывать ) ( на предпоследний элемент ) Хотя использование указателя Р Link Link немного более сложно для по нимания, однако и более универсально, так как работает даже в случае если бы у нас не было указателя коииа списка EndL Печать элементов односвязного списка от начала к концу Такой вариант вывода иа печать элементов списка выполняется аналогично описанной выше установке указателя иа предпоследний элемент с двумя отличиями I) передвижение рабочего указателя производится до последнего элемента.
в среде Turbo Pascal 225 , „повременно с передвижением указа™,, |„нф0Р«|иИОННОГ° П°ЛЯ kJTOOr° элемента списка оьга°™тс» на печать зна 1енис Р = BegL while Р <> П11 do begin Wnteln (Р- In£) р = Р* Link Печать элементов односвязного списка от конца к началу Очевидно что вывод на печать элементов списка от конца к началу нельзя о шить так же просто как в предыдущем случае поскольку связи направлены 1вЫ со в одну сторону и невозможно продвигаться по ним в сторону противо Т0" кн\ю В этом случае н^жно использовать либо еще один дополнительный k (но с обратными связями') для временного хранения элементов исходного )ска шбо использовать рекурсию Рассмотрим решение с помощью рекурсии Подобная задача уже рассматри валась в паве 12 когда выводились на печать в обратном порядке символы строки набнркмои на клавиатуре Поскольк$ мы используем рекурсию то действия должны быть оформлены в виде процедуры procedure PrintList (Р TPtr) { Параметру Р передается значение ) ( указателя начала списка BegL ) begin if р <> nil then begin PrintList (P* Link) Writeln (PA Inf) end end_________________________ 14 4 6 Работа с линейным двухсвязным списком Структура элемента линейного двухсвязного списка должна иметь на одно «’•Т0ШС1 указательное поле больше и будет иметь следующий вид T₽tr2L = ATElem2L - record Real TPtr2L Right TPtr2L Тил указателя на двухсвязных список ) Тип элемента двухсвязного списка ) Информационное поле элемента списка ) Указатель иа левого соседа ) Указателе на правого соседа } era
Работа с динамическими cmovm... 226 Для работы с двухсвязным списком нужны такие же указатели, кдк работы с односвязиым: иДля 1) указатель иа начало списка (возьмем идентификатор Beg2L) 2) указатель на конец списка (возьмем идентификатор End2L), 3) указатель на Ar-Й элемент списка, где будут производиться дейсп» которого (или же перед которым) будет вставлен элемент или же кото г*' Пос> удалить (возьмем идентификатор Рк); рый 4) временный указатель для выделения памяти под добавляемые и для освобождения памяти удаляемых элементов (возьмем идентификатор^^ Набор основных операций для двухсвязных списков тоже будет таким *е их реализация — аналогичной. Основные отличия состоят в том, что при добавлении новых элемент^ нужно устанавливать связи в обе стороны, а также несколько упрощаются такие действия как удаление Ar-го элемента и поиск предпоследнего элемента списка, по- скольку каждый элемент хранит два адреса, как левого, так и правого своих сосе- дей. С другой стороны, в связи с теми же двумя указателями в каждом элементе несколько усложняется связывание элементов при вставке и удалении средних и крайних элементов, что требует более аккуратной работы с указателями. Следует также отметить, что хотя оба конца списка теперь равнозначны, од- нако с одной стороны списка в nil устанавливается указатель Left, а с Другой сто- роны списка - указатель Right. Это также нужно учитывать при добавлении и уда- лении крайних элементов. Кроме того, при выводе на печать элементов двухсвят- ного списка рекурсия уже не требуется ни в первом, ни во втором случаях. Для большей конкретности рассмотрим два случая вставки и удаления сред- него элемента списка Структуру двухсвязного списка на схемах будем представлять следующим образом
i do Turbo Pascal 7 Q Вставка элемента в середину линейнг.™ „ списка пос™ аадапппгпТо 5\Км считать что адрес к го элемента Исходное состояние 227 уже известен и хранится в указателе Рк 2 Выделение памяти под новый элемент и занесение в него информации Beg2L Рк End2L < вяэыаание нового элемента с (Л+1) м элементом ft Последовательность связывания нового элемента с к м и (А+1) м злемен f X теми очень существенна Нельзя связывать новый элемент сначала сям а лотом с (А*1) м так как в этом случае будет потерян адрес (й+1) го эле мента и его придется отдельно искать начиная от конца списка________
Работа с динамическими структура*^ 228 FT Right := Pr.Right 4. Связывание нового элемента с А-м элементом BegZL Рк End2L P*.Lett := Рк; Рк*.Right := Р;
...ыиц^овэниг- d среде Turbo Pascal 7 о 229 удаление к-го элемента линейного двухсвязного списка Исходное состояние 2. на (А-1)-й Перестановка Left-указателя (к+Г)-го элемента указателя (Л-1 )-го элемента на (Л+1)-й элемент. 3. элемент и Right- fPk~.RighC.Left := Pk~.Left:J End2L PIC.LefC.Right := PIC.RightJ7 Pk~.RighC.Left := Pk*.Left; Pk~.Left~.Right := Pk*.Righf
Контрольные вопросы 1 г з 4 5 6 7 8 9 10 II 12 13 14 15 16 17 18 19 20 21 19 В чем особенность объявления данных динамической структуры9 Что выполняет операция разименования9 С помощью каких процедур происходит распределение памяти под динами ческие переменные9 Какие состояния может принимать указательная переменная9 В каких случаях указатель может находиться в неопределенном состоянии’ В чем различие между состоянием nil и неопределенным состоянием9 Какие действия выполняют процедуры New и Dispose9 В чем выражаются динамические свойства несвязанных динамических данных В чем сходство и различие между линейными и кольцевыми списками9 Что представляет собой очередь как структура данных9 Что представляет собой стек как структура данных9 от лт™у>ТаВЛЯеТ С°6°й пирамида как структура данных и в чем ее отлич» Какие бывают виды пирамид9 В ДЛЯ ^’Лаии" —х динамических структур данных’ структур данных9*" ииость описания типов для созл,ки« тнамичесЮ Сколько указателей требуется л>. __ Какие действия необходимо выполняя °'“Ю9 Как добавить или удалить элемент очееХ "" Сколько указатьipfi Trt, < Какие действия необходиГо^в^ Р36"™ “ СТеком'> Как добавить или „азить ,лемг1п~1Я Сколько указателей требуется стека' с линейным одиосвязным слиск0*1
umjix***u* о cpeiM Turbo Pascal 7 О 231 K1MIC действия необходимо выполнить для создания пшенного односвязного списка*’ прямого и обратного 21 МЬ добавить или удалить первый элемент линейного односвязного списка’ 22 Как добавить или удалить последний элемент линейного односвязного списка’ 23 Как добавить или удалить средний элемент линейного односвяэного списка ' 24. Как распечатать значения прямого линейного односвязного списка ог начала к концу н от конца к началу9 25. Какой должна быть структура элемента линейного двухсвязного списка9 26. Сколько указателей требуется для работы с линейным двухсвязным списком9 27 Как добавить средний элемент после заданного А-го элемента линейного двухсвязного списка9 28 Как удалить заданный А-го элемент линейного двухсвязного списка9 Контрольные задания 1. Задан файл / целых чисел Переписать элементы этого файла в обратном порядке, используя динамическую структуру данных (какую9) в качестве промежуточного звена 2. Создать очередь из л элементов и стек из т элементов Добавить элементы очереди в вершину стека 3. Создать прямой односвязный список из п элементов и стек из т элементов Добавить элементы стека после первого нулевого элемента списка 4. Создать очередь из п элементов Переставить значения элементов очереди в обратном порядке, не используя промежуточных массивов 5. Создать двухсвязный список из л элементов Переставить значения элементов списка в обратном порядке, не используя промежуточных массивов Сравните сложность решения этой задачи с решением задачи 4
ЧАСТЬ 3 МЕТОДОЛОГИИ РАЗРАБОТКИ БОЛЬШИХ ПРОГРАММНЫХ КОМПЛЕКСОВ ГЛАВА 15 СТРУКТУРНАЯ МЕТОДОЛОГИЯ РАЗРАБОТКИ ПРОГРАММ 233 ГЛАВА 16 ОБЪЕКТНО ОРИЕНТИРОВАННАЯ МЕТОДОЛОГИЯ РАЗРАБОТКИ ПРОГРАММ 239
ГЛАВА 15 ^Структурная методология I разработки программ Ls*— """ 1 15.1. ИСТОРИЧЕСКИЕ ЗАМЕТКИ ' ” '' 4 10Д0Ц -^е было очевидно, что программные проекты стали ч к южвыхш для успешного проектирования кодирования н отладки в мые сроки Кроме тою, программисты, решающие сложные задачи, псь с проблемой разрастания количества н размера программ до такой что ьоьнейший процесс разработки становился практически неуправляемым, и р.цработчнков нс мог с уверенностью сказать, что созванный программный <ci м выполняет то, что требуется, и что он не выполняет ничего такого, ,(и цыбуегся Таким образом, стала проблема коренного изменения подходов к Щ.ШИЮ больших программных комп кксов Исходя in зтнч проблем, лучшими лршраммнетлмп ”0-\ голов (Дейкстра, 5.фт, Дал. Хоар. Иордан. Константин. Майерс и другие) были разработаны строгие мина веления проектов, которые получили название структурном .методология. Важным этапом в становлении новых методологий стали международные еч^.тешши по программированию в !%S и го tax На вп-фой in них ^тсгер 1 (Оцкмга) впервые iiciuxibu ,ис <111 Пр11НШ1П11Х'1ЬН0 новыг MH, И о 1КП сор кого ’ВС \ ю .> н леи
Структурная методология рз^работки^^^-.^ 234 15.2. ЦЕЛИ СТРУКТУРНОГО ПРОГРАММИРОВАНИЯ Обеспечить дисциплину программирования Обеспечение дисшшчины программирования в процессе создания программных комплексов является основной целью структурного программирования и главнь1м фактором достижения остальных его целей Дейкстра дал следующее определение “Структурное программирование - это дисциплина которую программист! навязывает сам себе____.____________________________________| Улучшать читабельность программы Читабельность улучшается, если придерживаться следующих правил • избегать использования языковых конструкций с неочевидной семантикой • стремиться к локализации действия управляющих конструкций н использования структур данных, • разрабатывать программу так чтобы ее можно было читать от начала до конца без управляющих переходов на другую страницу Повышать эффективность программы Повышения эффективности можно достигнуть, если выполнять структури рование программы разбивая ее на модули так, чтобы можно было легко находить и корректировать ошибки, а также чтобы текст любого модучя с целью увеличения эффективности можно было переделать независимо от других Повышать надежность программы _ Высокой надежности функционирования программы можно достичь, если она охает легко поддаваться сквозному тестированию и не создаст проблем для организации процесса отладки Это обеспечивается хорошим структурированием программ*11 ПРИ раз®ивке ее на ч°зулн и выполнением правил написания читабельных Уменьшать время и стоимость программной разработки прои?МСНЬШеНИС СТОИМОС™ и вРсмени разработки программных комплексов RM ХОЯУ1Т * том случае, если кажтый программист команды разработчиков стано способным ПИсатъ количество программного кода ГгхА раиьшс ‘° есть, koi сдельность труда программиста соблюдение правил струк
iHuo a cpeOe Turbo Pascal 7 0 235 15 3. ОСНОВНЫЕ ПРИНЦИПЫ СТРУКТУРНОЙ МЕТОДОЛОГИИ Принцип абстракции V I ipiKUHH позволяв! PJ3P16O14HK\ пообр 13ИТЬ требуемое решение проблемы 1() (.(поминутною учета множеств! деталей Используя принцип абстракции рцрабогчик может рассматривав прО1рамму по уровням Верхним уровень показывает IIШ большую абстракцию упрощает взгляд на проект в то время как нижний уровень показывает мелкие детали реализации На принципе абстракции основываются многие структурные методы например юс ходящая и нисходящая стртплип программирования Принцип формальности Вторым фундаментальным принципом структурного подхода является принцип формиьности Слово формальность предполагает строгий методический подход Принцип формальности является базой для превращения программирования из импровизации в инженерную дисциплину кроме того этот принцип дает основания для доказательства правильности программ так как позволяет изучать программы (алгоритхты) как математические объекты Введению формальности в некоторый процесс технический или не технический часто сопротивляются на основании того что она подавляет творчество Однако стрхктхрный подход использует формальность для придания проиессх творчества определенной дисциплины и строгости что позволяет ускорять принятие решений и избегать множества ошибок Формальность является положительным и м явным способом соединения искусства и инженерных аспектов программирования Принцип “разделяй и властвуй” Принцип 'разделяй и властвх'й известен со времен Юлия Цезаря и является методом решения трудных проблем путем разделения проблемы на множество ме 1ких независимых которые легче понимать и решать В ракурсе применения к разработке програмх|ного обеспечения этот принцип сличает разделение программы нт отдельные фрагменты (модули) которые просты по хпршлению и допускают независимую отладку и тестирование Он позволяет разработчику программ спокойно работать над отдельной частью большом системы нс заботясь об огромнох! количестве деталей охвтгываюших всю систему Принцип иерархического упорядочения Принцип нер IpXII letKOro упорядочения ILcHO еВЯЗЛН е принципом разделяй mb i\ х рт рноисния иа части не менее важна чем сам факт такого pai И । иерархического упорядочения с успехом используется во Всех ах ♦ пельности человека и помогает решать сложные проблемы управления в системах включающих множество частей В применении к программированию этот принцип выдвигает требование цс; стрхктхрирования взаимосвязей между модулями программного К облегчает достижение рассмотренных выше целей структурного лр ,ия
Структурная^ методология Р» Юббот^г,^^ 236 15.4. МОДУЛЬНОЕ ПРОГРАММИРОВАНИЕ „„„vibHoro программирования является при,„„ Основныме программное - это организация Про1рамм" "разделяй и властвуй независимых блоков, называемых модулями, струи? как совокупности не определенным правилам и поведение которых пад использование слова “модуль , когда имеете. Заметим, чт > конструкция языков программирования (unit в Turb<) PasSy иногда имеется в виду единица дробления большой программы на отладь,,,Jt Pascal) и.ко гда им еализованы и в виде процедур, и в виде функций) И Использование модульного программирования позволяет упростить тестирование программы и обнаружение ошибок. Аппаратно-зависимые подзадачи мо^ быть строго отделены от Других подзадач, что улучшает мобильность создаваем», программ процесс повышения эффективности программ, так как критичные по времени модули могут многократно переделываться независимо от других. Кроме того, модульные программы значительно легче понимать, а модули могут исполь- зеваться как строительные блоки в других программах. Термин "модуль” в программировании начал использоваться в связи с внедрением модульных принципов при создании программ. В 70-х годах под модулем понимали какую-либо процедуру или функцию, написанную в соответствии с определенными правилами Например" “Модуль должен быть простым, замкнутым (независимым), обозримым (от 50 до 100 строк), реализующим только одну функцию задачи, имеющим только одну входную и только одну выходную точку" Однако общепризнанных требований не было и модулем очень часто называли любую процедуру размером до 50 строк Первым основные свойства программного модуля более-менее четко сформулировал Парнас (Parnas) “Для написания одного модуля должно быть достаточно минимальных знаний о тексте другого". Таким образом, в соответствии с этим определением, модулем могла быть любая отдельная процедура (функция) как самого нижнего уровня иерархии (уровня реализации), так и самого верхнего уровня, на котором происходят только вызовы других процедур-модулей Таким образом, Парнас первым выдвинул концепцию скрытия информации (information hiding) в программировании Однако существующие в языках 70-х годов только такие синтаксические конструкции, как процедура и функция, не могли обеспечить надежного скрытия информации, поскольку подвержены влиянию глобальных переменных поведение которых в сложных программах зачастую бывает трудно предсказуемым Решить эту проблему можно было только разработав новую синтаксическую конструкцию. которая не подвержена влиянию глобальных переменных Такая конструкция была создана и названа модулем Изначально предполагалось, по при реализации сложных программных комплексов модуль должен использоваться наравне с процедурами н функциями как конструкция, объединяющая н надежно скрывающая детали реализации определенной подзадачи. Таким образом, количество модулей в комплексе должно определяться декомпозицией поставленной задачи на независимые подзадачи В предельном случае модуль может использоваться даже для заключения в него всего лишь ошюи процедуры, если необходимо, чтобы выполняемое ею локальное действие бы гарантировано независимым от влияния других частей программы при любых изменениях и коррекциях Такое использование модуля характерно для класса задач реального времени, в которых критерий надежности и предсказуемости поведения Программы является ключевым
~^мированио в среде Turbo Pascal 7 р 237 [iiKpuNC специализированная синтаксичеек к> l-™, ,ЛЖСН1 н Виртом в 1975 г и включен i п и™ конструкция модуля была /был** сделана опытная реализация языка Modula0?!"1 ЯЗЫК M°dula В этом Ас язык был окончательно реХ^ан в переработки iModub 2 Впоследствии аналогичные конструкции с некоторыми отлХями “были AdaOWO) S7X~₽O°* PaSCa' P‘US (УЭЛШ *' Баста₽д 1979 Форма модульной программы Придание иерархической структуре модульной программы хорошей формы ПО30О1ЯСТ улучшить процесс ее разработки Число модулей которые вызываются каким либо модулем и число модулей которые ею вызывают, оказывают влияние на сложность программы Йодан (Yourdon) назвал число модулей вызываемых из данного модуля, размахом или ширинок управления модулями Наряду с большим размером модуля очень маленькая или очень большая ширина управления является признаком плохой схемы разбивки на мовли В обшем случае ширина управления модуля не должна превышать 10 ги Это инею связано с ‘магическим числом 7 которое базируется на положениях психологии и в особенности на теории кусков ( chunking ) информации Крагковрсменн ш память человека имеет ограниченные способности сохранения ‘кусков информации Психо югичсские эксперименты показали, что способность нашем кратковременной памяти находится в пределах 5—9 ‘кусков (в среднем — 7) Он । может одновременно оперировать около 7 кусками’ информации Когда человек превышает этот предел он более склонен к ошибкам Реорганизация информации с раабнвкои на подходящие <асти является важным действием для эффективного использования кратковременной памяти человека и аля улучшения понимаемости материала Люди во многих жизненных ситуация делают такую реорганизацию бессознательно Однако программист может сам сес помочь сознательно не допуская ширины управления модулями которая превышай! число 7 15 5 СТАНДАРТЫ СТРУКТУРНОГО ПРОГРАММИРОВАНИЯ 1 Программа должна разделяться на независимые чаши называемые моду 1ч i ’ 2 Модуль — это независимый блок код которого физически и логически । от кода других модулей выполняет только одну логическую функцию 1 модуля нс должен превышать 5 Миду ib имеет одну входную и • 6 Взаимосвязи между модулями \ )ПП операторов ю точку и по иерархической структуре । inn m *i цмяюшего его и из него я из него ненужных «УЮ или вы >ры вссч перем пнпч • группы идентификаторов должны начинали.» ч одинаково
238 Структурная методология разработки 2ggapgM). 11 . Использовать только стандартные управляющие конструкции (выбор, ПИКЛ, выход, блок). 12 В одной строке записывать не более одного оператора. Если для записи ' оператора требуется больше, чем одна строка, то все последующ^ строки записываются с отступами. 13 Не допускать вложенности операторов if более 3-х уровнен. 14 Избегать использования языковых конструкций с неочевидной семантикой и программистских “трюков". Например, в языке С вполне допустима следующая программа, которая работает противоположно тому, что должно было бы быть на первый взгляд. tfinclude <stdio.h> main() { if (3<2<1) printf(”BoT это ерунда’’’’*); else printff'A Паскаль такого не позволяет’"); ) Контрольные вопросы 1 Какие проблемы возникают при создании больших программных комплексов? 2 Что такое структурная методология? 3 Каковы цели структурного программирования? 4 . Каковы основные принципы структурной методологии? 5 . В чем состоит суть принципа абстракции? 6 В чем заключается принцип формальности9 7 . В чем заключается принцип “разделяй и властвуй"? чем заключается принцип иерархического упорядочения? 1ft Что такое модульное программирование9 11 R ЧеМ Преимущества модульного программирования? чем суть концепции скрытия информации в программировании?
ГЛАВА 16 ОБЪЕКТНО-ОРИЕНТИРОВАННАЯ МЕТОДОЛОГИЯ РАЗРАБОТКИ ПРОГРАММ 16.1. ОСНОВНЫЕ ПОНЯТИЯ И ОПРЕДЕЛЕНИЯ По определению признанного авторитета в области объектно-ориентированных Цетолов разработки программ Гради Буча [5] “объектно-ориентированное Программирование (ООП) — это методология программирования которая основана ’/г представчении программы в виде совокупности объектов, каждый из которых Я стоя реализацией определенного класса (типа особого вида) а классы образуют р\ию на принципах наследуемости" Объектно-ориентированная методология (ОО-методология) так же как и стрхктурная методология, была создана с целью дисциплинировать процесс разработки больших программных комплексов и тем самым снизить их сложность и стоимость ОО-методология преследует те же цепи что и структурная но решает их с др\гои отправной точки и в большинстве случаев позволяет упраалять более сложными проектами чем структурная методология Как отмечалось выше, одним из принципов управления сложностью проекта является декомпозиция Гради Буч выделяет две разновидности декомпозиции алгоритмическую (так он называет декомпозицию поддерживаемую структурными методами) и объектно-ориентированную отличие которых состоит по его мнению в следующем “Разделение по алгоритмам концентрирует внимание на порядке происходящих событии а разделение по объектам придает особое значение факторам либо вызывающим действия либо являющимся объектами приложения этих действий ’ а Другими словами алгоритмическая декомпозиция учитывает в большей " ‘Х степени структуру взаимосвязей между частями сложной проблемы а объектно ориентированная декомпозиция уделяет больше внимания ха- - рактеру взаимосвязей_____________________________________________ На практике рекомендуется применять обе разновидности декомпозиции при создании крупных проектов целесообразно сначала применять объектно- ориентированный подход для создания обшей иерархии объектов отражающих сущность программируемой задачи а затем использовать алгоритмическую деком позицию на модули для упрощения разработки и сопровождения разрабатываемого программного комплекса Следует заметить что определений понятия “объект’ существует несколько Датам определение объекта придерживаясь мнения Гради Буча "Объект — осязаемая сущность которая четко проявляет свое поведение ”
Овъетно-ори^нтированная шзт<х>опоги« рмрабогПт 240 Объект характеризуется как совокупностью всех своих свойств (ца для животных — это наличие головы ушей глаз и тд ) и их текущих зна₽И>1,р (голова — большая, уши — длинные, глаза — желтые и i д) так и совокуп допссгимых для данного объекта действии (умение принимать пищу стоять **°С|**’ идти бежать и т д ) Указанное объединение в единой объекте как ‘ натерна^^ составных частей (голова лапы, хвост), так и действий ащнипушрукущ^ ?6,,hCr частям (действие ‘бежать быстро перемешает лапы) называется инкапс Объекты постоянно взаимодействуют, оказывая влияние на другие объект свою очередь, подвергаясь влиянию с их стороны *’ ” & Другим принципом! управления сложностью проекта является иерап упорядочение объектов (подзадач) получаемых в процессе декомпозиции PXU4eciv* И структурная и ОО-методология преследуют цель построения нерапхии дерева взаимосвязей между объектами (подзадачами) Но если структурная ие строится по простому принципу разделения целого на составные части рархия то при создании объектно-ориентмрованнои иерархии (ОО-нерархии) приник другой взгляд на тот же исходный объект и в иерархии непременно отражается наследование свойств родительских (вышележащих) типов объектов дочерним* < нижележащими) типами объектов
241 . эмиром /tJC " P™'* T,l'bo Pascal 7 n ПРРЛ-~~~ ' ---- - —«..™ c £w»~ "* - L...L., и 'P.'.'P' P Прение. *ap Типы верхних уровней ОО-иерархии как пг-,лпи, L, эК,е„П1Яро» объектов Не существует, например, Хехга) который бы сам по себе называв “Млекопитающе™ или “п™ ца“ Такие типы называются абстрттными Конкретные экземш^ь, объектов иХ правило, типы самых нижних уровней ОО-иерархии “крокодил Гена” - юнкретнь,й экземпляр объекта типа “Крокодил”, “кот Матроскин” - конкретный ’ экземпляр объекта типа Кошка домашняя” Еше одним основополагающим понятием ООП является полиморфизм Ао1ил*орФизм представляет собой свойство различных объектов выполнять одно и то же действие по-своему Например, действие “бежать” свойственно большинству животных Однако каждое из них (лев, слон, крокодил, черепаха) выполняет это действие различным образом При традиционном (не объектно-ориентированном) подходе к програм- мированию, животных перемещать будет программист, вызывая отдельную для конкретного животного и конкретного действия подпрограмму При объектно- ориентированном подходе программист только указывает, какому объекту какое из присущих ему действий требуется выполнить, и (для рассматриваемого примера) однажды описанные объекты-животные сами будут себя передвигать характерным для них способом, используя входящие в его состав метода Таким образом, в данном случае действие “бежать” будет называться почиморфическим действием, а многообразие форм проявления этого действия - потиморфизмом 16.2. ОБЪЕКТНО-ОРИЕНТИРОВАННЫЕ СРЕДСТВА ЯЗЫКА Turbo Pascal 16.2.1. Описание типов и экземпляров объектов Синтаксис описания объектных типов приведен в конце главы 3 Переменные объектных типов — экземпляры объектов — также, как и записи представляют собой комбинированные структуры данных По внешнему виду описания они также похожи на записи Первым синтаксическим отличием описания объектов от записей является использование ключевого слова object вместо ключевого слова record. Например, в простейшем случае, положение шахматной фигуры на доске с помощью объектного типа может быть описано таким образом Гур® { Позиция на доске i TPosxtion • object Colman TColumne Row TRows end, те типы TColumns и TRnw\ имеют следующий вид
Обычно ориентированная методология Р«зра6от 242 тхА-кРвт от записи состоит в том, что объект может йкГ1 деветвленные в виде 'процедур и функции. которые в данном иучое методами Ъ'собо следует выделить, что хороший стиль работь/с^^-, ni-япючает прямое обращение к их полям-| Чтобы ОО-методология работала четко, требуется, чтобы объекты сам„ выполняли все действия с помощью своих методов Эти жесткие требовав,, соответствуют общему понятию дисциплины структурного программирования (см фразу Дейкстры в гл 15) Таким образом, для любого действия выполняемого )1И информационными полями объекта, должен быть написан отдельный метод Например, для работы с позицией шахматной фигуры, то есть с объектов типа TPosttion, можно создать следующие методы • метод (процедура Init) для установки значений полей объекта, • метод (функция GetColumn) для определения текущей колонки шахматной фигуры, • метод (функция GetRow) для определения текущей строки шахматной фигуры В программе описания заголовков методов располагаются после описании информационных почеи объекта и будут выглядеть так ( Позиция на доске } TPosxtion = abject Column TColumns Row TRows, procedure Inxt ( Cl TColumns Rw TRows ) , function GetColumn TColumns, function GetRow TRows, end Два формальных параметра Cl и Rw в процедуре Init предназначены дня передачи фактических значении координат позиции, на которую будет установлена шахматная фигура Объединение информационных полей и методов которые выполняют над ними действия в единый ооъект соответствует 00-понятию "инкапсуляция” Аналогично записям к полям переменных объектных типов разрешается обращаться как с помощью квалифицируемых (уточненных) идентификаторов так и с помощью оператора with Например, при описаниях переменных var WKingPoe TPoeition KxngCol TColumns KxngRow TRows в тексте программы вместо операторов begin WKxngPos Column ” WKingPos Row a 1 KingCol . WKxngPos Column KingRow e WKxngPos Row •nd
.:^ч(^.9ние а c^e(3t? Ttjrbo pascal 7 0 ~ -----------------------------------243 1М|ЧЛ110 использование оператора with такого вида F Более того, применение оператора „1Ы1 с объектными типами, также как и 2nd записей, не только возможно, но и рекомендуется Напомним, что хороший стиль работы с объектами исключает прямое .мне к информационным полям объектов Поэтому следуя строгим правилам в приведенном фрагменте операторы Column = ’s', Row = 1, KingCol = Column, KingRow = Row «буется заменить на вызов процедуры инициализации объекта и вызовы функций ятия значений текущей колонки и текущей строки Это может быть сделано как в случае информационных полей объекта, так и с помощью квалифицируемых хентификаторов IB и begin WKingPos Init KingCol » WKingPos GetColumn KingRow = WKingPos GetRow tnd, ti* pOr и in с помощью оператора with with WKingPos do begin Init ( e 1) KingCol = GetColumn KingRow = GetRow end, Обратите внимание что в разделе типов при описании объектных типов указываются только заголовки методов Полное же описание методов — их тело — указывается в разделе объявления процедур и ; функции_________________________________ ______________— Так объявление типа TPosittOn в разделе должно быть дополнено последующим полным описанием Imt. GetCoiumn и GetRow
ООьеОТн°^и"'“Р‘ж>ннаЯ Тура ( типы координат на доске I TColumns = "а*..’h’' TRows = 1. • 8; { позиция на доске } TPosition = object Column : TColumns; Row • TRows; procedure Init < Cl- TColumns; Rw: TRows ); function GetColumn : TColumns; function GetRow : TRows; end, { Реализация методов ) { Объект TPosition } procedure TPosition. Init < Cl: TColumns; Rw: TRows ), begin Column := Cl; Row := Rw; end; function TPosition.GetColumn : TColumns; begin GetColumn := Column; end; function TPosition.GetRow : TRows; begin GetRow := Row; end, Важной особенностью описания реализации методов является тс что доступ к информационным полям Column и Row объекта тип. TPosition, которому принадлежат определяемые методы Init, GetColunir GetRow, осуществляется так, как если бы операторные блоки тодое были окружены невидимым оператором wi с л Это вытекает из правил области действия (сферы видимости) полей и методе объекта, согласно которым они (поля и методы) разделяют одну и ту же облает действия, несмотря на то. что могут быть описаны в различных местах текст программы Если какой-либо экземпляр объектного типа ObjectVar вызывает приг 1 лежащий ему метод Method, то выполняется неявный оператор with ObjectVar do Method связывающий объект и его методы в единой области действия Например, при вызове WKingPoe Init ('w',1).
procedure TPo.ieion IniTTTP^—~~--- hMln ' TColumn» with WKingPoa do b-gin Column Row - •nd, -nd R* TRow. ), • С1, Rw, WQueenPoa Init (‘е’,р proedor. TPoeition Init ( Cl TColumn» r„ TRows ) begin with WQueenPos do begin Column я Cl, Row » Rw, end, end, I.imciiim, 'по на самом деле исходный теки процедуры TPosition Init не изменяется ынисимости or иыюиа. как к показанных примерах, которые были приведены э и ко дня объяснения смысла происходящих действий В дс пи ни icina гост и в ыголовках методов всегда присутствует невидимый орм umihiI траме гр с ндепт нфикагором Self, когоромх при вызове метода в качестве |цп'1цк(чо параметра неявно передастся имя конкретного экземпляра объекта ip iMCip Self фактически является 12 разрядным указателем на экземпляр объекта, лив с ТВЛЯ10ЩС1 о вы юн метода ► С труктуру невидимых описаний каждого метода можно представить так procedure MethodName ( Self Pointer другие параметры ) begin with Self do begin Операторы метода end -nd _________ Следует ымештъ. что хотя Sell в методе ircerai присутствует неявно, доптсыеоя ш»1ос ею нспольюмние Например в описании npoueiiypN hut тмин TPosition можно записать proc-dur- TPoaition Init ( Cl TColumn. Rw TRowa ) begin Self Column - Cl Self Row Rw —nd - Оливки применят». Sell рекомендуекя только в c«i)'Uie необходимости гримеру для )с гранения неоднозначностей в использовании идентнфика рое
246 Объектно-ориентированная методология разработ... 1 ~~~~~ 16.3 ОБЪЕКТЫ И МОДУЛИ Разделенность описания объектных типов и реализации их методов гарчо„ соответствхет оформлению в виде моадля ) которого (см глав) 6) также раэд опиелние заголовков экспортирлемых пропел)р в интерфейсном разделе и\ реализации в разделе реализации Поскольку объектные типы вводятся чаще всего для того чтобы их м использовать при написании различных программ то они как правило описыв^ в разделе interface Описание же реализации методов идеально соответствует размещен» разделе injslenientation, так как по самой сути объектов требуется чтобы конкреп работы их методов была скрыта от пользователя В целом общие принципы сфе* действия переменных принятые для модулей распространяются и на объять в разделе реализации можно использовать все что описано в интерфеисно разделе Запись приведенного объектного типа TPosition в виде модуля б\де выглядеть так unit ChessMod interface iype { Типы координат ча доске ) TColumns = a' 'h' TRows =1 8 t Позиция ча доске } TPositxon = object Column TColumns Row TRows proceefure Init ( Cl TColumns Rw TRows ) function GetColumn TColumns function GetRow TRows end 1 eman ta ti on 1 Реа^зация методов ) О*ъек- TPosition } procedure TPosition Tmb I ry , n In C1 TColumne Rw TRows ) Column = ci ROW a Rw end function TPosition GetCaliimr. , begin ^column TColumns GetColumn • eolith end function TPo.Xtxon GetRo, TOo„ GetRow « Row end begin end
247 in,ul» среде Turbo Рлчсл! 7 о 16.4. ДИРЕКТИВЫ private и public IM ,u кшия объектов в языке Turbo P.,st ,| 70 имеег дополнительные крелоя, „.„„ы.пия областью лид,«мости полей и методов Первое средство гнре™, te появилось ешс в предыдущей версии Turtro Pascal 6 0. а второе - rlXX" public «первые введено то ила в седьмой верит юшв 16.4.1. Директива private Директива private « рамках описания объекта выполняет т.1К\|о же роль клк и раздел реализации implementation в модуле Го есть преднтначеиа Ли скрытия яекоторыл деталей описания объекта от па сыователеи которые впослелегвии будут Испо1ыовать методы этою объекта Таким образом Turbo Pascal погвовяст ил цыц, внпрч объектов закрытые (приватные — private) поля п методы 1-7 Приватные поля и методы доступны только внутри того модуля в котором описан объект По умолчанию поим и методы опж.шныс непосредственно после tape ернированного слова object принимаются общедоступными Приватные поля и «етолы описываются пойле обычных общедоступных полей и методов велел за [резервированным словом private Структуру описания объекта с использованием директивы private можно [ридставить следующим образом Туре ObjectType object (Тип родители) Общедоступные поля. Общедоступные методы» private Приватные поля, Приватные методы, ______end Например для рассматриваемого типа TPostnon приватными целесообразно лсыть поля Column и Row (чтобы пользователи шахматного модуля не обращались ним напрямую, а только посредством методов) и метод Init (поскольку ои, как •удег видно далее, также ие требуется для прямого вызова пользователями) ( Полиция Н) Л 'Л I TPoeition object function GmtColumn TColumne function GmtRow TRowe prlva te Column TColumne Row TRowe procedure Init ( Cl TColumne Rw TRowe ) end В результате получить доступ к полям Columns и Row и методу Init в модулях импортирующих модуль ChessMod будет невозможно невзирая на н» по »ип I petition описан в интерфейсном разделе модуля
не .. - "^огич рвзр^г,. 16 4.2. Директива public „„ипзтные поля и методы должны располагаться п ^едХ-- НоГлирПе1к™па public позволяет, если это удобно. pacn0J)< и\ наоборот Objectrype = ob^et (Тип родителя) private Приватные поля; Приватные методы; public Общедоступные поля; Общедоступные методы; end; Таким образом, чтобы не нарушать ранее принятую последовательность описаний полей и методов типа TPosition, его можно объявить так ( Позиция на доске } TPosition = object private Column ; TColumns; Row : TRows; procedure Init ( Cl: TColumns; Rw: TROws ); public function GetColumn : TColumns; function GetRow : TRows; end, 16.5. НАСЛЕДОВАНИЕ, ПРАВИЛА НАСЛЕДОВАНИЯ Факт наследования каким-либо типом характеристик родительского типа обозначается указанием после ключевого слова object имени непосредственного родителя, которое заключается в круглые скобки Возьмем, например, тип шахматной иерархии TChessMan, который яазяется потомком типа TPosition и описывает характеристики обобщенной (абстрактной) шахматной фигуры 1 Цвет фигур } TColour = (Whitecolour, BlacXColour); ( Шахматная фигура ) TChessMan - object ( TPosition ) private Colour TColour, Present . Boolean; procedure Init ( Cl. TColumns, Rw TRows, BW TColour ), procedure Put ( Name String ).
...ш1ров^ие 9 среде Turbo Pascal 7 о 249 public“ —- function GetColour TColour function IsProsont Boolean procedure Clear procedure Del, procedure Digplay, end, Этот тип, по сравнению со своим родительским типом TPosition, расширен информационными полями Colour (цвет белый/черный) и Present (присутствие фигуры на доске True/False) а также методами • функцией GetColour, которая возвращает цвет фигуры, function TCheggMan GetColour TColour begin GetColour = Colour end • функцией IsPresent которая проверяет присутствие фигуры на доске function TChegsMan IgPregent Boolean begin IgPregent - Present, end • процедурой Clear которая стирает изображение фигуры на старой позиции экрана для перемещения ее на новую procedure TChessMan Clear begin Put ( ' ' ) ErrorMesgage ( 1 ) end • процедурой Del которая стирает изображение фигуры на экране с помощью вызова Clear и отмечает ее как чдатенную с доски procedure TChegsMan Del begin Clear Present * Falee end процедурой Display которая высвечивает изображение фигуры на ее текущей позиции ______________ procedure TCheeeMan Display begin Put ( CM ) end ______ -
~ : ^ятированняя метоОопогия рШра6отки „ 250 *** on Put которая вызывает метод GetCoords для преобразоМни процедурой put к Р устанавливает соответствующие полю „ =^7=т° изображение фигуры на ее текущей позиции procedure TChessMan . Put ( Name : String > : X, Y : Word; begin GetCoords (X, Y ) ; GotoXY ( X, Y ); if (Row + Ord (Column) ) mod 2 = 0 then TextBackGround (Black) else TextBackGround (White); case Colour of WhiteColour : TextColor ( LightRed ) ; BlackColour : TextColor ( LightGreen ); end; Write ( Name ); en d; Здесь же отметим, что методы GetCoords и ErrorMessage добавлены в объектный тип TPosition и вместе с методом Put служат для “привязки” шахматных действий и выводимых сообщений к изображению на экране монитора Метод GetCoords переводит логические шахматные координаты в физические экранные координаты и возвращает их в точку вызова. Поскольку тип TPosition наследуется всеми шахматными фигурами, то каждая из них при выполнении хода может преобразовать свои шахматные координаты в экранные и после этого показывать себя на дисплее Один из возможных вариантов реализации метода GetCoords имеет такой вид procedure TPosition GetCoords( var X, Y : Word ) ; const BegX = 20; BegY = 23; StepX = 7; StepY s -3; begin X . = BegX + StepX * (Ord ( Column ) - Ord ( 1 a ') ) ; Y •= BegY + StepY * ( Row - 1 ) , end. Метод ErrorMessage выводит на эран сообщения об ошибках procedure TPosition.ErrorMessage ( Mas : String ), const BegY «23, begin GotoXY ( 1, BegY ); TextBackGround (Blue) TextColor ( LightRed + Blink ) Write ( Meg ) , end; L----------------------------------------_______ Наследование дочерними типами информационных полей н методов их родительских типов выполняется согласно следующим правы гам
.Дамиром»1** e CPP^° Turbo Pascal 7 о llpjiui 10 1 Информационные поля и методы родительского типа наследуются всеми сГ0 ючерпими типами независимо от числа промежуточных уровней иерархии правило 2 Доступ к полям и методах! родительских типов в рамках описания любых дочерних типов выполняется так, как будто-бы они описаны в самом дочернем тиле QTC1oaa следует Правило 3. Правило 3. Ни в одном из дочерних типов не могут использоваться идентификаторы долей, совпадающие с идентификаторами полей какого-либо из родительских типов Это же относится и к идентификаторам формальных параметров, указанным в заголовках методов. Правило 4 Дочерний тип может доопределить произвольное число собственных методов и информационных полей. Правило 5. Любое изменение текста в родительском методе автоматически оказывает влияние на все методы порожденных дочерних типов, которые его вызывают Правило 6. В противоположность информационным полям (см. правило 3) идентификаторы методов в дочерних типах могут совпадать с именами методов в родительских типах. В этом случае говорят, что дочерний метод подавляет одноименный ему родительский, и в рамках дочернего типа, при указании имени такого метода, б\дет вызываться именно дочерний метод, а не родительский. Однако возможность обращения к подавленному родительскому методу остается с помощью квалифицируемого (уточненного) идентификатора, как это сделано, например, в методе TChessMan.lnit, реализация которого выглядит так procedure TChessMan.lnit ( Cl: TColumns; Rw: TRows; BW: TColour ); begin TPosition.Init ( Cl, Rw ); Colour := BW; Present := True; end; _______________ Опишем теперь для примера типы двух конкретных шахматных фигур — короля и пешки Списание объектны? { Король TKing = object ( TChessMan ) procedure Init (Cl: TColumns: Rw: TRows, BW: TColour): procedure Move ( Cl: TColumns: Rw: TRows); /unction IsMoveRight ( Cl. TColumns; Rw • TRows ) Boolean; procedure Display; end • TPawn « object ( TChesaMan ) procedure Init (Cl: TColumns; Rw: TRows; BW: TColour); procedure Move ( Cl: TColumns.- Rw: TRows); function IsMoveRxght ( Cl: TColumns; Rw. TRows) : Boolean; procedure Display; end
оаьсктмо-ориентировеннйн методология paipn(>c>m>tu прпч,Л.^ -------------------] реализация методов ) ( Объект TKing ) procedure TKmg but (Cl TColumns. Rw TRows BW TColour) begin-------------_ „T, . TChessMan Init ( Cl, Rw, BW )- end, procedure TKing Move ( Cl TColumns. Rw TRows), beyin if IsMoveRight (Cl, Rw) then begin Clear, Column = Cl, Row = Rw, Display, end else ErrorMessage ( 'Неверный ход’ ' ) , end function TKing IsMoveRight ( Cl TColumns, Rw TRows ) Boolean, var DeltaCl, DeltaRw Word, begin DeltaCl = Abs (Ord (Column)-Ord (Cl) ) , DeltaRw = Abs (Row -Rw) , if (DeltaCl > 1) or (DeltaRw > 1) or (DeltaCl = 0) and (DeltaRw = 0) then IsMoveRight = False else IsMoveRight = True end, procedure begin Put ( end, procedure begin TChessMan Init ( Cl, R„ b„ > end ' ' ’ procedure TPawn Move tn w , begin 1 C1 ^Columns Rw TRows) if IsMoveRight (Cl, R„, then begin Clear, Column « ci Row > Rw, Display, end end S2Se Err°tM“ss^ ( 'He..p„™ won- > TKing Display, 'Kg' ), { Объект TPawn I TPawn Init (Cl TColumns Rw TRows, BW TroMnv)
>и wi/t> к * furbo Pascal i Cl TColuana, var DeltaCl, DeltaRw Integer” TRows> Boolean, begin ' DeltaCl = Abs (Ord (Column) DeltaRw = RW - IsMoveRxght = False, case Colour of Ord (Cl)) WhiteColour if ( DeltaRw* *! > and ( DeltaC1<2 . or ( Row=2 ) and ( DeltaCl=0 ) and ( DeltaRw=2 ) then IsMoveRight = True Blackcolour lf ( DeltaRw=-l ) and ('oeltaCKZ ) or ( row=7 ) and ( DeltaCl=0 ) and ( DeltaRw=-2 ) then IsMoveRxght = True, end end, procedure TPawn Display begin Put ( ’P‘ ), end, В этих объектных типах добавлены новые методы • процедура Move для перемещения фигуры, • функция IsMoveRight для проверки соответствия выполняемого хода правилам передвижения конкретной фигуры, • процедура Display, которая подавляет действие одноименной процедуры объектного типа TChessMan чтобы выводить на экран изображение “своей’ фигуры (для короля — символы ‘Kg. для пешки — символ *Р') Аналогично будут описаны и остальные шахматные фигуры Отличительной чертой языка Turbo Pascal версии 7 0 относящейся к механизму наследования является новое зарезервированное слово inherited Это слово предназначено для использования вместо имени непосредственного 1ка данного объекта Его можно рассматривать как пссвдоимя “родительский inn аналогично понятию “родительский каталог” в MS DOS Например учитывая что тип TChessMan является непосредственным предком типа TKmg метод TKmg Init можно записать так________________________ | '"’бъскт TKinq J procedure TKing Init (Cl TColumne, Rw TRowe BW TColour) begin inherited Init ( Cl, Rw, BW ( Ранее здесь была строка TChessMan Init ( Cl, Rw, BW , f •nd
Пбъвктно-°Р<'вн'тр°а!'нн'>я ^тоДопогчя РДДРДбот»^ Заметим, что зарезервированное слово inherited нс может исподь. в методах объектных типов, которые не имеют предков. iO69Tkq Важным аспектом, касающимся наследования являются правила наследуемых методов. Правило 1. При вызове метода компилятор сначала ищет метод имя определено внутри типа объекта. В типе TKing определяеются метод 'С°то^ Display, таким же, как и у родительского типа TChessMan. Когда С ИМе"еМ TKing.Move вызывается метод Display, компилятор подставляет в кома ° Мет°Дс адрес собственного для TKing Метода Display. Нду 8ызова Правило 2 Если в типе объекта не определен метод с указанным в операторе вызова именем, например, не был бы описан TKing.Display, то компилятор в поисках метода с таким именем, поднимается выше к непосредственному родительскому типу. Если метод с требуемым именем найден, то в исходном коде дочернего метода TKing.Move вместо адреса метода TKing.Display подставляется адрес родительского метода TChessMan.Display Если метод с таким именем не найден, то компилятор продолжает продвигаться вверх по родительским объектам в поисках метода Если компилятор наталкивается на самый первый (высший) тип объекта, а методе требуемым именем не найден, то он выдает сообщение об ошибке, указывающее, что ни одного такого метода не определено. Правило 3 Если наследуемый метод найден и его адрес подставлен, то следует помнить, что вызываемый метод будет работать так, как он определен и компилирован для родительского типа, а не для дочернего. Если этот наследуемый родительский метод вызывает еше и другие методы, то вызываться уже будут только родительские или вышележащие методы, так как вызовы методов из нижележащих по иерархии типов не допускаются. Учитывая сказанное, модуль ChessMod. включающий все рассмотренные типы объектов и реализацию их методов, будет выглядеть так: unit ChessMod; interface type ( Типы координат на доске } TColumns = 'а 1 . . 'h'; TRows = 1. .8; j Цвет фигур } TColour = (WhiteColour, BlackColour); ( Позиция на доске j TPosition = object private Column •. TColumns; Ro* • TRows; procedure Init ( Cl; TColumns; Rw: TRows ); procedure GetCoords ( var X, Y : Word >; procedure ErrorMessage ( Mea • String ); public function GetColumn ; TColumns: function GetRow • TRows; end; '
• r-Pr^’ Tu,hf' PtKBI TO 255 “‘’mithj, фи,ур , TChe«M»n - object ( TPosition ) private Colour TColour prosent Boolean procedure Inxt ( cl TColu^e R„ TRo„3 BW TColour ) procedure Put( Name String ) public function GetColour TColour function IsPresent Boolean procedure Clear procedure Del procedure Display end { Король } TKing = object ( TChessMan ) procedure Init (Cl TColumns Rw TRows BW TColour) procedure Move ( Cl TColumns Rw TRows) function IsMoveRight ( Cl TColumns Rw TRows ) Boolean procedure Display end { Королева (Ферзь) } TQueen = object ( TChessMan ) procedure Init (Cl TColumns Rw TRows BW TColour) procedure Move ( Cl TColumns Rw TRows) function IsMoveRight ( Cl TColumns Rw TRows ) Boolean procedure Display end ( Ладья ) TCastle = object ( TChessMan ) procedure Init (Cl TColumns Rw TRows BW TColour) procedure Move ( Cl TColumns Rw TRows) function IsMoveRight ( Cl TColumns Rw TRows ) Boolean procedure Display end л н TBishop = object ( TChessMan ) procedure Init (Cl TColumns Rw TRows BW TColour) procedure Move ( Cl TColumns Rw TRows) function IsMoveRight ( Cl TColumns rw TRows ) Boolean procedure Display end
<у^тно ориентированная методологии Pflipa6om^^^ 256 { Конь ) = object ( TChessMan ) edure Init (Cl TColumns ______________ f Cl TColumns procedure Move ( function IsMoveRight ( Cl TKnxght Rw TRows BW TColout) Rw TRows) TColumns, TRows Boolean, procedure Display end { Пешка TPawn = object ( TChessMan ) procedur e procedure function Init (Cl TColumns, Move ( Cl TColumns IsMoveRight ( Cl Rw Rw Rw TColumns, TRows) TRows BW TColour) TRows), Boolean, procedure end Display, { Переменные шахматных фигур } WKg, BKg TKing, { Короли } WQ, BQ TQueen ( Королевы ( Ферзи) ] f WC1, WC2 , BC1 BC2 TCastle, { Ладьи ; WB1 WB2 BB1, BB2 TBishop, { Слоны ; WK1 WK2 BK1, BK2 TKnight, { Кони } WP1 WP2 WP3, WP4, WP5, WP6, WP7, WP8, { Пешки BP1 BP2 ВРЗ, BP4, BP5, BP6, ВР7, ВР8 TPawn, ( Пешки } iraplemen ta tion { Реализация методов } uses Crt, Dos ( Объект TPosition ) procedure TPosition Init ( cl TColumns Rw TRows ) begin Column = cl, Row = Rw, end function TPosition GetColumn TColumns begin GetColumn = Column end function TPosition GetRow TRows begin GetRow = Row end procedure TPosition GetCoords( war x, 1 word ) cons t BegX - 20 BegY - 23, StepX = 7 StepY ж -3 -J
257 « среде Tinbo Pesco/ 7 0 “begin 5C . s BegX + StepX * (Ord ( Column Y •_« BegY + StepY * ( Ro* - 1 ) ; end; Ord (1 a’)); procedure TPosition.ErrorMessage ( Mes String ); const BegY =23; begin GotoXY ( 1, BegY ); TextBackGround (Blue); TextColor ( LightRed + Blink ); Write ( Mes ); end; { Объект TChessMan } procedure TChessMan.Init ( Cl; TColumns; Rw: TRows; BW: TColour ); begin inherited Init ( Cl, Rw ); Colour := BW; Present :== True; end; function TChessMan.GetColour : TColour; begin GetColour := Colour; end; function TChessMan.IsPresent : Boolean; begin IsPresent ;= Present; end; procedure TChessMan.Clear; begin Put ( 1 • ) ; ErrorMessage ( ' * )/ end; procedure TChessMan.Del; begin Clear; Present := False; end; procedure TChessMan.Display; begin Put ( 'CM1 ) ; end; procedure TChessMan.Put( Name : String ); var x, Y : Word; begin GetCoords (X, Y >; GotoXY (X, Г ); if (Row + лт-rt (re) nmr.) ) mod 2 “ 0 then
258 П^тт-оР^»тиР°азт№ ме"погЮ,т;,ия PO’PQ&M,,^ ^BackGround (Black) :tBackGround (White) , Textcolor ( LightRed ); Textcolor ( LightGreen }; --------Tex else Tex' case Colour of WhiteColour BlackColour . end; Write ( Name ), end; ( объект TKing } procedure TKxng.Inxt (Cl: TColumns; Rw: TRows; BW: TColour), hegiinherited Init ( cl, Rw, Bw ) ; end; procedure TKing Move ( Cl- TColumns, Rw TRows), begin if IsMoveRight (Cl, Rw) then begin Clear, Column — Cl, Row - Rw, Display, end else ErrorMeggage ( 'Неверный ход’ ' ) , end, function TKing IsMoveRight ( cl: TColumns; Rw TRows ) Boolean, var DeltaCl, DeltaRw . word, begin DeltaCl = Abs (Ord (Column) -Ord (Cl) ) ; DeltaRw = Abs (Row -Rw), if (DeltaCl > 1) or (DeltaRw > 1) or (DeltaCl = 0) and (DeltaRw = 0) then IsMoveRight = False else IsMoveRight = True end procedure TKing Display, begin Put ( 'Kg1 ) , end, I ОСъект TPawn I procedure TPawn inxt (Cl TcniInRn. o — ___ begin ' TColumns; Rw TRows, BW TColour) inherited Inxt ( Cl, Rw BW 1 end, ' ' procedure TPawn Move ( Cl begin TColumns, Rw TRows); xf IsMoveRight (Cl, Rw) then begin Clear Column « ci Row * Rw Display, end
259 e cre.'e Fuibo Pascal 7 О Г----else ErrorMessage ('Неверный ход' 1 ---------------- end- function TPawn IsMoveRight ( Cl. TColumns; Rw: TRows) : Boolean, var DeltaCl, DeltaRw : Integer; hegxn DeltaCl := Abs (Ord(Column) - Ord(Cl)); DeltaRw := Rw - Row; IsMoveRxght := False; case Colour of Whitecolour : if ( DeltaRw=l ) and ( DeltaCl<2 ) or ( Row=2 ) and ( DeltaCl=O ) and ( DeltaRw=2 ) then IsMoveRight := True; BlackColour : if ( DeltaRw=-l ) and ( DeltaCl<2 ) or ( Row=7 ) and ( DeltaCl=0 ) and ( DeltaRw=-2 ) then IsMoveRigh t := True; end end; procedure TPawn Display; begin Put ( ’P’ ); end; { Объект TQueen } procedure TQueen Init (Cl: TColumns; Rw: TRows; BW: TColour); begin inherited Init ( Cl, Rw, BW ); end, procedure TQueen Move ( Cl* TColumns; Rw: TRows), begin if IsMoveRxght (Cl, Rw) then begin Clear; Column .= Cl; Row := Rw; Display; end else ErrorMessage ( 'Неверный ход* ' ), end, 1 function TQueen IsMoveRight ( Cl: TColumns. ! Rw TRows ) Boolean, l begin IsMoveRight = True end, procedure TQueen Display, begin Put ( 'Q' ) . end
260 п^но-ори^ир^нн^ методология разра6отаи ---------Г Объект TCastle } _ *. zri • TColumns; Rw: TRows; BW: TColour), TCastle.Init (Cl. lUQiLuu* inherited Init ( Cl, *», BW end; procedure TCastle.Move ( Cl: TColumns; Rw: TRows) begin if IsMoveRight (Cl, Rw) then begin Clear; Column := Cl; Row : = Rw ; Display; end else ErrorMessage ( 'Неверный ход’ ' ) ; end; function TCastle. IsMoveRight ( Cl: TColumns; Rw: TRows ) : Boolean; begin IsMoveRight := True; end; procedure TCastle.Display; begin Put ( 1C' ) ; end; { Объект TBishop } procedure ТВxshop.Imt (Cl: TColumns; Rw: TRows; BW: TColour); begin inherited Init ( Cl, Rw, BW ); end; procedure TBishop Move ( Cl: TColumns; Rw: TRows); begin if IsMoveRight (Cl, Rw) then begin Clear, Column = ci, Row .» Rw. Display, end else ErrorMessage ( на.арН1Л ход, . ) ; function TBishop IsMoveRight ( cl. TColumns, begin R*: TRows ) . Boolean, IsMoveRight • True; end, procedure TBishop Display, begin Put ( 'B1 ), end.
.„тование в среде Turbo Pascal 7 о ____________________________________________________________261 r"( ООъект TKnight ')------------------------------------------ p^wdsr. TKnight.Init (Cl: TColumne; Rw: TRows; BW: TColour); begin inherited Init ( Cl, RW/ bw )• end; procedure TKnight.Move ( Cl: TColumns; Rw: TRows); begin if IsMoveRight (Cl, Rw) then begin Clear; Column := Cl; Row := Rw; Display; end else ErrorMessage ( 'Неверный ход! 1 ) ; end; function TKnight. IsMoveRight ( Cl: TColumns; Rw; TRows ) : Boolean; begin IsMoveRight := True; end; procedure TKnight.Display; begin Put ( 'K' ); end; procedure BoardPicture; const BegX = 20; BegY = 24; StepX = 7; StepY = 3; var BX, BY Byte; 1, 3 : Byte; procedure Cell( X, Y, BW : Byte ); var j Byte; begin TextBackGround (BW); for з :« Y to Y+StepY do begin GotoXY (Х,з); Write ( 1 ’) ; end; end, begin for з «0 downto 1 do begin for i: «1 to 8 do if (1+3) mod 2 0 then Cell (BegX-3+(x-l)«StepX, BagY-3«StepY+1, Black)
262 end; GotoXY (BegX-3, BegY+1); TextBackGround (Blue); Textcolor ( Yellow ); Writef' abed for j ; =8 down to 1 do g e (BegX-5, BegY-3‘StepY+2) ; Write O:D' end: procedure SetCursorSlze (BegLine, EndLine: Byte); * ( установить курсор ) var Regs: Registers; begin with Regs do begin AH:=$01; CH:=BegLxne; CL:=EndLine; end; Intr($10,Regs); end; procedure HxdeCursor; { Спрятать курсор } var BegLxne, EndLxne : Byte; begin BegLxne:=$20; 1 $20 в качестве значения начальной } { пинии делает курсор невидимым } EndLxne:=$00; SetCursorSxze(BegLxne, EndLine) ; end; begin TextBackGround( Blue ); ClrScr; HxdeCuxaor; I Спрятать курсор } BoardPxcture; end. Обратите внимание, что “привязка" шахматных действии к изображению на экране монитора выполняется следующими подпрограммами- • рассмотренными выше методами GetCoords. ErrorMessage объектного типа Tposition и методом Put объектного типа TChessMan. • независимыми от иерархии объектов процедурами BoardPtclure (рисует на экране в текстовом режиме упрошенный вид шахматной доски). SetCursorSize и HideCursor (управляют выводом на экран курсора) Заметим также, что в привс-- -чип короля и пешки реализованы не полност инном виде проверяет только возможность тре ... .......... хода королем и пешкой, но не учитывает взаимог Приведем элементарную программу, истк. делает установи т* *’ > k - входное положение и вылолн 11 иих
в ср»Д» Тип» vV|0l’ КОДУ Выданы процедуры /иНшппены „„ пп для просмотра выполнения program Chess; uses ChessMod; begin Readin; WKg.Init ( Readin; BKg.Init ( Readin; WKg.Move ( Readin; BKg.Move ( Readin; end. 'e',1,Whitecolour ) ; WKg.Dxsplay; 'e' ,8,BlackColour ); BKg.Display ; ’ e ’ , 2 ) ; ' d', 8 ); Рассмотрим одну тонкость реализации правил наследования. Нетрудно заметить, что в описаниях всех шахматных фигур метод Move будет идентичным методу Move типа TKing, так как никаких конкретных особенностей именно короля в нем нет. Поэтому возникает естественное желание сократить текст и вынести повторяющийся метод на уровень выше в тип TChessMan Поскольку в методе Move вызывается метод IsMoveRight, то в типе TChessMan следует описать и его. { Шахматная фигура } TChessMan = object ( TPosition ) private Colour : TColour; Present : Boolean; procedure Init ( Cl: TColumns; Rw: TRows; BW: TColour ) ; procedure Put( Name String ); public function GetColour TColour; function IsPresent Boolean; procedure Clear; procedure Del; procedure Display; function IsMoveRight ( Cl. TColumns. Rw: TRows ) Boolean; procedure Move ( Cl: TColumns, Rw- TRo s) end; 1 Король ! TKrng = object ( TChessMan > TColour); procedure Init (Cl: TColumns, Rw. TKowa. function IsMoveRight ( Cl: TColumns, Rw: TRows ) • Boolean, procedure Display; end,
Объектно-ориентированная методология РЯ1рвбот^.. 264 1 По правилам наследования метод Move должен вызываться так бы был описан в типах каждой отдельной фигуры После того как*С' Ч такую модификацию программы, он действительно будет корректн МЬ| СДсЛа? фигуры, однако на новом месте вместо имен как белого, так и чеон ПереМеЧ|^ появятся соответствующие абстрактной шахматной фигуре символы ‘‘CM? Кор0;кй записаны в операторе вывода на экран в методе TChessMan Display ’ KoiBPi>If Это происходит потому, что до сих пор мы использовали тол называемые, статические методы, адреса которых связываются с экзе К°’ Та? объектов (переменными объектных типов) статически еще во время ком ЛЯрам^ не изменяются до завершения работы программы ЯЦии и В первом случае, когда каждая из фигур имела свой метод Move экземпляра объекта типа TKing имела такой вид ’ СТруктУра Объект WKg Column ’e’ Row 1 Colour WhiteColour Present True GetCoIumn адрес TPosition.GetCoIumn Наследуется Наследуется GetRow адрес TPosition.GetRow GetCoords адрес TPosition. GetCoords Наследуется Наследуется Наследуется Наследуется Наследуется Наследуется Наследуется TPosition.Init, ErrorMessage адрес TPosition. ErrorMessaee Put адрес TChessMan.Put GetColour IsPresent адрес TChessMan. GetColour адрес TChessMan.IsPresent Clear Del Init ядрес TChessMan.Clear адрес TChessMan. Del адрес TKing.Init TChessMan.Init Display адрес TKing.Display TChessMan. Display подавлен TChessMan. Vfove не описан TChessMan. Move адрес TKing.Move IsMoveRight адрес TKing. IsMoveRight sMoveRight не эписап в jtom случае работае т К0РРектная цепочка вызовов "TCg-Move 1 TKing.Move (!) .„.^-„^««^,(1) TChmM».Oe«r TKing.Divbv (D Коиежти»» проири Вмвд CWJMO. “Kg” ошоочных ходов
265 к ° Turbo Pascal 7 О " """"' Во пгором случае, когда вес фигуры имеют лл.и. •. .. „„„..ском типе TChessMan, стрткпра рХ^„ ™йа“Нб“;: О1ЬКО отличаться от предыдущей а 1 к,пе ь>яст Column Row Colour Present GetColumn GetRow GctCoords ErrorMessage Put GetColour IsPresent Clear Del Init Display Move IsMoveRight Объект WKr Наследуется Наследуется Наследуется Наследуется Наследуется Наследуется Наследуется Наследуется Наследуется TPosition. IniLTCh essMan.Init подавлены. TChessMan.Displa у подавлен. 'e' 1 WhiteColour True адрес TPosition.GetColumn адрес TPosition.GetRow адрес TPosition.GctCoords адрес TPosition. ErrorMessage адрес TChessMan.Put адрес TChessMan. GetColour адрес TChessMan.IsPresent адрес TChessMan.Clear адрес TChessMan.Del адрес TKing.Init адрес TKing.Display адрес TChessMan.Move(!) TChessMan. IsMo veRight подавлен адрес TKing.IsMo>eRight Наследуется. но в его теле вызываются TChessMan Display, и TChessMan IsMoxeRight а не TKing Dtspla\ и TKing IsMoxeRight В этом случае будет выполнена следчюшая цепочка вызовов WKg.Move I TChessMan.Move (!) TChessMan.IsMoveRight (!) Отсутствие реакции на ошибочные ходы TChessMan.Clear -----------1 TChessMan.Display (!) Вывод символов “CM"
..-..„„„пляннвя методология раэробо^ 00ъектно-ооиснтир 266 „ методов IsMoveRight и Display нс из того, как видно. n=^cS ” вмест0 типа TKing. который нужен - из типа ________ ______________ , „„тт/аиии -— ЧТООМ и Movrt qq., i чВт^ОвсеИраЯ6ога°ло правильно - будет использование полиМорф J ских действий (методов).------------ - . J „„„мппсЬическое действие - действие, которое для всех объект Напомним, п™”м°рф осмотренном выше примере о животных- дейет№с имеет одинаковое и } из объектов выполняется по-своему (львом, слоном “бежать’). но которое шахмат имеем одинаковое действие “xoa крокодилом, черепа' каждой из фигур по своим правилам. В раодод. рен^ой'си^ции на первый взгляд все было сделано правильно - общее действие Move вын^ено в родительский тип, чтобы оно было доступно всем, однако это действие не стало полиморфическим! Причина такого результата состоит в том, чтос помощью статических методов реализовать полиморфические действия т возможно, так как привязка адресов методов (процедур, функций) к эк- земплярам объектов выполняется статически. В первом случае метод TKing. Move статически связан с коррект- ными методами TKing.Display и TKing.IsMoveRight, так как они объявлены в одном типе TKing. Во втором случае вызванный по правилам наследования метод TChessMan Move был статически связан посредством объявления в типе TChessMan с ложными методами TChessMan.Display и TChessMan.IsMoveRight. Таким образом, для реализации полиморфизма е языке программиро- вания требуются не статическое, а динамическое (во время выпопнения программы) связывание экземпляров объектов с методами, которые поддерживают полиморфические действия 16.6. ВИРТУАЛЬНЫЕ И ДИНАМИЧЕСКИЕ МЕТОДЫ В Turbo Pascal есть два вида методов, которые динамически связываются с экземплярами объектов Методы первого вида называются виртуальными методами, а второго вида — динамическими методами Если виртуальные методы являются уже знакомым по предыдущим версиям языка объектно-ориентированным средством, то динамические методы — это нововведение языка Turbo Pascal версии 7 О сновное различие между ними состоит в том. что для их реализации компилятор внУтРснние та6лииы различной структуры для виртуальных методов — , - ,Т« лииу виртуальных методов), а для динамических методов — ТДМ V Динамических методов) Принцип же динамического связывания у них Далее по тексту в случаях, к виртуальным, и к динамическим "виртуальные" когда описываемые действия будут относиться и методам, будем использовать для краткости терхозн тепммнпллг” м0Пред—я еще двум терминам объектно-ориентированнои 1 С р М И п UJJU1 ИИ л»., Ра""еи связью называется процесс статического связывания методов с реализациями объектов Поздней связью называется процесс динамического связывания методов с реализациями объектов Синтаксически описание виртуальных и динамических методов отличается от статических наличием директивы vixtuai, которая указывается в конце заголовка
267 ооеамн<* 0 среде Turbo Pascal 7 Q ,,,011 при описании объектных тнпоп п^,. LMfnt ставится р оп"с'1нии реализации метола эта Pllpl Кроме того если объявляется виотуйпкыи.л . Lr 10 ’10 «•1кл‘шывлет следхющпе отроения ira ™6° ролительск°'' инп‘ и чення на его дочерние типы ♦ все методы дочерних типов одноимрНим₽ „ ! ,кже обязаны быть виртхальными (статическим™”" рол"тельскими привить виртуальный) метод никогда „осле того как метод стал виртуальным его заголовок не может „сняться в объектах более низкого хровня J еса реализации одного и того же аиртуального метода до.жны быть идентичными, включая число параметров и их типы (Лметим что это ограничение не относится к статическим мчодах, статический метод переопределяющий др\гон отличное число параметров и типы этих параметров) не может может иметь каждый объектный тип имеющий виртхальные методы обязан иметь кон^тр>ктор 76.6.7. Конструкторы 'Л ’Л Конструктор явтепгся специальным типом процедуры которая выпогняет мочальные установки д1я работы механизма виртуальных методов Заметим важный момент перед вызовом нового виртуального метода какого- шбо объекта необходимо вызвать конструктор этого объ- екта Вызов виртуального метода без предварительного вызову констрхк ropi может привести к блокированию системы а проверить ну уровне компиляции корректность вызова динамически связываемых методов невозможно Каждый отдельный экземпляр объекта должен быть инициализиро- ван отдельным вызовом конструктора Оператор присваивания только к-нирчет значения объектов но не выполняет иннииатпзаиию Поэтому См hi инициализировать один экземпляр объекта и затем присвоить этот экземпляр другому объекту то при вызове виртуальных методов второго ооъекта произойдет блокировка системы Отметим что в качестве имен конструкторов объектов также как и для процедур инициализации рекомендуется испозьзовать идентификатор Init Таким образом если нам требхется сделать методы TChessMan Мохе И hessMin Displax TChessMan IsMoxeRrght виртхальными то проиедхра инициализации Init должна быть преобразована в коистрхктор после чего описание hinoB TChessMan и Thing будет иметь такой вид Шахматная фигуоа } TChessMan = object ( TPoextxon ) private Colour TColour Present Boolean . constructor Init ( ci TCoIubhs Rw TRows EW TColour procedure Put( Nene String ) public function GetColour TColour function IsPresent Boolean procedure Clear procedure Del
266 >п,1янтир<^внмвя , Методы Display, IsMoveRight, Move сдспэнн виртуальными ... procedure Display, TColumns; function IsMoveRlg Rw(. TRows > : Boolean, procedure Move ( Cl: TColumns; Rw, TRows); end; virtual. { Король } TKina = object ( TChessMan ) constructor Xnit (Cl: TColumns; Rw; TRows; BW: TColour); ( Метод Move исключен ( Методы Display, IsMoveRight сделаны виртуальными ! I function procedure end; IsMoveRight ( Cl: TColumns; Rw: TRows ) : Boolean; virtual; Display; virtual; Как видно, метод Move в этом случае все-такн остался общим и описан в типе TChessMan, а индивидуальные для каждой фигуры методы проверки корректности хода IsMoveRight и вывода своего изображения на экран Display, помимо типа TChessMan, описаны и в типах фигур (в частности, в типе TKing), также как это было сделано в примере с ошибкой. Но сейчас методы Move, Display и IsMoveRight объявлены как виртуальные, в результате чего при работе с объектами будет выполняться не статическое (раннее), а динамическое (позднее) связывание При использовании виртуальных методов структура экземпляра объекта типа TKing в исходном состоянии будет иметь следующий вид: Объект WKg Column Row Colour Present GetColumn адрес TPosition. GetColumn Наследуется GetRow адрес TPosition.GetRow Наследуется GetCoords адрес TPosition.GetCoords Наследуется ErrorMessage адрес TPosition, ErrorMessage Наследуется Put адрес TChessMan.Put Наследуется Статические GetColour адрес TChessMan. GetColour Наследуется методы IsPresent адрес TChessMan,IsPresent Наследуется Clear адрес TChessMan.Clear Наследуется Del адрес TChessMan.Del Наследуется Init адрес TKing.Init Конструктор Display Move —► Виртуальные IsMoveRight методы Заметим, что для виртуальных методов статически только выделяется память для адресов, а сами адреса будут занесены в ячейки в процессе установленн0 плииик связи при вызове конструктора TKing Init. После выполнения оператора
WKg.Init ( 'e',l.WhitcColour ); цкт)ра экземпляра объекта примет такой вид Column Roh Colour Present GetColumn GetRow GctCoords ErrorMessage Put GetColour IsPresent Clear Del Init Display Move IsMoveRight Объект WKg___________ ‘е’ WhiteColour True адрес TPosition.GctColumn адрес TPosition.GetRow______ адрес TPosition.GetCoords адрес TPosition. ErrorMessage адрес TChessMan.Put_________ адрес TChessMan. GetColour адрес TChessMan.IsPresent адрес TChessMan.Clear_______ адрес TChessMan.Del_________ адрес TKing.Init____________ адрес TKing.Display_________ адрес TChessMan.Move (!) адрес TKing.IsMoveRight Наследуется Наследуется Наследуется Наследуется Наследуется Наследуется Наследуется Наследуется Наследуется Статические методы Конструктор методы Ках видно из рисунка, в экземпляре объекта находятся адреса тех же са- методов TChessMan Move, TKing Display и TKing IsMoveRight, что и в рас- ренном ошибочном случае. Однако теперь, благодаря виртуальности методов Move Display и IsMoveRight, в результате поздней связи метод TChessMan Move автома- тически настраивается на вызов методов Display и IsMoveRight из типа TKing, а не из типа TChessMan, как было при ранней связи1_______ Таким образом, цепочка вызовов методов будет снова правильной, хак в юм первом рассмотренном случае WKg. Move I TChessMan.Move (!) I rKtng. IsMoveRight (!) TChessMan.Clear TKing.Display (!) Корректная проверка ошибочных ходов Вывод символов "kg"
270 пл^^но-ори^ированнп» м*тодопояин разработку но —" °ТХЛр= одГи=Х и^> срс№™Хек"иекнтиро0анного программирования - полиморфизм. '"' 76 6 2 Отличие виртузльных и динамических методов Как упоминалось выше, динамические методы являются нововведение^ языка Turbo Pascal 7.0 и отличаются от виртуальных, в основном, структур внутренних таблиц компилятора. Если сказать точнее, то динамические методы - это нововведение ддя платформ, работающих в DOS, а для платформы Windows таковым не являются, поскольку уже использовались в Turbo Pascal for Windows. Динамические методы отличаются от виртуальных методов способом диспетчеризации на этапе выполнения. Для динамических методов компилятор вместо таблицы виртуальных методов (ТВМ) строит таблицу динамических методов (ТДМ) Применение ТДМ уменьшает размер памяти, используемой прикладной программой при работе с объектами. Однако программа при этом будет работать медленнее. Во всех других отношениях динамические методы считаются эквива- лентными виртуальным. Синтаксически, в отличие от виртуальных, для динамических методов в заголовке дополнительно указывается индекс динамического метода, который располагается непосредственно за ключевым словом virtual Индекс динамического метода должен быть целочисленной константой в диапазоне от 1 до 656535 и, кроме того, не должен повторяться среди индексов других динамических методов, которые описаны в данном объектном типе и/или его родительских типах. Пример описания заголовка динамического метода: procedure Move ( Cl: TColumns; Rw: TRows); virtual 77; При переопределении динамического метода в дочернем типе, его заголовок, также как и для виртуальных методов, должен быть идентичен заголовку в родительском типе, включая индекс. 16.7. ДИНАМИЧЕСКИЕ ОБЪЕКТЫ Сразу подчеркнем, что не следует путать динамические методы и динамические объекты Динамические методы могут присутствовать как в динамических, так и в статических объектах. В рассмотренных до сих пор примерах все экземпляры объектов были статическими, так как переменные объектных типов WKg. BKg были объявлены в разделе ver как статические, и память под них была выделена один раз в начале работы программы Средства языка Turbo Pascal позволяют описывать также и динамические экземпляры объектных типов, которые определяются в разделе var аналогично динамическим переменным любых других типов, а память под них выделяется теми же процедурами New и Dispose Таким образом, с одинаковым успехом можно вместо статических объектов WKg. BKg TKing,
’orho 7 о "" " ----------- ---------------------------271 1К’ПОЛ1ЛОП.1Т1, укаттсли на var PWKg, PBKg ATKing, При использовании динамических объект™ « „таксисом процедур New и D.spose ° МОбН° работать с Первое расширение синтаксиса касается того, что New разрешается вызывать не то1ько как процедуру, но и как функцию Например, следующая Тапись коррёХна type PTKing = ATKing, PWKg, PBKg: PTKing; begin PWKg := New(PTKing) , PBKg •= New(PTKing) , end Согласно второму расширению синтаксиса процедуры New, в ее записи разрешается использовать второй параметр Этот параметр служит для указания в процедуре New имени конструктора с фактическими параметрами, который инициали- зирует динамический объект сразу же, как только для него была выделена область памяти Например, для инициализации королей и вывода их на экран вместо фрагмента New (PWKg), PWKgA Init ( ' e',l,WhiteColour )), PWKgA Display, New (PBKg), PBKgA.Init ( ’e’,8,BlackColour )), PBKgA.Display, можно записать такие операторы New (PWKg,Init ( ’e',1,Whitecolour )), PWKg* Display, New (PBKg,Init ( 'e' ,8,BlackColour )) PBKgA Display, New Расширение процедуры Dispose аналогично втором) расширению Отличие состоит в том, что вторым параметром является имя не стр а деструктора Dispose(PWKg, Done) Dispose(PBKg, Done),
272 ^т^>ттиро^ ^тоОоноттрн^^^ 16.7.1. Деструкторы Деструктор - дак> также, как и конструктор, специатныи ти) мета)а по-другом}' еще называют "сборщиком мусора ' Деструкторы объявляются с использованием ключевого слова de вместо слова procedure и гтредиазмачены для удаления динамически объектов и освобождения занимаемой ими памяти Как правило объединяет все действия по освобождению памяти так, чтобы очистку выполнить за один вызов деструктора. Для каждого объектного типа п»и димости, может быть создано несколько деструкторов, которые выполняют памяти различными способами 0чИст^ О Аналогично конструкторам, для которых в каждом типе реком 11 использовать одинаковый идентификатор Init, для всех деструкторов ое Снл^* использовать имя Done Таким образом, тип TKing для работы с динами^^ объектами должен быть расширен еще одним методом — деструктором Оопе^''1' ПР' сРС 1)11 чего примет такой вид. { Король ) TKing = object ( TChessMan ) constructor Init (Cl: TColumns; Rw: TRows; BW: TColour); function IsMoveRight ( Cl: TColumns; Rw: TRows ) : Boolean; virtual; procedure Display; virtual; destructor Done; end; Деструкторы могут быть как статическими, так и виртуальными, и их разрешается наследовать Поскольку для различных типов объектов чаще всего требуются различные методы освобождения памяти, то рекомендуется всегда объявлять деструкторы виртуальными, благодаря чему для каждого типа объекта будет выполнен правильный деструктор Так, если реализовывать динамическими объектами все шахматные фигуры, то для них можно объявить общий деструктор в их родительском типе TChessMan. сделав его виртуальным ( шахматная фигура t TChessMan = object ( TPosition ) private Colour TColour; Present Boolean, constructor Init ( Cl: TColumns; Rw: TRows; BW: TColour procedure Put( Name : String ); public function GetColour TColour, function IsPresent Boolean, procedure Clear, procedure Del, procedure Display, function IsMoveRight ( Cl TColumns, Rw TRows ) Boolean, virtual; virtual, procedure Move ( Cl TColumns; Rw TRows) . destructor Done, end. virtual, virtual.
,ымиро«анив в среде Turbo Pascal 7 о 273 D ЦрН необходимости же какой либо фигуре имен ,, ато можно сделать объяви» в типе этой фигуры свой riX?'"”'''11 tRopuu’K фсгрукторы имеет смысл использовать ™ тетке памяти занимаемой динамическими объектами Х объе|сгами ,ь,ьныс действия которые гарантируют 6«™°PU °кь,полняЮ1 такое число байтов Особенно эффективна работа лестп/Х ос“о6ожлаться 11 полиморфических объектов С1^' торов при очистке Для освобождения памяти объектов, созданных при позднем связывании Пктор требуется вызывать используя расширенный синтаксис процедуры se Вызов деструктора вне процедуры D.spose не выполнит никакой очи™ |ТИ Блок операторов деструктора часто бывает пустым destructor TChessMan Done begin end В этом случае при вызове деструктора выполняются только его стандартные ci темные функции называемые эпилогом Работа эпилога заключается в поиске по таблице ТВМ (ТДМ) значения размера памяти занимаемой экземпляром объекта на который ссылается указатель записанный в процедуре Dispose и в пересылке этого значения процедуре Dispose Таким образом процедура Dispose освобождает правильное число байтов независимо от того ссылался ли указатель на экземпляр родительского типа или на экземпляр дочернего 16.8. СОВМЕСТИМОСТЬ ОБЪЕКТНЫХ ТИПОВ Вследствие применения при работе с объектными типами нового по сравнению с традиционными типами механизма наследования правила совместимости для них (объектных типов) также отличаются — ----- Основной принцип совместимости объектных типов состоит в том, что совместимость расширяется по направлению от нижних уровней иерархии объектов к верхним уровням (от потомков к родителям) Другими словами, объекты дочерних типов могут свободно испо1ъзоваться вместо объектов родительских, но не наоборот Кроме того, любой дочерний тип насле- дует совместимость всех своих родительских типов Совместимость объектных типов бывает трех видов • между экземплярами объектов • между указателями на экземпляры объектов • между формальными и фактическими параметрами 16 8 1 Совместимость между экземплярами объектов Объекту родительского типа можно присвоить экземпляр любого из [ * его дочерних типов Обратные присваивания недопустимы
Например. Д.ЧЯ рассматриваемого шахматного примера при объЯШ1ени>|)1 vax , Ро9 • TPosition, 04 TChessMan, икд TKing; допустимы следующие присваивания Ров := СМ; Ров :« WKg» СМ \« WKg; и не допустимы такие WKg .» CM; WKg := Ров; См :» Pos; При этом в правильных операторах присваивания из источника в приемник будут копироваться только поля, являющиеся общими и для объекта родительского типа, и для объекта дочернего типа Смысл совместимости объектов в том, что в результате выполни ния присваивания все информационные поля объекта-приемника стоящего в левой части оператора присваивания, должны получить значения Если же разрешить присваивание объектов родительских типов объектам дочерних, то те информационные поля, которые были добавлены в дочернем объекте по сравнению с родительским, останутся незаполненными А это может привести к непредсказуемым последствиям на этапе выполнения Поэтому такие присваивания запрещены 16.8.2. Совместимость между указателями наэкземпляры объектов Совместимость типов между указателями на экземпляры объектов работав также как и между экземплярами объектов, и подчиняется тем же общим правилам 1 Указатель на объект дочернего типа может быть присвоен указатет ма объект родительского типа Обратные присваивания также, как [ранее недопустимы 16.8.3. Совместимость между формальными и фактическими параметрами Правила совместимости типов при передаче параметров аналогична вышеописанным 1 Формальный параметр (либо параметр-значение либо ларематр-пв- ременная) данного объектного типа может принимать в качестве *' фактического параметра объект своего же типа или объекты всех - — своих дочерних типов
жирование в cpedo I urbo Pascal 7 о 275 lp„ ,том следует помнить различие механизм ,ры значения) и по адресу (параметоы-пепеме™! "ерСМЧИ по значению Нормальный параметр-переменная является * , мый в качестве параметра объект Указателем на фактический, Формальный параметр-значение объектного ,ра которая включает только те п™ ХыеТхХТт^ф^ЧССКОТ° ..... уналогично, если формальный параметр ямяетго Ф-1 ?иаГеТР МОЖеТ бЬ1ТЬ этот ™п обХНил™П„а°^&й 16.9. ПРИМЕР-УПРАЖНЕНИЕ ПО ОБЪЕКТНО-ОРИЕНТИРОВАННОМУ ПРОГРАММИРОВАНИЮ В качестве примера объектно-ориентированного программирования ниже приводится текст модуля ChessMod, являющийся “заготовкой” для написания игровых программ написания игровых прогамм иа шахматную тематику Заметим что i ыбор “шахматного’ примера в таком примитивном виде продиктован не желанием "помериться силами’ с фирмой Borland, которая программу игры в шахматы включила в дистрибутив пакета Borland Pascal with Objects, а просто стремлением дать читателю тематически интересную задачу для самостоятельного из\чсния объектно-ориентированных концепции В качестве начальных шагов усовершенствования предложенной “заготовки Ш1ХМГГ можно предложить следующее I) вместо текстового режима использовать графический, 2) нарисовать красивые фигуры 3) написать правила корректности хода (функции IsMoveRighi) для каждой * ЧЫ 4) создать параллельную иерархию объектных типов для хранения позиций на а и перелапать текущую позицию в методы Move и IsMoveRight для выполнения > ктного хода согласно текущей позиции 5) расширить методы lsMoveR>ght для каждой фигуры проверками с учетом ₽- тожения фигур _____________________________ unit ChessMod I В модуле демонстрируется использование виртуальных I { методов । interface гур« . 1 Типы координат на доске ) TColumns » 'л' ’h’« TRows «10, TColour - (WhitmColour. BlackColour) n su-кия на доске ) TPosition • object f private Column TColumns Row TRows ________________________
Объектно ориентированная методология разработ1(, 276 precede init ( Cl TColumns Rw procedure GetCoords ( var X, x procedure ErrorMessage ( Mes public function GetColumn TColumns function GstRow TRows TROWS ) Word ) String ) end { Шахматная фигура } TChessMan = object ( TPosition ) { Добавлены методы Move и IsMoveRight 1 1 • } private Colour TColour Present Boolean constructor Init ( Cl TColumns, Rw TRows, BW TColour ) procedure Put( Name String }, public function GetColour TColour, function IsPresent Boolean procedure Clear, procedure Del, ( Методы Display, IsMoveRight, Move сделаны виртуальными ’ ' ' } procedure Display virtual function IsMoveRight ( Cl TColumns Rw TRows ) Boolean virtual procedure Move ( Cl TColumns Rw TRows} virtual end { Король ) TKing = object ( TChessMan ) constructor Init (Cl TColumns Rw TRows BW TColour) { Метод Move исключен ♦’» } I Методы Display, IsMoveRight сделаны виртуальными •*• function IsMoveRight ( cl TColumns Rw TRows ) Boolean, virtual procedure Display virtual end ( Королева (Ферзь) ) TQueen - object ( TChessMan ) constructor Init (Cl TColumns Rw TRows BW TColour) ( Метод Move исключен I И ) Методы Display, IsMoveRight сделаны виртуальными 1'' function IsMoveRight ( ci TColumns Rw TRows ) Boolean virtual procedure Display virtual end
Луцп> р upwyg I МГРО Pascal 7 О I Ладья i ' ~ --- । Tcastle - object ( TChessMan ) constructor Init (Cl TColumns Rw _ KW TRows BW TColour) ( Метод Move исключен ... i j Методы Display, IsMoveRiaht 9 t сделаны виртуальными >»t j function IsMoveRight ( ci TColumns . Rw TRows ) procedure Display end, Boolean virtual virtual < Слон ) TBishop = object ( TChessMan ) constructor Init (Cl TColumns rw TRows BW TColour) { Метод Move исключен • i i } ( Методы Display, IsMoveRight сделаны виртуальными 1 *t } function IsMoveRight ( Cl TColumns Rw TRows ) Boolean virtual virtual procedure Display end { Конь } TKnight = object ( TChessMan ) constructor Init (Cl TColumns Rw TRows BW TColour) { Метод Move исключен ' ’ ' ) сделаны виртуальными { Методы Display, IsMoveRight function IsMoveRight ( Cl Rw procedure Display end TColumns TRows ) Boolean virtual virtual ( Пешка ) TPawn = object ( TChessMan ) constructor Init (Cl TColumns Rw TRows BW TColour) { Метод Move исключен •!• ) ( Методы Display, IsMoveRight сделаны виртуальными function IsMoveRight ( Cl Rw procedure Display end TColumns TRows) Boolean virtual virtual WKg WQ WC1 Переменные i BKg TKing BQ TQueen WC2 BC1 BC2 фигур } шахматных { Короли I королевы < Ферзи) ) । TCastle ( Ладьи )
278 пвъ«^т-'0<>Ривип',ироввнмвй мвгТ1од?пОРиа WB1 WK1 WP1, BP1, WB2, wk2, WP2 BP2, BB1, BB2 TBishop ( Слоны I BKl^ BK2 TKnight, { Кони } WP3, WP4, WP5, WP6, WP7, WP8, { Пешки } ВРз' BP4, BP5, в₽6' B₽7' ВР8 ТРа*«, impi emen ta 11on { Реализация методов } uses Crt, Dos, ( Объект Tposition } procedure TPosition Init ( Cl TColumns, Rw TRows ), begin Column = Cl; Row = Rw, end, function TPosition GetColumn TColumns , begin GetColunin = Column, end function TPosition GetRow TRows, begin GetRow » Row, end procedure Tposition GetCoords( var X, Y Word } const BagX = 20, BegY = 23, StepX = 7, StapY = -3, begin X = BegX + StepX * (Ord ( Column ) - Ord (’&’>>, Y = BegY + StepY * ( row - 1 ), end procedure TPosition ErrorMessage ( Mes String ) const BegY =23 begin GotoXY ( 1, BegY ), TextBackGround (Blue), Textcolor ( LightRed + Blink ), Write ( Mes ) end I Объект TChessMan } constructor TChessMan Init ( Cl TColumns, Rw TRows BW TColour ) begin inherited Init (Cl, RW > Colour = BW, Present « True end
279 „.MUcoeSNue в среде Turbo Pexnel 7 n M*.—- function TChessMan GetColour begin GetColour = Colour, end, function TChessMan IsPresent Boolean; begin IsPresent = Present, end, procedure TChessMan Del, begin Clear, Present » False, end, procedure TChessMan Display, begin Put ( 'CM' ), end procedure TChessMan Clear, £>egin Put ( ' ’ ) ErrorMessage ( ' ' ), end, procedure TChessMan Put( Name String ), var X, Y Word, begin GetCoords (X, Y ) , GotoXY (X, Y ) , if (Row + Ord (Column) > mod 2*0 then TextBackGround (Black) else TextBackGround (White) ) end Write ( Name ) end procedure TChessMan Move begin if IsMoveRight (Cl Rw) then begin Clear Column « Cl Row • Rw, Display end elee ErrorMessage ( 'Невермьм end
280 Объектно-ориентированная методология рвзработки function TChessMan.IsMoveRight; begin IsMoveRight :« True; end; { Объект TKing } constructor TKing.Init (Cl: TColumns; Rw. TRows; BW: TColour); begin inherited Init (Cl, Rw, BW ) ; end; function TKing.IsMoveRight ( Cl: TColumns; Rw: TRows ) : Boolean; var DeltaCl, DeltaRw : Word; begin DeltaCl := Abs (Ord(Column)-Ord(Cl)); DeltaRw := Abs (Row -Rw); if (DeltaCl > 1) or (DeltaRw > 1) or (DeltaCl = 0) and (DeltaRw = 0) then IsMoveRight := False else IsMoveRight := True end; procedure TKing.Display; begin Put ( ’Kg’ }; end; { Объект TPawn } constructor TPawn.Init (Cl: TColumns; Rw: TRows; BW: TColour); begin inherited Inxt ( Cl, Rw, BW ) ; end; function TPawn.IsMoveRight ( Cl. TColumns; Rw: TRows) : Boolean,- var DeltaCl, DeltaRw : Integer; begin DeltaCl -Abs (ord(Coluam) - Ord(Cl)); DeltaRw •» Rw - Row; IsMoveRight : False,- case Colour of Whitecolour : If ( D.ltaRw-l ) and ( DeltaCl<2 ) or Row-2 ) and ( Deltacl=0 ) and ( DeltaRw*2 ) than IsMoveRight : True- Blackcolour : if ( DeltaRw—1 ) and ( DeltaCl<2 ) or ( Row-? ) and ( DeltaCl-0 ) and ( DeltaRw—2 ) then laMoveRlght - True; end end;
в среде Turbo Pascal 7 О ’procedure TPawn Display begin Put ( ’P' ) end { Объект TQueen } constructor TQueen Init (Cl TColumns, Rw TRows, begin BW TColour) inherited Init ( Cl, RW, BW ) end, function TQueen IsMoveRight ( ci TColumns, Rw TRows ) Boolean begin IsMoveRight = True, end, procedure TQueen Display, begin Put ( ’Q1 ) , end, { Объект TCastle } constructor TCastle Init (Cl TColumns, Rw TRows BW TColour), begin inherited Init ( Cl, Rw, BW ), end, function TCastle IsMoveRight ( Cl TColumns Rw TRows ) Boolean begin IsMoveRight = True, end procedure TCastle Display, begin Put ( 'C ) end ( Объект TBishop ) constructor TBishop Init (Cl TColumns Rw TRows BW TColour) begin inherited Init ( Cl Rw BW ) end function TBishop IsMoveRight ( Cl TColumn» Rw TRows ) Boolean, begin IsMoveRight » True end
Объвктно-ориентироввннвя методопозия^взрвботхи 282 ---procedure TBishop” Display, begin Put ( *B' ), end, { Объект TKnight ) constructor TKnight Init (Cl TColuans, Rm TRows, BW TColour), begin inhen ted Ini t ( Cl, RM, BW ) , end, function TKnight IsMoveRight ( Cl TColunns, Rw TRoms ) Boolean, begin IsMoveRight = True end, procedure TKnight Display, begin Put ( 'K' ), end, procedure BoardPicture, const BegX =20 BegY =24 StepX - 7, StepY = 3 var EX, BY Byte, i, j Byte, procedure Cell( X, Y, BW Byte ) var j Byte begin TextBackGround (BW), /or J = t to Y+stepY do begin GotoXY (X,j) Write ( ) end end begin *OT 3 e8 downto 1 do begin for x -1 to В do it (i«l) mod 2 » 0 then Call (BegX-3«(i-l)«StepX BegY-j«3tepY«l Black) endSls“ Cel1 <BegX-3+ (1-1) «StepX, BogY-j«StepY+l, White) GotoXY (BegX-3, BegY+1) TextBackGround (Blue) TextColor ( Yellow )
for j eg begin --° срвйо т^о Р--~. GotoXY (BeaX-s « Write (j X) ' ®9Y~^*StepY+2) end, end. procedure SetCursorSize (b=„t — Reg. Begiste'sy"a“B« BYte) begin VI th Regs do b&gu АЬ =$01, CH =BegLine, -L “EndLine end. Intr($10 Regs) end procedure Hidecursor ( Спрятать var BegLine, EndLine Byte курсор } begin BegLine = $20, ( $20 в качестве значения начальной > EndLine = ( линии делает $00, курсор невидимым } SetCursorSize(BegLine, EndLine ) end. begin { Начальная расстановка фигур } TextBackGround( Blue ), ClrScr HideCursor { Спрятать курсор } Boardpicture ( Белые фигуры } WKg Init ( 'е•,1,WhiteColour WKg Display WQ :ni t ( 'd1,1,WhiteColour WQ Display WC1 Init ( 'а',1,Whi teColour WC1 Display WC2 Init ( ’h1,WhiteColour WC2 Display WK1 Init ( ’b1,WhiteColour WK1 Display WK2 Init ( 'д',1,WhiteColour WK2 Display WB1 Init ( 1c’,1,WhiteColour WB1 Display WB2 Init ( 'f•,1,WhiteColour WB2 Display WP1 Init ( 2,WhiteColour ; WP1 Display WP2 Init ( b’ 2 WhiteColour ; WP2 Display WP3 Init ( c,2,WhiteColour ) WP3 Display WP4 Init ( ’d' 2 WhiteColour ) WP4 Display WP5 Init ( <e‘ 2 WhiteColour ) WP5 Display HP 6 Init ( f 2 WhiteColour ) WP6 Display WP7 Init ( 'g' 2,WhiteColour ) HP7 Display HP 8 Init ( ’h',2,WhiteColour ) WPS Display < Черные фигуры » BKg Init ( ’o' 9 BlackColour > BKg Display ( -d’ 8 BlsckColour ) BQ Display BC1 Init ( <a’ 8,BlackColour ) BC1 Display BC2 Init ( 1 h',9,BlackColour ) BC2 Display
г^ъектно-ориенгпироеемнея метпдопогия рвУрпботки 284 BK1.Init ( BK2.Inxt ( BBl.Init ( BB2.Inxt ( BPl.Inxt ( BP2.Inxt ( BP3.Init ( BP4.Inxt ( BP5.Inxt ( BP6.Init ( BP7.Init ( BP8.Init ( end. <b’,8,BlackColour 1 g' ,8,BlackColour <c',8,BlackColour if,8,BlackColour -a’,7,BlackColour < b ’ , 7 ,BlackColour •c',7,BlackColour -d',7,BlackColour 'o',7,BlackColour •f•,7,BlackColour 'g',7,BlackColour h',7,BlackColour ), BK1.Display, ), BK2 Display; ); BB1.Display; ); BB2.Display; ); BP1.Display; ); BP2.Display; ); BP3.Display; ); BP4.Display; ); BP5.Display; ); BP6.Display; ); BP7.Display; ); BP8.Display; В качестве примера приведем также программу, использующую модуль ChessMod, которая выполняет несколько ходов пешкой и белым королем Процедуры Readln добавлены для удобства наблюдения за выполняемыми ходами. program Chess; uses ChessMod; begin Readln; WP5.Move ( 'o', 4 ); Readln; WP5.Move ( 'o', 8 ); Readln; WKg.Move ( 'o', 2 ); Readln; WKg.Move ( *d', 3 ); Readln; WKg.Move ( 'c', 3 ); Readln; WKg.Move ( 'd', 4 ); Readln; WKg.Move ( -o', 3 ); Readln; WKg.Move ( 'f'r 3 ); Readln; WKg.Move ( -o', 2 ); Readln; WKg.Move ( ’o’, 1 Readln; end. Контрольные вопросы L Что такое ООП9 2. С какой целью была создана ОО-методология9 3. Какие существуют принципы управления сложностью объекта? . Что такое декомпозиция и какие существуют разновидности декомпо- зиции? 5. Что такое инкапсуляция9 6. Какая основная цель ОО-методологии9 7. Что такое наследование свойств9 8. Какие типы называются абстрактными9 9. Что такое полиморфизм9 10. Что представляют собой переменные объектных типов9 11. В чем состоят отличия типа “объект" от типа “запись"9
ПрО^р .шмироыни* а среде Turbo Pascal 7 0 285 |2, Что называется методом9 13. В чем состоят отличия описания методов и процедур? 14. Для чего предназначена директива private? 15. Что позволяет директива public? 16. Каковы правила наследования в Turbo Pascal? 17. Для чего предназначено ключевое слово inherited9 18. Какие существуют правила вызова наследуемых методов9 19. Возможна ли реализация полиморфизма статическими методами9 20. В чем сходство и различие виртуальных и динамических методов9 21. Что называется ранней связью? 22. Что называется поздней связью? 23. Чем заключаются синтаксические особенности описания динамических и виртуальных методов? 24. Что такое конструктор? 25. В чем особенности использования конструктора9 26. В чем состоят особенности работы с динамическими объектами? 27. Что такое деструктор? 28. Как объявляются деструкторы? 29. Возможно ли наследование деструктора9 30. Что такое эпилог и в чем заключается его работа9 31. В чем состоит основной принцип совместимости объектных типов9 32. Каких видов бывает совместимость объектных типов9 33. Каковы правила совместимости объектных типов9
ЧАСТЬ 4 СТАНДАРТНЫЕ ПРИЕМЫ РАБОТЫ С УСТРОЙСТВАМИ IBM-PC ГЛАВА 17. РАБОТА С КЛАВИАТУРОЙ, КУРСОРОМ И ЗВУКОМ.... 287 ГЛАВА 18. РАБОТА В ТЕКСТОВОМ ВИДЕОРЕЖИМЕ.294 ГЛАВА 19. РАБОТА В ГРАФИЧЕСКОМ ВИДЕОРЕЖИМЕ.306 ГЛАВА 20. Turbo Pascal И АССЕМБЛЕР.......325
ГЛАВА 17 РАБОТА С КЛАВИАТУРОЙ -КУРСОРОМ и ЗВУКОМ ’ 17.1. КЛАВИАТУРА Все клавиши клавиатуры можно разделить на три группы: 1. Клавиши и комбинации клавиш, нажатие „„ г клавиатуры ASCII-код. ’ Иажатне которых посылает в буфер К таким клавишам относятся буквенно-цифровые клавиши и клавиши специальных символов в обоих регистрах (с Shift и без него) а также комбинации Ctrl+АлфавитноЦифроваяКлавиша и Ctrl+НекоторыеСпецСимволы, которые вырабатывают ASCn-коды управляющих символов (0...31). 2. Клавиши и комбинации клавиш, нажатие которых посылает в буфер клавиатуры расширенный код. К таким клавишам относятся функциональные клавиши, нажатые как самостоятельно, так и в комбинации с любой из клавиш Shift, Ctrl, Alt; буквенно- цифровые клавиши, нажатые в комбинации с Alt, а также некоторые другие клавиши и комбинации. Расширенный код состоит из двух символов: первый — символ с кодом О, второй — ASCH-символ. 3. Клавиши и комбинации клавиш, нажатие которых не посылает в буфер клавиатуры никаких кодов. К таким клавишам относятся клавиши регистров Shift, Ctrl, Alt, CapsLock. NumLock, ScrollLock, а также некоторые комбинации клавиш. Полный перечень ASCII-кодов и кодов, вырабатываемых нажатиями клавиш, приведен в приложениях. Для высокоуровневой обработки нажатия клавиш и организации хорошего диалога между пользователем и программой используются функции KcyPressed и R*-ddKey из модуля Crt. Рассмотрим два часто используемых в диалоговых задачах никла. Первый цикл _ _____ ( Цикл ожидания нажатия любой клавиши ) repeat until KeyPressed; приводит к ожиданию нажатия любой клавиши, вырабатываю шеи код, при у • что буфер клавиатуры пуст (т. е. KeyPressed = False) Если же уфер клаi и содержит хотя бы один код (т е KeyPressed = True), то этот цикл не ри каким действиям и управление передается следующему за ним оператору. Таким образом, чтобы можно было корректно использовать циклы Нажатия клавиш, необходимо предварительно очишать буфер клавиатур’ случайно нажатых пользователем клавиш Для этого применяется в р Ц следующего вида.
Работа с клавиатурой курсор^ 288 var ch ; Char; begin ( Цикл очистки буфера клавиатуры ) w-hlle KeyPressed do Ch := ReadKey; end. В качестве примера обработки нажатий алфавитно-цифровых клавиш рассмотрим простейшую программу, которая реагирует только на нажатия буквенных клавиш с символами -‘Y”, “У” и на нажатие клавиши Esc . program KeyBoardl; uses Crt; var Ch : Char; begin ClrScr; (очистка экрана) repeat (до нажатия "Esc") while KeyPressed do Ch: =ReadKey; (очистка буфера клавиатуры} Writein(' Нажатие клавиш, кроме "Y" , "у" и "Esc"’}; Writein ('не приведет ни к каким действиям. ') ; Writeln(’ Нажатие клавиш "У" или "у" повторно 1) ; Wrxteln(’выводит этот текст. ') ; Wrxteln(' Нажатие клавиши "Esc" заканчивает 1) ; Wrxteln('программу!'); Writein; repeat (до нажатия "Y" , "у" или "Esc") Ch := ReadKey; until Ch in [’Y', 'y', #27(Esc)]; until Ch = #27; (Esc) whxle KeyPressed do Ch := ReadKey; (очистка буфера клавиатуры} Wrxteln('Для завершения программы нажмите любую’); Wrxteln('клавишу ...'); repeat until KeyPressed; (ожидание нажатия клавиши) end. Для демонстрации обработки расширенных кодов клавиш, п программу, которая реагирует на нажатия клавиш-стрелок и функцио! клавиш F1-F10, а нажатия остальных клавиш игнорирует. program KeyBoard2; uses Crt; var Ch Char; ExtendedKay Boolean;
,pflMMUp°eBHUe 8 среде Turbo Pascal 7 p 289 t>egin ClrScr; (очистка экрана) while KeyPressed do Ch:=ReadKey; (очистка буфера клавиатуры) WrxtelnCПрограмма реагирует на нажатия только’) ; Vfrxteln (’клавиш-стрелок и функциональных'); Writeln('клавиш F1-F10’); Writein(‘Выход по клавише F10'); Writein(’Нажимайте клавиши ...'}; Writein; Writein; repeat (до нажатия F10) ExtendedKey •. «False; (флаг поступления расширенного кода) Ch:=ReadKey; (считывание кода новой нажатой клавиши} if Ch « #0 then (если "Да" - код расширенный} begin Ch •. «ReadKey; (считывается второй символ расширен- ного кода} ExtendedKey:=True; (флаг поступления расширенного кода) end; if ExtendedKey then (если код был расширенный} case Ch of #75: : Writein('Нажата стрелка "влево" '); #77: : Wrxteln('Нажата стрелка "вправо" '); #72: : Writein('Нажата стрелка "вверх" '): #80. : Writein(’Нажата стрелка "вниз" ’); #59..#68: ; Wrxteln(’Нажата F', (Ord(Ch)-58);1); end; (Ch = #68) and ExtendedKey; нажата F10) until ___, Wrxteln (’Демонстрация нажатия клавиш закончена.'); Wrxteln('Jln« завершения программы нажмите любую клавишу while KeyPressed do Ch:=ReadKey. (очистка буфера клавиатуры} (ожидание нажатия клавиши) repeat until KeyPressed, end. 17.2. КУРСОР Для организации красивого интерфейса между пользователем и программой на требуется изменить форму курсора (сделать утолщенным, величиной в целый (! *шол или же вообще сделать его невидимым) Каждый символ растрового шрифта, каким является системный шрифг I >юного режима, изображается в пределах определенной матрицы 8-8 или 8 -14 Курсор, также как и символы, изображается из одной или нескольких строк матрицы шрифта Линии сканирования нумеруются сверху вниз, начиная с 0 Таким образом, курсор, например, для шрифта 8’8. может иметь восемь различных форм
работа с клавиатурой кург.прои 290 Формы курсора промежуточной толщины Установка формы курсора выполняется с помощью предопределенного типа Registers, дающего доступ к регистрам процессора, и стандартной процедуры Intr из модуля Dos. type Registers = record case Inrteger of 0: (AX, BX, CX, DX, BP, SI, DI, DS, ES, Flags: Word); 1: (AL, AH, DL, DH, CL, CH, DL, DH: Byte); end; Для установки формы курсора требуется в регистр АН занести код функции S01 прерывания S10, в регистр СН занести номер начальной линии сканирования, в регистр CL — номер конечной линии сканирования и вызвать прерывание $10 с помощью процедуры Intr. Таким образом, требуемая процедура будет иметь вид procedure SetCursorSize (BegLine, EndLine: Byte); var Regs: Registers; begin with Regs do begin AH:=$01, CH.=BegLine; CL:^EndLine. end; Intr($10,Regs). end; Для установки курсора стандартной и максимальной формы могут быть Предложены такие процедуры
/9? в ГмгЬе pg5r?< ? $ I 14 I мнлартног<> курсор,! procedure Standardcursor; var BegLine, EndLine • Byte, begin if LastMode=Mono then begin BegLine=$0B, EndLine:~$0C; end else begin BegLine.—$06; EndLine:=$07 , end; SetCursorSize(BegLine, EndLine); end; Для максимального курсора: procedure Maxcursor; ' ' — var BegLine, EndLine : Byte; begin BegLine.=$00; rf LastMode=Mono then EndLine-=$0C else EndLine:=$07; SetCursorSize(BegLine, EndLine) , end; Следующая процедура делает курсор невидимым procedure Hidecursor; var BegLine, EndLine : Byte, begin BegLine:=$20; ( $20 в качестве значения начальной } { линии делает курсор невидимым } EndLine:=$00; SetCursorSize(BegLine, EndLine) ; end; 17.3. ЗВУК Для создания звуковых эффектов используются процедуры Sound NoSound и Delay из стандартного модуля Сп procedure Sound ( Hz integer }, Параметр Н/ процедуры S° v’t ^Оип7™н Хдуюшего^ 1зова процедуры ;Zd НоСХв“ гХ— старый звук и задает звук с ново, -'гот.)и указанной параметром Н/
Работа с клавиатурой, курсоре,^ 292 procedure NoSound; Процедура NoSound прекращает звучание динамика. Если эта проце программе не вызывается, то звучание сигнала не прекращается по оком в программы. Звук прекращается только процедурой NoSound. ании procedure Delay ( MSec : integer ) ; Процедура Delay задерживает работу программы, а соответственно и звучание на число миллисекунд, указанное параметром Msec. Приведем два примера, демонстрирующих простейшие звуки, которые можно извлечь из динамика компьютера с помощью процедур Sound, NoSound, Delay Первый пример демонстрирует звук занятого телефона. program PhonelsBusy; { Звук занятого телефона } { Константы подобраны для } { процессора 486DX2-66 } uses Crt; var I •. Integer; begin repeat { Продолжать сигнал до нажатия ) ( любой клавиши ) for I := 1 to 100 do { Этот цикл с кратковременным ) { выключением звука процедурой ) { NoSound создает эффект дре- ) { безжамия звука. } begin Sound{400); Delay(4); NoSound; end; Delay(600); until KeyPressed; end. Во втором примере последовательно извлекаются звуки частот от 100 Гц до 3000 Гц, и обратно В результате получается сигнал, напоминающий звучание сирены program Test_Sound: uses Crt; var I : Integer; begin repeat for I .» 100 to 3000 do
293 я еро(у Гифр Pascntm begin '----- Sound(I) Delay(1) r end, for I := 3000 downto 100 do begin Sound(I); Delay (1) ; end; until KeyPressed; NoSound; end. Контрольные вопросы 1 На какие группы можно разделить клавиши клавиатуры’ 2 Какой вид имеет цикл ожидания нажатия любой клавиши? 3 Какой вид имеет цикл очистки буфера клавиатуры’ 4 Какие особенности обработки расширенных кодов клавиатуры’ 5 Каким образом выполняется установка формы курсора’ 6 Какие процедуры используются для создания звуковых эффектов’ Контрольное задание Написать программу, которая по нажатию семи разных клавиш извлекает из динамика компьютера семь нот музыкального звукоряда, и которая при звучании различных нот устанавливает различную величину курсора (от минимального до максимального) Выключение динамика производить по нажатию клавиши “пробел'1 Частота нот в герцах С = 262 D = 294 Е = 330 F = 350 G = 392 А = 440 Н = 482
ГЛАВА 18 РАБОТА В ТЕКСТОВОМ ВИДЕОРЕЖИМЕ Управление видеопамятью в текстовом режиме выполняется с помощью предопределенных констант, процедур и функций стандартного модуля Crt. Модуль Crt включает также средства для работы со звуком, клавиатурой, таймером. В данном подразделе рассмотрены только средства, касающиеся текстового режима видеопамяти. 18.1. ЭКРАН В ТЕКСТОВОМ РЕЖИМЕ Размеры экрана в текстовом режиме могут быть по горизонтали 80 или 40 позиций, а по вертикали — 25, 43 или 50 позиций в зависимости от типа видео- адаптера, установленного в компьютере, и используемых в конкретный момент параметров текстового режима. Первая координата (X) изменяется по горизонтали слева направо, а вторая координата (Y) изменяется по вертикали сверху вниз. Началом отсчета координат является верхний левый угол, который имеет координаты (1,1). координата X <1-1 > -------------------------------> (МахХ.1) координата V (l.MaxY) (HaxX.MaxV) 18.2. КОНСТАНТЫ ЦВЕТА Константа Значение Black Blue 0 1 ( черный ) ( синий ) Green 2 ( зеленый ) Cyan Red 3 4 ( бирюзовый ) ( красный ) Magenta 5 < малиновый ) Brown 6 ( коричневый ) LightGray Dark Gray 7 8 ( светло-серый ) ( темио-серый ) UghtBlue 9 ( светло-синий )
295 ТифО Pascal ?0 Константа I ightGrccn I >an I ightRod 1 ighlMagenta A eHow White Bllllk 10 12 14 15 128 ---Д*!Должение таблиц. — -Значение "'— ( светло зеленый ) ( светло-бирюзовый ) ( свС '1<ькраснын ) ( скетто-малиповыи ) ( желтый ) ( белый ) ( мерцание) Символы МОГУТ быть любого цвета in '---------- тоико первых восьми ~ от 0-го (Black) до 7 r£ (l,S„Лперечн>' ’ ивет фона - Установка цвета символов выводимых на t„,u TextColor цвета фона, на который будут выводиться '”’"'<>''няется лроиеъРои TcMBackGround. а установка яркости символов п ' " пР°иедаР°" HighVdeo и NormVideo символов - процедурами Lo«v,deo Low Video — устанавливает бит яркости в О HighVideo — устанавливает биг яркости в 1 NormVideo - устанавливает бит яркости в значение которое было перед запуском программы Пример ( синий цвет фона } TextBackGround ( Blue ) { красный цвет символов } TextColor ( Red ) ( белый цвет символов с мерцанием ) TextColor ( White + Blink ) Заметьте что признак мерцания добавляется к цвету енмвоюв как спагаемое Цвет фона мерцать не может Очистка экрана в текстовом режиме выполняется процедурок ClrScr Экран при этом закрашивается текущим цветом фона (если цвет фона не установлен — то черным) Для демонстрации установки цветов может быть предложена такая программ! program TestTextColor uses Crt var TColor BColor Byte for BColor = Black to LightCrey do begin TextBackGround ( BColor ) ClrScr for TColor = Black to White do begin TextColor ( TColor ) Writeln ('Проверка цвет»') end Textcolor ( Tell®* * Blink ) Writeln ('Проверке мерцание )
296 Работа в текстовом Readin ( Задержка картинки на экране ) { до нажатия Enter I end, NormVideo, end __________________________________ Для управления цветами в текстовом режиме вместо вышеописанных процеду. можно использовать предопределенную переменную TextAttr модуля Си Эта переменная имеет тип Byte и в каждый момент времени содержит десятичное значение, определяющее совокупность цветовых атрибутов (цвет символов, цвет фона, мерцание, яркость) Чтобы понять механизм установки цветовых атрибутов, нужно смотреть на значение переменной TextAttr не в десятичной, а в двоичной системе счисления Каждый из восьми битов байта этой переменной отвечает за определенный атрибут Назначение битов переменной TextAttr показано на следующем рисунке Поскольку цвет символов определяется младшими разрядами, то присваивание переменной TextAttr просто значения цвета TextAttr .=4, { Красный } приведет к установке цвета символов указанным значением, черного (нулевого) цвета фона, низкой (нулевой) яркости и отсутствию мерцания (нулевое значение седьмого бита), так как двоичное представление значения TextAttr в этом случае б>дет иметь вид 7 6 5 4 3 2 1 0 |й|в|в|а|а|1|в|в~| Мерц К С 3 Я К С 3 L-H-J L-,------! ФОН символы Атрибуту яркости соответствует двоичное число 1000, которое равно десятичному 8 Заметим, что установка этого атрибута в соответствующее значение при использовании предопределенных констант Black White выполняется автоматически Атрибуту мерцания соответствует двоичное число 10000000, которое равно десятичному 128 При установке цвета фона с помощью переменной TextAtir необходимо принимать во внимание то, что цветовые константы фона имеют значения от 0 до 7, а за цвет фона отвечают не начальные биты, а биты с 4-го по 6-й Поэтому для корректной установки цвета фона нужную константе тух-бхегся помножить на 16 что
Ц| К I U'HI) пичсиич М 1(1 с 4-ГО ПО 6-й Примеры .—... { Цвет фона — синий ) ( Цвет символов — белый ) ( Мерцание — выключено ) (----------- TextAttr ~ 16 * Blue + white; (Фон) (синий) (белый) или то же самое TextAttr := 16 * 1 + 15; (фон) {синий} {белый} или то же самое TextAttr • = 31; 2 { Цвет фона — зеленый } { Цвет символов — красный } ( Мерцание — включено } TextAttr := 16 * Green + Red + Blink; {фон} (зеленый} {красный} (мерцание} или то же самое TextAttr .= 16 * 2 + 4 + 128, (фон} {Зеленый} (красный) {мерцание) или то же самое TextAttr := 164; Общую формулу установки атрибутов можно записать в таком виде ’TextAttr = 16 * ЦветФона + ЦзетСимволов + МерцаниеСимволов 18.3. ОКНА В ТЕКСТОВОМ РЕЖИМЕ j Turbo Pascal позволяет выводить текстовую информацию в рамках не всего Экрана, а только в пределах его определенной части (окна} Для этого служит процедура Window модуля Crt Ял я работы с окнами используются также переменные WindMin и WmdMax Заголовок процедуры Window имеет такой вид procedure Window (XI, JT1, Х2, Т2 Byte), Параметры xi, п представляют собой координаты верхнего левого угла окна, ^раиа1?14 Х2’ Г2 ~ ЭТо КооР'аинаты правого нижнего угла Верхний левый угол соответствует координате (1.1) Минимальный размер текстового окна —
Работа е текстовом 298 один сголбец иа^Х™" НСЛОПУпредопределеПнЫе переменные WmdMin и WmdMax типа Word в сохраняют текущее определение окна W.ndMm хранит координаты верхнего угла текущего окна, a WmdMax нижнего правого угла Координата X сохраняете, младшем байте этих переменных, а координата Y в старшем байте По умолчанию устанавливается размер окна, равный всему экрану, которЬ1и в зависимости от режима видеоадаптера, может быть одним из следующих Константа режима Значение Размер экрана BW40 0 40x25, черно-белый на цветном адаптере СО40 1 40x25, цветной на цветном адаптере BW80 2 80x25, черно-белый на цветном адаптере СО80 3 80x25, цветной на цветном адаптере Mono 7 80x25, черно-белый па монохромном адаптере Font8x8 256 для адаптеров EGA/VGA (43/50 строк) BW40, СО40, BW80 и СО80 представляют четыре цветных текстовых режи ма поддерживаемых цветным графическим адаптером IBM PC Константа Mono представляет единственный черно-белый режим, поддерживаемый монохромным адаптером IBM PC Константа Font8x8 предназначена для включения 43-х или 50-ти строчного режима EGA/VGA и используются совместно с СО80 Видеорежим устанавливается процедурой TextMode, заголовок которой име ет следующим вид TextMode (константа режима), После установки окна процедурой Window большинство процедур и функция модуля Crt (ClrEol, ClrScr, DelLme, GotoXY, InsLine, WhcreX, WhereY. Read Readin, Wnte, Wnteln) будут работать относительно его системы координат Например если в вышерассмотренном примере демонстрации цветов добавить установку окна то цвет и слова будут появляться только в заданных пределах Для установки курсора в требуемую позицию окна с координатами (X V) служит процедура GotoXY, заголовок которой имеет такой вид procedure GoToXY (X, Y Byte), Нетрудно заметить, что экран дисплея представляет собой своеобразную матрицу позиций, в которые заносятся символы Поэтому, для получсмия многих визуальных эффектов необходимо умегь хорошо работать с матрицами (двумерными массивами) вообще (см паву 10) Необходимо всегда помнить что в двумерном массиве первая координа- та изменяет значение вертикали а вторая — горизонтали А а процедуре! GotoXY — наоборот! | Например, выполнив обход по столбцам от середины экрана одновременно в двух направлениях к его краям, можно получить простейший визуальный эффект п laBjioio перекрашивания экрана
299 ^ш««'РР°ание ° сРеЛ> Turbo Pascal 7 р ^rogiem TestGotoXY, uses Crt, Rows = 24; Columns = 80, „ ..^471 RangeX = Columns div 2, — Т» - RangeY = Rows, Msec = 0, ( Количество заполняемых рядов ( Количество заполняемых колонок _, { Диапазон изменения по X { Диапазон изменение «- v ; диапазон изменения по Y { Величина задержки устанавливается { в зависимости от быстродействия { компьютера } procedure NewPicture, begin for 1 begin 3 z к Byte = RangeX down to 1 da k = Columns-i+l, for J = 1 to RangeY do begin GotoXY (i,j), Write (’J1), GotoXY {k,j), Write ('I'), Delay {Msec) end end end Begin TextAttr = Cyan + 16 ♦ Black ClrScr NewPicture repeat until KeyPressed end На компьютерах с быстрым процессором экран может перекрашиваться г ненно Поэтому в циклах добавлена процедура Delay изменяя можно отрегулировать скорость перекрашивания Заготовок имеет стедуюший вил procedure Delay (MSec word) MSrr зияет чист ыиззисекунл задержки ( т*вет также учитывать . I ’ н поэтому период можно выполнить ли по 'спирали •мя^пе в правый нижний угол экрана! < < гтроку вверх а курсор лереко-1 _____________________________I
300 ___________________._ P^onwemexcmonou,^ - ^**4 18.4. ПРЯМОЙ ДОСТУП К ВИДЕОПАМЯТИ Прямой доступ к видеопамяти позволяет увеличить скорость вывод,, информации на экран Прямой доступ к ячейкам памяти вообще и к видеопамяти в частное^, осуществляется с помощью предопределенных массивов Mem MemW Me^L Элементы массива Мет имеют тип Byte, элементы массива MemW — тип wOrd элементы массива MemL тип Longint В качестве индекса в этих массивах используются адресные константы, синтаксис описания которых такой же как и абсолютных переменных (см главу 3) Для указания сегмента и смещения могут быть использованы стандартные функции Seg и Ofs Для доступа к портам процессора в Turbo Pascal реализованы предопределенные массивы Port типа Byte и PortW типа Word, индексы которых имеют тип Word Когда элементам массива Port или PortW присваивается значение, оно выводится в выбранный порт Когда на элементы этих массивов имеются ссылки в выражениях то значение, находящееся в порту, подставляется в точку расположения массива в выражении Для IBM совместимых компьютеров видеопамять в цветном текстовом режиме располагается в ячейках начиная с адреса SB800 0000 а в монохромном режиме - с адреса SB000 0000 За каждый символ изображения отвечает два байта видеопамяти • первый байт содержит ASCH-код символа, • второй байт содержит атрибуты цвета в формате переменной TextAttr Для цветного режима: ASCII-код TextAttr ASCI I-код TextAttr SB800 0000 SB800 0001 SB800 0002 SB800 0003 Если программу предыдущего примера переделать так чтобы запись символов выполнялась непосредственно в видеопамять то она примет такой вид
'и* 9 qp+d* Turbo Pascal 7 о 301 junction Offset ( X,Y ; Byte } I begin Offset 2 * { Columns * {Y-Ц + {X-l) ) end; procedure NewPicture (Color ; Byte); var 1, j, к : Byte; begin for i :« RangeX downto 1 do begin к := Coiumn.s-i+1; for 3 := 1 to RangeY do begin Mem [ScreenSeg : OffSet(i,j)J ;sOrd('|'); Mam [ScreenSeg : OffSet{i,j)+1] ;= Color; Mem [ScreenSeg : OffSet(k,j)] ;sOrd('|'); Mem [ScreenSeg : OffSet(k,j)+1] ;= Color; Delay (Msec) end; end; end; Begin ClrScr; NewPicture (Cyan); repeat until KeyPressed; end. Определение конкретных адресов сегмента видеопамяти для записи элементов ‘нового” изображения в требуемом порядке выполняется с помощью вспомога* гельной функции OffSet Теперь покажем, как алгоритм рассмотренного визуального эффекта можно использовать для смены одной ‘‘картинки” размером в экран на другую “картинку”. Для этого изображение второй “картинки” предварительно подготавливается в отдельном массиве, имеющем размер, соответствующий используемому графическому режиму. Например, для режима 25 строк на 80 колонок размер такого массива в байтах можно вычислить по формуле ScreenSxze = 25 (строк) * 90 {колонок) * 2 (байта); Однако в программах для работы с элементами видеопамяти удобнее использовать такие структуры данных
Paboma в ^сшовомв^ const Rows =25, { Количество заполняемых рядов j Columns =80, { Количество заполняемых колонок } type { Тип символа изображения } TPoint = record Symb, Color Byte end, { Тип массива - образа экрана } TypeScreen = array [l..Rows, 1 Columns] of TPoint, var { Массив — образ экрана } NewScreen TypeScreen После того, как вторая ‘‘картинка’* будет подготовлена в массиве NewSreen останется только присвоить его значения соответствующим ячейкам видеопамяти в том порядке, который требуется для создания визуального эффекта По сравнению с предыдущей новая программа будет содержать дополнительно процедуру вывода на экран “старой" картинки OldPicture и процедур) TormNeuPicture для формирования “нового'* изображения в массиве NewScreen В процедуре же вывода на экран “новой" картинки NewPicture потребуется только заменить присваивания символа на присваивания соответствующих элементов массива NewScreen program ChangeScreen2, uses Crt const Rows = 25 { Количество заполняемых рядов } Columns =80, { Количество заполняемых колонок ) RangeX = Columns div 2, { Диапазон изменения по X ) RangeY = Rows, { Диапазон изменения по Y } Msec =1, { Величина задержки устанавливается ) ( в зависимости от быстродействия } ( компьютера ) ScreenSeg = $В0ОО ( Адрес сегмента видеопамяти } ( в цветном режиме ) type { Тип символа изображения ) TPoint = record Symb, Color Byte end, { Тип массива — образа экрана ) TypeScreen = array fl Rows 1 Coluant) ot TPoint var NewScreen TypeSoreen, ( Массив - образ экрана ) i э, k. Byte, Ch Char
,„иироввмив е сРвде Turbo Pascal 7 О function Offset ( X,Y : Byte ) Word. ( Функция Offset вычисляет последовательный адрес ) ( элемента изображения в видеопамяти по двумерен { координатам 'матрицы" экрана ) begin OffSet end; 2 * < Columns * (Y-l) + (x-j) , procedure OldPicture; const Str : String[Columns] = ’ old picture old picture old picture ’ ; var i Byte; procedure LastSymbol ( S : Char ) ; ( Процедура LastSymbol ставит символ S } ( в правый нижний угол экрана без смещения ) ( изображения ) begin GotoXY(Columns,Rows); Write(S); GotoXY(1,1); InsLine; end; begin TextBackGround(Red); TextColor(Green); LastSymbol(1 ’); Str := Str + Str; for i := 1 to Rows-1 do Write(Str); Delete (Str, Length(Str),1) ; Write(Str); end; procedure FomNewPicture; const Str String[Columns] = 1 NEW PICTURE NEW PICTURE NEW PICTURE 1; var i, 3 ' Byte, begin Str := Str + Str; for i = 1 to Rows do for з =1 to Columns do with NewScreen[i,3] do begin Symb Byte (Str[D)); Color = Yellow + 16 * Blue; end, end
Работа а текстовом еиоп_п 304 _ — ... procedure NewPicture var i,J,Byte begin for i = RangeX downto 1 do begin к = Columns~i+1/ for j = 1 to RangeY do begin with NewScreen [3,1] do begin Mem [ScreenSeg OffSet(i,j)] = Symb, Mem [ScreenSeg OffSet(1,3)+1] = Color end with NewScreen [3, k] do begin Mem [ScreenSeg OffSet(k,3)] = Symb, Mem [ScreenSeg OffSet(k,3)+1] = Color end Delay(Msec) end end end Begin TextAttr = White + 16 * Black ClrScr OldPicture FormNewPicture Ch = ReadKey, { Задержка на экране "старой" картинки NewPicture repeat until KeyPressed end Аналогично можно сделать визуальные эффекты смены картинок по спирали (см программу в главе 10) по диагонали и т п Контрольные вопросы 1 Какие координаты имеют угловые точки экрана в текстовом режиме9 2 Какая процедура предназначена для очистки экрана в текстовом режиме9 3 Какие значения могут принимать константы цвета для символов и для фона9 4 Какова структура байта атрибутов9 5 Как установить окно для вывода информации в текстовом режиме9 6 Какой размер окна устанавливается по умолчанию9 7 Какая процедура предназначена для установки видеорежяма9 8 Какое действие выполняет процедура Delay9 9 С помощью каких средств Turbo Pascal осушестн i^rc« прямой доступ к видеопамяти9 10 В каких адресах располагается видеопамять9
305 rump Ракш 7 о Контрольные задания ; I Цзлислъ процедуру, которая выполняет ввод элементов t 4П1К1Я курсор па экРа,,е Для ввода очередного элемента ,ню этого элемента в матрице матрицы А|К Ч| соответственно А[Ы] А[1,2] ... А[1,8] А[2,1] А[1,2] ... А[2,8] А[8,1] А[8,2] ... А[8,8] Экран монитора 2. Напишите программу, заполняющую окно заданного размера и место- положения символами случайно выбранного цвета1 1) по строкам; 2) по столбцам; 3) по “спирали”; 4) по “змейке” как показано ниже Решите эту задачу двумя способами с использованием процедуры GotoXY и с помощью прямого доступа к видеопамяти
ГЛАВА 19 РАБОТА В ГРАФИЧЕСКОМ ВИДЕОРЕЖИМЕ Работа в графическом режиме выполняется с помощью предопределенных констант, типов, процедур и функций стандартного модуля Graph 19.1. ПРЕДОПРЕДЕЛЕННЫЕ КОНСТАНТЫ 19.1.1. Константы цвета Константы цвета в модуле Graph имеют такие идентификаторы и коды, как и в модуле Crt 19.1.2. Константы типа линий и их толщины Константа Значение Примечание SolidLn 0 Сплошная линия DottedLn 1 Точечная линия Center Ln 2 Штрих-пунктирная линия DashedLn 3 Пунктирная линия UserBitLn 4 Тип линии, определяемый программистом Norm Width 1 Нормальная толщина линии ThickWidth 3 Жирная линия Эти константы используются с процедурами GetLmeSettings и SetLineStsle 19.1.3. Константы типов закраски Константа Значение Примечание EmptyFill 0 Закраска области фоновым цветом SolidFill 1 Сплошная закраска области LineFill 2 Закраска линиями — ItSlashFill 3 Закраска линиями //// Slash Fill 4 Закраска жирными линиями //// BkSlashFill 5 Закраска жирными линиями \\\\ LtBkSlashFill 6 Закраска линиями \\\\\ HatchFill 7 Закраска редкой штриховкой XHatchFill 8 Закраска частой штриховкой (в обоих направлениях) InterleaveFill 9 Закраска прерывистой линией WideDotFill 10 Закраска линией из редких точек Close DotFill 11 Закраска лилией из частых точек User Fill 12 _ Закраска, определяемая программистом Эти константы используются с процедурами GetFillSetiings and SetFillStyle
поовзние в среде Turbo Pascal 7 О 307 i9j,4. Константы типа шрифта и выравнивания текста Константы типа шрифта I Койстапга___ Значение Примечание "DefaultFont 0 8x8 растровым шрифт TriplexFont 1 Штриховой шрифт SmallFont 2 Штриховой шрифт SansSerifFont 3 Штриховой шрифт GothicFont 4 Штриховой шрифт 'IforizDir 0 Направление слева направо I VertDir 1 Направление снизу вверх UserCharSize 0 Размер символов, определяемый программистом Эти константы используются с процедурами SetTextStyle и GetTextSettings Константы выравнивания текста по горизонтали Константа Значение Примечание LeftText 0 По левому краю CenterText 1 По центру RightText 2 По правому краю Константы выравнивания текста по вертикали Константа Значение Примечание BottomText 0 По нижней линии CenterText 1 По центру TopText 2 По верхней линии Эти константы используются с процедурой SetTextJustify 19.1.5. Константы для процедуры SetViewPort Константа Значение ClipOn ClipOff True False Эти константы управляют отсечением изображения на границах окна вывода 19.1.6. Константы для процедуры ВагЗО Константа Значение TopOn True TopOff False Эти константы используются для управления отображением верхней грани «зсимоугольного параллелепипеда, рисуемого процедурой ВагЗР
308 Работе а графи таком ецдвОо^ 19.1.7. Константы для процедур Putlmage и SetWriteModp Константа Значение Операция Norm al Put 0 MOV CopyPut 0 MOV XorPut 1 XOR OrPut 2 OR AndPut 3 AND NotPut 4 NOT Эти константы используются для задания логических операций при работе изображениями с помощью процедуры Putlmage 19.2. ПРЕДОПРЕДЕЛЕННЫЕ ТИПЫ 19.2.1. Тип установки цветов палитры const MaxColors = 15, type PaletteType = record Size Byte Colors array[0 MaxColors] of Shortint end 19.2.2. Тип установки вида линий LineSettingsType = record LineStyle Word Pattern Word Thickness Word end 19.2.3. Тип установки оформления текста TextSettingsType = record Font Word Direction Word CharSize word Horiz Word Vert Word end 19.2.4. Типы установки вида закраски FillPatternType - array [1 8] of Byte FillSettingsType “ record Pattern Word Color Word end, .
?9.2.5. Тип для процедуры GetViewSettings VlewPortType = record xl, yl, x2 , y2 integer, Cllp Boolean, end, 19.2.6. Тип для работы с процедурами Arc и Ellipse ArcCoordsType = record X, Y, Xstart, Ystart, Xend, Yend integer, end, 19.2.7. Тип для задания координат точек на экране PointType = record X, Y integer; end, Краткое описание стандартных графических процедур и функций приведено в приложении 1 19.3. ГРАФИЧЕСКИЕ ДРАЙВЕРЫ И РЕЖИМЫ В модуле Graph поддерживаются следующие графические драйверы и режимы 19.3.1. Константы графических драйверов Константа Значение CurrentDriver Detect CGA MCGA EGA EGA64 EGAMono IBM8514 HercMono ATT400 VGA PC3270 -128 0 1 2 3 4 5 6 7 8 9 10
Работа в графическом 310 19.3.2. Константы графических режимов Имя константы Зна- чение Строк * столбцов Палитра Цвета Кол-во" хранив АТТ400С0 0 320*200 0 Светло-серый, свет- ло-красный, желтый. Л “ АТТ400С1 1 320*200 1 Светло-бирюзовый, свет- ло-малиновый, белый. г- АТТ400С2 2 320*200 2 Бирюзовый, малиновый, светло-серый. ATT400Med 4 640*200 ATT400Hi 5 640*400 CGACO 0 320*200 0 Светло-серый, свет- ло-красный, желтый. 1 CGAC1 1 320*200 1 Светло-бирюзовый, свет- ло-малиновый, белый. 1 CGAC2 2 320*200 2 Зеленый, красный, корич- невый. 1 CGAC3 3 320*200 3 Бирюзовый, малиновый, светло-серый. 1 CGAHi 4 640*200 EGALo 0 640*200 16 цветов 4 EGAHi 1 640*350 16 цветов 2 EGA64LO 0 640*200 16 цветов 1 EGA64H1 1 640*350 4 цвета 1 EGAMonoHi 3 640*350 64К на плату, 256К на плату. 1 2 HercMonoHi 0 720*348 IBM8514Lo 0 640*480 256 цветов IBM8514Hi 1 1024*76 256 цветов MCGACO 0 320*200 0 Светло-серый, свет- ло-красный, желтый. 1 MCGAC1 1 320*200 1 Светло-бирюзовый, свет- ло-малиновый, белый. 1 MCGAC2 2 320*200 2 Зеленый, красный, корич- невый. 1 MCGAC3 3 320*200 3 Бирюзовый, малиновый, светло-серый. 1 MCGAMed 4 640*200 MCGAHi 5 640*480 PC3270Hi 0 720*350 VGALo 0 640*200 16 цветов 4 VGAMcd 1 640*350 16 цветов .1 VGAHi 2 640*480 16 цветов —L- J
t в среда Turbo Pascal 7 q 311 19 4. СИСТЕМА КООРДИНАТ в Turbo Pascal принята следующая система координат рдинат графического режима координата X (0,0) -> (GetMaxX,0) координата ¥ (0,GetMax¥) (GetMaxX.GetMaxV) GetMaxX GetMaxY стандартные функции модуля Graph которые возвращают соответственно максимальные координаты по осям X и Y в зависимости от текущего режима видеоадаптера 19.5. ТЕКУЩИЙ УКАЗАТЕЛЬ Текущий указатель называют также графическим курсором Понятие текущего указателя используется во многих графических системах Он аналогичен текстовому курсору но в отличие от него невидим Для определения текущих координат невидимого текущего указателя используются функции GetX и GetY а для его перемещения без вывода каких либо изображении на экране — процедуры MoveTo и MoveRei Кроме того положение текущего указателя автоматически изменяется при выводе изображений процедурами LineTo LineRel и OutText которые переводят его в конечную точку нарисованного фрагмента и процедурами ииициализации графического режима и очистки экрана ImtGraph GraphDefaults ClearDevice SetGraphMode SetViewPort ClearViewPort которые устанавливают его в начало координат 19.6 ИНИЦИАЛИЗАЦИЯ ГРАФИЧЕСКОГО РЕЖИМА Инициализация графического режима выполняется процедурой ImtGraph а закрытие — процедурой Clo^eGraph Заголовок процедуры ImtGraph имеет такой вид InitGraph (Драйвер Integer Режим Integer Путь к файлу драйвера String) Первые два параметр.; определяются константами приведенными в таблице графических драйверов и режимов Чтобы инициализировать графический режим с автоматическим распознаванием драйвера и режима достаточно присвоить переменной отвечающей за драйвер константу Detect или 0 Присваивать какое либо значение переменной режима в .чае не требуется Tper ™па String должен получить строковое - которое представляет -си-иски корректный согласно х -т 4 я файлы графических драйверов ( Bbl)
312 Работа е графическом Пример program InxtDerao; uses Graph; { Использовать модуль Graph } var GraphDriver, { Графический драйвер ) GraphMode : Integer; { Графический режим ) begin GraphDriver := Detect; { Автораспознавание драйвера.} { Установка параметра Gm } { в этом случае не требуется } InxtGraph (GraphDrxver, GraphMode, ’C:\BP\BGI’); { Графические драйверы находятся ) { в подкаталоге BGI каталога ВР ) { на диске С:.} {Графические действия} Line (0,O,GetMaxX,GetMaxY); Readin; {задержка последней картинки на экране) CloseGraph; {закрытие графического режима) end. 19.7. ОШИБКИ ИНИЦИАЛИЗАЦИИ ГРАФИЧЕСКОГО РЕЖИМА И ИХ ОБРАБОТКА Если при инициализации графического режима произошла ошибка, то Turbo Pascal генерирует соответствующий код ошибки, который возвращается функцией GraphResult Для работы с кодами ошибок в модуле Graph введены следующие константы Константа ошибки графики Код ошибки Соответствующее сообщение об ошибке grOk 0 Нет ошибки grNoInitGraph -I Графика ие инициализирована grNotDetected -2 Графические средства ие найлеиы grFileNotFound -3 Файл ие найден grlnvalidDriver -4 Недопустимый драйвер grNoLoadMem -5 Драйвер ие загружен grNoScanMem -6 Ошибка при просмотре пям»^ grNoFloodMem -7 Ошибка при закраске grFontNotFound -8 Шрифт ие найден grNoFontMem -9 Шрифт ие загружен а память grlnvalidMode -10 Недопустимый режим grError -11 Ошибка графики grIOError -12 Ошибка ввода-вывода графики grlnvalidFont -13 Недопустимый файл шрифгга grlnvalidFontNum -14 Недопустимый номер шрифта Покажем инициализацию графики с обработкой возможных ошибок при частой работе с графикой процесс инициализации удобно оформить отдельной процедурой MyGraphlnjt, которая затем будет включаться в каждую графическую программу
ть модуль Graph ) ! Графический драйвер ) рафический режим } ' Код ошибки } program GraphlnitDemo; -_____ uses Graph; ( Использовать „ var GraphDrxver, , r дуль Graph } GraphMode, Графический драйвер ) ErrorCode : Integer,. к^ФИЧ®«КИЙ режим ' procedure MyGraphlnxt; ОШИ КИ ’ begin if ErrorCode <> grok then пХУЛЬ’а’ иниШ’ализации ) yi-vit слеп ( Произошла begin Автораспознавание } , ’C:\BP\BGI'); ошибка } Wrxteln (’Ошибка инициализации графики: GraphErrorMsg(ErrorCode)) ; ('Работа программы прервана’); Wrxteln ( Halt (1) ; end; end; begin MyGraphlnxt; { Графические действия ) Lxne (0,0,GetMaxX,GetMaxY) ; Readln; CloseGraph; end. 19.8. ПРОСТЕЙШИЕ ГРАФИЧЕСКИЕ ФИГУРЫ В первом примере демонстрируется работа с процедурами простейших ©метрических фигур и процедурой установки текущего цвета линий program SxmpleFxgureDemo; uses Graph; { Использовать модуль Graph } var GraphDrxver, ( Графический драйвер ) GraphMode, I Графический режим ) ErrorCode Integer; { Код ошибки ) procedure MyGraphlnxt; begin GraphDrxver := Detect; f InxtGraph (GraphDrxver, ( ErrorCode = GraphResult, , - . if ErrorCode <> grOk then { Произошла ошибка ) 9 Wrxteln ('Ошибка инициализации графики: GraphErrorMsg(ErrorCode)); Wrxteln ('Работа программы прервана'); Halt (1); end. end, Автораспознавание ) GraphMode, ’D:\BF\BGI’); • • ( Результат инициализации
работа а графическом чи/)пг,Пл^ 314 ЬвЯ1” инициализация графического режима ) MyGraphlnxt; { Цвет прямоугольника красный ) SetColor (Red); { рисование прямоугольника: левый верхний угол в точке с координатами (10, 15), правый нижний угол в точке с координатами (320, 175) ) Rectangle (10, 15, 320, 175); ( Цвет круга и диагоналей — зеленый ) SetColor (Green); ( Рисование окружности посередине прямоугольника* первые два параметра — координаты центра окружности, 40 - величина радиуса окружности.) Circle ((320+10) dxv 2, (175+15) dxv 2, 40); ( Рисование первой диагонали прямоугольника (10, 15) — координаты первой точки диагонали, (320, 175) — координаты второй точки диагонали.) Line (10, 15, 320, 175); ( Рисование второй диагонали прямоугольника: (10, 175) - координаты первой точки диагонали, (320, 15) - координаты второй точки диагонали.) Lxne (10, 175, 320, 15); ( Задержка картинки на экране до нажатия Enter ) Readln; CloseGraph, { Закрытие графического режима ) end Во втором примере демонстрируется рисование фигур различными типами линии и закрашивание фигур различными цветами program LxnesAndFxllDemo, uses Graph, ' Использовать модуль Graph / var GraphDrxver, { Графический драйвер ) GraphMode, ( Графический режим ) ErrorCode Integer l Код ошибки ) procedure MyGraphlnxt, begxn GraphDriver = Detect ( Автораспознавание } InxtGraph (GraphDrxver, GraphMode, 'E-\BP\BGI') ErrorCode = GraphResult, I Результат ииици-*"4 xf ErrorCode <> grOk then ( Произошла ошиб»- begxn Wrxteln ('Ошибка инициализации графики GraphErrorMsg(ErrorCode)) Wrxteln (’Работа программу прервана’) Halt (1) end, end,
'.тчие в cp< t^al 7 0 •-------——_________________ MyGraphlnxt; ( Инициали3ация графИческого ( рисование сектора сплошной Велой mJ, (стандартной) толщины, закрашенного краси^ТвеХ ') \ цвет — белый } SetColor (White); ( Сплошная линия нормальной толщины } SetLxneStyle (SolxdLn, 0, NormWxdth) ; { Сплошная закраска красным цветом } SetFillStyle (SolxdFxll, Red) ; { Закрашенный сектор с центром в точке (100,200) , ) ( начальным углом 45, конечным углом 135 и радиусом 80.) PxeSlxce (100, 200, 45, 135, 80); {------------------------------------------------------} { Рисование прямоугольника сплошной толстой красной } { линией, закрашенного желтым цветом. } ( Цвет — красный } SetColor (Red); ( Сплошная толстая линия ) SetLxneStyle (SolxdLn, 0, ThxckWxdth) ; ( Сплошная закраска желтым цветом ) SetFxllStyle (SolidFxll, Yellow); Рисование прямоугольника сплошной толстой красной линией } Rectangle (300, 10, 400, 70); i Закраска прямоугольника установленным цветом } ( закраски — Yellow; - « . , { (350, 50) - любая точка внутри закрашиваемой области; I I Рее - цвет линии, ограничивающей закрашиваемую область! FloodFxll (350, 50, Red); Рисование диагонали экрана пунктирном т-.л_т_ зеленой линией ( цвет - зеленый } SetColor (Green); I Пунктирная толстая зеленая линия ) SetLlneStyle (Oaahedbn, О, ThxckWxdth) , I Рисование диагонали экрана Lxne (0, GetMaxY, GetMaxX, О); ___________
Работа в грпфичпгком 316 , Рисование круга голувой линией нормальной । ( (стандартной) толщины, закрашенного { сетчатой штриховкой красного цвета. } { Цвет — голубой } SetColor (Cyan); { Сплошная линия нормальной толщины ) SetLxneStyle (SolxdLn, 0, NormWidth), { Сетчатая закраска красным цветом ) SetFxllStyle (XHatchFxll, Red); { Рисование окружности: (500,250) — центр окружности; } । 50 - радиус окружности } Cxrole (500, 250, 50); { Закраска установленным цветом закраски — Red; ) { {500, 250) - любая точка внутри закрашиваемой области , } { Cyan — цвет линии, ограничивающей закрашиваемую область ) FloodFxll (500, 250, Cyan); {--------------------------------------------------------} ( Задержка картинки на экране ) Readln; (--------------------------------------------------------) ( Закрытие графического режима ) CloseGraph; end 19.9. ВЫВОД ТЕКСТА В ГРАФИЧЕСКОМ РЕЖИМЕ Вывод текста на экран в графическом режиме выполняется процедурами OutText и OutTextXY По умолчанию текст выводится растровым системным шрифтом 8*8 Кроме того, для работы с текстом в графическом режиме в дистрибутиве пакета Turbo Pascal имеются файлы, так называемых, штриховых шрифтов, которые имеют расширение CHR Главное отличие штриховых шрифтов от растровых состоит в том. что при увеличении размера символов растрового шрифта качество изображения ухудшается, а при увеличении размера символов штрихового шрифта — не ухудшается Чтобы работа со штриховыми шрифтами выполнялась корректно, необходимо, чтобы файлы * CHR находились в том же каталоге, что и файлы графических драйверов (* BGI) Перечень предопределенных констант для работы со шрифтами приведен в начале главы Для установки к использованию штриховых шрифтов и изменения размера применяется процедура SetTextStyle. для выравнивания текста на экране — процедура SetTextJustif), для определения высоты букв указанной строки — функция TextHeight. для определения ширины указанной строки — функция TextWidth Гр «। .Р(Ю принимается растровый шрифт DefaultFoni размера 1
.чмн/и1 Л cpf>df> ГигЬо Pascal J Q Пример program TextlnGraphModeDemo^ -------------— - . Демонстрация различу шрифтов и * uses Graph; var GraphDriver, GraphMode, ErrorCode : Integer; procedure MyGraphlnxt; begin GraphDrxver := Detect; InxtGraph (GraphDrxver, ErrorCode := GraphResult• if ErrorCode <> grOk then ( Произошла ошибка ) begin Wrxteln ('Ошибка инициализации графики.- GraphErrorMsg(ErrorCode) ) ; Wrxteln (1 Работа программы прервана 1); Halt (1) ; end; end; [ Графический драйвер ) { Графический режим } ’ Код ошибки } {Автораслознавание} GraphMode , ' E -. \BP\BGI') ; { Результат инициализации } begxn MyGraphlnxt; ( Инициализация графического режима ) {------------------Горизонтальный текст----------------------} {--------Исходное состояние------------} ( Действует растровый шрифт Default, принятый по умолчанию. } { Выравнивание по умолчанию — по левому краю текста. } 1 Размер по умолчанию для растрового шрифта - 1 (8*0) . ) (----------------------------------------) ( Цвет - зеленый } SetColor (Green); OutTextXY ( (GetMaxX div 2)-50, 0, 'DefaultFont, Size 1'), Readln; <----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Цвет - синий ) SetColor (Blue); 1 Шрифт — Default, направление - горизонтальное, размер SetTextStyle (DefaultFont, HoriaDxr, 3) ; 1 Выравнивание по левому краю выводимого текста и п_> верхней линии символов строки SetTextJuetxfy (LeftText, TopText). OutTextXY (0, GetMaxY div 1, 'DefaultFont, Size 3 ), Readln; I JfiPT ~ ЦЗ-НЫТ SetColor (Red). I Шрифт - Tr±piex, направление - горизонтальное, размер SetTextStyle (TrxplexFont, HorxxDxr, 1);
318 ьпьота в графическая »..» ' """ ( выравнивание по центру выводимого текста и ) ( по нижней линии строки» у SetTextJustify (CenterText, BottomText); OutTextXY (GetMaxX div 2, GetMaxY dxv 3, ’TriplexFont, Size 1'); Readln; { Цвет — желтый ) SetColor (Yellow); ( Шрифт — Triplex, направление — горизонтальное, размер — 4 } SetTextStyle (TriplexFont, HorizDir, 4) ; { Выравнивание по левому краю выводимого текста и } ( по центру символов строки. ) SetTextJustify (LeftText, CenterText) ; OutTextXY (GetMaxX div 2, GetMaxY div 2, ’TriplexFont, Size 4 ’) ; Readln; {------------------------------------------------------j { Цвет — белый } SetColor (White) ; { Шрифт — Small, направление — горизонтальное, размер — 1 } SetTextStyle (SmallFont, HorizDir, 1); ( Выравнивание по правому краю выводимого теста } { и по верхней линии строки. } SetTextJustify (RightTeXt, TopText); OutTextXY (GetMaxX div 2, GetMaxY-180, 'SmallFont, Size 11); Readln; ( Цвет — сиреневый } SetColor(Magenta); ( Шрифт - Small, направление - горизонтальное, размер - 4 ) SetTextStyle (SmallFont, HorizDir, 4); I Выравнивание по центру выводимого текста у ( и по нижней линии символов строги. у SetTextJustify (CenterText, BottomText); OutTextXY (GetMaxX div 2, GetMaxY-120, 'SmallFont, Size 4'); Readln; -----------------Вертикальный текст-------------------у i Цвет - зеленый у SetColor (Green); Шрифт - Default, направление - вертикальное, раз:-- SetTextStyle (DefaultPont, VertDir, 1);
_ * c?ede Tufbo Pascal 7 p 319 OutTextXY Readln; (GetMaxX div 2 Г~Т~---- '0^tfoW,'£^ d- 3, I"------ ~ ( Цвет SetColor (Blue); синий Шрифт — Default, направление SetTextStyle (DefaultFont, ~ вертикальное, VertDir, 3); размер — <j j { Выравнивание по левому { и по верхней линии SetTextJustify (LeftText, краю выводимого текста символов строки. TopText); OutTextXY (GetMaxX div 4, 10, ’DefaultFont, Size 3') Readln; { Цвет — красный } SetColor (Red); { Шрифт — Triplex, направление - вертикальное, размер - 1 } SetTextStyle(TriplexFont, VertDir, 1) ; { Выравнивание по центру выводимого текста ) { и по нижней линии символов строки. } SetTextJustify (CenterText, BottomText), OutTextXY ((GetMaxX div 2)-40, GetMaxY div 2, ’TriplexFont, Size 1'); Readln; {------------------------------------------------------ ( Цвет - желтый } SetColor (Yellow); I Шрифт - Triplex, направление - вертикальное, размер - 4 > SetTextStyle (TriplexFont, VertDir, 4), I выравнивание no левому краю выводимого текста > ( и по центру символов строки. SatTextJustify (LeftText, CenterTaxt): OutTextXY ((GetMaxX div 2>+50, GetM»xY 'TriplexFont, Size Readln. ( Цвет SetColor (White); Шрифт - Small, направление - вертш-з SetTextStyle (SmallFont, VertDir- выравнивание по правому краю ВЫ®°5**КИ1 и по верхней линии символов , SetTextJuetify (RightText, TopText)»
Робота в графическом чиг^Г1/Уп 120 — _ --------OutTex^ ((GetMaxX div 2)-30, (GetMaxY dxv 2)^ ~ •SmallFont, Size 1'); Readln; _ ____________________________ ( Цвет — сиреневый ) SetColor (Magenta); ( Шрифт - Small, направление - вертикальное, размер - 4 } SetTextStyle (SmallFont, VertDir, 4) ; i Выравнивание по центру выводимого текста } { и по нижней линии символов строки. } SetTextJustify (CenterText, BottomText); OutTextXY (GetMaxX div 2, GetMaxY-100, 'SmallFont, Size 4'); Readln; ( Закрытие графического режима } CloseGraph; end. 19.10. ЭФФЕКТ ДВИЖЕНИЯ В ГРАФИЧЕСКОМ РЕЖИМЕ Для реализации простейших движений фигур в графическом режиме используются процедуры Getlmage, Putlmage и предназначенные для работы с ними константы CopyPut, XorPut, OrPut, AndPut и NotPut В следующей программе демонстрируется вывод на экран курсора в виде стрелки и перемещение его по экрану в соответствующем направлении в зависимости от нажатий клавиш-стрелок program GraphCursor; uses Graph, Crt; var X, У, XN, YN : Integer; { Координаты кончика стрелки курсора } PCursor: Pointer, { Указатель на образ курсора ) TheEnd: Boolean; | Флаг окончания работы программы } Ch: Char, ( Вспомогательная переменная } GraphDriver, { Графический драйвер ) GraphMode, ( Графический режим ) ErrorCode : Integer; { Код ошибки } procedure MyGraphlnit; begin GraphDriver := Detect; { Автораслознавание } InitGraph (GraphDriver, GraphMode, 'D:\BP\BGI'),- ErrorCode := GraphResult, I Результат инициализации ) if ErrorCode <> grOk then f Произошла ошибка }
пп/роезниэ в среде Turbo Pascal т о 321 begin WriteIn ('Ошибка инициализации графики; ' GraphErrorMsg (ErrorCode}}; Writein (’Работа программы прервана’} ; Halt (1}; end; end; procedure CursorDraw (var X,Y: Integer; var Р,- Pointer} { Процедура CursorDraw рисует курсор в виде стрелки ) { и сохраняет его для перемещения в динамической } { области памяти, адрес которой сохраняется в ука- } { зателе Р. } const { Многоугольник в виде стрелки } Cursor : arraytl..8] of PointType = ((X:320; Y:175), (X:323; Y.186}, (X-.325; Y:184} , (X.-332; Y.193}, (X:338; Y:187), (X:329; Y.-180} , (X;331; Y:178), (X.-320; Y.-175)); var Size: Word; begin ( Рисование курсора } DrawPoly (8, Cursor); ( Закрашивание курсора } FloodPill (323, 178, White); Определение размера области экрана, Size : = Imagesize (320, 175, ‘Э‘9Й Выделение памяти под буфер для в динамической области памяти, сан в указатель Р. } GetMem(₽, Size); —содержащей 338, 193); сохранения образа адрес которой буд- курсор ! курсора } Сохранение образа курсора / Getloiage (320, 175, 338, 193, ₽А) ; ;тановка переменных, хранящих координаты I кончика стрелки курсора. X ;= 320; Y :« 175; end, procedure NewXY (var X, A . v»r Flag- Boolean}; Y: Integer; var const Esc LeftArrow RightArrow => • 27, ( • 75; ( «77; < Клавиша Клавиша Клавиша Клавиша Esc > "стрелка "стрелка "стрелка влево" > вправо” ) вверх” 1 UpAxrow DownArrow * #80. Клавиша "стрелка аниз” 1
Работа в графическом 322 { множество символов клавиш-стрелок и клавиши Esc } ArrowsAndEsc set of Char { Флаг поступления расширенного кода } ExtendedKey Boolean { вспомогательная переменная для считывания символов } Ch Char begin ArrowsAndEsc = [ LeftArrow, RxghtArrow, UpArrow, DownArrow, Esc ] repeat ExtendedKey «False Ch «ReadKey { Считывание символа нажатой клавиши } if Ch = Esc then { Установка флага завершения } { работы программы } Flag «True if Ch = #0 then { Если да" - код расширенный } begin Ch «ReadKey ( Считывание второго символа } ( расширенного кода } ExtendedKey «True { Фиксация поступления } { расширенного кода } end if ExtendedKey then { Если код был расширенный ) { Изменение координат в зависимости от нажатой клавиши } case Ch of LeftArrow X «Х-10 RxghtArrow X =Х+10 UpArrow У «У-10 DownArrow У «У+10 end { Фиксация стрелки на левом крае экрана } if Х<0 then X =0 { Фиксация стрелки на правом крае экрана } if X>GetMaxX-20 then X «GetMaxX**20 ( Фиксация стрелки на верхнем крае экрана } if У<0 then У «0 { Фиксация стрелки на нижнем крае экрана ) if Y>G«tMaxY-20 then У -GetMaxY-20, ( Ожидание нажатия клавиши стрелки или клавиши Escf until Ch in ArrowsAndEsc end begin ’ Инициализация графического режима) MyGraphXnit ( Лкование курсора в точке У Y) и сохранение его образа J { в буфере на который указывает PCursor CureorDraw (X У PCursor) xn - х та «у
g Turbo Pasca/ 7 Q~ 323 । установка mnan- „ -- — —------- TheEnd “False; завершения программы } { очистка буфера клавиатуры > Vhile Repressed do Cht-ReadK^, repeat { Повторять до наж^,<а *» нажатия на клавишу Esc } NewXY возвращает новые координаты хм ум на клавишу-стрелку или TheEnd=True по^а нажатия } клавишу Esc) ue после нажатия на } NewXY (XN, YN, TheEnd); { Спрятать курсор на "старом" месте ) Putlmage (X, Y, PCursor*, XorPut); { Вывести курсор на новом месте } Putlmage (XN, YN, PCursor*, XorPut); ( Новые" координаты становятся "старыми" ) X •= XN; Y •= YN; { Задержка изображения стрелки на экране ) Delay (100); until TheEnd; { Выход из цикла при TheEnd = True ) I Закрытие графического режима } CloseGraph; end Контрольные вопросы 1 Какие значения могут принимать константы цвета для символов и для фона7 2 Какой процедурой выполняется установка типа линий7 3 Какой процедурой выполняется установка типа закраски7 4 Какой процедурой выполняется установка шрифта7 5 Какие шрифты для вывода текста в графическом режиме реализованы в Turbo Pascal7 6 Какие константы используются для задания логических операций при работе с изображениями с помощью процедуры Putlmage7 2 Какой вид имеет система координат экрана в графическом режиме7 8 Что такое текущий указатель7 5 Какая процедура предназначена для инициализации графического режима и какие параметры она имеет7 Ю Какая функция позволяет выполнять обработку ошибок графического режима7 11 С помощью каких процедур осуществляется вывод текста на экран в графи- ческом режиме7 12 В чем состоит отличие штриховых шрифтов от растровых7
Рлблтл л -г ~1фч шг »г,.« , 324 Контрольные задания 1. Нарисуйте произвольную букву русского или латинского алфавИта 1ксонометрии и раскрасьте стороны буквы различными цветами 2. Постройте график заданной функции, обеспечив следующие требования I) возможность изменения шага вычисления значений функции, Тс количества разбиений диапазона изменения аргумента, 2) изображение на экране координатных осей X, Y с размеченной шкалой и цифрами, соответствующими диапазонам изменения аргумента и функции (для этого рекомендуется предварительно выполнить анализ изменения значений функции на заданном интервале изменения аргумента) 3) изображение на свободном участке экрана математической формулы функции и фамилии автора программы
ГЛАВА 20 f\Turbo РазсаГй~АССЕМБЛЕР^_^| Turt» Ра**1 предоставляет пять способов включения ассемблерных фрагментов „пропну , оператор asm, , процедуры И функции С директивой assembler „ директивы {SL имя} и external, , оператор inline, . процедуры и функции с директивой inline Во встроенном ассемблере Turbo Pascal имеются перечисленные ниже зарезервированные идентификаторы AH CL FAR SEG AL CS HIGH SHL AND ex LOW SHR AX DH MOD SI BH DI NEAR SP BL DL NOT ss BP DS OFFSET ST BX DWORD OR TBYTE BYTE DX PTR TYPE CH ES QWORD XOR WORD 20.1. ОПЕРАТОР asm Оператор asm записывается аналогично составному оператору и имеет бедующую структуру asm ассемблерные команды end Оператор asm ^граммы и включает блока «Хс^с^'Л'р^ые- фрагменты ассемблерного текста .. „„пгптъся в любом месте операторного может располагаться в -----_ program Fibonacci чисел Фибоначчи > Программа вычисляет г и я uses Crt •label LI L2 F n N Word____________________________-— ----------
b»gin ClrScr; Write('Введите Readln(N): порядковой номер «мела ♦ивокачхи asm MOV XOR JCXZ MOV LI: ADD XCHG LOOP L2: MOV end; CX n { Загрузить номер s счетчик CX. } Ax'aX ( Очистить аккумулятор. ) L2* ( Если счетчик = 0, то F_n = 0. ) DX 1 { Занести в DX первый член ряда. ) ax.'dx ( Получить в АХ очередной член ряда. Ax'dX { Поменять местами два последних } { члена ряда. } L1 { Если счетчик <> 0, то продолжаем.) F п,АХ { Записать результат в Е_п. } Writein (’ Fib_n = F_n) end. Оператор asm можно использовать также и в процедурах и функциях. В этом случае автоматически генерируется код входа и выхода из процедуры/функции Чтобы функция возвращала правильный результат, итоговое значение функции следует занести в специальную переменную ©Result. Кроме того, в ассемблерном коде вместо обычных паскалевских меток допускается использование необъявленных меток, которые начинаются с символа program Fibonacci; uses Crt; var F_n, N : Word; function Fib n (N : Word) 1 : Word; begin asm MOV XOR JCXZ MOV 01; ADD XCHG LOOP 92; MOV end CX,N { AX, AX { @2 { DX,1 { ax.dx { AX,DX { { @1 { 0Re»ult,AX { Загрузить номер в счетчик CX. } Очистить аккумулятор. ) Если счетчик = 0, то F п = 0. ) Занести в DX первый член ряда. } Получить в АХ очередной член ряда. Поменять местами два последних } члена ряда. } Если счетчик <> 0, то продолжаем Записать результат в ^Result. } •nd; begin ClrScr; Write('Введите N: Readln(N); F_n :« Fib_n (N) ; Wrxteln(’Fib n - •, F n) end. ~
4 ? urbo Pascal 20.2. ДИРЕКТИВА *saembler Директиву assembler МОЖНО НСПОЛЬЗОВЯТЬ в Тг.' г, ^ратор'ШЙ блок процедуры ил„ фТО1а1ии х когда весь пример. 1”» решения той же зад™, как в пгедыаущем ипим-г^ » *оманл МОЖНО использовать следующую Процедуру с даректавой ^seX™ °ПСраТ0ра program Fibonacci; F_n, N : Word; .function Fib_n (N asni : Word) Word,- assembler; 92: end; MOV XOR JCXZ MOV ADD XCHG LOOP CX,N AX,AX 02 DX,1 AX,DX AX,DX Загрузить номер в счетчик СХ. ) Очистить аккумулятор. } Если счетчик « 0, то Г п » 0. > Занести s DX первый член ряда. ) Получить в АХ очередной член ряда. ) Поменять местами два последних } члена ряда. ) Если счетчик о 0, то продолжаем.) 01: begin ClrScr; Write('Введите N- F_n -.= Flb_n (N) ; Writeln(’Fib_n ® F_n) end Readln(N), Процедуры/фтнкиии с директивой вваешЫег имеют следующие особенности по сравнению с процедурами/функциями. не нспользуюшими ее • компилятор не генерирует код для копирования параметров-значений в локальные переменные Это влияет на все параметры-значения строкового типа и другие параметры-значения, размер которых не равен 1. 2 или 4 байтам Внутри процедуры илн функции такие параметры должны интерпретироваться, как если бы они были параметрами-переменными. ♦ компилятор не выделяет память для результата функции, и ссылка на идентификатор ^Result будет ошибкой Функции со строковым результатом являются исключением из этого правила. • функции. использующие директиву лззаоЫлг, должны возвращать результат следующим образом я) результаты функций порядкового типа (Integer. Char. Boolean, перечне ляемые типы) возвращаются в регистре А1_ для 8-разрядНых значений, в регистре А\ для 16-рдтрядных значений или в Паре регистров DX. АХ для 32-разрядныч значений. 6 ) результаты функций вещественного типа (Real) возвращаются в регист- - >. Гу V П \ \ Y
Turbo Pescel и аг 328 в) результаты ф)НКЦИЙ ТИПОВ, ИСПОЛЬЗУЮЩИХ инструкции Сопроц 8087 (Single Double, Extended Comp) возвращаются в регистпе^0^ сопроцессора ST(0), СТсМ г) результаты функций указательного типа возвращаются в папе пт DX, АХ, РСГИс^ д) результаты функций строкового типа возвращаются во временной на которую указывют ^Result ЧсЙке,- 20.3. ДИРЕКТИВЫ {$L имя} И external Директива компилятора {SL имя файла} позволяет в паскалевскую программу включить подпрограмму в объектном коде (в файле с расширением OBJ), полученную с помощью ассемблера Вставка кода подпрограммы выполняется в точке расположения директивы {$[_ имя файла} Тот же самый пример вычисления n-го числа Фибоначчи записанный hi будет следующим языке ассемблера Кроме того ней должен быть синтаксису языка Turbo Past i «хе«глл1 Например если получением «и» > ' MODEL CODE PUBLIC Large, Fib n PASCAL Fib_n PROC MOV XOR JCXZ MOV NEAR CX,N AX, AX L2 DX, 1 N WORD LI ADD XCHG LOOP L2 NOP RET Fib_n ENDP END AX, DX AX,DX LI что в паск 11 г описан j 1 i\ будет включен объектный код в 'ой проиелуры/функпии согласно указанием процедурной директивы Функцию Fib_n предварительно проассемблироватъ < файла Frb_n OBJ то программа, которая ее ‘ИЛ Сг <»L Fib г оЪ 1 ) Writ«ln(-rib &
е среде Turbo Pascal 7 О 329 20.4. ОПЕРАТОР inline Операторы inline позволяют вставлять инструкции машинного кода непосредственно в программу и, как правило, используются вместо небольших по размеру ассемблерных программ. Оператор inline состоит из зарезервированного (юва inline, за которым в круглых скобках располагаются записи машинного кода, к'нные косой чертой Такие операторы могут свободно чередоваться с другими , (горами языка Turbo Pascal. Ниже приведена программа, в которой для вычисления суммы двух квадратов + b' ) используется оператор inline, а для возврата результата функции — итор asm. program inline_operator; uses Crt; var a, b : Byte; Res : Word; function Pifagor (a, b : Byte) : Word; begin $8А/$46/04/ ( MOV AL,b $F6/$66/04/ ( MUL b $8В/$С8/ ( MOV CX,AX $8А/$46/06/ ( MOV AL,a $F6/$66/06/ ( MUL a $03/$С1 ( ADD AX, CX ) ; asm MOV (3Result,AX end end; begin ClrScr; Write('Введите a, b: ’)- Readln(a, b) ; Res :» Pifagor (a, b); Wrxteln(•c**2 = a»*2 + b**2 = end. 1, Res) 20.5. ДИРЕКТИВА inline С помощью директивы Inline описываются процедуры " Ug которых подставляется в генерируемый компилятором g у оператора («>чке ее вызова Синтаксис у директивы inline тако Решение предыдущей задачи с использованием функции inline имеет такой вид
ПРИЛОЖЕНИЕ 1 СТАНДАРТНЫЕ ПРОЦЕДУРЫ И ФУНКЦИИ В скобках после заголовков процедур и функций указан перечень целевых платформ для которых может быть выполнена компиляция ПРОЦЕДУРЫ И ФУНКЦИИ МОДУЛЯ SYSTEM Функция Abs Abs(X), ( Реальный режим, защищенный режим Windows ) Назначение Возвращает абсолютное значение аргумента Параметр X — выражение целого или вещественного типа Тип ре зультата соответствует типу параметра Функция Addr function Addr(X) Pointer; ( Реальный режим защищенный режим, Windows ) Назначение Возвращает адрес заданного объекта Параметр X — любая переменная или идентификатор процедуры или функции Результатом является указатель, ссылающийся на X Процедура Append procedure Appendfvar F : Text); ( Реальный режим защищенный режим Windows ) Назначение Открывает файл для присоединения Параметр F — файловая переменная текстового типа которая должна быть связана с внешним файлом с помощью процедуры Assign Функция АгсТап function ArcTanfX Real) Real, ( Реальный режим защищенный режим Windows ) Назначение Возвращает арктангенс аргумента Параметр X — выражение вещественного типа Результат представляет собой главное значение арктангенса х в радианах
7;2^M,'ptlea в среде Turbo Pascal 7 о 333 Процедура Assign „roccdure Assignfvar F; Name); 1 ( Реальным режим, защищенный режим, Windows) Назначение Присваивает имя внешнего файла файловой переменной Параметр F является файловой переменой любого файлового типа а Name выражением строкового типа функция Assigned function Assigned(var Р): Boolean; ( Реальный режим, защищенный режим, Windows) Назначение Проверяет имеет ли указатель, или процедурная переменная значе- ние П2.1 Параметр Р должен быть ссылкой на переменную или указателем процедурного типа Процедура BlockRead procedure BlockRead(var Ft File; var Buff; Count:Word f;Result: Word]) ( Реальный режим защищенный режим Windows ) Назначение Считывает из файла F в буфер BufT записи, число которых не пре восходит значения параметра Count Действительное число полных считанных записей (<= Count) возвращается в необязательном пара- метре Result Процедура BlockWrite procedure BlockWntefvar F: File; var Burt, Count. Word [, Result: Word ]), ( Реыьныи режим защищенный режим. Windows ) 1чение Записывает в файл F одну или более записей из буферной перемен- ной Buff, число которых не превосходит значения параметра Count Действительное число полных записанных записей (<= Count) воз- вращается в иеобязате гьном параметре Resiili Процедура Break cdure Break; ( реальный режим защищенный режим Windows ) учение Процедура Break завершает оператор for ити в тезе которого она распотагастся Процедура ChDir procedure ChDirfS String), ( Pean нни им Назначение Вищиняг? ПОМОЩЬЮ Mdpf 4 > е mor, который задается с ne S
1 Приложение 1 Стандартные процедуры и фу^. 334 Функция Chr 1U"CtlU? Ре^ьныТреж^Гзашишенный режим, Windows ) Иизна^ие Возвращает символ, соответствующий указанному значению хода ASCII (порядковому номеру) ---- —————~ процедура Close procedure Close(var F); , \ ( Реальный режим защищенный режим, Windows ) Назначение Закрывает открытый файл 4 Функция Concat function Concat(Sl, [SI.. Sn]' Stang). Stang; ( Реальныи режим защищенный режим, Windows ) Назначение Выполняет конкатенацию последовательности строк, указанных пара- метрами Если длина результирующей строки превышает 255 символов, то она усекается до 255 символов Процедура Continue procedure Continue; ( Реальный режим защищенный режим, Windows ) Назначение Выполняет переход на новую итерацию цикла того оператора fox, vhala или repeat в теле которого находится Функция Сору procedure Copy(S. String; Indx: Integer; Count Integer), ( Реальный режим, защищенный режим Windows ) Назначение Функция Сору возвращает строку число символов которой соответ- ствует параметру Count и которая начинается с символа строки S, индекс которого задан параметром Indx Функция Cos function Cos(X: Real), ( Реальный режим ищншгнныи ;<.жим i Назначение Возвращает косинус аргумента задающего угол в радианах Функция CSeg function CSeg Word, ( Реальный режим защищенный режим Windows ) Назначение Возвращает текущее значение регистра CS Результат длиной в слово представляет собой адрес сегмента для той части программы из которой была вызвана функция CSeg.
о среде Turbo Poses! 7 О 335 Процедура Dec urc Dec(var X [; N: Longint]); ( Реальный режим, защищенный режим, Windows) чение Уменьшает значение переменной Параметр X предстааляет собой переменную перечисляемого типа а уменьшается хеНН°е В“ра*ение’ дающее величину, на которую Процедура Delete dure Delete(var S: String; Indx: Integer; Count: Integer); ( Реальный режим, защищенный режим, Windows ) чение Функция Delete удаляет из строки S число символов, соответствую- щее параметру Count, начиная с символа, номер которого задан па- раметром Indx Процедура Dispose procedure Disposefvar Р: Pointer [, Destructor]); ( Реальный режим, защищенный режим, Windows) Назначение' Уничтожает динамическую переменную, на которую указывает ука- затель Р Функция Dseg function DSeg: Word; ( Реальный режим, защищенный режим, Windows ) Назначение Возвращает текущее значение регистра DS Результат длиной в слово представляет собой адрес сегмента данных Функция Eof function Eof ( (var F) ]: Boolean; ( Реальный режим, защищенный режим, Windows ) Назначение Возвращает состояние “конец файла” (end-of-file) для файлов Если те- кущая позиция в файле находится за последним элементом файла, или, если файл не содержит никаких элементов, то функция Eof(F) возвра- щает значение True В противном случае она возвращает значение False Функция Eoln function Eoln | (var F: Text) ): Boolean; { Реальный режим, защищенный режим. Windows Назначение Возвращает для текстовых файлов состояние конец строки {end-of-hnej Если текущая позиция в файле находится на метке конца строки, то функция Eoln(F) возвращает значение True В противном случае она возвращает значение False _
Приложение Стандартные процедуры и 336 Процедура Erase procedure Erase(var F), п.,1т1и1|1РННый режим, Windows ) ( файл, связанный с переменной F Исполу , Назначение Стирает^ икрытых файлов Процедура Exclude Процедура Exit procedu рсальный режим защищенный режим, Windows ) Назначение Выполняет немедленный выход из текущего блока Функция Ехр function Ехр(Х : Real): Real; ( Реальный режим, защищенный режим, Windows ) Назначение Возвращает экспоненциальное значение аргумента (число е в степе- ни X) Функция FilePos function FiiePos(var F): Longint; ( Реальный режим, защищенный режим, Windows ) Назначение Возвращает текущую позицию в файле Параметр F представляет собой файловую переменную Если теку щей позицией является начало файла, то функция FiIePos(F) возвра- щает значение 0 Если текущей позицией в файле является конец файла, то есть Eof(F) возвращает значение True, то значение, воз- вращаемое функцией FilePos(F), совпадает со значением, возвращае- мым функцией FtleSize(F) (то есть с размером файла) Функция FileSize function FileSize(var F): Longint; < Реальный режим, защищенный режим, Windows ) Назначение Возвращает текущий размер файла Параметр F представляет собой файловую переменную Данная функция возвращает число элементов в F Если файл пуст, функция возвращает значение О Функция не может использоваться для текстового файла Файл дол- жен быть открыт
337 Процедура FillChar .ct<urc Ь1Н hiir(var X; Count: Word; Vai); i"'11 ( реальный режим, заипиисмный режим, Windows ) Помешает в заданное число следующих друг за другом байт указан- ное значение. Параметр X является ссылкой на переменную любого типа. Count представляет собой выражение длиной в слово, Vai является выра- жением перечисляемого типа. Процедура записывает значение, указанное в параметре Vai, в то количество следующих друг за другом байтов памяти, начиная с первого байта, занимаемого пере- менной х, которое определяется параметром Count. Проверка на до- пустимость границ нс выполняется. Процедура Flush procedure Flush(var F: Text); ( Реальный режим, защищенный режим, Windows ) На точение: Выводит содержимое буфера открытого для вывода текстового фаада. Параметр F является файловой переменной •текстового типа, Функция Frac function Frac(X : Real): Real; ( Реальный режим, защищенный режим, Windows ) На яшчеиие Возвращает дробную часть аргумента. Параметр х является выражением вещественного шла Результа- том является дробная часть X, то есть Frac(X) - X - Int(X) Процедура FreeMem procedure FreeMeM<var P : Pointer; Size : Word); ( Реальный режим, защищенный режим. Windows ) 1чение' Уничтожает динамическую переменную данного размера Параметр Р является указателем на переменную (относящимся к любому типу указателей), для которою было предварительно вы- полнено присваивание с помощью процедуры GctMeM, или которо- му было присвоено значение с помощью оператора присваивания. Параметр Size представляет собой выражение /тиной в слово, ко- "рое задает размер уничтожаемой динамическом переменной (в байтах) Его значение должно в точности соответствовать числу бай- "»в памяти Мем Прон переменной процедурой Get- .....^ мгнмую. на которую ука- >ги в динамически рас- • ится на область памя- iriiHbix ранее для ' 1ем уни’П<‘ * мнятую ей 1И, Ю ВО >Ч’ 1НСИИЯ имения к П[ Мем цится неопределенным, о, к ошибке
Приложение 1 Стандартные процедуры 338 Процедура GetDir 1 procedure GetDir(D: Byte; var S: String); J ( Реальный режим, защищенным режим, Windows ) 1 Назначение Возвращает текущий каталог на заданном диске Параметр D представляет собой выражение целого типа, a S — Пе. i ременную строкового типа Значение текущего каталога на диске ] заданного параметром D, возвращается в переменной S | Значение D = 0 указывает на текущий дисковод, 1 — залает дисковой А, 2 — В и т д_____________________________________ Л Процедура GetMem procedure GetMem(var Р; Pointer; Size: Word); ( Реальный режим, защищенный режим, Windows ) Назначение Создает новую динамическую переменную указанного размера, и помещает адрес блока в переменную-указатель Параметр Р является переменной-указателем и может относится к любому типу указателей Параметр Size имеет длину в слово и м дает размер (в байтах) области памяти, выделяемой для динамиче ской переменной На вновь созданную переменную можно ссылать ся с помощью Р" Наибольший блок, который может быть выделен в динамически распределяемой области памяти, составляет 65521 байт Процедура Halt procedure Halt [ (ExtCode: Word) ]; ( Реальный режим, защищенный режим, Windows ) Назначение Останавливает выполнение программы и возвращает управ кt операционной системе Параметр ExtCode (код завершения) представляет собой нео( тельное выражение длиной в слово, которое задает код заверш программы Процедура Halt без параметров соответствует bi Halt(O) Код завершения может проверяться порождающим проис*- с помощью функции ExitCode модуля Dos или с помощью npOBi 1 ERROR! EVEt в командном файзе DOS Функция Hi function Hi(X): Byte; ( Реальный - Назначение Во t k ioro типа изи с Функция Hi возвращает старший байт X в виде значения без jhj* Функция High function High(X); ( Реальный г 4 \< j ьы н-ннп» Назначение Вс Пц ификатор ссылочной перемен нои Обозначенные “ <^кИ1.и
<* cpode Turbo Pascal 7 p 339 должен быть ПОРЯДКОВЫМ порядкового гнпа High возвращаётМстпп °°М 1L'1' Сф(ЖовЬ|м ™"‘>м Для Для типа массива High возвозипет ^“’Се значение в диапазоне типа, дексного типа массива Для стоек,, ар'"ее 3™чение в диапазоне ин- КЫЙ размер строки. Для открытого мае™ H‘sb BO1BPaluaCT описан- ие гра High возвращает значение типа Word™™ я™ Строкового паРа- в фактическом параметре, минус 1. ' зь,ная числ0 элементов Процедура1пс procedure Inc(X [ ; N : Longint ] ); ( Реальный режим, защищенный режим, Windows ) Назначение: Увеличивает значение переменной. Параметр X представляет собой переменную перечисляемого типа, a N — целочисленное выражение. Значение X увеличивается на 1 (или на N в случае Явного задания N). То есть 1'пс(Х) соответствует X .- Х+1, a Inc(X.N) соответствует X := X+N. Функция Inc порождает on- тимизированный код и особенно полезна в больших циклах. Процедура Include procedure Include(var S: set of T; I: T); ( Реальный режим, защищенный режим ) Назначение: Включает элемент в множество, S — это переменная множествен- ного типа, а I — выражение типа, совместимого с базовым типом S За- данный I элемент включается в множество, заданное S. Конструкция: lnclude(S, I) соответствует: S := S + [1], но процедура Include генерирует более эффективный код. Процедура Insert procedure Insert(Stringl: String; var S: String; Indx: Integer); ( Реальный режим, защищенный режим, Windows) Назначение- Вставляет в строку подстроку. Параметр Stnngl представляет собой выражение строкового типа Па- раметр S — переменная строкового типа любой длины Параметр Indx является выражением целого типа. Данная процедура вставляет строку, задаваемую параметром String 1, в строку, задаваемою метром S, начиная с позиции, определяемой параметром п _ получившаяся в результате строка превышает 255 символов, то он кается до 255 символов . . Функция Int function lnt(X : Real/; Real; ( Реальный режим, защищенный режим, Windows ) /М значение Возвращает целую часть аргумента. „,..„„птгапа Ре- Параметр X представляет собой выражение вещественного типа. Ре зультатом будет целая часть X. то есть X округляется в стор у у.
Приложение > процмур,, и , 340 функция lOResult funct’°° “ режГм. защищенный режим. W.ndows ) Назначение Возвращает целое значение, представляющее собой состояние послед ней выполненной операции ввода-вывода Чтобы перехватить ошибки ввода-вывода с помощью функции 10R esult проверка ввода-вывода должна быть выключена (директива ком пилятора ($1-)) Если проверка ввода-вывода выключена и происходит ошибка ввода-вывода, то, пока выполняется обращение к функции lOResult, все последующие операции ввода-вывода игнорируются Об- ращение к функции lOResult сбрасывает ее внутренний флаг ошибки Функция Length function Length(S: String): Integer; ( Реальный режим, защищенный режим, Windows ) Назначение Возвращает динамическую длину строки Параметр S представляет собой выражение строкового типа Резуль- татом будет длина S Функция Ln function Ln(X: Real): Real; ( Реальный режим, защищенный режим, Windows ) Назначение Возвращает натуральный логарифм аргумента Параметр X является выражением вещественного типа Результа- том будет натуральный логарифм выражения X Функция Lo function Lo(X): Byte; ( Реальный режим, защищенный режим, Windows ) Назначение Возвращает младший байт аргумента Параметр X — это параметр целого типа или параметр длиной в слово Функция Lo возвращает младший байт X в качестве беззпако вого значения Функция Low function Low(X); ( Реальный режим, защищенный режим, Windows ) означение Возвращает младшее значение в диапазоне аргумента Параметр X — это иденгификатор типа, или ссылка на перемен ную Тип, обозначенный X, или тип переменной, обозначенный X должен быть порядковым типом, типом массива или строковым зи пом Для порядкового типа функция Low возвращает младшее зна чение в диапазоне типа Для типа массива Low возвращает младше значение в диапазоне индексного типа массива Для строкового тип Low возвращает 0 Для открытого массива или строкового параметр Low возвращает 1
„цмчрооакм " среда Turbo Pascal 7 о Функция MaxAvail function MaxAvail: ixingint; ( Реальный режим, защищенный режим. Windows ) Имение: Возвращает размер наибольшего свободного блока п ски распределяемой области памяти Динамиче- «то расда™» « NJ, "о“" ^уйХкнГме^Г ДИНамтесКИ Распределяемой памяти ис- функция MemAvail function MemAvail: Longint; ( Реальный режим, защищенный режим, Windows) Назначение. Возвращает число свободных блоков в динамически распреде- ляемой области памяти Данное число определяется путем сложения размеров всех свободных блоков, расположенных ниже указателя динамически распределяемой области памяти, с объемом свободной памяти, расположенной выше указателя динамически распределяемой области Заметам, из-за фраг- ментации динамически распределяемой области памяти маловероятно, что будет доступен блок памяти, размер которого соответствует возвращаемому значению Для получения размера наибольшего сво- бодного блока используйте функцию MaxAvajJ Процедура MkDir procedure MkDir(S: String); ( Защищенный режим, Windows ) Назначение: Создает подкаталог Параметр S представляет собой выражение строкового типа Создается новым каталог с маршрутом доступа, заданным строкой S Последний элемент этой записи не может гаааватъ имя существующего файла Процедура Move procedure Movefvar Src, Dst; Count: Word); ( Реальный режим, защищенный режим. Windows ) Назначение: Копирует ыланное чисто непрерывных байтов из заданного диапазо- на в указанный целевой диапазон Параметры Src и Dst представляют собой указатели на переменные любого типа Параметр Count — это >......- типа Word Процеду- 1и копирует байтовый блок и I1 которого (в байтах) м Count, в блок.. Ийся с первого байта. ,юм Dst С данной процедурой следует работать аккур.пи" по, юп.ку никаких проверок не выполняется Процедура New procedure Newtvar Р: Pointer); I I\.i пап щ pea ич i шнипенный режим, Windows ) Нашачтт Г...Ц , и.,, к, шнамическую переменную и устанаази:
Приложение 1 Сто Параметр Р является переменной-указателем и спросится к УКа 1 лям любого типа. Размер выделяемого блока памяти соответ^ размеру того типа, на который указывает Р. На вновь созданн™ переменную можно ссылаться с помощью Р . Если для выделе ния памяти под новую динамическую переменную в динамически распределяемой области недостаточно свободной памяти, то во время выполнения программы происходит ошибка.___________ Функция Odd fraction Odd(X: Longint): Boolean; ( Реальный режим, защищенный режим, Windows ) Назначение: Проверяет, является ли аргумент нечетным числом. Параметр X — это выражение длинного целого типа. Результат принимает значение True, если х представляет собой нечетное число и False — в противном случае. Функция Ofs function Ofs(X): Longint; ( Реальный режим, защищенный режим. Windows ) Назначение' Возвращает для заданного объекта смещение. Параметр X представляет собой любую переменную или идентифи- катор процедуры или функции. Результат длиной в слово представ- ляет собой смешение для X. Функция Ord function Ord(X): Longint; ( Реальный режим, защищенный режим, Windows ) Назначение' Возвращает порядковый номер для значения перечисляемого типа Па- раметр X предстаапяет собой выражение перечисляемого тепа. Ре- зультат имеет длинный целый теп и его значение является порядко- вым номером X. Функция ParamCount function ParamCount: Word; < Реальный режим, защищенный режим. Windows ) Назначение. Возвращает число параметров, переданных в командной строке Раз- делителями служат пробелы и символы табх'ляцни Функция ParamStr function ParaMStr(Indx): String; ( Реальный режим, защищенный режим, Windows ) Назначение Возвращает заданный параметр командной строки -и выражение типа Word. Данная фумк- роки параметр, номер которого задает- ' -< -' '‘•’н строку, если Indx равняется нулю ши ooibiuc, чем РагамСоиш
e сро.чр < urbo Pascal / и 343 Функция Pi tion Pi: Reul, ( реальный режим, защищенный режим Windows) Возвращает значение 3.1415926535897ЧЛэде< висимоста от того, работает ли компилятор в Р‘’' В 8087 (80287, 80387), или только в режим^пХХогоХщчХ точность может меняться. обеспечения, Функция Pos function Pos(Sub, S: String): Byte; ( Реальный режим, защищенный режим, Windows) Назначение: Ищет подстроку в строке. Параметры Sub и S являются выражениями строкового типа. Данная функция ищет подстроку, заданную параметром Sub, в строке S и возвращает целое значение, являющееся позицией первого сим- вола подстроки в строке S. Если подстрока не найдена, то функция возвращает значение 0. Функция Pred function Pred(X); ( Реальный режим, защищенный режим, Windows) Назначение: Возвращает предшествующее значение аргумента. Параметр X — выражение перечисляемого типа. Результат, имею- щий тот же тип. что и X, является предшествующим значением X Функция Ptr function Ptr(Seg, OfTs: Word): Pointer; ( Реальный режим, защищенный режим, Windows) Назначение: Преобразует адрес, заданный 8 виде базового сегмента и смешения, в значение типа указатель. Параметры Seg (сегмент) и Offs (смешение) представляют собой вы- ражения типа Word Результатом является указатель на адрес, задан- ный параметрами Seg и Offs Результат функции Ptr совместим по присваиванию с указателями любых типов Функция Random function Random( (Range: Word) ]; ( реальный режим, защищенный режим. Windows ) /А. Bt. wtpjinnrT случайное число. J ,.i N iметр Range (диапазон) не задан, то . вс* цксп-нное число х в диапазоне 0 <= х < I ,еТР Range, го он должен > " 1’ результатом будет слу шапаэоме х ’ N, где N — значение. .....- , 1!,8е па^ метр Range меньше или равен нулю, то волврашаемое значение у лег равно нулю .
Приложение 1 Стандартные процедуры и фун Процедура Randomize ’ procedure Randomize; . \ ( Реальный режим, защищенный режим, Windows) Назначение. Инициализирует встроенный генератор случайных чисел случайным значением. Случайное значение получается от системного таймера. Число, полу- чаемое в результате работы генератора случайных чисел, хранится в предопределенной переменной с именем RandSeed. Процедура Read (текстовые файлы) procedure Read( [ var F: Text; ] VI, [, V2,...,Vn ] ); ( Реальный режим, защищенный режим, Windows) Назначение- Считывает одно или более значений из текстового файла в одну или более переменных. Параметр F (если он указан) является файловой переменной, соответствующей текстовому файлу Если он опушен, то подразумевается использование стандартной файловой переменной Input. Каждый параметр V является переменной символьного, стро- кового, целого или вещественного типа Процедура Read (типизированные файлы) procedure Read(F, VI, [, V2,...,Vn]); ( Реальный режим, защищенный режим, Windows ) Назначение Считывает в переменную элемент файла Параметр F является файловой переменной, соответствующей любому типу файла, кроме текстового, а каждый элемент V представляет со- бой переменную того же типа, что и элемент файла F При каждом считывании в переменную текущая позиция в файле продвинется к следующему элементу Попытка считывания следующего элемента файла в тот момент, когда текущая позиция файла находится в кон- це файла (то есть когда Eof(F) имеет значение True) является ошиб- кой Файл должен быть открыт Процедура ReadLn procedure Reading var F: Text; ] VI [, V2,...,Vn j ); ( Реальный режим, защищенный режим, Windows ) Назначение- Выполняет процедуру Read, затем переходит к следующей строке флипа Процедура Read Ln является расширением процедуры Read и 'ена для текстовых файлов После выполнения процедуры [юиедура ReadLn делает пропуск до начала следующей строки ’м ’ тмя работает только для текстовых файлов, включая стандарт- ный ввод Файл должен быть открыт для ввода Процедура Rename procedure * л режим, Windows ) Ч" •' .... .I-.,., п.п.метр F предстаатч . любому файловому гм, строкового типа или ти
345 tHMUpW11'1' " ироде Turbo Pascal 7 о nil PChar (если разрешен п файлу, связанному с переменно^гХХ™^™^ Вн™н=му параметром NewName Дальнейщие'опГоТиИмя- тев™« с внешним файлом с новым именем " С F будут ““полниться Процедура Rename не должна «mo» ------------------ а использоваться для открытого файла Процедура Reset procedure Reset(F [: file; Size : Won! ] ); ( Реальный режим, защищенный режим, Windows) Назначение Открывает существующий файл Параметр F является файловой переменной, соответствующей любом-.- типу файла Он должен быть связан с внешним файлом с помощью процедуры Assign Параметр размера Size представляет собой необя- зательное выражение длиной в слово и может указываться только в том случае, если F является нетипизированным файлом Процедура Rewrite procedure Rewrite(F [ : file; Size: Word ] ); ( Реальный режим, защищенный режим. Windows ) Назначение Создает и открывает новый файл Параметр F является файловой переменной, соответствующей любому типу файла Он должен быть связан с внешним файлом с помощью процедуры Assign Параметр размера Size представляет собой необяза- тельное выражение длиной в слово и может указываться только в том случае, если F является нетипизированным файлом Если этот параметр опушен, то подразумевается размер записи в 128 байт Процедура RmDir procedure RmDirfS: String); ( Реальный режим, защищенный режим. Windows ) Назначение Удаляет пустой подкаталог ___ Параметр S является выражением строкового типа лог с путем доступа, заданным строкой S Если путь доступа не су- шествХяХтая непустым или если он задает текущий каталог, то происходит ошибка ввода- вывода _______ Функция Round function RoundfX: Real). Longmt; ( Реальный режим, защищенный режим in // ... Blaine Округляет значение вещественного типа Параметр х представляет собой вы₽“™ Функция Round возвращает значение д рос я, -.-нисм X округленным ла I значения ueioiu ниы вещественного типа - "-«го типа, кото- <> цеюго чис- тежлх двумя целы ным п азо 11 .’Vi .. 1ИННОГО цемяо ПРОИСЧ< > 1И I . ни,, ,
Приложение I Стенину tnnL<t <jyf,, Процедура RunError procedure RunError [ (ErrCodc . Word ) ]; ( Реальный режим, защищенный режим, Windows ) Назначение Останавливает выполнение программы и генерирует ошибку этапа выполнения Процедура RunError аналогична процедуре Halt, но в дополнение к остановке программы она генерирует на текущем операторе ошибку этапа выполнения Параметр ErrCode представляет собой но- мер ошибки этапа выполнения Если текущий модуль был скомпили рован с установленным параметром Debug Information (Отладочная информация), и вы запускаете программу из среды интерактивной отладки IDE, то Turbo Pascal обрабатывает обращение к RunError, как обычную ошибку этапа выполнения Процедура Seek procedure SeekfF, N: Longint); ( реальный режим, защищенный режим, Windows ) Назначение Перемещает текущую позицию в файле к заданному элементу Па- раметр F является любой файловой переменной, кроме текстовой, а п представляет собой выражение целого типа Текущая позиция в фай- ле F перемешается к элементу с номером N Номер первого элемента файла равен 0 Для того, чтобы расширить файл, можно выполнить поиск элемента файла, расположенного за последним элементом То есть оператор Seek(F,FileSize(F)) перемешает текущую позицию в файле в конец файла Процедуру нельзя использовать для текстовых файлов Файл должен быть открыт Функция SeekEof function SeekEof ( (var F: Text) ]; Boolean; ( Реальный режим, защищенный режим, Windows ) Назначение Возвращает для файла состояние “конец файла” (end-of-file) За исключением того, что функция SeekEof пропускает все пробелы, знаки табуляции и метки конца строки, она полностью соответствует функции Eof Ее полезно использовать при считывании числовых зна чений из текстового файла Функцию можно использовать только для текстовых файлов Файл золжен быть открыт Функция SeekEoln function SeekEoln ( (var F : Text) ]; ( Реальный режим, защищенный режим, Windows ) Назначение Возвращает для файла состояние “коней строки’ (end-of-Iine) За исключением того что функция SeekEoln пропускает все пробелы и знаки табуляции, она полностью соответствует функции Eoln Г полезно использовать при считывании из текстового файла числ< вых значений Функцию можно использовать только для текстовых файлов Файл должен быть открыт
6 среде Turbo Pascal ? о "" -- - 347 Функция Seg flinc(ion Scg(X): Word; ( Реальный режим, защищенный режим Windows ) Процедура SetTextBuf procedure SetTextBuf(var F: Text; var Buf [ ; Size; Word]); ( Реальный режим, защищенный режим, Windows) Назначение Назначает для текстового файла буфер ввода-вывода Параметр F представляет собой файловую переменную, соответст- вующую текстовому файлу Параметр Buf (буфер) — любая пере- менная, а параметр Size (размер) — необязательное выражение дли- ной в слово Данная процедура никогда не должна применяться для открытого файла, хотя вызывать ее можно немедленно вслед за обращением к процедурам Reset, Rewrite и Append Вызов процедуры SetTextBuf для открытого файла во время выполнения операций ввода-вывода может из-за смены буфера привести к потере данных Функция Sin function Stn(X: Real): Real; ( Реальный режим, защищенный режим, Windows ) Назначение Возвращает синус аргумента Параметр X является выражением вещественного типа Результа- том будет синус X Предполагается, что это значение задает угол в радианах Функция SizeOf function StzeORX): Word; ( Реальный режим, защищенный режим, Windows ) Назначение Возвращает число байт, занимаемых аргументом Параметр X является ссылкой на переменную или типа Данная функция возвращает число байтов п X Функция SPtr ' п s?tr Word, Реальный режим,