ВВЕДЕНИЕ Язык программирования Паскаль. В настоящее время в компьютерном мире существует множество языков программирования. Программу, выполняющую одни и те же действия, можно написать на языках Бейсик (BASIC), Паскаль (Pascal), Си (C). Язык Pascal лучше других языков подходит для обучения программированию. Это обусловлено тем, что язык был разработан в 70-е годы швейцарским ученым Никлаусом Виртом специально для обучения студентов программированию. Язык был назван в честь французского математика и философа Блеза Паскаля. Наиболее популярным компилятором стала разработка американской фирмы Borland International. С появлением системы MS Windows возникла необходимость написания программ для этой системы и фирма Borland выпустила несколько версий компиляторов для создания программ в среде Windows (Turbo Pascal for Windows). Но наиболее удачной получилась система визуальной среды программирования (RAD-система) Borland Delphi. Первая версия Delphi была создана для Windows 3.1. С появлением системы MS Windows 95, была выпущена 16-разрядная версия Delphi 2.0, а затем и 32-разрядная Delphi 3.0. На момент 2001 года выпушена версия Delphi 6 (C 1998 года фирма Borland International стала называться Inprise Corporation). Среда Delphi предполагает использование визуальное проектирование и событийное программирование (программирование процедур обработки событий визуальных компонентов), применение которых позволяет существенно упростить процесс разработки и создания приложений, работающих в MS Windows. Программисту требуется только разработать «идею» программы, а «представление» программы сделает Delphi. Этапы разработки включают в себя: построение модели программы; разработку и выбор алгоритма решения поставленной задачи; набор текста программы. В визуальной среде программирования это означает: создание окна программы, содержащего различные визуальные элементы и написание команд событий; отладку; тестирование; написание и настройку файла помощи; создание инсталлятора. Модель программы. На этом этапе определяется, какая информация будет входной и какие результаты должны быть представлены на выходе. Разработка алгоритма — последовательность действий для достижения поставленной задачи. Результатом этого этапа является подробное словесное описание алгоритма или его графическое отображение построение структурной схемы алгоритма. После создания алгоритма осуществляется собственно этап написания программы. Необходимо создать макеты диалоговых окон и продумать взаимодействие между ними, а затем написать код программы. При написании программы неизбежно возникают ошибки, как синтаксические (ошибки при наборе текста), так и алгоритмические ошибки — ошибки в самом алгоритме программы. Требуется этап отладки. При окончании этапа отладки происходит этап тестирования, проверка работоспособности системы с различными входными данными. При создании коммерческой программы также необходимо создать контекстную помощь — этап создания файла помощи. Этот этап может быть включен в этап написания программы. Окончательно для распространения программы другим пользователям служит этап — создания инсталлятора. Схемы алгоритмов и программ. При написании алгоритма программы наиболее удобным способом отображения является графический способ — схема структурная. Для написания структурных схем алгоритма необходимо использовать ГОСТ 19.701-90 (ИСО 5807-85). Все основные символы алгоритма вписываются в прямоугольник со сторонами a x b. Соотношение сторон a = 2b или 2a = 3b. Базовый размер a берут из ряда 10,15,20 и так далее кратно 5. Основные символы показаны на рис В.2. R=0,25a 0,5a a R Решение 0,2a 0,2a Терминатор b a Граница цикла Процесс 0,15a 0,25a Предопределённый процесс Данные К стр. NS Из стр. NS N N N ø 0,5a Соединитель (N — буква Внешний и внутренний соединитель соединения ‘A’, ‘B’ и т.д.) (N — буква соединения; NS — номер страницы, соединяемого элемента Соединители Комментарий Комментарий 5min Линия Направление потока указывается в конце каждой линии или на всех потоках или на тех, которые идут справа налево и снизу-вверх. Пересечение потоков не имеет логической связи. Соотношение размеров Для сохранения формы символов при построении можно воспользоваться соотношением: b=1,5a или b=2a Схема «Простейшая программа» Название программы или проНачало цедуры Тело программы Конец 2 Рис.В.2. Основные символы, используемые для построения структурных схем алгоритмов Структура пособия. Каждая тема разделена на 2 части: теоретическое знакомство с материалом и описание алгоритма создания программы. Выполнение работы происходит на двух занятиях. На первом занятии требуется по предлагаемым инструкциям набрать программу и разобраться в её структуре. Второе занятие посвящено созданию программы по индивидуальному заданию. Результатом работы является созданная программа и отчет, включающий: титульный лист; схему алгоритма; тестовый пример (для вычислительных задач). Каждая работа заканчивается зачетом по теоретическому материалу рассматриваемой темы и созданной программе. Замечание. Для выполнения практических заданий подходят все версии Delphi. 1. ЗНАКОМСТВО СО СРЕДОЙ ПРОГРАММИРОВАНИЯ BORLAND DELPHI Цель: Получить представление об оболочке программирования Delphi, уметь запустить оболочку, создать простейшую программу. 1.1. ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ Оболочка Delphi. Для запуска оболочки Borland Delphi (в дальнейшем будем использовать обозначение Delphi) необходимо выполнить следующие операции: Выбрать в главном меню MS Windows пункт «Пуск/Программы/Borland Delphi X/Delphi X». Здесь Х обозначает номер версии. Запуск может быть осуществлён и с помощью значка Delphi на «Рабочем столе» (если этот значок там есть). Значок иконки оболочки Delphi в зависимости от версии показан на рис. 1.1. Окна Delphi показаны на рис. 1.2. Условно оболочка представляет 4 основных окна: «Главное окно системы», окно «Инспектор объектов», окно «Визуальный проектировщик форм» и окно «Редактор программы». Borland Delphi Версия 1 и 2 Borland Delphi Версия 3 Ivory Borland Delphi Версия 3 и 4 Inprise Delphi Версия 5 Inprise Delphi Версия 6 Рис.1.1. «Иконка» среды программирования Borland Delphi При создании программы в Delphi приняты понятия проект и модуль. Это связано с модульным способом построения программ. Главная программа называется проектом и содержит ссылки на дополнительные файлы – модули, используемые главной программой. 3 При создании в Delphi программы создаются следующие типы файлов: 1. имя1.dpr – имя файла проекта. Имя создаваемой программы определяется именем проекта; 2. имя2.dfm – имя визуального образа создаваемой программы; 3. имя2.pas – имя модуля программы, содержащей текст событий визуального образа; 4. имя1.cfg.,имя2.dcu, имя1.dof, имя1.dsk, имя1.dsm, имя1.res – вспомогательные файлы; 5. *.~* – резервные копии файлов; 6. имя1.exe – файл созданной программы. Для сохранения программы необходимы файлы, указанные в пунктах 1,2,3. Остальные файлы создаются автоматически при компиляции программы. Главное окно Delphi Окно редактора программ Визуальный проектировщик форм Окно настройки свойств и событий объектов Рис.1.2. Интегрированная среда программирования Borland Delphi «Главное окно» состоит из меню системы, панели инструментов, панели визуальных компонентов (рис 1.3.). Меню команд содержит команды Delphi для управления проектом. Панель инструментов содержит иконки кнопок «быстрого доступа» к некоторым командам меню. Панель визуальных компонентов содержит иконки всех визуальных компонент, кото4 рые программист может использовать в своей программе, для удобства визуальные компоненты сгруппированы по назначению и расположены на различных вкладках – Standard, Additional, Win32 и т.д. Меню системы Панель инструментов Панель визуальных компонентов Рис.1.3. «Главное окно Delphi» Инспектор объектов (Рис.1.4) состоит из двух частей (вкладок) – Properties (Свойства) и Events (События). В верхней строке указан визуальный компонент (объект), для которого настраивается свойства и события. Настроить свойство объекта (вкладка «Properties») можно тремя способами – набрать свойство в строке ввода, выбрать свойство из списка (значок ) и воспользоваться мастером настройки свойств (значок ). Некоторые свойства содержат подствойства, доступ к которым можно получить, щелкнув Обозначение объекта Настраиваемые события Настраиваемые свойства Свойство имеет подсвойства Свойство выбирается из списка Для настройки свойства служит «Мастер» Рис.1.4. Окно «Object Inspector» мышью на значке , чтобы свернуть список подствойств необходимо щелкнуть на значок . Для заполнения событий визуального объекта необходимо выбрать вкладку «Events». Чтобы запрограммировать событие необходимо щелкнуть на выбранном свойстве, при этом становится активным «окно редактора программ». Визуальный проектировщик форм представляет собой окно создаваемой программы. В Delphi есть шаблоны для создания некоторых «специ5 альных» окон: Окно о программе (About), различные диалоговые окна и т.д. Для создания такого окна необходимо при создании новой формы (вид создаваемого окна) выбрать необходимый шаблон в галерее форм. Для этого необходимо выполнить пункт меню в главном окне File/New form (в пятой версии Delphi – File/New…), значок . После создания окна необходимо настроить свойства окна (имя (Name) объекта окно, заголовок, цвет и др.) После этого на окне размещают другие визуальные компоненты. Для этой цели выбирают в главном окне в панели визуальных компонентов необходимый компонент и помещают его на форме (щелкают на выбранном элементе, затем щелкаю на форме в том месте, где должен быть расположен этот компонент). Для точного изменения размера компонента можно использовать комбинацию клавиш на клавиатуре <Shift> и <’стрелки’>. В инспекторе объектов эти свойства задаются в строках Height – высота объекта в пикселях и Width –ширина объекта. Для точного позиционирования объекта в форме можно использовать комбинации клавиш <Ctrl> и <’стрелки’>. Это свойства Top – верхний левый угол объекта и Left – левый край объекта. При помещении на форму визуального компонента, каждый компонент получает собственное имя (свойство Name). Это имя позволяет обращаться к этому объекту при программировании. Имя построено так, что содержит в названии имя класса, к которому относится объект и порядковый номер используемого элемента данного класса. Пример, имя Form1 – указывает на элемент формы и показывает, что это первый элемент класса Form. Рекомендация: необходимо изменять имена элементов, чтобы было понятно для чего нужен этот элемент. Но чтобы показать к какому свойству относится объект оставлять заглавные буквы от класса. Пример, Fmain – объект класса Form (буква ‘F’), который обозначает главное окно (‘Main’); BBQuit – объект класса BitBtn (кнопка с картинкой), на что указывает буквы ‘BB’ и эта кнопка служит для выхода из программы (‘Quit’ – выход). Но те объекты, которые будут использоваться только как видимые элементы можно не переименовывать. При выборе визуального компонента, для которого необходимо написать событие (Пример, для кнопки BBQuit написать команду выхода из программы), выбирают в Object Inspector вкладку Events и выбирают необходимое событие – onClick (щелчок мыши), onKeyPress (нажатие клавиши) и др. – и щелкают на нем мышью. Некоторое событие является событием «по умолчанию», то есть если в окне проектировщика форм выбрать визуальный элемент и дважды на нем щелкнуть, то будет программироваться именно это событие (это событие расположено первым в списке событий). При этом становится активным окно Редактора программ. При создании модуля программы часть стандартного текста вводится автоматически. 6 Структура модуля следующая: unit Модуль; {имя модуля программы} {************} interface {Описание интерфейсной части} {Разделы доступны другим модулям, использующим этот:} uses {Раздел модулей – модули, используемые в программе} Мод1, МодN; {Имена используемых модулей: «Мод1», «МодN»} Const {Раздел констант} Конст1 = Знач1; {Присвоение значения «Знач1» константе «Конст1»} Type {Раздел типов - используемые типы} Тип1 = описание1; {Описание типа с именем «Тип1»} var {Раздел переменных - используемые переменные} Пер1 : Тип1; {Описание переменной «Пер1» типа «Тип1»} {************} implementation {раздел описания модуля} {Разделы доступны глобально внутри модуля:} Uses {Раздел модулей - модули используемые в программе} Мод2; {Внутри модуля используется модуль «Мод2»} Const {Раздел констант} Конст2 = Знач2; {Присвоение значения «Знач2» константе «Конст2»} Label {Описание раздела меток} Метка1; {Описание метки с именем «Метка1»} Type {Раздел типов - используемые типы} Тип2 = описание2; {Описание типа с именем «Тип2»} var {Раздел переменных - используемые переменные} Пер2 : тип2; {Переменная «Пер2» типа «Тип2»} {************} procedure Проц1; {Описание процедуры с именем «Проц1»} {Разделы доступны локально внутри процедуры:} Type {Раздел типов - используемые типы} Тип3 = описаине3; {Описание типа с именем «Тип3»} var {Раздел переменных - используемые переменные} Пер3 : Тип3; {Переменная «Пер3» типа «Тип3»} Begin {Начало описания процедуры «Проц1»} Операция1; {Тело процедуры «Проц1», выполняющих «Операцию1»} end; {Конец описания процедуры «Проц1»} end. {Конец описания модуля «Модуль»} Таким образом, модуль представляет собой три части: 1. Описание типов, констант, процедур доступных другим программам использующих этот модуль; 2. Описание типов, констант и т.д. используемых в данном модуле (это раздел глобальных переменных); 3. Описание самих процедур со своими типами и константами (раздел локальных переменных). Для каждого оператора или группы операторов может быть написан комментарий. Комментарий заключается в «фигурные скобки». Если необходимо закомментировать одну строку можно использовать символы 7 «двойной слеш». Если необходимо закомментировать часть программы, где уже имеются комментарии, то необходимо использовать «круглые скобки со звездочкой»: //комментарий одной строки {комментарий части текста} (*Комментарий {текста} с комментариями*) При написании текста модуля имеет смысл использовать отступы в описании конкретных разделов, что дает возможность видеть начало и конец соответствующего раздела. Некоторые команды редактора. При написании программы можно использовать следующие комбинации клавиш для упрощения набора текста: Справка: <F1> – выдает справку (если курсор указывает на стандартный оператор, то будет выдана справка по этому оператору); Переключение между окнами: <F12> – переключает окна Визуальный проектировщик и Редактор программ; <F11> – делает активным окно Инспектор Объектов; <F10> – делает активным Главное окно Delphi. Перемещение по тексту: <> <> <> <> – передвинуть курсор вверх, вниз, вправо, влево; <PgUp>, <PgDn> – передвижение на страницу вверх, вниз; <Ctrl><PgUp>, <Ctrl><PgDn> – передвижение в начало текста, конец текста. Ввод и удаление текста: <Insert> – режим «вставки»/«замены» – текущий режим показан внизу окна Редактор программ – «Insert» (вставка) или «Overwrite» (замена); <Enter> – добавить новую строку; <Delete>, <BackSpace> – удалить символ в позиции курсора (Delete) или слева от курсора (BackSpace); <Alt><BackSpace> – восстановить текст (Пример, удаленный фрагмент). Работа с фрагментом текста: <Shift><«стрелки»>– выделение текста («окраска» текста инвертируется); <Ctrl><Insert> – поместить фрагмент в буфер обмена; <Shift><Delete> – удалить фрагмент в буфер обмена; <Shift><Insert> – вставить текст из буфера обмена; <Ctrl><K><H> – снять выделение фрагмента; <Ctrl><K><U> – сдвинуть фрагмент на символ влево; 8 <Ctrl><K><I> – сдвинуть фрагмент на символ вправо. Установка закладок: В большом тексте для облегчения перемещения по тексту можно устанавливать закладки. <Ctrl><K><«N»> - установить закладку с номером «N» (N номер закладки, в левой позиции строки появится символ с номером закладки, в данном случае номер «1» (комбинация клавиш <Ctrl><K><1>)) <Ctrl><K><«N»> - перейти на закладку с номером «N». Компиляция и запуск программы: <Ctrl><F9> - компиляция программы (создание файла с расширением «exe» без запуска программы); <F9> - запуск программы. 1.2. СОЗДАНИЕ ПРОГРАММЫ «МОЯ ПЕРВАЯ ПРОГРАММА» Задача: В качестве первой программы необходимо создать программу «Цветное окно с картинкой». Примерный вид окна программы показан на рис. 1.5. Рис.1.5. Примерный вид окна первой программы Процесс создания программы происходит по следующему алгоритму: 1. Запустить оболочку Delphi из пункта меню MS Windows или с «Рабочего стола»; 2. Сохранить проект в рабочем каталоге с помощью команды «File/Save Project As…», значок в Главном окне Delphi. Необходимо изменить предлагаемые по умолчанию имена на следующие: файл с расширением «dpr» назвать «Work1.dpr» (так будет называться файл создаваемой программы); модуль – файл с расширением «pas» назвать «main», то есть это главное окно программы. Рекомендация: имеет смысл каждый создаваемый проект хранить в отдельной папке; в именах файлов можно использовать только латинские буквы без пробелов!; 3. Настройка окна программы: Назвать форму FMain Окно Object Inspector, вкладка Properties, свойство Name; Заголовок окна изменить на Программа №1 свойство Caption; 9 4. Изменить свойство Position на poScreenCenter для вывода окна программы в центре экрана; Изменить цвет окна на свой «любимый цвет», выбрав цвет из списка свойство Color; Изменить иконки окна программы свойство BorderIcons, установить все подсвойства в значение False (в программе отсутствуют все системные кнопки окна); Поместить на форму картинку объект Image на вкладке Additional Па- нели визуальных компонент в Главном окне Delphi, иконка значка . На форме появится место будущей картинки. Картинка может быть отображена двумя способами: либо занять место, определенное пользователем (рамка картинки) либо изменить рамку под реальные размеры картинки. Для настройки картинки необходимо изменить следующие свойства: Свойство Picture загружает «мастера» для выбора картинки из файла. Выберите любой файл с картинкой из имеющихся на жестком диске. В состав Delphi входит набор картинок. Их можно получить из папки Image\Splash, находящейся в папке Delphi (для версий 1-2); или в папке Program Files\Common Files\Borland Shared\Image\Splash (для остальных версий). Картинки находятся в двух папках 16 Color и 256 Color в зависимости от используемых в картинке цветов; Свойство AutoSize – при значении true значения установленные пользователем для картинки (свойства Width – ширина и Height – высота) будут изменены в соответствии с реальными размерами картинки; Свойство Stretch – при значении true размеры картинки будут адаптированы к размерам установленных пользователем (указанных в свойствах Width и Height); (Замечание: Свойства AutoSize и Stretch являются взаимно исключающими). Свойство Transparent – при значении true картинка будет иметь прозрачный фон; 5. Поместить на форме кнопку для выхода из программы. Можно установить кнопки двух типов – простую объект Button, вкладка Standard, с иконкой объекта , или с картинкой объект BitBtn, вкладка Additional, значок . Изменить свойства: Name, если установлена кнопка Button изменить на BQuit, если кнопка BitBtn – BBQuit; Если установлена кнопка BitBtn установить тип кнопки – свойство Kind установить в bkOK (автоматически устанавливается картинка (свойство Glyph) кнопки и заголовок (свойство Caption)); 6. Поместить на форму метку для подписи к картинке объект Label, вкладка Standard, значок . Изменить свойства: Caption – заголовок, изменить на название помещенной картинки; Font – шрифт текста, запускает мастера для настройки названия, цвета и стиля шрифта метки. 7. Запрограммировать выход при щелчке по кнопке: Активный элемент, то есть элемент, свойства которого настраиваются, вы10 делен рамочкой , если рамочки нет не на одном элементе, то активна форма. Выбрать элемент установленной кнопки на форме (вокруг кнопки будет рамочка); Дважды щелкнуть по кнопке мышкой – будет выполнено событие onClick на вкладке Events в Object Inspector (это событие является событием «по умолчанием»). Станет активным окно Редактора программ. Автоматически будет создана процедура для программирования события onClick. текст. Пример, если была использована кнопка BBQuit, текст будет следующим: Procedure TFMain.BBQuitClick(Sender: TObject); begin end; В теле созданной процедуры (между операторными скобками begin и end) вписать команду закрытия окна – Close. Так как у нас одно окно, то закрытие окна приведет к выходу из программы. Текст программы станет таким: Procedure TFMain.BBQuitClick(Sender: TObject); begin Close; end; Обратите внимание! После слова «Close» стоит знак «;», так как на языке Паскаль необходимо ставить знак «точка с запятой» – «;» после каждой команды. 8. Программа создана! Для запуска программы необходимо: Сохранить программу команда File/Save All, значок в меню Главного окна Delphi; Запустить программу Run/Run, в меню Главного окна Delphi или щелк- 9. нуть на значок на Панели инструментов в Главном окне Delphi; Выход из оболочки Delphi осуществляется выбором команды File\Exit, значок 10. Если при следующем запуске Delphi потребуется загрузить проект, то это можно осуществить через пункт File/Open Project, значок в Главном окне Delphi. 1.3. ИТОГИ В первой теме были изучены: оболочка Delphi; структура программы; команды редактора. При создании демонстрационной программы были получены навыки работы со следующими командами и визуальными компонентами: окном формы Form; кнопкой Button; кнопкой с картинкой BitBtn; рисунком Image; меткой Label; командой закрытия окна Close. 2. УСЛОВНЫЕ ОПЕРАТОРЫ Цель: изучение типов переменных, описание переменных и констант, операций с переменными; изучение условных операторов. 11 2.1. ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ Типы данных. Язык Object Pascal предоставляет ряд типов данных. Все они построены на базе стандартных типов стандарта языка Паскаль: Integer – целый тип, переменные этого типа могут принимать положительные и отрицательные числа в диапазоне от –32768 до 32767; Real – вещественный тип, переменные этого типа могут принимать положительные и отрицательные числа, записываемые как в простой форме: 10.12, 5.6, так и в экспоненциальной: 2.123Е5 (=2.123*105), 0.854Е-3 (=0.854*10-4). Диапазон чисел этого типа от 2.9Е-39 до 1.7Е38; Char –символьный тип, переменные этого типа служат для записи значений символов, которые должны заключаться в прямые кавычки: ‘A’, ‘ю’, ‘7’ – переменная содержит символы А, ю, 7; Boolean – логический тип, переменные этого типа могут принимать только два значения true (истина) и false (ложь); Перечисляемый тип – указывает возможные значения переменной, Пример: 1, 5, 45, 56 – переменная такого типа может содержать только одно из перечисленных чисел. На базе стандартных типов переменных созданы все остальные типы Object Pascal. Сводная таблица типов Object Pascal представлена в таблице 2.1 (ячейки стандартных типов выделены). Таблица 2.1 Целые числа Диапазон Формат -128…127 Знаковый, 8 бит -32768…32767 Знаковый, 16 бит -2147483648…2147483647 Знаковый, 32 бита 0…255 Беззнаковый, 8 бит 0…65535 Беззнаковый, 16 бит –32768…32767 Знаковый, 16 бит 0..65535 Беззнаковый, 16 бит –2147483648…2147483647 Знаковый, 32 бита 0… 2147483647 Беззнаковый, 32 бита –9.2*1018 …9.2*1018 Целый, абсолютно точный Вещественные числа Диапазон Кол-во цифр Кол-во байт -39 +38 2.9*10 …1.7*10 11–12 6 1.5*10-45…3.4*10+38 7–8 4 -324 +308 5.0*10 …1.7*10 15–16 8 3.4*10-4932…1.1*10+4932 19–20 10 Символы Символы Коды ANSI 0…255 Unicode 0…65535 ANSI 0...255 Тип данных ShortInt SmalInt LongInt Byte Word Integer Поддержка 16 разрядов Cardinal Integer Поддержка 32 разряда Cardinal Comp Тип данных Real Single Double Extended Тип данных AnsiChar WideChar Char 12 Таблица 2.1 (продолжение) Строки Тип String ShortString LongString WideString Тип Boolean Тип строки Статическая длина от 0 до 255 символов Длина ограничена объемом памяти Тоже, но каждый символ Unicode-символ (16 бит) Логический Значение True (истина), False (ложь) Динамический Переменные и константы. Для описания переменных служит раздел переменных, начинающийся ключевым словом Var. Переменные могут быть глобальными (переменная доступна в любом месте программы) и локальными (переменные доступны только в той процедуре, в которой они описаны). Объявление переменной выглядит так: имя : тип; где имя – имя объявляемой переменной; тип – один из типов языка Object Pascal. Пример: var a,b,c: real; S : String; В примере введены три переменные типа real и одна переменная string. Однотипные переменные можно перечислять через запятую. Замечание: имя переменной может содержать только латинские буквы и не зависит от выбранного регистра, то есть переменные s и S – это одна и та же переменная. Удобно записывать разнотипные переменные на разных строках. При назначении переменной значения используется оператор «присвоить» – «:=». В общем виде присвоение выглядит так: Имя := Выражение; Пример: k := 5; – присвоить переменной k значение 5; с := 5 + t; – присвоить переменной с значение 5 + t . В языке Паскаль существует два вида констант: обычные и именованные. Обычная константа – это целое или дробное число, строка символов или отдельный символ, логическое значение. Именованные константы, как и переменные, перед использованием должны быть объявлены в разделе описания констант. Описание именованной константы в общем виде: Константа = значение; где константа – имя объявляемой константы; значение – значение именованной константы. 13 Пример: Const Ch = ‘S’; // Константа Ch содержит символ S V = 3; // Константа V содержит значение цифры 3 Тип константы определяется ее значением. После объявления константы в инструкциях программы вместо значения константы можно использовать её имя. Операции с переменными. Выражение состоит из операторов и операндов. Операции находятся между операндами. Операндами могут быть константы и/или переменные. Операции определяют действия, выполняемые над операндами. В таблице 2.2 указаны операторы, их действия и тип полученного выражения. Таблица 2.2 Оператор Действие + Сложение - Вычитание * умножение / div Деление Деление нацело Остаток от деления mod Оператор Действие and Дизъюнкция («И») or Конъюнкция («ИЛИ») Not Оператор > < = <> >= <= Инверсия (Отрицание) Описание Больше Меньше Равно Не равно Больше или равно Меньше или равно Тип оператора Если один операнд real все integer Если один операнд real все integer Если один операнд real все integer real или integer Всегда integer Тип выражения Real Integer Real Integer Real Integer Real Integer Всегда integer Integer Логические операторы Операнд1 Операнд2 Результат False false false False true false True false false True true true False false false True false true False true true True true true false true true false Значение выражения True, если первый операнд больше второго, иначе False True, если первый операнд меньше второго, иначе False True, если первый операнд равен второму, иначе False True, если первый операнд не равен второму, иначе False True, если первый операнд больше или равен второму, иначе False True, если первый операнд меньше или равен второму, иначе False Условные операторы. Условный оператор позволяет выбирать одно из двух действий, причем выбор осуществляется во время выполнения про14 граммы. Существует 2 вида условных операторов: 1. If условие then действие; 2. If условие then действие1 else действие2. где условие – выражение логического типа; действие1, действие2 – отдельные операторы или операторы, сгруппированные вместе при помощи операторных скобок begin и end. Такой оператор называется составным. Графически операторы условия изображены на рис 2.1. Условие ложь истина действие Оператор первого типа истина действие1 ложь Условие действие2 Оператор второго типа Рис. 2.1. Структурная схема условного оператора Замечание: над потоками должны быть указаны значения условия, при котором выполняется действия (на рисунке это «истина» и «ложь»). Для оператора первого типа, если выражение условие принимает значение true, выполняется действие, стоящее после ключевого слова then. Если же значение условие равно false, то действие не выполняется. Пример: If X > Y then X := 5; - значение переменной Х станет равным 5 только в том случае, если выполняется условие X > Y, в противном случае значение Х останется без прежним. Для оператора второго типа, если условие принимает значение true, то выполняется действие1, стоящее после оператора true, при значении условия false выполняется действие2, стоящие после оператора else. Пример: If X > Y then X := 5 else X := 3; - значение переменной Х станет равным 5 при условии X > Y, при невыполнении условия Х станет равным 3. Замечание 1: перед оператором else значок «точка с запятой» не ставится! Замечание 2: в условном операторе выполняется только один оператор стоящий после слов then или else, если требуется выполнить несколько операторов, необходимо поместить операторы между операторными скобками begin и end. Пример, переменные X и Y должны получить значения 5 и 23 соответственно при выполнении условия А>0 и обнуляются (получают значение 0), если A<0. Оператор условия будет выглядеть так: If A > 0 then 15 begin X := 5; Y := 23; end else begin X := 0; Y := 0; end; Операторы, следующие после then или else, в свою очередь также могут быть условными операторами. 1. Условный оператор первого типа - If условие then действие Оператор действие может быть условным оператором первого типа (рис. 2.2.). Тогда будет конструкция: If условие1 then истина If условие2 then действие Условие 1 В этом случае оператор действие опреложь истина Условие 2 деляется однозначно. Оператор действие ложь может быть условдействие ным оператором второго типа, тогда будет конструкция: Рис. 2.2. If условие1 then If условие2 then действие1 else действие2. Возникает вопрос: какому оператору then соответствует else? (Рис. 2.3). Для обеспечения однозначности в языке Паскаль принято соглашение о том, что каждому else соответствует предыдущий свободный then. 2. Условный оператор второго типа – If условие then действие1 else действие2 Оператор действие1 условный оператор первого типа, оператор действие2 не является условным оператором (Рис. 2.4.). Получаем конструкцию: If условие1 then begin If условие2 then действие1 end else действие2. 16 Видно, что оператор действие1необходимо заключить в операторные скобки, их отсутствие приведет к схеме на рис.2.3. Рекомендации: истина 1. Для упрощения чтения Условие 1 текста программы при описании условных ложь истина операторов испольУсловие 2 зуйте лидирующие пробелы для выделения ложь каждого раздела. 2. Если возникают Действие1 Действие2 трудности в оценке порядка выполнения действий в условном Рис. 2.3. операторе, используйте операторные скобки. Оператор выбора. Если при построении условного оператора известны большинство возможных значений условия, то необходимо использовать оператор выбора. В общем виде структура истина этого оператора следуУсловие 1 ющая: Case переменная of истина ложь Значение1 : Условие 2 Действие1; ложь … ЗначениеN : Действие2 Действие1 ДействиеN; else ДействиеN1; end; Рис. 2.4. где Переменная – переменная перечисляемого типа (например: integer, char); Значение1, … , ЗначениеN – возможные значения переменной; Действие1, … , ДействиеN – действия, выполняемые при значении переменной равному одному из значений Значение1, … ,ЗначениеN; ДействиеN1 – действие, выполняемое в случае, когда переменная не принимает ни одно из перечисленных значений (Значение1, … , ЗначениеN). Структурная схема оператора выбора показана на рисунке 2.5. Также, как и при использовании условного оператора, если Действие представляет собой несколько операторов их нужно поместить в 17 операторные скобки begin и end. Действие, выполняемое при отсутсвии значения переменной может отсутсвовать тогда схема оператора выбора будет следующей: Case переменная of Значение1 : Действие1; … ЗначениеN : ДействиеN; end; Условие Значение1 Действие1 ЗначениеN Значение2 Действие2 … ДействиеN иначе ДействиеN+1 Рис. 2.5. Оператор выбора Замечание: Оператор Case всегда оканчивается оператором end. Очень удобно использовать оператор выбора при анализе нажатия клавиш клавиатуры. Пример: Пусть в разделе переменных описана переменная Ch типа Char. Case Ch of ‘W’ : Y := Y + 1; ‘X’ : Y := Y – 1; end; В примере анализируется переменная Ch. Если Ch содержит символ «W», то переменная Y увеличивается на 1; Если Ch содержит символ «X», то переменная Y уменьшается на 1. 2.2. СОЗДАНИЕ ПРОГРАММЫ «ПОПАДАНИЕ ТОЧКИ В ФИГУРУ» Задача: Дана сложная фигура, вписанная в квадрат с координатами: левый нижний угол (5,5), верхний правый угол (20,20). Требуется написать программу для определения попадания точки с введенными координатами в указанную фигуру. Примерный вид окна программы показан на рис. 2.6. Процесс создания программы происходит по следующему алгоритму: 1. Запустить программу Delphi; 2. Сохранить проект как «Work2», модуль назвать «Main»; 3. Создать образ окна: Изменить заголовок на «Попадание точки в фигуру»; 4. Создать изображение фигуры: Поместить в форму элемент Shape, вкладка Additional, значок Изменить свойства объекта: ; 18 o Изменить размер объекта для обеспечения попадания в окно 3 элементов по вертикали и трех по горизонтали, элемент должен быть квадратом; o Изменить цвет квадратика (свойство Brush/Color и Pen/Color); Скопировать образ квадратика в буфер обмена (при классической раскладке кла- Рис. 2.6. Примерный вид окна программы «Попадание точки в фигуру» виатуры в Delphi это комбинация <Ctrl><Ins>); Поместить на форму 7 копий квадратика из буфера обмена (<Shift><Ins>); Разместить квадратики в фигуру «квадратный бублик» (см. рис.2.6). Необходимо обеспечить пустое пространство внизу и слева от фигуры для размещения начала координат – в левом нижнем углу фигуры должен «поместиться» как бы еще один квадратик; 5. Создать 2 элемента для ввода координат точки: Поместить на форму 2 элемента SpinEdit, вкладка Samples, значок ; Назвать один элемент SECoordX (для координаты X) и SECoordY (для координаты Y) свойство Name (в дальнейшем изменяемое свойство будет обозначаться после стрелки); Настроить минимальное возможное значение вводимого числа 0, максимальное – 25, значение по умолчанию 0 и шаг изменения величины 1 соответственно MinValue, MaxValue, Value и Increment; 6. Добавить надписи к полям ввода: Поместить 2 элемента Label, вкладка Standard, значок ; Настроить надписи на «Координата X» и «Координата Y» Caption; 7. Добавить метку для вывода результата попадания точки: Поместить элемент Label, вкладка Standard, значок ; Назвать элемент LResult Name; Изменить заголовок на «Мимо» Caption; 8. Добавить кнопки для запуска вычислений и выхода из программы: 19 Добавить 2 элемента Button, вкладка Standard, значок ; Назвать кнопку для выхода BQuit, а кнопку для вычисления BOk Name; Изменить заголовки кнопок на «Выход» и «Ok» Caption; 9. Образ окна создан! 10. Запрограммировать выход – щелкнуть на кнопке BQuit и ввести команду Close; 11. Проанализировать форму фигуры для создания алгоритма – в нашем случае проверить попадание в большой квадрат и проверить не попадает ли точка во внутренний квадрат; 12. Вернуться на форму (клавиша <F12>) и запрограммировать кнопку BOk: Щелкнуть дважды на кнопке BOk; Записать оператор проверки координат. (Координаты можно получить у элементов SECoordX и SECoordY через свойства Value – обращение к свойству объекта осуществляется через «точку» - например: SECoordX.Value дает значение свойства Value элемента SECoordX. SECoordX.Value дает значение введенной координаты X, SECoordY.Value дает значение введенной координаты Y.): If (((SECoordX.Value >= 5) and (SECoordX.Value <= 20) and { попадание Х в большой квадрат} (SECoordY.Value >=5) and (SECoordY.Value <= 20))and { попадание Y в большой квадрат} Not ((SECoordX.Value >10) and (SECoordX.Value < 15) and {не попадание Х в малый квадрат} (SECoordY.Value > 10) and (SECoordY.Value < 15))) { не попадание Y в малый квадрат} then LResult.Caption := ‘Попал’{Вывод сообщения «Попал» } else LResult.Caption := ‘Мимо’;{Вывод сообщения «Мимо» } 13. Запустить программу <F9> 14. Для улучшения программы необходимо: Перерисовывать результат сразу при вводе координат; Добавить «точку» для визуализации положения точки. 15. Для реализации пункта 14а необходимо: Выбрать элементы SECoordX и SECoordY (удерживая клавишу <Shift> щелкнуть сначала на одном элементе, затем на другом – оба элемента будут отмечены рамочкой - это позволит настраивать общие события для выделенных элементов одновременно); Настроить событие (вкладка Events в Object Inspector) onChange так, чтобы оно указывало на событие BOkClick (выбрать это событие из списка). Таким образом, для этих элементов событие onChange будет равносильно событию onClick для кнопки BOk – при смене координат сразу будет выполняться нажатие кнопки «Ok»; Так как кнопка «Ok» обрабатывается автоматически можно сделать эту кнопку «невидимой» - изменить свойство Visible в значение false для объекта BOk. При запуске программы кнопка «Ok» видна не будет. 16. Для реализации пункта 14b необходимо: Добавить точку на экран – элемент Shape, вкладка Additional, значок Изменить свойства этого элемента: o Name изменить на значение SPoint; ; 20 o Shape изменить на stCircle; o Width изменить на 3 – ширина точки будет равна 3 пикселя; o Height изменить на 3 – высота точки. Пересчитать начало координат «виртуальные» системы координат программы в координаты экрана (координаты экрана отсчитываются с верхнего левого угла экрана вниз и вправо): o Необходимо выяснить свойство Name для левого нижнего квадратика – пусть его имя ShapeN; o Элемент ShapeN имеет свои координаты левого верхнего угла – свойства Top и Left; также этот элемент имеет свойства ширины и высоты – Width и Height, таким образом, координаты начала координат равны: ShapeN.Left – ShapeN.Width и ShapeN.Top + 2*ShapeN.Height; o Рассчитать цену деления координатной сетки: для этого необходимо поделить длину и ширину квадратика на 5. ShapeN.Width div 5 даст шаг по координате X, а ShapeN.Height div 5 - по координатеY. Изменить текст события BOkOnClick: o Щелкнуть на кнопке BOk; o В начале процедуры дописать текст присвоения «точке» (объект SPoint) новых координат – к началу координат добавить величину X или Y умноженную на шаг координате X или Y: o SPoint.Left := ShapeN.Left – ShapeN.Width + SECoordX.Value * (ShapeN.Width div5); o SPoint.Top := ShapeN.Top + 2*ShapeN.Height - SECoordY.Value * (ShapeN.Height div5); 17. Запустить программу (клавиша <F9>) 2.3. ИНДИВИДУАЛЬНОЕ ЗАДАНИЕ Создать программу по заданию программы, рассмотренной выше, используя шаблон в соответствии с номером варианта: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 2.4. ИТОГИ Во второй теме были изучены: типы переменных; операции над операндами; условные операторы. При создании демонстрационной программы были получены навыки работы со следующими командами и визуальными компонентами: элементом фигура Shape; элементом изменения значения цифр SpinEdit; связыванием событий объектов. 21 3. ОПЕРАТОРЫ ЦИКЛА Цель: Изучение стандартных функций; метки; изучение операторов цикла; отладка программ. 3.1. ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ Стандартные функции. Для выполнения часто встречающихся вычислений и преобразования данных в Object Pascal существуют стандартные функции. Некоторые стандартные арифметические функции перечислены в таблице 3.1. Таблица 3.1 Функция Abs(n) Sqr(n) Sqrt(n) Sin(n) Cos(n) ArcTan(n) Exp(n) Ln(n) Действие Абсолютное значение значения n Число n в степени 2 Корень квадратный из числа n Синус числа n Косинус числа n Арктангенс числа n Число е в степени n Натуральный логарифм числа n Для более сложных расчетов необходимо подключить к программе модуль Math. Для этого в разделе описания модулей (например, после слова implementation) добавить следующие строки: Uses Math; Некоторые функции из этого модуля (арифметические, тригонометрические и для перевода углов из одной системы в другую) представлены в таблице 3.2. Таблица 3.2 Функция Lnxp1(x) Ceil(x) Floor(x) Frexp(x,m,e) IntPower(a,x) LdExp(x,p) Log10(x) Log2(x) LogN(n,x) Max(a,b) Min(a,b) Poly(x,C) Power(a,x) Действие Арифметические Натуральный логарифм числа (x + 1) (использовать при х близких к 0) Ближайшее большее число к х Ближайшее меньшее число к х Мантисса m и порядок e числа х а в целой степени х – ах Число х, умноженное на 2 в целой степени р – х*2р Десятичный логарифм числа х (Lg(x)) Двоичный логарифм числа х (Lb(x)) Логарифм по основанию n числа х (Lognх) Максимальное число из двух чисел а и b Минимальное число из двух чисел а и b Степенной ряд с коэфф. С (массив) – с0 + с1х + с2х2+…+ сnxn Число а в степени х (ах) 22 Таблица 3.2 (Продолжение) PI ArcCos(x) ArcCosH(x) ArcSin(x) ArcSinH(x) ArcTanH(x) CosH(x) Cotan(x) Hypon(a,b) SinCos(r,s,c) SinH(x) Tan(x) TanH(x) Тригонометрические Число ( ≈3,1415926535897932385) Арккосинус х Гиперболический арккосинус х Арксинус х Гиперболический арксинус х Гиперболический арктангенс х Гиперболический косинус х Котангенс х (Cos(x) / Sin(x)) Гипотенуза прямоугольного треугольника - a 2 b 2 Синус s и косинус с угла r в радианах Гиперболический синус х Тангенс х (Sin(x) / Cos(x)) Гиперболический тангенс х Перевод углов из одной системы в другую CycleToRad(x) Перевод периодов х в радианы (1 период соответствует 2) DegToRad(x) Перевод градусов х в радианы (180 соответствует ) Перевод величины x, представленной в радианах, в периоды RadToCycle(x) (2 соответствует период) Перевод величины х, представленной в радианах в градусы RadToDeg(x) ( радиан соответствует 180) Статистические расчеты Генерация случайного числа по распределению Гаусса, задаетRandG(m,sd) ся m – математическое ожидание, sd-стандартное отклонение MaxIntValue(D) Максимальное число из массива целых чисел D MaxValue(D) Максимальное число из массива чисел D Mean(D) Среднее число массива D MeanAndStdDev(D, Среднее число m и квадратичное отклонение sd массива D m,sd) MinIntValue(D) Минимальное число массива целых чисел D MinValue(D) Минимальное число массива чисел D Квадратичное отклонение массива D StdDev(D) Sum(D) Сумма всех чисел массива D SumInt(D) Сумма всех целых чисел массива D Функции преобразования типов. Функции преобразования служат для преобразования переменной одного типа к другому типу. Наиболее часто такие функции используются при вводе и выводе информации. Пример, для вывода значения переменной числового типа в поле ввода необходимо преобразовать значение в строковый тип, так как поле ввода позволяет выводить только строки. В таблице 3.3 перечислены основные функции преобразования типов. Таблица 3.3 Функция Chr(n) Значение Символ в стандарте ANSI с номером n 23 Таблица 3.3 (Продолжение) IntToStr(n) FloatToStr(n) FloatToStrF(n,f,l,m) StrToInt(s) StrToFloat(s) Round(n) Trunc(n) Frac(n) Int(n) Преобразование целого числа n в строку Преобразование вещественного числа n в строку Преобразование вещественного числа n в строку с форматом f, длинной строки l и количеством m цифр после десятичной точки Преобразование строки s в целое число Преобразование строки s в вещественное число Ближайшее к n целое Целая часть от n Дробная часть вещественного числа n Целая часть вещественного числа n Операторы цикла. При разработке алгоритмов решения большинства задач возникает необходимость повторения ряда шагов. Для организации новых повторов (циклов) можно использовать три разновидности операторов цикла: с параметром, с предусловием, с постусловием. Каждую разновидность цикла можно реализовать с помощью условного оператора и безусловного перехода (см. ниже). Если число повторений тела цикла заранее известно, то применяется оператор цикла с параметром. Структурная схема представлена на рис.3.1. Общий вид следующий: For переменная := нач_значение to кон_значение do тело или For переменная := нач_значение downto кон_значение do тело I := NV где переменная – параметр цикла, в качеТело цикла стве параметра может быть использована любая переменная перечисляемого типа (например, integer); I := KV нач_значение и кон_значение – выражения, задающие начальное и конечное значение параметра Рис. 3.1. Цикл с параметром цикла соответственно; тело – простой или составной оператор. Тип начального и конечного значений цикла должны совпадать с типом параметра цикла. Выполнение оператора цикла начинается с проверки условия переменная <= конзн для цикла to и переменная >= конзн для цикла downto. Если оно не выполняется, то оператор тело не выполняется и управление передается следующему за циклом оператору. Если же условие истинно, то выполняется оператор тело, затем параметру цикла переменная присваивается следующее значение (цикл to) или предыдущее значение (цикл downto). Далее процесс повторяется. Если параметр цикла целого типа, то это означает его увеличение (соответственно уменьшение) на единицу при каждом вычислении расположенного в цикле оператора. Замечание: шаг изменения параметра всегда равен или 1 или –1. 24 Примеры: (считается, что раздел переменных имеет следующий вид: var S,I: Integer; Sim : Char; L : Boolean;) 1) S:= 0; For I := 5 to 7 do Inc(S); Операция Inc(S,K) означает S := S + K, то есть увеличение параметра S на значение K. Если К не задан, то считается, что К = 1. (Обратная функция Dec(S,K) – уменьшение переменной S на значение К). В примере после выполнения цикла переменная S получит значение 3. 2) S:=10; For I:= 10 downto 6 do Dec(S,2); S получит значение 0. 3) S:=0; For Sim := ‘A’ to ‘D’ do S:= S + 1; S получит значение 4. 4) S:=0; For L:=false to true do Inc(S,3); S получит значение 6. Если в цикле необходимо выполнить несколько операторов, то используется составной оператор. Пример: S:=0; For I:= 1 to 3 do begin S:= S + Sqr(I); P := S + 1; end; После выполнения цикла переменная S станет равной 14, а переменная P равной 15. Замечания: 1. значение параметра цикла, начального и конечного значений параметра цикла изменять внутри цикла нельзя: 2. Для принудительного выхода из цикла в Object Pascal используют команду Break; 3. Для выполнения тела цикла сначала со следующим значением параметра цикла в Object Pascal используют команду Continue; 4. При выходе из цикла значение параметра цикла не определено; Оператор цикла с параметром позволяет осуществить цикл, когда известно сколько раз цикл должен быть выполнен, шаг цикла равняется 1 или –1. Но часто заранее неизвестно сколько раз должен быть выполнено тело цикла. Тогда необходимо использовать два других типа цикла: с предусловием или постусловием. Оператор цикла с предусловием имеет вид: while условие do тело; где условие – выражение условного типа; тело - простой или составной оператор. Структурная схема цикла показана на рис.3.2. 25 Выполнение оператора начинается с вычисления значения выражения условие. Ес- Имя цикла Имя цикла ли это значение True, то выполняется операУсловие тор тело. Затем выполнение оператора цикла повторяется до тех пор, пока значение выра- Тело цикла Тело цикла жение условие не станет равным False. В этом случае управление передается оператору, стоящему за оператором цикла. Если значение Имя цикла Имя цикла выражения условие при первом входе в цикл Условие равно false, то цикл не выполняется не разу. а б Замечание: один из операторов внутри цикла должен влиять на значение условие, иначе Рис. 3.2. Цикл с предусловием цикл будет повторяться бесконечно – проис- (а) и постусловием (б) ходит «зацикливание» программы. Пример: k := 0; while k <6 do begin Inc(k,2); Y := Sqr(k); end; В примере использована процедура Inc(k,2), которая увеличивает значение переменной k на 2. Общий вид процедуры: Inc(перем [, знач]) – увеличить значение переменной перем на величину знач. При отсутствии величины знач переменная перем будет увеличина на 1. Процедура Dec(перем [, знач]) – уменьшает значение переменной перем на величину знач. В процессе выполнения цикла переменная Y будет иметь значения 4, 16, 36. Оператор цикла с постусловием имеет структурную схему, показанную на рисунке 3 и похож на оператор цикла с предусловием, но условие проверяется после выполнения операторов, составляющих тело цикла. Общий вид оператора: Repeat тело; until условие; где условие - выражение логического типа; тело - оператор или составной оператор; Замечания: 1. так как тело цикла заключено между ключевыми словами цикла, то при использовании в теле цикла составного оператора помещать его между операторными скобками begin и end не нужно; 2. так как условие проверяется в конце цикла, то необходимо, что26 бы цикл выполнялся как минимум один раз. Оператор цикла с постусловием начинается с выполнения операторов внутри цикла. Затем вычисляется выражение условие. Если значение равно true, то осуществляется выход из цикла, а при значении false выполнение тела повторяется. Замечание: выход из цикла с предусловием осуществляется при достижении ложности условия, а цикла с постусловием при достижении истинности условия. Пример: возьмем тот же пример, что и в цикле с предусловием: k:=0; repeat Inc(k,2); Y := Sqr(k); until(k>6); результат будет тот же. Любой тип оператора цикла может быть построен с помощью условного оператора. Например, структурная схема цикла с постусловием, построенным, с помощью условного оператора, показана на рис 3.3. При построении такого цикла необходимо переслать информационный поток перед Тело цикла операторами цикла. Для таких целей необходимо использовать метки и оператор безусловного перехода – goto. Как и переменные метки должны быть объявлены. Метки объявУсловие ляются в разделе меток (Label). При использоложь вании метки необходимо использовать имя истина метки и двоеточие. Переход на метку осуРис.3.3. Цикл с постусловием, ществляется командой goto метки. Рассмотрим тот же пример, но с исполь- построенный с помощью условного оператора зование условного оператора. В разделе меток необходимо описать метку. Пусть имя метки beg. Пример: Label beg; begin {прочие операторы} k:=0; beg :Inc(k,2); Y := Sqr(k); If k < 6 then goto beg; {прочие операторы} end; Рекомендация: Использование безусловного оператора goto затруд27 няет «легкость» чтения текста программы программистом, поэтому использовать безусловный переход не рекомендуется. Отладка программы. При построении сложных программ могут возникать ошибки. Ошибки принято делить на три группы: 1. Синтаксические; 2. Ошибки времени выполнения; 3. Алгоритмические. Наиболее простые из них синтаксические – ошибки набора текста – они исправляются в процессе компиляции программы. Ошибки времени выполнения – ошибки, возникающие при несоответствии типов введенных параметров типам используемых переменных или ошибки вычислений (например, деление на 0), отслеживаются также не сложно уже при первых запусках программы. Будем считать, что программа запускается из оболочки Delphi. После возникновения такой ошибки необходимо нажать «Ok» в окне сообщения об ошибке, а затем завершить выполнение программы – пункт меню «Run/Program reset» или нажать комбинацию клавиш <Ctrl><F2>. При возникновении такой ошибки курсор в программе будет указывать на строку вызвавшую ошибку. Наиболее сложно находимые являются алгоритмические ошибки. Программа компилируется без ошибок, не дает ошибок при пробных запусках, но при анализе результатов выясняется, что результат неправильный. Необходимо вручную «прокрутить» алгоритм – требуется отладка программы. Для трассировки программы (проверка «логики алгоритма»), то есть выполнения программы по шагам, необходимо выполнить следующие действия. В пункте меню выбрать пункт «Run/Step over» или «Run/Trace in to», им соответствуют клавиши <F8> и <F7> соответственно, команда «Run/Trace in to» отличаются более детальной трассировкой. Для прекращения трассировки и продолжения выполнения программы в автоматическом режиме необходимо выбрать пункт «Run/Run» или нажать <F9>. Остановить программу можно с помощью команды «Run/Program reset» или нажать комбинацию клавиш <Ctrl><F2>. Иногда необходимо выполнить трассировку с определенной строки программы. Для этой цели подводят курсор к интересующей строке и выполняют команду «Run/Run to cursor» или нажимают <F4>. Часто известно, где может быть ошибка алгоритма – тогда используют точку останова. Программист устанавливает на нужной строке курсор и ставит там точку останова с помощью команды «Run/Add Breakpoint» или, нажав <Ctrl><F8>. Выбранная строка будет отмечена. Для снятия точки останова необходимо на этой строке снова нажать <Ctrl><F8>. При выполнении программы, программа будет выполняться до точки останова, затем программист сможет трассировать программу с помощью <F7> и <F8>. При необходимости можно указать условие, по которому будет происходить остановка на точке останова (эта настройка осуществляется в окне «Breakpoints», пункт меню «Run/Add 28 breakpoints»). При выполнении программы по шагам часто необходимо проверять не только правильность «логики алгоритма», но знать и значения некоторых переменных. Для этой цели выполняют команду «View/Watch/Add watch» и вводят имя интересующей переменной. Эту команду можно выполнить и так – подвести курсор к переменной, значение которой необходимо просмотреть и нажать <Ctrl><F7>. При трассировке программы в этом случае в окне «Watch list» можно видеть изменение значения интересующих переменных. 3.2. СОЗДАНИЕ ПРОГРАММЫ «СТЕПЕННЫЕ РЯДЫ» Задача: Необходимо рассчитать значения функций ex и Ln(x), заданных с помощью рядов, с определенной точностью. Точность и аргумент функции вводится с клавиатуры. Результат работы сравнить со значениями стандартных функций. Формулы разложения в ряд экспоненты и логарифма представлены в таблице 3.4. Таблица 3.4. Стандартная Функция Разложение в ряд Замечания функция x 2 x3 x 4 Exp(x) Exp(x) e x 1 x ... 2! 3! 4! Необходим модуль x 2 x3 x 4 Ln(x) Lnxp1(x+1) Math Ln( x 1) x ... 2 3 4 |x|<1 Рис.3.4. Примерный вид окна программы «Степенные ряды» Примерный вид окна программы представлен на рис.3.4. Процесс создания программы происходит по следующему алгоритму: 1. Запустить Delphi; 2. Сохранить проект, как «Work3», модуль – «Main»; 3. Изменить свойства окна: a. Заголовок «Степенные ряды» Caption; 29 4. Создать поля ввода для значений X и погрешности Е. Будем считать, что все числа целые – порядок чисел будем задавать программно: Взять два элемента SpinEdit, вкладка Samples, значок ; Назвать (свойство Name) один SEValueX – для ввода X, другой SEValueE – ввод E; Настроить минимальные значения элементов на 0 MinValue; Настроить максимальное значение для элемента SEValueX – 9, для SEValueE – 14 MaxValue; Изменить шаг дискретизации на 1 Increment; 5. Добавить 2 элемента для вывода результатов – функция, рассчитанная с помощью ряда, и функция, рассчитанная с помощью стандартной функции: Добавить два элемента Edit, вкладка Standard, значок ; Назвать элементы (свойство Name) для вывода рассчитанной функции ERFun, для стандартной ESFun. Для элемента ESFun изменить свойство Text на 0 (по умолчанию результат равен «0»); Добавить метки для обозначения вводимых и выводимых величин: Изменить заголовки (Caption) для метки для поля ввода X – «Введите Х», для ввода погрешности «Введите погрешность 10^-Е» (погрешность будем вводить как количество знаков после запятой, например, число 3 будет обозначать погрешность 0.001), для вывода расчетного значения – «Рассчитанная функция», для вывода стандартного значения функции – «Стандартная функция». 6. Так как, будем рассчитывать две функции добавим переключатель – какая функция рассчитывается: Добавить элемент RadioGroup, вкладка Standard, значок ; Изменить название на RG Name; Изменить заголовок на «Функция» Caption; Добавить названия функций «Экспонента» и «Логарифм» - для этих целей запустить мастер свойства Items: o Ввести две строки: «Экспонента» и «Логарифм»; o Установить активным первый элемент (нумерация начинается с 0) ItemIndex установить в 0; 7. Добавить две кнопки для выхода из программы и для начала расчета: Добавить элемент Button, вкладка Standard, значок ; Кнопки назвать: кнопка выхода BQuit, кнопка расчета BOk Name; Изменить заголовки на «Выход» и «Ok» Caption; 8. Окно готово! 9. Запрограммировать выход на кнопку BQuit (команда Close); 10. Запрограммировать расчет на кнопке BOk; Расчет будет осуществлен для функции, которая отмечена элементом RG. Первой является функция «экспонента»; Проанализировать ряд, по которому осуществляется расчет функции, и выявить, как получить элемент ряда an, зная элемент an-1. Для расчета экспоненты необходимо элемент ряда умножить на «x / n»; Для расчета функции потребуются переменные для хранения значения функции – назовем ее Func – эта переменная должна быть вещественной – тип Real; пере30 менная для хранения n-го и n+1-го членов ряда (переменные также типа Real) назовем их а и а1 соответственно; переменная для хранения точности расчета (тип Real), переменная e и для удобства записи формул введем переменную x типа Real. Также необходима переменная для счетчика цикла – переменная n тип Integer. Эти переменные необходимо описать в разделе var процедуры нажатия на кнопку «ОК». Текст процедуры станет таким: procedure TForm1.BOkClick(Sender: TObject); var Func : real; A,A1 : real; e : real; x : real; n : integer; Присвоим значению переменной x значение элемента SEValueX (свойство Value). Для расчета точности будем в цикле умножать переменную e на число 0.1 столько раз, сколько знаков после запятой нам нужно (это число содержит элемент SEValueE). Добавим после начала процедуры (оператор begin) следующие строки: x := SEValueX.Value; e := 1; For n := 1 to SEValueE.value do e := e * 0.1; Выяснить какая функция рассчитывается можно по переменной RG.ItemIndex, если она равна 0, то рассчитываем функцию «экспонента», а 1 – «логарифм». Для решения такой задачи удобно использовать оператор выбора Case. После расчета точности необходимо добавить: case RG.ItemIndex of 0 : begin {расчет экспоненты} end; 1 : begin {расчет логарифма} end; end; {case} Для расчета функции будем использовать оператор цикла с постусловием, так как наша функция как минимум один раз может быть рассчитана. Условием выхода из цикла будет тот факт, что очередной член ряда станет меньше заданной точностью. После комментария {расчет экспоненты} добавим строки: Func := 1; a := 1; n := 1; repeat a1 := a * x /n; Func := Func + a1; a := a1; Inc(n); until(a<e); Для вывода результатов расчета необходимо преобразовать числа в строки, так как поле ввода/вывода элемента Edit является строка. После окончания цикла (строка end {case}) необходимо добавить следующие строки: ERFun.Text := FloatToStr(NFunc); 31 ESFun.Text := FloatToStr(Exp(x)); 11. Расчет экспоненты окончен! Запустить программу, нажав <F9>; 12. Для улучшения программы: Необходимо написать текст расчета функции «логарифм». Так как ряд использует в качестве аргумента x+1 удобно использовать функцию Lnxp1, которая также возвращает натуральный логарифм числа (х+1). Но для использования этой функции требуется к программе подключить модуль Math. Это можно сделать в разделе описания модулей после слова implementation. Необходимо добавить: Uses Math; Для автоматического расчета после ввода значений в поля ввода (без нажатия на кнопку «Ok») необходимо назначить элементам SEValueX и SEValueE событие onChange кнопки BOK и сделать невидимой кнопку BOK (эти задачи рассмотрены в разделе 2.2); 3.3. ИНДИВИДУАЛЬНОЕ ЗАДАНИЕ Создать программу по заданию демонстрационной программы, используя две функции в соответствии с номером варианта (таблица 3.6). Разложение в ряд функций и стандартные функции перечислены в таблице 3.5. Таблица 3.5 Разложение в ряд Стандартная функция Замечания e x 2 x3 x 4 e 1 x ... 2! 3! 4! Exp(x) - Ln(x) x 2 x3 x 4 Ln( x 1) x ... 2 3 4 Lnxp1(x+1) Необходим модуль Math |x|<1 Sin(x) - Cos(x) - ArcTan(x) |x|<1 e x e x sh( x) 2 - Функция x Sin(x) Cos(x) Arctg x x3 x5 x 7 Sin ( x) x ... 3! 5! 7! x 2 x 4 x6 Cos( x) 1 ... 2! 4! 6! x3 x5 x7 ArcTg ( x) x ... 3 5 7 Sh(x) x3 x5 x7 sh( x) x ... 3! 5! 7! Ch(x) x 2 x 4 x6 Ch( x) 1 ... 2! 4! 6! 1 1 1 1 ... 4 3 5 7 sh( x) e x e x 2 PI/4 Точность ограничить 5 знаками 32 Таблица 3.6 № 1 2 3 4 5 F1 Sin Sin Sin Sin Sin F2 Cos ArcTg Ln Sh Ch № 6 7 8 9 10 F1 Sin Cos Cos Cos Cos F2 ArcTg Ln Sh Ch № 11 12 13 14 15 F1 Cos ArcTg ArcTg ArcTg ArcTg F2 Ln Sh Ch № 16 17 18 19 20 F1 Ln Ln Ln Sh Sh F2 Sh Ch Ch 3.4. ИТОГИ В третьей теме были изучены: стандартные функции; функции модуля Math; функции преобразования типов; операторы циклов. При создании демонстрационной программы были получены навыки работы со следующими командами и визуальными компонентами: элемент строка ввода Edit; элемент список зависимых кнопок RadioGroup; 4. ТИП ДАННЫХ МАССИВ Цель: объявление новых типов данных; генератор случайных чисел; изучение структуры массив; алгоритмы действий с массивами; 4.1. ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ Новые типы данных. Когда необходимо объявить свой тип данных, то следует поместить его описание в разделе описания типов. В общем случае описание типов выглядит так: Имя = Описание типа; где Имя – имя нового типа; Описание типа – описание возможных значений переменных созданного типа. Замечание: при описании нового типа после имени типа ставится знак «равно», затем следует описание типа. Примеры: DayOfWeek = (Monday, Wednesday, Friday); Day = 1..31; тип подобного вида называется перечисляемый тип, переменные такого типа может принимать только перечисленные значения. В примере это одно из названий дня недели (тип DayOfWeek) или одно из чисел от 1 до 31 (тип Day). К переменным перечисляемого типа можно использовать функции Pred(переменная) и Succ(переменная) возвращающие предыдущее (Pred) и последующее (Succ) из допустимых значений. Примеры: Пусть объявлены переменные W : DayOfWeek и D : Day тогда: W := Wednesday; Succ(W); {оператор вернет значение ‘Monday’} 33 D := 5; Pred(D); {оператор вернет значение ‘4’} Замечания: 1. Значения перечисляемого типа не могут содержать русские буквы; 2. Если обратиться с помощью операторов Succ или Pred к последнему для оператора Succ или первому для оператора Pred элементу, то это приведет к ошибке. Массивы. Массив – это структура данных, которую можно рассматривать как набор переменных одинакового типа, имеющих общее имя. Массивы удобно использовать для хранения однородной по своей природе информации, например, таблиц, коэффициентов уравнений, матриц. Объявление массива. Массив, как и любая переменная, перед использованием должен быть объявлен в разделе объявления переменных. В общем случае объявление массива выглядит следующим образом: Имя : array [нижний_индекс..верхний_индекс] of тип где Имя – имя переменной-массива; array – зарезервированное слово языка Паскаль, обозначающее, что переменная является массивом; нижний_индекс, верхний_индекс – целые константы, определяющие диапазон изменения индекса элементов массива и, неявно, количество элементов массива; тип – тип элементов массива. Примеры: day = array [1..30] of integer; {объявлен тип-массив 30 целых чисел} r : array [5..7] of boolean; {объявлена переменная-массив 3 логических элементов} В случае, когда необходимо объявить несколько элементов типа массив имеет смысл создать новый тип массив в разделе описания типов, а в разделе описания переменных указать в качестве типа созданный тип. В этом случае описание массива будет следующим: type {раздел описания типов} ИмяТипа = array [нижний_индекс..верхний_индекс] of тип; var {раздел описания переменных} Имя : ИмяТипа; При объявлении массива удобно использовать именованные константы. Пример: Const N = 1; E = 5; Type Ar = array [N..E] of Char; Массивы могут быть многомерными (обычно размерность массива не 34 более 3-х). Для описания такого массива необходимо указать диапазоны индексов для каждой размерности через запятую. В общем случае описание, например, двухмерного массива, будет таким: Имя : array [н_и1..в_и1, н_и2..в_и2] of тип где н_и1, в_и1, н_и2, в_и2 – целые константы, определяющие диапазон изменения верхнего и нижнего индекса первой и второй размерности. Пример: Coord : array [1..5, 1..3] of integer; {Переменная типа массив Coord описывает двухмерный массив} Для того чтобы в программе использовать элемент массива, надо указать имя массива и номер элемента (индекс), заключив его в квадратные скобки. Индекс может быть константой или выражением целого типа. Примеры: P := Coord[1,3]; Coord[5,2] := Coord[3,1]; Типичные действия с массивом. Вывод массива; ввод массива; поиска максимального или минимального элемента массива; поиска в массиве заданного элемента; сортировка массива. Под выводом массива понимается вывод в диалоговое окно значений элементов массива. Для вывода всех элементов массива можно использовать оператор цикла For, при этом параметр цикла может быть использован в качестве индекса элементов массива. При выводе элементов массива можно, например, использовать следующие элементы: метка (элемент Label, вкладка Standard, значок ), строка ввода (Edit, Standard, ). Под вводом массива понимается получение от пользователя во время работы программы значений элементов массива. Способ ввода зависит от алгоритма программы – можно вводить каждый элемент массива отдельно, а можно вводить сразу все элементы, используя, например, элемент строка ввода и разделяя элементы определенным символом, например пробелом, с последующей обработкой строки. Для ввода элементов массива можно использовать: для ввода целых чисел элемент Ввод целых чисел (SpinEdit, Samples, ); при вводе/выводе массива (особенно двухмерного) очень удобно использовать элемент Таблица (StringGrid, Additional, ). Подробно работа с этими элементами при работе с массивами будет рассмотрена при построении демонстрационной программы. Генератор псевдослучайных чисел. Если необходимо получить чис35 ла, содержащие случайные значения, то можно использовать генератор псевдослучайных чисел. Существует два оператора: 1. Randomize – служит для «запуска» генератора чисел (иначе последовательность генерируемых чисел всегда будет одна и та же); 2. Random[(R)] – служить для генерации случайного числа в диапазоне от 0 до R, включая значение R. Квадратные скобки при описании какоголибо оператора указывают, что часть кода указанная в них может не указываться, тогда будут использованы начальные установки для этого оператора. Если в операторе Random граница R не указана, то числа будут генерироваться в диапазоне от 0 до 1, включая значение 1. Для генерации случайного числа по нормальному распределению необходима функция RandG(m,sd) из модуля Math (задается математическое ожидание m и стандартное отклонение sd). Поиск минимального (максимального) элемента. В качестве примера будем использовать одномерный массив целых чисел. Алгоритм поиска минимального (максимального) элемента массива довольно очевиден: сначала делается предположение, что первый элемента массива является минимальным (максимальным), затем остальные элементы массива последовательно сравниваются с этим элементом. Если во время очередной проверки обнаруживается, что проверяемый элемент меньше (больше) принятого за минимальный (максимальный), то этот элемент принимается за минимальный (максимальный) и продолжается проверка оставшихся элементов. Пример: Пусть Size – размер массива a, переменная для хранения минимума min, максимума max, I параметр цикла. Тогда поиск минимального и максимального значения будет выглядеть так: min := a[1]; max := a[1]; For I := 1 to Size do Begin If a[I] < min then min := a[I]; If a[I] > max then max := a[I]; end; После окончания цикла в переменной min будет храниться минимальное значение, а в переменной max – максимальное. 36 Поиск заданного элемента. Самый простой способ – перебора – последовательный перебор значений массива и сравнение с искомым. Но при большой размерности массива приведет к неоправданной затрате времени. Оптимальным является метод бинарного поиска. Алгоритм предполагает, что исходный массив отсортирован. Структурная схема алгоритма представлена на рис.4.1. Построение программы по представленной структурной схеме дается на самостоятельное изучение. Для ускорения поиска, как указано выше, удобно начало использовать отсортированный массив. Рассмотрим алN+K S= +N горитмы сортировки дан2 ных. Наиболее популярным алгоритмом является «метод Да пузырька». В основе алгоA[S]=F ритма лежит обмен соседних элементов массива. Нет Каждый элемент массива, Нет Да начиная с первого, сравниA[S]<F вается со следующим и если он больше следующего, то K := S – 1 N := S + 1 элементы меняются местами. Таким образом, элементы с меньшими значениями передвигаются к началу Нет N>K массива («всплывают»), а с большими значениями – к Да концу массива («тонут»). Поэтому этот метод и назван конец «пузырьковая сортировка». Процесс сравнения поРис. 4.1. Бинарный поиск вторяется столько раз, Приняты обозначения: A – массив значений; S – сколько элементов массива средний индекс массива; N – начальный индекс минус единица, поэтому при массива; K – конечный индекс массива; F – искобольшом количестве эле- мое значение ментов процесс сортировки требует много времени. Структурная схема представлена на рис.4.2. 4.2. СОЗДАНИЕ ПРОГРАММЫ «РАБОТА С МАССИВОМ» Задача: Необходимо сгенерировать матрицу случайных чисел размерностью 5 на 5 и в соответствии с имеющимся шаблоном сформировать итоговый массив по следующему правилу: если в шаблоне позиция зачернена, то в этой позиции в итоговую матрицу за37 писывается число из той же позиции из исходной матрицы, иначе записывается 0. Примерный вид окна программы представлен на рис.4.3. Процесс создания программы происходит по следующему алгоритму: 1. Запустить Delphi; 2. Сохранить проект («work4.dpr» и «main.pas»); 3. Настроить окно проекта: Изменить заголовок окна на «Работа с массивом» Caption; начало Сформировать изображение шаблона массива: Цикл I o Поместить на форму элемент I := 1 фигура (элемент Shape, вкладувеличение ка Additional, значок ); o Настроить размеры фигуры, чтобы можно было из них построить квадрат размером 5 на 5 фигур. Для этого изменить свойства фигуры Width – ширина и Height – высота; o Скопировать элемент в буфер (<Ctrl><Ins>); o Сделать 24 копии (<Shift><Ins>); o Разместить квадратики в квадрат 5х5; o Выделить средний квадрат размером 3х3 (удерживая <Shift> щелкать на нужных квадратиках) – выделенные квадратики будут отмечены рамочкой ; o Изменить цвет этого выделенного квадрата на красный (свойство Shape/Color установить в значение clRed); Поместить 2 элемента для хранения массивов: o Поместить на форму 2 элемента Цикл J J := K уменьшение A[J-1]< A[J] Да Нет J := J + 1 A[J-1]:=A[J] A[J]:=A[J-1] Цикл J J=I Цикл I I=K конец Рис. 4.2. «Пузырьковая сортировка» Приняты обозначения: А – массив, К – конечный индекс массива, I,J – параметры цикла строковая таблица (StringGrid,Additional, ), разместив их слева (начальная матрица) и справа (итоговая матрица) от построенного шаблона; o Настроить имена этих элементов SGIshod и SGItog для хранения исходного и итогового массива соответственно (Name); o Остальные настройки этих двух элементов будут совпадать – выделить эти два элемента; 38 Рис. 4.3. Примерный вид окна программы «Работа с массивами» o Настроить размеры таблиц (5х5 количество квадратиков и заголовки - итого размер 6х6) (свойства ColCount (количество столбцов) и RowCount (количество строк) установить в значение 6); o Так как, в ячейки будут записаны цифры размером 8х8 пикселей изменить размеры ячеек на значение 16 ширину (DefaultColWidth) и высоту (DefaultColHeight); o Изменить размеры (свойства Width и Height установить в значение 110); o Каждая табличка имеет заголовок строк и столбцов. Для их выделения можно использовать цвет, например «ярко голубой» (FixedColor установить в clAqua); o Изменить размер шрифта, используемого в табличках, на 8 (Font/Size); o Для того, чтобы при выводе цифр не появлялся скроллер изменить свойство ScrollBars на ssNone; Поместить элементы для вывода не отсортированного массива и отсортированного: o Для не отсортированного массива использовать элемент метка (Label,Standard, ); o Назвать элемент LSort (Name); o Для отсортированного массива использовать элемент строка ввода (Edit,Standard, ); o Назвать элемент ESort (Name); Поместить метки для подписи всех видимых элементов «Исходный массив», «Итоговый массив», «Шаблон», «Не отсортированный массив» и «Отсортирован ный массив»(Label, Standard, ); Добавить кнопки запуска расчетов и выхода из программы: o Добавить 2 элемента Кнопка (Button, Standard, ); o Назвать один «BOk» (расчет) и «BQuit» (выход) (Name); 39 Форма готова! 4. Запрограммировать выход на кнопку BQuit (команда Close); 5. Для отображения первого результата расчета сразу после запуска программы, то есть при её активизации запрограммируем свойство формы onActivate: Сделать активной форму – щелкнуть на окне на свободном от элементов месте; Выбрать в Object Inspector на вкладке Events свойство onActivate; Дважды щелкнуть на нем для начала ввода текста программы; Ввести раздел переменных и ввести переменные: параметры цикла I,J,K; массивы исходный MIs, итоговый MIt, для описания шаблона MSh (элементы, отмеченные цветом, будут иметь значение 1, остальные 0), одномерный массив для сортировки Mass. Необходимо ввести следующие строки перед оператором begin: Var I,J,K : Integer; MIs, MIt, MSh : array [1..5,1..5] of integer; Mass : array [1..25] of integer; Перед заполнением массива требуется запустить генератор псевдослучайных чисел – после слова begin – необходимо добавить оператор Randomize; Пронумеруем заголовки строк и столбцов цифрами от 1 до 5. Для этих целей удобно использовать цикл с параметром. При обращении к элементам таблицы (StringGrid) необходимо указать через точку свойство Cells. Это свойство является двухмерным массивом и позволяет хранить значения используемого массива. Нумерация индексов массива Cells начинается с 0, причем нулевые элементы это элементы заголовков; первый индекс – это столбец, второй строка; После выполнения пунктов «e» и «f», текст программы будет следующим: Randomize; For I := 1 to 5 do begin {Элемент таблицы строка – требуется преобразование типов} SGIshod.Cells[0,I] := IntToStr(I); {Пронумеровали строки} SGIshod.Cells[I,0] := IntToStr(I); {Пронумеровали столбцы} SGItog.Cells[0,I] := IntToStr(I);; {Пронумеровали строки} SGItog.Cells[I,0] := IntToStr(I);; {Пронумеровали столбцы} end; Проанализировать полученный шаблон – в нашем случае структура массивов представляет квадрат и легко описывается циклом с параметром; Алгоритм обработки массива будет следующим: o Обнуление массива шаблона; o Обнуление итогового массива; o Заполнение массива шаблона единицами в позициях заданного шаблона (центральный квадрат размером 3х3); o Заполнение случайными числами исходного массива. Для этого будем использовать оператор Random, но он возвращает числа, начиная от 0, значит надо генерировать число и прибавлять 1 – команда «Random(9)+1» как раз и будет генерировать числа от 1 до 9; o Просматривая исходный массив в соответствии с правилом заполнить итоговый массив; o Отобразить полученный итоговый массив в элементе SGItog; o Итак, выполнив эти пункты, получим следующий текст программы: {Обнуляем итоговый массив и массив шаблона} 40 For I:= 1 to 5 do For J := 1 to 5 do begin MSh[I,J] := 0; MIt[I,J] := 0; end; {Заполняем массив шаблона} For I:= 2 to 4 do For J := 2 to 4 do MSh[I,J] := 1; {Заполняем итоговый массив и отображаем его} For I:= 1 to 5 do For J := 1 to 5 do begin MIs[I,J] := Random(9)+1; SGIshod.Cells[I,J] := IntToStr(MIs[I,J]); end; {Заполнить по шаблону итоговый массив и отобразить его} For I:= 1 to 5 do For J := 1 to 5 do begin If MSh[I,J] = 1 then MIt[I,J] := MIs[I,J]; SGItog.Cells[I,J] := IntToStr(MIt[I,J]); end; {окончание заполнения массива} Для реализации алгоритма сортировки массива необходимо: o Перевести двухмерный массив в одномерный – пусть элемент с индексом [1,1] будет иметь индекс [1], [1,2] – [2], [1,3] – [3], [1,4] – [4], [1,5] – [5], [2,1] – [6], [2,2] – [7] и т.д. Эту операцию также легко сделать, используя двойной цикл по параметрам цикла двухмерного массива и внутри цикла изменяя параметр цикла одномерного массива. Текст программы дополниться после строки «{окончание заполнения массива}» следующими строками: k:=0; For I := 1 to 5 do For J := 1 to 5 do begin Inc(k); Mass[k] := MIs[J,I]; end; Далее массив выводится в поле вывода, задаваемое меткой LSort (сначала строку обнуляем, а затем, чтобы цифры при выводе не сливались, будем добавлять после каждой цифры пробел): Lsort.Caption := ‘’; For I:=1 to 25 do LSort.Caption := LSort.Caption+IntToStr(Mass[I])+’ ‘; {массив ещё не отсортирован} Алгоритм сортировки массива Mass написать самостоятельно. Поместить созданный текст алгоритма после строки {массив ещё не отсортирован}; 6. Для того чтобы программу можно было запускать на расчет без перезапуска программы связать команду onClick кнопки BOk с командой onActivate (в поле команды onClick в Object Inspector выбрать процедуру FormActivate); 41 7. Запустить программу <F9>; 8. Программа готова! 4.3. ИНДИВИДУАЛЬНОЕ ЗАДАНИЕ Создать программу по заданию демонстрационной программы, используя шаблон в соответствии с номером варианта. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 4.4. ИТОГИ В четвёртой теме были изучены: объявление новых типов данных; генератор случайных чисел; изучение структуры массив; алгоритмы операций с массивами. При создании демонстрационной программы были получены навыки работы со следующими командами и визуальными компонентами: элемент фигура StringGrid; 5. ГРАФИЧЕСКИЕ ПРИМИТИВЫ Цель: знакомство с графическими примитивами; печать изображения; мультипликация; формирование программируемого изображения. 5.1. ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ Графические примитивы. При создании программы может возникнуть ситуация, когда, используя видимые элементы Delphi не удается сформировать нужное изображение (это могут быть чертежи, иллюстрации, гра42 фики и т.п.). В этом случае можно использовать программирование изображения. Вся поверхность окна представляет собой холст, на который программа может выводить графику. Этот холст за- (0,0) дается свойством Canvas. Это свойство позволяет выводить графические примитивы (точки, линии, окружности, прямоугольники и т.п.) и задавать их характеристики: цвет, толщину (Image1.Width, Image1.Height) и стиль линий; цвет и вид заполнения областей; характери(Form1.ClientWidth, Form1.ClientHeight) стики шрифта при выводе текстовой информации. Холст Рис. 5.1. Координаты точек холста представляет собой систему ко- и элемента Image ординат с началом в верхнем левом углу – таким образом, увеличение координаты X идет слева направо, а координаты Y сверху вниз (рис. 5.1). Холст можно представить как набор пикселей – начало координат имеет координаты (0,0), а правый нижний угол окна – (Client.Width, Client.Height). Для рисования графических объектов используют карандаш (Pen), а для заполнения замкнутых областей – кисть (Brush). Свойства инструментов Pen и Brush в таблице 5.1. Таблица 5.1 Свойство Color Width Style Mode Color Style Определение Карандаш – Pen Цвет линии Толщина линии Стиль линии Режим отображения Кисть Brush Цвет закрашиваемой области Стиль заполнения области В таблице 5.2 представлены все стандартные цвета, которые пользователь может использовать в качестве значений свойства Color. Таблица 5.2 Константа clAqua clBlack clBlue clDkGray clFuchsia clGray Цвет Бирюзовый Чёрный Синий Тёмно серый (clGray) Фиолетовый Серый (clDkGray) Константа clMaroon clNavy clOlive clPurple clRed clSilver Цвет Тёмно бордовый Тёмно синий Оливковый Пурпурный Красный Серебристый (clLtDark) 43 clGreen clLime clLtGray Зелёный Салатный Светло серый (clSilver) clTeal clWhite clYellow Тёмно голубой Белый Жёлтый Если требуется использование других цветов, то можно воспользоваться функцией RGB(Red,Green,Blue), в качестве параметров которой передаются значения соответствующего цвета (красного, зеленого, синего) в значении от 0 (значение отсутствует) до 255 (цвет полностью насыщен). Пример: RGB(255,0,0) – даст чисто красный цвет (clRed); RGB(100,100,100) – даст оттенок серого; RGB(255,255,255) – даст чисто белый цвет (clWhite). Также полезным может оказаться свойство Pen.Width устанавливающее толщину рисуемой линии в пикселях. Дополнительную справку по остальным свойствам карандаша и кисти можно получить из контекстной справки Delphi. Рассмотрим графические примитивы: TextOut – вывод текста, Pixels – вывод точки, LineTo – вывод линии, PolyLine – вывод ломаной, PolyGon - многоугольник, Rectangle - прямоугольник, RoundRec – прямоугольник с закругленными краями, Ellipse - эллипс, Arc - дуга и Pie - сектор. TextOut(X,Y) – вывод текста в прямоугольник, имеющий координаты верхнего левого угла X,Y. Стиль (Style), цвет (Color), название шрифта (Name), размер шрифта (Size) определяется объектом Font. Пример: Font.Name := ‘Times New Roman’; {название шрифта Times New Roman} Font.Size := 14; {размер шрифта 14} Font.Color := clBlue; {цвет шрифта Синий (clBlue)} Font.Style := [fsBold, fsItalic, fsUnderLine, fsStrikeOut]; {Настройка стиля шрифта, указывается в прямоугольных скобках через запятую – fsBold – жирный, fsItalic – курсив, fsUnderLine – подчеркнутый, fsStrikeOut - зачеркнутый} Для настройки фона выводимого текста необходимо настроить цвет кисти (Brush.Color), например системный цвет clBtnFace позволит выводить фон текста такой же, как у окна. Pixels[X,Y] := цвет – вывод точки с координатами X, Y указанным переменной цвет цветом. Замечание: Все последующие процедуры чертятся цветом, установленным для инструмента карандаш – Pen.Color. LineTo(X,Y) – рисует линию от текущей точки окна (позиция курсора) до точки с координатами X и Y. Чтобы установить курсор в определенную точку необходимо использовать процедуру MoveTo[X,Y], которая перемещает курсор в точку с координатами X и Y. Пример: MoveTo(0,0); LineTo(ClientWidth,ClientHeight); В примере будет проведена линия от левого верхнего угла окна до 44 правого нижнего угла. PolyLine(array of TPoint) – рисует ломанную кривую по точкам указанным в массиве точек, соединяя первую со второй, вторую с третьей и т.д. Точки массива могут быть перечислены как непосредственно в процедуре PolyLine, так и описанны ранее. Использование процедуры будет понятно из примера. Пример: 1. Точки описаны в процедуре: PolyLine([Point(10,20),Point(20,10),Point(30,20)]); будет построена ломанная с вершинами в точках, указанных в стандартной переменной Point с координатами (10,20), (20,10), (30,20) 2. Для описания массива точек назначим массив PArray, который опишем в разделе описания переменных. Затем необходимо заполнить массив значениями точек и, наконец, вызвать процедуру PolyLine: Var PArray : array[1..3] of TPoint; begin … {описание программы} PArray[1].X := 10; PArray[1].Y := 20; PArray[2].X := 20; PArray[2].Y := 10; PArray[3].X := 30; PArray[3].Y := 20; PolyLine(PArray); Здесь также будет построена ломанная с теми же координатами вершин, что и в предыдущем случае. Второй пример, несмотря не громоздкость, в случае, когда используется многократное использование PolyLine позволит разделить текст, описывающий точки, и текст построения изображения, что более структурирует текст программы. PolyGon(array of TPoint) – отличается от предыдущей процедуры тем, что соединяет последнюю точку массива с первой – то есть получаем замкнутую фигуру. Замечание: Все замкнутые фигуры чертятся цветом, установленным для инструмента карандаш – Pen.Color и заполняются цветом, определенным для инструмента кисть – Brush.Color. Rectangle(X1,Y1,X2,Y2) – прямоугольник, имеющий левый верхний угол с координатами (X1,Y1) и X3 нижний правый угол с координата- X1,Y1 ми (X2,Y2). Если длина X1-Y1 Y3 окажется равной X2-Y2, то полуX2,Y2 чится квадрат. RoundRec(X1,Y1,X2,Y2,X3,Y Рис.5.2. Прямоугольник со 3) – вычерчивает прямоугольник скругленными углами (X1,Y1,X2,Y2), но с кругленными 45 углами, размер скругления определяется X3 – диаметр скругления по X, Y3 – диаметр скругления по Y (рис 5.2). Ellipse(X1,Y1,X2,Y2) – эллипс, вписанный в прямоугольник с координатами (X1,Y1,X2,Y2), если это квадрат, то получаем окружность. Arc(X1,Y1,X2,Y2,X3,Y3,X4,Y4) – вычерчивает дугу эллипса, вписанного в прямоугольник с вершинами (X1,Y1,X2,Y2); X3,Y3 – определяет точку начала дуги; X4,Y4 – определяет точку конца дуги. Начальная (конечная) точка – это точка пересечения границы эллипса и прямой, проведенной из центра эллипса в точки с координатами (X3,Y3) и (X4,Y4). Дуга вычерчивается против часовой стрелки от начальной точки к конечной. Pie(X1,Y1,X2,Y2,X3,Y3,X4,Y4) – строит сектор. Строится по тем же правилам, что и дуга, но отличается тем, что сектор - замкнутая фигура, то есть имеет цвет заполнения. Дуга и сектор изображены на рис 5.3. Дуга X1,Y1 X3,Y3 X1,Y1 X4,Y4 X3,Y3 X4,Y4 X2,Y2 X2,Y2 Сектор X1,Y1 X3,Y3 X1,Y1 X4,Y4 X2,Y2 X4,Y4 X3,Y3 X2,Y2 Рис.5.3. Значение параметров для построения дуги и сектора Печать изображения. Печать изображения является тем же, что и вывод на экран. Принтер также имеет свойство Canvas, как и форма. Здесь также действует та же система координат и те же инструменты карандаш и кисть. Отличие состоит лишь в следующем: при печати надо сообщить принтеру, чтобы он начал и закончил печать. Для этого надо поместить все графические вызовы, которые должны распечатать изображение между командами принтера: Printer.BeginDoc и Printer.EndDoc. Как только принтер получит команду Printer.EndDoc, он сразу отпечатает изображение. Для печати необходимо настроить принтер с помощью стандартного окна настройки. Для этого Delphi имеет вкладку наиболее популярных диалогов – Dialogs. На этой вкладке есть и диалоги настройки свойств принте46 ра (значок ) и свойств печати (значок ). Для вызова этих диалогов необходимо выполнить команду Execute. Например, команда PrinterDialogSetup1.Execute откроет стандартное окно настройки принтера (считается, что на форму помещён элемент настройки печати с именем PrinterDialog1). Если при создании программы планируется, что изображение будет печататься, необходимо предусмотреть умножение всех размеров используемых объектов на константу, определяющую различие между размерами окна и размерами бумаги. Для этих целей необходимо использовать свойства принтера Printer.PageWidth и Printer.PageHeight, дающих размеры бумаги – ширину и высоту соответственно. Получить коэффициенты пересчета можно, поделив самые короткие размеры печатаемой страницы на самые короткие размеры отображаемой формы: КоэффициентX Printer.PageWidth ; Form.ClientHeight Таким образом, при печати изображения останется только умножать все размеры на эту константу. Мультипликация. Под мультипликацией обычно понимают передвижение объекта или изменение его свойств (формы, цвета и т.п.). Сделать движущийся объект очень просто – достаточно вывести изображение, затем через некоторое время стереть его и вывести новое. Подобрав время между выводом изображений, можно добиться плавного изменения изображения. Для создания задержки в Delphi служит невидимый элемент Timer, вкладка System, значок . «Невидимый компонент» означает, что во время выполнения программы этот элемент виден не будет, поэтому на стадии разработки окна этот значок можно поместить в любое место. Этот элемент имеет всего три свойства: имя (Name), интервал (Interval) и запрещение/разрешение работы (Enabled). Таким образом, необходимо настроить интервал перерисовки (значение свойства Interval заданное в миллисекундах) и разрешить перерисовку (свойство Enabled установить в TRUE). Для запуска событий, которые должны перерисовываться, необходимо обратиться к свойству onTimer. Картинка будет перерисовываться с частотой заданной свойством Interval. Если требуется, чтобы картинка двигалась, то необходимо при программировании картинки ввести базовую точку и все координаты рассчитывать от этой точки. Обычно это делается так: вводятся константы по координатам, которые должны изменяться и все соответствующие координаты изображения увеличиваются на это значение. Пример: Пусть необходимо передвигать окружность с координатами (5,5,10,10) по горизонтали. Вводим переменную базовой точки по координате X, пусть переменная называ47 ется dx. Рисование окружности будет осуществляться командой: Ellipse(dx+5,5,dx+10,10); Затем в нужный момент старое изображение затирается цветом фона, изменяются координаты базовой точки, и прорисовывается картинка с новыми координатами. 5.2. СОЗДАНИЕ ПРОГРАММЫ «ГРАФИЧЕСКИЕ ПРИМИТИВЫ» Задача: Написать программу, формирующую графическое изображение, используя графические примитивы. Окно программы представлено на рис. 5.4. Рис. 5.4. Возможный вид экрана программы «Графические примитивы» Процесс создания программы происходит по следующему алгоритму: 1. Запустить Delphi; 2. Сохранить проект («work5.dpr», «main.pas»); 3. Настроить вид экрана: Настроить размеры формы: ширину (свойство Width) установить в 600, а высоту (свойство Height) установить в 370; Форма содержит всего два элемента: видимый элемент – кнопка (Button), и для создания мультфильма элемент таймер (Timer). Все остальные элементы создаются программно: изменить заголовок окна: «Графические примитивы» (Caption); Поместить кнопку для программирования выхода (Button, Standard, назвать кнопку BQuit (Name); Поместить на форму элемент таймера (Timer, System, ); установить время обращения к этому элементу – 1 раз в секунду (1000 микросекунд), так как значения таймера устанавливаются в микросекундах убедиться, что значение Interval ): 48 4. 5. 6. 7. равно 1000; Форма настроена! Запрограммировать выход из программы: команда «Close» при нажатии на кнопку BQuit; Чтобы осуществить прорисовку изображения сразу при запуске программы, нам нужно настроить событие прорисовки окна – onPaint (щелкнуть на форму (Form1), выбрать свойство onPaint, вкладка Events в Object Inspector) щелкнуть на этом событии; Запрограммировать правую часть окна на рис.5.4: Назначить область рисования Canvas – набрать после begin текст: with canvas do //обращаемся к свойствам холста begin {область рисования} end; Для вывода текста настроить цвет фона и свойства шрифта (набрать текст после строки {область рисования}): Brush.Color := clBtnFace; //цвет фона – (цвет кнопки в стандарте Windows) with Font do //обращаемся к свойствам шрифта begin Name := 'Times New Roman'; //имя шрифта Size := 12; //размер шрифта Style := [fsBold,fsItalic]; //стиль – жирный курсив end; {настройка шрифта закончена} Набрать текст программирования примитивов: TextOut(410,22,'(TextOut)'); //вывод текста Pen.Color := clBlack; //цвет карандаша - черный Brush.Color := clWhite; //цвет кисти белый Pixels[350,80] := clRed; //вывод точки Brush.Color := clBtnFace; {смена цвета на цвет фона (цвет кнопки в стандарте Windows) для вывода текста-подсказки} TextOut(335,85,'(Pixels)'); Brush.Color := clWhite; MoveTo(400,80); //переместить курсор LineTo(450,80); //соединить с точкой – получится линия Brush.Color := clBtnFace; TextOut(405,85,'(MoveTo)'); TextOut(405,100,'(LineTo)'); Brush.Color := clWhite; PolyLine([Point(480,100),Point(505,50),Point(530,100)]); //Ломаная кривая Brush.Color := clBtnFace; TextOut(480,105,'(PolyLine)'); Brush.Color := clWhite; Rectangle(325,125,375,175); //Прямоугольник Brush.Color := clBtnFace; TextOut(325,180,'(Rectangle)'); Brush.Color := clWhite; RoundRect(400,125,455,175,20,20); //Прямоугольник с закругленными углами 49 Brush.Color := clBtnFace; TextOut(400,180,'(RoundRect)'); Brush.Color := clWhite; PolyGon([Point(480,175),Point(505,125),Point(530,175)]); //Многогранник Brush.Color := clBtnFace; TextOut(480,180,'(PolyGon)'); Brush.Color := clWhite; Ellipse(325,210,375,260); //эллипс Brush.Color := clBtnFace; TextOut(335,270,'(Ellipse)'); Brush.Color := clWhite; Arc(400,210,455,260,427,210,455,235);//Дуга Brush.Color := clBtnFace; TextOut(420,270,'(Arc)'); Brush.Color := clWhite; Pie(480,210,530,260,530,234,504,210); //Сектор Brush.Color := clBtnFace; TextOut(500,250,'(Pie)'); Для демонстрации мультипликации запрограммируем перемещение глаз у кота «влево - вправо». Добавим начальную прорисовку глаз: Pen.Color := clWhite; //Цвет глаз – белый - карандаш Brush.Color := clWhite; //Цвет глаз – белый – кисть //таким образом, рисуем и закрашиваем одним цветом Ellipse(73,105,113,147); // Левый глаз Ellipse(138,105,178,147); // Правый глаз Pen.Color := clGreen; //Цвет зрачков - зеленый Brush.Color := clGreen; Цвет зрачков - зеленый Pie(85,115,110,145,90,135,60,145); // Левый зрачок Pie(150,115,175,145,155,135,75,145); // Правый зрачок end; // Конец рисования на холсте Замечание: При программировании сложного изображения следует располагать элементы послойно - сначала те, что расположены на нижнем фоне, а затем те, что выше. 8. Программируем изменение положения зрачков: Необходимо ввести глобальную переменную, которая будет отвечать за сторону, куда смотрят глаза: В программе найти строчку implementation (необходима глобальная переменная) и ввести в разделе переменных переменную B логического типа: Var B : Boolean; Вернуться на изображение формы (нажать <F12>) и выбрать событие onActivate у формы, щелкнуть на нем и ввести следующий текст: B := true; // начальное значение переменной B Снова вернуться на изображение формы, выбрать объект Timer и запрограммировать его свойство onTimer – перерисовка, набрать следующий текст: with Canvas do //Снова обращаемся к холсту begin If B then //если глаза смотрят вправо Begin //закрашиваем правые зрачки цветом глаза - белым 50 Pen.Color := clWhite; Brush.Color := clWhite; Pie(85,115,110,145,90,135,60,145); // Левый зрачок Pie(150,115,175,145,155,135,75,145); // Правый зрачок // цвет зрачка - зеленый Pen.Color := clGreen; Brush.Color := clGreen; //рисуем левые зрачки Pie(75,115,100,145,80,135,50,145); // Левый зрачок Pie(140,115,165,145,145,135,65,145); // Правый зрачок B := False; //Глаза смотрят влево end else begin //аналогично, если глаза смотрели влево //закраска фоном Pen.Color := clWhite; Brush.Color := clWhite; Pie(75,115,100,145,80,135,50,145); // Левый зрачок Pie(140,115,165,145,145,135,65,145); // Правый зрачок //рисуем правые зрачки Pen.Color := clGreen; Brush.Color := clGreen; Pie(85,115,110,145,90,135,60,145); // Левый зрачок Pie(150,115,175,145,155,135,75,145); // Правый зрачок B := True; //Глаза смотрят вправо end; end; Программа завершена! 9. Запустить программу – <F9>. 5.3. ИНДИВИДУАЛЬНОЕ ЗАДАНИЕ Придумать изображение средней сложности (не меньше 20 команд рисования) и запрограммировать его. 5.4. ИТОГИ В пятой теме были изучены: графические примитивы; основы печати графического изображения; способ программирования мультипликации; диалог настройки принтера; диалог настройки печати. При создании демонстративной программы получены навыки работы: с визуальным компонентом таймер; построения сложного изображения. 6. РАБОТА С ТЕКСТОВОЙ ИНФОРМАЦИЕЙ Цель: изучение работы со строковыми переменными; работа с текстовыми файлами; стандартные диалоговые окна. 6.1. ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ 51 Символы и строки. Для использования в программе символьных переменных можно использовать стандартный тип языка Паскаль – Char. Значением переменных типа Char может быть любой символ, отображаемый на экране: буква русского или латинского алфавитов, цифра, знак препинания, специальные символы, например символ клавиши <Enter> («переход на новую строку»). Переменная должна быть объявлена в разделе описания переменных. Значение переменной заключается в прямые одинарные кавычки: ch := ‘Л’ – переменная ch получает значение – символ буквы Л. Переменные типа Char можно сравнивать друг с другом, используя соотношение: ‘0’<’1’<…<’A’<’B’<…<’a’<’b’<…<’А’<’Б’<…<’а’<…<’я’. Часть символов не имеет буквенных обозначений на клавиатуре. Для обозначения этих символов необходимо использовать оператор Chr(код), где код – номер символа, который нужно вывести. Все символы пронумерованы: системные символы имеют коды 1..31, цифры (’0’…’9’) – 48…57, латинские буквы (’A’…’z’) – 65…122, русские буквы (’А’…’п’) – 128…175, (’р’…’я’) – 224…239. Вместо функции Chr можно использовать оператор #. Для обратной операции – получения номера указанного символа необходимо использовать оператор Ord(символ). Пример: Ch := Chr(13) – переменной символьного типа Ch присвоить значение символа «переход на новую строку»; S := #10 – переменной символьного типа S присвоить значение символа «конец строки». V := Ord(’5’) – переменная целого типа получит значение кода символа ’5’ – код символа ’5’ равен 53. На базе стандартного типа Char создан тип «строка» - String и все производные от этого типа типы (смотри раздел 2.1). Ниже будем рассматривать стандартный тип String. Строка представляет собой массив символов, то есть строка является описанием array [0..255] of Char. Таким образом, к элементу строки можно обращаться по номеру – если переменная S имеет тип строка, то S[2] – даст второй символ строки, S[5] – пятый символ строки, S[0] – даст символ, отображающий длину строки. Например, если строка имеет длину 7 символов и обозначена переменной S, то S[0] даст символ ’7’. По умолчанию максимально доступная длина строки равняется– 255 символам. Если необходимо ограничить длину строки, то после описания типа переменной String указывают в квадратных скобках требуемую длину строки. Примеры: S : String[15]; – переменная S является строкой с максимально доступной длиной равной 15; Если переменная имеет значение S := ’абвгд’, то S[2] даст значение ’б’ – второй символ в строке s. Строки можно сравнивать друг с другом. Строки сравниваются посимвольно – если символы строк одинаковы, то такие строки равны; если в 52 одинаковых позициях расположены разные символы, то больше та строка, у которой код символа больше. Пример: ’Аб’ > ’АБ’ – во второй позиции код символа Б больше кода б; ’Аб’ < ’Аб ’ – вторая строка имеет большую длину; ’Аб’ = ’Аб’ – строки равны по длине и по составу символов. Со строками можно использовать следующие операции: Length(строка) – возвращает длину строки, описанной переменной строка. В отличие от команды переменная[0] команда Length возвращает числовое значение длины строки. Delete(строка, позиция, количество) – удаляет из строки количество символов, начиная с позиции позиция. Pos(подстрока, строка) – возвращает позицию вхождения подстроки подстрока в строку строка. Если в строке нет искомой подстроки, оператор Pos вернет значение 0. Copy(строка, позиция, количество) – копирует из строки строка с позиции позиция количество символов, указанных в переменной количество. Insert(строка, подстрока, позиция) – вставляет в строку строка с позиции позиция подстроку подстрока. Примеры: Пусть есть переменная S строкового типа, которая имеет значение ’СанктПетербург’ и переменная целого типа V: V := Length(S) – V получит значение 14; Delete(S,1,6) - переменная S получит значение ’Петербург’; V := Pos(’Петербург’,S) – переменная V получит значение 7; S := Copy(S,7,8) - переменная S получит значение ’Петербург’; Insert(S, ’-’,6) - строка S получит значение ’Санкт--Петербург’. Файлы и работа с текстом. Иногда необходимо выводить информацию не на экран, а в файл или считывать информацию из файла. Для этих целей существует переменная типа file. При создании переменной типа файл указывается тип файла, то есть тип данных, которые будет хранить файл. Для указания типа файл указывают file of тип. Особым является файл для содержания текстовой информации. Такой файл описывается так – TextFile. Примеры Res : file of char; Переменная Res указывает на файл символов; T : file of integer; Переменная T указывает на файл целых чисел; Str : File of String; Переменная Str указывает на файл строк; Text : TextFile; Переменная Text указывает на текстовый файл. Замечание: файл строк и текстовый файл это не одно и тоже. Текстовый файл самостоятельно обрабатывает признак конца строки и переход на новую строку. Для связки переменной типа файл с конкретным файлом на диске необходимо использовать оператор AssignFile(переменная, путь_к_файлу). 53 Примеры: AssignFile(text,’document.txt’); – установление связи между переменной text и файлом ’document.txt’; AssignFile(res,’a:\chars.dat’); - установление связи между переменной res и файлом ’chars.dat’, находящегося в корневой папке диска а:. Замечание: Для обеспечения возможности запуска программы с разных папок/компьютеров необходимо без необходимости не указывать жесткий путь к файлу, а считать, что файл хранится в текущей папке или указывать путь от текущей папки. Данное соглашение позволит переносить программу на другой компьютер без требования идентичной настройки структуры папок на двух компьютерах. Для вывода информации в файл используется оператор write(переменная_типа_файл, информация) или writeln(переменная_типа_файл, информация), где переменная_типа_файл – переменная, указывающая на файл, в который осуществляется вывод информации; информация – записываемая в файл информация. Оператор writeln работает только в текстовых файлах, его отличие от write в том, что после вывода информации курсор в файле переводится на новую строку. Команда writeln(переменная_типа_файл) – добавит пустую строку. Пример: Пусть описана переменная F типа текст (F : TextFile) и выводимая информация хранится в переменных X1 и Y1. Вывод значений этих переменных в файл на разных строках может быть выполнен так: writeln(F,X1); writeln(F,Y1); Для считывания информации используется оператор read(переменная_типа_файл, информация) или readln(переменная_типа_файл, информация). Описание этих операторов такое же, как и у операторов вывода. Оператор readln также может быть использован только для считывания информации из текстового файла, при этом предполагается, считываемые значения находятся на разных строках. Команда readln(переменная_типа_файл) – переведет курсор в файле на новую строку. Для работы с файлом необходимо указать операцию, которая будет выполняться с файлом: чтение или запись (здесь мы не рассматриваем случаи, когда необходима работа с файлом, позволяющая одновременно и записывать и считывать информацию). Для текстовых файлов существует еще одна возможность – открыть файл на последней строке для дописи информации. Эти операции описываются операторами: Reset(переменная_типа_файл) - открыть файл для чтения; Rewrite(переменная_типа_файл) - открыть файл для записи; Append(переменная_типа_файл) - открыть файл для дописи. 54 Необходимо отметить об особенностях работы этих операторов. Оператор Reset открывает файл для чтения, если в момент открытия файла не существует, то это приведет к ошибке. Это же ограничение накладывается и на команду Append. При открытии для записи (команда Rewrite) уже имеющегося файла, файл будет предварительно очищен, то есть вся информация из этого файла будет удалена; если файл на момент открытия отсутствовал, то он будет создан. При возникновении таких ошибок программа выдаст стандартное окно сообщения об ошибке. Для того чтобы самостоятельно учитывать и обрабатывать возможные ошибки при работе с файлами, необходимо: 1. Отключить автоматический контроль работы с файлами – директива {$R-}, такая команда сообщает компилятору, что автоматическая обработка исключительных ситуаций при работе с файлами отключена. (Все директивы компилятора начинаются с последовательности двух значков – «открывающаяся фигурная скобка» и «знак доллара» и заканчиваются «закрывающейся фигурной скобкой»); 2. Выполнить критическую операцию (открытие, чтение и т.д.); 3. Включить директиву автоматической проверки корректности операций с файлами – директива {$R+}. 4. Проверить результат операции. Результат операции возвращается оператором IOResult. Если этот оператор возвращает 0, то операция прошла успешно, иначе она возвращает код ошибки; 5. Проанализировать сообщение оператора IOResult и в случае необходимости выполнить необходимые действия. (Например, если при открытии файла для чтения выяснилось, что файл не существует, то создать его командой Rewrite, а затем снова открыть для чтения); После окончания работы с файлом необходимо закрыть переменную типа файл с помощью команды CloseFile(переменная_типа_файл). Замечание: Сколько раз файл был открыт (для чтения или для записи) столько же раз он должен быть закрыт. При считывании информации из файла необходимо знать – сколько информации можно считать из файла? Для этих целей введена переменная EOF(переменная_типа_файл), (переменная читается End Of File – конец файла) которая принимает значение true при достижении конца файла и false в противном случае. Поэтому процесс считывания информации из файла обычно осуществляется в цикле до тех пор, пока не достигнут конец файла (если нет другого условия окончания операции считывания). Для текстовых файлов существует также переменная, оценивающая, не достигнут ли конец строки – EOLn(переменная_типа_файл), (переменная читается End Of Line – конец строки) которая принимает значение true при достижении конца строки и false в противном случае. Для демонстрации последовательности работы с файлом рассмотрим фрагмент программы для посимвольного считывания информации из тек55 стового файла ‘document.txt’ и подсчета количества символов в файле. Будем считать, что раздел переменных содержит описание переменных: F:TextFile; C:Char; - считываемые символы; I:Integer; - переменная для подсчета количества символов. Пример: Var //раздел описания переменных F : TextFile; C : Char; I : Integer; begin AssignFile(F, ’document.txt’); //Связка файла и файловой переменной {$R-} //Отключить автоматическую проверку reset(F); //Открыть файл для чтения {$R+} //Включить автоматическую проверку If IOResult = 0 then //Если операция прошла успешно, то begin I := 0; //Установить счетчик символов в 0 While Not EOF(F) do //Пока не конец файла begin While Not EOLn(F) do //Пока не конец строки begin Read(F,C); //Считать очередной символ Inc(I); //Увеличить счетчик символов end; Readln(F); //Перейти к считыванию новой строки end end else begin MessageDlg(‘Ошибка открытия файла’, mtError, [mbOk], 0); //В случае ошибки выдать сообщение об ошибке end; end; В примере для вывода сообщения об ошибке было использовано стандартное диалоговое окно. Стандартные диалоговые окна. Для вывода различных сообщений можно использовать стандартные диалоговые окна Delphi. Диалоговые окна запускаются командой: MessageDlg(сообщение, Тип, Кнопки, КонтекстСправки) где Сообщение – выводимое сообщение; Тип - тип сообщения, Сообщение может быть информационным, предупреждающим или сообщением об ошибке; Кнопки - список, определяющий число и вид кнопок; КонтекстСправки – определяет номер экранной справки, так как экранная справка не используется, то необходимо установить значение 0. Константы, определяющие тип окна сообщения и вид кнопок пере56 числены в таблице 6.1. Таблица 6.1 Константа Тип сообщения Сообщения MtWarning Внимание MtError Ошибка MtInformation Информация mtConfirmation Запрос подтверждения MtCustom Пользовательское окно Вид кнопок Обозначение Да Нет Ok Отмена Помощь Прекращение Повтор Игнорировать Все Константа MbYes MbNo MbOk MbCancel MbHelp MbAbort MbRetry MbIgnore MbAll Значок Код возврата mrYes mrNo mrOk mrCancel mrHelp mrAbort mrRetry mrIgnory mrAll При вызове диалогового окна с набором кнопок, константы кнопок перечисляются в квадратных скобках через запятую. Для анализа, какая кнопка была активирована, следует значение, возвращаемое диалоговым окном, присвоить переменой типа word. Пример: Пусть необходимо выдать диалоговое окно запроса с тремя кнопками «Yes», «No» и «Cancel» и проанализировать какая кнопка была «нажата». W := MessageDlg(‘Какую кнопку нажать?’, mtConfirmation, [mbYes, mbNo, mbCancel]); Case W of mrYes : {действие, связанное с «нажатием» на кнопку Yes}; mrNo : {действие, связанное с «нажатием» на кнопку No}; mrcancel : {действие, связанное с «нажатием» на кнопку Cancel}; end; 6.2. СОЗДАНИЕ ПРОГРАММЫ «РЕДАКТОР ТЕКСТА» Задача: Написать программу, считывающую посимвольно информацию из текстового файла, позволяющую отредактировать считанный текст и сохранить файл на диске. Окно программы представлено на рис.6.1. Процесс создания программы происходит по следующему алгоритму: 1. Запустить Delphi; 2. Сохранить проект («work6.dpr», «main.pas»); 3. Настроить вид экрана: Для отображения быстрой справки – подсказки для видимых элементов окна 57 необходимо установить свойство формы ShowHint (показывать подсказку) в значение True. Все элементы, размещенные в окне, автоматически будут иметь свойство ShowHint в значении true; Рис.6.1. Примерный вид окна программы «Работа с текстом» В качестве дизайна окна будем использовать «главное меню» и панель «горячих клавиш». Поместить панель на форму и настроить ее свойства: o Поместить панель (элемент Panel, вкладка Standard, значок ); o Изменить заголовок на ‘’ Caption; o Изменить высоту панели так, чтобы она была чуть больше кнопок, которые будут в неё вставлены (Height = 40). o Сделать так, чтобы панель независимо от размера окна всегда находилась вверху окна Align установить в значение alTop – вверху; Поместить на экран «горячие кнопки» (SpeedButton, Additional, ). Такие кнопки обычно не имеют заголовка, а несут функциональную информацию по картинке и контекстной справке. Поместить 3 таких кнопки: «Выход», «Открыть файл», «Сохранить файл»: o Назвать кнопки (Name) соответственно SBQuit, SBOpen и SBSave; o Выбрать картинки для кнопок в соответствии с назначением кнопок (картинки можно взять из папки кнопок в папке общих программ Borland или в папке Delphi (папка «Images\Buttons»))Glyph; можно выбрать следующие картинки: FileOpen для открытия файла, FileSave для закрытия файла, DoorShot для выхода из программы; o Назначить подсказки для кнопок: для кнопки SBQuit – «Выход из программы»; для SBOpen – «Открыть файл»; для SBSave – «Сохранить файл» Hint; Создать главное меню: o Поместить главное меню на форму (MainMenu, Standard, ); o Этот значок запускает программу-мастера построения меню – щелкнуть на значке для запуска мастера; o Построить иерархическое меню. Для этого в поле ввода Файл набрать название пункта меню («Файл») (Caption), затем смеОткрыть ститься в подменю и вводить названия «Открыть» и «Сохра- Сохранить нить», затем поставить разделитель пунктов – при вводе названия Выход поставить «-» (минус); 58 o Для каждого пункта меню назначить «горячую клавишу», то есть ту комбинацию клавиш, при нажатии на которую этот пункт меню будет активизироваться (свойство ShortCut). Назначить такие комбинации (выбрать из списка) – для пункта «Открыть» – <Ctrl><O>; «Сохранить» – <Ctrl><S>; «Выход» – <Ctrl><Q>; Для открытия файла поместить стандартный диалог открытия файлов: Поместить объект открыть файл (Dialogs, OpenDialogs, ); Дать ему имя ODText (Name) Настроить заголовок окна на «Открытие текстового файла» (Title); Назначить имя папки, из которой будут открываться файлы по умолчанию, дав ему имя «.» - текущая папка (папка программы) (InitialDir); o Настроить фильтр файлов, которые будут открываться (Filter). Это свойство запустит мастера – слева в окне описание групп файлов (Filter Name), справа – шаблон группы (Filter). Изменить описание на «Текстовые файлы», а шаблон на «*.txt»; Для сохранения файлов необходимо: o o o o o Поместить на форму элемент диалог сохранения (SaveDialog, Dialogs, ); o Настроить имя на SDText (Name); o Остальные свойства настроить как и у объекта OpenDialog; Для переключения между режимами чтения файла (посимвольное чтение или чтение сразу всего файла) необходимо: Поместить на панель объект независимая метка (CheckBox, Standard, ); Настроить имя на CBChar ( Name); Заголовок изменить на «Посимвольно» ( Caption); Кнопка активна (выполняется чтение посимвольно) ( Checked установить в true); Для вывода текста необходимо: o o o o o На форму поместить элемент примечаний (Memo, Standard, ); o Настроить имя на MText ( Name); o Изменить свойство ScrollBars на ssBoth для добавления в поле вывода текста скроллеров – обеспечение перемещения по тексту, если текст окажется больше окна вывода; o Очистить окно текста. Выбрать свойство Lines и удалить строку MText; o Расположить поле вывода текста на всё доступное пространство формы. Для этого изменить свойство Align на alClient; Форма настроена! 4. Приступить к программированию событий: Запрограммировать выход из программы на кнопку SBQuit (Событие onClick, команда - Close); Запрограммировать открытие файла на кнопку SBOpen (Событие onClick), добавив следующий текст: o Добавить в разделе переменных процедуры следующие переменные – F – переменная типа текстовый файл для связки с файлом на диске; C – считываемый символ – переменная типа символ и W – переменная типа целое число для записи текста в поле MText, так как этот объект не позволяет добавлять строку посимвольно: var 59 F : TextFile; C : Char; W : Word; o Технология считывания следующая: открыть диалог открытия файлов; получить имя открываемого файла из этого диалога; открыть файл; Проверить результат открытия файла, если ошибка – выдать сообщение, иначе приступить к считыванию информации; Если осуществляется чтение сразу всего файла, то считать текст, иначе: пока не конец файла добавить в поле вывода текста пустую строку; пока не конец строки считать символ и добавить его к пустой строке; o Текст, реализующий этот алгоритм: If ODText.Execute then //Если в диалоге выбран файл begin MText.Clear; //Очистить поле вывода AssignFile(F,ODText.FileName); //Связать файл с F {$I-} //Отключить проверку reset(F); //Открыть файл {$I+} //включить проверку If IOResult = 0 then //Файл открыт удачно begin Form1.Caption := ODText.FileName; {В заголовке окна отобразить имя открытого файла} W := 0; //счетчик строк If CBChar.Checked then //если посимвольный ввод begin while Not EOF(F) do //пока не конец файла begin MText.Lines.Add(''); //добавить пустую строку While Not EOLn(F) do //пока не конец строки begin read(F,C); //считать очередной символ MText.Lines[W]:=MText.Lines[W]+C; {добавить к пустой строке считанный символ} end; Inc(W); //увеличить счетчик строк readln(F); {перейти к считыванию новой строки} end; end else //файл считывается сразу begin MText.Lines.LoadFromFile(ODText.FileName); {считать файл} end; CloseFile(F); //закрыть файл end else //файл не открыть ShowMessage('Ошибка открытия файла '+ODText.FileName); 60 {выдать сообщение об ошибке} end; //конец работы с файлом В программе виден способ заполнения элемента MText текстом: текст представляет собой массив строк (свойство Lines) и, или загружается сразу из указанного файла (строка MText.Lines.LoadFromFile(ODText.FileName);), или происходит обращение по индексу к нужной строке и заполнение её (строка MText.Lines[W]:=MText.Lines[W]+C; – к строке с индексом W добавить считанный символ C, необходимо учитывать, что нумерация строк начинается с 0); o Запрограммировать сохранение введенного или отредактированного файла на диск на кнопку SBSave (Событие onClick): Ввести следующий текст: If SDText.Execute then {если выбрано сохранение файла} begin Mtext.Lines.SaveToFile(SDText.FileName); //сохранить файл Form1.Caption := SDText.FileName; {изменить заголовок окна на имя сохранённого файла} end; 5. Для улучшения программы можно выполнить следующее: 5.1. Ввести индикатор изменения текста в поле ввода – как только текст изменен отобразить индикатор изменения; 5.2. При осуществлении сохранения файла проверять нет ли уже файла с таким именем и выдавать запрос на перезапись; 6. Например, пункт 5.1. можно выполнить так: На форму (на панель) добавить элемент метка (Label, Standard, ). Изменить его свойства: o Имя изменить на LModify (Name); o Заголовок на «Текст изменён» (Caption); o Видимость (если текст не изменён, то и индикатор изменения не показывать) установить видимость в значение False (Visible); Запрограммировать событие элемента MText нажатие клавиши onKeyPress и ввести текст: o LModify.Visible := true; При сохранении текста (событие onClick кнопки SBSave) после строки «{изменить заголовок окна на имя сохранённого файла}» добавить строку изменения состояния индикатора: o LModify.Visible := false; 7. При желании пункт 5.2. запрограммировать самостоятельно (рекомендация: попытаться открыть файл с введенным именем и если файл открывается (файл существует!), то требуется вывести запрос на перезапись); 8. Программа готова – запуск <F9> 6.3. ИНДИВИДУАЛЬНОЕ ЗАДАНИЕ Модифицировать созданную программу для выполнения операции с текстом в зависимости от номера варианта: 1. В считанном тексте подсчитать количество гласных символов; 2. В считанном тексте подсчитать количество согласных символов; 61 3. Заменить все гласные буквы в тексте на порядковые номера – «а»-1, «е»-2 и т.д.; 4. Добавить после каждого слова текста запятую; 5. Подсчитать количество слов в тексте; 6. Найти слово с максимальным соотношением согласные/гласные; 7. Найти в тексте самое длинное слово; 8. Подсчитать все знаки препинания в тексте; 9. Найти в тексте самое длинное предложение; 10. Выводить каждую строчку в обратном порядке; 11. Выводить только нечетные слова текста; 12. Выводить только четные слова текста; 13. Подсчитать количество предложений в тексте; 14. Выводить только те слова, длина которых больше введенного числа; 15. Выводить только те строки, которые содержат введенную подстроку; 16. Каждый символ, считываемый из файла, закодировать его кодом, после кода ставить знак «;»; 17. Выводить каждое считанное предложение с новой строки; 18. Найти предложение с максимальным количеством слов; 19. Удалить из текста введенный фрагмент строки; 20. Заменить в тексте один введенный фрагмент на другой введенный фрагмент. 6.4. ИТОГИ В шестой теме были изучены: функции для работы со строками; функции для работы с текстовыми файлами; стандартные диалоговые окна. При построении демонстрационной программы получены навыки использования новых компонентов: панели; кнопки быстрого доступа - «горячие кнопки»; главного меню окна; диалоговых окон – открытие файла и сохранение файла; элемента независимого выбора. 7. РАБОТА С БАЗАМИ ДАННЫХ Цель: Создание составных типов данных; изучение оператора присоединения; работа с базами данных. 7.1. ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ Составные типы данных. В практике программирования довольно часто приходиться иметь дело с данными, которые естественным образом состоят из других данных. Например, сведения о студентах могут содержать фамилию, имя, отчество, число, месяц и год рождения, домашний адрес и другие данные. Для представления подобной информации в языке Паскаль используется структура, которая носит название record (запись). С одной стороны, запись можно рассматривать как единую структуру, а с другой – как набор отдельных элементов, компонентов. Характерной особенностью записи является то, что составляющие её компоненты могут быть разного типа. Другая особенность состоит в том, что каждый компонент записи имеет имя. Итак, запись – это структура данных, состоящая из отдельных 62 именованных компонентов разного типа, называемых полями. Объявление записи может быть двух типов: как новый тип данных для описания переменных этого типа, так и непосредственное описание переменной, как запись. В общем виде описание выглядит так: Имя = record поле1 : тип1; поле2 : тип2; …… полеN : типN; end; где Имя - имя переменной или типа запись; поле1, …, полеN - поля записи – имена переменных с указанием типов этих переменных (тип1,…,типN). record - зарезервированное слово, указывающее на описание записи. Описание записи должно оканчиваться словом end. Пример: type date = record day : integer; month : string[8]; year : integer; end; var D : date; C : record hour : integer; minute: integer; end; В примере объявлен тип date для описания даты и описаны две переменные D, описанного типа date и C – переменная типа запись для описания времени. При описании типов полей, некоторые поля также могут быть записью. Пример: student :record name : string[15]; born :record date : integer; month : string [8]; year : integer; end; end; В примере поле записи born является записью. Для обращения к полю переменной типа записи, необходимо указывать имя переменной и через точку указать имя поля. Примеры: 63 s.name := ‘Петров’; s.born.day := 15; Если при работе происходит обращение к нескольким полям, то можно не указывать каждый раз при описании полей имя переменной, а воспользоваться оператором присоединения: with имя do операция, где имя – имя переменной типа запись; операция - операции с полями записи. Пример: Пусть есть переменная d типа date для описания даты, и требуется заполнить значения полей этой переменной: with d do begin day := 15; month := ‘Сентябрь’; year := 2002; end; Для хранения данных на диске можно использовать файлы типа запись. Пример: Пусть в разделе переменных описаны переменная d типа запись date для описания даты и переменная F : file of date – файл типа запись date. Требуется записать значение даты в файл и считать его (записать сразу всю запись, а считать только значение месяца): with d do begin day := 15; month := ‘Сентябрь’; year := 2002; end; write(F,d); //запись сразу всех полей записи … read(F,d.mounts); //чтение значения месяца переменной d Используя переменные типа запись и переменную типа файл записи можно строить базы данных. Но в Delphi есть более удобный способ для построения баз данных – поддержка стандартных типов баз данных и операций для работы с ними. Базы данных. В состав Delphi входят средства и компоненты для создания и работы с базами данных различных систем: от dBase до Informix и Oracle. База данных (БД) – это набор однородной, как правило, упорядоченной по некоторому критерию информации. БД представляют собой файл (или набор файлов) содержащих информацию. БД состоит из записей. Каждая запись содержит информацию об одном экземпляре данных. Например, запись из базы данных «студенты» содержит информацию толь64 ко об одном экземпляре – студенте. Записи состоят из полей. Каждое поле содержит информацию об одной характеристике экземпляра. Например, база данных «студенты» состоит из следующих полей: «Идентификационный номер», «Имя», «Дата рождения», «Пол», «Номер группы», «Признак иногороднего», «Стипендия», «Средний балл сессии», «Средний балл аттестата» – это имена полей. Содержание этих полей идентифицирует конкретного студента. Замечание: все записи содержат одинаковые поля. Некоторые поля могут быть не заполнены, но они все равно должны присутствовать в записи. БД легко представить в виде таблицы. Каждая строка – запись, а ячейка таблицы – поле. Поэтому файл данных БД принято называть «Таблица». В Delphi можно предложить следующий порядок создания БД: создание папки; создание псевдонима; создание таблиц. БД может представлять собой несколько таблиц, при работе с БД могут создаваться вспомогательные файлы. Поэтому при работе с БД удобно хранить все файлы (таблицы и вспомогательные файлы БД) в одной папке. Таким образом, при разработке программы, использующей БД необходимо создать папку для хранения файлов БД. Для обозначения местонахождения файлов БД в Delphi принято понятие псевдонима – каждая БД имеет псевдоним, содержащий имя папки, где хранятся файлы БД. Такая структура позволяет при перенесении программы в другую папку только изменить псевдоним. Создание псевдонима. Для создания псевдонимов (Alias) вместе с Delphi поставляется утилита BDE Administrator (значок программы Окно программы показано на рис. 7.1. ). Рис. 7.1. Задание псевдонима БД 65 Слева представлены псевдонимы установленных на компьютере таблиц. Для создания нового псевдонима необходимо выбрать пункт «Object/New». В появившемся окне необходимо выбрать драйвер доступа к данным создаваемой таблицы. Драйвер STANDARD обеспечивает доступ к данным таблиц в формате Paradox. После выбора драйвера необходимо изменить имя псевдонима созданного по умолчанию (Standard) и указать путь нахождения файлов таблицы. Замечание: в Delphi 2.0 необходимо вписать путь в строку ввода, более поздние версии Delphi позволяют воспользоваться мастером для выбора папки нахождения файлов таблицы. После создания псевдонима необходимо выбрать команду «Object/Apply» и подтвердить необходимость сохранения конфигурации. Создание таблиц. Для создания таблицы сначала необходимо проанализировать данные, которые необходимо хранить в БД. Можно использовать следующее правило: если предполагается, что во время использования программы будет выполняться выборка информации по какому-то критерию, то информацию, обеспечивающую возможность этой выборки, следует поместить в отдельное поле. БД могут состоять как из одной таблицы, в простейшем случае, так и из нескольких таблиц связанных между собой по некоторым полям (такие БД называются реляционными). После определения структуры БД можно приступить к созданию таблиц. Для этого можно использовать утилиту «Database desktop» из папки программ Delphi, ярлык программы . Эта утилита позволяет создавать и модифицировать БД различных форматов (Paradox, dBase, Microsoft Access и др.). Главное окно утилиты представлено на рис. 7.2. Рис.7.2. Главное окно утилиты Для создания новой таблицы необхо«Database Desktop» димо выполнить пункт «File/New/Table». В окне (рис. 7.3) выбрать тип создаваемой БД (по умолчанию это Paradox 7) . В итоге появится окно создания новой БД (рис.7.4). Необходимо указать имя поля табРис. 7.3. Создание новой таблицы лицы в ячейке «FieldName», затем в поле «Type» указать тип поля. Получить список доступных значений поля можно, нажав правую кнопку мыши. В демонстрационной программе будут использоваться следующие типы: Alpha (A) – символьные значения длиной до 255 символов (в скобках указано принятое сокращение); Number (N) 66 – числовые значения с плавающей точкой в диапазоне –10307…+10308, точность до 15 значащих цифр; Money ($) - тип предназначен для хранения де- Рис. 7.4. Окно создания структуры новой БД нежных сумм, число знаков после запятой по умолчанию – 2, при показе значения выводится знак денежной единицы; Date (D) – значения даты (в диапазоне от 01.01.9999 до н.э. до 31.12.9999). Автоматически изменяемое поле Autoincrement (+) – значения этого поля изменяются автоматически, поле удобно для создания первичного ключа (см. ниже). При использовании типа Alpha в ячейке Size необходимо указать максимально допустимый размер. Для полей можно указать на обязательную необходимость заполнения значения (поле ввода «Required Field»), минимально допустимое значение («Minimum Value»), максимально допустимое значение («Maximum Value»), значение по умолчанию («Default Value»), шаблон ввода значения (Picture) – для построения которого можно воспользоваться мастером («Assist»). Для получения однозначности данных в таблице одно из полей (или набор полей) должно носить уникальный характер. Такое поле (поля) называется первичным ключом таблицы (должно располагаться в начале списка полей) и обозначается символом «*» в поле «Key» (для назначения поля первичным ключом достаточно в поле Key нажать любую клавишу). Заполнив значение всех ячеек для вводимого поля можно перейти к вводу нового поля. Для этого достаточно нажать клавишу «стрелка вниз». Для ввода поля выше введенного – нажать <Insert>. Для удаления ошибоч67 ного поля – <Ctrl><Del>. При выполнении сортировки значений таблицы по какому-то из полей или фильтрации поля по какому-то значению необходимо, чтобы БД по этому полю была проиндексирована, т.е. построить вторичный индекс таблицы. Для этих целей в поле «Table Properties» выбрать свойство «Secondary Indexes» и запустить мастера настройки, щелкнув на кнопку «Define». При этом будет выведено окно построения «вторичного индекса» (Рис.7.5.). В левой части окна перечислены поля таблицы, которые могут быть использованы в качестве вторичного индекса. С помощью кнопок «» и «» выбирают нужные поля для индекса (порядок следования полей во вторичном индексе указывает их последовательность, для изменения порядка следования используются кнопки «» и «»). После выбора полей индекса и указания порядка их следования необходимо сохранить индекс, нажав на кнопку «Ok», Рис. 7.5. Окно определения вторичного индекса и присвоить ему имя. Рекомендация: следует давать индекс, начиная со слова «Index», а затем перечислять поля, по которым построен индекс. Таким образом, из названия будет понятно, что это индекс и по каким полям он построен. Пример, в примере, показанном на рисунке, индекс следует назвать, например, так: Index_Name_Sex –индекс по имени и полу. Список всех построенных вторичных индексов будет показан в окне под кнопкой «Define». При необходимости индекс можно изменить – кнопка «Modify» или удалить – «Erase». После создания таблицы её нужно сохранить на диске (кнопка «Save as») в папке определенной псевдонимом для этой БД. Доступ к данным таблицы. При программировании доступа к данным БД в Delphi используется такая структура: Файл БД (таблица) Элемент Table Элемент DataSource Видимые элементы для отображения полей таблицы Элемент Table указывает на файл БД и содержит все настройки таблицы (индексные файлы, активность и т.д.). На элемент Table указывает 68 элемент DataSource, который является связкой между элементом Table и всеми видимыми элементами, служащими для отображения полей таблицы. При работе с таблицей часто может потребоваться отсортировать данные таблицы по какому-то из полей, или отфильтровать значения по какому-то полю, или найти запись с каким-то значением. Рассмотрим, какие команды можно использовать для решения этих задач. Для того чтобы данные в таблице были отсортированы по определенному полю, нужно указать в качестве индекса имя вторичного индекса поля, по которому надо отсортировать данные. Эта команда в общем виде записывается так: Таблица.IndexName := Имя_индекса; где Таблица – имя таблицы БД; Имя_индекса – имя требуемого для сортировки индекса; Если требуется отфильтровать данные в таблице, необходимо отсортировать данные по тем полям, по которым будет осуществлена фильтрация и выполнить команду фильтрации. В общем виде команда пишется так: Таблица.IndexName := Имя_индекса; Таблица.SetRange([нзн1,нзнN],[кзн1,кзнN]); где в квадратных скобках указываются начальные допустимые значения фильтрации по всем необходимым полям через запятую, во вторых квадратных скобках соответственно допустимые конечные значения фильтрации по всем полям фильтрации (показан случай для поиска по двум значениям нзн1,нзнN и кзн1,кзнN). Для отмены фильтрации необходимо выполнить команду: Таблица.CancelRange; Если требуется найти запись с определенным содержимым можно воспользоваться командой неполного поиска (поиска по неполному значению искомого значения). При удачном поиске указатель таблице будет установлен на найденной записи, иначе указатель будет установлен на запись, ближайшей к искомой записи. Перед выполнением этой команды также необходимо, чтобы таблица была отсортирована по искомым полям. В общем виде команда записывается так: Таблица.IndexName := Имя_индекса; FindNearest([зн1,знN]); где в квадратных скобках указываются через запятую искомые значения по полям поиска (показан случай для поиска по двум значениям зн1,знN). Использование этих команд станет понятным при построении демонстрационной программы. 69 7.2. СОЗДАНИЕ ПРОГРАММЫ «СПИСОК СТУДЕНТОВ» Задача: Написать программу управления структурой БД «студенты», которая позволяет добавлять, редактировать и удалять записи, а также сортировать, фильтровать записи и осуществлять поиск записи студента по введенной фамилии. Окно программы представлено на рис.7.6. Рис.7.6 Примерный вид окна программы «Список студентов» Процесс создания программы происходит по следующему алгоритму: 1. Настроить псевдоним базы данных: Создать в папке создаваемой программы папку для хранения баз данных. Назвать папку «Data»; Запустить BDE Administrator (из папки Delphi – «Пуск/Программы/Borland Delphi/BDE Administrator», иконка ); назвать псевдоним (Alias) именем по номеру группы (например, если номер группы 9599, то псевдоним назвать 9599); С помощью мастера (для Delphi 3 - 6) или вручную указать папку, где будут находится файлы базы данных (указать путь к созданной папке «Data»); Сохранить конфигурацию («Object/Apply») и выйти из BDE Administrator («Object/Exit»); 2. Создать базу данных: Запустить Database Desktop («Пуск/Программы/Borland Delphi/Database Desk top», иконка ); Создать новую таблицу («File/New/Table»). Выбрать драйвер базы данных Paradox; Создать поля таблицы «Студенты». Структура БД: идентификационный (уникальный) номер студента (поле ID) – тип поля автоинкремент, поле первичного индекса; фамилия студента (поле Name) – тип данных символьное поле; пол студента (поле Sex) – тип данных символьный; группа студента (поле Group) – тип данных числовой. Вид заполненной таблицы полей показан в таблице 7.1: 70 Таблица 7.1 Field Name Type Size Key 1 ID + * 2 Name A 20 3 Sex A 7 4 Group N Сделать 3 вторичных индекса: по полям Name; Sex, Name (в индекс включены два поля – первое Sex, второе Name); Group, Name (выбрать среди свойств таблицы (Table Properties) свойство Secondary indexes). Назвать индексы: Index_Name, Index_Sex_Name, Index_Group_Name соответственно; Сохранить таблицу (кнопка «Save as») в папке «Data», созданной в 1 пункте для БД, дав имя таблице «Student.db»; Выйти из Database desktop – команда «File/Exit»; 3. Запустить Delphi; 4. Создать новый проект и сохранить его папке создаваемой программы («work7.dpr», «main.pas»); 5. Настроить вид экрана: Для подключения файла баз данных необходимо: o Поместить на форму таблицу связки (элемент Table, вкладка DataAccess, значок ). Настроить элемент Table: o Дать имя таблице TStud ( Name); o В свойстве DatabaseName указать имя псевдонима (в нашем примере 9599); o Настроить имя таблицы - выбрать из списка имя файла «Student.db» ( TableName); o Настроить индексный файл – выбрать из списка имя индекса Index_Name (сортировка по фамилии студента) ( IndexName); o Сделать таблицу активной (показать содержимое базы данных) – установить свойство Active в значение true; Поместить элемент-связку (DataSource, DataAccess, ): o Дать имя объекту DSStud (Name); o Настроить связку на элемент TStud, выбрать из списка ( DataSet); Поместить на форму элемент отображения данных БД и работы с ним – элемент таблица баз данных (DBGrid, DataControl, ). Настроить его свойства: o Дать имя объекту DBGStud (Name); o Указать элемент связку DSStud (DataSet); o Настроить поля, которые будут отображены в таблице (Columns), запустив ма- стера настройки : Удалить поле «ID», нажав клавишу <Del>; Изменить заголовки таблицы для каждого поля («Фамилия», «Пол», «Группа»): выбрать в списке поле и изменить его свойство Title.Caption; Для поля «Пол» ввести список значений, позволяющий при вводе записи выбирать значение из списка – свойство PickList – добавить две строки «мужской», «женский»; Закрыть настройщик свойств полей; Для сортировки данных поместить элемент Зависимых групп кнопок ниже элемента DBGStud слева (на рис.7.6 элемент не виден): 71 o Поместить элемент RadioGroup (Standard, ) и настроить свойства: Имя объекта изменить на RGSort (Name); Изменить заголовок на «Сортировка» (Caption); Добавить список сортировки («Имя», «Пол», «Группа»), введя эти значения при редактировании свойства Items; Установить по умолчанию сортировку по имени (свойство ItemIndex установить в 0); Для фильтрации добавить еще один элемент зависимых кнопок (разместить справа от элемента RGSort): o Поместить элемент RadioGroup (Standard, ) и настроить свойства: Изменить имя на RGFiltr (Name); Изменить заголовок на «Фильтрация» (Caption); Добавить список фильтрации («Весь список», «Юноши», «Девушки») (Items); Установить по умолчанию отображение всего списка (ItemIndex); Для осуществления поиска студента по фамилии добавить элементы ниже элементов RGSort и RGFiltr: o Элемент ввода фамилии – строка ввода (Edit,Standard, EFind (Name); o Подсказку к строке ввода – элемент метка (Label, Standard, ловок на «Поиск фамилии:» (Caption); ), элемент назвать ), изменить заго- o Кнопку начала поиска – элемент кнопка (Button, Standard, ), изменить имя на BFind (Name); Добавить кнопку выхода из программы (расположить справа от таблицы) – элемент кнопка (Button, Standard, ), изменить имя на BQuit (Name); Форма готова! 6. Запрограммировать кнопку выхода BQuit; 7. Запрограммировать сортировку списка студентов. Сортировка осуществляется при анализе индекса (ItemIndex) объекта RGSort. Необходимо добавить следующие строки на событие этого элемента onClick: Case RGSort.ItemIndex of 0 : TStud.IndexName := 'Index_Name'; //индекс по имени 1 : TStud.IndexName := 'Index_Sex_Name'; //индекс по полу 2 : TStud.IndexName := 'Index_Group_Name'; //индекс по группе end; DBGStud.SetFocus; {сделать активным таблицу DBGStud} 8. Запрограммировать фильтрацию списка студентов. Фильтрация осуществляется при анализе индекса (ItemIndex) объекта RGFiltr. Необходимо добавить следующие строки на событие onClick этого элемента: Case RGFiltr.ItemIndex of 0 : TStud.CancelRange; //отменить фильтр 1 : begin TStud.CancelRange; //отменить фильтр 72 2: TStud.IndexName := 'Index_Sex_Name'; TStud.SetRange(['мужской'],['мужской']); {показать только мужчин} end; begin TStud.CancelRange; TStud.IndexName := 'Index_Sex_Name'; TStud.SetRange(['женский'],['женский']); {показать только женщин} end; //индекс по полу //установить фильтр //отменить фильтр //индекс по полу //установить фильтр end; DBGStud.SetFocus; {сделать активным элементом таблицу DBGStud} 9. Запрограммировать поиск записи по введенной фамилии в поле ввода элемента EFind, используя событие onClick элемента кнопка BFind. Необходимо добавить следующие строки: TStud.CancelRange; //отменить фильтр (вдруг он установлен?) RGSort.ItemIndex := 0; //отобразить режим сортировки RGFiltr.ItemIndex := 0; //отобразить режим фильтра TStud.IndexName := 'Index_Name';//Индекс по искомому полю TStud.FindNearest([EFind.Text]); //Поиск записи DBStud.SetFocus; //Сделать активным таблицу DBGStud 10. Программа написана! 11. Запустить программу - <F9>; 12. После запуска программы ввести данные базы данных и проверить работоспособность программы. 7.3. ИНДИВИДУАЛЬНОЕ ЗАДАНИЕ Модифицировать созданную программу для обработки данных БД «Студенты». Варианты заданий перечислены ниже: 1. Выводить список студентов, определенного года рождения, вводимого из поля ввода; 2. Выводить список студентов, определенной группы, вводимой в поле ввода; 3. Выводить список студентов, у которых средний балл аттестата больше 4; 4. Выводить список студентов, у которых нет троек по результатам сессии (средний бал сессии больше 4); 5. Выводить список иногородних студенток; 6. Выводить список иногородних студентов мужчин; 7. Выводить список студентов отличников определенной группы, вводимой в поле ввода; 8. Выводить список студентов определенной группы и определенного пола задаваемых из полей ввода; 9. Выводить список студентов получающих стипендию больше введенного числа; 10. Выводить список студентов не получающих стипендию; 11. Выводить список студентов определенного года рождения и пола; 12. Выводить список студентов, имеющих средний балл аттестата и сданной сессии больше 4; 13. Осуществить поиск студентов с введенной фамилией определенной группы; 14. Осуществить поиск студентов с введенной фамилией определенного года рождения; 73 15. Осуществить поиск студентов с введенной фамилией определенного пола; 16. Осуществить поиск студентов хорошистов, получающих стипендию; 17. Осуществить поиск студентов с введенной фамилией получающих стипендию; 18. Выводить список студентов юношей, получающих стипендию и имеющих среднюю оценку сессии больше 4; 19. Выводить список студентов, получающих стипендию и имеющих среднюю оценку сессии меньше 4; 20. Вывести список девушек, окончивших школу на "отлично". 7.4. ИТОГИ В седьмой теме были изучены: способы построения БД с помощью комбинированного типа запись; способы построения БД с использованием аппарата Delphi по поддержке баз данных; стандартные утилиты создания БД (BDE Administrator и Database desktop); некоторые стандартные операции при работе с БД. При построении демонстрационной программы были получены навыки работы с визуальными компонентами: невидимым элементом настройки БД – Table; невидимым элементом связки файла БД с видимыми элементами – DataSource; элементом отображения, набора и редактирования данных БД – DBGrid. 8. ВЫПОЛНЕНИЕ КУРСОВОГО ПРОЕКТА ПО ПРОГРАММИРОВАНИЮ В процессе выполнения курсового проекта студент должен составить алгоритм и написать программу, реализующую этот алгоритм. В качестве отчета по проделанной работе студент предъявляет: работающую программу; отчет. Отчет должен содержать следующие разделы: титульный лист; задание на курсовое проектирование; основной текст, содержащий: словесное описание алгоритма работы программы; структурную схему алгоритма программы; распечатку программы; для расчетных программ – расчет контрольного примера с помощью программы и выполненный вручную. Курсовая работа заканчивается защитой работы. 8.1. ВАРИАНТЫ КУРСОВЫХ РАБОТ 1. 2. 3. 4. 5. 6. 7. 8. 9. Создать программу расчета биоритмов человека на определенный срок; Программирование стрелочного таймера; Построение графика электрокардиограммы по заданным параметрам PQRST; Выдача гороскопа для введенной даты рождения; Построение психодиагностического теста для оценки типа темперамента; Нахождение корней степенного уравнения (показатель степени 4); Преобразование арифметических операций в веденной строке в польскую запись; Построение строчного калькулятора; Создать программу для статистических расчётов для фармакологии и токсикологии (использование методов альтернативного анализа); 74 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. Создание графического редактора; Создание программы выравнивания текста по ширине (справа и слева); Создание программы разбиения слов текста на слоги; Создать программу для расчёта статистических показателей в работе практического врача организатора здравоохранения; Создать программу для расчёта показателей, используемых в пульмонологии; Расчет системы линейных уравнений; Создать программу, реализующую простейшие операции (сложение, вычитание, умножение и деление) с комплексными числами; Создать программу для расчётов кардиогемодинамических показателей; Создать программу вычисления показателей работы почек; Создать программу расчёта средних показателей эксперимента (среднее арифметическое, среднее гармоническое, среднее кубическое и др.); Программирование картотеки бальных поликлинического учреждения; Перевод чисел из одной системы счисления в другую (двоичная, десятичная, шестнадцатиричная, римские числа); Размещение 8 ферзей на шахматном поле так, чтобы не один ферзь не оказался под боем; Написание шифровальщика и дешифровальщика текста; Создание календаря на введенный год; Создать программу для оценки степени соответствия эмпирических и теоретических данных по различным критериям; Создание архиватора и разархиватора файлов; Программа умножения матриц. Размерность матрицы задается; Написать программу создания правильного тетраэдра с возможностью вращения построенного тетраэдра; Построение самостоятельно пополняющегося словаря перевода с одного языка на другой. Задается текст, программа, просматривая текст, переводит все слова имеющиеся в словаре. При отсутствии слова в словаре выдается запрос о его переводе и введенное слово и перевод заносится в словарь. Задается граф – вершины и соединяющие их дуги. Требуется написать программу, которая позволит пройти через вершины, используя дуги, но проходить по дуге можно только один раз. ЗАКЛЮЧЕНИЕ Данное методическое пособие содержит 7 тем, каждая тема логически заканчивается рассмотрением практической задачи, использующей рассмотренные теоретические сведения. Несмотря на небольшой объём, данное пособие позволяет получить начальные сведения по построению программ. Главный замысел пособия состоит в том, чтобы предоставить студенту начальную информацию по программированию в Borland Delphi и быть основой для решения задач, выполняемых на старших курсах. СПИСОК РЕКОМЕНДУЕМОЙ ЛИТЕРАТУРЫ 1. Джефф Дантеманн, Джим Мишел, Дон Тейлор Программирование в среде Delphi. Киев: DiaSoft Ltd, 1995. 2. Культин Н. Delphi 4. Программирование на языке Object Pascal. СПб: 75 3. 4. 5. 6. 7. БХВ – Санкт-Петербург, 1999. Шумаков П.В. Фаронов В.В. Delphi 5. Руководство разработчика баз данных. М.: Нолидж, 2000. Архангельский А.Я. Программирование в Delphi 5. 2 издание. М.: ЗАО «Издательство БИНОМ», 2000. Том Сван. Delphi 4. Библия разработчика. Киев, М., СПб.: Диалектика, 1998. Никлаус Вирт. Алгоритмы и структуры данных. СПб.: Невский диалект, 2001 Единая система программной документации. Схемы алгоритмов, программ, данных и систем. Условные обозначения и правила выполнения. ГОСТ 19.701-90 (ИСО 5807-85). М.: Государственный комитет по управлению качеством продукции и стандартам, 1990. СОДЕРЖАНИЕ Введение ................................................................................................................... 1 1. Знакомство со средой программирования Borland Delphi ............................. 3 1.1. Теоретические сведения .................................................................................. 3 1.2. Создание программы «моя первая программа» ............................................ 9 1.3. Итоги................................................................................................................ 11 2. Условные операторы......................................................................................... 11 2.1. Теоретические сведения ................................................................................ 12 2.2. Создание программы «попадание точки в фигуру» ................................... 18 2.3. Индивидуальное задание ............................................................................... 21 2.4. Итоги................................................................................................................ 21 3. Операторы цикла ............................................................................................... 22 3.1. Теоретические сведения ................................................................................ 22 3.2. Создание программы «степенные ряды» ..................................................... 29 3.3. Индивидуальное задание .............................................................................. 32 3.4. Итоги................................................................................................................ 33 4. Тип данных массив ........................................................................................... 33 4.1. Теоретические сведения ................................................................................ 33 4.2. Создание программы «работа с массивом» ................................................. 37 4.3. Индивидуальное задание ............................................................................... 42 4.4. Итоги................................................................................................................ 42 5. Графические примитивы .................................................................................. 42 5.1. Теоретические сведения ................................................................................ 42 5.2. Создание программы «графические примитивы» ...................................... 48 5.3. Индивидуальное задание ............................................................................... 51 5.4. Итоги................................................................................................................ 51 6. Работа с текстовой информацией .................................................................... 51 6.1. Теоретические сведения ................................................................................ 51 6.2. Создание программы «редактор текста» ..................................................... 57 76 6.3. Индивидуальное задание ............................................................................... 61 6.4. Итоги................................................................................................................ 62 7. Работа с базами данных .................................................................................... 62 7.1. Теоретические сведения ................................................................................ 62 7.2. Создание программы «список студентов» .................................................. 70 7.3. Индивидуальное задание ............................................................................... 73 7.4. Итоги................................................................................................................ 74 8. Выполнение курсового проекта по программированию.............................. 74 8.1. Варианты курсовых работ ............................................................................. 74 Заключение ............................................................................................................ 75 Список рекомендуемой литературы.................................................................... 75 77