Министерство России по связи и информатизации Поволжская Государственная Академия Телекоммуникаций и Информатики
МЕТОДИ...
22 downloads
406 Views
5MB Size
Report
This content was uploaded by our users and we assume good faith they have the permission to share this book. If you own the copyright to this book and it is wrongfully on our website, we offer a simple DMCA procedure to remove your content from our site. Start by pressing the button below!
Report copyright / DMCA form
Министерство России по связи и информатизации Поволжская Государственная Академия Телекоммуникаций и Информатики
МЕТОДИЧЕСКИЕ УКАЗАНИЯ к лабораторным работам
"Программирование в среде Delphi"
Авторы-составители: АКЧУРИН Э.А., д.т.н., профессор СТЕФАНОВА И.А., ст. преподаватель Редактор:
АКЧУРИН Э.А., д.т.н., профессор
Рецензент:
КОРАБЛИН М.А., д.т.н., профессор
Самара 2003
2
Содержание Введение....................................................................................................................................................................
3
1
ИСР Delphi..................................................................................................................................................................
4
2.
Структура программы и типы данных .....................................................................................................................
13
3.
Линейные структуры .................................................................................................................................................
17
4.
Структуры с ветвлениями.........................................................................................................................................
21
5.
Циклы с неизвестным числом повторений..............................................................................................................
26
6.
Циклы с заданным числом повторений...................................................................................................................
30
7.
Массивы .....................................................................................................................................................................
34
8.
Файлы.........................................................................................................................................................................
38
8.
Подпрограммы...........................................................................................................................................................
46
10.
Динамическая память ...............................................................................................................................................
50
11.
Исключения................................................................................................................................................................
53
12.
Списки ........................................................................................................................................................................
57
13.
Модули .......................................................................................................................................................................
61
14.
Таблицы .....................................................................................................................................................................
66
15.
Графика, отображение графиков функций .............................................................................................................
71
16.
Графика, примитивы .................................................................................................................................................
75
17.
Графика, изображения и анимация .........................................................................................................................
83
18.
Тестирование и отладка ...........................................................................................................................................
89
19.
Квадратное уравнение..............................................................................................................................................
94
20.
Класс TThread ............................................................................................................................................................
98
21.
Класс TStream............................................................................................................................................................
104
3
0. Введение Лабораторный цикл содержит 19 работ по изучению программирования на языке Delphi (Object Pascal) в интегрированной среде разработки (ИСР) Delphi. Цикл может использоваться в лабораторном практикуме по дисциплинам: "Программирование на языках высокого уровня" (специальность 220400), "Языки программирования" (специальность 071900), "Информатика и программирование" (специальность 351400), "Высокоуровневые методы информатики и программирования" (специальность 351400). Рекомендуемая литература: Основная: 1. Культин Н. Delphi 7. Основы программирования в Delphi 7. – СПб.: БХВ-Петербург, 2003. 2. Кандзюба С. Delphi 6/7. Базы данных и приложения. - К: ДиаСофт, 2002. 3. Фаронов В. Delphi 7. Учебный курс. – М.: Нолидж, 2003. 4. Карпов Б. Delphi: Специальный справочник. – СПб.: Питер, 2001. Дополнительная: 1. Гофман В. и др. Delphi 6. – СПб.: БХВ, 2001. 2. Кэнту М. Delphi 5 для профессионалов. – СПб.: Питер, 2001. Содержание отчета: 1. Название работы, цель работы, задание в соответствии с вариантом. 2. Блок-схем алгоритма в соответствии с номером варианта. 3. Коды программы. 4. Результаты выполнения программы на ПК. 5. Выводы. Сохранение кодов Каждый студент должен на локальной машине в папке D:\Users\Temp создать свою папку, в которой будут затем размещаться папки проектов. Коды программ каждому студенту рекомендуется сохранять в своей папке. ИСР Delphi для каждого проекта создает несколько файлов. Чтобы файлы разных проектов не перепутывались, следует для каждого проекта создавать свою папку с именем, содержащим номер работы и номер задания (например, папку 03_1 для задания 1 работы 3). Рекомендуется имена проектов выбирать со ссылкой на дисциплину, номер работы и номер задания (например, Prg_3_1 – проект для задания 1 работы 3 по программированию). Файлы проекта Prg_3_1 нужно сохранить в папке 03_1. Для приложений надо сохранять и файл модуля. Рекомендуется для него выбирать имя, как у проекта, с добавлением символа подчеркивания в конце. Для правильного обращения к файлам в консольных приложениях нужно использовать в именах папок только латиницу. Иерархия папок следующая: Диск С Дисциплина (например, Prg_YVU) Фамилия студента (например, Ivanov) Номер работы и задания (например, 03_1) Файлы проекта Prg_3_1. В этой папке на каждом занятии следует сохранять файлы проекта (одно задание лабораторной работы – один проект, одна папка). Рекомендуется при выполнении работы периодически сохранять незавершенные проекты в текущем состоянии, чтобы избежать потерь документов при сбоях. Методические указания МУ доступны в электронном виде. Иерархия папок с документацией следующая: Диск С Дисциплина (например, Prg_YVU) Методические указания Папка с файлами методических указаний. Рекомендуется на первом занятии скопировать файлы МУ с сервера на локальную машину. В случае изменения МУ содержимое папки с МУ на локальной машине следует обновлять с сервера. Кроме того, методические указания выложены в сети Internet на сервере кафедры ВТ ПГАТИ с именем www.pgativt.da.ru. Они находятся на Web-странице в папке «Методические руководства». Выполнение работ ИСР Delphi позволяет разрабатывать разные программы, они называются проектами. В лабораторном цикле создаются проекты двух типов: Консольное приложение (Console Application) - под операционную систему DOS с символьным интерфейсом. Приложение (Application) – под операционную систему Windows с графическим интерфейсом.
4
1. Интегрированная среда разработки Delphi Подготовка к работе По указанной литературе изучить: 1. Методику активизации интегрированной среды разработки (ИСР) Delphi. 2. Структуру главного меню и его пункты. 3. Опции выпадающих меню. Контрольные вопросы 1. Активизация ИСР и выход из среды. 2. Окна ИСР. 3. Назначение и содержание главного окна ИСР. 4. Окно Инспектора объектов 5. Окно Конструктора формы. 6. Окно Дерева объектов. 7. Окно Редактора кода. 8. Панели инструментов. 9. Палитра компонент. 10. Главное меню главного окна ИСР. Опции пунктов Файл, Правка, Поиск, Вид, Проект, Выполнить, Компоненты, База данных, Сервис, Окно, Помощь. 11. Отличия проектов Приложение, Приложение CLX и Консольное приложение. 12. Использование встроенного подсказчика. 13. Кодировки ANSI и ASCII. Зачем нужно преобразование кодировок в консольном приложении? Задание 1. Активизировать ИСР. Ознакомиться с окнами ИСР. 2. Создать проект консольного приложения Prg_1_1. Оно должно в символьном режиме выводить на экран фразу «Hello, World & Россия!». Для него использовать модуль RusTrans с функцией Rus, обеспечивающей перекодировку ANSI => ASCII для отображения кириллицы в консольном приложении. 3. Создать проект приложения Prg_1_2. Оно должно в графическом режиме при нажатии кнопки «Нажми» выводить на экран фразу «Hello World & Россия!». Пример выполнения Задание 1. Активизировать ИСР. Ознакомиться с окнами ИСР. При старте ИСР из Windows по соглашению создается заготовка проекта типа Приложение (Приложение – программа под Windows). Вид экрана при старте ИСР показан на рис. 1.1. На нем представлены: Главное окно вверху экрана. Окно Дерева объектов под главным окном слева вверху. Окно Инспектора объектов слева внизу. Окно Конструктора формы (пустая форма с именем Form1) под главным окном справа. Окно Редактора кода (позиционируется там же, где окно Конструктора формы, переключение клавишей F12). Это окно можно переместить, чтобы видеть одновременно и окно Конструктора формы (так сделано на рис. 1.1).
рис. 1.1. Окно ИСР в режиме Приложения Для Приложения код исполняемой программы находится в двух файлах: Файл проекта с расширением .dpr. Код проекта делается в ИСР автоматически, его не надо редактировать, по соглашению он не показывается. Его можно посмотреть, подключив модуль проекта командой Вид=>Модули, которая выводит окно выбора, в котором нужно выбрать модуль проекта. После этого в редакторе кода появиться закладка с именем проекта. Файл модуля формы с расширением .pas.
5
Главное окно ИСР расположено в верхней части экрана и имеет вид рис. 1.2. Окно содержит: строку заголовка с именем ИСР (Delphi 7) и именем проекта (по умолчанию Project1); под ним строка главного меню ИСР; ниже главного меню слева панели инструментов; справа от них палитра компонент со страницами с закладками; ниже палитра компонент.
рис. 1.2. Главное окно ИСР Панели инструментов содержат кнопки часто употребляемых команд для быстрого доступа (помещены в группы определенного функционального назначения): Панель Место размещения Имя Назначение Под строкой главного меню слева. Standard Стандартная View Вид Debug Отладка Custom Пользователь Component Palette Палитра Компоненты Под панелями. Desktops Настройки Список справа от панелей. Пункты главного меню главного окна ИСР. Пункт Назначение File Файл Работа с файлами. Edit Правка Редактирование. Search Поиск Поиск фрагментов. View Вид Выбор, что показывать. Project Проект Операции с проектом. Run Запуск Прогон и отладка. Component Компоненты Работа с компонентами. Database Базы Данных Работа с базами данных. Tools Инструменты Использование внешнего инструментария. Windows Окно Перечень окон для выбора фокуса. Help Помощь Контекстная. Окно Конструктора формы – стандартное окно Windows с координатной сеткой для согласованного размещения компонент внутри формы. Вид окна в начале работы приведен на Рис. 1.3.
Рис. 1.3. Окно конструктора формы Окно Дерева объектов. Обычно размещается вверху слева от окна Конструктора формы. Рекомендуется не заслонять окно другими окнами, так как оно часто требуется. Пример дан на рис. 1.4. Содержит: Заголовок. Панель инструментов. Список объектов формы в виде дерева. В начале конструирования формы там присутствует только сама форма с именем Form1. По мере заполнения формы компонентами дерево автоматически дополняется.
6
рис. 1.4 Окно Дерева объектов Окно Инспектора объектов обычно размещается слева внизу от окна Конструктора формы. Рекомендуется не заслонять окно другими окнами, так как оно часто требуется. Содержит: Заголовок. Под ним список объектов в форме с возможностью выбора Ниже описание выделенного в форме (или выбранного в списке) объекта. Описание объекта разделено на две страницы с закладками Свойства (Properties) и События (Events). Вид окна приведен на рис. 1.5 (слева - страница свойств, справа - страница событий).
рис. 1.5. Окно инспектора объектов Свойства отображаются в двух столбцах: слева имя свойства, справа значения свойства. Некоторые свойства представляются списками. Признак списка - символ (+) или (-) слева от имени. Свойства могут сортироваться по алфавиту или по категориям (как на рис. 1.5). При этом одно и то же свойство может повторяться в нескольких категориях. События также отображаются в двух столбцах: слева имя события, справа имя обработчика этого события (может выбираться из списка). Имена событий начинаются с префикса On (в переводе означает На), за которым следует имя события на английском языке. Редактор кода для Приложения. Переключаем окно Конструктора формы на окно Редактора кода клавишей F12. Если окна совмещены, то происходит смена видимого окна. Если же окна видны одновременно, то происходит просто передача фокуса управления. Код модуля формы размещается в окне Редактора кода, показанном на рис. 1.6. Обычно к нему слева "приклеивается" Проводник кода (Code Explorer), в котором в иерархической форме отображаются все объявления модуля (его можно отключить). Окно Редактора кода по соглашению имеет такие же размеры, как и окно Конструктора формы, и позиционируется там же для экономии места на экране.
7
рис. 1.6. Окно Редактора кода для Приложения В окне Редактора кода на рис. 1.6 показан код модуля формы. Его ИСР формирует автоматически. В тексте использовано синтаксическое выделение: Зарезервированные слова полужирным шрифтом. Комментарии курсивом синего цвета. Директивы компилятора зеленым цветом. Задание 2. Создать проект - Консольное приложение Prg_1_1. Оно должно выводить на экран фразу – Hello World & Россия! Создаем консольное приложение, выбирая его в диалоговом окне команды Файл=>Новый=>Другое. ИСР выводит окно выбора типа проекта, показанное на Рис. 1.7. В нем выбираем «Консольное». ИСР в окне Редактора кода формирует заготовку для проекта, показанную на рис. 1.8. Имя проекта по умолчанию содержит слово Project с номером в сеансе работы с ИСР. В консольном приложении формы (а значит и соответствующего ей модуля) нет, Инспектор объектов пустой, так как объектов в проекте нет. В заготовке программы проекта размещены: Директива {$APPTYPE CONSOLE}, которая предписывает компилятору создавать консольное приложение. Комментарий // Insert user code here (Вводите код пользователя здесь). В панели Проводника кода (на рис. 1.8 слева) указана ссылка на модуль SysUtils –системные утилиты. Этот модуль содержит наиболее часто употребляемые подпрограммы. Ссылку на него ИСР создает в строке uses автоматически.
Рис. 1.7. Окно выбора типа проекта
8
рис. 1.8. Окно Редактора кода для консольного приложения Код проекта (строки на языке Object Pascal) размещается в окне Редактора кода. Каркас кода формируется ИСР автоматически (эти строки не надо редактировать!!!). Пользователь добавляет в код строки, определяющие выполняемые проектом функции. Код проект сохраняем в папке 01_1. На Рис. 1.9 показано окно Редактора кода с кодом проекта.
Рис. 1.9. Код проекта задания 1 При запуске проекта получаем окно, показанное на Рис. 1.10 слева. Есть проблема – неправильное отображение букв кириллицы. Правильное отображение показано на этом же рисунке справа. Причина ошибки - консольное приложение создается в ИСР, где используется операционная система Windows с кодировкой ANSI, а исполняется под управлением операционной системы MS DOS, использующей кодировку ASCII. Для решения проблемы нужно делать перекодировку букв кириллицы из стандарта ANSI в стандарт ASCII. Для этого в проект Prg_1_1 добавим ссылку на модуль RusTrans с функцией Rus преобразования строк ANSI в ASCII.
Рис. 1.10. Окно проекта задания 1 при исполнении Код проекта после сделанных изменений показан на Рис. 1.11. В нем добавлена ссылка на модуль RusTrans, а в операторе вывода строка текста преобразуется функцией Rus. На Рис. 1.10 справа приведено окно работающего приложения с правильным отображением символов кириллицы.
9
Рис. 1.11. Код проекта задания 1 с модулем RusTrans Задание 3 Создать проект приложения Prg_1_2. Оно должно при нажатии кнопки «Нажми» выводить на экран фразу – Hello, World! Командой Файл => Новый => Приложение создаем новый проект Prg_1_2, файлы которого будем сохранять в папке 01_2. При этом ИСР автоматически в Редакторе кода создает заготовку модуля формы, включая в него в строке uses ссылки на подключаемые модули. Свойству caption (надпись) формы присвоим значение «Моя первая программа». В окне Конструктора формы размещаем два компонента: кнопку Button1 с надписью «Нажми!», метку Label1 для вывода текста. В разделе interface кода модуля формы ИСР автоматически добавляет эти компоненты. Окно Конструктора формы проекта на этапе конструирования показано на Рис. 1.12.
Рис. 1.12. Окно Конструктора формы проекта задания 2 Двойным щелчком левой кнопкой мыши по кнопке Button1 инициируем создание обработчика события нажатия этой кнопки. ИСР автоматически добавляет для обработчика в разделе interface заголовок, а в разделе implementation заготовку его кода. Курсор автоматически устанавливается в тело кода обработчика, куда необходимо занести исполняемые коды. Для нашего проекта это всего две команды: Label1.Caption:=’Hello, World & Россия!’; Button1.Visible:=false; Первая команда свойству caption (надпись) метки Lable1 присваивает значение строки для вывода сообщения на экран, вторая команда свойству visible (видимость) кнопки Button1 присваивает значение false (ложь), делая ее невидимой. При вводе кодов команд целесообразно использовать встроенный в ИСР подсказчик, который позволяет выбирать нужный член класса компонента из большого списка. После набора имени компонента и точки нужно сделать паузу. Появится окно списка членов класса (см. Рис. 1.13 для выбора свойства caption компонента Label1), в котором нужно выбрать нужный член и дважды щелкнуть по нему левой кнопкой мыши. Член класса переместится в код программы. После завершения ввода кодов нужно проект сохранить с заданным именем в созданной для него папке, используя команду Файл => Сохранить проект как. В диалоговом окне нужно выбрать нужную папку, задать имя и сохранить проект. Внимание! При первом сохранении проекта запись файлов в папку происходит в два этапа: Сначала сохраняется модуль формы проекта с расширением .pas. Для него рекомендуется имя Prg_1_2_. Затем сохраняется файл проекта с расширением .dpr. Для него рекомендуется имя Prg_1_2. При сохранении в папке проекта автоматически создается группа вспомогательных файлов, которые не надо удалять или редактировать.
10
Листинг модуля формы: unit Prg_1_2_; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; Label1: TLabel; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); begin Label1.Caption:='Hello, World и Россия'; // Вывод текста Button1.Visible:=false; // Кнопка невидима end; end.
Рис. 1.13. Использование встроенного подсказчика Теперь программу можно запустить на исполнение командой «Запуск» (или клавишей F9, или кнопкой со стрелкой из палитры инструментов). Если при кодировании ошибок не было, то появится окно приложения, как в Конструкторе формы. При нажатии кнопки «Нажми», окно принимает вид Рис. 1.14.
11
Рис. 1.14. Окно формы проекта задания 2 при исполнении Если при кодировании допущены ошибки, то компиляция не происходит, в окне Редактора кода внизу выводится список обнаруженных синтаксических ошибок (логические ошибки компилятор не обнаруживает). Для каждой ошибки имеется описание. Для ошибки, помеченной стрелкой слева от кода, строка в коде выделяется цветом, как показано на Рис. 1.15. В данном примере обнаружен необъявленный идентификатор Hello. Причина - пропущены апострофы, обрамляющие текстовую строку. В результате компилятор рассматривает слово Hello не как часть строки, а как идентификатор, который в коде не определен. После исправления ошибки программу следует запустить повторно. При этом компиляция и сохранение файлов проекта произойдет автоматически. Проект приложения – это стандартная программа Windows, которая в качестве встроенного модуля использует модуль формы. При желании можно посмотреть код проекта, но редактировать его не надо. Для просмотра кода проекта нужно: Командой Вид => Модули вызвать окно со списком модулей проекта, в котором выбрать Prg_1_2. Теперь окно Редактора кода примет вид Рис. 1.16, в котором появляется страница с закладкой Prg_1_2, в которой размещен код проекта. Код проекта в строке uses содержит ссылки на модули Forms (стандартный, содержащий средства работы с окном формы) и Prg_1_2_ (модуль формы нашего приложения) со ссылкой на его исходник (файл Prg_1_2.pas). В исполняемой части проекта имеются 3 стандартные процедуры Windows: Application.Initialize – инициализация приложения, Application.CreateForm – создание формы, Application.Run – запуск формы на исполнение.
Рис. 1.15. Сообщения о синтаксических ошибках
12
Рис. 1.16. Код проекта задания 2 Выход из ИСР осуществляется стандартным для программ под Windows способом. Выводы 1. ИСР Delphi – интегрированная среда быстрой разработки приложений. 2. Приложение в Delphi создается в окне Конструктора формы путем размещения там готовых компонентов. 3. Иерархия компонентов формы отображается в Delphi в окне Дерева объектов. 4. Свойства компонентов отображаются в Delphi в окне Инспектора объектов. 5. Каркас кода проекта ИСР создает автоматически. 6. Пользователь добавляет в него функциональность, вводя коды, определяющие выполняемые действия. 7. При кодировании следует использовать встроенный в ИСР подсказчик. 8. ИСР позволяет создавать приложения под Windows и консольные приложения под DOS. 9. Для консольных приложений с выводом текста на русском языке необходима перекодировка символов ANSI в ASCII. Для этого в строку uses консольного приложения следует добавить ссылку на модуль RusTrans.
13
2. Структура программы и типы в языке Delphi Подготовка к работе 1. Изучить: Структуру программы на языке Delphi. Задание констант, переменных. Типы численных данных и ошибки при преобразованиях типов численных данных. Организацию простейшего ввода-вывода данных. 2. Составить программу решения задачи в виде консольного приложения. Контрольные вопросы 1. Алфавит языка Delphi, операции, идентификаторы. 2. Структура программы. Разделы объявления констант, переменных, меток, типов данных, подпрограмм 3. Константы. Их объявление. Константные выражения. 4. Переменные. Их объявление. 5. Форматы представления чисел (с фиксированной и плавающей точкой). 6. Типы целых чисел без знака: Byte, Word, LongWord = Cardinal. 7. Типы целых чисел со знаком: Shortint, Smallint, Integer = Longint, Int64. 8. Типы вещественных чисел: Single, Real48, Double = Real, Extended, Comp, Currency. 9. Тип TDateTime и его использование 10. Логические типы данных Boolean. 11. Символьные типы: AnsiChar = Char, WideChar. 12. Строковые типы для длинных строк: AnsiString = String, WideString. 13. Строковые типы для коротких строк: ShortString, String[N]. 14. Совместимость типов при присвоениях. 15. Тип Variant и его использование. Задание 1. Создать программу взаимных преобразований типов численных данных в соответствии с вариантами, приведенными в табл. 2.1. Нужно преобразовывать численные данные из типа Start в типы Fin1 и Fin2 для вещественных и целых чисел. 2. Создать программу взаимных преобразований строковых и символьных типов. Она должна отображать фамилию студента строками разного типа и добавлять к строке символ. 3. Создать программу работы с типом TDateTime. Она должна запрашивать дату и время рождения студента, выводить текущие дату/время, запрашивать желаемое время дальнейшего обучения, выводить дату/время и день недели конца обучения. табл. 2.1. Варианты заданий Типы вещественных чисел Типы целых чисел № Start Fin_1 Fin_2 Fin_3 Start Fin_1 Fin_2 Fin_3 1 Single Currency Extended Real48 Byte Cardinal Integer Smallint 2 Real48 Single Currency Double Word Byte Cardinal Integer 3 Double Real48 Single Real LongWord Word Byte LongInt 4 Real Double Real48 Single Cardinal LongWord Word Byte 5 Extended Real Double Real48 Shortint Cardinal LongWord Word 6 Comp Extended Real Double Smallint Shortint Cardinal LongWord 7 Currency Comp Extended Real Integer Smallint Shortint Cardinal 8 Single Currency Comp Extended LongInt Integer Smallint Shortint 9 Real48 Single Currency Comp Int64 LongInt Integer Smallint 10 Double Real48 Single Currency Word Int64 LongInt Integer 11 Real Double Real48 Single LongWord Byte Int64 LongInt 12 Extended Real Double Real48 Cardinal Word Int64 Int64 13 Comp Extended Real Double Shortint LongWord Byte Word 14 Currency Comp Extended Real Smallint Cardinal Word LongWord 15 Real Currency Comp Extended Integer Shortint LongWord Cardinal Пример выполнения Задание 1. Создать программу преобразования численных данных из типа Start в типы Fin1, Fin2 и Fin3: 1. Для вещественных чисел: Start = Real, Fin1 = Extended, Fin2 = Single, Fin3 = Currency. 2. Для целых чисел: Start = Smallint, Fin1 = Cardinal, Fin2 = Longint, Fin3 = Byte. Для контроля размеров данных в программе используется встроенная функция SizeOf, возвращающая размер аргумента в байтах. Каждый раз данные выводятся в виде значения, размера в байтах и типа данных. Числа для наглядности
14
отображаются в формате с фиксированной точкой. При этом задается число позиций под выводимое значение, что позволяет позиционировать выводимые данные в строке. Листинг программы program Prg_2_1; {$APPTYPE CONSOLE} uses SysUtils,RusTrans; const real_0:real=123.456789; int_0:smallint=-1111; var real_1:extended; real_2:single; real_3:currency; int_1:cardinal; int_2:longint; int_3:byte; begin writeln(Rus('Вещественное число в разных типах')); writeln; real_1:=real_0; real_2:=real_0; real_3:=real_0; writeln(Rus('Значения и размер в байтах в разных типах')); writeln('real_0=',real_0:10:6,sizeof(real_0):4,' real'); writeln('real_1=',real_1:10:6,sizeof(real_1):4,' extended'); writeln('real_2=',real_2:10:6,sizeof(real_2):4,' single'); writeln('real_3=',real_3:10:6,sizeof(real_3):4,' currency'); readln; writeln(Rus('Целое число в разных типах')); int_1:=int_0; int_2:=int_0; writeln; writeln(Rus('Значения и размер в байтах в разных типах')); writeln('int_0=',int_0:10,sizeof(int_0):4,' smallint'); writeln('int_1=',int_1:10,sizeof(int_1):4,' cardinal'); writeln('int_2=',int_2:10,sizeof(int_2):4,' longint'); writeln('int_3=',int_3:10,sizeof(int_3):4,' byte'); readln; end. В листинге программы в разделе констант const объявлены, как типизированные константы, стартовые числа Start. В разделе var объявлены группы переменных Fin1, Fin2, Fin3 для каждого вида чисел. На рис. 2.1 показан вид окна консольного приложения перед закрытием программы.
рис. 2.1. Окно задания 1 при выполнении Задание 2 Создать программу взаимных преобразований строковых и символьных типов. Она должна отображать слово World строками разного типа и добавлять к строке символ восклицательного знака !.
15
Листинг программы program Prg_2_2; {$APPTYPE CONSOLE} uses SysUtils, RusTrans; var Str_1:string; Str_2:string[10]; ShortStr:ShortString; AnsiStr:AnsiString; WideStr:WideString; MyChar:char; begin Str_1:='World'; writeln(Rus('Строки в разных типах')); writeln; Str_2:=Str_1; ShortStr:=Str_1; AnsiStr:=Str_1; WideStr:=Str_1; writeln(Rus('Значения и размер в байтах в разных типах')); writeln; writeln('AnsiStr =',AnsiStr:7,SizeOf(AnsiStr):5,' AnsiString'); writeln('Str_1 =',Str_1:9,SizeOf(Str_1):5,' String'); writeln('WideStr =',WideStr:7,SizeOf(WideStr):5,' WideString'); writeln('ShortStr =',ShortStr:6,SizeOf(ShortStr):5,' ShortString'); writeln('Str_2 =',Str_2:9,SizeOf(Str_2):5,' String[..]'); readln; writeln(Rus('Добавим к строке символ !')); writeln; MyChar:='!'; Str_2:=Str_2+MyChar; writeln('Str_2 =',Str_2:9,SizeOf(Str_2):5,' String[..]'); readln; end.
Рис. 2.2. Окно задания 2 при выполнении Задание 3 Создать программу работы с типом TDateTime. Она должна запрашивать дату и время рождения, выводить текущие дату/время, запрашивать желаемое время обучения, выводить дату/время и день недели конца обучения. На Рис. 2.3 показано окно работающего приложения задания 3. Листинг программы program Prg_2_3; {$APPTYPE CONSOLE} uses SysUtils, RusTrans; var Date_1,Date_2,Time,DateTime:string; DateTime_1,DateTime_2:TDateTime; Day:integer; begin
16
writeln(Rus('Введите дату рождения в формате день.месяц.год')); readln(Date_1); writeln; writeln(Rus('Введите время рождения в формате часы.минуты.секунды')); readln(Time); writeln; DateTime:=Date_1+Time; DateTime_1:=StrToDateTime(DateTime); DateTime_2:=Now; writeln(Rus('Сегодня '),DateTimeToStr(Now)); writeln; writeln(Rus('Сколько дней еще хотите учиться?')); readln(Day); writeln; DateTime_2:=DateTime_2+Day; Day:=DayOfWeek(DateTime_2); writeln(Rus('Вы станете совсем умным '),DateToStr(DateTime_2)); writeln(Rus('Это будет день недели номер '),Day); readln; end.
Рис. 2.3. Окно задания 3 при выполнении Выводы 1. Программа на языке Delphi имеет следующую структуру: Заголовок. Разделы объявлений констант, переменных, типов, меток, подпрограмм (процедур и функций). Раздел операторов, помещенный в операторные скобки begin…end. Точка, как признак конца программы. 2. Для чисел возможны типы: вещественные, целые без знака и со знаком, 16-ричные. 3. Вещественные числа запоминаются в формате с плавающей точкой. Для них лучше всего использовать тип real. При переходе к типу с меньшим размером теряется точность. При использовании типов с максимальными размерами потребная память увеличивается, но точность может не измениться. Для округления результатов используются типы вещественных чисел с ограниченной дробной частью: comp (0 разрядов) и currency (4 разрядов). 4. Целые числа запоминаются в формате с фиксированной точкой. Для них лучше всего использовать тип integer. При переходе к типу с меньшим размером возможна грубая ошибка, если число не умещается в отведенную под него память. Целые числа без знака целесообразно использовать для уменьшения занимаемой памяти. 5. Для работы с короткими строками используются типы ShortString, String [N до 255]. Это область в статической памяти, назначаемая при компиляции программы. 6. Для работы с длинными строками используются типы String, AnsiString, WideString. Это указатели размером 4 байта, в которые помещается адрес начала строки в динамической памяти, назначаемый при исполнении программы. 7. Операция + со строками выполняет конкатенацию (присоединение в конец) строк или символов. 8. Для работы с датой и временем определен тип TDateTime. Он в формате вещественного числа содержит и дату (целая часть - число суток, прошедших с 30.12.1899) и время (дробная часть - часть суток, прошедших с 0 часов). Тип позволяет выполнять с датой/временем операции, как с вещественными числами.
17
3. Линейные структуры Подготовка к работе 1. Изучить: Запись констант, переменных, стандартных функций. Правила записи арифметических выражений. Арифметический оператор присваивания. 2. Разработать алгоритм решения в соответствии с заданием. 3. Составить программу решения задачи в виде консольного приложения. Контрольные вопросы 1. Алфавит языка Delphi. 2. Операции. 3. Идентификаторы. 4. Типы данных. 5. Структура программы консольного приложения. 6. Где описываются константы, переменные, метки и типы данных? 7. Стандартные функции. 8. Оператор присваивания. 9. Пустой и составной операторы. 10. Процедуры ввода read и readln. 11. Процедуры вывода write и writeln. 12. Последовательность действий при выполнении оператора присваивания. 13. Приоритетность выполнения операций в выражениях. 14. Как организовать пропуск одной, двух строк при выводе? Задание 1. Вычислить значения переменных в соответствии с вариантами задания, приведенными в табл. 3.1. Вывести значения вводимых исходных данных и результаты, сопровождая их вывод именами выводимых переменных. Задание выполнить в виде консольного приложения. 2. Повторить задание 1, используя функции из модуля math. табл. 3.1. Варианты заданий № Расчетные формулы Данные x = 1.82 y = 18 1 z y− z = -3.29
s = xy/x − 2
s = 1+ x +
y y−x ; w = (y − x) 2 x 1 + (y − x)
x2 x3 x4 + + ; w = x (sin x + cos y ) 2! 3! 4!
(
x = 0.33 y = 0.02
)
3
y = e−bt sin(at + b) − bt + a ; s = b sin at2 cos(at) −1
4
b 2 sin3 (x + a) w= x +b − ; y = cos2 ( x 3 ) − x / a 2 + b 2 x a bx 2 − a 2 s = x 3tg 2 (( x + b ) ) + ; g = ax e −1 x+b
5 6 7 8 9
2
r=
x 2 ( x + 1) − sin 2 ( x + a ); s = b
(
)
2
y = sin 3 ( x 2 + a ) −
y = b ⋅ tg 2 x −
(
xb 3 + cos(( x + b ) ) a
x2 x 3 ; z= + cos(( x + b ) ) a b
a ; d =a⋅e sin ( x / a ) 2
)
a
⋅ cos(bx / a )
f = ln a + x 2 + sin 2 ( x / b ); z = e −cx ⋅
x+ x+a x − ln( x − b )
a = -0.5 b = 1.7 t = 0.44 a = -0.5 b = 15.5 x = -2.9 a = 16.5 b = 3.4 x = 0.61 a = 0.7 b = 0.05 x = 0.5 a = 1.1 b = 0.04 x = 0.2 a = 3.2 b = 17.5 x = -4.8 a = 10.2 x = 2.2 b = 9.2 c = 0.5
18
10 11 12 13 14
15
a 2 x + b − x ⋅ cos((a + b)x) 2 2 ; r = x + b − b sin( x + a) / x x +1
a = 0.3 b = 0.9 x = 0.61
z = ax ⋅ sin(2x) + e−2x ( x + b); w = cos2 (x3 ) − x / a 2 + b2 b bx − a s = x ⋅ ctg 2 ( x − a) + ; w = a− x e −1 x+b −x 2 a x + e cos(bx) u= ; f = e 2 x ln(a + x ) − b 3 x ln(b − x ) −x bx − e sin(bx) + 1
a = 0.5 b = 3.1 x = 1.4 a = 16.5 b = 3.4 x = 0.61
π 2 cos x − b a = ; 2 1 / 2 + sin ( y )
x = 1.42 y = -1.27 z = 3.5
y=
b =1+
2
z 3+ z2 /5
sin x
s = e −ax x + 1 + e −bx x + 1,5; z =
a = 0.5 b = 2.9 x = 0.3
1 + m2 sin2 x
m = 0.7 x = 1.7
− cm ⋅ ln(mx)
c = 2.1 a = 0.5
Пример выполнения Задание 1 Вычислить при x = 2.1, y = 0.59, z = -4.8 значения a и b, используя формулы:
a = y ⋅ tg ( x ) + 3
2
z2 ; y2 + x2
(
)
b = ln y + x 2 + sin 2 ( z / x)
Блок-схема алгоритма представлена на рис. 3.1. Начало Расчет a, b
4
Ввод x, y, z
1
Вывод a, b Вывод x, y, z
2
Ожидание Enter 3
5
6
Верно? Нет
Да
Конец
рис. 3.1 Блок-схема алгоритма В блоке 1 исходные данные вводятся, в блоке 2 осуществляется их контрольный вывод. В блоке 3 пользователь проверяет правильность введенных данных, при ошибке ввод повторяется. Если данные верные, то в блоке 4 функции вычисляются, а в блоке 5 их значения выводятся. Блок 6 обеспечивает паузу в исполнении программы, чтобы пользователь мог увидеть результат. На рис. 3.2 приведено окно работающего приложения. Листинг программы program Prg_3_1; {$APPTYPE CONSOLE} uses SysUtils,RusTrans; label 10; var a,b,c,x,y,z: real; proba:integer; begin 10: writeln(Rus('Введите x,y,z'));
19
readln(x,y,z); writeln; writeln(Rus('Вы ввели')); writeln('x=',x:8:3,' y=',y:8:3,' z=',z:8:3); writeln; writeln(Rus('Введите 1, если отображенные данные совпадают с заданными')); readln(proba); if proba<>1 then begin writeln; goto 10; end; writeln; c:=sin(x*x)/cos(x*x); a:=y*c*sqr(c)+sqrt(z*z/(y*y+x*x)); b:=ln(y+x*x)+sqr(sin(z/y)); writeln(Rus('Результат')); writeln('a=',a:8:3,' b=',b:8:3); readLn; end.
рис. 3.2. Окно работающего приложения Задание 2 Повторить задание 1, используя функции из модуля math. В листинг добавляем ссылку на модуль math, что позволяет использовать прямо функцию тангенса tan(аргумент) и возведения в степень power(основание, степень). Окно работающего приложения имеет такой же вид, как в задании 1. Листинг программы program Prg_3_2; {$APPTYPE CONSOLE} uses SysUtils,RusTrans,math; label 10; var a,b,c,x,y,z: real; proba:integer; begin 10: writeln(Rus('Введите x,y,z')); readln(x,y,z); writeln; writeln(Rus('Вы ввели'));
20
writeln('x=',x:8:3,' y=',y:8:3,' z=',z:8:3); writeln; writeln(Rus('Введите 1, если отображенные данные совпадают с заданными')); readln(proba); if proba<>1 then begin writeln; goto 10; end; writeln; c:=tan(x*x); a:=y*power(c,3)+sqrt(z*z/(y*y+x*x)); b:=ln(y+x*x)+sqr(sin(z/y)); writeln(Rus('Результат')); writeln('a=',a:8:3,' b=',b:8:3); readLn; end. Выводы 1. Консольное приложение – программа под DOS. Проект – программа. Используется единственное окно. Ввод/вывод осуществляется процедурами read, readln, write и writeln. 2. Программа с линейной структурой содержит операторы, завершаемые символом «точка с запятой». Рекомендуется один оператор в строке. 3. Выражения используются для нахождения новых значений переменных. В выражениях можно использовать стандартные математические функции. Основные функции определены в модуле SysUtils. 4. Дополнительные математические функции определены в модуле math. Чтобы они были доступны, нужно включить модуль math в строку uses кода программы. 5. Для безусловного перехода можно использовать оператор goto metka, который передает управление помеченному оператору. Метка должна быть предварительно описана в разделе объявления меток label. В исполняемой части программы метка размещается слева от оператора, за именем метки следует вертикальное двоеточие. 6. Несколько операторов можно объединить в один составной, поместив их в операторные скобки begin…end. 7. Рекомендуется вводить в программу комментарии. Это либо текст до конца строки после символов //, либо несколько строк, помещенных в фигурные скобки. В листинге программы комментарий по умолчанию отображается курсивом.
21
4. Структуры с ветвлениями Подготовка к работе 1. Изучить возможности языка программирования для реализации: условной и безусловной передачи управления; вычислительного процесса с разветвляющейся структурой. 2. Разработать алгоритм решения в соответствии с заданием. 3. Составить программы решения задач. Контрольные вопросы 1. Какие структуры вычислительных процессов Вы знаете? 2. Как организовать разветвление вычислений? 3. Условный оператор if...then...else. 4. Условный оператор if...then. 5. Вложенные условные операторы. 6. Оператор выбора case …of. 7. Зачем нужно при отладке программы тестировать все ветви алгоритма? Задания к работе 1. Вычислить значения функции по варианту задания из табл. 4.1. Вывести значения исходных данных и полученные результаты, сопровождая их именами переменных. Значения аргумента взять из указанного диапазона так, чтобы протестировать все ветви программы. Проект – консольное приложение. 2. Вывести сообщения для дней недели с использованием оператора выбора. Проект – консольное приложение. табл. 4.1. Варианты заданий № Функции и условия Данные Диапазон аргумента a = -0.5 t = [0 .. 3] 1 1⋅ ⋅ ⋅ при ⋅ ⋅ ⋅ t 〈1 b = 2 шаг 0.25
2
y = at 2 ln t ⋅ ⋅ ⋅ при ⋅ ⋅ ⋅1 ≤ t ≤ 2 e at cos bt ⋅ ⋅ ⋅ при ⋅ ⋅ ⋅ t 〉 2 πx 2 − 7 / x 2 ⋅ ⋅ ⋅ при ⋅ ⋅ ⋅ x〈1.3 y = ax3 + 7 x ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅при ⋅ ⋅ ⋅ x = 1.3 tg x + 7 x ⋅ ⋅ ⋅ ⋅ ⋅ ⋅при ⋅ ⋅ ⋅ x〉1.3
(
3
4
5
6
a = 1.5
x = [0.8 .. 2.8] шаг 0.25
a = 2.8 b = -0.3 c=4
x = [1 .. 2] шаг 0.25
a = 1.65 b = 1.1
x = [0.5 .. 2] шаг 0.25
a = 2.3
x = [0.2 .. 3] шаг 0.4
a = 2.5
x =[1 .. 2.5] шаг 0.25
)
ax 2 + bx + c ⋅ ⋅ ⋅ при ⋅ ⋅ ⋅ x〈1.2 y = a / x + x 2 − 1 ⋅ ⋅ ⋅ при ⋅ ⋅ ⋅ x = 1.2 2 (a + bx ) / x + 1 ⋅ ⋅ ⋅ при ⋅ ⋅ ⋅ x〉1.2 πx 2 − 7 / x 2 ⋅ ⋅ ⋅ при ⋅ ⋅ ⋅ x〈1.4 y = ax 3 + 7 x 2 − 1 ⋅ ⋅ ⋅ при ⋅ ⋅ ⋅ x = 1.4 2 (a + bx ) / x + 1 ⋅ ⋅ ⋅ при ⋅ ⋅ ⋅ x〉1.4 1.5 cos 2 x ⋅ ⋅ ⋅ при ⋅ ⋅ ⋅ x ≤ 1 2 y = ( x − 2 ) + 6 ⋅ ⋅ ⋅ при ⋅ ⋅ ⋅1〈 x〈 2 3tgx ⋅ ⋅ ⋅ при ⋅ ⋅ ⋅ x〉 2 x x − a ⋅ ⋅ ⋅ при ⋅ ⋅ ⋅ x〉 a y = e − ax sin( ax) ⋅ ⋅ ⋅ при ⋅ ⋅ ⋅ x〈 a x ⋅ sin(ax) ⋅ ⋅ ⋅ при ⋅ ⋅ ⋅ x = a
22
7
bx − lg bx ⋅ ⋅ ⋅ при ⋅ ⋅ ⋅ bx〈1 q = 1 ⋅ ⋅ ⋅ при ⋅ ⋅ ⋅ bx = 1 bx + ln bx ⋅ ⋅ ⋅ при ⋅ ⋅ ⋅ bx〉1
8
sin(ln x) ⋅ ⋅ ⋅ при ⋅ ⋅ ⋅ x〉 3.5 q= 2 cos x ⋅ ⋅ ⋅ при ⋅ ⋅ ⋅ x ≤ 3.5 ln( x + 1) ⋅ ⋅ ⋅ при ⋅ ⋅ ⋅ x〉1 f = 2 sin ( ax ) ⋅ ⋅ ⋅ при ⋅ ⋅ ⋅ x ≤ 1
9
b = 1.5
x = [0.5 .. 3] шаг 0.25
x = [2 .. 5] шаг 0.25 a = 20.3
x = [0.5 .. 2] шаг 0.25
10
a ⋅ ln x + x ⋅ ⋅ ⋅ при ⋅ ⋅ ⋅ x〉1 y= 2a ⋅ cos x + 3 x 2 ⋅ ⋅ ⋅ при ⋅ ⋅ ⋅ x ≤ 1
a = 0.9
x = [0.5 .. 2] шаг 0.5
11
ln 2 ( x) + x 2 / x + 1 ⋅ ⋅ ⋅ при ⋅ ⋅ ⋅ x〈0.5 z = x + t + 1 / x ⋅ ⋅ ⋅ при ⋅ ⋅ ⋅ x = 0.5 2 cos x + t ⋅ sin x ⋅ ⋅ ⋅ при ⋅ ⋅ ⋅ x〉 0.5
t = 2.2
x = [0 .. 2] шаг 0.25
12
a+b e x + cos x ⋅ ⋅ ⋅ при ⋅ ⋅ ⋅ x〈 2.8 u = (a + b ) / ( x + 1) ⋅ ⋅ ⋅ при ⋅ ⋅ ⋅ 2.8 ≤ x ≤ 5 e x + sin x ⋅ ⋅ ⋅ при ⋅ ⋅ ⋅ x〉5 a 2 i + bi + c ⋅ ⋅ ⋅ при ⋅ ⋅ ⋅ i 〈 4 w = i ⋅ ⋅ ⋅ при ⋅ ⋅ ⋅ 4 ≤ i ≤ 6 ai + bi 2 ⋅ ⋅ ⋅ при ⋅ ⋅ ⋅ i〉 6
a = 2.6 b = -0.39
x = [0 .. 6] шаг 1
a = 2.1 b = 1.8 c = -20.5
i = [0 .. 8] шаг 1
14
i2 + 1 i2 + 1 〉 0 a при ⋅ sin sin ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ n n y= i2 + 1 cos(i + 1 / n ) ⋅ ⋅ ⋅ при ⋅ ⋅ ⋅ sin 〈 0 n
a = 2.5 n = 10
i = [1 .. 2.5] шаг 0.25
15
at 2 + b ⋅ sin t + 1 ⋅ ⋅ ⋅ при ⋅ ⋅ ⋅ t 〈 0.1 w = at + b ⋅ ⋅ ⋅ при ⋅ ⋅ ⋅ t = 0.1 2 at + b ⋅ cos t + 1 ⋅ ⋅ ⋅ при ⋅ ⋅ ⋅ t 〉 0.1
a = 2.5 b = 0.4
t = [-1 .. 1] шаг 0.2
13
(
)
Пример выполнения Задание 1 Вычислить при y=1.3, x=[0.. 2.1] с шагом 0.3 значения функции a. Результат вывести в виде таблицы. Проект – консольное приложение.
yx + 1 ⋅ ⋅ ⋅ при ⋅ ⋅ ⋅ yx〈1 a = cos( yx) ⋅ ⋅ ⋅ при ⋅ ⋅ ⋅ yx = 1 e − yx cos( yx) ⋅ ⋅ ⋅ при ⋅ ⋅ ⋅ yx〉1 Блок-схема алгоритма представлена на рис. 4.1. Для организации цикла введены следующие переменные: xs - начальное значение, xk - конечное значение dx - шаг изменения аргумента x. Окно работающего приложения показано на Рис. 4.2.
23
Начало
Ввод y, xs, xk, dx
1
Заголовок
2
x=xs
3
Нет
4
6 y*x>1?
y*x<1?
Да Да
Нет
5 a=y*x+1
9
Вывод x, a
10
x=x+dx
7
a=cos(yx)
a:=exp(-y*x)*cos(y*x)
11 Ожидание Enter
x<=xk? Да
Конец
Нет рис. 4.1. Блок-схема алгоритма задания 1
Листинг программы: program Prg_4_1; {$APPTYPE CONSOLE} uses SysUtils,RusTrans; var a,y,x,xs,xk,dx: real; label 20; begin writeln(Rus('Введите y,xs,xk,dx')); // readln(y,xs,xk,dx); // writeln; writeln(Rus('Таблица a(x)')); // x:=xs; // 20: if y*x<1 then a:=exp(-y*x)*cos(y*x) // else if y*x=1 then a:=cos(y*x)// else a:=y*x+1; writeln('x=',x:5:1,' a=',a:6:3);
Приглашение Ввод данных Заголовок Начало цикла Первое ветвление Вложенное ветвление
8
24
x:=x+dx; if x<=xk then goto 20; readln end.
// Конец цикла
Рис. 4.2. Окно работающего приложения задания 1 Задание 2 Вывести сообщения для дней недели с использованием оператора множественного ветвления. Проект – консольное приложение. В программе в разделе объявления типов type определен тип WeekDay из 7 строк. В разделе переменных var объявлена переменная MyWeek этого типа, значениям которой в исполняемой части программы присвоены русскоязычные имена дней недели. Программа содержит цикл запроса у пользователя номера дня недели в пределах 1..7. После ввода номера в этом интервале с помощью оператора выбора case..of формируется текстовое сообщение о дне недели. Если пользователь вводит номер 0, работа приложения завершается. Ввод чисел, отличных от 0..7, программа рассматривает, как ошибку, и просит повторить ввод, Окно работающего приложения показано на Рис. 4.3. Листинг программы: program Prg_4_2; {$APPTYPE CONSOLE} uses SysUtils,RusTrans; label 10; type WeekDay=array[1..7] of string; var s:string; MyWeek:WeekDay; x:integer; begin MyWeek[1]:='Понедельник'; MyWeek[2]:='Вторник'; MyWeek[3]:='Среда'; MyWeek[4]:='Четверг'; MyWeek[5]:='Пятница'; MyWeek[6]:='Суббота'; MyWeek[7]:='Воскресенье'; writeln(Rus('Введите номер дня недели 1..7, а чтобы закончить 0')); writeln; 10:readln(x); case x of 0: s:=Rus('Спасибо, до свидания'); 1: s:=Rus(MyWeek[x])+Rus(' - день бездельник'); 2,3,4: s:=Rus(MyWeek[x])+Rus(' - рабочий день'); 5: s:=Rus(MyWeek[x])+Rus('. Уф, завтра отдыхаем!'); 6: s:=Rus(MyWeek[x])+Rus(' - выходной день'); 7: s:=Rus(MyWeek[x])+Rus(' - выходной день, а завтра...'); else begin writeln(Rus('Вы ошиблись, повторите')); goto 10;
25
end; end; writeln(s); if x<>0 then goto 10; readln end.
Рис. 4.3. Окно работающего приложения задания 2 Выводы 1. Для безусловной передачи управления применяется оператор goto <Метка>. 2. Для ветвлений используется оператор If <условие> then <оператор1> else <оператор2>. 3. Возможен сокращенный оператор ветвлений if <условие> then <оператор>. 4. Для множественного ветвления можно применить оператор выбора case…of. Селектор этого оператора должен быть порядкового типа (чаще всего целочисленного, например integer). 5. Если в ветвях then или else нужно выполнить несколько операторов, то их нужно объединить в один составной оператор с помощью операторных скобок begin…end. 6. Оператор ветвления может применяться для создания циклов.
26
5. Циклы с неизвестным числом повторений Подготовка к работе 1. По указанной литературе изучить: организацию циклов с неизвестным числом повторений; организацию таких циклов с помощью операторов while...do и repeat...until; вычисление суммы членов бесконечного ряда. 2. Разработать алгоритм решения задачи. 3. Составить программы решения задачи. Контрольные вопросы. 1. Циклический процесс с неизвестным числом повторений. 2. Его отличия от цикла с заданным числом повторений. 3. Операторы языка Object Pascal для организации таких циклов. Их сравнение. 4. Формат оператора while...do. 5. Как выполнить группу операторов в цикле while...do? 6. Формат оператора repeat...until. 7. Как выполнить группу операторов в цикле repeat...until? 8. Прямое вычисление значения суммы членов бесконечного ряда. 9. Вычисление значения суммы членов бесконечного ряда по рекуррентной формуле. 10. Условие выхода из цикла при вычислении значения суммы членов бесконечного ряда. Задание к работе 1. Вычислить значение суммы членов бесконечного ряда с заданной точностью Е с использованием оператора цикла while...do. На печать вывести значение суммы и число членов ряда, вошедших в сумму. Варианты заданий даны в табл. 5.1. Проект – консольное приложение. 2. Выполнить ту же задачу с применением оператора цикла repeat...until. Проект – консольное приложение. табл. 5.1. Варианты заданий N Сумма членов ряда Значения Точность Е 2 4 2n x = 0.1 1 10 −5 (2 x ) (2 x ) (2 x )
s=−
2 3 4 5 6 7 8 9 10 11
2!
+
4!
+ (− 1)
n
(2n )!
+L
2 n −1 x3 n −1 x ( ) s = x− + K + −1 +K 3 2n − 1 2 n +1 x3 x5 n +1 x s= − + (− 1) +K 5 17 4n 2 + 1 x xn π π s = 1 + cos + L + cos( n) + L 1! 4 4 n! 2 2n x x +L+ +L ch( x) = s = 1 + (2n )! 2!
x3 x 2 n +1 +L+ +L (2n + 1)! 3! 1 1 n +L arctg( x) = s = + L + (− 1) x (2n + 1)x 2n+1 sh( x) = s = x +
1 3
π = s = 41 − + L + (− 1)n
x = 0.1
0.5 ⋅10 −4
x = 0.15
10 −3
x = 0.12
10 −4
x = 0.7
10 −4
x = 1.7
10 −3
x = 1.5
0.5 ⋅10 −3 10 −4
1 + L 2n + 1
2n ( π / 6)2 n (π / 6) cos = s = 1 − + L + (− 1) +L (2n)! 6 2! 2n+1 π π (π / 3)3 n (π / 3) sin = s = − + L+ (−1) +L (2n + 1)! 3 3 3! 2n x 2 3x 4 n (2n − 1)x − + L + (− 1) +L s = 1+ (2n )! 2! 4!
0.5 ⋅10 −4
π
0.5 ⋅10 −4 x = 0.75
0.5 ⋅10 −3
27
12 13 14 15
cos x cos 2 x cos nx + +L+ +L 1! 2! n! x ⋅ cos(π / 3) x n cos(nπ / 3) s= +L+ +L n 1 2 n +1 x3 x5 n +1 x s= − + L + (− n ) +L 3 15 4n 2 − 1 2 3 n n s = sin2x − sin3x + L+ (−1) 2 sinnx + L 3 8 n −1 s = 1+
x = 0.2
10 −4
x = 0.25
10 −4
x = 0.3
10 −5
x = 0.62
10 −4
Пример выполнения Задание 1 Вычислить значение суммы членов бесконечного ряда
s = x−
x3 X 5 x 2 n +1 n + + L + (− 1) +L (2n + 1)! 3! 5!
при x = 0.1 с точностью до члена ряда с модулем, меньшим E=10-10. Для вычисления очередного члена ряда будем использовать рекуррентное соотношение, связывающее его с предыдущим членом a(n+1) = q*a(n). Применение рекуррентных формул позволяет избежать вычисления факториала и возведения в произвольную степень. Рекуррентный коэффициент q найдем из выражений для текущего и следующего членов ряда
x 2 n +1 a(n ) = (− 1) (2n + 1)! n
Деля второе выражение на первое, получим
q=
и
a(n + 1) = (− 1)
n +1
x 2(n +1)+1 . (2(n + 1) + 1)!
a(n + 1) − x2 = (2n + 2)(2n + 3) a(n )
Значение начального члена ряда задаем до цикла путем прямого присваивания (номер начального члена n в разных вариантах равен 0 или 1, правильное значение определяется по формуле текущего члена). В нашем задании n=0, a=x. Блок- схема алгоритма приведена на рис. 5.1. В блоке 1 вводятся исходные данные. Инициализация данных для цикла выполняется в блоке 2. Блок 3 открывает цикл while...do. Блок 4 – тело цикла. Результаты выводятся в блоке 5. Начало
1
Ввод x,E
2
n := 0; a := x; s := a;
3
4
while abs(a)>E do
q:= -x*x/(2*n+2)/(2*n+3); a:= a*q; s:= s+a; n:= n+1;
Вывод s,n
рис. 5.1. Блок- схема алгоритма задания 1
Конец
5
28
Окно работающего приложения задания 1 показано на Рис. 5.2.
Рис. 5.2. Окно работающего приложения задания 1 Листинг программы program Prg_05_1; {$APPTYPE CONSOLE} uses SysUtils, RusTrans; var a,e,q,s,x: real; n: integer; begin writeln(Rus('Введите точность')); // Ввод данных write('e='); readln(e); writeln(Rus('Введите аргумент')); write('x='); readln(x); n := 0; // Инициализация цикла a := x; s := a; while abs(a)>E do // Начало цикла begin // Тело цикла q:=-x*x/(2*n+2)/(2*n+3); a:=a*q; s:=s+a; n:=n+1; end; writeln; writeln(Rus('Результат')); // Вывод результатов writeln(Rus('Сумма s='),s:8:3); writeln(Rus('Членов ряда n='),n); readln; end. Задание 2 Блок- схема алгоритма приведена на рис. 5.3. В блоке 1 вводятся исходные данные. Инициализация данных для цикла выполняется в блоке 2. Блок 3 - цикл repeat...until. Результаты выводятся в блоке 4. Результат работа программы такой же, как для задания 1. Листинг программы program Prg_05_2; {$APPTYPE CONSOLE} uses SysUtils,RusTrans; var a,e,q,s,x: real; n: integer; begin writeln(Rus('Введите точность')); // Ввод данных write('e='); readln(e); writeln(Rus('Введите аргумент')); write('x='); readln(x); n := 0; // Инициализация цикла
29
a := x; s := a; repeat q:=-x*x/(2*n+2)/(2*n+3); a:=a*q; s:=s+a; n:=n+1; until abs(a)<e; writeln; writeln(Rus('Результат')); writeln(Rus('Сумма s='),s:8:3); writeln(Rus('Членов ряда n='),n); readln; end.
// Начало цикла // Тело цикла
// Вывод результатов
Начало
1
2
Ввод x,E
n := 0 a := x s := a
3 repeat q= -x*x/(2*n+2)/(2*n+3); 5 a:= a*q; s:= s+a; n:= n+1 until abs(a)<E Вывод s, n
4
Конец рис. 5.3. Блок- схема алгоритма задания 2 Выводы 1. Для организации циклов с неизвестным числом повторений применяются операторы: while...do (цикл ДО), repeat...until (цикл ПОКА). 2. Для выполнения в цикле while...do группы операторов необходимо превратить ее в один составной оператор с помощью операторных скобок begin…end. 3. При выполнении цикла repeat...until в теле цикла может находиться множество операторов. Составной оператор не требуется.
30
6. Циклы с заданным числом повторений Подготовка к работе 1. По указанной литературе изучить: организацию циклов с известным числом повторений; возможности языка для организации таких циклов с помощью операторов с параметром for...to...do и for...downto...do. 2. Разработать алгоритм решения задач. 3. Составить программы решения задач. Контрольные вопросы 1. Преимущества использования операторов циклов в программе. 2. Циклический процесс с заданным числом повторений. 3. Средства языка Object Pascal для организации циклов с заданным числом повторений. 4. Оператор цикла for...to...do. 5. Оператор цикла for...downto...do. 6. Разница между операторами for...to...do и for...downto...do. 7. Требования к переменной цикла в операторах for...to...do и for...downto...do. 8. Организация вычисления суммы. 9. Организация вычисления произведения. Задание к работе 1. Вычислить значения функции с использованием оператора цикла for...to...do. Проект – консольное приложение. 2. Вычислить значения функции с использованием вложенных операторов цикла for...to...do. Проект – консольное приложение. Варианты заданий даны в табл. 6.1. табл. 6.1. Варианты заданий № Задача 1 Задача 2 a = 2.8; x = 5.1; c = 1.8; b = 0.81 1
5
10
t = ∑ cos 2 na n=2
2
n =1 a =1
12
z = ∏ (cos k + sin k ) k =1
3
15
18
15
(
)
13
(
z = b ⋅ ∏ cos n 2 b
)
n =1
7
40
z = ∏ (cos an + bn ) n =1
8
12
t = ∑ ( x ⋅ sin na ) n =1
9
17
(
( ))
u = ∑ n ⋅ sin 2 n 2 a n =1
10
t = ∏ ∑ ln ac a =1 c =1 10
10
t = ∏ ∑ cos(a + b ) a = 2 b =1
n =1
6
a =1 b = 2
b =1 c = 2 5 10
z = ∑ (cos ak + sin c ) z = ∏ a 2 + ln nc
10
t = ∏ ∑ tgbc
k =1
5
5
t = ∏∑ sin ab 10
p = ∏ (cos nbcx ) n =1
4
10
t = ∑∏ cos na
5
10
t = ∏ ∑ bc b = 2 c =1 5
3
t = ∏ ∑ (a 2 c ) a =1 c =1 8
10
t = ∏∑
(
b +c
b = 2 c =1 5
5
t = ∏ ∑b2a a = 2 b =1
)
31
10
7
10
t = ∑ 5 ⋅ lg(abn ) n=2
11
c = 2 b =1
20
9
y = ∏ z 2 cos( x + 1)
13
a = 2 c =1
x+k y=∑ k =1 c + b
9
15
b =1 c =1 9
10
y = ∑ 5 ⋅ ln (abn )
b =1 c =1 8
15
y = ∑ (lg a + k ⋅ ln c ) 25
(
y = ∏ cos na 2 b 2
5
t = ∏∑ b 2 cos c 2 5
(
t = ∏∑ b ⋅ cos 2 a
)
a = 3 b =1
n =1
15
10
t = ∏∑ cos c
n=2
14
10
t = ∏∑ (a + c )
z =1
12
5
t = ∏ ∑ cb 2
)
10
10
(
t = ∏∑ b 2 a
)
a = 5 b =1
n =1
Пример выполнения Задание 1 Вычислить z =
20
∑x
2
/i
i =1
Блок-схема алгоритма задания представлена на рис. 6.1. Начало
1
2 3
4
Ввод x
z=0
Для i=1..20 с шагом 1
z := z+x2/i
Вывод z
6
Ожидание Enter
7
Конец рис. 6.1. Блок-схема алгоритма задания 1 В блоке 1 вводится значение переменной х. Блок 2, задающий начальное значение суммы, стоит перед циклом, в котором она накапливается. Блок 3 - цикл с известным числом повторений. В его теле блок 4 вычисляет значение слагаемого x2/i и накапливает сумму. Результат представляет собой одно число, которое выводится блоком вывода 5. В блоке 6 организуется пауза, чтобы пользователь увидел результат. Листинг программы: program Prg_6_1; {$APPTYPE CONSOLE} // Директива компилятора uses SysUtils, RusTrans; // Ссылка на модули
32
var x,z: real; i: integer; begin writeln(Rus('Введите х:')); readln(x); z:=0; for i:=1 to 20 do z:=z+(sqr(x)/i); writeln; writeln(Rus(‘Результат’)); writeln('x=', x:8:3, ' z=', z); readln end.
// Ввод x // Обнуление суммы // Накопление суммы // Заголовок результата // Вывод результата // Ожидание нажатия клавиши Enter
Задание 2 Вычислить t =
10
10
∏∑ cos(ijx) i =1 j =1
Блок-схема алгоритма задачи представлена на рис. 6.2. В блоке 2 присваивается начальное значение 1 произведению t. Блок 3 открывает цикл по переменной n для формирования произведения. В теле цикла готовится очередной сомножитель в виде суммы. Блок 4 обнуляет значение переменной s, в которой происходит накапливание суммы. Блок 5 открывает цикл для вычисления очередной суммы. Формирование произведения осуществляет блок 7. Блок 8 выводит итоговое значение произведения. В алгоритме для разнообразия один цикл реализован оператором for...to...do, а другой - оператором for...downto...do. Начало 1
2
3
Ввод x
t=1
Для i=1..10 с шагом 1
4
s := 0
Вывод t
5
Для j=10..1 с шагом -1
Конец
6
s := s+cos(i*j*x)
7
t := t*s рис. 6.2. Блок-схема алгоритма задания 2
Код программы: program Prg_6_2; {$APPTYPE CONSOLE} uses SysUtils, RusTrans;
// Директива компилятора // Ссылка на модули
8
33
var x,s,t: real; I,j: integer; begin writeln(Rus('Введите х:')); readln(x); t:=1; for i:=1 to 10 do begin s:=0; for j:=10 downto 1 do s:=s+Cos(i*j*x); t:=t*s end; writeln; writeln(Rus(‘Результат’)); writeln('x=', x:8:3, ' z=', z); readln end.
// Ввод x // Инициализация произведения // Цикл произведения // Обнуление суммы // Цикл суммы
// Заголовок результата // Вывод результата // Ожидание нажатия клавиши Enter
Выводы 1. Для организации циклов с известным числом повторений применяются операторы: Инкрементный: for i:=<начальное значение> to <конечное значение> do <оператор>. В нем переменная индекса цикла I увеличивается с шагом 1. Декрементный: for i:=<начальное значение> downto <конечное значение> do <оператор>. В нем переменная индекса цикла I уменьшается с шагом 1. 2. Переменная индекса цикла должна быть порядкового типа (например, Integer). 3. Если в теле цикла используется много операций, то их нужно оформить, как составной оператор, с помощью операторных скобок begin…end.
34
7. Массивы Подготовка к работе 1. По рекомендуемой литературе изучить: способы описания размеров массивов; способы ввода и вывода массивов; реализацию приемов накопления суммы или произведения элементов массивов, запоминания результатов, нахождение наибольшего и наименьшего; способы ввода и вывода матриц. 2. Разработать алгоритм решения в соответствии с заданием. 3. Составить программу решения задачи. Контрольные вопросы 1. Что такое массив? 2. Описание типа - массив. 3. Какие операторы языка можно использовать для описания массивов? 4. Особенности организации цикла при обработке массивов? 5. Особенности программирования при обработке массивов? 6. Особенность ввода и вывода массивов? 7. Представление строковых переменных типа String, как одномерных массивов. 8. Вложенные массивы. Задание к работе 1. Обработка одномерного массива. Варианты заданий в табл. 7.1. Проект – консольное приложение. 2. Обработка матрицы. Варианты заданий в табл. 7.2. Проект – консольное приложение табл. 7.1. Варианты задания 1 № Имя Задание массива 1 X(100) Вычислить сумму и количество элементов массива X, условие 0 ≤ X (i ) ≤ 1 . 2 А(80) Вычислить среднее арифметическое значение элементов массива A, условие A(i )〉 0 . 3
X(70)
4
В(50)
5
С(40)
6 7
D(80) Y(20)
8
А(4)
9 10
N(50) X(N)
11 12
X(N) X(N)
13
В(K)
14
С(K)
15
А(K)
Переписать элементы массива X в массив Y и подсчитать их количество, если − 1 ≤ X (i ) ≤ 1 . Определить максимальный элемент массива В и его порядковый номер при B (i )〉 0 .
Вычислить минимальный элемент массива С и его номер при C (i )〈 0 . Найти максимальный и минимальный элементы массива D и поменять их местами. Найти сумму элементов массива. Разделить каждый элемент исходного массива на полученное значение. Результат получить в том же массиве. Полученный массив распечатать в одной строке. Найти сумму элементов массива. Разделить каждый элемент исходного массива на полученное значение. Результат получить в том же массиве. Напечатать в одной строке. Определить сумму элементов массива N, кратных трем. Условие: INT(N(i)/3)*3=N(i). Вычислить сумму и количество элементов массива X. Условие X (i )〉 0, N ≤ 30 . Переписать в массив Y подряд положительные элементы массива X. Условие N ≤ 40 . Переписать подряд в массив Y положительные и в массив Z отрицательные элементы массива X. Условие N ≤ 40 . Определить максимальный элемент массива B и его порядковый номер при B(i )〈 0, K ≤ 50 . Определить минимальный элемент массива С и его порядковый номер при − 1 ≤ C (i ) ≤ 1, K ≤ 50 . Найти среднее значение элементов заданного массива. Преобразовать исходный массив, вычитая из каждого элемента среднее значение. Полученный массив распечатать в виде строки. K<=40.
35
табл. 7.2. Варианты задания 2 № Матрица Задание 1 A Вычислить и запомнить сумму и число положительных элементов каждого столбца матрицы. Результаты отпечатать в виде двух строк 2 B Вычислить и запомнить суммы и числа элементов каждой строки матрицы. Результаты отпечатать в виде двух столбцов. 3 C Вычислить сумму элементов побочной диагонали матрицы. 4 A Найти след матрицы. 5 B Найти сумму элементов второй строки матрицы. 6 C Найти сумму элементов второго столбца матрицы. 7 A Вывести на печать элементы матрицы А(i,j)<=4 8 A Вывести на печать элементы матрицы 2<= А(i,j) <=5 9 B Вывести на печать отрицательные элементы матрицы. 10 A Вывести на печать положительные элементы матрицы. 11 A Вычислить сумму элементов матрицы. 12 A Найти сумму элементов побочной диагонали матрицы. 13 B Вычислить сумму элементов двух первых столбцов матрицы. 14 C Вычислить среднее арифметическое матрицы. 15 A Определить сумму элементов третьей строки матрицы. Используемые матрицы:
− 2 6 A= 2 4
10 4 0 5
4 8 2 − 0.5 6 8 2 1
−3 2 B= 3 2
18 −4 4 3
−6 2 5 4
−15 1 1 5
−0.5 −2 C= 3 5
6 4 8 −10
8 5 6 8
10 1 4 1
Пример выполнения Задание 1 Вычислить наибольший элемент Xmax массива Х и его порядковый номер Nmax. Размерность массива N ≤ 30 . Результат – консольное приложение. Блок-схема алгоритма представлена на рис. 7.1. Начало
Ввод n, x(i) 1 Imax:= 1; Xmax:=x[1]
2
Для i=1..n с шагом 1
3
Нет 4
6
Ожидание Enter
7
x[i]<=Xmax? Да
5
Вывод Xmax, Imax
Xmax := x[ I ]; Imax := i
Конец
рис. 7.1. Блок-схема алгоритма задания 1
36
В блоке 1 вводятся число элементов массива n и значения элементов массива x[i]. В блоке 2 в качестве кандидатов в ответы выбирается первый элемент (Xmax = первый элемент массива, Imax = 1). Блок 3 открывает цикл с известным числом повторений. В блоке 4 текущий элемент массива x[i] сравнивается с Xmax. Если он больше Xmax, то в блоке 5 Xmax и Imax меняются на параметры текущего элемента. Результат выводится блоком 6. Блок 7 обеспечивает паузу в исполнении программы, чтобы пользователь мог увидеть результат. Листинг программы program Prg_7_1; {$APPTYPE CONSOLE} uses SysUtils,RusTrans; const NN=30; var i,n,Xmax,Imax: integer; x:array[1..NN] of integer; begin writeln (Rus('Введите размер массива n')); readln(n); writeln; randomize; for i:=1 to n do x[i]:=random(100); // Ввод элементов массива x Xmax:=x[1]; // Кандидат в Xmax Imax:=1; // Его номер for i:=2 to n do if x[i]>Xmax then // Поиск Xmax begin Xmax:=x[i]; Imax:=i end; writeln; writeln(Rus('Результат')); writeln(Rus('Максимум Xmax='),Xmax); writeln(Rus('Его номер Imax='),Imax); readln end. Задание 2 Вывести квадратную матрицу X размером N в виде таблицы. Вычислить и вывести сумму первых положительных элементов нечетных столбцов матрицы и обнулить элементы, размещенные над суммируемыми элементами. Листинг программы: program Prg_7_2; {$APPTYPE CONSOLE} uses SysUtils,RusTrans; const NN=30; var i,j,k,l,n,s: integer; x:array[1..NN,1..NN] of integer; begin writeln (Rus('Введите размер матрицы n')); readln(n); writeln; randomize; for i:=1 to n do // Формирование матрицы for j:=1 to n do x[i,j]:=50-random(100); for i:=1 to n do // Вывод матрицы begin for j:=1 to n do write(x[i,j]:4); writeln; end; s:=0; // Инициализация суммы for j:=1 to n do begin if j mod 2=0 then continue; // Пропустить четные столбцы for i:=1 to n do
37
begin if x[i,j]>0 then begin s:=s+x[i,j]; // Суммирование break; // Досрочный выход из цикла end; x[i,j]:=0; // Обнуление элемента матрицы end; end; writeln; writeln(Rus('Сумма='),s); for k:=1 to n do begin // Вывод измененной матрицы for l:=1 to n do write(x[k,l]:4); writeln; end; readln; end. На Рис. 7.2 приведено окно работающего приложения задания 2. По нему нужно проверить правильность исполнения алгоритма.
Рис. 7.2. Окно работающего приложения задания 2 Выводы 1. Массив – это набор компонент одинакового типа. 2. Размерность массива ограничена только доступной памятью. 3. Для обработки массивов применяются операторы циклов с известным числом повторений. 4. При использовании операторов циклов можно применять процедуры: continue для перехода к следующей итерации в цикле, break для досрочного выхода из цикла. 5. Переборный алгоритм позволяет найти элемент массива с заданным свойством (например, имеющий максимальное значение). 6. Матрицы наглядно отображаются в табличной форме. Для вывода матриц в таком виде используются операторы: write для размещения нескольких элементов в одной строке текста, writeln для перехода к другой строке.
38
8. Файлы Подготовка к работе 1. По рекомендуемой литературе изучить: типы файлов, определенные в Delphi; связь с дисковыми файлами; операции с типизированными файлами; операции с текстовыми файлами; операции с нетипизированными файлами. 2. Разработать алгоритмы решения в соответствии с заданием. 3. Составить программы решения задач. Контрольные вопросы 1. Типы файлов, определенные в Delphi. 2. Способы связи с файлами (прямой, файловая переменная). 3. Файловая переменная. 4. Как связать файловую переменную с дисковым файлом? 5. Процедуры создания, открытия, закрытия типизированных файлов. 6. Организация прямого доступа к компонентам типизированных файлов. 7. Процедуры создания, открытия, закрытия текстовых файлов. 8. Процедуры создания, открытия, закрытия нетипизированных файлов. 9. Высокоскоростное копирование файлов. 10. Контроль ошибок работы с файлами. Задание к работе Выполнить 4 задания по работе с файлами. Все проекты - консольные приложения. Задания и исходные данные представлены в табл. 8.1. Задания: 1. Создать программу создания и дополнения текстового файла. Сначала создать текстовый файл из 5 строк и посмотреть его содержимое. Затем добавить в этот файл произвольные строки и проверить содержимое итогового файла. 2. Создать программу демонстрации произвольного доступа к элементам файла. Она заносит в файл последовательно числа от N1 до N2. После записи из файла считываются на дисплей все компоненты. 3. Создать программу для высокоскоростного копирования файла-источника в файл-приемник. В качестве файлаисточника использовать результат компиляции Prg_8_1.exe программы задачи 1, созданный ранее в папке 8_1. В качестве файла-приемника определить файл с именем Prg_8_1a.exe в папке 8_3. 4. Создать программу обмена данными с файлом, использующую прямое обращение к именам файлов. Она заносит в буфер N1 случайных чисел и переносит их в файл. Затем буфер обнуляется, и из файла возвращаются первые N1-2 числа. табл. 8.1. Варианты задания 2, 4. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 N1 4 6 8 7 9 43 21 23 14 12 17 18 25 33 28 N2 9 11 16 21 19 58 44 46 25 29 34 42 53 44 43 Примеры выполнения Задание 1 Создать программу создания, записи и добавления записи текстового файла. Создать текстовый файл из 5 строк и посмотреть его содержимое. Затем добавить в этот файл еще 5 строк и проверить содержимое итогового файла. Блок-схема алгоритма приведена на рис. 8.1.
39
Начало 1
Имя файла
2
Путь к файлу Создать файл
Дозапись в файл
11
Строка в файл
12
Да 3
Ошибка? Нет
4
Запись в файл
5
Строка в файл
Закрыть файл. Открыть для проверки
Пауза Чтение из файла
6
13
14
15
Закрыть файл. Открыть для проверки
7
Пауза
8
Чтение из файла
Строка из файла
16
Закрыть файл 17
9
10
Строка из файла
Закрыть файл. Открыть для дозаписи
Пауза
18
Конец
рис. 8.1. Блок-схема алгоритма задания 1 В блоке 1 вводится имя файла на диске. В блоке 2 из известного имени папки (константа FileDir в коде программы) и этого имени генерируется путь к файлу, после чего создается файл. Если произошла ошибка, то в блоке 3 программа завершается. Внимание! При работе с файлами в консольном приложении нельзя применять в путях к файлам символов кириллицы. Если ошибок не произошло, то в блоке 4 открывается цикл по вводу в файл Imax строк. Ввод строк осуществляется в блоке 5. Рекомендуется вводить строки со смыслом, лучше всего числовые - 1, 2, 3...Imax. В блоке 6 файл закрывается, а затем открывается для проверки, которая организуется в блоке 8 цикла путем построчного вывода блоком 9 Imax строк. В блоке 10 файл опять закрывается, а затем открывается для дополнения, которое осуществляется в блоке 11 цикла путем построчного ввода блоком 12 еще Imax строк в хвост файла. В блоке 13 файл закрывается, а затем открывается для проверки, которая организуется в блоке 15 цикла путем построчного вывода блоком 16 всех Imax*2 строк. Для наблюдения за процессом в алгоритм введены паузы (блоки 7, 14 и 18). Окно работающего приложения задания 1 показано на Рис. 8.2. Листинг программы:
40
program Prg_8_1; {$APPTYPE CONSOLE} uses SysUtils, RusTrans; const FileDir='c:\users\PO_11\Ivanov\08_1\';; var MyFile: text; // Файловая переменная FilePath,FileName,Temp: string; // Переменные для строк i,imax: integer; label Exit; // Метка выхода begin writeln(Rus('Введите имя файла')); readln(FileName); writeln; FilePath:=FileDir+FileName; // Путь к файлу AssignFile(MyFile,FilePath); // Связь файлом на диске {$I-} // Отключить контроль ошибок Rewrite(MyFile); // Создать новый файл {$I+}; // Включить контроль ошибок if IOResult = 0 // Проверить ошибку открытия файла then writeln(Rus('Спасибо')) else begin writeln(Rus('Ошибка')); readln; goto Exit // Выход при ошибке end; writeln; imax:=5; writeln(Rus('Введите '),imax,Rus(' строк')); for i:=1 to imax do // Повторять 5раз begin write(Rus('Строка '),i,' = '); readln(Temp); // Чтение строки с клавиатуры writeln(MyFile,Temp); // Запись этой строки в файл end; CloseFile(MyFile); // Закрыть файл Reset(MyFile); // Открыть его для проверки i:=1; writeln; writeln(Rus('Содержимое файла')); writeln; while not EOF(MyFile) do // Повторять до конца файла begin readln(MyFile,Temp); // Чтение строки из файла writeln(Rus('Строка '),i,' = ',Temp); // Вывод этой строки на дисплей i:=i+1 end; writeln; CloseFile(MyFile); // Закрыть файл {$I-} // Отключить контроль ошибок Append(MyFile); // Открыть файл для добавления строк {$I+}; // Включить контроль ошибок if IOResult = 0 // Проверить ошибку открытия файла then writeln('OK') else begin writeln(Rus('Ошибка')); readln; goto Exit // Выход при ошибке end; writeln; writeln(Rus('Введите еще '),imax,Rus(' строк')); for i:=imax+1 to imax*2 do // Повторять 5 раз
41
begin write(Rus('Строка '),i,' = '); readln(Temp); // Чтение строки с клавиатуры Writeln(MyFile,Temp) // Запись этой строки в файл end; CloseFile(MyFile); // Закрыть файл Reset(MyFile); // Открыть его для проверки i:=1; writeln; writeln(Rus('Содержимое файла')); writeln; while not EOF(MyFile) do // Повторять до конца файла begin readln(MyFile,Temp); // Чтение строки из файла writeln(Rus('Строка '),i,' = ',Temp); // Вывод этой строки на дисплей i:=i+1 end; writeln; writeln('OK'); readln; CloseFile(MyFile); // Закрыть файл Exit:; end.
Рис. 8.2. Окно работающего приложения задания 1 Задание 2 Создать программу демонстрации произвольного доступа к элементам файла. Она заносит в файл последовательно числа в диапазоне от N1 до N2 (целые и положительные). После записи из файла считываются на дисплей все его компоненты с номерами (начиная с 0). Блок-схема алгоритма приведена на рис. 8.3. В блоке 1 пользователь по запросу вводит имя файла на диске (например, E). В блоке 2 из известного имени папки, в которой файл должен быть размещен (константа FileDir в коде программы), и этого имени генерируется путь к файлу, после чего создается файл. Если произошла ошибка, то в блоке 3 программа завершается с сообщением Error - Ошибка. Окно работающего приложения задания 2 показано на Рис. 8.4.
42
Начало
1
Имя файла
2
Путь к файлу Создать файл Да
3
Ошибка? Нет Ожидание Enter
9
Imax=N2-N1
Чтение из файла
10
Запись в файл
Компонента из файла
11
4
Ввод N1, N2
5
6
7
8
Компонента в файл
Закрыть файл. Открыть файл для проверки
Закрыть файл
Ожидание Enter
12
13
Конец рис. 8.3. Блок-схема алгоритма задания 2 В противном случае в блоке 4 пользователь вводит два целых положительных числа N1 и N2. В блоке 5 определяется число компонент Imax = N2-N1, которые надо занести в файл. Блок 6 открывает цикл записи Imax компонент, в теле которого блок 7 выполняет запись в файл чисел в интервале N1..N2. В блоке 8 файл закрывается, а затем открывается для проверки, которая организуется в блоке 10 цикла путем построчного вывода блоком 11 Imax компонент из файла вместе с номерами. В блоке 12 файл закрывается. Для наблюдения за процессом в алгоритм введены паузы (блоки 9 и 13). Листинг программы: program Prg_8_2; {$APPTYPE CONSOLE} uses SysUtils,RusTrans; label Exit; const FileDir='c:\users\PO_11\Ivanov\08_2\';; var MyFile: File of integer; // Файловая переменная FilePath, FileName: string; N1,N2,i,imax,Temp: integer; begin
43
writeln(Rus('Введите имя файла')); readln(FileName); writeln; FilePath:=FileDir+FileName; AssignFile(MyFile,FilePath); // Связь файлом на диске {$I-} // Отключить контроль ошибок Rewrite(MyFile); // Создать новый файл {$I+}; // Включить контроль ошибок if IOResult = 0 // Проверить ошибку открытия файла then writeln(Rus('Спасибо')) else begin writeln(Rus('Ошибка')); readln; goto Exit // Выход при ошибке end; writeln; writeln(Rus('Введите N1, N2')); readln(N1,N2); writeln; imax:=N2-N1; for i:=0 to imax do begin Temp:=N1+i; write(MyFile,Temp) // Записать в файл значение номер i end; CloseFile(MyFile); Reset(MyFile); writeln(Rus('Компоненты файла')); // Открыть файл для проверки for i:=0 to imax do // Цикл чтения begin Seek(MyFile,i); // Указатель файла на элемент i read(MyFile,Temp); // Прочитать элемент writeln(Rus('Компонент '),i,' = ',Temp);// Вывести его на дисплей end; CloseFile(MyFile); writeln; writeln('OK'); readln; Exit:; end.
Рис. 8.4. Окно работающего приложения задания 2
44
Задание 3 Создать программу для высокоскоростного копирования файла-источника в файл-приемник. В качестве файлаисточника использовать результат компиляции Prg_8_1.exe программы задачи 1, созданный ранее. В качестве файлаприемника определить файл с именем Prg_8_1a.exe. После выполнения нужно проверить, что на диске имеется файлприемник того же размера и содержания. Чтобы убедиться в этом, можно этот файл исполнить. Листинг программы: program Prg_8_3; {$APPTYPE CONSOLE} uses SysUtils,RusTrans; label Exit; const FileDir='c:\users\PO_11\Ivanov\08_1\';; FileDir='c:\users\PO_11\Ivanov\08_3\';; var InFile,OutFile: File; // Файловые переменные Buf: array[1..512] of byte; // Буфер FilePath1,FilePath2: string; // Пути к файлам i,j: integer; begin FilePath1:=FileDir1+'prg_8_1.exe'; AssignFile(InFile,FilePath1); // Связь файлом источником на диске FilePath2:=FileDir2+'prg_8_1a.exe'; AssignFile(OutFile,FilePath2); // Связь файлом приемником на диске Reset(InFile,512); // Открыть файд источник Rewrite(OutFile,512); // Создать файл приемник writeln(Rus('Файл источник '),FilePath1); writeln(Rus('Файл приемник '),FilePath2); writeln; writeln(Rus('Копировать файл?')); readln; writeln(Rus('Копирование начато')); writeln; while not EOF(InFile) do begin BlockRead(InFile,Buf,1,i); // Читать блок из InFile в буфер BlockWrite(OutFile,Buf,1,j) // Писать блок из буфера в OutFile end; writeln(Rus('Копирование завершено')); readln; CloseFile(InFile); // Закрыть файл источник CloseFile(OutFile); // Закрыть файл приемник end. Задание 4 Создать программу обмена данными с файлом, использующую связь с файлами без файловых переменных. Она заносит в буфер 6 случайных чисел и переносит их в файл (он создается в папке проекта). Затем буфер обнуляется, и из файла возвращаются первые 4 числа. Окно работающего приложения задания 2 показано на Рис. 8.5. Листинг программы: program Prg_8_4; {$APPTYPE CONSOLE} uses SysUtils,RusTrans; const Count=6; // Константа Count var hMyFile: Integer; // Дескриптор файла Buffer: Array[1..Count] of Byte; // Буфер i, Fact: Integer; begin hMyFile:=FileCreate('MyFile'); // Создать файл writeln(Rus('В буфере случайные числа')); Randomize; for i:=1 to Count do // Заполнить буфер begin
45
Buffer[i]:= Random(100); writeln(' ', Buffer[i]); // Вывод буфера на дисплей end; Fact:=FileWrite(hMyFile, Buffer, Count); // Запись в файл writeln(Rus('В файл записаны '),Fact); readln; writeln(Rus('Буфер очищается')); for i:=1 to Count do begin Buffer[i]:=0; writeln(' ',Buffer[i]); // Вывод буфера на дисплей end; readln; FileSeek(hMyFile, 0, 0); // Установить маркер на начало файла Fact:=FileRead(hMyFile, Buffer, Count-2); // Чтение из файла writeln(Rus('Из файла в буфер прочитаны')); for i:=1 to Count do begin writeln(' ',Buffer[i]); // Вывод буфера на дисплей end; writeln(Rus('В буфере не нулевых чисел '),Fact); FileClose (hMyFile); // Закрыть файл readln; end.
Рис. 8.5. Окно работающего приложения задания 4 Выводы 1. В Delphi определены типизированный, текстовый и нетипизированный файлы. 2. Связь с файлами может быть через файловые переменные или по именам. 3. При применении файловых переменных для связи с файлами на диске используется процедура AssignFile. 4. В типизированном файле возможен произвольный доступ к компоненту с любым номером. 5. В текстовом файле произвольный доступ к символу невозможен. Можно обращаться к строкам текста. 6. Нетипизированные файлы полезны для скоростного копирования.
46
9. Подпрограммы Подготовка к работе 1. По рекомендованной литературе изучить: правила объявления подпрограмм, связь формальных и фактических параметров, способы передачи фактических параметров в подпрограмму, обращение к процедурам и функциям. 2. Разработать алгоритмы и программы решения задач. Контрольные вопросы 1. Что такое подпрограмма? Ее назначение. 2. Правила объявления процедур в программе. 3. Правила объявления функций в программе. 4. Правила обращения к процедуре в программе. 5. Правила обращения к функции в программе. 6. Формальные и фактические параметры. 7. Передача параметров в процедуру с помощью параметров-значений. 8. Передача параметров в процедуру с помощью параметров-переменных. Использование слова var. 9. Передача параметров в процедуру с помощью параметров-констант. Использование слова const. 10. Использование слова out. Задания к работе 1. Создать программу, использующую подпрограмму-функцию. Функция должна возвращать сумму элементов с заданными свойствами в массивах или матрицах. Варианты заданий приведены в Табл. 9.1. Проект – консольное приложение. 2. Создать программу, использующую подпрограмму-процедуру. В этом задании подпрограмма должна возвратить и следы матриц. Проект – консольное приложение. Табл. 9.1. Варианты задания 1 № Что искать Примечание 1 Суммы ненулевых элементов массивов X(n), Y(m). Для массива. 2 Суммы положительных элементов массивов X(n), Y(m). Для массива. 3 Суммы отрицательных элементов массивов X(n), Y(m). Для массива. 4 Суммы элементов массивов X(n), Y(m). имеющих значения в интервале Min…Max. Для массива. 5 Суммы ненулевых элементов матриц X(m,n) и Y(p,q). Для матрицы. 6 Суммы положительных элементов матриц X(m,n) и Y(p,q). Для матрицы. 7 Суммы отрицательных элементов матриц X(m,n) и Y(p,q). Для матрицы. 8 Суммы элементов матриц X(m,n) и Y(p,q), имеющих значения в интервале Min…Max. Для матрицы. 9 Суммы ненулевых элементов каждой строки матрицы X(m,n). Для строки. 10 Суммы положительных элементов каждой строки матрицы X(m,n). Для строки. 11 Суммы отрицательных элементов каждой строки матрицы X(m,n). Для строки. 12 Суммы элементов каждой строки матрицы X(m,n), имеющих значения в интервале Min…Max. Для строки. 13 Суммы ненулевых элементов каждого столбца матрицы X(m,n). Для столбца. 14 Суммы положительных элементов каждого столбца матрицы X(m,n). Для столбца. 15 Суммы отрицательных элементов каждого столбца матрицы X(m,n). Для столбца. 16 Суммы элементов каждого столбца матрицы X(m,n), имеющих значения в интервале Min…Max. Для столбца. Пример выполнения Задание 1 Найти след (сумма элементов главной диагонали) квадратных матрицы A[k,k] и B[n,n], где k, n – размеры матриц. Сделаем это с помощью подпрограммы-функции Sled. В программе пользователь по запросу вводит размеры матриц A и B. Затем матрицы заполняются случайными числами с помощью вложенных циклов и функции Random (возвращает случайные вещественные числа в интервале 0..1). Для контроля ввода матрицы выводятся на экран. Далее последовательно для матриц A и B вызывается функция Sled, и вычисленные значения следов матриц A и B выводятся на экран. Окно работающего приложения показано на Рис. 9.1.
47
Рис. 9.1. Окно приложения задания 1 при исполнении Листинг программы program Prg_9_1; {$APPTYPE CONSOLE} uses SysUtils,RusTrans; const Max=40; // Максимальный размер матриц type Mas=array[1..Max,1..Max] of Real; // Тип для матрицы var i,j,k,n:Integer; A,B:Mas; Sled1,Sled2:Real; function Sled(M:Mas; r:Integer):Real; // Функция var i:Integer; s:Real; begin s:=0; // Обнуление суммы for i:=1 to r do s:=s+M[i,i]; // Накопление суммы Result:=s; end; begin writeln(Rus('Введите размеры матриц не более '),Max); write(Rus(' Первая k=')); // Первая матрица ReadLn(k); write(Rus(' Вторая n=')); // Вторая матрица readln(n); writeln; writeln(Rus('Спасибо. Для продолжения нажмите Enter')); writeln; readln; Randomize; for i:=1 to k do // Формирование матрицы A for j:=1 to k do A[i,j]:=0.5-random; for i:=1 to n do // Формирование матрицы B for j:=1 to n do B[i,j]:=0.5-random; writeln(Rus('Матрицы заполнены случайными числами')); writeln;
48
for i:=1 to k do // Вывод матрицы A begin for j:=1 to k do write(A[i,j]:8:3); writeln; end; writeln; for i:=1 to n do // Вывод матрицы B begin for j:=1 to n do write(B[i,j]:8:3); writeln; end; readln; Sled1:=Sled(A,k); // Вызов функции для первой матрицы Sled2:=Sled(B,n); // Вызов функции для второй матрицы writeln(Rus('Результаты')); // Заголовок ответа writeln; writeln('Sled1= ', Sled1:5:2); // Ответы writeln('Sled2= ', Sled2:5:2); readln; // Ожидание Enter end. Задание 2 Найти сумму всех элементов и след (сумму элементов главной диагонали) квадратных матриц A[k,k] и B[n,n], где k, n – размеры матриц. Сделаем это с помощью подпрограммы-процедуры Sum_Sled. В отличие от задания 1 в подпрограмме вычисляются два значения Sum – сумма и Sled - след. Окно работающего приложения показано на Рис. 9.2.
Рис. 9.2. Окно приложения задания 2 при исполнении Листинг программы: program Prg_9_2; {$APPTYPE CONSOLE} uses SysUtils, RusTrans; const Max=40; // Максимальный размер матриц type Mas=array[1..Max,1..Max] of real; // Тип для матрицы var i,j,k,n:integer; A,B:Mas; Sum1,Sum2,Sled1,Sled2:real;
49
procedure Sum_Sled(var Sum,Sled:real;M:Mas; r:integer); // Процедура var i,j:integer; begin Sum:=0; // Обнуление суммы Sled:=0; // Обнуление следа for i:=1 to r do for j:=1 to r do begin Sum:=Sum+M[i,i]; // Накопление суммы if i=j then Sled:=Sled+M[i,j]; // Накопление следа end; end; begin writeln(Rus('Введите размеры матриц не более '),Max); write(Rus(' Первая k=')); // Первая матрица readLn(k); write(Rus(' Вторая n=')); // Вторая матрица readln(n); writeln; writeln(Rus('Спасибо. Для продолжения нажмите Enter')); writeln; readln; randomize; for i:=1 to k do // Формирование матрицы A for j:=1 to k do A[i,j]:=0.5-random; for i:=1 to n do // Формирование матрицы B for j:=1 to n do B[i,j]:=0.5-random; writeln(Rus('Матрицы заполнены случайными числами')); writeln; for i:=1 to k do // Вывод матрицы A begin for j:=1 to k do write(A[i,j]:8:3); writeln; end; writeln; for i:=1 to n do // Вывод матрицы B begin for j:=1 to n do write(B[i,j]:8:3); writeln; end; readln; Sum_Sled(Sum1,Sled1,A,k); // Вызов процедуры для матрицы A Sum_Sled(Sum2,Sled2,B,n); // Вызов процедуры для матрицы B writeln(Rus('Результаты')); // Заголовок ответа writeln; writeln('Sum1=',Sum1:5:2,' Sled1= ', Sled1:5:2); writeln('Sum2=',Sum2:5:2,' Sled2= ', Sled2:5:2); readln; // Ожидание Enter end. Выводы 1. Для упрощения программ используются подпрограммы. При их многократном использовании код вводится один раз. 2. Доступны два вида подпрограмм – функции и процедуры. Функция возвращает одно значение, процедура – ни одного или несколько. 3. Процедура вызывается по имени (со списком фактических параметров) в строке кода программы. 4. Функция вызывается по имени (со списком фактических параметров) в выражениях. При установленной опции расширенного синтаксиса функцию можно вызывать, как процедуру. При этом значение, возвращаемое функцией, игнорируется. 5. В подпрограмму могут передаваться параметры-значения, параметры-переменные (со словом var, это адреса с возможностью чтения/записи), параметры-константы (со словом const, это адреса с возможностью только чтения), параметры-выходные (со словом out, это адреса с возможностью только записи).
50
10. Динамическая память Подготовка к работе 1. По рекомендуемой литературе изучить: назначение динамической памяти, назначение и свойства указателей, операции с динамическими структурами, фрагментацию данных в динамической памяти. 2. Составить программы решения задач. Контрольные вопросы 1. Что такое динамическая память? 2. Назначение и свойства указателей. 3. Типизированные указатели. 4. Указатель Pointer. 5. Процедура выделения New(p) динамической памяти для типизированных структур. 6. Процедура освобождения Dispose(p) динамической памяти для типизированных структур. 7. Процедура выделения GetMem(p,size) динамической памяти для структур произвольного размера. 8. Процедура освобождения FreeMem(p,size) динамической памяти для структур произвольного размера. Задание к работе 1. Программа демонстрации работы с типизированными динамическими структурами. Создать динамические структуры ds1 и ds2, выполнить над ними операцию op, после чего освободить память для указанных структур в порядке, обратном выделению. Проект – консольное приложение. 2. Программа скоростного копирования файла произвольного размера (файл prg_8_1.exe) из папки 08_01 в папку 10_02 с использованием ДП и процедур GetMem и FreeMem. Варианты заданий представлены в табл. 10.1. табл. 10.1. Варианты заданий № ds1 ds2 op 1 Word Real сложение 2 Real Integer умножение 3 Integer byte вычитание 4 byte Word деление 5 Word Real сложение 6 Real Integer умножение 7 Integer byte вычитание 8 byte Word деление 9 Real Real сложение 10 Integer Integer умножение 11 byte byte вычитание 12 Word Word деление 13 Real Real сложение 14 Integer Integer умножение 15 byte byte вычитание Пример выполнения Задание 1 Создать динамические структуры типов byte и word, выполнить над ними операцию сложения, после чего освободить память для указанных структур в порядке, обратном выделению. Проект – консольное приложение. Окно работающего приложения задания 1 показано на Рис. 10.1. Листинг программы: program Prg_10_1; {$APPTYPE CONSOLE} uses SysUtils,RusTrans; const p1:^Byte=Nil; //Указатели с инициализацией p2:^Word=Nil; var Result:real; begin writeln(Rus('Объект p1')); new(p1); // Выделить ДП под p1 writeln(Rus(' Размер p1='),SizeOf(p1));
51
writeln(Rus(' Размер p1^='),SizeOf(p1^)); writeln(Rus('Объект p2')); new(p2); // Выделить ДП под p2 writeln(Rus(' Размер p2='),SizeOf(p2)); writeln(Rus(' Размер p2^='),SizeOf(p2^)); writeln; writeln(Rus('Введите операнды')); write(' a='); readln(p1^); //Присвоить значение р1 write(' b='); readln(p2^); //Присвоить значение р2 Result:=p1^+p2^; //Операция с р1 и р2} writeln('p1^=',p1^); writeln('p2^=',p2^); writeln(Rus('Результат операции = '),Result:5:2); readln; Dispose(p2); //Освободить ДП под р2 p2:=Nil; Dispose(p1); //Освободить ДП под р1 p1:=Nil; writeln; write('p1='); if p1=Nil then writeln('Nil'); // Указатель p2 пуст write('p2='); if p2=Nil then writeln('Nil'); // Указатель p2 пуст readln; end.
Рис. 10.1. Окно работающего приложения задания 1 Задание 2 Программа скоростного копирования файла произвольного размера (файл prg_8_1.exe) из папки 08_01 в папку 10_02 с использованием ДП и процедур GetMem и FreeMem. Окно работающего приложения задания 2 показано на Рис. 10.2.
Рис. 10.2. Окно работающего приложения задания 2 Листинг программы:
52
program Prg_10_2; {$APPTYPE CONSOLE} uses SysUtils,RusTrans; const FileDir1='c:\users\PO_11\Ivanov\08_1\'; FileDir2='c:\users\PO_11\Ivanov\10_2\'; var InFile,OutFile:file; // Файловые переменные FilePath1,FilePath2:string; // Пути к файлам Size:Integer; // Число записей Buffer:PChar; // Буфер в ДП begin FilePath1:=FileDir1+'prg_8_1.exe'; // Путь к файлу источнику AssignFile(InFile,FilePath1); // Связь с файлом источником InFile FilePath2:=FileDir2+'prg_8_1a.exe'; // Путь к файлу приемнику AssignFile(OutFile,FilePath2); // Связь с файлом приемником OutFile Reset(InFile); // Открыть InFile Rewrite(OutFile); // Создать OutFile Size:=FileSize(InFile); // Число записей (по 128 байт) в InFile writeln(Rus('Размер входного файла = '),Size); GetMem(Buffer,Size*128); // Выделить в ДП Buffer (в байтах) writeln(Rus('Размер буфера = '),SizeOf(Buffer), Rus(' блока по 128 байт')); readln; BlockRead(InFile,Buffer^,Size); // Копирование из Infile в Buffer BlockWrite(OutFile,Buffer^,Size); // Копирование из Buffer в OutFile writeln(Rus('Копирование завершено')); writeln(Rus('Размер выходного файла = '),FileSize(OutFile)); readln; FreeMem(Buffer); // Освободить Buffer Buffer:=Nil; // Сделать Buffer пустым Write(Rus('Буфер=')); if Buffer=Nil then writeln('Nil') else writeln(Rus('Ошибка')); CloseFile(InFile); // Закрыть файлы CloseFile(OutFile); readln; // Пауза end. Внимание: Size – размер выделяемой памяти в записях (по умолчанию это 128 байт). Для пары процедур GetMem, FreeMem имя указателя и размер памяти должны быть одинаковы. Удалять нужно точно те байты, которые выделялись. В процедуре FreeMem размер можно пропустить, по умолчанию он будет таким же, как в процедуре GetMem. Выводы 1. В программах применяются переменные: статические, под которые память выделяется при компоновке на все время работы программы; динамические, под которые память выделяется в процессе работы на время надобности в них. 2. Динамические структуры обеспечивают экономное использование памяти, особенно когда переменных много и они не всегда нужны. 3. Динамические структуры заданного типа (размера) создаются с использованием типизированных указателей p процедурой New(p), а освобождаются процедурой Dispose(p). В указатель заносится адрес первого байта выделяемой памяти, число байт определяется типом данных. 4. Динамические структуры произвольного размера создаются c использованием указателей p процедурой GetMem(p, Size), а освобождаются процедурой FreeMem(p, Size). В указатель заносится адрес первого байта выделяемой памяти, число байт определяется значением Size (фактически это Size*128). 5. После освобождения памяти рекомендуется сделать указатель неопределенным, присвоив ему значение Nil.
53
11. Исключения Подготовка к работе 1. По рекомендованной литературе изучить класс исключений и их обработку. 2. Разработать алгоритмы решения задач. 3. Составить программы решения задач. Контрольные вопросы 1. Что такое исключение? 2. Классы исключений и их свойства. 3. Оператор try…except. Назначение, структура и применение. 4. Оператор try…finally. Назначение, структура и применение. 5. Глобальные и локальные обработчики исключений. 6. Обработчик исключения on…do. 7. Исключение EZeroDivide. 8. Исключение ERangeError. 9. Как включить отработку исключения ERangeError. 10. Как отключить перехват исключения системой. Задание к работе 1. Создать программу, обрабатывающую исключения с использованием оператора try… except. Проект – консольное приложение. 2. Создать программу, обрабатывающую исключение с использованием оператора try… finally. Проект – консольное приложение. В заданиях надо рассчитывать функции f1(x) и f2(x) при x = i*h. i - индекс цикла (целые числа в интервале -10...10). Шаг изменения h. Варианты заданий приведены в табл. 11.1. табл. 11.1. Варианты заданий Функция 1 Функция 2 № f1(x) h1 тип f2(x) h2 тип 1 1/x real 200+x 10 byte π/5 2 1/sin(x) single (300+x)*50 100 word π/5 3 1/cos(x) extended 300+x 10 shortint π/5 4 tg(x) real (200+x)*200 10 smallint π/5 5 ctg(x) single 100+x 15 byte π/5 6 1+1/x extended (300-x)*50 20 word π/10 7 2+1/sin(x) real 50+x 30 shortint π/10 8 3+1/cos(x) single 200+x 10 smallint π/10 9 4+tg(x) extended 250+x 50 byte π/10 10 5+ctg(x) real 200-x 30 word π/10 11 1-1/x single 200+x 10 shortint π/20 12 2-1/sin(x) extended (200+x)*200 10 smallint π/20 13 3-1/cos(x) real 400+x 100 byte π/20 14 4- tg(x) single 200+x 10 word π/20 15 5-ctg(x) extended 100-x 30 shortint π/20 Необходимо отслеживать два исключения: Деление на 0 (исключение EZeroDivide). Выход за пределы диапазона (исключение ERangeError). Внимание: Встроенный отладчик Delphi перехватывает все исключительные ситуации и формирует свои сообщения о них в диалоговом окне, которое пользователь перед продолжением программы должен закрыть. Чтобы избежать этого, следует отменить использование отладчика, сбросив флаг «Встроенный отладчик» в окне команды Сервис=>Опции отладчика. Чтобы отслеживать исключения в операциях с числами, необходимо в окне команды Проект=>Опции... на вкладке «Компилятор» установить флаги директив компилятора: Проверка области. Проверка ввода/вывода. Проверка переполнения. При работе с программой рекомендуется менять h1 и h2, чтобы получать разные результаты и условия возможного возникновения исключений.
54
Пример выполнения Вариант задания: f1(x) = 1/sin(x), h1 = π/6, тип данных для f1(x) Real. f2(x) =100+x, h2 = 4, тип данных для f2(x) Byte Задание 1 Создать программу обработки исключений, использующую оператор try…except. Проект – консольное приложение. Окно работающего приложения задания 1 показано на Рис. 11.1 для трех вариантов: исключений нет, ошибка деления на 0, ошибка диапазона.
Рис. 11.1. Окно работающего приложения задания 1 Листинг программы program Prg_11_1; {$APPTYPE CONSOLE} uses SysUtils,RusTrans; const h1=pi/8; h2=20; var f:boolean=false; i,imax,imin,i_error:integer; y:array[-10..10] of real; b:array[-10..10] of byte; begin writeln(Rus('Введите Imin и Imax в пределах -10...10')); write(' Imin='); readln(imin); write(' Imax='); readln(imax); try for i:=imin to imax do begin i_error:=i; // i, если ошибка y[i]:=1/sin(i*h1); end; for i:=imin to imax do
55
begin i_error:=i; // i, если ошибка b[i]:=100+i*h2; end; except on EZeroDivide do begin writeln(Rus('Деление на 0')); writeln(Rus('при i='),i_error); f:=true; end; on ERangeError do begin writeln(Rus('Ошибка диапазона')); writeln(Rus('при i='),i_error); f:=true; end; end; if not f then writeln('OK'); readln; end. Задание 2 Создать программу обработки исключений, использующую оператор try…finally. Проект – консольное приложение. Листинг программы program Prg_11_2; {$APPTYPE CONSOLE} uses SysUtils,RusTrans; const h1=pi/6; //шаг для f1 h2=40; //шаг для f2 var f:boolean=false; //флаг ошибки i,Imin,Imax,i_error,dy:integer; s:string; y:array[-10..10] of real; b:array[-10..10] of byte; begin writeln(Rus('Введите Imin и Imax в пределах -10...10')); write(' Imin='); readln(imin); write(' Imax='); readln(imax); try //Секция Try for i:=Imin to Imax do //Начало оператора 1 begin i_error:=i; // i, если ошибка if sin(i*h1)=0 then begin f:=true; //Установить флаг ошибки writeLn(Rus('Деление на 0')); //Вывод сообщения об ошибке writeln(Rus('при i='),i_error); end else f:=false; y[i]:=1/sin(i*h1); end; for i:=Imin to Imax do //начало оператора 2 begin i_error:=i; //i, если ошибка dy:=i*h2; if (dy<-30) or (dy>225) then begin
56
f:=true; //Установить флаг ошибки writeLn(Rus('Ошибка диапазона')); //Вывод сообщения об ошибке writeln(Rus('при i='),i_error); end else f:=false; b[i]:=30+i*h2; end; finally //Секция Finally if not f then writeln('OK'); //OK, если ошибок нет end; //Конец Try...Finally readln; //Пауза end. Окно работающего приложения задания 2 в целом совпадает с окном задания 1. Однако оператор try…finally не обрабатывает исключение. Поэтому при возникновении ошибки срабатывает системный обработчик исключения и выдает свое сообщение, показанное на Рис. 11.2.
Рис. 11.2. Сообщение системного обработчика исключений в задании 2 Выводы 1. При исполнении программ возможны исключения (ситуации с ошибками). Примеры исключений - деление на ноль EZeroDivide, выход значений за пределы допустимого диапазона ERangeError. 2. Встроенный отладчик Delphi перехватывает все исключительные ситуации и формирует свои сообщения о них в диалоговом окне, которое пользователь перед продолжением программы должен закрыть. Чтобы избежать этого, следует отменить использование отладчика, сбросив флаг «Встроенный отладчик» в окне команды Сервис=>Опции отладчика. 3. Чтобы отслеживать исключения в операциях с числами, необходимо в окне команды Проект=>Опции... на вкладке «Компилятор» установить флаги директив компилятора: Проверка области, Проверка ввода/вывода, Проверка переполнения. 4. Для обработки исключений используются обработчики исключений (глобальные и локальные). Глобальные обработчики определены в ИСР и вызываются автоматически, если отладчик подключен. Локальные обработчики создает пользователь. 5. Для локальной обработки исключений определен оператор try…except…end. В секции try размещаются операторы, в которых могут возникнуть исключения, а в секции except обработчики исключений. При обнаружении исключения исполнение операторов секции try прекращается, управление передается нужному обработчику в секции except. 6. Обработчик исключения имеет формат on <исключение> do <оператор> end. 7. Для обнаружения исключений определен оператор try…finally. В секции try размещаются операторы, в которых могут возникнуть исключения, а в секции finally операторы, исполняемые всегда. При возникновении исключения исполнение операторов секции try прекращается, управление передается первому оператору секции finally. После исполнения секции finally в случае ошибки появиться сообщение системного обработчика исключений.
57
12. Списки Подготовка к работе По указанной литературе изучить определенные в ИСР Delphi списки и основные команды, используемые для работы с ними. Контрольные вопросы 1. Списки, их назначение. 2. Компоненты списков ListBox (список) и ComboBox (комбинированный список) в ИСР Delphi. Их назначение и сравнение. 3. Создание в форме компонентов списков. 4. Свойства Count (количество) и Capacity (емкость) компонент списков. 5. Свойства Items (элементы) и ItemIndex (номер элемента) компонент списков. Нумерация элементов списков. 6. Предварительное редактирование списков. 7. Свойство Text (текст) компонента ComboBox. 8. Программное редактирование строк компонентов списков.. 9. Метод добавить элемент Add(Item) и его использование. 10. Метод ввести элемент Insert(Index,Item) и его использование. 11. Метод удалить элемент Delete(Index) и его использование. 12. Метод очистки Clear и его использование. 13. Метод поменять элементы Exchange(Index1, Index2) и его использование. 14. Метод переместить элемент Index1 в позицию Index2 Move(Index11, Index2) и его использование. Задание 1. Активизировать ИСР. 2. Создать пустую форму проекта и задать ее свойства. 3. Заполнить форму компонентами в соответствии с заданием. 4. Посмотреть текст модуля формы в редакторе кода. 5. Написать коды обработчиков событий. 6. Отладить проект. 7. Сохранить проект на локальной машине. 8. Выход из ИСР. 9. Скопировать проект на сервер. Пример выполнения Задание Создать проект работы со списками. В проекте предусмотреть: 1. Заполнение комбинированного списка из поля ввода. 2. Редактирование комбинированного списка (ввести строку, переместить строку). 3. Копирование строк из списка ComboBox в список ListBox, Рекомендуемая форма программы приведена на рис. 12.1.
рис. 12.1. Форма программы
58
Форма содержит следующие компоненты: ListBox1 - простой список. Label1 – метка для заголовка компонента ListBox1. ComboBox1 - комбинированный список. Label2 – метка для заголовка компонента ComboBox1. Edit1- однострочный редактор для ввода текста. В него вводится текст строки для списка. Label3 – метка для заголовка редактора Edit1. Button1– кнопка "Инициализация". Позволяет очистить поле Edit1 и установить там курсор. Button2 – кнопка "Принять в ComboBox" для заполнения компонента ComboBox1. Button3 – кнопка "Редактировать ComboBox". Позволяет вводить, удалять, взаимозаменять и перемещать строки в списке. Button4 – кнопка "Копировать в ListBox". Позволяет скопировать в ListBox строки, выбираемые в ComboBox. Выполнение 1. Активизируем ИСР, выбрав Delphi в проводнике Windows. Экран имеет вид, показанный на рис. 12.2. По умолчанию выводится пустая форма, которую нужно заполнить компонентами. В окне Дерева объектов отображен компонент Форма с именем Form1 по умолчанию.
рис. 12.2. Экран после старта ИСР Delphi Задание свойств формы. Выбираем объект Form1 и подбираем его размеры и положение. В окне Инспектора объектов назначаем свойства формы: Свойство Значение English Перевод English Русское Name Имя Prg_12_1 Caption Надпись Prg_12_1 Программирование_ Номер_Задание Position Положение poScreenCenter В центре экрана У формы меняется заголовок Form1=> Prg_12_1. 2.
3.
Заполнение формы При заполнении формы в палитре компонент выбирается нужный блок и переносится в форму. Там подбираются его положение и размеры. Затем в окне Инспектора объектов назначаются свойства компонента. Большая часть свойств устанавливается автоматически, их редактировать не следует. Нужные нам компоненты размещаются в палитре компонент на странице Standard. Для кнопок необходимо добавить функциональность, написав код обработчика события нажатия. При двойном щелчке по кнопке ИСР автоматически объявляет подпрограмму обработчика. В код модуля формы проекта заносятся: 1. В поля объекта заголовок обработчика. Заголовок обработчика формируется автоматически. Его имя содержит записанные без пробелов имя компонента и события с префиксом on, которое отрабатывается. 2. В раздел реализации шаблон обработчика. Он имеет заголовок, совпадающий с заголовком в поле объекта с добавлением имени формы в начале заголовка. В него между операторными скобками begin…end надо внести текст подпрограммы обработки события. Для некоторых обработчиков могут потребоваться и локальные переменные.
59
Листинг модуля формы: unit Prg_12_1_; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TPrg_12_1 = class(TForm) ListBox1: TListBox; ComboBox1: TComboBox; Button1: TButton; Edit1: TEdit; Button2: TButton; Label1: TLabel; Label2: TLabel; Label3: TLabel; Button3: TButton; Button4: TButton; procedure Button1Click(Sender: procedure Button2Click(Sender: procedure Button3Click(Sender: procedure Button4Click(Sender: private { Private declarations } public { Public declarations } end;
TObject); TObject); TObject); TObject);
var Prg_12__1: TPrg_12__1; implementation {$R *.dfm} procedure TPrg_12_1.Button1Click(Sender: TObject); begin Edit1.Text:=''; Edit1.SetFocus; end; procedure TPrg_12_1.Button2Click(Sender: TObject); begin ComboBox1.Items.Add(Edit1.Text); Edit1.Text:=''; Edit1.SetFocus; end; procedure TPrg_12_1.Button3Click(Sender: TObject); begin ComboBox1.Items.Insert(comboBox1.ItemIndex,Edit1.Text); Edit1.Text:=''; Edit1.SetFocus; end; procedure TPrg_12_1.Button4Click(Sender: TObject); begin ListBox1.Items.Add(ComboBox1.Items[ComboBox1.ItemIndex]); end;
60
end. После заполнения панелей компонентами форма примет вид рис. 12.1. Окно Дерево объектов приобретает вид, показанный на рис. 12.3. Проверьте по нему правильность введенных компонент, их имена и иерархию.
рис. 12.3 Дерево объектов после заполнения формы компонентами Сохраним проект в папке с именем 12_1. Для этого вызовем команду Файл => Сохранить Проект Как, которая приводит к появлению диалогового окна. В нем нужно попасть в нужную папку и сохранить проект. При сохранении проекта приложения необходимо сохранять проект (с именем Prg_12_1) и модуль формы (с именем Prg_12_1_). 5. Проверим программу в работе. Запускаем программу командой Выполнить. Возникает окно приложения. Инициализация. Кнопкой Инициализация очищаем Edit1 и передаем ему фокус ввода. Курсор появляется в поле ввода Edit1. Заполнение списка ComboBox. Для каждой строки в редакторе Edit1 заносим текст, кнопкой Принять в ComboBox переносим его в список. Повторяем операцию нужное число раз. Каждый раз проверяем список ComboBox, убеждаясь в появлении новой строки в конце. Редактирование. В редакторе Edit1 заносим строку текста для ввода в произвольно выбираемую позицию. В ComboBox выделяем позицию для ввода, ее текст перемещается в верхнюю строку редактирования. Копирование. В ComboBox выделяем позицию для копирования, ее текст перемещается в верхнюю строку редактирования. Кнопкой Копировать в ListBox переносим строку в ListBox. Каждый раз наблюдаем ListBox, чтобы убедится в появлении там новой строки в очередной позиции. Выводы 1. Списки используются для выбора элементов из большого набора. 2. В ИСР Delphi определены несколько компонент списков: ListBox - простой список строк текста для выбора без редактирования. ComboBox - комбинированный список строк текста с возможностью выбора и редактирования. ComboBoxEx - расширенный комбинированный список строк с отображением в строках текста и значков. 3. Все списки содержат массив строк текста, для которых применяются свойства: Items(Index) - массив строк текста с номером Index. Нумерация с 0. ItemIdent - номер выделенного элемента. Count - число элементов в списке. Capacity - максимальное число элементов в списке. 4. Для работы со списками доступны методы: Add - добавляет элемент в конец списка. Insert(Index,Item) - добавляет элемент Item в позицию с номером Index. Список переиндексируется. Delete (Index) - удаляет элемент с номером Index. Список переиндексируется. Clear - очищает список. Делает Count=0, Capacity=0. Exchange(Index1, Index2) - меняет местами элементы с номерами Index1 и Index2. Move(CurIndex, NewIndex) - перемещает элемент из текущей позиции CurIndex в новую позицию NewIndex. 5. Список ComboBox может отображаться в полной и краткой формах. В первом случае отображаются строка редактирования и список для выбора. Во втором случае список выбора выпадающий, отображается по требованию. 4.
61
13. Модули Подготовка к работе 1. По рекомендованной литературе изучить назначение и использование модулей и DLL (Dynamic Linked Library = динамически связываемая библиотека); 2. Разработать алгоритмы решения задач. 3. Составить программы решения задач. Контрольные вопросы 1. Что такое модуль? Его назначение и создание. 2. Структура модуля. 3. Назначение и содержание секций Interface, Implementation, Initialization, Finalization. 4. Связывание модуля с вызывающей программой. 5. Что такое DLL? Ее назначение и создание. 6. Структура DLL. 7. Экспортируемые и внутренние подпрограммы DLL. 8. Назначение и содержание списка Exports. 9. Связывание DLL с вызывающей программой. 10. Способы вызова подпрограмм из DLL. Задание к работе 1. Создать вызывающую программу, использующую модуль комплексной арифметики Complex, содержащий 4 функции: сложение, вычитание, умножение и деление. Вызывающая программа должна выполнить функцию 1 с комплексными операндами Comp1=a + i*b и Comp2=c + i*d b и функцию деления Comp1 на ноль. Варианты заданий в табл. 13.1. Проект – приложение. 2. Повторить задание 1, реализовав модуль в виде DLL Complex2. Проект – приложение. табл. 13.1. Варианты заданий № a b c d Функция 1 1 1 2 3 4 Сложение 2 5 6 7 8 Вычитание 3 9 10 11 12 Умножение 4 4 1 2 3 Сложение 5 8 5 6 7 Вычитание 6 12 9 10 11 Умножение 7 3 8 1 2 Сложение 8 7 14 5 6 Вычитание 9 11 12 9 10 Умножение 10 2 3 4 1 Сложение 11 6 7 8 5 Вычитание 12 10 11 12 9 Умножение 13 4 1 3 12 Сложение 14 8 5 7 10 Вычитание 15 12 9 11 68 Умножение Пример выполнения Задание 1 Создать вызывающую программу, использующую модуль комплексной арифметики Complex, содержащий 4 функции: сложение, вычитание, умножение и деление. Вызывающая программа должна выполнить функцию сложения с комплексными операндами Comp1=6 + i*8 и Comp2=7 + i*11 функцию деления Op1 на ноль. 1. Командой File=>New вызываем окно архива и выбираем в нем Unit (модуль без формы). Получаем в окне Редактора кода страницу шаблона модуля с именем Unit1. 2. В редакторе кода заносим код модуля. Секции Initialization и Finalization не используем. 3. Сохраним модуль с именем Complex.Pas. 4. Компилируем модуль. 5. Командой Файл => Создать => Приложение создаем проект вызывающей программы. Форма приложения приведена на рис. 13.1.
62
рис. 13.1. Форма вызывающей программы Форма содержит: Метки Label1…Label6 для отображения поясняющих надписей. Однострочные редакторы Edit1…Edit4 для ввода значений переменных a, b, c, d. Многострочный редактор Memo1 для вывода результатов. Кнопки BitBtn1…BitBtn4 с именами Ввод, Выполнить, Очистить, Закрыть. Кнопка Ввод принимает значения введенных переменных, Копка Выполнить осуществляет вычисления и выводит результаты. Кнопка Очистить удаляет содержимое поля результатов, Кнопка Закрыть завершает работу программы (дублирует стандартную кнопку закрытия окна Windows). 6. В коде модуля формы вызывающей программы добавляем: В строку uses ссылку на модуль Complex. В раздел var переменные a,b,c,d типа real и Comp1, Comp2, Comp3 типа TComplex. 7. Создаем обработчики нажатия кнопок. 8. Сохраняем проект под именем Prg_13_1. Листинг модуля Complex: unit Complex; interface type TComplex = Record Re, Im: Real end; function AddC(x,y: TComplex):TComplex; function SubC(x,y: TComplex):TComplex; function MultC(x,y: TComplex):TComplex; function DivC(x,y: TComplex):TComplex; implementation function AddC(x,y: TComplex):TComplex; begin Result.Re:=x.Re + y.Re; Result.Im:=x.Im + y.Im; end; //AddC function SubC(x,y: TComplex):TComplex; begin Result.Re:=x.Re - y.Re; Result.Im:=x.Im - y.Im; end; //SubC function MultC(x,y: TComplex):TComplex; begin Result.Re:=x.Re*y.Re - x.Im*y.Im; Result.Im:=x.Re*y.Im + x.Im*y.Re;
// Комплексная арифметика // Тип комплексного числа // // // //
Комплексное Комплексное Комплексное Комплексное
сложение вычитание умножение деление
63
end; {MultC} function DivC(x,y: TComplex):TComplex; var z: Real; begin z:=sqr(y.Re)+sqr(y.Im); try //Защита при делении на 0 Result.Re:=(x.Re*y.Re + x.Im*y.Im)/z; Result.Im:=(x.Re*y.Im - x.Im*y.Re)/z; except // Если делитель 0, то. Result.Re:=1.1e309; Result.Im:=1.1e309 end; end; {DivC} end. Листинг модуля формы вызывающей программы: unit Prg_13_1_; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Buttons, ExtCtrls, Complex; type TForm1 = class(TForm) bbRun: TBitBtn; // Кнопка Выполнить bbClose: TBitBtn; // Кнопка Закрыть bbVvod: TBitBtn; // Кнопка Ввод bbClear: TBitBtn; // Кнопка Очистить Edit1: TEdit; // для a Edit2: TEdit; // для b Edit3: TEdit; // для c Edit4: TEdit; // для d Label1: TLabel; // Введите значения переменных Label2: TLabel; // a = Label3: TLabel; // b = Label4: TLabel; // c = Label5: TLabel; // d = Label6: TLabel; // Результаты Memo1: TMemo; procedure bbRunClick(Sender: TObject); procedure bbVvodClick(Sender: TObject); procedure bbClearClick(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; a,b,c,d: real; Comp1, Comp2, Comp3:TComplex; implementation {$R *.DFM} procedure TForm1.bbRunClick(Sender: TObject); begin Comp1.Re:=a; Comp1.Im:=b; Comp2.Re:=c; Comp2.Im:=d; Comp3:=AddC(Comp1,Comp2); memo1.Lines.Add('Исходные данные'); memo1.Lines.Add('Comp1='+FloatToStr(Comp1.Re)+’+i*'+FloatToStr(Comp1.Im)); memo1.Lines.Add('Comp2='+FloatToStr(Comp2.Re)+'+i*'+FloatToStr(Comp2.Im)); memo1.Lines.Add(''); memo1.Lines.Add('Результат комплексной операции’); memo1.Lines.Add('Comp3='+FloatToStr(Comp3.Re)+'+i*'+FloatToStr(Comp3.Im)); end;
64
procedure TForm1.bbVvodClick(Sender: TObject); begin a:=StrToFloat(Edit1.Text); b:=StrToFloat(Edit2.Text); c:=StrToFloat(Edit3.Text); d:=StrToFloat(Edit4.Text); end; procedure TForm1.bbClearClick(Sender: TObject); begin memo1.Clear; end; end. Задание 2 Повторить задание 1, реализовав модуль в виде DLL Complex2. Проект – приложение. 1. Командой Файл => Создать => Еще вызываем окно архива и выбираем в нем DLL. Получаем в окне Редактора кода страницу шаблона DLL с именем Project1. 2. В редакторе кода заносим в нее код DLL. Подпрограммы те же, что в модуле Complex задания 1. Секция begin…end – пустая. 3. Сохраним DLL с именем Complex2.Pas. 4. Компилируем DLL. Итог Complex2.dll. 5. Так как DLL не экспортирует типов, то создаем вспомогательный модуль Complex1, содержащий только интерфейсную часть с описанием типа TComplex и имен вызываемых подпрограмм DLL. Сохраняем его под именем Complex1. 6. Командой Файл => Создать => Приложение создаем проект вызывающей программы. Форму делаем аналогичной заданию 1. 7. В коде модуля формы вызывающей программы добавляем: В строку uses ссылку на модуль Complex1. В раздел var переменные a, b, c, d типа real, Comp1, Comp2, Comp3 типа TComplex. 8. Создаем обработчики нажатия кнопок. 9. Сохраняем проект под именем Prg_11_2. Листинг DLL Complex2 library Complex2; uses SysUtils, Classes; {$R *.RES} type TComplex = record Re, Im: real end; function CAdd(x,y:TComplex):TComplex; export; begin Result.Re:=x.Re + y.Re; Result.Im:=x.Im + y.Im; end; // CAdd function CSub(x,y:TComplex):TComplex; export; begin Result.Re:=x.Re - y.Re; Result.Im:=x.Im - y.Im; end; // CSub function CMult(x,y:TComplex):TComplex; Export; begin Result.Re:=x.Re*y.Re - x.Im*y.Im; Result.Im:=x.Re*y.Im + x.Im*y.Re; end; // CMult function CDiv(x,y:TComplex):TComplex; Export; var z: real; begin z:=sqr(y.Re)+sqr(y.Im); try Result.Re:=(x.Re*y.Re + x.Im*y.Im)/z;
// Комплексная арифметика
// Тип комплексного числа // Комплексное сложение
// Комплексное вычитание
// Комплексное умножение
// Комплексное деление
//Защита при делении на 0
65
Result.Im:=(x.Re*y.Im - x.Im*y.Re)/z; except Result.Re:=1.1e309; Result.Im:=1.1e309 end; end; // СDiv exports CAdd Index 1 Name 'AddC' Resident, CSub Index 2 Name 'SubC', CMult Index 3 Name 'MultC', CDiv Index 4 Name ‘DivC’; begin end.
// Результат, если делитель 0
// Список экспорта
Листинг модуля Complex1 unit Complex1; interface type TComplex=record // Тип комплексного числа Re, Im: real end; // Вызываемые функции function AddC(x,y:TComplex):TComplex; External 'Complex2' Index 1; function SubC(x,y:TComplex):TComplex; External 'Complex2' Index 2; function MultC(x,y:TComplex):TComplex; External 'Complex2' Index 3; function DivC(x,y:TComplex):TComplex; External 'Complex2' Index 4; implementation end. Листинг модуля формы вызывающей программы такой же, как в задании 1, только в строке uses добавлена ссылка на модуль Complex1. В этом модуле устанавливается связь с DLL. Выводы 1. Для работы с часто используемыми подпрограммами применяются модули и DLL 2. Модуль или DLL - это набор готовых подпрограмм, хранящихся в компилированном виде. 3. Модуль связывается с вызывающей программой при компоновке. 4. DLL связывается с вызывающей программой динамически: DLL загружается на время обращения к ее подпрограммам. 5. Одна и та же DLL может использоваться несколькими параллельно работающими программами.
66
14. Таблицы Подготовка к работе По указанной литературе изучить: 1. Cвойства компонентов Label, Button, Edit, StringGrid. 2. Cобытия onClick, onChange, onCreate. 3. Как создать код обработчика события. Контрольные вопросы 1. События onClick, onCreate. 2. Назначение и свойства компонента кнопка. 3. Назначение и свойства компонент метка. 4. Назначение и свойства компонента однострочный редактор. 5. Назначение и свойства компонента StringGrid. 6. Как инициализировать таблицу при старте приложения. 7. Как создать обработчик события onClick. 8. Как создать обработчик события onDblClick. 9. Как создать обработчик события onChange. 10. Как использовать строковые данные для вычислений. 11. Как увеличить число строк в таблице. 12. Как уменьшить число строк в таблице. 13. Как увеличить число столбцов в таблице. 14. Как увеличить число столбцов в таблице. 15. Подпрограммы. Основные понятия. Задание Создать проект “Таблица конвертации” для конвертации рублей России в разные валюты с учетом комиссии. В таблице предусмотреть возможность редактирования содержимого ячеек, добавления и удаления строк и столбцов. Варианты заданий приведены в табл. 14.1. табл. 14.1. Варианты заданий № 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Доллар США Фунт стерлингов Евро Японская йена Рубль Беларуси Гривна Украины Доллар США Фунт стерлингов Евро Японская йена Рубль Беларуси Гривна Украины Доллар США Фунт стерлингов Евро
Валюты Фунт стерлингов Евро Японская йена Рубль Беларуси Гривна Украины Фунт стерлингов Японская йена Японская йена Рубль Беларуси Гривна Украины Фунт стерлингов Евро Японская йена Рубль Беларуси Гривна Украины
Евро Рубль Беларуси Гривна Украины Японская йена Доллар США Доллар США Фунт стерлингов Евро Японская йена Рубль Беларуси Гривна Украины Японская йена Рубль Беларуси Гривна Украины Фунт стерлингов
Пример выполнения Задание Создать проект “Таблица конвертации” для конвертации с учетом комиссии рублей России в валюты США, Великобритании и Европейского союза. Выполнение 1. Запустить Delphi. 2. Создать в ней новое приложение. 3. Присвоить свойству Caption компонента Form1 значение Пересчет денежных сумм. 4. Сохранить модуль под именем Prg_14_1_, а проект под именем Prg_14_1. 5. Установить на форме компоненты: однострочные редакторы Edit1 и Edit2, метки Label1 - Label4, кнопки Button1- Button7 (со страницы Standard), таблицу строк StringGrid1 (со страницы Additional). Компоненты расположить, как показано на рис. 14.1. 6. Задать следующие свойства компонент: Компонент Caption (Надпись) Name (Имя) Описание функций
67 StringGrid1 Edit1 Edit2 Label1 Label2 Label3 Label4 Button1 Button2 Button3 Button4 Button5 Button6 Button7
Редактор ячеек Сумма для конвертации Таблица LbDate OK Принято Выход < > /\ \/
StringGrid1 EdCell EdSum Label1 Label2 Label3 Label4 SellAgree SumAgree Exit DecCol IncCol DecRow IncRow
Основная таблица Редактирование ячейки Редактирование суммы Поясняющая надпись Поясняющая надпись Заголовок Текущая дата Принятие изменений текущей ячейки Принятие суммы и расчет по курсу Выход из приложения Уменьшение числа столбцов на 1 Увеличение числа столбцов на 1 Уменьшение числа строк на 1 Увеличение числа строк на 1
StringGrid1
рис. 14.1. Заготовка интерфейса проекта "Таблица" После вышеперечисленных установок интерфейс проекта примет вид рис. 14.2.
рис. 14.2. Интерфейс проекта в режиме конструирования
68 7. Листинг модуля формы проекта: unit Prg_14_1_; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Grids; type TForm1 = class(TForm) StringGrid1: TStringGrid; EdCell: TEdit; EdSum: TEdit; SellAgree: TButton; SummAgree: TButton; Exit: TButton; DecCol: TButton; IncCol: TButton; DecRow: TButton; IncRow: TButton; Label1: TLabel; Label2: TLabel; Label3: TLabel; Label4: TLabel; procedure FormCreate(Sender: TObject); procedure DecColClick(Sender: TObject); procedure IncColClick(Sender: TObject); procedure DecRowClick(Sender: TObject); procedure IncRowClick(Sender: TObject); procedure ExitClick(Sender: TObject); procedure SellAgreeClick(Sender: TObject); procedure StringGrid1DblClick(Sender: TObject); procedure SummAgreeClick(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.DFM} procedure TForm1.FormCreate(Sender: TObject); begin StringGrid1.ColCount:=6; StringGrid1.RowCount:=4; StringGrid1.Cells[0,0]:='Валюта'; StringGrid1.Cells[1,0]:='Курс рубля; StringGrid1.DefaultColWidth:=78; StringGrid1.Cells[2,0]:='Сумма выдачи'; StringGrid1.Cells[3,0]:='Комиссия, %'; StringGrid1.Cells[4,0]:='Комиссионные'; StringGrid1.Cells[5,0]:='Взнос, руб.'; StringGrid1.Cells[0,1]:='USA'; StringGrid1.Cells[0,2]:='FST'; StringGrid1.Cells[0,3]:='EUR'; StringGrid1.cells[1,1]:='31,5'; StringGrid1.cells[1,2]:='45'; StringGrid1.cells[1,3]:='32,1'; StringGrid1.cells[3,1]:='2'; StringGrid1.cells[3,2]:='2'; StringGrid1.cells[3,3]:='2'; Label4.Caption:='По состоянию на '+DateToStr(Date); end;
69 procedure TForm1.DecColClick(Sender: TObject); begin if StringGrid1.ColCount>2 then StringGrid1.ColCount:=StringGrid1.ColCount-1; end; procedure TForm1.IncColClick(Sender: TObject); begin StringGrid1.ColCount:=StringGrid1.ColCount+1; end; procedure TForm1.DecRowClick(Sender: TObject); begin if StringGrid1.RowCount>2 then StringGrid1.RowCount:=StringGrid1.RowCount-1; end; procedure TForm1.IncRowClick(Sender: TObject); begin StringGrid1.RowCount:=StringGrid1.RowCount+1; end; procedure TForm1.ExitClick(Sender: TObject); begin Close; end; procedure TForm1.SellAgreeClick(Sender: TObject); begin StringGrid1.Cells[StringGrid1.Col,StringGrid1.Row]:=EdCell.Text; end; procedure TForm1.StringGrid1DblClick(Sender: TObject); begin if (StringGrid1.Col=1) and (StringGrid1.Row>0) then EdCell.Text:=StringGrid1.Cells[StringGrid1.Col,StringGrid1.Row]; end; procedure TForm1.SummAgreeClick(Sender: TObject); var ResVal, Komis:real; i:byte; S:string; begin with form1 do for i:=1 to StringGrid1.RowCount-1 do if (StrToFloat(StringGrid1.Cells[1,i])<>0) then begin Komis:=StrToFloat(EdSum.Text)/100* StrToFloat(StringGrid1.Cells[3,i]); ResVal:=(StrToFloat(EdSum.Text)-Komis)/ StrToFloat(StringGrid1.Cells[1,i]); str(Komis:0:2,s); StringGrid1.Cells[4,i]:=s; str(ResVal:0:2,s); StringGrid1.Cells[2,i]:=s; str(StrToFloat(EdSum.Text):0:2,s); StringGrid1.Cells[5,i]:=s; end; end; end. В программе применены следующие методы: 1. FormCreate. Он при создании формы заносит начальные данные в таблицу по координатам ячеек ACol (номер столбца) и ARow (номер строки). Одельным ячейкам компонента StringGrid1 через свойство StringGrid.Cell [ACol, ARow]
70 присваиваются текстовые значения, а свойству Caption метки Label4 значение текущего времени. CellAgreeClick. Он данные из текстового "Редактора ячеек" EdCell при нажатии на кнопку SellAgree (ОК) заносит в таблицу по текущим координатам выделенной ячейки таблицы. Учтите, что данные заносятся, как текстовая информация. 3. StringGrid1DblClick. Он позволяет двойным щелчком мыши по ячейкам таблицы переносить данные из таблицы в окно "Редактора ячеек" EdCell для их дальнейшего быстрого редактирования. Например, при изменении курса или процента комиссионных. Доступ к координатам текущей ячейки обеспечивается с помощью свойств Col и Row компонента StringGrid1. Редактировать надо только курсы валют. 4. SumAgreeClick. С его помощью данные из текстового редактора "Сумма для конвертации" EdSum при нажатии на кнопку SumAgree (Принято) заносятся в таблицу по текущим координатам. Учтите, что данные воспринимаются редактором, как текстовая информация, а вычисления необходимо производить с числами. 5. Для изменения размеров таблицы используются свойства ColCount и RowCount. Следующие 4 метода увеличивают или уменьшают числа столбцов и строк в процессе выполнения программы щелчками (вызывают событие onClick) по кнопкам размеров таблицы: Уменьшение числа столбцов TForm1.DecColClick. Увеличение числа столбцов TForm1.IncColClick. Уменьшение числа строк TForm1.DecRowClick. Увеличение числа строк TForm1.IncRowClick. 6. Для завершения работы с программой использован метод ExitClick, при осуществлении которого закрывается основная форма. Дублируется кнопка закрытия окна Windows. Запустить проект на выполнение и опробовать действие всех кнопок. Внести в EdSum сумму для конвертации и проконтролировать результат расчетов в соответствующих ячейках. Изменить курс валюты и проконтролировать, как это повлияет на результаты расчетов. Форма при исполнении имеет вид рис. 14.3. 2.
рис. 14.3. Интерфейс проекта в режиме выполнения Выводы 1. Для создания таблиц используется компонент StringGrid (таблица строк). 2. Для управления используются компоненты Button (кнопка) и их обработчики событий. 3. Для пояснений используются компоненты Label (метка). 4. Для ввода данных используются компоненты Edit (однострочный редактор). 5. Кнопка “Выход” дублирует стандартную кнопку завершения приложения Windows.
71
15. Графика, отображение графиков функций Подготовка к работе 1. По рекомендованной литературе изучить графические средства Delphi. 2. Разработать алгоритмы решения задач. 3. Составить программы решения задач. Контрольные вопросы 1. GDI (Graphics Device Interface) - интерфейс и драйверы графических устройств. Контекст отображения (дисплейный контекст) и его инструменты: шрифт, перо, кисть. 2. Класс TGraphicObject (графический объект). 3. Класс TFont - шрифт. Свойства Charset (набор символов), Name (имя), Size (размер в кеглях), Style (стиль), Color (цвет фона). 4. Класс TPen - перо. Свойства Color (цвет), Style (стиль), Width (ширина), Mode (режим). 5. Класс TBrush - кисть. Свойства Color (цвет), Style (стиль). 6. Класс TCanvas - холст (поверхность рисования). Свойства CopyMode (режим копирования), Pen (перо), Brush (кисть), Font (шрифт), Pixels (цвет пикселя). 7. Использование свойства TCanvas.Pixels или метода TCanvas.LineTo для рисования графиков функций. 8. Метод MoveTo (переместить перо к). 9. Компонент TChart. 10. Задание функции для отображения в компоненте TChart. 11. Использование легенды в компоненте TChart. Задание к работе Создать программу вывода текста и рисования в форме графиков функций. Проект – приложение. Варианты заданий приведены в табл. 15.1. табл. 15.1. Варианты задания 1 График функции y(x) № Функция x начальное x конечное 1 sin(x) 0 6π 2 cos(x) 0 6π 3 sin(x)+sin(2x) 0 6π 4 sin(x)-sin(2x) 0 6π 5 sin(x)+cos(2x) 0 6π 6 sin(x)-cos(2x) 0 6π 7 sin(x)*exp(x) 0 6π 8 cos(x)*exp(x) 0 6π 9 sin(x)*exp(-x) 0 6π 10 cos(x)*exp(-x) 0 6π 11 exp(x) 0 2 12 exp(-x) 0 2 13 ln(x) 1 10 14 lg(x) 1 100 15 ln(x)+lg(x) 1 10 Пример выполнения Создать программу рисования в форме графика функции с поясняющим текстом. Проект – приложение. Функция - синус. Программа предусматривает три варианта рисования графика: Точками с помощью свойства Pixels (график в левой верхней части окна). Линиями с использованием метода LineTo (график в нижней левой части окна). С использованием компонента TChart (в правой части окна). На рис. 15.1 представлено окно формы в начале конструирования. В форме размещены следующие компоненты: Кнопка BitBtn1 (Графика) из страницы Additional. Она вызывает построение графиков в окне. Кнопка BitBtn2 (Закрыть) из страницы Additional. Дублирует кнопку закрытия приложения Windows. TChart1. Компонент построения графиков из страницы Additional.
72
рис. 15.1. Окно формы на этапе конструирования Для подготовки TChart к работе используется встроенный редактор свойств этого компонента, вызываемый двойным щелчком по компоненту. На рис. 15.2 слева представлено окно этого редактора. В нем в закладке Series нужно нажатием кнопки Add добавить по крайней мере одну серию данных для построения графика. Остальные параметры компонента можно оставить без изменения. При этом возникает окно для выбора способа отображения графика, показанное на рис. 15.2 справа.
рис. 15.2. Выбор серии для TChart После выбора вида графика окно редактора приобретает вид рис. 15.3, а у компонента TChart в окне формы отображается примерный вид представления графика (см. рис. 15.4 слева). По умолчанию в правой части компонента отображается легенда - столбик из вычисляемых значений функции. При желании легенду можно удалить. Для этого следует вновь вызвать редактор свойств TChart, на вкладке Legend которого выключить флаг Visible. Окно формы примет вид, показанный на рис. 15.4 справа.
рис. 15.3. Окно редактора TChart после выбора серии
73
рис. 15.4. Окно формы после выбора серии Листинг модуля формы unit Prg_15_1_; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls, Buttons, TeEngine, Series, TeeProcs, Chart; type TForm1 = class(TForm) BitBtn1: TBitBtn; BitBtn2: TBitBtn; Chart1: TChart; Series1: TLineSeries; procedure BitBtn1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.BitBtn1Click(Sender: TObject); var i,amp,x01,y01,x02,y02,imax,t:integer; func:real; begin imax:=100; //число точек в периоде t:=3; //число периодов amp:=70; //амплитуда x01:=20; //начала координат x02:=20; y01:=20+amp; y02:=y01+2*amp+40; //Рисуем график с Pixels Canvas.TextOut(0,0,'График функции с Pixels'); Canvas.MoveTo(x01,y01); //Рисуем ось X Canvas.LineTo(x01+imax*t,y01); Canvas.MoveTo(x01,y01+amp); //Рисуем ось Y Canvas.LineTo(x01,y01-amp); for i:=0 to imax*t do //Рисуем график begin func:=-amp*sin(2*pi/imax*i); Canvas.Pixels[x01+i,y01+round(func)]:=clBlack; end;
74
//Рисуем график с LineTo Canvas.TextOut(x02,y02-amp-20,'График функции c LineTo'); Canvas.MoveTo(x02,y02); //Рисуем ось X Canvas.LineTo(x02+imax*t,y02); Canvas.MoveTo(x02,y02+amp); //Рисуем ось Y Canvas.LineTo(x02,y02-amp); //func:=amp*sin(0); //Canvas.MoveTo(x01,y0+round(func)); for i:=0 to imax*t do //Рисуем график begin func:=-amp*sin(2*pi/imax*i); Canvas.LineTo(x02+i,y02+round(func)); end; //Рисуем график в компонентеTChart for i:=0 to imax*t do Chart1.SeriesList[0].AddXY(i,amp*sin(2*pi/imax*i),'',clRed); end; initialization end. На рис. 15.5 представлено окна работающего приложения проекта. Оно возникает при нажатии кнопки График. В окне видны графики одной и той же функции, построенные разными способами: С использованием свойства Pixels (вверху слева). С использованием метода LineTo (внизу слева). С помощью компонента TChart (справа).
рис. 15.5. Окна работающего приложения задачи Выводы 1. Для рисования используется класс Canvas (поверхность рисования, или холст). 2. Многие компоненты имеют свойство Canvas. Например, Form (форма), компонент Image (изображение). 3. Canvas имеет два инструмента: Pen (перо) для рисования линий, Brush (кисть) для заливки областей. 4. Pen имеет свойства: Color - цвет линии, значения с префиксом cl (например, clRed), Style - тип линии, значения с префиксом ps (например, psSolid, принято по умолчанию), Width - толщина линии, в пикселах (по умолчанию 1), Mode - режим взаимодействия с поверхностью холста, значения с префиксом pm (например, pmCopy - писать цветом пера, режим по умолчанию), 5. Brush имеет свойства: Color - цвет заливки, Style - стиль заливки, значения с префиксом bs (Например, bsCross). 6. Для рисования графиков функций используются свойство TCanvas.Pixel(x,y) и метод TCanvas.LineTo. Второй метод дает более качественный график.
75
7.
Для построения графиков есть компонент TChart, позволяющий автоматизировать значительную часть операций.
75
16. Графика, примитивы Подготовка к работе По указанной литературе изучить: Назначение, типы и методы работы с графическими примитивами. Свойства компонента TShape. Метафайлы. Контрольные вопросы 1. Назначение графических примитивов. 2. Графический примитив Линия и метод LineTo его отображения. 3. Графический примитив Кусочно-ломаная линия и метод PolyLine и его отображения. 4. Графический примитив Хорда (линия поперек эллипса) и метод Chord его отображения. 5. Графический примитив Прямоугольная рамка и метод FrameRect его отображения. 6. Графический примитив Заполненный прямоугольник и метод Rectangle его отображения. 7. Графический примитив Заполненный многоугольник и метод Polygon его отображения. 8. Графический примитив Заполненный прямоугольник со скругленными углами и метод RoundRect его отображения. 9. Графический примитив Дуга и метод Arc его отображения. 10. Графический примитив Заполненный эллипс и метод Ellipse его отображения. 11. Графический примитив Пирог (сектор эллипса) и метод Pie его отображения. 12. Метод заполнения замкнутых фигур FloodFill (заполнить область), 13. Методы вывода текста: TextOut (вставить строку текста). 14. Компонент TShape. 15. Метафайлы, назначение, структура, создание и использование. Задание к работе 1. Создать программу рисования в форме графического примитива с заливкой. Примитив рисуется при нажатии кнопки мыши (событие onDown) на форме. Цвет линий, стиль и цвет заливки зависит от того, какая кнопка мыши нажимается (левая или правая). Проект – приложение. Варианты заданий приведены в табл. 16.1. табл. 16.1. Варианты задания 1 Цвет линий Заливка Левая кнопка Правая кнопка Стиль Цвет 1 Ellipse clBlue clGreen bsSolid clRed 2 Rectangle clGreen clWhite bsHorizontal clBlue 3 Pie clWhite clRed bsVertical clGreen 4 RoundRec clRed clBlue bsDiagonal clWhite 5 Polygon (3) clBlue clGreen bsBDiagonal clRed 6 Ellipse clGreen clWhite bsCross clBlue 7 Rectangle clWhite clRed bsDiagCros clGreen 8 Pie clRed clBlue bsSolid clWhite 9 RoundRec clBlue clGreen bsHorizontal clRed 10 Polygon (7) clGreen clWhite bsVertical clBlue 11 Ellipse clWhite clRed bsDiagonal clGreen 12 Rectangle clRed clBlue bsBDiagonal clWhite 13 Pie clBlue clGreen bsCross clRed 14 RoundRec clGreen clWhite bsDiagCros clBlue 15 Polygon (6) clWhite clRed bsSolid clGreen 2. Создать проект, демонстрирующий использование графического компонента TShape для изменения пользовательского интерфейса при выполнении программы. В проекте на форме с изменяемым цветом отображается фигура с разными типом, размерами и цветом. Варианты заданий приведены в Табл. 16.2. Возможные типы фигуры: Тип Имя Круг StCircle Эллипс stEllipse Прямоугольник stRectangle Прямоугольник со скругленными углами stRoundRect Квадрат stsquare Квадрат со скругленными углами stRoundSquare(квадрат с округлыми углами) №
Примитив
Табл. 16.2. Варианты задания 2 1 2 3
stCircle stEllipse stRectangle
stEllipse stRectangle stRoundRect
stRectangle stRoundRect stsquare
76 4 stRoundRect stsquare stCircle 5 stsquare stRoundSquare stRectangle 6 stRoundSquare stCircle stRoundRect 7 stCircle stRectangle stsquare 8 stEllipse stRoundRect stRoundSquare 9 stRectangle stsquare stRectangle 10 stRoundRect stRoundSquare stRoundRect 11 stsquare stRoundRect stsquare 12 stRoundSquare stsquare stRoundSquare 13 stCircle stRoundSquare stRoundSquare 14 stEllipse stRoundRect stsquare 15 stRectangle stsquare stCircle 3. Создать проект работы с метафайлом. Метафайл содержит график с графическими примитивами,, создается программно, отображается на форме и сохраняется на диске ПК. Для проверки праильности метафайла он считывается в компонент Image формы. Проект – приложение. Графические примитвы студент выбирает самостоятельно. Пример выполнения Задание 1 Создать программу рисования в форме графического примитива с заливкой. Примитив - пятиугольная звезда, рисуется при нажатии кнопки мыши (событие onDown) на форме. Если нажата левая кнопка мыши, то цвет линий clBlack (черный), стиль заливки bsDiagCross (диагональный крест), цвет заливки - clRed (красный). Если нажата правая кнопка мыши, то цвет линий clRed (красный), стиль заливки bsCross ( крест), цвет заливки clBlue (синий). Проект – приложение. Листинг модуля формы unit Prg_16_1_; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls; type TForm1 = class(TForm) procedure FormMouseDown(Sender: TObject; Button:TMouseButton; Shift: TShiftState; x,y:integer); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} procedure StarLine(x0,y0,r: integer; Canvas: TCanvas); // x0,y0 - координаты центра звезды // r - радиус звезды var p: array[1..11] of TPoint; // массив координат лучей и впадин a: integer; // угол между ОХ и радиусом к точке звезды i: integer; begin a := 18; // строим от правого горизонтального луча for i:=1 to 10 do begin if (i mod 2 = 0) then begin // впадина звезды p[i].x := x0+Round(r/2*cos(a*2*pi/360)); p[i].y:=y0-Round(r/2*sin(a*2*pi/360)); end else begin // луч звезды p[i].x:=x0+Round(r*cos(a*2*pi/360)); p[i].y:=y0-Round(r*sin(a*2*pi/360)); end;
77 a := a+36; end; p[11].X := p[1].X; p[11].Y := p[1].Y; Canvas.Polyline(p); end;
// чтобы замкнуть контур звезды // начертить звезду
// нажатие кнопки мыши procedure TForm1.FormMouseDown(Sender: TObject; Button:TMouseButton; Shift: TShiftState; x,y:integer); begin with Form1 do begin if Button = mbLeft // нажата левая кнопка? then begin Canvas.Pen.Color := clBlack; StarLine(x, y, 30,Canvas); Canvas.Brush.Style:=bsDiagCross; Canvas.Brush.Color:=clRed; Canvas.FloodFill(x,y,Canvas.Pen.Color,fsBorder); end else begin Canvas.Pen.Color := clRed; StarLine(x, y, 30,Canvas); Canvas.Brush.Style:=bsCross; Canvas.Brush.Color:=clBlue; Canvas.FloodFill(x,y,Canvas.Pen.Color,fsBorder); end; end; end; end. На рис. 16.1 представлен вид окна приложения задачи 1 при исполнении.
рис. 16.1. Окно работающего приложения задачи 1 Задание 2 Создать проект в котором в форме, цвет которой может изменяться, отображается компонент Shape1 (фигура), для которого можно менять тип, цвет и размеры. Формы фигур: stCircle, stEllipse, stsquare. Выполнение 1. Запустить Delphi. 2. Создать в ней новое приложение. 3. Присвоить свойству Caption компонента Form1 значение Prg_16_2. 4. Сохранить модуль под именем Prg_16_2_, а проект под именем Prg_16_2. 5. Установить на форме компоненты:
78 кнопки Button1 и Button2, комбинированный список ComboBox1, линейки прокрутки ScrollBar1 и ScrollBar2, панель Panel1 (со страницы Standard). фигура Shape1 (со страницы Additional). диалог цвета ColorDialog1 (со страницы Dialogs). 6. Задать свойству Shape компонента Shape1 значение stEllipse (Эллипс). Используя свойство Brush, установить произвольный цвет объекта Shape1. 7. Установить значения свойств компонентов линеек прокрутки ScrollBar1 и ScrollBar2: Name ScrollBar1 ScrollBar2 Kind ( Тип) sbHorizobntal (Горизонтальная) sbVertical (Вертикальная) Align (Размещение) alBottom (Снизу) alRight (Справа)
8. Компоненты Button1, Button2, ComboBox1 установить на передний план объекта Panel1 и выровнять их по вертикали. 9. Установить значения свойств компонентов Button1, Button2: Компонент Button1 Button2 Name (Имя) FormColor ShapeColor Caption (Надпись) Цвет формы Цвет фигуры 10. Установить следующие значения строк списка ComboBox1: Имя фигуры Тип фигуры stRectangle Прямоугольник stSguare Квадрат stRoundRect Прямоугольник со скругленными углами stRoundSguare Квадрат со скругленными углами stEllipse Эллипс stCircle Круг Внимание: имена фигур надо заносить в указанном порядке, так как они далее анализируются по номеру в списке. 11. Задать свойству BorderWidth компонента Panel1 значение 5. После вышеперечисленных установок интерфейс проекта примет вид, показанный на .
рис. 16.2. Форма проекта задачи 2 12. Для изменения цвета фигуры или формы во время выполнения приложения использовать стандартное диалоговое окно выбора цвета ColorDialog1. Этот компонент при исполнении программы невидим. 13. Двойным щелчком по кнопке Цвет формы создать заготовку обработчика отклика на событие OnClick (на щелчок) для кнопки Цвет формы. Написать код обработчика, который при нажатии кнопки Цвет формы вызывает стандартное диалоговое окно выбора цвета с помощью диалогового окна ColorDialog1. 14. Двойным щелчком по кнопке Цвет фигуры создать заготовку обработчика события OnClick (на щелчок) для кнопки Цвет фигуры. Написать код обработчика, который при нажатии кнопки установит значение свойства Brush.Color (цвет закраски) фигуры Shape1, выбираемое с помощью диалогового окна ColorDialog1. 15. Запустить проект командой Выполнить и проверить действие кнопок Цвет формы и Цвет фигуры. При нажатии кнопок выбора цвета в отдельном окне (см. рис. 16.3) отображается окно диалога выбора цвета, в котором следует выбирать желаемый цвет.
79
рис. 16.3. Окно диалога выбора цвета Вернуться в режим конструирования. 16. Запрограммировать изменение размера фигуры с помощью полос прокрутки. Для этого: • Двойным щелчком по компонентам создать заготовки методов для отклика на событие OnChange (на изменение) для каждой из полос прокрутки ScrollBar1 и ScrollBar2. • Написать для этих методов коды, которые установят свойство Width (ширина) или Height (высота) фигуры Shape1 в соответствии с положением "бегунка" на горизонтальной (ScrollBar1) или вертикальной (ScrollBar2) полосах прокрутки. • Подобрать соотношение между положением бегунков полосы прокрутки ScrollBar1.Position и ScrollBar2.Position (лежат в пределах 1...100) и размерами фигуры, при котором достигается лучшее представление изменения размеров фигуры. 17. Запустить проект и проверить действие каждой из полос прокрутки. Вернуться в режим конструирования. 18. Для выбора нового вида фигуры использовать выпадающий список (ComboBox). Чтобы создать список в режиме проектирования, необходимо ввести нужные элементы в список Items, щелкнув маленькую кнопку с тремя точками в правой части строки Инспектора объектов, отображающую данное свойство. Список показан на рис. 16.4.
рис. 16.4. Список опций свойства Shape 19. В диалоговое окно текстового редактора (см. рис. 16.4) ввести фигуры по заданию. 20. Двойным щелчком по компоненту ComboBox1 создать заготовку обработчика события OnClick (на щелчок) для списка ComboBox1. В нее вставить код, позволяющий выбрать из списка нужный элемент. 21. Для проверки кода запустить проект, а затем поочередно выбрать из списка разные виды фигур. 22. Сохранить и закрыть проект. Запустить исполняемый файл проекта Prg_16_2 из среды Windows и проверить его работоспособность. Листинг модуля формы unit Prg_16_2_; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls; type
80 TForm1 = class(TForm) FormColor: TButton; ShapeColor: TButton; ScrollBar1: TScrollBar; ComboBox1: TComboBox; Shape1: TShape; ColorDialog1: TColorDialog; ScrollBar2: TScrollBar; Panel1: TPanel; procedure FormColorClick(Sender: TObject); procedure ShapeColorClick(Sender: TObject); procedure ScrollBar1Change(Sender: TObject); procedure ScrollBar2Change(Sender: TObject); procedure ComboBox1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.DFM} procedure TForm1.FormColorClick(Sender: TObject); begin if ColorDialog1.Execute then Form1.Color:= ColorDialog1.Color; end; procedure TForm1.ShapeColorClick(Sender: TObject); begin if ColorDialog1.Execute then Shape1.Brush.Color:= ColorDialog1.Color; end; procedure TForm1.ScrollBar1Change(Sender: TObject); begin Shape1.Width:= ScrollBar1.Position*3; end; procedure TForm1.ScrollBar2Change(Sender: TObject); begin Shape1.Height:= ScrollBar2.Position*3; end; procedure TForm1.ComboBox1Click(Sender: TObject); var Index: integer; begin if ComboBox1.Text='stRectangle' then Index:=0; if ComboBox1.Text='stSquare' then Index:=1; if ComboBox1.Text='stRoundRect' then Index:=2; if ComboBox1.Text='stRoundSquare' then Index:=3; if ComboBox1.Text='stEllipse' then Index:=4; if ComboBox1.Text='stCircle' then Index:=5; Shape1.Shape:=TShapeType(Index); end; end. Задание 3 Создать проект работы с метафайлом. Метафайл содержит график с двумя фигурами (эллипс и квадрат), создается программно, отображается на форме и сохраняется на диске ПК. Для проверки праильности метафайла он считывается в компонент Image формы. Проект – приложение.
81 На рис. 16.5 показана форма проекта задачи 3. Она содержит компонент Image1 для просмотра метафайла и две кнопки: • Button1 - «Создать метафайл». При нажатии кнопки метафайл MyMetafile.wmf создается, прорисовывается на форме и сохраняется на диске. • Button2 - «Смотреть метафайл». Нажатие этой кнопки приводит к отображению метафайла в компоненте Image1 формы.
рис. 16.5. Форма проекта задачи 3 Листинг модуля формы unit Prg_16_3_; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls; type TForm1 = class(TForm) Sozdath: TButton; Image1: TImage; Smotreth: TButton; procedure SozdathClick(Sender: TObject); procedure SmotrethClick(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; MyMetafile:TMetafile; implementation {$R *.dfm} procedure TForm1. SozdathClick(Sender: TObject); begin with TMetafileCanvas.Create(MyMetafile, 0) do try Brush.Color := clRed; Ellipse(0,0,150,100); // Рисуем эллипс Brush.Color:=clWhite;
82 Rectangle(150,150,200,200); // Рисуем квадрат finally Free end; MyMetafile.SaveToFile('MyMetafile.wmf'); // Сохранить метафайл Form1.Canvas.Draw(0,0,MyMetafile); // Рисовать метафайл на форме end; procedure TForm1. SmotrethClick(Sender: TObject); begin Image1.Picture.LoadFromFile('MyMetafile.wmf'); // Просмотр метафайла end; initialization MyMetafile := TMetafile.Create; end.
// Создать метафайл
Внимание Работа с метафайлом осуществляется в динамической памяти, поэтому перед использованием созданного метафайла необходимо освободить ДП процедурой Free. На рис. 16.6 показано окно работающего приложения задачи 3. Левая часть отображается при нажатии кнопки «Создать метафайл», правая – при нажатии кнопки «Смотреть метафайл».
рис. 16.6. Форма работающего приложения задачи 3 Выводы 1. Для построения графиков используются графические примитвы. 2. Определены графические примитивы: Линия и метод LineTo его отображения. Кусочно-ломаная линия и метод PolyLine и его отображения. Хорда (линия поперек эллипса) и метод Chord его отображения. Прямоугольная рамка и метод FrameRect его отображения. Заполненный прямоугольник и метод Rectangle его отображения. Заполненный многоугольник и метод Polygon его отображения. Заполненный прямоугольник со скругленными углами и метод RoundRect его отображения. Дуга и метод Arc его отображения. Заполненный эллипс и метод Ellipse его отображения. Пирог (сектор эллипса) и метод Pie его отображения. 3. Определен метод заполнения замкнутых фигур FloodFill (заполнить область), 4. Имеется метод вывода текста: TextOut (вставить строку текста). 5. Определен компонент TShape (фигура)., позволяющий быстро выбирать фигуру для построения. 6. Для изменения интерфейса используются кнопки, линейки прокрутки, списки, меню, диалоги. 7. Замкнутые фигуры с помощью инструмента Brush могут быть залиты узором. 8. График с использованием примитивов может быть сохранен в формате метафайла Windows.
83
17. Графика, растровые изображения и анимация Подготовка к работе 1. По рекомендованной литературе изучить графические средства Delphi. 2. Разработать алгоритмы решения задач. 3. Составить программы решения задач. Контрольные вопросы 1. Класс TImage - компонент изображения. 2. Класс TBitMap - растровое изображение. 3. Класс TJpegImage - сжатое по стандарту Jpeg изображение. 4. Сжатие изображений в стандарте Jpeg за счет изменения системы цветов.. 5. Сжатие изображений в стандарте Jpeg за счет дискретного косинусного преобразования. 6. Сжатие изображений в стандарте Jpeg за счет обнаружения повторяющихся кодов. 7. Сжатие изображений в стандарте Jpeg за счет использования алгоритма Хафмена. 8. Компонент TrackBar и его использование. 9. Использование класса TMemoryStream для определения размеров файлов. 10. Принцип создания анимации. 11. Использование в анимационной программе фоновой картинки. 12. Использование в анимационной программе картинки образа. 13. Использование в анимационной программе буфера. Задание к работе 1. Создать программу обработки битовых изображений. Проект – приложение. Нужно использовать два компонента TImage, в одном отображается растровая картинка, в другом - она же с использованием алгоритмов сжатия. Для сжатия использовать класс TJpegImage. 2. Создать программу анимации (движение самолета на фоне изображения фабрики) в компоненте TImage. Проект – приложение. Пример выполнения Задание 1 Создать программу работы с графическими файлами, Проект – приложение. В программе используется файл растровой картинки picture.bmp, который надо загрузить в ту же папку, где находится проект приложения. Этот файл находится в папке УМД к ЛР. На рис. 17.1 показана форма проекта задания 1.
рис. 17.1. Форма проекта задания 1 В форме размещены: Компоненты Image1 и Image2 для отображения битовых образов. Кнопки Button1 (BitMap) и Button2 (JpegImage), нажатие которых приводит к прорисовке изображений. Метки Label1 и Label2 для вывода размеров файлов исходного и сжатого изображений. Регулятор TrackBar1 для изменения качества сжимаемого изображения.
84
Метки Label3, Label4 и Label5 для отображения минимального, максимального и текущего значения коэффициента качества. Диапазон этого коэффициента определен в пределах 1...100. Метка Label6 предназначена для заголовка компонент регулятора. Программа содержит 3 процедуры. Две отрабатывают нажатие кнопок, третья изменение состояния регультора. В программе используется класс TJpegImage, описанный в ИСР в модуле Jpeg. Поэтому в строке uses нужно добавить ссылку на этот модуль. В программе определены: переменные MyBitmap и MyJpeg для взаимных преобразований картинок. переменная MyMemory для создания буфера в памяти, по нему определяются размеры файлов в байтах. вспомогательные переменные. файлы картинок должны размещаться в папке проекта. Листинг модуля формы unit Prg_17_1_; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Buttons, ExtCtrls, jpeg, ComCtrls; type TForm1 = class(TForm) Image1: TImage; Image2: TImage; BitBtn1: TBitBtn; BitBtn2: TBitBtn; Label1: TLabel; Label2: TLabel; TrackBar1: TTrackBar; Label3: TLabel; Label4: TLabel; Label5: TLabel; Label6: TLabel; procedure BitBtn1Click(Sender: TObject); procedure BitBtn2Click(Sender: TObject); procedure TrackBar1Change(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; MyJpeg:TJpegImage; MyBitMap:TBitmap; MyMemory:TmemoryStream; s1,s2,s3,s:string; size:integer; implementation {$R *.dfm} procedure TForm1.BitBtn1Click(Sender: TObject); begin Image1.Picture.Assign(MyBitmap); MyMemory.Clear; Mymemory.LoadFromFile(s1); str(MyMemory.Size,s3); Label1.Caption:=s3; end; procedure TForm1.BitBtn2Click(Sender: TObject); begin MyJpeg.Assign(MyBitmap); MyJpeg.CompressionQuality:=100;
85
MyJpeg.Compress; MyJpeg.SaveToFile(s2); Image2.Picture.LoadFromFile(s2); MyMemory.Clear; Mymemory.LoadFromFile(s2); str(MyMemory.Size,s3); Label2.Caption:=s3; end; procedure TForm1.TrackBar1Change(Sender: TObject); begin str(TrackBar1.Min,s3); Label3.Caption:=s3; str(TrackBar1.Max,s3); Label4.Caption:=s3; str(TrackBar1.Position,s3); Label5.Caption:=s3; MyJpeg.CompressionQuality:=TrackBar1.Position; MyJpeg.Compress; MyJpeg.SaveToFile(s2); Image2.Picture.LoadFromFile(s2); MyMemory.Clear; Mymemory.LoadFromFile(s2); str(MyMemory.Size,s3); Label2.Caption:=s3; end; initialization s1:='E:\Eddy\Umd\Prg_YVU\LR\Delphi_examples_2\17_1\Picture.bmp'; s2:='E:\Eddy\Umd\Prg_YVU\LR\Delphi_examples_2\17_1\Picture.jpeg'; MyBitmap:=TBitMap.Create; MyBitmap.LoadFromFile(s1); MyMemory:=TmemoryStream.Create; MyJpeg:=TJpegImage.Create; end. При запуске проекта на выполнение появляется окно в котором картинок нет. При нажатии на кнопку BitMap отображается исходная картинка и размер ее файла (в примере 309862), При нажатии на кнопку JpegImage отображается сжатая картинка и размер ее файла (в примере 89598). Это показано на рис. 17.2. Картинки получены при качестве 100, когда никаких отличий не видно, хотя сжатый файл имеет размер примерно в 3 раза меньше.
86
рис. 17.2. Форма при запуске программы Если теперь перемещать движок регулятора, сжатая картинка и размер ее файла динамически изменяются. Например, при коэффициенте качества 1 картинки имеют вид, показанный на рис. 17.3. Размер сжатого файла 3119, т.е произошло сжатие примерно в 100 раз Граница заметности ухудшение качества для использованной картинки - коэффициент качества 10. При этом размер сжатого файла 5599, что примерно в 55 раз меньше, чем у исходного изображения.
рис. 17.3. Картинки при коэффициенте качества 1 Задание 2 Создать программу демонстрации анимации: движение самолета на фоне фабрики. Проект – приложение. В программе используются два файла растровых картинок, которые надо загрузить в ту же папку, где находится проект приложения: фон - фабрика, файл factory.bmp, движущийся объект - самолет, файл aplane.bmp. Эти файлы находятся в папке УМД к ЛР. Листинг модуля формы unit prg_17_2_; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls, Buttons; type TForm1 = class(TForm) Timer1: TTimer; Image1: TImage; procedure FormActivate(Sender: TObject); procedure Timer1Timer(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); private { Private declarations } public { Public declarations } end; var Form1: TForm1;
87
implementation {$R *.DFM} var Back, Bitmap, Buf : TBitMap; BackRct : TRect; BufRct: Trect; x,y:integer; W,H: integer;
// Фон, картинка, буфер // Область фона, восстановлена из буфера // Область буфера для фона // Текущее положение картинки // Размеры картинки
procedure TForm1.FormActivate(Sender: TObject); begin // создать три объекта - битовых образа Back := TBitmap.Create; // Фон Bitmap := TBitmap.Create; // Картинка Buf := TBitmap.Create; // Буфер // загрузить и вывести фон Back.LoadFromFile('factory.bmp'); Form1.Image1.canvas.Draw(0,0,Back); // загрузить картинку, которая будет двигаться Bitmap.LoadFromFile('aplane.bmp'); // определим "прозрачный" цвет Bitmap.Transparent := True; Bitmap.TransParentColor := Bitmap.canvas.pixels[1,1]; // создать буфер для сохранения копии области фона под картинку W:= Bitmap.Width; H:= Bitmap.Height; Buf.Width:= W; Buf.Height:=H; Buf.Palette:=Back.Palette; // Для соответствия палитр !! Buf.Canvas.CopyMode:=cmSrcCopy; // определим область буфера, используемую для восстановления фона BufRct:=Bounds(0,0,W,H); // начальное положение картинки x := -W; y := 20; // определим сохраняемую область фона и сохраним ее BackRct:=Bounds(x,y,W,H); Buf.Canvas.CopyRect(BufRct,Back.Canvas,BackRct); end; // обработка сигнала таймера procedure TForm1.Timer1Timer(Sender: TObject); begin Form1.image1.canvas.Draw(x,y,Buf); // Восстановлением фона удалим рисунок x:=x+2; if x>form1.Image1.Width then x:=-W; // определим сохраняемую область фона и сохраним ее копию BackRct:=Bounds(x,y,W,H); Buf.Canvas.CopyRect(BufRct,Back.Canvas,BackRct); // выведем рисунок Form1.image1.canvas.Draw(x,y,bitmap); end; // завершение работы программы procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); begin // освободим память, выделенную для хранения битовых образов Back.Free; Bitmap.Free; Buf.Free; end; end. На рис. 17.1 представлен вид кадра окна приложения при исполнении. Самолет движется слева направо.
88
рис. 17.1. Окно работающего приложения задачи 2 Выводы 1. Для работы с изображениями класса TBitmap предназначен компонент TImage. 2. ИСР содержит класс TJpegImage для работы со сжатыми по стандарту Jpeg изображениями. 3. Для фотореалистических изображений возможно сжатие в десятки раз без заметного ухудшения качества. 4. При создании анимации образ движущегося объекта рисуется на холсте со смещением во времени. Перед очередным рисованием область фона, на которую накладывается текущий образ движущегося объекта, запоминается в буфере для последующего восстановления.
89
18. Тестирование и отладка Подготовка к работе 1. Изучить по литературе и методическим указаниям: Способы получения данных состояния программы. Отладочная печать. Использование окна отладки «Наблюдатели» (Watches). Пошаговое выполнение программы в версиях «Пропуск блока» (Step over) и «Трассировка» (Trace into). Выполнение программы до позиции курсора. Использование окна «СтопТочки» (Breakpoints). Использование окна «Стек вызова» (Call stack). Использование окон «CPU» и «FPU». Использование опции «Вычислить/Изменить» (Evaluate/Modify). 2. Изучить алгоритм и программу учебной задачи в данной работе. 3. Получить для численного примера набор данных для отладочного контроля. Контрольные вопросы 1. Способы получения данных о состоянии программы. 2. Отладочная печать и ее использование при тестировании программ. 3. Структура и использование окна отладки «Наблюдатели» (Watches). 4. Пошаговое выполнение программы в версии «Пропуск блока» (Step over). 5. Пошаговое выполнение программы в версии «Трассировка» (Trace into). 6. Использование опции прогона программы до позиции курсора. 7. Структура и использование окна «СтопТочки» (Breakpoints).. 8. Структура и использование окна «Стек вызова» Call stack. 9. Назначение и использование окон «CPU» и «FPU». 10. Использование опции «Вычислить/Изменить» (Evaluate/Modify). Задание к работе В работе используется учебная программа, которая по паре вводимых чисел c,d в цикле для i=1...10 вычисляет значения пары других параметров a=(c+d)*i, b=(c-d)*i. Функция Ample вычисляет квадратный корень из суммы квадратов целых частей от a,b, и эти значения суммируются в s. По завершении цикла вычисляется среднее арифметическое sm от выходных параметров функции Ample. Функция Ample оформлена в виде подпрограммы. В программе определены метки, задающие точки останова. Варианты задания представлены в табл. 18.1. Листинг программы: program Prg_16_1; {$APPTYPE CONSOLE} uses SysUtils, RusTrans; // Ссылка на модули label m1,m2,m3,m4,m5,m6; var a,b,c,d,s,f,sm: real; i: integer; function Ample(x,y:real):real; var x1,y1,f: real; begin m5: x1:=Int(x); m6: y1:=Int(y); Result:=sqrt(x1*x1+y1*y1);
90
end; begin writeln(Rus('Введите c,d')); readln(c,d); writeln; s:=0; for i:=1 to 10 do begin m1: a:=(c+d)*i; m2: b:=(c-d)*i; m3: f:=Ample(a,b); m4: s:=s+f; writeln('s[',i,']=',s:8:3); end; sm:=s/10; writeln; writeln('Resultat=',sm:8:3); readln; end. табл. 18.1. Варианты заданий N 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Переменные для окна «Наблюдатели» a, b, f c, d, s a, c, s b, d, f a, d, c b, a, s c, d, f d, c, a f, d, b s, f, c a, s, f b, a, s c, d, f s, d, c a, c, f
Строки останова m1,m2,m3 m4,m5,m6 m2,m3,m4 m1,m5,m6 m3,m4,m5 m1,m2,m6 m4,m5,m6 m1,m2,m3 m5,m6,m1 m4,m2,m3 m6,m1,m2 m3,m4,m5 m1,m3,m5 m4,m5,m3 m2,m1,m6
Выражение для окна «Вычислить/Изменить» a+b a*b a-b a/b a+b a*b a–b a/b a+b a*b a–b a/b a*b a–b a/b
Пример выполнения Задание Протестировать учебную программу с условиями: С помощью отладочной печати контролировать массив s[i]. Переменные для окна «Наблюдатели» (Watches) - a,b,s,i. Точки останова - m1,m2,m4. Выражение для окна «Вычислить/Изменить» (Evaluate/ Modify) «a+b» Выполнение 1. Создаем консольное приложение. 2. Размещаем в нем код учебной программы. 3. Проверка значений s[i] с помощью отладочной печати. Отладочная печать - вывод значений переменных в окно приложения осуществляется при прогоне программы. Ниже показано окно приложения при прогоне.
91
4. Командой Инструменты=>Опции отладчика вызвать диалоговое окно, в котором установить флаг «Встроенная отладка». После этого доступны средства тестирования и отладки программ.
5. Командой Вид =>Окна отладки=>Наблюдатели создаем окно «Наблюдатели». В начале оно пустое. 6. Командой Запуск=>Добавить наблюдателя через окно «Свойства наблюдателя» последовательно заносим в него переменные a, b, s, i.
92
После занесения переменных окно «Список наблюдателей» приобретает вид
Так как переменные доступны только при выполнении программы, для них указано, что процесс не доступен. При тестировании в окне будут появляться конкретные значения. 7. Осуществляем проверку программы с помощью пошагового выполнения в версии «Пропуск блока» (Step over). При этом на каждом шаге в редакторе кода указывается строка кода для исполнения. Она выделяется цветом и помечается стрелкой зеленого цвета слева от строки кода.
При исполнении шага меняется содержание окна «Список наблюдений».
8. Осуществить проверку программы с помощью пошагового выполнения в версии «Трассировка» (Trace into). Все происходит аналогично, но с заходом в подпрограмму. 9. Командой Вид=>Окна отладки=>СтопТочки создаем окно «СтопТочки» (Breakpoints). В начале окно пустое.
93
10. Задаем в нем точки останова. Для этого командой Запуск=>Добавить СтопТочку=>СтопТочка исходника вызываем окно
11. В нем заносим данные о точке останова. То же самое можно выполнить быстрее, делая щелчки левой кнопкой мыши по точкам, помечающим строки кода в редакторе кода программы.
В редакторе кода точки и строки кода получают цветовое выделение, а в окне «Список СтопТочек» появляются сведения об этих точках.
12. Осуществить проверку программы с использованием точек останова. Для этого использовать команду Запуск. При каждом выполнении осуществляется прогон до следующей точки останова. 13. На любом шаге трассировки командой «Запуск=>Вычислить/Изменить» можно вызвать окно «Вычислить/Изменить» (Evaluate/Modify),
94
В нем ввести в поле «Выражение» формулу и командой Вычислить в поле «Результат» получить вычисленное значение. Если в поле «Выражение» введено имя переменной, то будет доступна команда Изменить, по которой значение, введенное в поле «Новое значение», будет присвоено этой переменной. Выводы по работе 1. Данные о состоянии программы можно получить, используя отладочную печать или отладочные средства ИСР. 2. Чтобы сделать отладочные средства доступными, нужно командой Инструменты=>Опции отладчика вызвать диалоговое окно, в котором установить флаг «Встроенная отладка». 3. Для контроля значений переменных можно использовать окно отладки «Наблюдатели». В нем при каждом останове программы можно наблюдать текущие значения переменных или выражений с их использованием. 4. Для трассировки программы предназначено пошаговое выполнение программы в версиях «Пропустить блок» и «Трассировка». В первом случае подпрограмма исполняется за один шаг, а во втором происходит построчное исполнение кодов подпрограммы. 5. Если есть уверенность в правильности программы до определенной строки, то для ускорения трассировки следует использовать команду Запуск=>Запуск до курсора. 6. Для задания произвольных точек останова используются команда Запуск=>Добавить СтопТочкува=>На строку исходника и окно «СтопТочки». 7. Для контроля вызова подпрограмм используется окно «Стек вызова». 8. Для контроля состояния регистров процессора используются окно «CPU» в котором отображаются 16-ричные коды содержимого регистров процессора и значения флагов, а также окно «FPU», в котором отображаются данные о регистрах сопроцессора, выполняющего команды с плавающей точкой. 9. При каждом останове программы можно, используя команду Запуск=>Вычислить/Изменить, вычислить выражение с текущими значениями переменных, либо присвоить выбранной переменной новое значение.
94
19. Квадратное уравнение Подготовка к работе По указанной литературе изучить: 1. Cвойства компонентов Label, Button, Edit, StringGrid. 2. Cобытия onClick, onChange, onCreate. 3. Как создать код обработчика события. Контрольные вопросы 1. События onClick, onCreate. 2. Назначение и свойства компонента кнопка. 3. Назначение и свойства компонент метка. 4. Назначение и свойства Компонента однострочный редактор. 5. Как создать обработчик события onClick. 6. Как создать обработчик события onDblClick. 7. Как создать обработчик события onChange. 8. Подпрограммы. Основные понятия. Задание Создать проект “Решение квадратного уравнения”. Пример выполнения 1. Запустить Delphi. 2. Создать в ней новое приложение. 3. Присвоить свойству Caption компонента Form1 значение Решение квадратного уравнения. 4. Сохранить модуль под именем Roots, а проект под именем SQR. 5. Установить на форме компоненты: однострочные редакторы Edit1 - Edit3, метки Label1 - Label5, кнопки Button1- Button3 (все со страницы Standard). Компоненты расположить, как это показано на рис. 19.1.
рис. 19.1. Заготовка интерфейса проекта "Решение квадратного уравнения" 6. В Инспекторе объектов задать следующие свойства компонент меток Label: Name Label1 Label2 Label3 Caption * Уравнение задается Коэффициент А коэффициентами AutoSize True True False Top 136 8 48 Left 24 40 24 Height 24 24 24 Width 40 270 95 Parent Fond True False True FontName Arial FontSize 11 * Компонент Label1 предназначен для вывода значений корней квадратного ошибках.
Label4 Коэффициент B
Label5 Коэффициент C
False 48 136 24 95 True
False 48 248 24 95 True
уравнения Ax2+Bx+C=0 или сообщений об
95 7. В Инспекторе объектов задать следующие свойства компонент кнопок Button: Name Button1 Button2 Caption Вычислить Новое Top 208 208 Left 24 136 Height 25 25 Width 81 81
Button3 Завершить 208 248 25 81
8. После вышеперечисленных установок интерфейс проекта примет вид рис. 19.2.
рис. 19.2. Интерфейс проекта в режиме конструирования 2.
3. 4. 5. 6. 7.
Создать обработчик события OnCliсk для кнопки "Вычислить", в котором необходимо описать: • все переменные, используемые при вычислении корней квадратного уравнения, • процедуру преобразования текста в число для трех коэффициентов уравнения, • код вычисления коэффициентов уравнения, при вводе в соответствующее текстовое поле коэффициентов и вывода полученных корней x1 и x2 в Label1, • сообщения о некорректности задания коэффициентов уравнения при А=0, • сообщения об отсутствия решения, если дискриминант меньше 0. • процедуру преобразования числа в строку при выводе корней уравнения, Создать обработчик событий OnClik для кнопки "Новое". Он должен очищать поля редактирования от первоначальных записей и устанавливать курсор в поле ввода коэффициента при второй степени неизвестного. Создать обработчик событий OnClik для кнопки "Завершить", который завершает работу приложения. Сохранить модуль проекта под именем Prg_19_1_, а проект под именем Prg_19_1. Запустить программу командой Run, а затем вести такие коэффициенты квадратного уравнения, чтобы проверить все виды сообщений и вывода корней уравнения. Закрыть проект SQR, а затем запустить его из среды Windows и проверить на его работоспособность.
Пример выполнения Код модуля проекта: unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,StdCtrls; type TForm1 = class(TForm) Button1: TButton; Button2: TButton; Button3: TButton; Edit1: TEdit; Edit2: TEdit; Edit3: TEdit; Label1: TLabel; Label2: TLabel; Label3: TLabel; Label4: TLabel;
96
var
end;
Label5: TLabel; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button3Click(Sender: TObject); private { Private declarations } public { Public declarations }
Form1: TForm1; implementation {$R *.DFM} // обработчик события OnCliсk для кнопки "Вычислить" procedure TForm1.Button1Click(Sender: TObject); var a,b,c:real; // коэффициенты уравнения d:real; // дискриминант x1,x2:real; // корни уравнения code:integer; // для преобразования текста в число st1,st2:string[10]; begin // ввод исходных данных из полей редактирования val(Edit1.text,a,code); // преобразование текста в число val(Edit2.text,b,code); val(Edit3.text,c,code); if a=0 then Label1.caption:='Коэффициенты при второй степени'+chr(13)+'неизвестного равен нулю!'; else begin // решение уравнения d:=b*b-4*a*c; if d<0 then Label1.caption:='Дискриминант < 0' +chr(13)+'Уравнение не имеет корней' else begin x1:=(-b+sqrt(d))/(2*a); x2:=(-b-sqrt(d))/(2*a); str(x1:10:5,st1); // в переменные str1, str2 помещаются str(x2:10:5,st2); // строковые изображения корней Label1.Caption:='Корни уравнения:'+ chr(13)+'x1='+st1+ chr(13)+'x2='+st2; end; end; end; // обработчик событий OnClik для кнопки "Новое" procedure TForm1.Button2Click(Sender: TObject); begin Edit1.Text:=''; Edit2.Text:=''; Edit3.Text:=''; Label1.Caption:=''; Edit1.SetFocus; end; // обработчик событий OnClik для кнопки "Завершить" procedure TForm1.Button3Click(Sender: TObject); begin Close; end; end.
На рис. 19.3 приведен вид окна работающего приложения после ввода коэффициентов и вычислений.
97
рис. 19.3.Форма приложения при исполнении Выводы 1. Для управления используются компоненты Button (кнопка) и их обработчики событий. 2. Для пояснений используются компоненты Label (метка). 3. Для ввода данных используются компоненты Edit (однострочный редактор). 4. Кнопка “Выход” дублирует стандартную кнопку завершения приложения Windows.