МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ РЕСПУБЛИКИ КАЗАХСТАН ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ имени ШАКАРИМА г. СЕМЕЙ Документ СМК 3 уровня УМКД УМКД 042-39. 1.ХХ/032013 УМКД Редакция №____от_____ Учебно-методические материалы по дисциплине «Программирование II» УЧЕБНО-МЕТОДИЧЕСКИИ КОМПЛЕКС ДИСЦИПЛИНЫ «Программирование II» для специальности 5В011100 – «Информатика » УЧЕБНО-МЕТОДИЧЕСКИЕ МАТЕРИАЛЫ Семей 2013 СОДЕРЖАНИЕ 1 2 3 4 5 Глоссарий Лекции Практические и лабораторные занятия Курсовая работа (проект) Самостоятельная работа студента 1. ГЛОССАРИИ Абстрагирование (abstraction). Метод решения задач, при котором объекты разного рода объединяются общим понятием (концепцией). Затем сгруппированные сущности рассматриваются как элементы единой категории. Несущественная информация игнорируется. Абстрактный класс (abstract с1аss). Класс, который не используется для создания экземпляров. Он служит исключительно для порождения других классов. В языке С++ этот термин относится к классам, которые содержат хотя бы один чисто виртуальный метод. В языке Java абстрактным считается класс, явно объявленный с ключевым словом abstract. См. также отложенный класс. Абстрактный метод (abstract method) Метод, который явно объявлен с ключевым словом abstract. Такие методы должны быть переопределены до их вызова. Автоматическое управление памятью (automatic storage manedgement). Алгоритм распределения памяти, при котором исполнительная система нижнего уровня отвечает за нахождение и повторное использование недоступных (а следовательно, ненужных) блоков памяти. Из рассматриваемых в этой книге языков только Smalltalk и Java обеспечивают автоматическое управление памятью. См. также: сборка мусора. Базовый класс (base с1аss). Класс, из которого порождается другой класс. Синонимы: класс-предок, надкласс, родительский класс. Глобальная переменная (g1оЬа1 variable). Переменная, к которой потенциально разрешен доступ из любого места программы. Деструктор (destructor) . Метод, который вызывается непосредственно перед тем, как освобождается память, занимаемая объектом. Деструктор может выполнять любые необходимые действия. Имя деструктора конструируется из символа “тильда” (~), за которым следует имя класса1. Динамическая переменная (dynamic variable). Переменная, для которой память выделяется явной командой пользователя. Противопоставляется автоматической переменной, память для которой отводится автоматически при входе в процедуру. Динамический тип данных (daynamic tуре). Тип данных, связанный со значением, которое содержится в переменной в текущий момент. Он не обязательно совпадает со статическим типом данных, присвоенном переменной при ее объявлении. В объектно-ориентированных языках программирования динамический тип, как правило, является потомком статического типа. Динамическое связывание (dynamic binding). Связывание имени и атрибута, которое производится во время выполнения программы, а не во время компиляции. Закрытый метод (рrivate method). Метод, который не предназначен для вызова извне объекта. Более конкретно: получатель сообщения, которое приводит к вызову такого метода, должен быть обязательно объектом того же класса, которому принадлежит отправитель сообщения (см. ключевое слово self). Противопоставляется открытым методам. Идентификатор метода (method designator). Идентификатор имени метода. Используется как имя процедуры или функции в выражении типа пересылки сообщения. Идентификатор метода применяется при поиске подходящего метода при пересылке сообщения. В общем случае, зная только идентификатор метода, невозможно определить из текста программы, какой именно метод будет активизирован во время выполнения. Синоним: селектор сообщения. Идентификатор поля объекта (object field designator). Идентификатор (возможно, составной), который определяет поле внутри объекта. Иерархия (hierarchy). Структура, упорядоченная по подчиненности в соответствии с некоторым набором правил. В объектно-ориентированном программировании иерархия обычно образуется связями “класс-подкласс”. Иерархии классов (class hierarchy). Иерархия, образуемая классами в соответствии с их взаимосвязью “класс-подкласс”. См. также иерархия. Иерархия объектов (object hierarchy). В языке Оbject Pascal последовательность объектных типов, связанных через наследование. Синоним: иерархия классов. Инкапсуляция (encapsulation). Техника, при которой информация прячется внутри структуры подобно тому, как данные, связанные с экземпляром класса, прячутся внутри класса. Класс (с1аss). Абстрактное описание данных и поведения для совокупности похожих объектов, представители которой называются экземплярами класса. Синоним: объектный тип данных. Класс-предок (аncestor с1аss) Тип данных, из которого производится наследование. Класс, указанный при определении объектного типа, называется непосредственным предком. Синонимы: базовый класс, надкласс. Композиция (composition). Техника, при которой новый объект получается композицией, объединением старых и новых частей. Противопоставляется наследованию. Конструктор (constructor). Метод, используемый для создания нового объекта. Обеспечивает решение двух задач: он выделяет память под новую переменную и гарантирует, что переменная инициализируется надлежащим образом. Описывая конструктор, программист влияет на процесс инициализации. Контейнерные классы (соntainer сlasses). Классы, которые используются как структуры данных, содержащие набор элементов. Примеры контейнерных классов: списки, множества, таблицы Метакласс (metaclass). Класс объекта-класса. Для каждого класса имеется ассоциированный с ним метакласс. Объект-класс является правило, единственным экземпляром метакласса. Метаклассы позволяют 4 специфировать поведение классов. Без них все классы (но не экземпляры классов!) стали бы вести себя идентично. Метапрограммирование (metaprogramming). Стиль программирования, который интенсивно использует метаклассы. При этом семантика языка и смысл различных конструкций видоизменяются средствами самого же языка программирования.. Метод (method). Процедура или функция, связанная с классом (или объектным типом), вызываемая в стиле пересылки сообщений. Наследование (inheritance). Свойство объектов, посредством которого экземпляры класса получают доступ к данным и методам классов-предков без их повторного определения. См. также: класс-предок. Объектно-ориентированное программирование, ООП (objectoriented programming). Стиль разработки программ, который состоит в делегировании обязанностей независимым взаимодействующим агентам. Характеризуется использованием пересылки сообщений и классов, организованных в иерархию (иерархии) наследования. Объектный тип данных (object type). В языке Оbject Раscal — структура, аналогичная записи (record), которая наряду с полями данных содержит поля процедур и функций (то есть методы). Синоним: класс. Объявление метода (method declaration). Часть объявления класса, которая относится к конкретному методу. Парадигма (раradigm). Базовая модель конкретного способа организации информации. Объектно-ориентированная парадигма делает упор на поведении и обязанностях. Параметризованные классы (parametrized classes). Классы, в определении которых некоторые типы данных оставлены неопределенными. До создания экземпляров класса происходит доопределение неизвестных типов. Переопределение метода (override). Действие, которое происходит, когда метод подкласса имеет то же самое имя, что и метод надкласса. Метод подкласса имеет приоритет по сравнению с методом надкласса. Обычно во время связывания сообщений и методов выбирается переопределенный метод. Селектор сообщения (message selector). Текстовая строка, которая идентифицирует сообщение при пересылке сообщений. Она используется для того, чтобы найти соответствующий метод (что является частью процесса поиска требуемого метода). Синонимы: селектор, селектор метода, идентификатор метода. Сообщение (message). Текстовая строка, которая определяет требуемое действие при пересылке сообщений. Эта строка используется для того, чтобы найти соответствующий ей метод (что является частью процесса поиска требуемого метода). Синонимы: селектор, селектор сообщения, селектор метода, идентификатор метода. 5 Экземпляр (instance). В языке С++ - переменная типа с1аss. В языке Object Pascal - объектная переменная. В языке Smalltalk - конкретный пример структуры общего вида, определяемой классом. Синоним: объект. 2. ЛЕКЦИИ Лекция 1 Тема: Объектно-ориентированное программирование. Основные принципы ООП. Цель: Рассмотреть основные понятия и принципы ООП. Объектно-ориентированное программирование (ООП) зародилось в языках программирования Паскаль, Ада, С++. До появления ООП технология создания компьютерных программ базировалась на процедурном программировании, в котором основой программ являлись функции и процедуры, т.е. действия. Созданная т.о. компьютерная программа отличалась четким алгоритмом работы – последовательностью действий по достижению поставленной цели. В ООП основной точкой опоры при проектировании программы является – объект. Программа ООП – это не последовательность операторов, а совокупность объектов и способов их взаимодействия. Обмен информацией между объектами происходит посредством сообщений. Объектом назовем понятие, абстракцию или любой предмет с четко очерченными границами, который имеет смысл в контексте рассматриваемой прикладной проблемы. Объекты могут наследовать характеристики и поведение других объектов, называемых родительскими или предками. Наличие механизма наследования является самым существенным различием между обычным программированием на Pascal ООП программированием в Delphi. Основным понятием ООП является понятие класса: классом – называют особую структуру, которая может иметь в своем составе поля, методы и свойства. Наследование. В терминах Паскаль объект наиболее схож с типом Record, который является структурированным типом для объединения нескольких связанных элементов под одним именем. Процесс, с помощью которого один тип наследует характеристики другого типа, называется наследованием. В Delphi все классы являются потомками класса TObject. Свойства объекта. Совокупность данных и методов их чтение и записи называются свойством. Свойства объектов можно устанавливать в процессе проектирования, а также можно изменять программно во время выполнения программы. (В процессе проектирования приложений в среде программирования Delphi можно просматривать значения некоторых из этих данных в окне Инспектора Объектов и изменять эти значения). 6 События и их обработка. Средой взаимодействия объектов являются сообщения, генерируемые в результате наступления различных событий. Событие – это взаимодействие на объект. Событие наступает в результате действий пользователя (перемещение курсора, нажатие кнопки и т.п.). В каждом объекте определено множество событий, на которые он может реагировать. В конкретных объектах могут быть определены обработчики каких-то из этих событий. К написанию этих обработчиков и сводится основное программирование с помощью Delphi. Таким образом, можно определить объект как совокупность свойств и методов, а также событий, на которые он может реагировать. Внешнее управление объектом осуществляется через обработчики событий. Эти обработчики обращаются к методам и свойствам объекта. Начальные значения данных объекта могут задаваться также в процессе проектирования установкой различных свойств. В результате выполнения методов объекта могут происходить новые события, воспринимаемые другими объектами программы или пользователем. Контрольные вопросы 1. Дайте определение ООП. 2. Что называется объектом? 3. Дайте определение события Лекция 2 Тема: Объектно-ориентированное программирование. Инкапсуляция. Наследование. Полиморфизм. Описание объектового типа. Виртуальные методы. Цель: дать понятие инкапсуляции, классов и методов. Объектно-ориентированное, или объектное, программирование (в дальнейшем ООП) — парадигма программирования, в которой основными концепциями являются понятия объектов и классов. В случае языков с прототипированием вместо классов используются объекты-прототипы. Объектно-ориентированное программирование базируется на трех важнейших принципах, придающих объектам новые свойства. Этими принципами являются инкапсуляция, наследование и полиморфизм. 1. Инкапсуляция - это объединение в единое целое данных и алгоритмов обработки этих данных. В рамках ООП данные называются полями объекта (свойствами), а алгоритмы - объектными методами или просто методами. Инкапсуляция позволяет в максимальной степени изолировать объект от внешнего окружения. Она существенно повышает надежность разрабатываемых программ, т.к. локализованные в объекте алгоритмы обмениваются с программой сравнительно небольшими объемами данных, причем количество и тип этих данных обычно тщательно контролируются. В результате замена или модификация алгоритмов и данных, инкапсулированных в объект, как правило, не влечет за собой плохо прослеживаемых последствий для программы в целом (в целях повышения 7 защищенности программ в ООП почти не используются глобальные переменные). Другим немаловажным следствием инкапсуляции является легкость обмена объектами, переноса их из одной программы в другую. 2. Наследование - есть свойство объектов порождать своих потомков. Объект-потомок автоматически наследует от родителя все поля и методы, может дополнять объекты новыми полями и заменять (перекрывать) методы родителя или дополнять их. Принцип наследования решает проблему модификации свойств объекта и придает ООП в целом исключительную гибкость. При работе с объектами программист обычно подбирает объект, наиболее близкий по своим свойствам для решения конкретной задачи, и создает одного или нескольких потомков от него, которые "умеют" делать то, что не реализовано в родителе. 3. Полиморфизм - это свойство родственных объектов (т.е. объектов, имеющих одного общего родителя) решать схожие по смыслу проблемы разными способами. В рамках ООП поведенческие свойства объекта определяются набором входящих в него методов. Изменяя алгоритм того или иного метода в потомках объекта, программист может придавать этим потомкам отсутствующие у родителя специфические свойства. Для изменения метода необходимо перекрыть его в потомке, то есть объявить в потомке одноименный метод и реализовать в нем нужные действия. В результате в объекте-родителе и объекте-потомке будут действовать два одноименных метода, имеющие разную алгоритмическую основу и, следовательно, придающие объектам разные свойства. Это и называется полиморфизмом объектов. Объектом в языке Паскаль называется совокупность данных, процедур и функций, обрабатывающих эти данные. Данные в объекте называются полями, а процедуры и функции - методами. Поля объектов описываются так же, как поля записей, а описание метода - это заголовок процедуры или функции. Виртуальный метод (виртуальная функция) — в объектноориентированном программировании метод (функция) класса, который может быть переопределён в классах-наследниках так, что конкретная реализация метода для вызова будет определяться во время исполнения. Виртуальные методы — один из важнейших приёмов реализации полиморфизма. Они позволяют создавать общий код, который может работать как с объектами базового класса, так и с объектами любого его класса-наследника. При этом базовый класс определяет способ работы с объектами, и любые его наследники могут предоставлять конкретную реализацию этого способа. Контрольные вопросы 1. Назовите три принципа ООП и дайте им определение 2. Что означает виртуальный метод 8 Лекция 3 Тема: Динамическое создание объектов. Конструкторы и деструкторы. Скрытые поля и методы. Цель: ввести понятие конструкторов и деструкторов. Динамическое создание объектов. Динамические объекты предоставляют такие элементы, как свойства и методы, во время выполнения, а не во время компиляции. Это позволяет создавать объекты для работы со структурами, не соответствующими статическому типу или формату. Динамические объекты обеспечивают удобный доступ к динамическим языкам, таким как IronPython и IronRuby. С помощью динамического объекта можно ссылаться на динамический скрипт, интерпретируемый во время выполнения. Список команд, позволяющих динамически создавать объекты: Создание кнопки – CreateTextButton ("inlabel","outlabel$,x,y,w,h,text") Создание текстового объекта - CreateText("inlabel","outlabel$,x,y,text") Создание текста с полосой прокрутки CreateParagraph("inlabel","outlabel$,x,y,w,h,text") Создание круга - CreateCircle("inlabel","outlabel$,x,y,w,h,r,g,b") Создание прямоугольника CreateRectangle("inlabel","outlabel$,x,y,w,h,r,g,b") Создание линии (относительное позиционирование) CreateLine("inlabel","outlabel$,x,y,w,h,r,g,b") Создание прямоугольника (абсолютное позиционирование) CreateLineAB("inlabel","outlabel$,x1,y1,x2,y2,r,g,b") Создание активной области - CreateHotSpot("inlabel","outlabel$,x,y,w,h") Создание скрипта - CreateScript("inlabel","outlabel$") Конструкторы и деструкторы В объектно-ориентированном программировании конструктор класса (от англ. constructor, иногда сокращают ctor) — специальный блок инструкций, вызываемый при создании объекта. Конструктор схож с методом, но отличается от метода тем, что не имеет явным образом определённого типа возвращаемых данных, не наследуется, и обычно имеет различные правила для рассматриваемых модификаторов. Их задача — инициализировать члены объекта и определить инвариант класса, сообщив в случае некорректности инварианта. Корректно написанный конструктор оставит объект в «правильном» состоянии Некоторые языки программирования различают несколько особых типов конструкторов: конструктор по умолчанию — конструктор, не принимающий аргументов; конструктор копирования — конструктор, принимающий в качестве аргумента объект того же класса (или ссылку из него); 9 конструктор преобразования — конструктор, принимающий один аргумент (эти конструкторы могут вызываться автоматически для преобразования значений других типов в объекты данного класса). Деструктор — специальный метод класса, служащий для деинициализации объекта (например освобождения памяти). Для объявления деструктора в Delphi используется ключевое слово destructor. Имядеструктора может быть любым, но рекомендуется всегда называть деструктор Destroy. В Delphi все классы являются потомками, по крайней мере, класса TObject, поэтому, для корректного освобождения памяти, необходимо перекрывать деструктор, используя директиву override. Практически всегда деструктор делается виртуальным. Делается это для того, чтобы корректно (без утечек памяти) уничтожались объекты не только заданного класса, а и любого производного от него. Например: в игре уровни, звуки и спрайты могут создаваться загрузчиком, а уничтожаться — менеджером памяти, для которого нет разницы между уровнем и спрайтом. Скрытые поля и методы. Скрытые поля формы определяются с помощью <input type="hidden" />. Они используются для предоставления информации о состоянии элемента управления программам сервера. Скрытые элементы формы никогда не отображаются на экране, но их пары "имя-значение" будут отправлены серверу при подаче запроса. Ввиду того что эти элементы не имеют визуального представления и не допускают интерактивного взаимодействия, синтаксис скрытых полей XHTML таков: <input type=" hidden" name="имя поля" id="имя поля" value="значение" /> Свойства JavaScript, полезные для работы со скрытыми полями, это disabled, form, id, name и value. Во многих задачах, требующих сохранения информации о состоянии, без скрытых полей обойтись трудно. Использование скрытых полей для сохранения информации о состоянии элементы управления несет в себе потенциальную опасность — их содержимое может без труда увидеть и случайно или намеренно изменить любой конечный пользователь. Контрольные вопросы 1. Что представляет собой конструктор ? 2. Какие типы конструкторов различают? 3. Что представляет собой деструктор? Лекция 4 Тема: Теоретические основы объектно-ориентированного программирования. От процедурного программирования к объектному. Основные принципы и этапы ООП. Объектная декомпозиция. 10 Цель: познакомить с теоретическими основами ООП, дать понятие объектной декомпозиции. Объектно-ориентированное, или объектное, программирование (в дальнейшем ООП) — парадигма программирования, в которой основными концепциями являются понятия объектов и классов. В случае языков с прототипированием вместо классов используются объекты-прототипы. При объектно-ориентированном подходе программные задачи распределяются между объектами программы. Объекты обладают определенным набором свойств, методов и способностью реагировать на события (нажатие кнопок мыши, интервалы времени и т.д.) Чтобы проект можно было считать объектно-ориентированным, объекты должны удовлетворять некоторым требованиям. Этими требованиями являются инкапсуляция, наследование и полиморфизм. Инкапсуляция - это объединение в единое целое данных и алгоритмов обработки этих данных. Наследование - есть свойство объектов порождать своих потомков. Полиморфизм - это свойство родственных объектов (т.е. объектов, имеющих одного общего родителя) решать схожие по смыслу проблемы разными способами. ООП центральным является понятие класса. Класс – это шаблон, по которому создаются объекты определенного типа. Класс объединяет в себе данные и методы их обработки. Объекты — это экземпляры определенного класса. Элементы управления — это объекты, используемые при разработке пользовательского интерфейса. Первые программы были организованы очень просто. Они состояли из собственно программы на машинном языке и обрабатываемых данных. Сложность программ ограничивалась способностью программиста одновременно мысленно отслеживать последовательность выполняемых операций и местонахождение большого количества данных. Появление сначала ассемблеров, а затем и языков высокого уровня сделало программу более обозримой за счет снижения уровня детализации и естественно позволило увеличить ее сложность. Структурное программирование представляет собой совокупность рекомендуемых технологических приемов, охватывающих выполнение всех этапов разработки программного обеспечения. Были сформулированы основные принципы выполнения разработки: 1. принцип нисходящей разработки, рекомендующий на всех этапах вначале определять наиболее общие моменты, а затем поэтапно выполнять детализацию (что позволяет последовательно концентрировать внимание на небольших фрагментах разработки); 2. собственно структурное программирование, рекомендующее определенные структуры алгоритмов и стиль программирования (чем нагляднее текст программы, тем меньше вероятность ошибки); 11 3. принцип сквозного структурного контроля, предполагающий проведение содержательного контроля всех этапов разработки. Метод пошаговой детализации заключается в следующем: определяется общая структура программы в виде одного из трех вариантов: последовательности подзадач (например, ввод данных, преобразование данных, вывод данных); альтернативы подзадач (например, добавление записей к файлу или их поиск); повторения подзадачи (например, циклически повторяемая обработка данных). Основные принципы и этапы ООП. В теории программирования ООП определяется как технология создания сложного программного обеспечения, которая основана на представлении программы в виде совокупности объектов, каждый из которых является экземпляром определенного типа (класса), а классы образуют иерархию с наследованием свойств Основное достоинство ООП - сокращение количества межмодульных вызовов и уменьшение объемов информации, передаваемой между модулями, по сравнению с модульным программированием. Основной недостаток ООП - некоторое снижение быстродействия за счет более сложной организации программной системы. В основу ООП положены следующие принципы: 1) абстрагирование; 2) ограничение доступа; 3) модульность; 4) иерархичность; 5) типизация; 6) параллелизм; 7) устойчивость. Необходимость ограничения доступа предполагает разграничение двух частей в описании абстракции: а) интерфейс – совокупность доступных извне элементов реализации абстракции (основные характеристики состояния и поведения); б) реализация – совокупность недоступных извне элементов реализации абстракции (внутренняя организация абстракции и механизмы реализации ее поведения). Иерархия - это ранжированная или упорядоченная система абстракций. Принцип иерархичности предполагает использование иерархий при разработке программных систем. В ООП используются два вида иерархии. 1. Иерархия «целое/часть» – показывает, что некоторые абстракции включены в рассматриваемую абстракцию, как ее части, например, лампа состоит из цоколя, нити накаливания и колбы. Этот вариант иерархии используется в процессе разбиения системы на разных этапах 12 проектирования (на логическом уровне – при декомпозиции предметной области на объекты, на физическом уровне - при декомпозиции системы на модули и при выделении отдельных процессов в мультипроцессной системе). 2. Иерархия «общее/частное» – показывает, что некоторая абстракция является частным случаем другой абстракции, например, «обеденный стол – конкретный вид стола», а «столы – конкретный вид мебели». Используется при разработке структуры классов, когда сложные классы строятся на базе более простых путем добавления к ним новых характеристик и, возможно, уточнения имеющихся. Объектная декомпозиция. Объектной декомпозицией называют процесс представления предметной области задачи в виде совокупности функциональных элементов (объектов), обменивающихся в процессе выполнения программы входными воздействиями (сообщениями). Каждый выделяемый объект предметной области отвечает за выполнение некоторых действий, зависящих от полученных сообщений и параметров самого объекта. Совокупность значений параметров объекта называют его состоянием, а совокупность реакций на получаемые сообщения - поведением. В процессе решения задачи объект, получив некоторое сообщение, выполняет заранее определенные действия, например, может изменить собственное состояние, выполнить некоторые вычисления, нарисовать окно или график и, в свою очередь, сформировать сообщения другим объектам. Таким образом, процессом решения задачи управляет последовательность сообщений. Передавая эти сообщения от объекта к объекту, программа выполняет необходимые действия. Контрольные вопросы 1. В чем заключается метод пошаговой детализации 2. Основное достоинство ООП 3. Какие принципы положены в основу ООП 4. Какие виды иерархии используются в ООП. 5. Что называется объектной декомпозицией? Лекция 5 Тема: Теоретические основы объектно-ориентированного программирования. Объекты и сообщенния. Классы. Основные средства разработки классов. Дополнительные средства разработки классов. Цель: ввести понятие класса и познакомить с дополнительными средствами разработки классов Каждый объект, получая сообщения должен определенным образом «реагировать» на них, выполняя заранее определенные для каждого типа сообщения действия. 13 Реакция объекта на сообщение может зависеть от его состояния, так объект Файл, получив сообщение «Добавить запись», прежде, чем добавлять запись, должен проверить, открыт ли соответствующий файл, и при закрытом файле должен выдать пользователю отказ на выполнение операции добавления. Состояние объекта характеризуется набором конкретных значений некоторого перечня всех возможных свойств данного объекта, характеризуется скоростью обслуживания машин, тем, занята колонка или нет, и в занятом состоянии - временем ее освобождения. Наличие внутреннего состояния объектов означает, что порядок выполнения операций имеет существенное значение, т. е. объект может моделироваться с применением теории конечных автоматов. Поведение объектов, характеризуется определенным набором реакций на получаемые сообщения и часто зависит от состояния объекта. Классы. В любой системе функционирует множество объектов. Некоторые из них «похожи» и однотипны. Однотипные объекты объединяются в классы. Все объекты одного и того же класса обладают одинаковым интерфейсом и реализуют этот интерфейс одним и тем же способом. Два объекта одного класса в ООП могут отличаться только текущим состоянием, причем всегда теоретически возможно так изменить состояние одного объекта, чтобы он стал равным другому объекту. Индивидуальные объекты называются экземплярами класса, а класс в ООП — это шаблон по которому строятся объекты. Названия классов в ООП пишутся с большой буквы, а названия объектов — с маленькой. Интерфейс — это внешняя часть класса. Интерфейс определяет, как объекты данного класса могут взаимодействовать с другими объектами этого или других классов. Тип — это область определения некой величины, т.е. множество ее возможных значений и набор применимых операций. Тип может задаваться классом. Важнейшим свойством классов в ООП и их принципиальным отличием от абстрактных типов данных (встроенных в язык программирования) является наследование. Наследование — это отношение между классами, при котором один класс разделяет структуру или поведение одного или нескольких других классов. Основные средства разработки классов. Базовый класс, производный класс или оба класса могут иметь конструкторы и/или деструкторы. Если у базового и у производного классов имеются конструкторы и деструкторы. То конструкторы выполняются в порядке наследования, а деструкторы - в обратном порядке. Конструктор базового класса выполняется раньше конструктора производного класса. 14 Деструктор производного класса выполняется раньше деструктора базового класса. Когда инициализация проводится только в производном классе, аргументы передаются обычным образом. Однако при необходимости передать аргумент конструктору базового класса ситуация несколько усложняется, так как все необходимые аргументы базового и производного классов передаются конструктору производного класса. Затем, используя расширенную форму объявления конструктора производного класса, соответствующие аргументы передаются дальше в базовый класс. Синтаксис передачи аргументов из производного в базовый класс: Конструктор_произв_класса (список-арг): базов_класс(список-арг) { // тело конструктора производного класса } Обычно конструкторы базового и производного классов не используют один и тот же аргумент. Если необходимо передать каждому конструктору класса один или несколько аргументов, то надо передать конструктору производного класса все аргументы, необходимые конструкторам обоих классов. Затем конструктор производного класса передает конструктору базового класса те аргументы, которые ему требуются. Контрольные вопросы 1. Чем характеризуется состояние объекта 2. Чем характеризуется поведение объектов 3. По какому принципу объединяются объекты в классы 4. Какие объекты называются экземплярами класса Лекция 6 Тема: Среда визуального программирования. Формы приложения. Компоненты формы. Цель: знать что представляет собой форма приложения и основные компоненты формы Визуальное программирование — способ создания программы для ЭВМ путём манипулирования графическими объектами вместо написания её текста. Необходимо различать: графический язык программирования — который прежде всего язык программирования (со своим синтаксисом) визуальные средства разработки — как правило, под ними подразумевают средства проектирования интерфейсов или какую либо CASE-систему для быстрой разработки приложений или SCADA-систему для программирования микроконтроллеров. Языки визуального программирования могут быть дополнительно классифицированы в зависимости от типа и степени визуального выражения, на следующие типы: 15 языки на основе объектов, когда визуальная среда программирования предоставляет графические или символьные элементы, которыми можно манипулировать интерактивным образом в соответствии с некоторыми правилами; языки, в интегрированной среде разработки которых на этапе проектирования интерфейса применяются формы, с возможностью настройкой их свойств. Примеры: Delphi и C++ Builder фирмы Borland, С# языки схем, основанные на идее «фигур и линий», где фигуры (прямоугольники, овалы и т. п.) рассматриваются как субъекты и соединяются линиями (стрелками, дугами и др.), которые представляют собой отношения. Пример: UML. В современных разработках делаются попытки интегрировать подход визуального программирования с программированием потоков данных, чтобы иметь непосредственный доступ к состоянию программы для онлайновой отладки, или автоматизированная генерация и документирование программы. Языки потоков данных также позволяют делать автоматическое распараллеливание, которое может стать одним из величайших достижений программирования в будущем. Формы приложения. Форма - это важнейший визуальный компонент. Формы представляют собой видимые окна Windows и являются основной частью практически любого приложения. Формы приложения Delphi делятся на модальные и немодальные. Первая отличается тем, что она приостанавливает выполнение той процедуры, которая ее вызвала, и продолжается до того времени, пока пользователь не закроет ее. Еще одним отличительным фактом является то, что модальную форму невозможно переключить курсором мыши на любые другие формы этого приложения, до тех пор, пока модальную форму не закроет сам пользователь. В итоге для того, чтобы продолжить работу с приложением, пользователь обязан выполнить определенные действия, которые предлагаются модальной формой. Модальную форму спокойно можно удалить либо создать в той же области действия, это дает полную гарантию предотвращения утечки памяти. Для работы с формой предназначен компонент Form класса TForm. С создания формы начинается конструирование приложения. В форме размещаются визуальные компоненты, образующие интерфейсную часть приложения, и системные (невизуальные) компоненты. Компоненты формы. Свойства формы определяют ее внешний вид: размер, положение на экране, текст заголовка, вид рамки. YPE="TEXT" Текстовое поле в одну строку длину которого можно определить использованием атрибута SIZE, а введённую по умолчанию строку — с помощью атрибута VALUE. Может использоваться в двух вариантах: с аргументом "TEXT" (обычные условия ввода данных) или с аргументом 16 "PASSWORD" (вместо символов ввода в поле высвечиваются скрытые символы). TYPE="CHECKBOX" Компонент — один из вариантов форм выбора, принимающий одно из двух устойчивых положений: «выбрано» или «не выбрано». Каждый из компонентов формы типа CHECKBOX создаёт логическую пару: «имя элемента / его состояние». Для установки значения по умолчанию (отмечен либо нет) используют атрибуты так, как указано ниже. TYPE="RADIO" Компонент RADIO (или так называемая «радиокнопка») очень похож на предыдущий, но переменная может принимать лишь одно значение из представленного множества. TYPE="BUTTON" Компонент — кнопка, клик на которой приводит к запрограммированному в обработчике (скрипт на сервере) действию. С помощью атрибута NAME компоненту присваивается уникальное имя, атрибут VALUE определяет надпись на кнопке. TYPE="RESET" Компонент — кнопка, клик на которой приводит к очистке заполненных полей. Синтаксис исключительно прост, а действие имеет локальный характер (то есть просто очищаются все поля формы, а на сервер не передаётся никакой информации). Контрольные вопросы 1. Дайте определение формы 2. На какие две группы делятся формы приложения Delphi 3. Чем они отличаются Лекция 7 Тема: Среда визуального программирования. Событийно-управляемое программирование. Событие и процедура обработки события. Цель: дать определение событийно-управляемому программированию. Программирование как область деятельности бурно развивается. Если несколько лет назад о создании своих собственных программ под Windows рядовому программисту оставалось только мечтать, так как практически единственным инструментом разработки ориентированных на работу в Windows программ был Borland C++ for Windows, явно предназначенный для профессионалов, то сейчас, благодаря появлению Delphi, возможность создания программ под Windows стала реальностью.Delphi — это среда разработки программ, ориентированных на работу в Windows. В качестве языка программирования в Delphi используется объектно-ориентированный язык Object Pascal, который можно рассматривать как дальнейшее развитие Turbo Pascal 7.0.В основе идеологии Delphi лежат технологии визуального проектирования и событийного программирования, применение которых 17 позволяет существенно сократить время разработки и облегчить процесс создания приложений — программ, работающих в среде Windows. Событийно-управляемое программирование - объектно-ориентированное программирование, при котором задаются реакции программы на различные события. Эволюция языков системного программирования asm->c->c++>java->python/jscript? Событийное программирование предполагает наличие возможностей по управлению выполнением задач со стороны пользователя посредством возможностей операционной системы через события объектов. Перехват событий. Событие (прерывание) - это способность объекта реагировать на события, которые могут исходить от пользователя программы, и представляют собой программы. Программы обслуживания событий программируются в отличие от методов объектов теми, кто непосредственно использует эти объекты в своих программах. Под событием обработки события в математическом смысле далее будем иметь в виду соотнесение над объектом предметной области, который в рамках терминологии курса будем называть индивидом. При неформальном подходе под индивидом понимается такой объект предметной области (или языка программирования), который возможно выделить в этой области (или языке) посредством указания так называемой индивидуализирующей функции. Построение такой функции будем считать зависимым от эксперта в предметной области. Обычно такая функция имеет в качестве области своих значения истинности (а именно, "истина" и "ложь") и является истинной при аппликации к данному объекту и ложной - в противном случае. Ранее нами было рассмотрено понятие типа как совокупности объектов. Заметим, что произвольное семейство (действительных в нашем частном случае) объектов может быть параметризовано (или, иначе, концептуализировано) не только типами, но и событиями. Контрольные вопросы 1. Что такое событийно-управляемое программирование 2. Что понимают под событием обработки события 3. Что такое событие Лекция 8 Тема: Среда визуального программирования. Компоненты библиотеки VCL Delphi. Кнопки, индикаторы, управляющие элементы библиотеки VCL Delphi. Компоненты ввода и отображения текстовой информации. Цель: Познакомить с компонентами библиотеки VCL Delphi. Библиотека визуальных компонентов содержит множество классов, которые вы можете использовать в своих приложениях. Она написана на языке Object Pascal и непосредственно связана с интегрированной средой разработки Delphi. В частности, все кнопки, расположенные на палитре 18 компонент являются ни чем иным, как представлением визуальных компонент VCL. Использование стандартных объектов при создании приложений не только уменьшает сроки разработки, но и снижает количество ошибок. Отрицательным же следствием их применения является увеличение размера программы. Библиотека VCL содержит несколько сотен классов, образующих древовидную иерархию. Рассмотрим фрагмент такой иерархии: TObject – базовый класс иерархии. В нем нет полей, но заданы методы, определяющие основу поведения любого объекта, – создание, уничтожение объекта, обработку сообщений. Все классы, как стандартные, так и создаваемые программистом, прямо или косвенно наследуются от TObject. Их можно разделить на визуальные и невизуаьные. Визуальные классы предназначены для организации взаимодействия с пользователем, невизуальные – для хранения и обработки данных. Exception – является базовым классом для обработки исключительных ситуаций, которые возникают, например, при попытке деления на нуль, выходе за пределы выделенной области памяти, обращении к не существующему файлу и т.д. В Object Pascal реализован механизм обработки исключений, а VCL включает почти сотню классов для представления всех исключительных ситуаций. TPersistent – является предком всех классов, которые могут иметь раздел published (элементы, заданные в этом разделе, отображаются в инспекторе объектов). Опубликованные свойства объектов сохраняются при записи на диск. TList – предназначен для хранения произвольного количества элементов разных типов и доступа к ним по индексу аналогично массиву. Для хранения данных предназначены и другие потомки TPersistent, например классы TStack, TCollection, TStrings и их потомки. Для сохранения данных и объектов на внешних носителях предназначен класс TStream и его производные. TComponent – является предком визуальных и невизуальных компонентов (таких, как объект-приложение TApplication). Потомки TComponent могут отображаться в палитре компонентов, быть владельцами других компонентов и помещаться на форму. TControl – задает основные свойства всех визуальных компонентов. От него наследуются так называемые элементы управления – кнопки, метки, списки, флажки. Через эти элементы осуществляется диалог с пользователем. Те элементы, которые могут получить фокус ввода (воспринимают ввод с клавиатуры), наследуются от TControl через TWinControl 19 Перечень компонентов ввода и отображения текстовой информации: Контрольные вопросы 1. Что содержит библиотека визуальных компонентов 2. Что дает использование стандартных объектов при создании приложений 3. Назовите некоторые компоненты Лекция 9 Тема: Среда визуального программирования. Компоненты отображения табличных данных. Компоненты отображения иерархических данных. Компоненты – меню. Цель: познакомить с компонентами отображения табличных данных Среда разработки Delphi ориентирована, прежде всего, на создание программ для Windows. При этом большое внимание уделяется возможности визуальной разработки приложений с помощью большого набора готовых компонентов Delphi, позволяющих избежать ручного кодирования. Компоненты Delphi охватывают практически все аспекты применения современных информационных технологий. Конечно, для работы в Delphi прежде всего требуется изучить базовые компоненты Delphi, которые требуются при подготовке практически любого приложения. Для отображения табличных данных можно использовать компонент TStringGrid, в целом не плохой, но имеющий ряд ограничений: 1. События клика мышкой и выделения ячейки не распространяются на "фиксированные ячейки". Поэтому, в частности, ни коим образом нельзя отсортировать данные в таблице по какому-то признаку. (Как, например, делаем в проводнике windows в режиме показа "Таблица". Щёлкаем по "Вид" и всё упорядочивается по "виду"...) 20 2. Внешний вид немного староват и груб. Сравнить хотя бы с той же таблицей в windows 7. 3. На последнем скриншоте видна всплывающая подсказка, что чисто невозможно в TStringGrid. К компонентам отображения иерархических данных относится древовидный список (TreeView). Кроме того, в библиотеке Juce имеется специальный компонент для отображения файлов в заданной директории в виде древовидного списка — FileTreeComponent (его класс унаследован от TreeView). Эти компоненты служат для отображения каких-либо иерархических данных (например, структура предприятия, файлов и директорий в корневом каталоге, оглавления документов и т.п.) в виде дерева, в котором пользователь может выбрать нужный ему узел или узлы. С каждым узлом могут быть связаны какие-либо данные. Узел представляет собой элемент древовидного списка с включёнными в него дочерними элементами (субэлементами), которые могут быть видны, если узел открыт, либо скрыты. При удалении узла удаляется как родительский, так и все дочерние элементы. Тем самым, компонент с TreeView служит для управления множеством элементов. Для создания элемента древовидного списка служит класс TreeViewItem. Это абстрактный класс, содержащий ряд виртуальных функций. Рассмотрим пример класса, наследующего TreeViewItem, — TTreeViewItem Контрольные вопросы 1. Какой компонент используется для отображения табличных данных Лекция 10 Тема: Среда визуального программирования. Отображение графической и мультимедиа – информации. Системные диалоги. Организация управления приложением. Диспетчеризация действий. Цель: знать компоненты для работы с графической информацией Работа с графикой в Delphi это не только линии и рисунки, но также и и печать текстовых документов. Поэтому в Delphi работе с графикой нужно уделить немного времени. Работа с графикой в Delphi предполагает обращение к канве - свойству Canvas компонентов. Canvas Delphi это холст, который позволяет программисту иметь доступ к каждой своей точке (пикселу), и словно художнику отображать то, что требуется. Конечно, 21 рисовать попиксельно для работы с графикой в Delphi не приходится, система Delphi предоставляет для мощные средства работы с графикой, облегчающие задачу программиста. В работе с графикой в Delphi в распоряжении программиста находятся канва (холст, полотно - свойство Canvas Delphi компонентов), карандаш (свойство Pen), кисть (свойство Brush) того компонента или объекта, на котором предполагается рисовать. У карандаша Pen и кисти Brush можно менять цвет (свойство Color) и стиль (свойство Style). Доступ к шрифтам предоставляет свойство канвы Font. Эти инструменты позволяют отображать как текст, так и достаточно сложные графики математического и инженерного содержания, а также рисунки. Кроме этого, работа с графикой позволяет использовать в Delphi такие ресурсы Windows как графические и видеофайлы. Конечно, не все компоненты в Delphi имеют эти свойства. На вкладке Additional расположен специализированный компонент TImage, специально предназначенный для рисования, но также свойство Canvas имеют, например, такие компоненты как ListBox, ComboBox, StringGrid, а также и сама Форма, которая размещает наши компоненты! Кроме того, для печати документов Delphi обращается к свойству Canvas такого объекта как принтер. Основное свойство такого объекта как Canvas Delphi - Pixels[i, j] типа TColor, то есть это двумерный массив точек (пикселов), задаваемых своим цветом. Рисование на канве происходит в момент присвоения какой-либо точке канвы заданного цвета. Каждому пикселу может быть присвоен любой доступный для Windows цвет. Например, выполнение оператора Image1.Canvas.Pixels[100, 100]:=clRed; приведёт к рисованию красной точки с координатами [100, 100]. Узнать цвет пиксела можно обратным присвоением: Color:=Image1.Canvas.Pixels[100, 100]; Тип TColor определён как длинное целое (LongInt). Его четыре байта содержат информацию о долях синего (B), зелёного (G), и красного (R) цветов. В 16-ричной системе это выглядит так: $00BBGGRR. Доля каждого цвета может меняться от 0 до 255. Поэтому чтобы отобразить максимально красную точку, ей нужно присвоить цвет $000000FF. Для стандартных цветов в Delphi определён набор текстовых констант. Увидеть его можно, открыв в Инспекторе Объектов свойство Color, например, той же Формы. Итак, классическое приложение Windows должно иметь хотя бы одно окно. Окно приложения должно уметь выполнять целый ряд важных операций. Оно должно правильно отображать себя на экране, уметь взаимодействовать с другими окнами и операционной системой, управлять размещенными на нем элементами управления, реагировать на разнообразные события. В среде разработки Delphi понятие окна приложения совмещено с понятием формы. По существу это одно и то же. Просто формой называется 22 окно приложения на этапе разработки. Форме при разработке и окну при выполнении приложения соответствует один и тот же экземпляр класса, тем не менее, введение понятия "форма" представляется оправданным. Дело в том, что на этапе разработки окно должно обладать целым рядом ценных свойств, которые обеспечивают процесс программирования и обязаны исчезнуть при запуске приложения. Самые важные из них заключаются в том, что форма умеет взаимодействовать с инструментами среды разработки (Палитрой компонентов, Инспектором объектов и т. д.) и размещенными на ней компонентами. Первое из названных свойств обеспечивается возможностями, унаследованными от базового класса иерархии VCL TComponent. Второе свойство обеспечено механизмами самого класса формы. Кроме этого, форма обеспечивает еще целый ряд удобных и полезных для разработчика функций. Это разметка рабочей области, возможность выравнивания компонентов и т. д. Для хранения каждой формы проекта используются два файла. Файл с расширением dfm хранит описание свойств формы и размещенных на ней компонентов. Для хранения исходного кода класса формы и ее компонентов предназначен файл модуля с расширением раз. Формы играют исключительно важную роль в процессе создания приложения. Они обеспечивают создание пользовательского интерфейса с одной стороны, и хранение программной логики приложения — с другой. Хотя форма и является потомком класса TComponent, она не присутствует в Палитре компонентов. Для создания новой формы проекта необходимо использовать команду New Form из меню File или Репозиторий, где хранятся прототипы часто используемых форм. Это говорит о роли формы в процессе разработки приложения — на нее возложено гораздо больше обязанностей, чем на обычный компонент. Контрольные вопросы 1. Что представляет собой Canvas Delphi 2. Какие инструменты для работы с графикой вы знаете? Лекция 11 Тема: Объектная модель Delphi Pascal. Определение класса. Особенности реализации переопределения методов. Виртуальные методы. Абстрактные методы. Перегрузка методов. Цель: дать понятие объектной модели, познакомить с определением класса Объектная модель Delphi Pascal по сравнению с моделью, использованной Borland Pascal 7.0., является более полной. Она включает: ограничение доступа к полям и методам за счет определения собственного интерфейса к каждому полю класса (5 типов секций при объявлении класса, свойства); 23 более развитые механизмы реализации полиморфных методов (абстрактные, динамические методы); средства работы с метаклассами (переменные метаклассов, методы классов, механизм RTTI); возможность делегирования методов (указатели на методы) и т. д. Определение класса. Все классы, используемые в Delphi (уже определенные в библиотеках объектов и создаваемые разработчиком для конкретного приложения), наследуются от класса TObject. Формат описания нового класса выглядит следующим образом: Type <имя объявляемого класса> = class(<имя родителя>) private <скрытые элементы класса> protected <защищенные элементы класса> public <общедоступные элементы класса> published <опубликованные элементы класса> automated <элементы, реализующие OLE-механизм> end; Имя родителя указывать не обязательно, по умолчанию считается, что, если имя родителя не указано, то класс непосредственно наследуется от TObject. Внутри описания класса выделяется до пяти секций. Секция private содержит внутренние элементы, обращение к которым возможны только в пределах модуля (а не класса, как в С++), содержащего объявление класса. Секция protected содержит защищенные элементы, которые доступны в пределах модуля, содержащего объявление класса, и внутри потомков класса. Секция public содержит общедоступные элементы, к которым возможно обращение из любой части программы. Секция published содержит опубликованные элементы, которые по ограничению доступа аналогичны public. Для визуальных компонент, вынесенных на панель компонент, информация об элементах, размещенных в этой секции, становится доступной через Инспектор Объектов. Секция automated содержит элементы, доступ к которым также выполняется аналогично public. Но для элементов, описанных в этой секции генерируется дополнительная информация, используемая OLE. Секцию имеет смысл объявлять для потомков класса TAutoObject. Методы представляют собой процедуры и функции, принадлежащие классу. Можно сказать, что методы определяют поведение класса. В классе всегда должны присутствовать два важнейших метода: конструктор и деструктор. При проектировании класса можно создать произвольное количество любых других методов, необходимых для решения конкретных задач. Типы методов 24 Методы объекта могут быть описаны как статические (static), виртуальные (virtual), динамические (dynamic) или как методы обработки сообщения (message), для чего к ним добавляются соответствующие директивы. Статические методы. Статические методы работают подобно обычным процедурам или функциям. Этот тип методов устанавливается по умолчанию. Адрес такого метода известен уже на стадии компиляции, и компилятор в коде программы оформляет все вызовы данного метода как статические. Такие методы работают быстрее других, однако не могут быть перегружены в целях полиморфизма объектов. Виртуальные методы. Вызов виртуальных методов из-за возможности их перегрузки немного сложнее, чем вызов статических, так как во время компиляции адрес конкретного вызываемого метода не известен. Для решения этой задачи компилятор строит таблицу виртуальных методов (VMT), обеспечивающую определение адреса метода в процессе выполнения программы. VMT содержит все виртуальные метолы предка и виртуальные методы самого объекта, поэтому виртуальные методы используют несколько больший объем памяти, чем методы динамические, однако их вызов происходит быстрее. Динамические методы. Динамические методы в целом подобны виртуальным методам, но обслуживаются другой диспетчерской системой. Каждому динамическому методу компилятор назначает уникальное число и использует его вместе с адресом метода для построения таблицы динамических методов (DMT- Dynamic Method Table), В отличие от VMT, DMT содержит методы лишь данного объекта, благодаря чему обеспечивается экономия используемой памяти, но замедляется вызов метода, поскольку для поиска его адреса, скорее всего, будет пересмотрена не одна DMT в иерархии объектов. Методы обработки сообщения. Методы обработки сообщений предназначены аля обработки приходящих сообщений, с помощью которых происходит обмен информацией в операционной системе Windows. Значение после ключевого слова message определяет сообщение, в ответ на которое вызывается данный метод. Такие методы создаются для реакции на те или иные сообщения Windows. Контрольные вопросы 1. От какого класса наследуются все классы, используемые в Delphi 2. Формат описания нового класса 3. Сколько и какие секций выделяется внутри описания класса 4. Что представляют собой методы Лекция 12 Тема: Объектная модель Delphi Pascal. Свойства. Простые свойства. Свойства – массивы. Индексированные свойства. Метаклассы. Ссылка на класс (метакласс). Операции is и as. Методы класса. Цель: познакомить со свойствами, метаклассами, познакомить со свойствами-массивами 25 Массив— это структура данных, представляющая собой набор переменных одинакового типа, имеющих общее имя. Массивы удобно использовать для хранения однородной по своей природе информации, например, таблиц и списков. Объявление массива Массив, как и любая переменная программы, перед использованием должен быть объявлен в разделе объявления переменных. В общем виде инструкция объявления массива выгладит следующим образом: Имя: [нижний_индекс..верхний_индекс] of тип где: имя — имя массива; array — зарезервированное слово языка Delphi, обозначающее, что объявляемое имя является именем массива; нижний_индекс и верхний_индекс — целые константы, определяющие диапазон изменения индекса элементов массива и, неявно, количество элементов (размер) массива; тип — тип элементов массива. Memol.Lines[0] := 'Строка'; Свойства-массивы имеют перечисленные ниже особенности. Свойства-массивы объявляются с указанием одного или нескольких индексных параметров. Тип индексов должен быть целым или строковым (в отличие от обычных массивов, свойства-массивы могут индексироваться строками). Доступ к значению свойства-массива может быть только косвенным (через методы SetXXXX/GetXXXX). Если в определении свойства-массива используется несколько индексов (многомерные свойства-массивы), методы доступа должны содержать параметры для каждого индекса в том же порядке, что и в объявлении свойства. Свойства-массивы нельзя объявлять в секции published. Доступ к значениям свойства-массива на этапе конструирования возможен только с помощью специализированного редактора свойств. Метаклассы. Ссылки на классы Язык Object Pascal позволяет рассматривать классы как своего рода объекты, которыми можно манипулировать в программе. Такая возможность рождает новое понятие — класс класса; его принято обозначать термином метакласс. Для поддержки метаклассов введен специальный тип данных — ссылка на класс (class reference). Он описывается с помощью словосочетания class of, например: Code: type TResourceGaugeClass = class 26 of TResourceGauge; Переменная типа TResourceGaugeClass объявляется в программе обычным образом: Code: var ClassRef: TResourceGaugeClass; Значениями переменной ClassRef могут быть класс TResourceGauge и все порожденные от него классы. Допустимы, например, следующие операторы: Code: ClassRef TResourceGauge; ClassRef TDiskGauge; ClassRef TMemoryGauge; := := := По аналогии с тем, как для всех классов существует общий предок TObject, у ссылок на классы существует базовый тип TCIass: Code: type TCIass = class of TObject; Переменная типа TCIass может ссылаться на любой класс.Практическая ценность ссылок на классы состоит в возможности создавать программные модули, работающие с любыми классами объектов, даже с теми, которые еще не разработаны. Контрольные вопросы 1. Что такое массив? 2. Как объявить массив? 3. Какие особенности имеют свойства-массивы? Лекция 13 Тема: Объектная модель Delphi Pascal. Механизм определения типов на этапе выполнения программы. Делегирование методов. Библиотека стандартных классов Delphi. Отношения «основной - вспомогательный» и «старший - младший». Цель: познакомить с библиотекой стандартных классов Delphi 27 Помимо наследования и перекрытия методов родителя Delphi дает еще одну возможность модифицировать поведение того или иного объекта. Речь идет о делегировании метода одного объекта другому. Для этого в класс, которому делегируется метод, вставляется поле процедурного типа с обязательным упоминанием, что делегируемый метод должен быть методом класса, с помощью зарезервированных слов of object: type TNotifyEvent = procedure(Sender: TObject); TMyClass = class FaEvent: TNotifyEvent of object; end; TAnotherClass - class procedure MyEvent(Sender: TObject); end; Теперь экземпляр класса TAnotherClass может делегировать свою процедуру MyEvent объекту класса TMyClass: var FMyClass: TMyClass; FAnotherClass: TAnotherClass; begin FMyClass TMyClass.Create; FAnotherClass := TAnotherClass.Create; FMyClass.FaEvent := FAnotherClass.MyEvent; end; Делегирование используется для определения обработчиков того или иного события вновь созданного объекта. Делегированный обработчик будет вызываться внутри методов другого объекта и, таким образом, модифицировать его поведение без перекрытия этих методов. Библиотека стандартных классов Delphi VCL содержит сотни классов, на базе которых разработчик может создавать собственные приложения Windows. На рисунке ниже показана иерархия основных базовых классов библиотеки VCL, на базе которых созданы все остальные классы Delphi. Рис. Иерархия классов основных компонент библиотеки VCL 28 Как уже упоминалось ранее, все компоненты библиотеки наследуются от класса TObject, который содержит целый ряд специальных методов существенно снижающих сложность программирования в Delphi: type TObject = class constructor Create; {конструктор} destructor Destroy; virtual; {деструктор} procedure Free; {уничтожить, если элемент был создан} class Function InitInstance(Instance: Pointer): TObject; {инициализирует память при создании объекта} class Function NewInstance: TObject; virtual; {выделяет пямять для размещения объекта} Procedure CleanupInstance; {осуществляет корректное завершение работы со строками и другими сложными структурами при уничтожении объекта} Procedure FreeInstance; virtual; {освобождает память, выделенную под размещение объекта} Function ClassType: TClass;{возвращает класс объекта} class Function ClassName: ShortString; {возвращает имя класса} class Function ClassNameIs(const Name: string): Boolean; {проверяет принадлежность объекта указанному классу} class Function ClassParent: TClass;{возвращает тип предка} class Function ClassInfo: Pointer;{возвращает указатель на таблицу RTTI} class Function InstanceSize: Longint;{возвращает размер объекта в байтах} class Function InheritsFrom(AClass: TClass): Boolean;{проверяет принадлежность класса или объекта семейству указанного класса} Procedure Dispatch(var Message);{посылает сообщение объекту} class Function MethodAddress(const Name: ShortString): Pointer; {возвращает адрес опубликованного метода по имени} class Function MethodName(Address: Pointer): ShortString; {возвращает имя опубликованного метода по его адресу} Function FieldAddress(const Name: ShortString): Pointer; {возвращает адрес опубликованного поля по его имени} Function GetInterface(const IID: TGUID; out Obj): Boolean; {проверяет соответствие указанного интерфейса класс} class Function GetInterfaceEntry(const IID: TGUID): PInterfaceEntry; {возвращает указатель на структуру, содержащую описание специального интерфейса класса} class Function GetInterfaceTable: PInterfaceTable; {возвращает указатель на структуру, содержащую описание интерфейса для класса} Function SafeCallException(ExceptObject: TObject; ExceptAddr: Pointer): Integer; virtual; {метод поддержки исключение OLE} Procedure DefaultHandler(var Message); virtual;{выполняет обработку сообщения по умолчанию} end; От класса TObject наследуется родоначальник всех классов, которые могут иметь секцию published - класс TPersistent. Этот класс обеспечивает 29 корректную работу Инспектора Объектов с опубликованными свойствами (сохранение их в файлах формы, инициализацию опубликованных свойств при компиляции программы и копирование полей одного объекта в другой). От класса TPersistent наследуются классы TComponent (компоненты) родоначальник всех классов-компонент и некоторые другие вспомогательные классы, например: TStrings (строки), TCollection (коллекции), TCanvas («холсты» - поля, на которых можно «рисовать»), TGraphicObject (графические объекты), TGraphic (графические элементы), TPicture (изображения). От класса TComponent наследуются все компоненты приложения, в том числе и само приложение (класс TApplication). Особенность потомков класса TComponent заключается в том, что объекты-компоненты могут находиться между собой в отношении «основной – вспомогательный». Основной компонент отвечает за управление памятью при размещении вспомогательных компонентов: выделение памяти при создании компонента и освобождение памяти при его уничтожении. Для всех компонент, размещенных в форме (TForm) основным компонентом является форма, а для самой формы основным компонентом является приложение (TApplication). Реализация отношения «основной – вспомогательный» в класса TComponent осуществляется с использованием следующих свойств: 1. свойство Owner, которое должно содержать указатель на основной компонент для текущего компонента (оно инициализируется автоматически при помещении компонента в форму); 2. свойство ComponentIndex - содержит номер текущего компонента в массиве Components (начиная с 0) основного компонента; определяет порядок создания и изображения вспомогательных компонентов; 3. свойство Components[Index] - свойство-массив типа TComponent, содержит указатели на все вспомогательные компоненты текущего компонента; 4. свойство ComponentCount содержит количество вспомогательных компонент текущего компонента. Таким образом, при необходимости можно просмотреть свойствомассив Components размером ComponentCount и найти нужные вспомогательные компоненты. Особое место среди потомков TComponent занимает класс TControl, от которого наследуются все элементы управления, размещаемые в окне формы. Соответственно, этот класс содержит свойства, определяющие расположение элементов управления относительно формы на экране. Считается, что любой элемент управления занимает прямоугольник внутри окна формы. Положение этого прямоугольника определяется относительно окна формы координатами верхнего левого и нижнего правого углов. Класс TControl определяет методы, обрабатывающие сообщения мыши и обеспечивающие генерацию соответствующих событий (обычное, двойное нажатие, движение с нажатыми клавишами и т.п.). 30 От класса TControl наследуются классы TWinControl - оконные элементы управления и TGraphicControl - графические элементы управления. Оконные элементы управления имеют собственную функцию окна и, соответственно, могут получать сообщения Windows (TEdit, TMemo, TListBox), в том числе сообщения от клавиатуры, т.е. могут получать фокус ввода. Соответственно, класс TWinControl включает методы обработки сообщений клавиатуры, которые формируют события клавиатуры. Графические элементы управления порождаются от TGraphicControl и не могут обрабатывать ввод с клавиатуры (TLabel, TImage, TBevel). Они в основном используются для отображения информации. Класс TWinControl устанавливает между оконными элементами управления отношение «старший – младший». Это отношение определяет подчиненность изображений оконных элементов управления на экране. Например, если форма становится невидимой, то невидимыми становятся все ее младшие элементы управления (метки, кнопки и т.д.). Контрольные вопросы 1. Что представляет собой делегирование 2. Для чего используется делегирование 3. Что содержится библиотека стандартных классов Delphi VCL Лекция 14 Тема: Создание и обработка сообщений и событий. Сообщения Delphi. Методы обработки сообщений. Генерация сообщений. Создание событий. Обработка сообщений VCL. Управление циклом обработки сообщений. Цель: познакомить с методами обработки сообщений Стандартная библиотека классов Delphi VCL предлагает разработчику достаточно большой набор сообщений и методов их разработки. Однако он имеет возможность добавить новое сообщение или переопределить методы обработки существующих сообщений. При создании нового сообщения необходимо выполнить следующие действия: 1. описать тип сообщения; 2. объявить номер (или индекс) сообщения; 3. объявить метод обработки нового сообщения в классе, который должен его обрабатывать; 4. инициализировать (передать) сообщение. Сообщения Delphi. В Delphi определено около 100 стандартных типов сообщений. В соответствии с правилами Windows сообщение состоит из нескольких полей. Первое поле обычно называется Msg. Оно должно содержать индекс сообщения - 16 разрядное целое положительное число (тип Cardinal). Далее следуют поля, содержащие передаваемые значения. Последние поля обычно используются для записи результата обработки сообщения. Они могут отсутствовать. 31 Например, основной тип сообщений, используемых в Delphi, определяется следующим образом: Type TMessage=record Msg:Cardinal; case Integer of 0: (WParam:LongInt; LParam:LongInt; Result:LongInt); 1: (WParamLo:Word; WParamHi:Word; LParamLo:Word; LParamHi:Word; ResultLo:Word; ResultHi:Word); end; end; Номер сообщения. Номер (или индекс) сообщения используется для идентификации сообщения в системе: он определяет вид события, о котором система уведомляет приложение (нажатие клавиш, нажатие кнопок мыши и т.д.). При создании собственных сообщений следует учитывать, что номера с 0 до $399 зарезервированы за системой. Первый свободный номер обозначен константой WM_USER = $400, относительно которой обычно и определяются номера пользовательских сообщений: Const Mes1 = WM_USER; Mes2 = WM_USER+1; Методы обработки сообщений. Класс, объекты которого должны принимать и обрабатывать некоторые сообщения, должен включать специальные методы обработки этих сообщений. При разработке этих методов необходимо учитывать специальные правила, существующие в Delphi. Метод обработки сообщения по умолчанию является динамическим, причем спецификаторы dinamic или override при его описании опускаются: Procedure wm<имя метода>(var Message:<тип сообщения>); message <номер сообщения>; Имена методов обработки некоторого сообщения, переопределяемых в иерархии классов, могут не совпадать: переопределяемый метод идентифицируется по совпадающему номеру сообщения, указываемому после специальной директивы message. Номер сообщения обычно задается в виде символического имени, но может указываться и целой положительной константой. Добавление метода обработки сообщений к классу выполняется так же, как и любого другого метода: type <имя класса>= class <имя класса-родителя> public Procedure wm<имя метода>(var Message:<тип сообщения>); message <номер сообщения>; 32 ... end. Контрольные вопросы 1. Какие действия нужно выполнить для создания нового сообщения 2. Для чего используется номер (или индекс) сообщения для идентификации Лекция 15 Тема: Обработка исключений. Структура фрагментов с исключениями. Создание исключений. Генерация исключений. Обработка исключений. Цель: знать понятие исключительной ситуации, ее обработку средствами Delphi Под исключительной ситуацией мы будем понимать некое непредвиденное событие, способное повлиять на дальнейшее выполнение программы. При обработке такой ситуации Delphi, как обычно, работает с объектами. С точки зрения компилятора Delphi исключительная ситуация - это объект. Для работы с этим специфичным объектом в Delphi (точнее, в Object Pascal) были введены следующие языковые конструкции: ry .. except и try .. finally. Рассмотрим эти языковые конструкции более подробно. Итак, конструкция try .. except имеет следующий синтаксис: try {исполняемый код}; except on Exceptionl do {код, исполняемый в случае возникновения ошибки 1}; on Exception2 do {код, исполняемый в случае возникновения ошибки 2}; else {код, обработчик всех не перехваченных ранее ошибок}; end; Если при выполнении кода, размещенного в разделе try, генерируется исключение, то выполнение этого раздела прекращается и управление передается коду, размещенному в разделе except. Раздел except может использоваться двумя способами. Во-первых, в нем могут располагаться любые операторы, кроме обработчиков исключений, начинающихся с приставки on. Это и операторы сообщения об ошибке, и команды, позволяющие освобождать системные ресурсы, а также другие операторы и команды. Во-вторых, раздел except используется для обработки исключений. В этом случае в него могут включаться только операторы обработки исключений. Если среди обработчиков встретился обработчик, соответствующий сгенерированному исключению, то выполняется оператор этого обработчика, исключение разрушается и управление передается коду, расположенному после оператора on Exception do. Раздел, расположенный 33 после ключевого слова else, служит для обработки любых исключений, не описанных в разделе except. Этот раздел не является обязательным. Если при обработке исключительной ситуации не будет найден подходящий обработчик, то произойдет обработка системным обработчиком исключений. Рассмотрим простой пример обработки исключительной ситуации деления на ноль : try а:=10; b:=0; c:=a/b; except on EZeroDivide do MessageBox('Делить на ноль нельзя!'); end; Итак, как можно видеть из приведенного выше примера, для обработки разных исключений служат разные операторы. Рассмотрим более подробно оператор обработки on .. do. Данный оператор находится внутри раздела except и может иметь две формы: on <класс исключения> do <оператор>; или on <имя>: <класс исключения> do <операторы, в которых можно использовать свойства исключения> Этот оператор обрабатывает только тот класс исключений, который в нем указан. При указании родительского (базового) класса, все классы исключений - потомки данного класса - также будут обработаны. Для обработки всех исключений можно обратиться к базовому классу всех исключений: Exception. После обработки исключения оно разрушается. Вторая форма оператора on .. do отличается от первой тем, что данному исключению можно временно присвоить имя и обращаться к свойствам исключения. Обращаться к свойствам исключения можно с помощью конструкции <имя>.<имя свойства>. Посмотрим try ScrollBarl.Max := ScrollBarl.Min - 1; except on E: EInvalidOperation do MessageDlg( 'Игнорируем исключение: '- + E.Message, mtlnformation, [mbOK], O) end; В приведенном примере мы присваиваем исключению EInvalidOperation временное имя Е. Затем в окне сообщения выводим текст ошибки E.Message, выдаваемый Delphi по умолчанию (если бы не было нашего обработчика ошибки). Иногда, бывает необходимо, чтобы после обработки исключительной ситуации своим кодом вызывался стандартный обработчик ошибки. Например, в случае возникновения некоторой ошибки вы хотите, чтобы приложение сообщало пользователю какую-либо информацию, а затем 34 передавало управление стандартному обработчику ошибок. Как вы уже знаете, после обработки исключения вашим кодом, исключение уничтожается. Для того чтобы самостоятельно вызвать снова это исключение, можно воспользоваться регенерацией исключений. Для регенерации исключения служит команда raise. Рассмотрим: try { операторы } except on <класс исключения> do begin {операторы обработки исключения} raise; // Регенерация исключения end; end; После выполнения операторов обработки исключения, написанных программистом, выполняется команда raise, которая снова принудительно вызывает это исключение, после чего управление передается стандартному обработчику исключений. В случае, когда исключение успешно проходит через все блоки try в коде приложения, вызывается метод HandleException. Контрольные вопросы 1. Что понимают под исключительной ситуацией 3. ПРАКТИЧЕСКИЕ И ЛАБОРАТОРНЫЕ ЗАНЯТИЯ Лабораторная работа №1 Тема: Язык программирования Delphi. Этапы разработки программы. Цель: Сформировать практические навыки: реализация линейных процессов обработки данных с помощью оператора присваивания Object Pascal; построение однооконных интерфейсов с помощью визуального компонента «окно» (класс TForm) и визуальных компонентов панели инструментов Standard: «метка» (класс TLabel), «редактор» (класс TEdit), «кнопка» (класс TButton). ЗАДАНИЕ 1. В соответствии с вариантами задания и приведенной ниже спецификацией реализуйте приложение под Windows. 2. Разработайте тестовые задания, и оттестируйте программу одним из методов тестирования. Спецификация приложения 1. В соответствии с приведенными вариантами заданий реализуйте приложение под Windows, используя для организации пользовательского интерфейса следующие элементы управления: «форма» (класс TForm), 35 «кнопка» (класс TButton), «метка» (класс TLabel), «однострочный редактор» (класс TEdit). Ввод данных и вывод результатов осуществляйте в элементы управления «однострочный редактор». Подписи к однострочным редакторам выполните с помощью элементов «метка». Вычисление результата свяжите с нажатием на элементе управления «кнопка» левой клавиши мыши. 2. Организуйте контроль содержимого строки, вводимой в элемент «однострочный редактор». Если вводимая строка не соответствует заданному формату, то необходимо предусмотреть следующее: в окне сообщений вывести сообщение об ошибке, очистить строку, введенную в «однострочный редактор». Рекомендации к выполнению 1. Для организации управляющей структуры программы используйте оператор присваивания. 2. Для выполнения заданий используйте операции mod, div и стандартные функции Abs, Int, Frac,Trunc, Round, Odd. 3. Для преобразования введенных значений из строкового формата в числовой, а результатов – из числового формата в строковый формат используйте библиотечные подпрограммы StrToInt, StrToFloat, IntToStr, FloatToStr модуля Sysutils. 4. Организуйте контроль ввода данных в элемент «однострочный редактор». Для этого используйте блок try…finally и процедуру ShowMessage модуля Dialogs. 5. Разработанные приложения сохраняйте в отдельной папке. Варианты заданий 1. Вычислите значение функции y (e x1 e x2 ) / 2. 2. Вычислите площадь треугольника со сторонами a, b, c по формуле Герона: s p * ( p a ) * ( p b) * ( p c); p ( a b c) / 2. 3. Вычислите высоты треугольника со сторонами a, b, c по формулам: s p * ( p a) * ( p b) * ( p c); p (a b c ) / 2; ha 2 * s / a; hb 2 * s / b; hc 2 * s / c. 4. Вычислите площадь поверхности s и объем v усеченного конуса, используя функцию возведения в квадрат SQR: s * (R r ) * l * R2 * r 2 ; v (1/ 3) * ( R 2 r 2 R * r ) * h. 5. Вычислите значение функции, используя функцию возведения e в заданную степень EXP и функцию SIN: y a * e a**x *sin( * x); x ( / 2 ). 6. Выведите третий справа разряд целого числа, содержащего не менее трех разрядов. Для решения используйте операции mod, div. 36 7. Выведите первый после десятичной точки разряд дробной части действительного числа, содержащего не менее одного разряда в дробной части. Для решения используйте функции Int, Frac. ПРИМЕР Пусть требуется определить частное от деления двух вещественных чисел. Для решения этой задачи можно построить приложение, состоящее из одной формы следующего вида (рис. 1): Label1 Edit1 Button1 Edit2 Label2 Edit3 Label3 Рис. 1 Ей соответствует модуль, текст которого приведен ниже. unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Edit1: TEdit; Edit2: TEdit; Label1: TLabel; Label2: TLabel; Button1: TButton; Edit3: TEdit; Label3: TLabel; procedure Button1Click(Sender: TObject); private {Private declarations} public {Public declarations} end; var Form1: TForm1; 37 implementation {$R *.DFM} procedure TForm1.Button1Click(Sender: TObject); var a,b,c: real; begin a:= StrToFloat(Edit1.Text); //Преобразуем введенную строку в вещественное число b:= StrToFloat(Edit2.Text);//Преобразуем введенную строку в вещественное число c:= a/b; Edit3.Text:= FloatToStr(c); //Преобразуем вещественное число в строку Edit1.SetFocus; //Устанавливаем фокус ввода на Edit1 end; end. Разработанное выше приложение имеет ряд недостатков: • приложение не работает, если при вводе допускаются ошибки: введенная строка не является изображением числа или ни одного символа не было введено в строку; • возникает ошибка выполнения, если делитель равен 0. Указанных недостатков лишено приложение, текст модуля которого приведен ниже. Его интерфейс совпадает с интерфейсом приложения, описанного выше. В этом приложении нельзя покинуть элемент управления «однострочный редактор» (переместить фокус ввода на другой визуальный компонент), пока не введена строка, изображающая число. В случае ошибки ввода пользователь приложения получает окно, содержащее сообщение об ошибке. Если он закрывает окно сообщения, фокус ввода вновь устанавливается в «однострочный редактор», содержащий строку с ошибкой. В случае, когда делитель равен нулю, пользователь также получает окно с сообщением о делении на ноль. Когда он закрывает окно сообщения, фокус ввода вновь устанавливается в «однострочный редактор», содержащий строку с ошибкой. procedure TForm1.Button1Click(Sender: TObject); var a,b,c: real; begin try a:= StrToFloat(Edit1.Text); //Преобразуем введенную строку в вещественное число b:= StrToFloat(Edit2.Text); //Преобразуем введенную строку в вещественное число c:= a/b; Edit3.Text:= FloatToStr(c); //Преобразуем вещественное число в строку Edit1.SetFocus; //Устанавливаем фокус ввода на Edit1 except 38 on EZerodivide do //операторы выполняются begin //в случае деления на ноль ShowMessage('Деление на ноль'); Edit2.SetFocus; end; end; end; procedure TForm1.Edit1Exit(Sender: TObject); var a: real; begin try a:= StrToFloat(Edit1.Text) except on EConvertError do begin ShowMessage('Ошибка ввода'); Edit1.SetFocus; end; end; end; procedure TForm1.Edit2Exit(Sender: TObject); var a: real; begin try a:= StrToFloat(Edit2.Text) except on EConvertError do begin ShowMessage('Ошибка ввода'); Edit2.SetFocus; end; end; end; end. СОДЕРЖАНИЕ ОТЧЕТА 1. Задание. 2. Текст программы на Object Pascal. 3. Тестовые наборы данных для тестирования приложения. КОНТРОЛЬНЫЕ ВОПРОСЫ 1. Назовите синтаксические правила, в соответствии с которыми записывается оператор присваивания. 2. Укажите порядок, в котором выполняется оператор присваивания. 39 3. Какое отношение должно существовать между ссылкой на переменную, стоящую слева от символа оператора присваивания, и типом выражения, стоящего справа от него? 4. В каком разделе подпрограммы описываются переменные? 5. Какую информацию извлекает компилятор из описания переменной? 6. Для чего предназначена функция StrToFloat? 7. Для чего предназначена процедура ShowMessage? 8. Для чего предназначен метод SetFocus? 9. Для чего предназначена функция FloatToStr? 10. Для чего предназначен визуальный компонент «метка» (тип TLabel)? 11. Для чего предназначен визуальный компонент «однострочный редактор» (тип TEdit)? 12. Для чего предназначен визуальный компонент «командная кнопка» (тип TButton)? 13. Когда вызывается событийная процедура OnExit и как создать шаблон ее кода для компонента «однострочный редактор» (тип TEdit) в интегрированной среде разработки (IDE)? 14. Когда вызывается событийная процедура OnClick и как создать шаблон ее кода для компонента «командная кнопка» (тип TButton) в интегрированной среде разработки (IDE)? Лабораторная работа №2 Тема: Управляющие структуры языка Delphi. Условие. Цель: Сформировать практические навыки: реализация разветвляющихся процессов обработки данных с помощью операторов if, case Object Pascal; построение однооконных интерфейсов с помощью визуального компонента «окно» (класс TForm) и визуальных компонентов панели инструментов Standard: «метка» (класс TLabel), «редактор» (класс TEdit), «кнопка» (класс TButton). ЗАДАНИЕ 1. В соответствии с вариантами задания и приведенной ниже спецификацией реализуйте приложение под Windows. 2. Разработайте тестовые задания, и оттестируйте программу одним из методов тестирования. Спецификация приложения 1. В соответствии с приведенными вариантами заданий реализуйте приложение под Windows, используя для организации пользовательского интерфейса следующие элементы управления: «форма» (класс TForm), «кнопка» (класс TButton), «метка» (класс TLabel), «однострочный редактор» (класс TEdit). Ввод данных и вывод результатов осуществляйте в элементы управления «однострочный редактор». Подписи к однострочным редакторам 40 выполните с помощью элементов «метка». Вычисление результата свяжите с нажатием на элементе управления «кнопка» левой клавиши мыши. 2. Организуйте контроль содержимого строки, вводимой в элемент «однострочный редактор». Если вводимая строка не соответствует заданному формату, то необходимо предусмотреть следующее: в окне сообщений вывести сообщение об ошибке, очистить строку, введенную в «однострочный редактор». 3. Визуальный компонент, в который выводится результат, должен быть доступен только для чтения, чтобы пользователь не мог редактировать его содержимое. 4. Установите удобный для пользователя порядок перемещения фокуса по компонентам с помощью клавиши Tab. Рекомендации к выполнению 1. Для организации управляющей структуры программ используйте оператор if в форме if then и if then else или case. 2. Для выполнения заданий используйте операции mod, div и стандартные функции Abs, Int, Frac,Trunc, Round, Odd. 3. Для преобразования введенных значений из строкового формата в числовой, а результатов – из числового формата в строковый формат используйте библиотечные подпрограммы StrToInt, StrToFloat, IntToStr, FloatToStr модуля Sysutils. 4. Организуйте контроль ввода данных в элемент «однострочный редактор». Для этого используйте блок try…finally и процедуру ShowMessage модуля Dialogs. 5. Чтобы компонент был доступен только для чтения, необходимо в его свойство ReadOnly занести значение True. 6. Чтобы на компонент нельзя было установить фокус ввода с помощью клавиши Tab, необходимо занести в его свойство TabStop значение False. 7. Чтобы установить нужный порядок перемещения фокуса ввода по элементам формы с помощью клавиши Tab: • установите указатель мыши на форме; • нажмите правую клавишу мыши; • в появившемся меню выберите пункт Tab Order; • в появившемся диалоговом окне установите требуемый порядок перемещения фокуса. 8. Разработанные приложения сохраняйте в отдельной папке. Варианты заданий 1. Вычислите площадь треугольника со сторонами a, b, c. Перед вычислением проанализируйте значения, введенные в качестве длин сторон. Если эти значения не могут выступать в качестве длин сторон треугольника, необходимо сообщить об этом пользователю и потребовать повторный ввод. Площадь треугольника вычисляйте по формуле Герона: s p * ( p a) * ( p b) * ( p c); p ( a b c) / 2. 41 2. Вычислить высоты треугольника ha, hb, hc по длинам трех его сторон a, b, c. Перед вычислением площади проанализируйте введенные в качестве длин сторон значения. Если эти значения не могут выступать в качестве длин сторон треугольника, необходимо сообщить об этом пользователю и потребовать повторный ввод. Площадь треугольника s вычисляйте по формуле Герона: s p * ( p a) * ( p b) * ( p c); p (a b c ) / 2; ha 2 * s / a; hb 2 * s / b; hc 2 * s / c. 3. Проанализируйте введенное с клавиатуры целое число и выведите сообщение о его четности. 4. Проанализируйте введенную с клавиатуры пару целых чисел a, n и выведите сообщение о кратности числа a числу n. 5. Вычислите корни квадратного уравнения ax2 bx c 0, если d b2 4* a * c 0, то корни действительные; следовательно, необходимо вычислять x1,2 e f ; e b /(2 * a); f d /(2 * a), если d < 0, то корни мнимые x1,2 e i * f ; e b /(2 * a); f d /(2 * a). 6. Вычислите значение функции x a; sin( x), z cos( x), a x b;. tg( x), x b. 7. Определите, попадает ли точка с координатами x0, y0 в круг радиусом r. Уравнение окружности: r2 = x2 + y2. 8. Определите и сообщите, к какому множеству символов принадлежит введенная литера: • прописная латинская; • строчная латинская; • арабская цифра; • прописная кириллица; • строчная кириллица; • другой символ. Проверку принадлежности введенного символа множеству и вывод сообщения об этом осуществляйте в событийной процедуре OnKeyPress элемента «однострочный редактор». Внутри этой процедуры введенный символ хранится в переменной Key в формате Char. После вывода сообщения 42 о принадлежности введенного символа очищайте содержимое элемента управления «однострочный редактор», используя метод Clear (Например, Edit1.Clear). 9. Выполните задание предыдущего пункта (8), используя оператор Case. ПРИМЕР Пусть требуется определить, является ли введенный символ арабской цифрой или другим символом. Для решения этой задачи можно построить приложение, состоящее из одной формы следующего вида (рис. 2): Edit1 Edit2 Рис. 2 Ей соответствует модуль, текст которого приведен ниже. unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Edit1: TEdit; //Элемент «однострочный редактор» для ввода символа Edit2: TEdit; //Элемент «однострочный редактор» для вывода ответа Label1: TLabel; //Элемент «метка» для хранения надписи к Edit1 Label2: TLabel; //Элемент «метка» для хранения надписи к Edit2 procedure Edit1KeyPress(Sender: TObject; var Key: Char); private {Private declarations} public {Public declarations} end; var Form1: TForm1; implementation {$R *.DFM} procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char); 43 begin if ((Key>='0') and (Key<= '9')) then //Clear – метод, который очищает поле Text «однострочного редактора» begin Edit2.Text:='Арабская цифра'; Edit1.Clear end else begin Edit2.Text:='Другой'; Edit1.Clear end end; //Событийная процедура, вызываемая при нажатии клавиши, когда фокус ввода находится на элементе Edit1 end. СОДЕРЖАНИЕ ОТЧЕТА 1. Задание. 2. Текст программы на Object Pascal. 3. Тестовые наборы данных для тестирования программы. КОНТРОЛЬНЫЕ ВОПРОСЫ 1. Назовите синтаксические правила, в соответствии с которыми записывается оператор if. 2. Укажите порядок, в котором выполняется оператор if. 3. Как поместить в Then- и Else- часть несколько операторов? 4. Что можно размещать между зарезервированными словами if и Then? 5. Что можно размещать после зарезервированного слова Then? 6. Что можно размещать после зарезервированного слова Else? 7. Нарисуйте управляющую структуру, соответствующую оператору if, содержащему только Then- часть, и укажите порядок выполнения узлов. 8. Нарисуйте управляющую структуру, соответствующую оператору if, содержащему Then- и Else- часть, и укажите порядок выполнения узлов. 9. Для чего предназначен метод Clear визуального компонента «однострочный редактор» и как на него можно сослаться в тексте программы? 10. Что содержится в свойстве Text визуального компонента «однострочный редактор» и как на него можно сослаться в тексте программы? 11. Каково множество значений типа Char и как записываются значения этого множества в тексте программы? 12. Перечислите операции, определенные на значениях типа Char, и поясните правила их выполнения. 13. Перечислите стандартные процедуры и функции, определенные на значениях типа Char, и поясните правила их выполнения. 14. Когда вызывается событийная процедура OnKeyPress и как создать шаблон ее кода для компонента «однострочный редактор» (тип TEdit) в интегрированной среде разработки? Лабораторная работа №3 Тема: Управляющие структуры языка Delphi. Выбор. 44 Цель: Сформировать практические навыки: реализация разветвляющихся процессов обработки данных с помощью оператора case Object Pascal и применения логических и побитовых операций; построение однооконных интерфейсов с помощью визуального компонента «окно» (класс TForm) и визуальных компонентов панели инструментов Standard: «метка» (класс TLabel), «редактор» (класс TEdit), «кнопка» (класс TButton), «список» (TListBox), «комбинированный список» (TComboBox). ЗАДАНИЕ 1. В соответствии с вариантами задания и приведенной ниже спецификацией реализуйте приложение под Windows. 2. Разработайте тестовые задания и оттестируйте программу одним из методов тестирования. Спецификация приложения 1. В соответствии с приведенными вариантами заданий реализуйте приложение под Windows, используя для организации пользовательского интерфейса следующие элементы управления: «форма» (класс Tform), «кнопка» (класс TButton), «метка» (класс TLabel), «однострочный редактор» (класс TEdit), «список» (класс TListBox), «комбинированный список» (класс TComboBox). Ввод данных и вывод результатов осуществляйте в элементы управления «однострочный редактор». Подписи к редакторам сделайте с помощью элементов «метка». Выбор операции реализуйте с помощью элемента управления «комбинированный список». Вычисление результата свяжите с нажатием на элементе управления «командная кнопка» левой клавиши мыши. 2. Организуйте контроль содержимого строки, вводимой в элемент «однострочный редактор». Если вводимая строка не соответствует заданному формату, то необходимо предусмотреть следующее: в окне сообщений вывести сообщение об ошибке, очистить строку, введенную в «однострочный редактор». 3. Визуальный компонент, в который выводится результат, должен быть доступен только для чтения, чтобы пользователь не мог редактировать его содержимое. 4. Установите удобный для пользователя порядок перемещения фокуса по компонентам с помощью клавиши Tab. Рекомендации к выполнению 1. Для организации управляющей структуры программ используйте оператор case. 2. Для выполнения заданий используйте логические и побитовые операции. 3. Для преобразования введенных значений из строкового формата в числовой, а результатов – из числового формата в строковый формат используйте библиотечные подпрограммы StrToInt, StrToFloat, IntToStr, FloatToStr модуля Sysutils. 45 4. Организуйте контроль ввода данных в элемент «однострочный редактор». Для этого используйте блок try…finally и процедуру ShowMessage модуля Dialogs. 5. Чтобы компонент был доступен только для чтения, необходимо в его свойство ReadOnly занести значение True. 6. Чтобы на компонент нельзя было установить фокус ввода с помощью клавиши Tab, нужно занести в его свойство TabStop значение False. 7. Разработанные приложения сохраняйте в отдельной папке. Варианты заданий 1. Реализуйте Windows-приложение, которое обеспечивает пользователю возможность выбора любой побитовой операции из определенных в языке, ввод значений операндов, вычисление и вывод результата. 2. Реализуйте Windows-приложение, которое обеспечивает пользователю возможность выбора любой логической операции из определенных в языке, ввод значений операндов, вычисление и вывод результата. ПРИМЕР 1 Пусть требуется обеспечить пользователю возможность выбора любой арифметической операции на целых значениях из определенных в языке, ввод значений операндов, вычисление и вывод результата. Для решения этой задачи можно построить приложение, состоящее из одной формы следующего вида (рис. 3): Рис. 3 Ей соответствует модуль, текст которого приведен ниже. unit Unit1; interface uses 46 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls; type TForm1 = class(TForm) ComboBox1: TComboBox; Edit1: TEdit; Edit2: TEdit; Label1: TLabel; Button1: TButton; Edit3: TEdit; Label2: TLabel; Label3: TLabel; Label4: TLabel; Label5: TLabel; procedure ComboBox1Change(Sender: TObject); procedure Button1Click(Sender: TObject); procedure FormActivate(Sender: TObject); procedure Edit1Exit(Sender: TObject); procedure Edit2Exit(Sender: TObject); private {Private declarations} public {Public declarations} end; var Form1: TForm1; implementation {$R *.DFM} procedure TForm1.ComboBox1Change(Sender: TObject); begin Label3.Caption:= ComboBox1.Items[ComboBox1.ItemIndex]; if Label3.Caption= 'minus' then begin Label1.Hide; Edit1.Hide; Edit2.SetFocus; end else begin Label1.Visible:= True; Edit1.Visible:= True; Edit1.SetFocus; end; end; procedure TForm1.Button1Click(Sender: TObject); var a,b,c: integer; 47 begin if ComboBox1.ItemIndex<>5 then a:= StrToInt(Edit1.Text); b:= StrToInt(Edit2.Text); case ComboBox1.ItemIndex of //Вычисляется индекс выбранного значения комбинированного списка 0: c:= a + b; 1: c:= a – b; 2: c:= a * b; 3: c:= a mod b; 4: c:= a div b; 5: c:= –b; end; Edit3.Text:= IntToStr(c); if ComboBox1.ItemIndex<>5 then Edit1.SetFocus else Edit2.SetFocus; end; procedure TForm1.FormActivate(Sender: TObject); begin ComboBox1.ItemIndex:= 0; ComboBox1.Text:=ComboBox1.Items[ComboBox1.ItemIndex]; Label3.Caption:=ComboBox1.Items[ComboBox1.ItemIndex]; end; procedure TForm1.Edit1Exit(Sender: TObject); var a:integer; begin try a:= StrToInt(Edit1.Text); except on EConvertError do begin ShowMessage('Ошибка ввода');Edit1.SetFocus; end end; end; procedure TForm1.Edit2Exit(Sender: TObject); var a:integer; begin try a:= StrToInt(Edit2.Text); except on EConvertError do begin ShowMessage('Ошибка ввода');Edit2.SetFocus; end end; end; 48 end. ПРИМЕР 2 Пусть требуется обеспечить пользователю возможность выполнения логической операции and, ввод значений операндов, вычисление и вывод результата. Для решения этой задачи можно построить приложение, состоящее из одной формы следующего вида (рис. 4): Рис. 4 Ей соответствует модуль, текст которого приведен ниже. unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls; type TForm1 = class(TForm) Label1: TLabel; Button1: TButton; Label2: TLabel; Label3: TLabel; Label5: TLabel; ListBox1: TListBox; ListBox2: TListBox; Edit1: TEdit; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.DFM} procedure TForm1.Button1Click(Sender: TObject); var a,b,c: Boolean; begin 49 if ListBox1.Items[ListBox1.ItemIndex]= 'True'//Анализируется содержимое выделенной строки then a:= True else a:= False; if ListBox2.Items[ListBox2.ItemIndex]='True'' //Анализируется содержимое выделенной строки then b:= True else b:= False; c:= a and b; if c then Edit1.Text:= 'True' //Заносится результат else Edit1.Text:= 'False'; end; procedure TForm1.FormActivate(Sender: TObject); begin ListBox1.ItemIndex:= 0; //Выделяем строку с индексом 0 ListBox2.ItemIndex:= 0; //Выделяем строку с индексом 0 end; end. СОДЕРЖАНИЕ ОТЧЕТА 1. Задание. 2. Текст программы на Object Pascal 2.0. 3. Тестовые наборы данных для тестирования приложения. КОНТРОЛЬНЫЕ ВОПРОСЫ 1. Назовите синтаксические правила, в соответствии с которыми записывается оператор Case. 2. Укажите порядок, в котором выполняется оператор Case. 3. Как поместить в Case- часть несколько операторов? 4. Что можно размещать между зарезервированными словами Case и of? 5. Что можно размещать после зарезервированного слова Else? 6. Что допустимо использовать в качестве меток варианта в операторе Case? 7. Перечислите допустимые варианты записи меток варианта. 8. Нарисуйте управляющую структуру, соответствующую оператору Case, и укажите порядок выполнения узлов. 9. Для чего предназначены функции StrToInt и IntToStr? 10. Перечислите, какие типы относятся к целочисленным типам, охарактеризуйте множества их значений, покажите, как записываются значения этих типов в тексте программы. 11. Перечислите операции, определенные на значениях целочисленных типов, и поясните правила их выполнения. 12. Перечислите стандартные процедуры и функции, определенные на значениях целочисленных типов, и поясните правила их выполнения. 50 13. Когда вызывается событийная процедура OnKeyPress и как создать шаблон ее кода для компонента «редактор» (тип TEdit) в интегрированной среде разработки? 14. Как сослаться на значение индекса выбранной строки визуального компонента «комбинированный список» (тип TComboBox) в тексте программы? 15. Как сослаться на выбранную строку визуального компонента «комбинированный список» (тип TComboBox) в тексте программы? 16. Когда вызывается событийная процедура OnKeyPress и как создать шаблон ее кода для компонента «редактор» (тип TEdit) в интегрированной среде разработки? 17. Когда вызывается событийная процедура OnChange и как создать шаблон ее кода для компонента «комбинированный список» (тип TComboBox) в интегрированной среде разработки? Лабораторная работа №4 Тема: Управляющие структуры языка Delphi. Циклы. Цель: Сформировать практические навыки: реализация циклических процессов обработки данных с помощью операторов While, Repeat Object Pascal; построение однооконных интерфейсов с помощью визуального компонента «окно» (класс TForm) и визуальных компонентов панели инструментов Standard: «метка» (класс TLabel), «редактор» (класс TEdit), «кнопка» (класс TButton), «многострочный редактор текста» (TMemo). ЗАДАНИЕ 1. В соответствии с вариантами задания и приведенной ниже спецификацией реализуйте приложение под Windows. 2. Разработайте тестовые задания и оттестируйте программу одним из методов тестирования. Спецификация приложения 1. В соответствии с приведенными вариантами заданий реализуйте приложение под Windows, используя для организации пользовательского интерфейса следующие элементы управления: «форма» (класс Tform), «кнопка» (класс TButton), «метка» (класс TLabel), «однострочный редактор» (класс TEdit), «многострочный редактор» (класс TMemo). Ввод данных и вывод результатов осуществляйте в элементы управления «однострочный редактор». Подписи к редакторам сделайте с помощью элементов «метка». Документирование работы с приложением выполните с помощью элемента управления «многострочный редактор». Вычисление результата свяжите с нажатием на элементе управления «кнопка» левой клавиши мыши. 2. Организуйте контроль ввода в элемент «редактор», так что если вводимая строка не соответствует требованиям, то в окне сообщений выводится сообщение об ошибке, очищается строка «однострочный редактор». 51 3. Документируйте сеанс работы с приложением: запоминайте введенные исходные данные и полученный результат в элементе управления «многострочный редактор». Рекомендации к выполнению 1. Для организации управляющей структуры программ используйте операторы While, Repeat. 2. Для преобразования введенных значений из строкового формата в числовой, а результатов – из числового формата в строковый формат используйте библиотечные подпрограммы StrToInt, StrToFloat, IntToStr, FloatToStr модуля Sysutils. 3. Организуйте контроль ввода данных в элемент «редактор». Для этого используйте блок try…finally и процедуру ShowMessage модуля Dialogs. 4. Чтобы компонент был доступен только для чтения, необходимо в его свойство ReadOnly занести значение True. 5. Чтобы на компонент нельзя было установить фокус ввода с помощью клавиши Tab, необходимо занести в его свойство TabStop значение False. 6. Документирование сеанса осуществляйте с помощью компонента «многострочный редактор», как показано в примере. 7. Разработанные приложения сохраняйте в отдельной папке. Варианты заданий 1. Выведите заданный разряд целого числа. Разряды нумеруйте справа налево, начиная с единицы. Для решения используйте операции mod, div. Решите задачу дважды: первый раз – используя оператор While, второй раз – оператор Repeat. 2. Выведите заданный разряд дробной части действительного числа. Разряды нумеруйте от десятичной точки направо, начиная с единицы. Для решения используйте функции Int, Frac. Решите задачу дважды: первый раз – используя оператор While, второй раз – оператор Repeat. 3. Вычислите и выведите сообщение о четности введенного целого числа. Операции mod, div и функцию Odd не использовать. Решите задачу дважды: первый раз с помощью оператора While, второй раз – оператора Repeat. 4. Вычислите и выведите сообщение о кратности пары введенных целых чисел. Операции mod, div и функцию Odd не использовать. Решите задачу дважды: первый раз с помощью оператор While, второй раз – оператора Repeat. 5. Вычислите и выведите число Фибоначчи по его номеру, который вводится пользователем. Ряд чисел 1, 1, 2, 3, 4, 8, 13, … называются числами Фибоначчи. Каждое число называется «фибом». Таким образом, первый «фиб» или «фиб(1)» – это 1, «фиб(2)» – это 1, «фиб(3)» – это 2 и т.д. Ряд строится на основе того, что каждый последующий «фиб» является суммой двух предыдущих, т.е. фиб(8) = 21. 6. Напишите программу, которая вычисляет наибольший общий делитель (НОД) двух натуральных чисел. 52 ПРИМЕР 1 Пусть требуется заполнить таблицу из двух колонок: в первую заносится графический символ, во вторую – код символа. Для решения этой задачи можно построить приложение, состоящее из одной формы следующего вида (рис. 5): Рис. 5 Для хранения таблицы использован компонент «многострочный редактор», расположенный в правой части формы. Ввод символа и отображение его кода осуществляется в компоненты «однострочный редактор». Для переноса введенного символа и его кода из компонентов «однострочный редактор» в строку компонента «многострочный редактор» используется компонент «командная кнопка» с подписью «Запомнить». Для удаления последней строки из компонента «многострочный редактор» используется компонент «командная кнопка» с подписью «Удалить». Первую строку компонента «многострочный редактор», содержащую текст «Символ Код», можно сформировать на этапе визуального проектирования формы. Для этого необходимо: • выделить на форме компонент Memo1; • в инспекторе объектов выделить свойство Lines и кликнуть указателем мыши на кнопке с тремя точками; • в появившемся окне редактора ввести необходимый текст. Чтобы можно было просматривать строки текста компонента «многострочный редактор», которые не помещаются на экране, необходимо в свойстве ScrollBars установить значение ssVertical. Разработанной форме соответствует модуль, текст которого приведен ниже. unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Edit1: TEdit; Edit2: TEdit; Label1: TLabel; Label2: TLabel; Button1: TButton; 53 Memo1: TMemo; Button2: TButton; procedure Edit1KeyPress(Sender: TObject; var Key: Char); procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); private {Private declarations} public {Public declarations} end; var Form1: TForm1; implementation {$R *.DFM} procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char); begin Edit2.Text:= IntToStr(Ord(Key)); //Код введенного символа заносится в редактор Edit1.Clear; end; procedure TForm1.Button1Click(Sender: TObject); begin Memo1.Lines.Add(Edit1.Text+' '+Edit2.Text); //Добавляется строка в компонент Memo1 Edit1.SetFocus; end; procedure TForm1.Button2Click(Sender: TObject); begin if Memo1.Lines.Count>1 then //Удаляем из Memo1 последнюю строку, если строк больше одной Memo1.Lines.Delete(Memo1.Lines.Count-1); Edit1.SetFocus; end; end. ПРИМЕР 2 Пусть требуется подсчитывать количество значащих десятичных разрядов в целом неотрицательном числе и заполнять таблицу из двух колонок: в первую заносится введенное целое, во вторую – количество разрядов. Для решения этой задачи можно построить приложение, состоящее из одной формы следующего вида (рис. 6): 54 Рис. 6 Для хранения таблицы использован компонент «многострочный редактор», расположенный в правой части формы. Ввод целого и отображение количества разрядов в нем осуществляется в компоненты «однострочный редактор». Для переноса введенного целого и количества разрядов в нем из компонентов «однострочный редактор» в строку компонента «многострочный редактор» используется компонент «командная кнопка» с подписью «Запомнить». Для удаления последней строки из компонента «многострочный редактор» используется компонент «командная кнопка» с подписью «Удалить». Первую строку компонента «многострочный редактор», содержащую текст «Символ Код», можно сформировать на этапе визуального проектирования формы. Для этого необходимо: • выделить на форме компонент Memo1; • в инспекторе объектов выделить свойство Lines и кликнуть указателем мыши на кнопке с тремя точками; • в появившемся окне редактора ввести необходимый текст. Чтобы можно было просматривать строки текста компонента «многострочный редактор», которые не помещаются на экране, необходимо в свойстве ScrollBars установить значение ssVertical. Разработанной форме соответствует модуль, текст которого приведен ниже. unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Edit1: TEdit; Edit2: TEdit; Label1: TLabel; Label2: TLabel; Button1: TButton; // Кнопка добавить Memo1: TMemo; Button2: TButton; // Кнопка удалить 55 Button3: TButton;// Кнопка вычислить procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button3Click(Sender: TObject); procedure Edit1Exit(Sender: TObject); private {Private declarations} public {Public declarations} end; var Form1: TForm1; implementation {$R *.DFM} procedure TForm1.Button1Click(Sender: TObject); begin //Добавляется строка к списку строк компонента Memo1 Memo1.Lines.Add(Edit1.Text+' '+Edit2.Text); Edit1.SetFocus; end; procedure TForm1.Button2Click(Sender: TObject); begin if Memo1.Lines.Count>1 then begin //Удаляем из Memo1 последнюю строку, если строк больше одной Memo1.Lines.Delete(Memo1.Lines.Count-1); end; Edit1.SetFocus; end; procedure TForm1.Button3Click(Sender: TObject); var k,n: Integer; begin n:= StrToInt(Edit1.Text); k:= 0; while n>0 do begin//Вычисляем число разрядов n:= n div 10; inc(k); end; Edit2.Text:= IntToStr(k); end; procedure TForm1.Edit1Exit(Sender: TObject); var a:Cardinal; begin try a:= StrToInt(Edit1.Text); except 56 on EConvertError do begin showMessage('Ошибка ввода'); Edit1.SetFocus end; end; end; end. СОДЕРЖАНИЕ ОТЧЕТА 1.Задание. 2.Текст программы на Object Pascal. 3.Тестовые наборы данных для тестирования приложения. КОНТРОЛЬНЫЕ ВОПРОСЫ 1. Назовите синтаксические правила написания оператора While. 2. Укажите порядок, в котором выполняется оператор While. 3. Как поместить в do= часть несколько операторов? 4. Что можно размещать между зарезервированными словами While и do? 5. Нарисуйте управляющую структуру, соответствующую оператору While, и укажите порядок выполнения узлов. 6. Назовите синтаксические правила написания оператора Repeat. 7. Укажите порядок, в котором выполняется оператор Repeat. 8. Что можно размещать между зарезервированными словами Repeat и until? 9. Нарисуйте управляющую структуру, соответствующую оператору Repeat, и укажите порядок выполнения узлов. 10. Охарактеризуйте множество значений типа Boolean, покажите, как записываются значения этого типа в тексте программы. 11. Перечислите операции, определенные на значениях типа Boolean, и поясните правила их выполнения. 12. Перечислите стандартные процедуры и функции, определенные на значениях типа Boolean, и поясните правила их выполнения. 13. Как добавить строку в конец списка строк визуального компонента «многострочный редактор» (класс TMemo) в тексте программы? 14. Как сослаться на текущую длину списка строк визуального компонента «многострочный редактор» (класс TMemo) в тексте программы? 15. Как удалить последнюю строку списка строк визуального компонента «многострочный редактор» (класс TMemo) в тексте программы? Лабораторная работа №5 Тема: Символы и строки Цель: Сформировать практические навыки: реализация процессов обработки символьных и строковых данных с помощью функций и процедур; построение однооконных интерфейсов с помощью визуального компонента «окно» (класс TForm) и визуальных компонентов панели 57 инструментов Standard: «метка» (класс TLabel), «редактор» (класс TEdit), «кнопка» (класс TButton), «многострочный редактор текста» (TMemo) Компьютер может обрабатывать не только числовую информацию, но и символьную. Язык Delphi оперирует с символьной информацией, которая может быть представлена как отдельными символами, так и строками (поcледовательностью символов). Символы Для хранения и обработки символов используются переменные типа Ansichar и wideChar. Тип Ansichar представляет собой набор ANSI-символов, з котором каждый символ кодируется восьмиразрядным двоичным числом (байтом). Тип wideChar представляет собой набор символов в кодировке Unicode, в которой каждый символ кодируется двумя байтами. Для обеспечения совместимости с предыдущими версиями поддерживается тип Char, эквивалентный AnsiChar. Значением переменной символьного типа может быть любой отображаемый символ: буква русского или латинского алфавитов; цифра; знак препинания; И специальный символ, например, "новая строка". Переменная символьного типа должна быть объявлена в разделе объявления переменных. Инструкция объявления символьной переменной в общем виде выглядит так: Имя: char; где: имя — имя переменной символьного типа; char — ключевое слово обозначения символьного типа. Примеры: otv: char; ch: char; Как и любая переменная программы, переменная типа char может получить значение в результате выполнения инструкции присваивания. Если переменная типа char получает значение в результате выполнения операции присваивания, то справа от знака := должно стоять выражение типа char, например, переменная типа char или символьная константа — символ, заключенный в кавычки. В результате выполнения инструкций c1 := '*'; с2 := c1; переменная c1 получает значение присваиванием значения константы, а переменная с2 — присваиванием значения переменной cl (предполагается, что переменные c1 и с2 являются переменными символьного типа). Переменную типа char можно сравнить с другой переменной типа char или с символьной константой. Сравнение основано на том, что каждому символу поставлено в соответствие число (см. приложение 2), причем символу 'о' соответствует число меньшее, чем символу У, символу 'А' — 58 меньшее, чем 'в', символу V — меньшее, чем а. Таким образом, можно записать: '0'<'1'<..<'9'<..<'A'<'B'<..<'Z'<'a'<'b'<..<'z' Символам русского алфавита соответствуют числа большие, чем символам латинского алфавита, при этом справедливо следующее: 'А'<'Б'<'В'<..<'Ю'<'Я'<'а'<'б'<'в'<...<'э'<'ю'<'я' В тексте программы вместо символа можно указать его код, поставив перед числом оператор #. Например, вместо константы 'в' можно записать #193. Такой способ записи, как правило, используют для записи служебных символов или символов, которые во время набора программы нельзя ввести с клавиатуры. К примеру, часто используемый при записи сообщений символ "новая строка" записывается так: #13. В программах обработки символьной информации часто используют функции chr и Ord. Значением функции chr является символ, код которого указан в качестве параметра. Например, в результате выполнения инструкции c:=chr(32) переменной с будет присвоено значение пробел. Функция ord позволяет определить код символа, который передается ей в качестве параметра. Например, в результате выполнения инструкции k:=ord('*') переменная k будет содержать число 42 — код символа *. Программа, текст которой приведен в листинге 3.1, выводит таблицу кодировки букв русского алфавита. Вид окна программы представлен на рис. 3.1. Основную работу выполняет процедура обработки события OnActivate, которая формирует и выводит в поле метки (Label1) таблицу. Событие OnActivate происходит при активизации формы приложения, и поэтому процедура TForm1.FormActivate выполняется автоматически, сразу после появления формы на экране. Рис. 3.1. Форма приложения во время разработки 59 Рис. 3.2. Форма приложения во время работы Листинг 3.1. Таблица символов unit tablsim_; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Label1: TLabe1; procedure FormActivate(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.DFM} procedure TForm1.FormActivate(Sender: TObject); var st:string; // таблица формируется как строка символов dec: byte; // код символа i,j:integer; // номер строки и колонки таблицы begin st:=''; dec:=192; for i:=0 to 15 do // шестнадцать строк begin dec:=i + 192; for j:=1 to 4 do // четыре колонки 60 begin st:=st+chr(dec)+'-'+IntToStr(dec)+' '; dec:=dec + 16; end; st:=st + #13; // переход к новой строке экрана end; Label1.caption:=st; end; end. Форма приложения Таблица символов содержит только один компонент -поле метки (Label1l). Для того чтобы колонки таблицы имели одинаковую ширину, свойству Label1.Font.Name следует присвоить имя шрифта, у которого все символы имеют одинаковую ширину, например, courier New cyr. Вид окна приложения во время работы приведен на рис. 3.2. Строки Строки могут быть представлены следующими типами: shortstring, Longstring и widestring. Различаются эти типы предельно допустимой длиной строки, способом выделения памяти для переменных и методом кодировки символов. Переменной типа shortstring память выделяется статически, т. е. до начала выполнения программы, и количество символов такой строки не может превышать 255. Переменным типа Longstring и widestring память выделяется динамически — во время работы программы, поэтому длина таких строк практически не ограничена. Помимо перечисленных выше типов можно применять универсальный cтроковый тип String. Тип String эквивалентен типу Shortstring. Переменная строкового типа должна быть объявлена в разделе объявления переменных. Инструкция объявления в общем виде выглядит так: Имя: String; или Имя: String [длина] где: имя — имя переменной; string — ключевое слово обозначения строкового типа; длина — константа целого типа, которая задает максимально допустимую длину строки. Пример объявления переменных строкового типа: name: string[30]; buff: string; Если в объявлении строковой переменной длина строки не указана, то ее длина задается равной 255 символам, т. е. объявления stroka: string [255]; stroka: string; эквивалентны. В тексте программы последовательность символов, являющаяся строкой (строковой константой), заключается в одинарные кавычки. 61 Например, чтобы присвоить строковой переменной parol значение, нужно записать: parol:= 'Большой секрет'; или parol:= '2001'; Следует обратить внимание, что инструкция parol:=2001; неверная, т.к. тип константы не соответствует типу переменной. Во время компиляции этой инструкции будет выведено сообщение: incompatible types: 'Char' and 'Integer' (типы Char и Integer несовместимы). Используя операции =, <, >, <=, >= и о, переменную типа string можно сравнить с другой переменной типа string или со строковой константой. Строки сравниваются посимвольно, начиная с первого символа. Если все символы сравниваемых строк одинаковые, то такие строки считаются равными. Если в одинаковых позициях строк находятся разные символы, большей считается та строка, у которой в этой позиции находится символ с большим кодом. В табл. 3.1 приведены примеры сравнения строк. Таблица 3.1. Сравнение строк Строка 1 Строка 2 Результат сравнения Иванов Иванов Строки равны Васильев Васильев Строка 1 больше строки 2 Алексеев Петров Строка 1 меньше строки 2 Иванова Иванов Строка 1 больше строки 2 Кроме операции сравнения, к строковым переменным и константам можно применить операцию сложения, в результате выполнения которой получается новая строка. Например, в результате выполнения инструкций f irst__name: ='Иван' ; last_name:='Иванов'; ful_name:=first_name+last_name; переменная fui_name получит значение 'Иван Иванов'. Операции со строками В языке Delphi есть несколько полезных при работе со строками функций и процедур. Ниже приведено их краткое описание и примеры использования. Функция length Функция length возвращает длину строки. У этой функции один параметр — выражение строкового типа. Значением функции length (целое число) является количество символов, из которых состоит строка. Например, в результате выполнения инструкций n:=length('Иванов'); m:=length(' Невский проспект '); значение переменных n и m будет равно 6 и 20. Процедура delete 62 Процедура delete позволяет удалить часть строки. В общем виде обращение к этой процедуре выглядит так: delete(Строка, р, п) где: Строка — переменная или константа строкового типа; р — номер символа, с которого начинается удаляемая подстрока; п — длина удаляемой подстроки. Например, в результате выполнения инструкций p:='Город Санкт-Петербург'; delete(s,7,6); значением переменной s будет строка ' город Петербург'. Функция роs Функция роз позволяет определить положение подстроки в строке. В общем виде обращение к функции выглядит так: pos(Подстрока,Строка); где Подстрока — строковая константа или переменная, которую надо найти в строковой константе или переменной строка. Например, в результате выполнения инструкции р := pos('Пе','Санкт-Петербург'); значение переменной р будет равно 7. Если в строке нет искомой подстроки, то значение функции роз будет равно нулю. Ниже приведена инструкция while, в результате выполнения которой удаляются начальные пробелы из строки st. while(pos(' ',st) = 1) and(length(st) > 0) do delete (st,1,1); Пробелы удаляет инструкция delete (st, i, i), которая выполняется в цикле до тех пор, пока первым символом строки является пробел (в этом случае значение роs (' ',st) равно единице). Необходимость проверки условия length (st) > 0 объясняется возможностью того, что введенная строка состоит только из пробелов. Функция сору Функция сору позволяет выделить фрагмент строки. В общем виде обращение к функции сору выглядит так: сору(Строка, р, п) где: строка — выражение строкового типа, содержащее строку, фрагмент которой надо получить; р — номер первого символа, с которого начинается выделяемая подстрока; n — длина выделяемой подстроки. Например, в результате выполнения инструкций st:= 'Инженер Иванов'; fam:=copy(st, 9, 6) ; значением переменной fam будет строка 'Иванов1. Задания для самостоятельной работы 1. Написать программу, которая будет подсчитывать количество символов в введенной строке. 2. Модернизировать предыдущую программу таким образом, чтобы дополнительно узнать сколько пробелов было в введенной строке. 63 3. Измените предыдущую программу таким образом, чтобы кроме подсчета символов она заменяла все пробелы буквой "s" и выводила на экран итоговый результат. 4. Напишите программу, которая будет удалять пробелы из строки, а результат выводить на экран. 5. Напишите программу, которая читает с клавиатуры строку текста и выводит ее на экране "задом на перед". Лабораторная работа №6 Тема: Массивы. Объявление массивов. Ввод и вывод. Цель: Сформировать практические навыки: реализация процессов обработки одномерных и двумерных массивов; построение однооконных интерфейсов с помощью визуального компонента «окно» (класс TForm) и визуальных компонентов панели инструментов Standard: «метка» (класс TLabel), «редактор» (класс TEdit), «кнопка» (класс TButton), (класс TStringGrid). Массив – это структура данных, представляющая собой набор переменных одинакового типа, имеющих общее имя. Массивы удобно использовать для хранения однородной по своей природе информации, например, таблиц и списков. Описание и обработка массивов в Delphi осуществляются так же как и в Pascale , а вот ввод и вывод отличаются. В Delphi для ввода данных используются компоненты StringGrid палитры Additional (Дополнительная) или Memo палитры Standart (Стандартная), а вывод осуществляется или в поле диалогового окна (обращение к свойству Caption текстовой метки Label1.Caption или к свойству Lines многостраничного поля Memo1.Lines.Add(st) или в окно сообщения ShowMessage. При вводе-выводе удобно использовать инструкцию for. При этом переменная-счетчик инструкции for может быть использована в качестве индекса элемента массива. При вводе массива через таблицу (StringGrid), надо учитывать, что колонки и строки таблицы нумеруются с нуля. Рассмотрим ввод-вывод массива на примере: вычисление среднего арифметического значения элементов массива. Использование компонента StringGrid Значок StringGrid находится на вкладке Additional (Дополнительная). Компонент StringGrid представляет собой таблицу, ячейки которой содержат строки символов. Ниже перечислены некоторые свойства компонента StringGrid: RowCount, ColCount – число строк и столбцов, включая заголовок Row,Col – текущие строка и столбец 64 ColWidths[], RowHeights[] – массивы ширины столбцов и высоты строк Cells[столбец, строка] – данные ячейки таблицы (строковый тип) FixedCols, FixedRows – число зафиксированных столбцов слева и строк сверху. Нумеруются с нуля, причем нулевые строка и столбец по умолчанию отведены для заголовков Options – настройки таблицы со значениями True/False (.goEditing – допустимость редактирования, goRowSizing, goColSizing – можно ли пользователю менять размеры строк и столбцов) DefaultColWidth, DefaultRowHeight – ширина и высота ячейки по умолчанию GridLineWidth –ширина линий, ограничивающих ячейки Options.AlwaysShowEditing – Признак нахождения компонента в режиме редактирования. Если значение свойства False, то для того, чтобы в ячейке появился курсор, надо начать набирать текст, нажать клавишу<F2> или сделать щелчок мышью. Options.goTabs – Разрешает (True) или запрещает (False) использование клавиши <Tab> для перемещения курсора в следующую ячейку таблицы. Добавляется компонент StringGrid в форму точно та же, как и другие компоненты. После добавления компонента к форме нужно выполнить его настройку: ColCount=10 FixedCols=0 RowCount=1 DefaultRowHeight=24 DefaultColWidth=64 Options. GoEditing=true Options.AlwaysShowEditing=true Options.goTabs=true Значения свойств Height и Width следует при помощи мыши установить такими, чтобы размер компонента был равен размеру строки. Приложение должно иметь следующий вид: Label1 StringGrid Label2 Label3 Button1 Button2 65 Button3 Процедура обработки события OnClick (клавиша Вычислить) представлена ниже: procedure TForm1.Button1Click(Sender: TObject); var a:array[1..10] of integer; sum,i:integer; sr:real; s:string; begin s:=''; for i:=1 to 10 do begin ввод массива if length(StringGrid1.Cells[i-1,0])<>0 then a[i]:=StrToInt(StringGrid1.Cells[i-1,0]) else a[i]:=0; s:=s+StringGrid1.Cells[i-1,0]+' '; Label2.Caption:='Введенный массив'+#13+s+#13; вывод end; массива sum:=0; for i:=1 to 10 do sum:=sum+a[i]; обработка массива sr:=sum/10; Label3.Caption:='сумма элементов:'+IntToStr(sum)+ вывод результата #13+'Среднее арифметическое:'+FloatToStr(sr) end; Текст процедуры обработки события OnKeyPress приведен ниже. Процедура осуществляет контроль вводимых данных, разрешая вводить в ячейку таблицы только цифры. Следует обратить внимание на свойство Col, которое во время работы программы содержит номер колонки таблицы, в которой находится курсор. Это свойство можно также использовать для перемещения курсора в нужную ячейку таблицы при нажатии клавиши<Enter>. Однако нужно учитывать, что колонки и строки таблицы нумеруются с нуля. Procedure TForm1.StringGrid1KeyPress(Sender: TObject; var Key: Char); begin case key of #8,'0'..'9':; #13: if StringGrid1.Col<StringGrid1.ColCount-1 then StringGrid1.Col:=StringGrid1.Col+1; else key:=Chr(0); end; end; При нажатии клавиши Сброс происходит очистка полей ввода: procedure TForm1.Button2Click(Sender: TObject); var i:integer; begin For i:=1 to 10 do StringGrid1.Cells[i-1,0]:=''; 66 Label2.Caption:=’ ‘; Label3.Caption:=’ ‘; end; При нажатии клавиши Выход происходит закрытие приложения: procedure TForm1.Button3Click(Sender: TObject); begin form1.Close end; Использование компонента Memo. В некоторых случаях для ввода массива можно использовать компонент Memo. Компонент Memo позволяет вводить текст, состоящий из достаточно большого количества строк, поэтому его удобно использовать для ввода символьного массива. Компонент Memo добавляется в форму обычным образом. Значок компонента находится на вкладке Standart (Стандартная). Свойство Lines определяет массив, каждый элемент которого содержит одну строку находящегося в поле Memo текста, а свойство Lines.Count определяет количество строк текста в поле Memo. При использовании компонента Memo для ввода массива значение каждого элемента массива следует вводить в отдельной строке и после ввода каждого элемента массива нажимать клавишу <Enter>. Для того, чтобы курсор был виден в поле ввода компоненты Memo, надо установить у свойства OnRead значение False, а у свойства Enabled значение True. Получить доступ к находящейся в поле Memo строке текста можно при помощи свойства Lines, указав в квадратных скобках номер нужной строки (строки нумеруются с нуля). Основной цикл процедуры ввода символьного массива из компонента Memo может выглядеть так: for i:=1 to 10 do a[i]:=Memo1.Lines[i-1]; Для ввода числового массива надо использовать функции преобразования StrToInt или StrToFloat: for i:=1 to 10 do a[i]:=StrToInt(Form1.Memo1.Lines[i-1]); for i:=1 to 10 do a[i]:=StrToFloat(Form1.Memo1.Lines[i-1]); Приложение должно иметь следующий вид: Label1 Memo Окно 1 ShowMessag e 67 Batton Batton Batton 1 2 3 Процедура обработки события OnClick (клавиша Вычислить) представлена ниже: procedure TForm1.Button1Click(Sender: TObject); var a:array[1..10] of integer; sum,i,n:integer; sr:real; s:string; begin s:=''; n:=Memo1.Lines.Count; if n=0 then begin ShowMessage('Исходные данные не введены!'); Exit; end; if n>10 then begin ShowMessage('Количество строк превышает размер массива.'); n:=10; end; for i:=1 to n do begin a[i]:=StrToInt(Form1.Memo1.Lines[i-1]); s:=s+Form1.Memo1.Lines[i-1]+#13; end; s:='Введенный массив'+#13+s+#13; sum:=0; for i:=1 to n do sum:=sum+a[i]; sr:=sum/n; s:=s+'сумма элементов:'+IntToStr(sum)+ #13+'Среднее арифметическое:'+FloatToStr(sr); ShowMessage(s); end; Процедура TForm1.Button1Click сначала проверяет, есть ли в поле Memo1 текст. Если текст есть (в этом случае значение свойства Lines.Count больше нуля), то процедура сравнивает количество введенных строк и размер массива. Если это количество превышает размер массива, то программа 68 выдает сообщение об этом и изменяет значение n, тем самым подготавливает ввод только первых 10 строк. Если текста нет, т.е. n=0, то выдается сообщение об ошибке и программа завершает свою работу. Веденный массив и результаты работы программы выдаются в отдельное окно функцией ShowMassage. Текст процедуры обработки события OnKeyPress приведен ниже. Процедура осуществляет контроль вводимых данных, разрешая вводить в ячейку таблицы только цифры. procedure TForm1.Memo1KeyPress(Sender: TObject; var Key: Char); begin Case key of '0'..'9',#8,#13:; else key:=chr(0); end; end; При нажатии клавиши Сброс происходит очистка полей ввода при помощи события Clear: procedure TForm1.Button2Click(Sender: TObject); begin Memo1.Clear; end; При нажатии клавиши Выход происходит закрытие приложения: procedure TForm1.Button3Click(Sender: TObject); begin Form1.Close; end; Задание: 1. Напишите программу поиска трех последовательных элементов, сумма которых максимальна, в числовом массиве из 30 элементов. 2. Дан целочисленный массив из 30 элементов. Элементы могут принимать значения от 0 до 100 – баллы, полученные на ЕНТ. Напишите программу, которая подсчитывает и выводит средний балл учащихся, сдавших экзамен (получивших оценку более 20 баллов). Гарантируется, что хотя бы один ученик в классе успешно сдал экзамен. Лабораторная работа №7 Тема: Поиск элементов массива. Сортировка массивов. Цель: Сформировать практические навыки: реализация процессов обработки одномерных и двумерных массивов; построение однооконных интерфейсов с помощью визуального компонента «окно» (класс TForm) и визуальных компонентов панели инструментов Standard: «метка» (класс TLabel), «редактор» (класс TEdit), «кнопка» (класс TButton), (класс TStringGrid). 69 Поиск минимального (максимального) элемента массива Будем искать минимальный элемент в целочисленном массиве. Для этого немного изменим обработчик события OnClick для кнопки: procedure TForm1.Button1Click(Sender: TObject); var i:integer;//номер элемента, сравниваемого с минимальным a:array[1..10] of integer; min:integer;//номер минимального элемента begin //Введем массив for i:=1 to 10 do //Преобразуем полученные подстроки в числа a[i]:=StrToInt(GetSubStr(Edit1.text,' ',i));//используем пробел в качестве разделителя //Найдем минимальный элемент min:=1; //пусть номер минимального элемента = 1 for i:= 2 to 10 do // начнем искать со следующего if a[i] < a[min] then min:=i; Form1.caption:=IntToStr(a[min]); // выводим в заголовок формы минимальный элемент end; В этом примере a[min] минимальный элемент массива, а min - номер минимального элемента. Алгоритм очень простой: сравниваем каждый следующий элемент с минимальным, если он меньше минимального, то запоминаем его номер в переменной min, и продолжаем сравнивать уже с ним. Чтобы найти максимальный элемент, нужно изменить всего одну строку: >>> if a[i] < a[min] then min:=i; Надо заменить на: if a[i] > a[min] then min:=i; Только теперь a[min] - максимальный элемент, а min - номер максимального элемента. Поиск заданного элемента в массиве Поступим методом простого перебора. Для этого будем перебирать все элементы массива, пока не встретим искомый элемент, или пока не дойдем до конца массива. Элемент, совпадение с которым нам надо найти будем хранить в текстовом поле Edit2. Обработчик события OnClick нашей кнопки будет иметь такой вид: procedure TForm1.Button1Click(Sender: TObject); var i:integer; a:array[1..10] of integer; n:integer;//образец found:boolean; 70 begin //Введем массив for i:=1 to 10 do //Преобразуем полученные подстроки в числа a[i]:=StrToInt(GetSubStr(Edit1.text,' ',i));//используем пробел в качестве разделителя n:=StrToInt(Edit2.text); found:=false; i:=1; REPEAT if a[i] = n then found:=true else i:=i+1; UNTIL (i > 10) or (found = true); if found then showmessage('Совпадение с элементом номер '+IntToStr(i)); end; Сортировка массива Под сортировкой массива подразумевается процесс перестановки элементов массива, целью которого является размещение элементов массива в определенном порядке. Например, если имеется массив целых чисел а, то после выполнения сортировки по возрастанию должно выполняться условие: а[1] < а[2] < .. .< a[SIZE] где SIZE — верхняя граница индекса массива. Примечание Задача сортировки распространена в информационных системах и используется как предварительный этап задачи поиска, т. к. поиск в упорядоченном (отсортированном) массиве проводится намного быстрее, чем в неупорядоченном (см. рассмотренный ранее метод бинарного поиска). Существует много методов (алгоритмов) сортировки массивов. Рассмотрим два из них: метод прямого выбора; метод прямого обмена. Сортировка методом прямого выбора Алгоритм сортировки массива по возрастанию методом прямого выбора может быть представлен так: 1. Просматривая массив от первого элемента, найти минимальный элемент и поместить его на место первого элемента, а первый — на место минимального. 2. Просматривая массив от второго элемента, найти минимальный элемент и поместить его на место второго элемента, а второй — на место минимального. 3. И так далее до предпоследнего элемента. Ниже представлена программа сортировки массива целых чисел по возрастанию, диалоговое окно которой изображено на рис. 5.15. 71 Рис. 5.15. Диалоговое окно программы сортировки массива простым выбором Процедура сортировки, текст которой приведен в листинге 5.9, запускается нажатием кнопки Сортировка (Button1). Значения элементов массива вводятся из ячеек компонента StringGrid1. После выполнения очередного цикла поиска минимального элемента в части массива процедура выводит массив в поле метки (Label2). Листинг 5.9. Сортировка массива простым выбором procedure TForm1.ButtonlClick(Sender: TObject); const SIZE=10; var a:array[1..SIZE] of integer; min:integer; { номер минимального элемента в части массива от i до верхней границы массива } j:integer; { номер элемента, сравниваемого с минимальным } buf:integer; { буфер, используемый при обмене элементов массива } i,k:integer; begin // ввод массива for i:=l to SIZE do a[i]:=StrToInt(StringGridl.Cells[i-1,0]) ; Iabel2.caption:=''; for i:=l to SIZE-1 do begin { поиск минимального элемента в части массива от а[1] до a[SIZE]} min:=i; for j:=i+l to SIZE do if a[j] < a [min] then min:=j; { поменяем местами a [min] и a[i] } buf:=a[i]; a[i]:=a[min]; a[min]:=buf; { вывод массива } for k:=l to SIZE do Label2.caption:=label2.caption+' '+IntTostr(a[k]); Label2.caption:=label2.caption+#13; end; Label2.caption:=label2.caption+#13+'MaccMB отсортирован.'; 72 end; На рис. 5.16 приведено диалоговое окно программы после завершения процесса сортировки. Рис. 5.16. Диалоговое окно программы Сортировка массива Сортировка методом обмена В основе алгоритма лежит обмен соседних элементов массива. Каждый элемент массива, начиная с первого, сравнивается со следующим, и если он больше следующего, то элементы меняются местами. Таким образом, элементы с меньшим значением продвигаются к началу массива (всплывают), а элементы с большим значением — к концу массива (тонут). Поэтому данный метод сортировки обменом иногда называют методом "пузырька". Этот процесс повторяется столько раз, сколько элементов в массиве, минус единица. На рис. 5.17 цифрой 1 обозначено исходное состояние массива и перестановки на первом проходе, цифрой 2 — состояние после перестановок на первом проходе и перестановки на втором проходе, и т. д. Рис. 5.17. Процесс сортировки массива 73 Рис. 5.18. Диалоговое окно программы Сортировка методом обмена На рис. 5.18 приведено диалоговое окно программы сортировки массива методом обмена. Процедура сортировки, текст которой приведен в листинге 5.10, запускается нажатием кнопки Сортировка (Button1). Значения элементов массива вводятся из ячеек компонента stringGrid1. Во время сортировки, после выполнения очередного цикла обменов элементов массива, программа выводит массив в поле метки Label2. Листинг 5.10. Сортировка массива методом обмена procedure TForm1.Button1Click(Sender: TObject); const SIZE=5; var a:array[1..SIZE] of integer; k:integer; // текущий элемент массива i:integer; // индекс для ввода и вывода массива changed:boolean; // TRUE, если в текущем цикле были обмены buf:integer; // буфер для обмена элементами массива begin // ввод массива for i:=1 to SIZE do a[i] := StrToInt(StringGrid1.Cells[i-1, 0] ); label2.caption:=''; // сортировка массива repeat Changed:=FALSE; // пусть в текущем цикле нет обменов for k:=l to SIZE-1 do if a[k] > a[k+l] then begin // обменяем k-й и k+1-й элементы buf := a[k]; a[k] := a[k+l]; a[k+l] := buf; changed := TRUE; end; // вывод массива for i:=l to SIZE do Label2.caption:=label2.caption+' '+IntTostr(a[i]); 74 Label2.caption:=label2.caption+#13; until not changed; // если не было обменов, значит // массив отсортирован Label2.caption:=label2.caption +#13+'Maccив отсортирован.'; end; Следует отметить, что максимальное необходимое количество циклов проверки соседних элементов массива равно количеству элементов массива минус один. Вместе с тем возможно, что массив реально будет упорядочен за меньшее число циклов. Например, последовательность чисел 5 1 2 3 4, если ее рассматривать как представление массива, будет упорядочена за один цикл, и выполнение оставшихся трех циклов не будет иметь смысла. Поэтому в программу введена логическая переменная changed, которой перед выполнением очередного цикла присваивается значение FALSE. Процесс сортировки (цикл repeat) завершается, если после выполнения очередного цикла проверки соседних элементов массива (цикл for) ни один элемент массива не был обменен с соседним, и, следовательно, массив уже упорядочен. Рис. 5.19. Пример работы программы сортировки массива методом обмена На рис. 5.19 приведено диалоговое окно программы сортировки массива методом обмена после завершения процесса сортировки. Задания для самостоятельной работы 1. Создайте одномерный массив, заполните его случайноым образом и отсортируйте по убыванию методом"пузырька". Форма должна содержать компоненты для отображения исходного и отсортированного массива, а также компонент для ввода количества элементов. 2. Задана целочисленная матрица А размером NxM, Получить массив B, присвоив его к-му элементу значения 0, если все элементы к-го столбца матрицы -нулевые, и значение в 1 противном случае (k=1,2,...,M). Лабораторная работа №8 Тема: Процедуры и функции 75 Цель: Сформировать практические навыки описания и применения подпрограмм Object Pascal для обработки данных; построение однооконных интерфейсов с помощью визуального компонента «окно» (класс TForm) и визуальных компонентов панели инструментов Standard: «метка» (класс TLabel), «однострочный редактор» (класс TEdit), «кнопка» (класс TButton), «многострочный редактор текста» (TMemo). ЗАДАНИЕ 1. В соответствии с вариантами задания и приведенной ниже спецификацией реализуйте приложение под Windows. 2. Разработайте тестовые задания, и оттестируйте программу одним из методов тестирования. Спецификация приложения 1. В соответствии с приведенными вариантами заданий реализуйте приложение под Windows, используя для организации пользовательского интерфейса следующие элементы управления: «форма» (класс TForm), «кнопка» (класс TButton), «метка» (класс TLabel), «однострочный редактор» (класс TEdit). Ввод данных и вывод результатов осуществляйте в элементы управления «однострочный редактор». Подписи к однострочным редакторам выполните с помощью элементов «метка». Вычисление результата свяжите с нажатием на элементе управления «кнопка» левой клавиши мыши. 2. Организуйте контроль содержимого строки, вводимой в элемент «однострочный редактор». Если вводимая строка не соответствует заданному формату, то необходимо предусмотреть следующее: в окне сообщений вывести сообщение об ошибке, очистить строку, введенную в «однострочный редактор». 3. Визуальный компонент, в который выводится результат, должен быть доступен только для чтения, чтобы пользователь не мог редактировать его содержимое. 4. Установите удобный для пользователя порядок перемещения фокуса по компонентам с помощью клавиши Tab. Рекомендации к выполнению 1. Для выполнения заданий используйте результаты предыдущих лабораторных работ. Для этого предварительно создайте новую папку, куда скопируйте все файлы подходящего приложения, после чего откройте его в Delphi и внесите необходимые изменения. 2. Описания разрабатываемых в работе подпрограмм помещайте в разделе реализации (раздел модуля, который начинается после зарезервированного слова implementation) модуля формы вашего приложения. Варианты заданий 1. Разработайте функцию, которая получает через параметры два вещественных значения и возвращает наименьшее из них. 2. Разработайте функцию, которая получает через параметры целое значение, соответствующее 16-ичной цифре, и возвращает символ, изображающий эту цифру. 76 3. Разработайте функцию, которая получает через параметры символ, изображающий 16-ичную цифру, и возвращает целое значение, соответствующее этой цифре. 4. Разработайте функцию, которая получает через параметры длины трех сторон треугольника a, b, c, вычисляет и возвращает в качестве своего результата его площадь s. Площадь треугольника вычисляйте по формуле Герона: s p *( p a) *( p b) *( p c); p (a b c) / 2. 5. Разработайте функцию, которая получает три вещественных параметра, возвращает в качестве своего результата булевское значение True, если полученные значения могут быть сторонами треугольника, False – в противном случае. 6. Разработайте функцию, которая получает три вещественных параметра R, r, l, вычисляет и возвращает в качестве своего результата площадь s усеченного конуса: s * (R r) * l * R2 * r 2. 7. Разработайте функцию, которая получает три вещественных параметра R, r, h, вычисляет и возвращает в качестве своего результата объем v усеченного конуса: v (1/ 3) * ( R 2 r 2 R * r ) * h. 8. Разработайте функцию, которая получает через параметры два вещественных значения x1, x2, вычисляет и возвращает в качестве своего результата вещественное значение y в соответствии со следующей формулой: y (e x1 e x2 ) / 2 9. Разработайте функцию, которая вычисляет и возвращает в качестве своего результата заданный разряд целого числа. Целое число и номер разряда функция получает через параметры. Разряды нумеруйте справа налево, начиная с единицы. Для решения используйте операции mod, div. 10. Разработайте функцию, которая вычисляет и возвращает в качестве своего результата значение заданного разряда дробной части вещественного числа. Вещественное число и номер разряда функция получает через параметры. Разряды нумеруйте от десятичной точки направо, начиная с единицы. Для решения используйте функции Int, Frac. 11. Выполните приведенные выше варианты заданий, описывая процесс обработки данных в форме процедуры Object Pascal. 12. Разработайте процедуру, которая получает через параметры две вещественные переменные x, y и обменивает переменные их значениями. Например, до вызова процедуры переменные имеют значения: x = 5, y = 8. После вызова процедуры переменные имеют значения: x = 8, y = 5. ПРИМЕР Пусть требуется написать функцию, которая получает через параметр (тип Char) литеру, определяет к какому из приведенных ниже подмножеств она принадлежит: 77 • латиница; • цифра; • кириллица; • другая; и возвращает строку (значение типа String), содержащую имя этого подмножества. Для решения этой задачи можно построить приложение, состоящее из одной формы следующего вида (рис. 7): Рис. 7 Ей соответствует модуль, текст которого приведен ниже. unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Edit1: TEdit; Edit2: TEdit; Label1: TLabel; Label2: TLabel; procedure Edit1KeyPress(Sender: TObject; var Key: Char); private {Private declarations} public {Public declarations} end; var Form1: TForm1; implementation {$R *.DFM} function Litera(Ch: Char):String;// Описание функции begin if ((Ch>='A') and (Ch<= 'Z')) or ((Ch>='a') and (Ch<= 'z')) then Litera:='Латиница' 78 else if ((Ch>='А') and (Ch<= 'Я')) or ((Ch>='а') and (Ch<= 'я')) then Litera:='Кириллица' else if ((Ch>='0') and (Ch<= '9')) then Litera:='Цифра' else Litera:='Другой' end; procedure Litera_(Ch: Char;var Res: String);// Описание процедуры begin if ((Ch>='A') and (Ch<= 'Z')) or ((Ch>='a') and (Ch<= 'z')) then Res:='Латиница' else if ((Ch>='А') and (Ch<= 'Я')) or ((Ch>='а') and (Ch<= 'я')) then Res:='Кириллица' else if ((Ch>='0') and (Ch<= '9')) then Res:='Цифра' else Res:='Другой' end; procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char); var s: String; begin Litera_(Key,s); //Вызов процедуры Edit2.Text:= s; //Edit2.Text:= Litera(Key); //Вызов функции Edit1.Clear end; end. СОДЕРЖАНИЕ ОТЧЕТА 1. Задание. 2. Текст программы на Object Pascal 2.0. 3. Тестовые наборы данных для тестирования приложения. КОНТРОЛЬНЫЕ ВОПРОСЫ 1. Назовите синтаксические правила, описания функции. 2. Назовите синтаксические правила, написания вызова функции. 3. Назовите синтаксические правила, описания процедуры. 4. Назовите синтаксические правила, написания оператора процедуры. 5. В чем отличие процедуры от функции? 6. Что такое локальные переменные подпрограммы? 7. Что такое глобальные переменные? 8. Что такое формальные параметры подпрограммы и для чего они предназначены? 9. Что такое фактические параметры подпрограммы и для чего они предназначены? 10. Как должны соотносится между собой фактические и формальные параметры подпрограммы при ее вызове? 79 11. Перечислите, какие виды формальных параметров используются в подпрограммах, укажите их назначение и особенности применения. Лабораторная работа №9 Тема: Графические возможности Delphi. Цель: Отработка практических навыков создания DELPHI-приложения с использованием компонентов TImage, TChart. Задание 1. Создать проект, позволяющий просматривать и редактировать рисунки, а также просматривать простейшие геометрические фигуры Примерный вид формы: MainMenu1 Image SavePictureDialo 1 g1 OpenPictureDialog 1 Shape ColorBox1 ComboBox1 Выполнение задания: 1. Разместите на форме указанные компоненты. 2. Установите следующие свойства компонентов Компонент Свойство Значение ComboBox1 Items квадрат круг Image1 AutoSuze true Stretch false 3. Создайте главное меню формы 4. Запрограммируйте выбор пункта меню открыть procedure TForm1.N2Click(Sender: TObject); 80 1 begin if OpenPictureDialog1.Execute then Image1.Picture.LoadFromFile(OpenPictureDialog1.FileName); end; 5. Запрограммируйте выбор пункта меню сохранить: procedure TForm1.N3Click(Sender: TObject); begin if SavePictureDialog1.Execute then Image1.Picture.SaveToFile(SavePictureDialog1.FileName); end; 6. Запрограммируйте выбор цвета для рисования с помощью компонента ColorBox1: procedure TForm1.ColorBox1Change(Sender: TObject); begin Image1.Canvas.Pen.Color:=ColorBox1.Selected; end; 7. Запрограммируйте установку графического указателя при нажатии клавиши мыши в пределах компонента Image1: procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin Image1.Canvas.MoveTo(X,Y); end; 8. Запрограммируйте рисование линии при нажатии левой клавиши мыши и ее перемещении по компоненту Image1: procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin if ssLeft in Shift then Image1.Canvas.LineTo(X,Y); end; 9. Запрограммируйте выбор простой геометрической фигуры с помощью компонента ComboBox1: procedure TForm1.ComboBox1Change(Sender: TObject); begin case ComboBox1.ItemIndex of 0: Shape1.Shape:=stSquare; 1: Shape1.Shape:=stCircle; end; end; 10. Сохраните проект и проверьте его работу. Задание для самостоятельной работы Доработайте проект следующим образом: 1) добавьте в список ComboBox1 новые пункты: прямоугольник и эллипс и предусмотрите возможность изображения этих фигур; 81 2) запрограммируйте закраску фигуры Shape1 цветом, выбранном в компоненте ColorBox1; 3) добавьте на форму две кнопки Button1 и Button2. При щелчке мышью по Button1 размеры компонента Shape1 увеличиваются вдвое, а при щелчке по Button2 – уменьшаются вдвое. Форма представления отчета: Отчет о выполненной самостоятельной работе должен содержать: 1) тему лабораторной работы; 2) условие задачи; 3) листинг программы; 4) результаты ее тестирования. Компонент Chart Компонент Chart позволяет строить графики, диаграммы различных видов. Компонент Chart расположен на палитре Additional. Круговая диаграмма 1. Создайте форму следующего вида 2. Label2 Label1 Edit1 Edit1 ColorDialog 1 StringGrid1 Button1 Chart1 2. Присвойте компонентам следующие значения Компонент Свойство Значение Label1 Caption Пролив Label2 Caption Длина Edit1 Text Edit2 Text Button1 Caption Ввод SrtingGrid1 ColCount 2 RowCount 10 FixedCols 0 3. Дважды щелкните по объекту Chart и в появившемся окне добавьте элемент Series (Add) и выберите тип Pie 82 4. Выделите объект Form1 в диспетчере объектов и перейдите на закладку Events в Object Inspector и дважды щелкните в поле справа от события OnCreate 5. Запрограммируйте событие создания формы. procedure TForm1.FormCreate(Sender: TObject); begin StringGrid1.Cells[0,0]:='Пролив'; StringGrid1.Cells[1,0]:='Длина'; Chart1.Title.Text.Clear; Chart1.Title.Text.Add('Диаграмма'); Series1.Clear; Series1.Marks.Visible:=false; end; 6. Запрограммируйте событие onClick для button1 procedure TForm1.Button1Click(Sender: TObject); var A,A1:integer; begin A:=Edit1.tag; inc(A); Edit1.tag:=A; StringGrid1.Cells[0,A]:=Edit1.Text; StringGrid1.Cells[1,A]:=Edit2.Text; A1:=StrToInt(Edit2.Text); if ColorDialog1.Execute then Series1.Add(A1,Edit1.text, ColorDialog1.Color) 83 else Series1.Add(A1,Edit1.text, clYellow); end; 7. Запустите программу на исполнение. Помните в поле Edit2 нужно вводить только числа Построение графиков функций 1. Создайте форму следующего вида CheckBox1 Button1 Chart1 2. Присвойте компонентам следующие значения Компонент Свойство CheckBox1 Caption 3D Значение 3. Дважды щелкните по объекту Chart и в появившемся окне добавьте элемент Series (Add) и выберите тип Line 4. Запрограммируйте событие onClick для button1 procedure TForm1.Button1Click(Sender: TObject); var i:integer; begin Series1.Clear; Chart1.View3D:=false; Series1.Title:='Sin'; for i := 0 to 100 do 84 begin Series1.AddXY(0.02 * Pi * i, sin(0.02 * Pi * i), '', clRed); end; end; Задания для самостоятельной работы 1. Добавьте еще один элемент Series и постройте график функции Sin, программа должна выглядеть так 2. Настройте вывод графиков в зависимости от выключателя 3D в двухмерном или трехмерном варианте. Изменения должны также происходить и при включении и выключении 3D/ Форма представления отчета: Отчет о выполненной самостоятельной работе должен содержать: 1) тему лабораторной работы; 2) условие задачи; 3) листинг программы; 4) результаты ее тестирования. Построение графиков функций в декартовых координатах Пример 1. Создать в среде DELPHI проект, позволяющий построить график функции у = х2 - 2, x[-10 ; 10]. Для перехода от естественных координат к экранным воспользуемся формулами: х1 = Ox + Мx*х. у1 = Oy - Мy*у , где х , у - естественные координаты, х1 , у1 - экранные координаты, (Ox, Oy) – экранная точка, выбранная в качестве начала координат, Mx , My масштаб, т.е. длина единичных отрезков в пикселях. Разработка проекта: 1. Разместить на форме компоненты PaintBox1, Label1, Label2, Edit1, Edit2, Button1, Button2 следующим образом: 85 Label 1 Edit1 Label 2 Edit2 PaintBox1 Button 1 Button 2 2. Создать процедуру для построения графика функции (двойной щелчок мышкой по Button1) procedure TForm1.Button1Click(Sender: TObject); var x1, y1, ox, oy, mx, my, i : integer; x, y: real; begin paintbox1.Canvas.Pen.Color:=clblue; {устанавливаем синий цвет пера} ox:=paintbox1.Width div 2; {начало координат размещаем в центре oy:=paintbox1.Height div 2; компонента paintbox1} mx:=StrToInt(Edit1.Text); {масштаб по оси x} my:=StrToInt(Edit2.Text); {масштаб по оси x} paintbox1.Canvas.moveto(0, oy); {строим оси координат} paintbox1.Canvas.LineTo(640, oy); paintbox1.Canvas.moveto(ox, 0); paintbox1.Canvas.LineTo(ox, 480); for i:= -10 to 10 do begin {разметка оси ox} x1:=ox+mx*i; paintbox1.Canvas.moveto(trunc(x1), oy-5); paintbox1.Canvas.LineTo(trunc(x1), oy+5); end; for i:= -10 to 10 do begin { разметка оси oy } y1:=oy-my*i; paintbox1.Canvas.moveto(ox-5, trunc(y1)); paintbox1.Canvas.LineTo(ox+5, trunc(y1)); 86 end; paintbox1.Canvas.Pen.Color:=clred; {устанавливаем красный цвет пера} x:= -10; y:=sqr(x)-2; {вычисляем координаты начальной точки графика} x1:= trunc(ox+mx*x); y1:= trunc(oy-my*y); {перевод в экранные координаты} paintbox1.Canvas.moveto(x1, y1); {перемещаем перо в эту точку} while x<=10 do { построение графика функции} begin y:=sqr(x)-2; x1:= trunc(ox+mx*x); y1:= trunc(oy-my*y); paintbox1.Canvas.LineTo(x1, y1); x:=x+0.1; end; end; 3. Создать процедуру для очистки изображения графика (двойной щелчок мышкой по Button2) procedure TForm1.Button2Click(Sender: TObject); begin paintbox1.Canvas.Pen.Color:=clblack; paintbox1.Canvas.Brush.Color:=clwhite; paintbox1.Canvas.Rectangle(0,0,paintbox1.Width,paintbox1.Height); end; 4. Запустить проект на исполнение и проверить его работу, задавая различный масштаб. Задание для самостоятельной работы Доработать данный проект следующим образом: а) разместить на форме компонент RadioGroup , позволяющий выбирать для построения графика одну из функций у = х2 – 2, y=sin x, y = sin(ex). y= ecos x ; б) разместить на форме кнопку Выход, при щелчке по которой проект завершает работу. Форма представления отчета: Отчет о выполненной самостоятельной работе должен содержать: 1) тему лабораторной работы; 2) условие задачи; 3) листинг программы; 4) результаты ее тестирования. Лабораторная работа №10 Тема: Мультимедиа возможности Delphi. 87 Цель: Отработка практических навыков создания DELPHI-приложения с использованием компонентов TImage, TChart, TMediaPlayer. Средства создания мультимедийных приложений Delphi позволяет легко и просто включать в программу такие мультимедийные объекты, как звуки, видео и музыку. В данной работе рассмотрим, как это сделать, используя встроенный в Delphi компонент TMediaPlayer. Что такое мультимедиа? Точного определения, что же это такое, нет. Но в данный момент и в данном месте, наверное, лучше дать по-возможности наиболее общее определение и сказать, что “мультимедиа” - это термин относящийся к почти всем формам анимации, звукам, видео, которые используются на компьютере. Давая такое общее определение, можно сказать, что мы имеем дело с подмножеством мультимедиа, которое включает: 1. Показ видео в формате Microsoft's Video for Windows (AVI). 2. Воспроизведение звуков и музыки из MIDI и WAVE файлов. Данную задачу можно выполнить с помощью динамической библиотеки Microsoft Multimedia Extensions для Windows (MMSYSTEM.DLL), методы которой инкапсулированы в компоненте TMediaPlay, находящейся на странице System Палитры Компонент Delphi. Для проигрывания файлов мультимедиа может потребоваться наличие некоторого оборудования и программного обеспечения. Так для воспроизведения звуков нужна звуковая карта. Для воспроизведения AVI в Windows требуется установить ПО Microsoft Video. Мультимедиа в Delphi В Delphi есть компонент TMediaPlayer, который дает Вам доступ ко всем основным возможностям программирования мультимедиа. Данный компонент очень прост в использовании. Простоту использования можно воспринимать двояко: С одной стороны - это дает возможность любому создавать мультимедиа приложения. С другой стороны, можно обнаружить, что в компоненте реализованы не все возможности. Если Вы захотите использовать низкоуровневые функции, то придется копаться достаточно глубоко, используя язык Delphi. Компонент TMediaPlayer Для начала создайте новый проект, затем поместите компонент TMediaPlayer (стр. System Палитры) на форму, как показано на рис.1. Рис.1: Компонент TMediaPlayer на форме. 88 Компонент TMediaPlayer оформлен, как панель управления устройством с кнопками. Как и на магнитофоне, здесь есть кнопки “воспроизведение”, “перемотка”, “запись” и др. Поместив компонент на форму, Вы увидите, что Инспектор Объектов содержит свойство "FileName" (см. рис.2). Щелкните дважды Рис.2: Свойства TMediaPlayer в Инспекторе Объектов на этом свойстве и выберите имя файла с расширением AVI, WAV или MIDI. На рис.2 выбран AVI файл DELPHI.AVI. Далее нужно установить свойство AutoOpen в True. После выполнения этих шагов программа готова к запуску. Запустив программу, нажмите зеленую кнопку “воспроизведение” (крайняя слева) и Вы увидите видеоролик (если выбрали AVI) или услышите звук (если выбрали WAV или MID). Если этого не произошло или появилось сообщение об ошибке, то возможны два варианта: 1. Вы ввели неправильное имя файла. 2. Вы не настроили правильным образом мультимедиа в Windows. Это означает, что либо у Вас нет соответствующего ”железа”, либо не установлены нужные драйверы. Установка и настройка драйверов производится в Control Panel, требования к “железу” приводятся в любой книге по мультимедиа (нужна звуковая карта, например совместимая с Sound Blaster). Итак, Вы имеете возможность проигрывать AVI, MIDI и WAVE файлы просто указывая имя файла. Еще одно важное свойство компонента TMediaPlayer - Display. Изначально оно не заполнено и видео воспроизводится в отдельном окошке. Однако, в качестве экрана для показа ролика можно использовать, например, панель. На форму нужно поместить компонент Tpanel (находится в палитре SYSTEM), убрать текст из св-ва Caption. Далее, для TMediaPlayer, в свойстве Display выбрать из списка Panel1. После этого надо запустить программу и нажать кнопку “воспроизведение” (см. рис.3) 89 Рис.3. Воспроизведение AVI на панели. Два вида программ мультимедиа Иногда приходится предоставлять пользователям простой путь для проигрывания максимально широкого круга файлов. Это означает, что Вам нужно будет дать пользователю доступ к жесткому диску или CD-ROM, и затем позволить ему выбрать и воспроизвести подходящий файл. В этом случае, на форме обычно располагается TMediaPlayer, предоставляющий возможность управления воспроизведением. Иногда программист может захотеть скрыть от пользователя существование компонента TMediaPlayer. То есть, воспроизвести звук или видео без того, чтобы пользователь заботился об их источнике. В частности, звук может быть частью презентации. Например, показ какого-нибудь графика на экране может сопровождаться объяснением, записанным в WAV файл. В течении презентации пользователь даже не знает о существовании TMediaPlayer. Он работает в фоновом режиме. Для этого компонент делается невидимым (Visible = False) и управляется программно. Пример программы с мультимедиа Рассмотрим пример построения приложения с мультимедиа первого типа. Создайте новый проект (File | New Project). Поместите TMediaPlayer на форму; поместите компоненты TFileListBox, TDirectoryListBox, TDriveComboBox, TfilterComboBox (находятся на палитре Win3.1)для выбора файла. В свойстве FileList для DirectoryListBox1 и FilterComboBox1 поставьте FileListBox1. В св-ве DirList для DriveComboBox1 поставьте DirectoryListBox1. В св-ве Filter для FilterComboBox1 укажите требуемые расширения файлов: AVI File(*.avi)|*.avi WAVE File(*.wav)|*.wav MIDI file(*.MID)|*.mid Пусть по двойному щелчку мышкой в FileListBox1 выбранный файл будет воспроизводиться. В обработчике события OnDblClick для FileListBox1 укажите Procedure TForm1.FileListBox1DblClick(Sender:TObject); begin 90 with MediaPlayer1 do begin Close; FileName:=FileListBox1.FileName; Open; Play; end; end; Внешний вид формы представлен на рис.4 Рис.4: Начальный вид проекта Сохраните проект, запустите его, выберите нужный файл и дважды щелкните на него мышкой. MediaPlayer должен воспроизвести этот файл в отдельном окне. Как уже говорилось выше, видеоролик можно воспроизводить внутри формы, например, на панели. Давайте слегка модифицируем проект и добавим туда панель TPanel (см. рис.5). В св-ве Display для MediaPlayer1 укажите Panel1. Нужно убрать надпись с панели (Caption) и св-во BevelOuter = bvNone. Чтобы переключаться при воспроизведении с окна на панель поместите TСheckBox на форму и в обработчике события OnClick для него запишите: procedure TForm1.CheckBox1Click(Sender: TObject); var Start_From : Longint; begin with MediaPlayer1 do begin if FileName='' then Exit; Start_From:=Position; Close; Panel1.Refresh; if CheckBox1.Checked then Display:=Panel1 else Display:=NIL; Open; 91 Position:=Start_From; Play; end; end; Запустите проект и воспроизведите видеоролик. Пощелкайте мышкой на CheckBox. Рис.5: Добавлена панель для воспроизведения видео и переключатель окно/панель. Во время выполнения программы может потребоваться отобразить текущее состояние объекта MediaPlayer и самого ролика (время, прошедшее с начала воспроизведения, длину ролика). Для этого у объекта TMediaPlayer есть соответствующие свойства и события: Length, Position, OnNotify и др. Давайте добавим в проект прогресс-индикатор (TGauge), который отобразит в процентах, сколько прошло времени (см. рис.6). Для обновления показаний индикатора можно воспользоваться таймером. Поместите на форму объект Ttimer (панель SYSTEM), установите для него Interval = 100 (100 миллисекунд). В обработчике события OnTimer нужно записать: procedure TForm1.Timer1Timer(Sender: TObject); begin with MediaPlayer1 do if FileName<>'' then Gauge1.Progress:=Round(100*Position/Length); end; Запустите проект, выберите файл (AVI) и щелкните на нем два раза мышкой. При воспроизведении ролика прогресс-индикатор должен отображать процент, соответствующий прошедшему времени (см. рис.6). 92 Рис.6: Законченное приложение для воспроизведения AVI, WAV и MDI файлов. Задание для самостоятельного выполнения: 1. Используя компоненты для работы с мультимедиа создать программу, позволяющую выбирать и просматривать видеоизображения 4. САМОСТОЯТЕЛЬНАЯ РАБОТА СТУДЕНТА СРСП № 1 Тема: Теоретические основы ООП. Цель: знать основные определения и понятия На протяжении всех лет своего существования практика программирования требовала совершенствования технологических приемов и создания на их основе таких средств программирования, которые упростили бы процесс разработки программ, позволяя создавать все более сложные программные системы. Первые программы были организованы очень просто. Они состояли из собственно программы на машинном языке и обрабатываемых данных. Сложность программ ограничивалась способностью программиста одновременно мысленно отслеживать последовательность выполняемых операций и местонахождение большого количества данных. Появление сначала ассемблеров, а затем и языков высокого уровня сделало программу более обозримой за счет снижения уровня детализации и естественно позволило увеличить ее сложность. Существенно снизило трудоемкость разработки программ появление в языках средств, позволяющих оперировать подпрограммами. Подпрограммы можно было сохранять и использовать в других программах. В результате были накоплены огромные библиотеки расчетных и служебных подпрограмм, которые по мере надобности вызывались из разрабатываемой программы. Типичная программа того времени состояла из основной программы, области глобальных данных и набора подпрограмм (в основном библиотечных), выполняющих обработку всех данных или их части (рис. 1.1). Рис. 0.1. Архитектура программы, использующей глобальную область данных 93 Слабым местом такой архитектуры было то, что при увеличении количества подпрограмм возрастала вероятность искажения части глобальных данных какой-либо подпрограммой. Например, обычно подпрограмма поиска корней уравнения на заданном интервале по методу деления отрезка пополам меняет величину интервала. Если при выходе из подпрограммы не предусмотреть восстановления первоначального интервала, то в глобальной области окажется неверное значение интервала, полученное при последнем делении отрезка в ходе работы подпрограммы. Необходимость исключения таких ошибок привела к идее использования в подпрограммах локальных данных (рис. 1.2). Рис. 0.2. Архитектура программы, использующей подпрограммы с локальными данными. И вновь сложность разрабатываемого программного обеспечения стала ограничиваться возможностью программиста отслеживать процессы обработки данных уже на новом уровне. К этому добавились проблемы согласования интерфейса при ведении разработки несколькими программистами. В результате встал вопрос создания технологии разработки сложных программных продуктов, снижающей вероятность появления ошибок. Усилиями многих авторов такая технология была создана и получила название «структурное программирование». Структурное программирование представляет собой совокупность рекомендуемых технологических приемов, охватывающих выполнение всех этапов разработки программного обеспечения. Были сформулированы основные принципы выполнения разработки: 1) принцип нисходящей разработки, рекомендующий на всех этапах вначале определять наиболее общие моменты, а затем поэтапно выполнять детализацию (что позволяет последовательно концентрировать внимание на небольших фрагментах разработки); 2) собственно структурное программирование, рекомендующее определенные структуры алгоритмов и стиль программирования (чем нагляднее текст программы, тем меньше вероятность ошибки); 3) принцип сквозного структурного контроля, предполагающий проведение содержательного контроля всех этапов разработки (чем раньше обнаружена ошибка, тем проще ее исправить). 94 В основе структурного программирования лежит декомпозиция (разбиение на части) сложных систем с целью последующей реализации в виде отдельных небольших (до 40-50 операторов) подпрограмм. В отличие от используемого ранее интуитивного подхода к декомпозиции, структурный подход требовал представления задачи в виде иерархии подзадач простейшей структуры, для получения которой рекомендовалось применять метод пошаговой детализации. С появлением других принципов декомпозиции (объектного, логического и т.д.) данный способ получил название процедурной декомпозиции. Метод пошаговой детализации заключается в следующем: 1) определяется общая структура программы в виде одного из трех вариантов (рис 1.3): 1. последовательности подзадач (например, ввод данных, преобразование данных, вывод данных); 2. альтернативы подзадач (например, добавление записей к файлу или их поиск); 3. повторения подзадачи (например, циклически повторяемая обработка данных). Рис. 0.3. Основные структуры процедурной декомпозиции 2) каждая подзадача, в свою очередь, разбивается на подзадачи с использованием тех же структур. 3) процесс продолжается, пока на очередном уровне не получается простейшая подзадача, которая достаточно просто реализуется средствами используемого языка (1-2 управляющих оператора языка). Контрольные вопросы 1. Что представляет собой структурное программирование? 2. Сформулируйте основные принципы выполнения разработки. 3. В чем заключается метод пошаговой детализации? СРСП № 2 Тема: Абстракция данных, объект. Инкапсуляция. Цель: знать основные определения и понятия История становления программирования богата какими-либо нововведениями, которые коренным образом меняют всю предшествующую систему. Одним из первых и наиболее ярких таких открытий можно считать выход в свет книги «Программирование без GOTO». Следующим наиболее важным шагом по праву считают переход к процедурно-функциональному 95 программированию, когда программы разбивались на ряд независимых блоков, и в итоге просто грамотно соединялись в единое целое. Ну и третьим, наверное, самым большим открытием можно считать появление объектноориентированного программирования. ООП объединило в себе одновременно процедурные методы, для чего создавались самостоятельные модули, структурное проектирование и стимулировало творческий подход к созданию программ. Сегодня ни одна программа не представляется без наличия в ней объектов. Объектно-ориентированное программирование вышло на новую ступень своего развития, когда внедрить объект в программу не составляет большого труда, а порой, это за вас сделает визуальная среда. Таким образом, такой мощный инструмент, как объект стал доступным даже для начинающего программиста. Теперь любой программист может использовать всю мощь и эффективность объектно-ориентированного программирования. Неформально можно сказать, что объектно-ориентированное программирование стоит на трёх китах, таких как инкапсуляция, полиморфизм и наследование. Объектно-ориентированное проектирование — это методология программирования, основанная на представлении программы в виде совокупности объектов, каждый из которых является экземпляром определенного класса, а классы образуют иерархию наследования. Для ООП существует важное значение такое понятие, как абстрагирование. Абстракция выделяет существенные характеристики некоторого объекта, отличающие его от всех других видов объектов и, таким образом, четко определяет его концептуальные границы с точки зрения наблюдателя. Для удобного представления программы используются модульность и иерархия. Модульность — это разделение программы на фрагменты, которые компилируются по отдельности, но могут устанавливать связи с другими модулями. Иерархия — это упорядочение абстракций, разложение их по уровням. Сохраняемость — способность объекта существовать во времени, переживая породивший его процесс, и (или) в пространстве, перемещаясь из своего первоначального адресного пространства. Говоря другими словами, сохраняемость — это способность классов использоваться не только в одной программе или части программы. Контрольные вопросы 1. Дайте определение абстракций 2. Дайте определение модульности 3. Дайте определение иерархий 4. Дайте определение сохраняемости СРСП № 3 96 Тема: Иерархия классов, наследование, полиморфизм. Цель: знать иерархию классов, основные определения и понятия Все классы Object Pascal порождены от единственного родителя - класса TObject. Этот класс не имеет полей и свойств, но включает в себе методы самого общего назначения, обеспечивающие весь жизненный цикл любых объектов - от их создания до уничтожения. Новый класс можно создать на основе этого базового класса. Принцип наследования приводит к созданию дерева классов, постепенно разрастающегося при перемещении от TObject к его потомкам. Каждый потомок дополняет возможности своего родителя новыми свойствами и передает их своим потомкам. В состав Delphi входят более 300 различных классов. Для примера приведем небольшой фрагмент дерева классов Delphi: Рис.1. Фрагмент дерева классов Delphi Класс TPersistent обогащает возможности своего родителя TObject; он умеет сохранять данные в файле и получать данные из него. Класс TComponent умеет взаимодействовать со средой разработчика и передает это умение своим потомкам. Класс TComponent является базовым для создания не визуальных компонентов. TControl не только способен работать с файлами и средой разработчика, но он уже умеет создавать и обслуживать видимые на экране изображения. Класс TControl является базовым для создания визуальных компонентов. Потомок этого класса TWinControl может создавать Windows-окна т.д. Контрольные вопросы 1. От какого класса порождены все классы Object Pascal? 97 2. К чему приводит принцип наследования? СРСП № 4 Тема: Полиморфный объект. Цель: знать понятие полиморфыного объекта Если в качестве параметра можно передавать любой тип из типов, порождаемых типом параметра, то как тот, кто использует этот параметр, определяет какой тип объекта получен. Фактически пользователь не знает этого явно. Точный тип фактического параметра неизвестен во время компиляции. Он может быть любым типом объекта, порожденным от типа параметра var и поэтому называется полиморфным объектом. В чем же преимущество полиморфных объектов? Самое главное в том, что полиморфные объекты допускают обработку объектов, тип которых неизвестен во время компиляции. Предположим, что Вы написали пакет графических чертежных средств, который поддерживает различные типы фигур, точки, окружности, квадраты, прямоугольники, кривые и т.п. Может возникнуть необходимость написать в качестве части этого пакета подпрограмму, которая будет изображать графическую фигуру на экране с помощью указателя "мышь". Старый способ заключается в написании отдельных процедур для изображения графических фигур всех типов, поддерживаемых пакетом. Нужно написать процедуры DragCircle, DragSquare, DragRectangle и т.д. Даже если строгое типирование Паскаля разрешает это (и не забывайте, что всегда есть способы обойти строгое типирование) различие между типами графических фигур будет, по-видимому, препятствовать написанию общей подпрограммы изображения этих фигур. Кроме того, окружность не имеет сторон, квадрат имеет одну длину стороны, прямоугольник - две различные длины сторон и т.д. В этом случае искусные программисты на Turbo Pascal идут дальше и выполняют вышеописанную задачу следующим образом: передают запись графической фигуры процедуре DragIt как содержимое общего указателя. Внутри DragIt просматривают поле признака при фиксированном смещении внутри записи графической фигуры, чтобы определить какой тип имеет данная фигура и затем осуществляют вставку с помощью предложения case: case FigureIdTage of Point: DragPoint; Circle: DragCircle; Square: DragSquare; Rectangle: DragRectangle; Curve: DragCurve; 98 Конечно, включение семнадцати небольших кусков программы внутрь одного куска является небольшим шагом вперед, но при этом остается нерешенной следующая проблема: что делать, если пользователь пакета определит несколько новых графических фигур, например, пользователь разрабатывает дорожные знаки и хочет работать с восьмиугольником для знака остановки. Пакет не имеет типа Octagon (восьмиугольник), поэтому DragIt не имеет метку этого типа в предложении case и, следовательно, откажется нарисовать новую восьмиугольную фигуру. Если эту запись передать DragIt, то фигура типа Octagon должна попасть в часть else предложения case как нераспознанная фигура. Очевидно, что построение программ пакета для продажи без исходного кода страдает из-за следующей проблемы: пакет может работать только типами данных, которые он "знает", т.е. с типами, которые были определены разработчиками пакета. Пользователь пакета не может расширить функции пакета в направлениях, не использованных разработчиками пакета. Что пользователь покупает, то он и получает. Выход состоит в использовании для объектов правил расширенной совместимости типов Turbo Pascal и проектировании прикладной задачи с использованием полиморфных объектов и виртуальных методов. Если процедура пакета DragIt написана так, чтобы она могла работать с полиморфными объектами, то она будет работать с любыми объектами, определенными внутри пакета - и с любыми порожденными объектами, которые Вы определили сами. Если типы объектов пакета используют виртуальные методы, то объекты и подпрограммы пакета могут работать с обычными графическими фигурами в собственных терминах этой фигуры. Виртуальный метод, который Вы определите сейчас, может вызываться файлом модуля .TPU пакета, который был написан и откомпилирован годом позже. Объектно-ориентированное программирование делает это возможным, а виртуальные методы являются ключом к решению этой проблемы. Понимание того, как виртуальные методы делают такие вызовы полиморфных методов возможными, требует знания некоторых основ, касающихся объявления и использования виртуальных методов. Контрольные вопросы 1. Какой тип объекта называется полиморфным? 2. В чем же преимущество полиморфных объектов? СРСП № 5 Тема: Параметризованные классы. Цель: знать предназначение параметризованного класса Шаблон (template) или параметризованный класс (parametrized class) предназначен для обозначения такого класса, который имеет один (или 99 более) нефиксированный формальный параметр. Он определяет целое семейство или множество классов, каждый из которых может быть получен связыванием этих параметров с действительными значениями. Обычно параметрами шаблонов служат типы атрибутов классов, такие как целые числа, перечисление, массив строк и др. В более сложном случае формальные параметры могут представлять и операции класса. Графически шаблон изображается прямоугольником, к верхнему правому углу которого присоединен маленький прямоугольник из пунктирных линий (рис. 1), большой прямоугольник может быть разделен на секции, аналогично обозначению для класса. В верхнем прямоугольнике указывается список формальных параметров для тех классов, которые могут быть получены на основе данного шаблона. В верхней секции шаблона записывается его имя по правилам записи имен для классов. Рис. 1. Графическое изображение шаблона на диаграмме классов Шаблон не может быть непосредственно использован в качестве класса, поскольку содержит неопределенные параметры. Чаще всего в качестве шаблона выступает некоторый суперкласс, параметры которого уточняются в его классах-потомках. Очевидно, в этом случае между ними существует отношение зависимости с ключевым словом "bind", когда классклиент может использовать некоторый шаблон для своей последующей параметризации. В более частном случае между шаблоном и формируемым от него классом имеет место отношение обобщения с наследованием свойств шаблона (рис. 2). В данном примере отмечен тот факт, что класс "Адрес" может быть получен из шаблона Связный_список на основе актуализации формальных параметров "S, k, l" фактическими атрибутами "улица, дом, квартира". Этот же шаблон может использоваться для задания (инстанцирования) другого класса, скажем, класса "Точки_на_плоскости". В этом случае класс "Точки_на_плоскости" актуализирует те же формальные параметры, но с другими значениями, например, <координаты_точки, х, у>. Концепция шаблонов является достаточно мощным средством в ООП, и поэтому ее использование в языке UML позволяет не только сократить размеры диаграмм, но и наиболее корректно управлять наследованием свойств и поведения отдельных элементов модели. 100 Рис.2. Пример использования шаблона на диаграмме классов Контрольные вопросы 1. Для чего пердназначен параметризированный класс? 2. Что чаще всего выступает в качестве шаблона? 3. Что позволяет использование концепция шаблонов в языке UML? СРСП № 6 Тема: Реализация ООП в языке программирования Цель: знать основные понятия Язык Pascal был создан задолго до того, как выяснилось, что ООП становится de facto стандарной концепцией разработки программного обеспечения. Соответственно, появившиеся реализации ООП подхода на Pascal'е несут в себе отпечаток дообъектного прошлого этого языка. Лидер разработок компиляторов паскаля в Borland Андрес Хейлсберг (Andres Heilsberg) решил ввести элементы ООП лишь в версию (5.5), а следующие версии сделать полностью ООП-ориентированными. К сожалению, полностью это так и не удалось. Синтаксис Для того, чтобы объявить класс на Pascal'е необходимо воспользоваться ключевым словом Object. Так как класс всегда является типом, делать это можно лишь в Type части программы: Type Class1 = Object {список полей} A: Byte; V: Real; {список методов} Procedure Nothing(Var K: Byte); End; Легко заметить, что поля и методы (общее для них название - члены класса) объявляются очень похоже на поля записи и обычные процедуры/функции. Объекты класса объявляются так же, как и обычные переменные: Var Object1, Object2: Class1; 101 Соотвенно, доступ к полям объекта некоторого класса производится аналогично доступу к полям записи: Object1.V:= Object2.A; Обращение к методам класса производится аналогичным образом: Object1.Nothing(Object1.A); Наследование Pascal не поддерживает множественного наследования, то есть каждый класс может иметь не более одного наследника. Для того, чтобы объявить класс наследником какого-то другого класса достаточно указать имя классапредка при объявлении наследника: Type Class2 = Object(Class1) M: Integer; End; Var Object3: Class2; При таком объявлении объект Object3 обладает тремя полями - A, V, M - и одним методом - Nothing(Var Byte). Методы Методы объектов обладают единственным отличием от обычных процедур/функций: они, собственно, принадлежат объектам. Следовательно, они обладают доступом к полям именно "своему" объекту. Так как объектов в программе может быть множество, то, во избежание дублирования кода, каждый метод получает в качестве неявного параметра указатель на объект, для которого он вызван. Данный указатель доступен в теле метода как @Self. Естественно, что объявленный (декларированный) при определении класса метод должен быть определен (дефинирован) в программе. Известно, что все методы класса делятся на обычные (статические) и виртуальные. Любой метод считается статическим, если не указано обратное. Указать же, что метод является виртуальным можно, указав после его декларации в дефиниции класса ключевое слово Virtual: Type Class3 = Object Procedure Nothing(Var K: Byte); Virtual; End; Это ключевое слово должно быть указано для всех методов, для которых необходимо применять механизм позднего связывания. Порядок чередования виртуальных и невиртуальных методов в дефиниции класса не регламентируется. Конструкторы и деструкторы Среди всех методов класса выделяют две особых группы, имеющих особое значение при создании и удалении объектов этого класса: кконструкторы; ддеструкторы. Конструкторы предназначены для инициализации полей объектов в момент их создания. Объявляются они следующим образом: 102 Type Class4 = Object B: Byte; Constructor Init(CB: Byte); Destructor Done; Virtual; End; Constructor Class3.Init(CB: Byte); Begin B:= VB; End; Destructor Class3.Done; Begin End; Заметим, что в вышеприведенном примере определен также и виртуальный деструктор. Назначение деструкторов обратно назначению конструкторов - выполнять некоторые действия при удалении объектов. Конструкторы, в отличие от деструкторов не могут быть виртуальными. Несмотря на то, что как конструктор, так и деструктор могут быть вызваны непосредственно, их специфическое назначение привело к появлению возможности вызова их параллельно с созданием/удалением объектов. Так как создание/удаление объектов в процессе выполнения программы на Pascal'е возможны только при использовании ДРП, то функции создания/удаления типизированных переменных имеют дополнительный синтаксис {...} Type PClass4 = ^Class4; Var P: PClass4; {...} Begin P:= New(PClass4, Init(4)); {...} Dispose(P, Done); End; Именно здесь мы впервые встретились с возможностью с помощью одной и той же переменной получить доступ к объектам различных классов. Действительно, в зависимости от хода алгоритма указателю P может быть присвоено значение адреса как объекта класса Class4, так и адреса объекта класса-наследника от Class4. Перекрытие методов Перекрыть метод предка в классе наследнике очень просто: продекларировать метод с тем же именем. Type Class5 = Object(Class1) Procedure Nothing; End; При этом если перекрывается метод виртуальный, то перекрывающий метод тоже обязан быть виртуальным и, кроме того, иметь тот же список параметров. Если требование объявлять перекрывающий метод виртуальным введено, вероятно, для того, чтобы программист не забывал о его 103 унаследованной виртуальности (компилятор вполне в состоянии самостоятельно определить, является ли перекрываемый метод витруальным), то второе - требование одинаковости списка параметров насущно необходимо: при вызове виртуального метода для любого объекта любого класса-наследника компилятор может генерировать код передачи одинакового списка параметров - ведь заранее неизвестен реальный тип объекта. Контрольные вопросы 1. Наследование 2. Для чего предназначены конструкторы? 3. Назначение деструкторов СРСП № 7 Тема: Создание проектов с использованием символов и строк Цель: знать основные функции для работы с символами и строками Сегодня мы с вами разберемся, как в Delphi можно работать со строками, мы рассмотрим ряд функций и процедур которые пришли к нам еще из самого Pascal. Некоторые из них есть только в Object Pascal . Ну что же приступим, для начала разберемся, как можно переводить строку в число и обратно. Для этого используются функции IntToStr – для перевода числа в строку и StrToInt – для перевода строки в число. Вот пример: var a,b:Integer; str:string; begin a:=5; b:=1; str:=IntToStr(a+b); ShowMessage(str); end; Ну а противоположную функцию можно смело использовать например если вы хотите преобразовать строку лежащую, например в компоненте TEdit . Вот пример: var a:Integer; begin a:=StrToInt(Edit1.Text)+StrToInt(Edit2.Text); Edit3.Text:=IntToStr(a); end; Следующая функция, которую мы рассмотрим, определяет длину строки. Это функция Length (str), где str это строка, которую мы должны измерить. 104 var a:Integer; str:string; begin str:='Hello World!'; a:=Length(str); end; В переменной а будет хранится число 12, именно столько символов, включая пробел содержит строка ‘ Hello World !'. Следующая процедура Delete ( str , index , count ) – она удаляет количество count символов начиная с index в строке str . Ловите пример var str:string; begin str:='Hello World!'; Delete(str,6,7); ShowMessage(str); end; На экран будет выведено слово Hello . Следующая функция Insert ( substr , str , index ) – эта функция вставляет подстроку substr в строку str , начиная с index . Например, давайте представим строку ‘ my girlfriend ' и давайте преобразуем ее в строку ‘ my best girlfriend '. var str,substr:string; begin str:='my girlfriend'; substr:='best '; Insert(substr,str,4); ShowMessage(str); end; Следующая функция с которой мы познакомимся соединяет строки. Это Concat ( s 1, s 2,…). Вот практический пример: var str1,str2,str3:string; begin str1:='MU'; str2:=' versus'; str3:=' Arsenal'; str1:=Concat(str1,str2,str3); ShowMessage(str1); end; В итоге в str 1 мы получили строку ‘ MU versus Arsenal '. Теперь давайте научимся копировать из строки определенное количество символов. Для этого используется функция Copy . Итак, Copy ( str 105 , index , count ) – нужно копировать количество символов count начиная с index из строки str . Пример : var str1,str2:string; begin str1:=' один два три '; str2:=Copy(str1,6,3); ShowMessage(str2); end; В итоге на экране появится строка два. Теперь познакомимся с функцией Pos (str1, str2) которая возвращает число, например: var str1,str2:string; i:Integer; begin str1:='Hello world'; str2:='world'; i:=Pos(str2,str1); end; После выполнения данного кода в переменной I будет хранится число 7. Именно с него начинается слово world в строке str1. PosEx по сути функция очень похожая на предыдущую. PosEx (substr, str, x) – тут все по сути почти также как и в предыдущей, только поиск начинается с x символов. Чтобы перевести вещественное число в строку надо использовать функцию FloatToStr , а если надо наоборот то StrToFloat . Но у этих двух функции есть аналоги – val b str . Сейчас на примерах мы рассмотрим как с ними работать. Var S: string; X: Extended; code: integer; Begin S:= ' 7 . 8 '; Val(S, X, code); End ; Результатом этого кода будет то, что в переменной x будет хранится число 7,8. Для чего нам нужен code ? Он выдает ноль если все в порядке или номер символа котолрый не является числом если произошла ошибка. Теперь обратный пример : Var S: string; X: integer; Begin 106 X:= 10 ; Str(X, S); End; После этого кода в переменной S будет хранится строковое значение ‘10'. Контрольные вопросы 1. Опишите предназначение каждой функций СРСП № 8 Тема: Событийно-управляемое программирование Цель: знать происхождение СУП В 1991 году корпорация Microsoft представила компьютерному миру VISUAL BASIC. Правильно надо говорить не просто язык программирования, а среда программирования VISUAL BASIC. Система программирования это объединение языка программирования с системными программными средствами, которые обеспечивают создание и выполнение программы на этом языке. Система программирования VISUAL BASIC позволяет, "отстранившись" от сложнейшей внутренней структуры Windows создавать в ней программы различной сложности. VISUAL BASIC - один из первых языков, поддерживающий событийно управляемое программирование (event-driven programming). Программирование традиционно ориентировалось на поэтапное описание конкретного процесса, поэтому программный код во многом напоминал кулинарный рецепт. (Пример) Повар все делает сам, и нельзя забыть о какойнибудь мелочи. С этим в кулинарии можно и смириться, хотя согласитесь, залить кипятком лапшу "Доширак" (приготовленную кем-то) если не вкуснее, так уж точно удобнее, а в некоторых случаях просто незаменимо. Но это в кулинарии, а уж при разработке современных компьютерных приложений всех "мелочей" не предусмотришь. Отсюда и вытекает смысл событийно-управляемого программирования. Вместо скрупулезного описания каждого шага Вы лишь указываете, как реагировать на различные события (действия пользователя): выбор команды, щелчок мыши на каком-то определенном месте, перемещение мыши. На одни события можно предусмотреть реакцию, другие - просто игнорировать. Вы создаете не одну большую программу, а приложения Windows, состоящие из набора взаимодействующих микропрограмм (процедур), управляемых пользователем. С помощью VISUAL BASIC такое приложение можно разработать достаточно быстро и без глубоких профессиональных познаний и навыков. Кроме того, в среде Вы пользуетесь уже созданными элементами управления, как инструментами. Программы на языке VISUAL BASIC пишутся по большей части для того, чтобы управлять этими элементами. Контрольные вопросы: 1. Что такое система программирования? 107 2. Расскажите про язык программирования VISUAL BASIC? СРСП № 9 Тема: Управление техническими средствами через API. Цель: знать как можно с помощью вызовов Windows API управлять объектами из VCL. Разработчики библиотеки визуальных компонент (VCL) Delphi очень серьезно поработали над ее проектированием и воплощением в реальность. Как показывает практика, стандартного набора объектов обычно достаточно для создания реальных приложений. И, что более существенно, им (разработчикам) удалось решить очень сложную задачу, стоящую перед создателями любой среды визуального программирования - скрыть от программиста сложность и трудоемкость программирования в Windows и, в то же время, не лишать его возможности доступа к тем богатым возможностям системы, которые предоставляет Windows API. Ниже рассмотрено несколько примеров, как с помощью вызовов Windows API можно управлять объектами из VCL. Стандартная страница Палитры Компонент Компоненты, расположенные на странице “Standard”, представляют из себя объектную оболочку для стандартных управляющих элементов Windows. Поэтому для них существуют ограничения, накладываемые самой системой. Например, 32Кб - максимальный размер текста в TMemo. Для добавления в меню картинки можно использовать функцию API Windows SetMenuItemBitmaps(), например, следующим образом: … implementation … var BMP1, BMP2 : TBitMap; … procedure TForm1.FormCreate(Sender: TObject); begin BMP1:=TBitMap.Create; BMP1.LoadFromFile('c:\images\uncheck.bmp'); BMP2:=TBitMap.Create; BMP2.LoadFromFile('c:\images\check.bmp'); SetMenuItemBitmaps(File1.Handle, 1, MF_BYPOSITION, BMP1.Handle, BMP2.Handle); end; procedure TForm1.FormDestroy(Sender: TObject); begin BMP1.Free; BMP2.Free; end; 108 File1 это объект класса TMenuItem - пункт меню “File”. Значения параметров при вызове функции можно посмотреть в справочнике по Windows API. При уничтожении меню освобождения связанных с ним картинок не происходит и их надо уничтожать вручную. Вторая картинка BMP2 отображается рядом с пунктом меню, когда он выбран (Checked=True). TMemo Компонент класса TMemo может содержать до 32К текста (для Windows 3.x) вследствие ограничения Windows. Определение позиции каретки в TMemo. Можно использовать сообщения Windows API EM_LINEFROMCHAR и EM_LINEINDEX для определения текущей позиции каретки. procedure TForm1.ShowPosition; var LineNum: longint; CharNum: longint; begin LineNum:= Memo1.Perform(EM_LINEFROMCHAR, Memo1.SelStart,0); CharNum:= Memo1.Perform(EM_LINEINDEX, LineNum, 0); Label1.Caption := 'Line : '+ IntToStr(LineNum+1); Label2.Caption := 'Position :' + IntToStr((Memo1.SelStart CharNum)+1); end; Метод Perform, определенный в классе TControl, посылает сообщение своему же объекту, то есть его использование имеет тот же эффект, что и вызов функции API SendMessage(): SendMessage(Memo1.Handle,EM_LINEFROMCHAR, Memo1.SelStart,0); Операция UnDo в TMemo. Отмена последнего редактирования (операция UnDo) в объекте класса TMemo выполняется так же с помощью сообщений, посылаемых в данный объект: procedure TForm1.UnDoClick(Sender: TObject); begin if Memo1.Perform(EM_CANUNDO, 0, 0)<>0 then Memo1.Perform(EM_UNDO, 0, 0); end; В справочнике по Windows API описаны сообщения, которые можно послать в объект TMemo для управления его поведением. Кроме вышеназванных, имеется еще несколько полезных: EM_EMPTYUNDOBUFFER Сбрасывает флажок UnDo EM_GETHANDLE Получает указатель на буфер с текстом EM_LINESCROLL Прокрутка текста в окне TMemo EM_SETHANDLE Установка указателя на буфер с текстом EM_SETTABSTOPS Устанавливает табуляцию в окне с текстом 109 TListBox, TComboBox Windows накладывает ограничение на количество элементов в списке этих управляющих элементов. В случае Windows 3.x это количество равно 5440, в Windows’95 - 32767. Как получить горизонтальную прокрутку (scrollbar) в ListBox? Так же как в случае с TMemo, здесь можно использовать сообщения. Например, сообщение может быть отослано в момент создания формы: procedure TForm1.FormCreate(Sender: TObject); begin ListBox1.Perform(LB_SETHORIZONTALEXTENT, 1000, Longint(0)); end; Второй параметр в вызове - ширина прокрутки в точках. Вставка графики в ListBox. У класса TListBox (и TComboBox тоже) есть свойство Style, определяющее порядок рисования объекта. По-умолчанию оно установлено в lbStandard и за внешний вид объекта отвечает Windows. Если установить это значение в lbOwnerDrawFixed или lbOwnerDrawVariable, то можно несколько разнообразить внешний вид объекта. Давайте построим для примера ListBox, отображающий названия файлов формата .BMP из какой-либо директории вместе с их картинками. Прежде всего, оказывается, что вовсе не нужно заполнять ListBox вручную именами файлов, для этого достаточно послать ему сообщение: procedure TForm1.Button1Click(Sender: TObject); var s : String; begin s:='c:\windows\*.bmp'#0; ListBox1.Perform(LB_DIR, DDL_READWRITE, Longint(@s[1])); end; Далее, как уже было сказано, свойство Style нужно установить в lbOwnerDrawFixed и создать обработчик события OnDrawItem: procedure TForm1.ListBox1DrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState); var Bitmap: TBitmap; Offset: Integer; BMPRect : TRect; begin with (Control as TListBox).Canvas do begin {очищаем прямоугольник} FillRect(Rect); 110 {считываем картинку} Bitmap:=TBitMap.Create; Bitmap.LoadFromFile ('c:\windows\'+ListBox1.Items[Index]); if Bitmap <> nil then begin {вычисляем квадрат для показа картинки} BMPRect:=Bounds(Rect.Left + 2, Rect.Top + 2, Rect.Bottom-Rect.Top-2, Rect.Bottom-Rect.Top-2); {рисуем картинку} StretchDraw(BMPRect, BitMap); Offset := Rect.Bottom-Rect.Top + 6; end; {выводим текст} TextOut(Rect.Left+Offset,Rect.Top, Listbox1.Items[Index]); {не забыть освободить!} Bitmap.Free; end; end; Чтобы картинки получились побольше, значение свойства ItemHeight можно увеличить. Есть около двух десятков сообщений, которые можно послать в объекты класса TListBox и TComboBox. Контрольные вопросы 1. Какие еще примеры можете привести СРСП № 10 Тема: Создание проектов с использованием табличных данных Цель: развитие навыков в создании проектов Компонент StringGrid находится на странице Additional палитры компонентов. Там находятся "дополнительные" компоненты. StringGrid - компонент для отображения различных данных в табличной форме. Как следует из названия, ячейки компонента StringGrid Delphi могут содержать данные, имеющие тип String, а также отображать графику. Таблица StringGrid состоит из выделенных серым FixedCols и FixedRows - зафиксированных ячеек-заголовков, и обычных, белых ячеек. Содержимое Fixed ячеек недоступно редактированию, и меняется только программно. За возможность редактирования обычных ячеек отвечает одно из значений свойства Options. Итак, компонент StringGrid имеет возможность адресации каждой отдельной ячейки по номеру столбца и строки. Содержимое ячейки (i, j), где где i - номер столбца, j - номер строки, имеет вид StringGrid1.Cells[i, j] и доступно как для чтения, так и для записи. Здесь, как и всегда, номера столбцов ( i ) и строк ( j ) отсчитываются от 0. Выделенная ячейка таблицы имеет 111 номер столбца: StringGrid1.Col номер строки: StringGrid1.Row поэтому содержимое выделенной ячейки будет адресоваться так: S:=StringGrid1.Cells[StringGrid1.Col, StringGrid1.Row]; Написание такой строки - утомительный процесс. Поэтому пользуйтесь оператором присоединения with: with StringGrid1 do S:=Cells[Col, Row]; А лучше сразу задать в свойстве Name имя покороче, например SG. За многие свойства компонента Delphi StringGrid отвечает свойство Options. В Инспекторе Объектов Options - это раскрывающийся список, представляющий собой элементы данного множества. Если значение элемента равно True, то он присутствует в множестве, если False - то нет. Контрольные вопросы 1. Предназначение StringGrid? 2. Из чего состоит таблица StringGrid? 3. Назначение свойства Options? СРСП № 11 Тема: Структура приложения Windows. Цель: знать структуру приложения Здесь будет рассмотрен процесс построения простейшего приложения для Windows, на примере которого покажем основные принципы и приемы построения такой программы. Эту программу можно использовать в дальнейшем как основу для написания своих собственных приложений. При написании любых программ для Windows необходим включаемый файл windows.h. В нем содержатся прототипы всех функций Windows, определены типы и структуры данных, глобальные переменные и константы. Как уже отмечалось выше, приложение Windows содержит, по крайней мере, два принципиально важных модуля: · Функция WinMain(); · Функция WndProc(). Функция WinMain Подобно функции main обычной программы на Си, функция WinMain обязана присутствовать в каждом приложении Windows. Функции WinMain передается управление в начальный момент загрузки приложения. Перечислим действия, выполняемые WinMain: · регистрация класса окна приложения и другие инициализации; 112 · создание главного окна приложения и, возможно, других, подчиненных окон; · запуск цикла обработки сообщений, помещаемых в очередь приложения; · завершение работы приложения при извлечении из очереди сообщения WM_QUIT. Шаблон функции WinMain выглядит так: int PASCAL WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow) HANDLE hInstance; // дескриптор текущей копии HANDLE hPrevInstance; // предыдущая копия LPSTR lpCmdLine; // указатель на командную строку int nCmdShow; // флаг “окно_открыто/окно_закрыто {} Функция WinMain имеет четыре параметра. Первый параметр – hInstance – является дескриптором копии приложения. Это число однозначно определяет каждую копию приложения, исполняемую под Windows. Можно одновременно выполнять несколько копий одного приложения, при этом каждой копии будет соответствовать уникальный индекс. Второй параметр – hPrevInstance – является дескриптором, определяющим копию данного приложения, которая была последней активной копией. Если параметр hPrevInstance равен нулю, других копий этого приложения не существует. Третий параметр – lpCmdLine – это дальний указатель на командную строку, оканчивающуюся нулем. Он позволяет приложению получать данные через командную строку. Четвертый параметр – nCmdShow – определяет, как приложение первоначально отображается на дисплее: пиктограммой (nCmdShow = SW_SHOWMINNOACTIVE) или в виде открытого окна (nCmdShow = SW_SHOWNORMAL). Работа с копиями приложения В Windows можно несколько раз запустить одну и ту же программу. Известно, что в выполняемом модуле программы код и данные разделены (расположены в разных сегментах). В Windows при вторичном запуске той же программы в оперативную память не загружается секция, содержащая код программы, а просто организуется второй сегмент данных, соответствующий второму запуску программы. С этим сегментом работает физически тот же код программы, что и первый. Такой механизм позволяет экономить оперативную память при запуске нескольких копий, но налагает дополнительные ограничения на код программы. Самым очевидным условием является то, что программа не должна модифицировать сама себя. В сегмент кода нельзя также записывать данные. 113 Для того, чтобы отличить одну копию данных от другой той же программы, каждой копии программы Windows ставит в соответствие уникальный дескриптор копии приложения (instance handle). Соответствующую целочисленную переменную hInstance Windows передает функции WinMain при вызове в качестве одного из обязательных параметров. Другим обязательным параметром является также целочисленный параметр hPrevInstance, который позволяет копии программы в процессе работы определить, первая она или нет. При запуске первой копии Windows присваивает hPrevInstance значение нуль. Дело в том, что первая копия программы в памяти играет особую роль. Поскольку многие создаваемые приложением ресурсы (например, классы окон) становятся доступными всем остальным приложениям, только первая копия программы должна создавать новые ресурсы. Все последующие копии могут воспользоваться уже созданными ресурсами, не создавая своих собственных. Если по логике программы запуск двух ее копий нежелателен или не допустим , то можно запретить запуск второй копии, поместив в функцию WinMain проверку: if (hPrevInstance) return NULL; Контрольные вопросы: 1. Какой файл необходим при написании любых программ для Windows? 2. Какие два важных модуля содержит приложение Windows? 3. Какие действия выполняет WinMain? СРСП № 12 Тема: Основные понятия и принципы программирования Цель: знать основные понятия и принципы визуальной системы Delphi – это система объектно-ориентированного визуального программирования. В основе Delphi лежит технология визуального проектирования и событийного программирования, суть которой заключается в том, что среда разработки берет на себя большую часть рутинной работы, оставляя программисту работу по конструированию диалоговых окон и функций обработки событий. Delphi использует язык Object Pascal в среде визуальной разработки. Приложения (прикладные программы) Delphi являются интерактивными системами, в которых для организации взаимодействия между пользователем и программой используются методы (подпрограммы), управляемые событиями. Основой объектно-ориентированного программирования является объект. Объект можно определить как совокупность данных (компонентов) и методов работы с ними. Объектно-ориентированная программа – это 114 совокупность объектов и способов их взаимодействия. Обмен информацией между объектами производится с помощью сообщений. Сообщения являются результатом появления событий. Событие – это отклик на внешнее воздействие. Суть программирования, управляемого событиями, состоит в отслеживании таких событий, которые требуют реакции приложения. Объектно-ориентированное программирование (ООП, OOP – Object Oriented Programming) позволяет решать сложные задачи с помощью объектов, необходимых для программирования в Windows. При работе с Delphi можно и не использовать концепции ООП, но использование элементов визуальной разработки автоматически ведёт к применению ООП. Объекты в Delphi – это элементы, из которых строится приложение: форма, рамка, кнопка, метка и др. Объектом является и включаемый визуальный компонент (например, кнопка) в том виде, как он представлен во время помещения его на форму и во время выполнения программы. Объекты изображаются на экране до выполнения самой программы. Поэтому программирование в Delphi – визуальное. Основным окном разрабатываемого приложения является форма. В процессе разработки приложения при размещении объекта на форме (например, кнопки) в визуальной среде основные параметры объекта (размер, положение на экране, цвет и пр.) сразу отображается в виде реального компонента на форме, а соответствующий ему код на языке Object Pascal автоматически записывается в исходный файл формы, который отображает объект в процессе выполнения программы. Не весь код программы, написанной для Delphi, находится в приложении Delphi. Небольшая его часть фактически является частью Windows. Например, коды для стандартных окон диалога и кнопок полностью получены от Windows. Delphi просто использует их, выполняя соответствующие вызовы из Windows DLL (Dynamic Linked Library). Схематично взаимосвязь программ с Delphi и Windows представлена на рис.1. Рисунок 1 115 Свойства – это атрибуты (основные характеристики), которые описывают особенности объекта; например, отображают такие характеристики, как цвет, высота, ширина и положение объекта. На внешний вид объекта можно воздействовать (изменять его) во время разработки и выполнения приложения, изменяя его свойства. Практически все объекты реагируют на определённые события от мыши и клавиатуры. Приложения Windows используют методы (подпрограммы) обработки событий для управления взаимодействием между программой и пользователем и для реакции на действия ОС. Программный код, который пишет программист в Delphi, будет обеспечивать реакцию на события. Подпрограмма, которая реагирует на событие, называется обработчиком события. Delphi работает с событиями путём вызова определённых процедур – обработчиков событий. Если процедура не связана с данным событием, то оно игнорируется и выполняется стандартная реакция системы или не производится никакого действия. Контрольные вопросы 1. Что лежит в основе Delphi? 2. Какой язык использует Delphi? 3. Что представляет собой объектно-ориентированная программа 4. Что такое событие? 5. В чем состоит суть программирования, управляемого событиями? СРСП № 13 Тема: Создание собственных компонентов. Цель: знать и уметь создавать собственные компоненты Для создания собственного компонента важно иметь представление о библиотеке визуальных компонентов, об иерархии компонентов. Все это вам уже знакомо. Решение о создании новых компонентов может быть принято по ряду причин, среди которых: - разработка нового пользовательского интерфейса с дальнейшим использованием его в других приложениях; - создание принципиально нового класса, которого нет в стандартной библиотеке Kylix; - упрощение кода приложения путем введения новых компонентов; - распространение своих компонентов среди других программистов; - желание глубоко изучить среду, разобраться с тонкостями программирования. Естественно, кроме названных причин, вы можете назвать множество собственных. Создание компонентов по сложности практически не отличается от создания приложений. 116 Конечно, все зависит от сложности компонента. Но, если вы уже решились на создание компонента, рекомендации будут следующими: - определите для себя, какие действия должен выполнять компонент; - разработайте краткий алгоритм, по которому будет работать компонент; - разбейте всю конструкцию компонента на независимые части; - предоставьте возможность дальнейшей разработки компонента (возможно, в будущем вы захотите создать на его основе компонентпотомок); - напишите код компонента (этот пункт разбивается на такие этапы): выбор предка для вашего компонента; создание заготовки (модуля) компонента; создание свойств, событий и методов компонента; отладка и тестирование; регистрация компонента в среде; создание справки для вашего компонента. Далее мы рассмотрим перечисленные выше этапы создания компонента. Выбор предка компонента Создание заготовки компонента Итак, вы выбрали класс-предок для вашего компонента. Теперь можно приступать к созданию модуля вашего компонента. Создание модуля (заготовки) для нового компонента можно выполнить путем вызова окна Delphi, которое называется экспертом компонентов (Component Expert). Данное окно можно вызвать путем выбора в главном меню Delphi пункта Соmponent/New Component. Рассмотрим данное окно. Итак, первое поле ввода Ancestor type предназначено для ввода класса - предка для нового компонента. Данное поле ввода держит в выпадающем списке все зарегистрированные классы библиотеки СLX. Предположим, что мы будем создавать компонент, предком которого яется кнопка TButton. Для этого выберем в выпадающем списке класс Button. Следующее поле Class Name предназначено для ввода имени нового класса. Пусть в нашем случае это будет новый класс TButton. Заметьте, что по умолчанию Delphi заполняет это поле именем класса-предка с добавлением порядкового номера (в нашем случае TButtoni). Контрольные вопросы 1. Для чего же нужны новые компоненты? Зачем их создавать? 2. Перечислите классы CLX 3. Опишите возможности класса TCustomClassName 4. От чего зависит создание компонента? СРСП № 14 Тема: Создание встроенной справочной системы Цель: знать процесс создания справочной системы 117 После того как создан файл справочной информации системы (RTFфайл), можно приступить к созданию справочной системы (HLP-файла). Для этого удобно воспользоваться программой Microsoft Help Workshop, которая поставляется вместе с Delphi и находится в файле Hcw.exe. Запустить Microsoft Help Workshop можно из Windows или из Delphi, выбрав из меню Tools команду Help Workshop. Если в меню Tools команды Help Workshop нет, то надо из этого же меню выбрать команду Configure Tools и в открывшемся диалоговом окне Tool Options (рис. 14.4) щелкнуть на кнопке Add. В результате этого откроется диалоговое окно Tool Properties (рис. 14.5), в поле Title которого надо ввести название программы — Help workshop, а в поле Program — полное (т. е. с указанием пути) имя исполняемого файла программы Microsoft Help Workshop— C:\Program Files\Borland\Delphi7\Help\Tools\HCW.exe. Для ввода имени файла можно воспользоваться кнопкой Browse. Рис. 14.4. Диалоговое окно Tool Options 118 Рис. 14.5. Диалоговое окно Tool Properties После запуска программы Microsoft Help Workshop на экране появляется главное окно программы. Для того чтобы приступить к созданию справочной системы, нужно из меню File выбрать команду New, затем в открывшемся диалоговом окне тип создаваемого файла — Help Project. В результате этих действий открывается окно Project File Name. В этом окне сначала надо выбрать папку, где находится программа, для которой создается справочная система, и где уже должен находиться файл документа справочной системы (RTF-файл). Затем в поле Имя файла нужно ввести имя файла проекта справочной системы. После щелчка на кнопке Сохранить открывается окно проекта справочной системы . Используя окно проекта справочной системы, можно добавить необходимые компоненты в проект, задать характеристики окна справочной системы, выполнить компиляцию проекта и пробный запуск созданной справочной системы. СРСП № 15 Тема: Создание проектов с использованием возможностей программы Delphi Цель: развитие навыков в создании проектов графических Delphi позволяет программисту разрабатывать программы, которые могут выводить графику: схемы, чертежи, иллюстрации. Программа выводит графику на поверхность объекта (формы или компонента Image). Поверхности объекта соответствует свойство canvas. Для того чтобы вывести на поверхность объекта графический элемент (прямую линию, окружность, прямоугольник и т. д.), необходимо применить к свойству canvas этого объекта соответствующий метод. Например, 119 инструкция Form1.Canvas.Rectangle (10,10,100,100) вычерчивает в окне программы прямоугольник. Как было сказано ранее, поверхности, на которую программа может выводить графику, соответствует свойство Canvas. В свою очередь, свойство canvas — это объект типа TCanvas. Методы этого типа обеспечивают вывод графических примитивов (точек, линий, окружностей, прямоугольников и т. д.), а свойства позволяют задать характеристики выводимых графических примитивов: цвет, толщину и стиль линий; цвет и вид заполнения областей; характеристики шрифта при выводе текстовой информации. Методы вывода графических примитивов рассматривают свойство Canvas как некоторый абстрактный холст, на котором они могут рисовать (canvas переводится как "поверхность", "холст для рисования"). Холст состоит из отдельных точек — пикселов. Положение пиксела характеризуется его горизонтальной (X) и вертикальной (Y) координатами. Левый верхний пиксел имеет координаты (0, 0). Координаты возрастают сверху вниз и слева направо (рис.). Значения координат правой нижней точки холста зависят от размера холста. Рис. Координаты точек холста Размер холста можно получить, обратившись к свойствам Height и width области иллюстрации (image) или к свойствам формы: ClientHeight и Clientwidth. Контрольные вопросы 1. Методы какого типа обеспечивают вывод графических примитивов 2. Какие свойства позволяют задать характеристики выводимых графических примитивов СРС № 1 Тема: Классификация языков программирования, поддерживающих объектную парадигму Цель: знать основные понятия и определения 120 Объектно-ориентированная парадигма (ООП) представляет программу как набор объектов и их взаимодействий. Основными понятиями ООП являются следующие: объект — элементарная сущность, описываемая определенными свойствами (хранящимися в виде атрибутов объекта) и поведением (реализованным в виде методов); класс описывает структуру свойств и поведения одного типа объектов. Каждый объект программы является экземпляром некоторого класса; классы могут наследовать атрибуты и методы их родительских классов, в то же время добавляя свои собственные. Иерархия классов позволяет моделировать сущности решаемой задачи на нескольких уровнях детализации и в дальнейшем использовать класс, отвечающий уровню детализации, необходимому для решения конкретной подзадачи. инкапсуляция подразумевает, что некоторые детали реализации класса скрыты от взаимодействующих с ним объектов. У каждого класса есть интерфейс, описывающий взаимодействие объектов этого класса с прочими объектами, и реализация, описывающая то, как это взаимодействие отражается на объекте этого класса. Многие современные языки поддерживают ООП, хотя и в разной степени: чисто объектно-ориентированные языки, например, Smalltalk и Ruby, разработаны для того, чтобы поддерживать и даже навязывать объектно-ориентированный стиль разработки, и не поддерживают другие стили программирования; преимущественно объектно-ориентированные языки, например, Java, C++ и Python, разработаны в основном для поддержки ООП, но позволяют использовать элементы процедурного программирования; исторически процедурные языки, например, Perl и Fortran 2002, были доработаны и в них была добавлена поддержка некоторых элементов ООП; экзотические языки, например, Modula-2 и Oberon, реализуют некоторые черты и принципы ООП, но в оригинальной форме. ООП можно противопоставить модульному или процедурному программированию: как объекты, так и модули/подпрограммы являются самодостаточными (в некоторой степени) единицами, но объекты фокусируются на содержащихся в них данных, а модули/подпрограммы — на сгруппированных в них действиях. Языки программирования, поддерживающие данную парадигму программирования: ABAP COBOL o Ada Cool C# D C++ Dylan Ceylon Factor 121 Falcon FORTRAN Groovy Java LUX MATLAB Nemerle Nimrod Objeck Objective-C Onyx Perl PHP Pike Processing R REXX Scratch Simula Smalltalk 122 СРС № 2 Тема: Библиотека визуальных компонентов Цель: знать предназначение библиотеки Библиотека визуальных компонентов (Visual Component Library, сокращенно — VCL) содержит большое количество классов, предназначенных для быстрой разработки приложений. Библиотека написана на Object Pascal и непосредственно связана с интегрированной средой разработки приложений Delphi. Несмотря на название, в VCL содержатся главным образом невизуальные компоненты, однако имеются и визуальные, а также другие классы, начиная с абстрактного класса TObject. При этом все компоненты являются классами, но не все классы являются компонентами. В Delphi 7 также имеется возможность использовать библиотеку CLX (межплатформенный вариант библиотеки VCL) для разработки приложений под Windows и Linux. Все классы VCL расположены на определенном уровне иерархии и образуют дерево (иерархию) классов. Знание происхождения объекта оказывает значительную помощь при его изучении, т. к. потомок наследует все элементы объекта-родителя. Так, если свойство caption принадлежит классу TControl, то это свойство будет и у его потомков, например, у классов TButton и TCheckBox, и у компонентов— кнопки Button и флажка CheckBox соответственно. Фрагмент иерархии классов с важнейшими классами показан ниже на схеме. Кроме иерархии классов, большим подспорьем в изучении системы программирования являются исходные тексты модулей, которые находятся в каталоге source главного каталога Delphi. Класс TObject — общий предок всех классов Object Pascal — находится в корне иерархии. Этот класс является абстрактным и реализует наиболее общие для всех классов-потомков методы, важнейшими из которых являются: Create (создание объекта); Destroy (удаление объекта); Free (удаление объекта, созданного методом create, при этом вызывается и метод Destroy). 123 Большинство этих методов переопределяются в классах-потомках. Дадим краткую характеристику важнейшим классам-потомкам TPersistent, TComponent и TControl, к которым относится большинство общих свойств, методов и событий и которые, в свою очередь, также порождают множество классов. Класс TPersistent является абстрактным классом для тех объектов, свойства которых загружаются из потока и сохраняются в потоке. Механизм потоков используется для работы с памятью (обычно дисковой или оперативной). В дополнение к методам класса TObject класс TPersistent имеет метод Assign, позволяющий передавать поля и свойства одного объекта другому. Класс TComponent является базовым для всех компонентов и в дополнение к методам своих предков предоставляет средства, благодаря которым компоненты способны владеть другими компонентами. В результате при помещении в форму любой компонент будет принадлежать другому компоненту (чаще всего форме). При создании компонента он обеспечивает автоматическое создание всех принадлежащих ему компонентов, а при удалении этого компонента все принадлежащие ему компоненты также автоматически удаляются. Основные свойства TComponent. Components (список принадлежащих компонентов); Сomponentcount (число принадлежащих компонентов); Component index (номер компонента в списке принадлежащих компонентов); Сomponentstate (состояние текущего компонента); Name (имя компонента); Owner (владелец компонента); Tag (целое значение, хранимое вместе с компонентом). Основные методы класса TComponent: DestroyComponents (разрушает все принадлежащие компоненты); Destroying (уведомляет принадлежащий компонент о его разрушении); FindComponent (находит компонент в списке Components). От класса TComponent происходят визуальные и невизуальные компоненты. Многие невизуальные компоненты порождены непосредственно от класса TComponent, например, таймер (Timer). Компонент Timer позволяет реализовать выполнение действий через определенные интервалы времени. Для этого используется событие onTimer типа TNotifyEvent, генерируемое по истечении заданного интервала времени. Интервал времени в миллисекундах задается свойством Interval типа Cardinal и по умолчанию равен 1000, что соответствует тиканью таймера через 1 секунду. Если установить интервал равным нулю, то таймер остановится и не будет генерировать события onTimer. Остановить таймер также можно, присвоив значение False свойству Enabled. 124 Если система занята выполнением более важных задач, чем отслеживание хода таймера, то интервал между соседними тиканьями таймера может увеличиваться. Это происходит, например, при считывании с диска больших файлов или при выполнении длинного цикла. Класс TControl является базовым классом для визуальных компонентов (элементов управления) и обеспечивает основные средства для их функционирования, в том числе прорисовку на экране. Все визуальные компоненты делятся на оконные и графические, происходящие, соответственно, от классов TWinControl и TGraphicControl. СРС № 3 Тема: Методы программирования сетевых приложений Цель: знать методы программирования сетевых приложений В области компьютеризации понятие программирования сетевых задач или иначе называемого сетевого программирования (англ. network programming), довольно сильно схожего с понятиями программирование сокетов и клиент-серверное программирование, включает в себя написание компьютерных программ, взаимодействующих с другими программами посредством компьютерной сети. Программа или процесс, инициирующие установление связи, называются клиентским процессом, а программа, ожидающая инициации связи, называется серверным процессом. Клиентский и серверный процессы вместе образуют распределенную систему. Связь между клиентским и серверным процессами может быть или на основе соединений (как например, TCP-протокол, устанавливающий виртуальное соединение или сессию), или без соединений (на основе UDP-датаграмм). Программа, которая может функционировать и как клиент и как сервер, основывается на одноранговой связи. Сокеты обычно реализуются библиотекой интерфейса программирования приложений (API), как например, сокеты Беркли, впервые представленные в 1983 году. Большинство реализаций основаны на сокетах Беркли, например, Winsock, представленный в 1991 году. Существуют и другие реализации API сокетов, например, Интерфейс транспортного уровня (TLI) на основе STREAMS. Ниже следуют примеры функций или методов, обычно реализуемые библиотекой API: socket() создает новый сокет определенного типа, идентифицируемый при помощи целого числа, после чего выделяет ему системные ресурсы. bind(), как правило, используется на серверной стороне; ассоциирует сокет с адресной структурой сокетов, то есть определенным номером локального порта и IP-адресом. 125 listen() используется на стороне сервера; переводит TCP-сокет в режим прослушивания. connect() используется на клиентской стороне; привязывает номер незанятого локального порта к сокету. В случае с TCP-сокетом, вызывает попытку установить новое TCP-соединение. accept() используется на стороне сервера. Данная функция принимает полученную попытку создания нового TCP-соединения от удаленного клиента и создает новый сокет, ассоциированный с парой сокетных адресов этого соединения. send() и recv() или write() и read() или recvfrom() и sendto() используются для отправки и получения данных к/от удаленного сокета. close() вызывает освобождение системных ресурсов, выделенных сокету. В случае TCP, соединение завершается. СРС № 4 Тема: Программирование для Интернет Цель: иметь представление о языках программирования, ориентированных на разработку Internet-приложений Веб-программирование. Бурно развивающийся раздел программирования, ориентированный на разработку динамических Internetприложений. Языки веб-программирования — это соответственно языки, которые в основном предназначены для работы с интернет-технологиями. Языки веб-программирования делятся на две группы: клиентские и серверные. Клиентские языки Как следует из названия, программы на клиентских языках обрабатываются на стороне пользователя, как правило их выполняет браузер. Это и создает главную проблему клиентских языков — результат выполнения программы (скрипта) зависит от браузера пользователя. То есть если пользователь запретил выполнять клиентские программы, то они исполняться не будут, как бы ни желал этого программист. Кроме того, может произойти такое, что в разных браузерах или в разных версиях одного и того же браузера один и тот же скрипт будет выполняться по-разному. С другой стороны, если программист возлагает надежды на серверные программы, то он может упростить их работу и снизить нагрузку на сервер за счет программ, исполняемых на стороне клиента, поскольку они не всегда требуют перезагрузку (генерацию) страницы. Самыми распространенными клиентскими языками программирования являются: JavaScript VBScript ActionScript Java 126 Серверные языки Когда пользователь дает запрос на какую-либо страницу (переходит на неё по ссылке или вводит адрес в адресной строке своего браузера), то вызванная страница сначала обрабатывается на сервере, то есть выполняются все программы, связанные со страницей, и только потом возвращается к посетителю по сети в виде файла. Этот файл может иметь расширения: HTML, PHP, ASP, ASPX, Perl, SSI, XML, DHTML, XHTML. Работа программ уже полностью зависима от сервера, на котором расположен сайт, и от того, какая версия того или иного языка поддерживается. Список серверных языков программирования: PHP, Perl, Python, Ruby, любой .NET язык программирования (технология ASP.NET), Java, Groovy. Важной стороной работы серверных языков является возможность организации непосредственного взаимодействия с системой управления базами данных (или СУБД) — сервером, на котором упорядоченно хранится информация, которая может быть вызвана в любой момент. Популярными среди систем управления базами данных являются: Firebird IBM DB2 IBM DB2 Express-C Microsoft SQL Server Microsoft SQL Server Express mSQL MySQL Oracle PostgreSQL SQLite Sybase Adaptive Server Enterprise ЛИНТЕР MongoDB 127 Примерные вопросы: 1. Объектно-ориентированное программирование. Основные принципы ООП. 2. Объектно-ориентированное программирование. Инкапсуляция. Наследование. Полиморфизм. 3. Описание объектового типа. Виртуальные методы. 4. Динамическое создание объектов. Конструкторы и деструкторы. Скрытые поля и методы. 5. Теоретические основы объектно-ориентированного программирования. От процедурного программирования к объектному. 6. Основные принципы и этапы ООП. Объектная декомпозиция. 7. Теоретические основы объектно-ориентированного программирования. Объекты и сообщенния. Классы. 8. Основные средства разработки классов. Дополнительные средства разработки классов. 9. Среда визуального программирования. Формы приложения. Компоненты формы. 10.Среда визуального программирования. Событийно-управляемое программирование. Событие и процедура обработки события. 11.Среда визуального программирования. Компоненты библиотеки VCL Delphi. Кнопки, индикаторы, управляющие элементы библиотеки VCL Delphi. 12.Компоненты ввода и отображения текстовой информации. 13.Среда визуального программирования. Компоненты отображения табличных данных. 14.Компоненты отображения иерархических данных. Компоненты – меню. 15.Среда визуального программирования. Отображение графической и мультимедиа – информации. 16.Системные диалоги. Организация управления приложением. Диспетчеризация действий. 17.Объектная модель Delphi Pascal. Определение класса. Особенности реализации переопределения методов. 18.Виртуальные методы. Абстрактные методы. Перегрузка методов. 19.Объектная модель Delphi Pascal. Свойства. Простые свойства. Свойства – массивы. Индексированные свойства. 20.Метаклассы. Ссылка на класс (метакласс). Операции is и as. Методы класса. 21.Объектная модель Delphi Pascal. Механизм определения типов на этапе выполнения программы. 22.Делегирование методов. Библиотека стандартных классов Delphi. Отношения «основной - вспомогательный» и «старший - младший». 128 23.Создание и обработка сообщений и событий. Сообщения Delphi. Методы обработки сообщений. Генерация сообщений. 24.Создание событий. Обработка сообщений VCL. Управление циклом обработки сообщений. 25.Обработка исключений. Структура фрагментов с исключениями. 26.Создание исключений. Генерация исключений. Обработка исключений. 129