/
Автор: Сухарев М.
Теги: программирование программное обеспечение компьютерные технологии pascal
ISBN: 5-94387-299-X
Год: 2007
Текст
Сухарев М.
TURBO
PASCAL
7.0.
Теория
и
практика
проrраммирования
3-е
изд.,
СПб.: Наука и Техника, 2007.- 544 с., ил.
ISBN 5-94387-299-Х
Серия «Просто о сложном))
Книга представляет собой подробное учебное пособие по языку Turbo Pascal7.0
и общим принципам программирования. Изложение материала построено от
простого
к сложному. Используется большое количество примеров: от работы
с текстом и рисования простых графических объектов до спрайтовой анимации,
драйвера мыши и построения СУБД. Подробно разбирается код каждого примера.
Отдельно рассмотрены специальные nриемы nрограммирования, как, например,
рекурсия.
Кроме
того,
в
книге приведены все необходимые сведения,
позволяющие
принципиально понять, как создается и работает nрограмма, осуществляются
адресация
и
взаимодействие
с
памятью,
обрабатывается
информация,
функционирует комnьютер. То есть все то, без чего невозможно nолноценно изучить
nрограммирование. В последней главе описано, как nравильно и nрофессионально
оформлять программы, изложены nоложения Венгерской нотации.
Книга предназначена для школьников и студентов. Наnисана автором на основе
многолетнего опыта nреподавания программирования
в Санкт-Петербургском
Городском Дворце творчества юных. Особенно будет nолезна для всех, кто хочет
nолучить серьезные и глубокие знания. Адаnтирована для самостоятельного
изучения.
ISBN 5-94387-299-Х
Контактные телефоны издательства:
(812) 56770 25, (812) 56770 26, (044 ) 516 38 6 6
Официальный сайт: www.nit.com.ru
© М. Сухарев
© Наука и техника (оригинал-макет), 20 07
9 795943
872999
000 «Наука и Техника•
Лицензия Ng000350 от 23 декабря 1999 года.
198097, г. Санкт-Петербург, ул. Маршала Говорова, д. 29.
Подписано в печать 01.07.2006. Формат 70х1 00 1/16.
Бумага газетная. Печать офсетная. Объем 34 п. л.
Тираж 5000. Заказ 702
Отпечатано с готовых диапозитивов в ОАО •Техническая книга•
190005, Санкт-Петербург, Измайловекий пр., 29.
Содержание
ПРЕДИСЛОВИЕ
............................................................................... . .......
.
...
14
ГЛАВА 1 . ВВЕДЕНИЕ ..................................................................................... 20
1.1
ОСНОВЫ АВТОМАТИЗАЦИИ
.
.....
...
..
.
. .
..........
.
1.2 ПРОГРАММИРОВАНИЕ КАК ЧАСТ Ь ПРОЦЕССА
1.3 МОДЕЛИРОВАНИЕ .
..
1.4. СТРУКТ УРА
.
.....
.
....
.
....
. .
.................
.
....
ПЕРСОНАЛЬНОГО КОМПЬЮТЕРА
....
АВТОМАТИЗАЦИИ
.. .
..... . ... ....
..
.
.
.
......
. ..
...
.
.... .
......
.
.
.
...
.
. .. . . . . .
...
..
. . ....
.
..
.
..
.
.........
.
... . .. ...
.......
.
...... ...
. .
. .....
.
..
. ..
.
.. .
..
..
..
. ...
.......
.
....
..... .....
.....
...
.
.
.......
. . .
.
20
. 22
....................
1.4.1. Внутренние устройства. ..................................... ..... .. ....
.
.
...
23
. 25
...
. ...... 26
.
1.4.2. Внешние устройства . . .. ... . ... ... ....... ........... ... ....... .... ..... ... . 27
.
.
..
.
. .
.
.
.
.
1.4.3. Операционная система.... .... ...... ... ................... ...... ... ..... ..... 27
. .
.
.
.
. .
1.4.4. Механизм работы переанального компьютера
1.5.
. ..
. . .. ....
.
.
ПРОЦЕСС СОЗДАНИЯ ПРОГРАММЫ И ИНСТРУМЕНТЫ ПРОГРАММИРОВАНИЯ
.
. . .
... . .... . 29
.
.
.
••• . ••••••••••••••
30
Представление программы ....................................................... 30
Этапы разработки программы . .. .. .... ..... .. .... . .. ..
.
. .
.
.
. .
. .
.
.
.
. . .
.. ..... . 32
. .
.
Виды ошибок, возникающих в процессе разработки
программы ................................................................................ 32
Основные инструменты программирования ............................... 34
1.6.
.. . .
ВЫБОР ЯЗЫКА ПРОГРАММИРОВАНИЯ
.
.
.
.. . .
.
...
...
..
.
. ................
. ..
..
.
.
. ..... ..
.
..... ......
.....
34
По уровню предоставляемых возможностей (функций языка) ... 34
По функциональному назначению разрабатываемой
программы ....... . ....
. .
. . .
........ . . ................. . .. . .......... .. .. ...... . 35
.
..
.
.
По среде выполнения... ... .... . . .
.
.
Прочие показатели . .... .
.
. .
.
. . .
.
. ..
...
. .
....... . .... ....
.
.
.
...... . ..... ..
.
. .
. .
. . .
.
.. .
.
.
. .
.
. .... ..... .. ... ... . 37
. .
. .
.
. .
ГЛАВА 2. ИНТЕГРИРОВАННАЯ СРЕДА РАЗРАБОТЧИКА BORLAND PASCAL 7.0
2.1. ВВЕДЕНИЕ
. .
.... ........ .. ...... 36
.
. .
.
.•• . •.. . .•
38
............................................................................................................
38
2.2. УСТАНОВКА BORLAND PASCAL 7.0 ............................................................................ 40
2.2.1. Установка версии 7.0
. . .. .......
.
..
.
.
...
. ... ..... . .. .. ............. . ........ . 41
..
.
.
..
.
..
Пункты главного меню программы установки ............................. 42
2.2.2. Установка обновления Borland Pascal7.0 .... ..... ..... ... ... .. . .. .. 43
.
. .
.
.
.
.
.
3
Tur bo Pascal 7 . 0
2.3. ЗАПУСК ИНТЕГРИРОВАННОЙ СРЕДЫ .
.
............
2.4. ВСТРОЕННЫЙ РЕДАКТОР ИНТЕГРИРОВАННОЙ СРЕДЫ
2.5. ГЛАВНОЕ МЕНЮ
.
.
................. .........
2 . 5 . 1 Подм еню Fi le
..
2 . 5 . 2 . П одменю Edit
..
....... ..........
..
................
..
. . ...
.
.
. . . .
. .
.
............ ......
.
.
. ..
...
..
.
.
...
. ..
.. ...
.
2. 5 . 5 . Подменю Window .
2 . 5 . 6 . П одменю Help .
. .
.
.
..
..... . . .
...
..
..
..
.
. ..
.
. .
.. . ... ... .
... . ..
.....
. .
.. .
..
.
..
ГЛАВА 3. ОСНОВЫ ПРОГРАММИРОВАНИЯ
..
. . ....
..
. .
..
.
...
.
.
3.3. ПРОСТЕЙШАЯ ПРОГРАММА .
... .......
..
..........
.
..
.
.
..
....
.
.
..
.
.
.... . ..
.
..
.
. . .
. . ..
.
..
.
. .
. .
..
. . .
. . . . .. .
. ..
.. ..... .... .. ...
. . ..
.
. 45
............
.
. ... .. . .
.
.
.
....
. . ......
. .
.
.
. . .
.
...
. .. .
.
.
. . .
.... . . ...
. ..
..
. . . .
47
.
.
. ..
.
......
.
. ..
48
. . 51
.
. . .
.. 52
. .
..
53
. ..
54
.
.
. . ..
. . . . . 55
..
.
.
........
58
...... ............ .........
59
.........
...
.
... . . .
.. .
....
.
......
......... ..........
.. ...... ........ ...
П ишем текст п рограмм ы . .
....
.
. .. . ... .. ..
...............
. ......... .................
.
... .
. .......
...
..
.
.
............. .. .. ....
. ... .
.....
........
3.1. ОСНОВНЫЕ ЭЛЕМЕНТЫ ПРОГРАММЫ И АЛФАВИТ ЯЗЫКА .
3.2. СТРУКТУРА ПРОГРАММЫ
.
.
... . ..
....... . ..... . ..
. . . . . . . ..
.
.
..
2 . 5 . 4 . П одменю R u n
.
.
. .. .. . .. . ...
..............
.
. . .. .
...
2.53
. . П одменю Search . . . . . .. . . .
. .
.... .. ....
...................... ........
...
..
..
.. .
............
.
.. .
43
...... .. .............. ............ ... ... ..... .. . ....... ...
. . . . ..
..
..
.
.............................. ..... .
.. . .............. ....
.. ....
.
...
.
. . . .
... ......... . ..... ..
. .. . . .
.
.
... ...
.. .
..
62
63
. . 63
. . ..
Создаем, сохраняе м и заnускаем п рограмму с пом ощью
интегрированной среды . . . . .
. ... . . .. ... ....
. . .... . .
. 64
.
3.4. ПЕРЕМЕННЫЕ .
. ....
.
.. ........ .
..
.
...
.
....
.
.
.
...
. . .
.
. . . .
.
...
. .
. .
.
..... .......... ... ........ ..... .... .... .... .............. . ... .. .. ..... ....... . .. . .
67
3. 4 . 1 . П онятие переменной. Классификация данных, используемых
в п рограмм е
. .. . .
. . . .. . . . . . . . . . .
. . . . . .. .. . 67
. . . . .. . . . .
.
.
.
. .. . .
3. 4. 2 . Правила назначен и я имен .
..
3 . 4 . 3 . Ти п ы данных
..... . .
. . .. . . . .
.
.
..
.
..
.
. .
.
.
. .
..
. . .
. . . .. . . . . . .
...
. ..
..
..
. .
.
..
. ...
.....
.
.
. .
. . . . . . . .
.
. . . .
. .
. . . .
....
..
...
..
.
..... .
.. .. ..
.
.
. . .
.
. . ..
.. . . . .
.
.
. .
. . .. . . . .
...
.
3 . 4. 4. Оператор п рисваи вания. Совместимость ти пов данных
.
..
. . ..
. ..
.
.......
...
..
.
..
.....
.. ..
.
П ростейшее использование оператора п рисваивания .
Совмести мость типов .
.. . . . .
. . . .
..............
.
........
...
.
. . .
.. . .
. . . .
... . .
. . . . . . . . . ..
.
. . .
. . . . . .
Механизм работы оператора присваивания
. . .
.
... . . . .
. . . ...
.
. .
. . . ..
..... . . ..
...
.
.
.
. ..
. . .
68
. . 69
.....
Арифметически е и логически е выраже н и я в операторах
п р исваивания . . .
..
.
..
. . .
..
. . . ..
.
..
72
.72
. . .
. . ...
75
79
3.5. КОНСТАНТЫ...................................................................................... . . . ................. 81
Общие положения . .
..
...
.
.....
. .
.
. . ...
.
...
.. . .... . . ... .. ..
.
.
Методика использовани я констант . .
.
Безы мянные константы . . . . . .
.
.
.
.
..
. . . .
..
.
..
...
. .
...
. .
. ..
.
.. . .
.
...
.
.
. .
.
.. ....
.
...
.
...
. .. . .
.
. . .
.... . ...
....
..
.. .
.
.
. ... .
3.6 СИСТЕМЫ СЧИСЛЕНИЯ .
. ..
.
4
.
. .
... ..
.
.
. . .
.
. . ..
.
.
. . ..
. . . . . . . .
.
.
.
..
....
. . ... .
.
. . . .......... .. ............ . ................... . ... ... ......... ... .. . ... .... ..
Двоичная система счисления . . .
. .. 81
..
.. .
. .
.
.
.
. . 84
. . . .
........ ...
. . . ... . .
.
. . . . .
86
88
. 88
Содержание
Другие систем ы счисления .
. . . ..
. . . ......
.
..
.
.
..
.
.
. ...
...
.
.
.. .
. .....
.
. ... .. .
.
... ..
90
ГЛАВА 4. ВЫВОД ИНФОРМАЦИИ В ТЕКСТОВОМ РЕЖИМЕ ••••••••••••••••••••••••••••••••••• 91
4.1. ВЗАИМОДЕЙСТВИЕ С ПОЛЬЗОВАТЕЛЕМ ................................................................... 91
4.2.МЕХАНИЗМ ОТОБРАЖЕНИЯ ТЕКСТОВОЙ ИНФОРМАЦИИ НА ЭКРАНЕ МОНИТОРА .............. 92
4.3. ПРОЦЕДУРЫ ВЫВОДА ИНФОРМАЦИИ ....................................................................... 92
П роцедура Write
....
.
.
.. . ......... .... .......................... ...
.
.. ... . .
.
...
В ы вод нескольких значений одновременно
.
.
. ..
.
...
.....
. 92
... . . . . ... ..
Процедура Writeln . Вы вод с переходом на новую строку
.....
.. .. 94
. ....
.
........ . ...
96
4.4. УПРАВЛЕНИЕ РЕЖИМАМИ ВЫВОДА ИНФОРМАЦИИ...... ............. ..... ........ .. .......... . ... 97
.
4.4. 1. Очистка экрана. Процедура Clrscr
4.4. 2. Функция ReadKey .
...
.
......
.
. .
.
.
..
4. 4.3. П роцедуры работы с цветом
.
.
..
. .
..
.
.
.
. . . .
... .
. ..
.
.
. . ...
.
. .
.. ..
.
.
.
.
Цвет текста. Процедура Text Color . . .
.
.
.
.
.
.
.
..
..
.
.. . .
. ........
.. .
.........
.
.
.
. .. . . .
.
.
. .
.. .
.
..
.. . .. . .
. . . .
4 . 4. 5. Определение nоложения курсора.
Процедуры WhereX и WhereY. .. . .
.. .. . . . .
.
. .
.
.
..
.
.
.
.
..
..
.
..
.
.
......
.
..
. .. .
.
.
.
.
. ..
.....
. .
.. . . .
.. .
.
. .. .
..
.
.
...
.
..
.
..
.. .
. . . . .. .
.
.
.
. . .... .
.
.
. .
. 99
. ..
.
. .
99
1 01
1 02
... 1 0 3
.. . . .
.
.
. ..
.
.....
.. . .........
. . ..
98
. . 98
...
.
. .
... .
. ..
.
.. . . . . .
...
. ..
....
. .. . ... ...
.
.. .. . ...
ГЛАВА 5. ГРАФИКА В TURBO PASCAL. ВЫВОД ИНФОРМАЦИИ
В ГРАФИЧЕСКОМ РЕЖИМЕ . . . . . . . . . .
.
.
..
..
.. . .. . .. . .. .......
4.4.4 . Уnравление расположением информаци и .
П роцедура GoToXY
. . .
.. .
.
.
.. . . ..
.. .
.. . ..
..
Т екущий цвет фона. Процедура TextВ ackGround
Культура цветового оформления
.
.
... . . .
.
.
....
.
...... .. . ... . . . . . .. . . .. .. ....
..
. . . .. .
.
.
..
. .
..........................
1 05
1 09
5.1. ОСНОВЫ РАБОТЫ С ГРАФИЧЕСКИМИ РЕЖИМАМИ .....................................................109
5.2. ИНИЦИАЛИЗАЦИЯ И ЗАКРЫТИЕ ГРАФИЧЕСКОГО РЕЖИМА .......... .. ............................1 1 1
.
Модуль Graph и его подключение . . . . .
.
.
.. . . ..
.. .
.
.
.... . . ..
.. .
.
..
...
.
...... . ...
И н и циализаци я графического режима. П роцедура lnitGraph
.
.
Закрытие графического режима. Процедура C l oseGraph . .
. ... .
Возможн ые проблемы и их решен и я
.. . . . . ..
..
.
.
.
.. .
. .
.
.. . .
. .. . . . .
.
.
.
.
.
. .
111
1 12
. 1 15
.
.. 1 1 5
...
5.3. ПАРАМЕТРЫ ГРАФИЧЕСКИХ ОБЪЕКТОВ И ИХ ЗАДАНИЕ ...............................................116
5 . 3. 1 . Общие положения .
. .
1 16
.................. . .. . . . . . . . . . . .......... . . . ........ . . . ........... .. . ........ .......
1 17
.
5. 3 . 2 . Обводка
. .
...
.
. .. .
..
.
.
....
. . .
.
Цвет обводки . Процедура SetColor
Толщина и стиль линии обводки
.
.
. . .
.
. .
.. .
..... .
. . .
.
.
.
.
..
.. . .
. .... . ..
. . . .
. . .
.
.
П рограмм н о определяемые стили обводки
.
.
.
. .
... . . .
..
.
..
.... .. . ..
...... .
.
.
.
....
.
..
..
.. .
.
.
. . .
. . . ..
... .
. . ... ..
. .
. ....
. ...
.
. ..
..
. ...
.
. .
1 18
.... . ..
1 19
.
. .
.. .
.
. .
.
..
. .
..
1 21
5
Tur bo Pascal 7 . 0
5. 3 . 3 . Зал и вка.
.
..
............................................
Задание стиля и цвета зали вки
... . .
..........
. .. .
.
...
. ..
5 . 3 .4 . Цвет фона . . .
.
...
5.4. КООРДИНАТНАЯ ПЛОСКОСТЬ
.. . . . .
.
. .
.
..
...
.
...
..
.. .
...............
.........
.
.
. . .....
.
. .
..
..
1 22
.......
1 22
.......................
1 24
..
......
. .
.
.........
. .. . . .. . .. .
...
П рограммно определяемые стили зал и вки
.
.
.
.
..
.......
..
.. .
.
..
.
....
. . . 1 27
...
.
.
127
........... ................ .. ............................. .. ..... ........ . .. .....
5.5. ВЫВОД ТОЧЕК И ЛИНИЙ ........................................................................................ 128
5 . 5 . 1 . В ы вод точек
...
...
. .
.........
.
.
.................
5 . 5. 2 . Работа с текущим указателем
П оняти е текущего указателя
............
.
..
.........
.....
....
. .. .
.
.
....
.
.. .
..
.. .
...
.
.
П роцедуры смещения текущего указателя . ..
.
... .
.
.
...
.
......
.
..
.........
.. ... . ..
.......
. ..
. ....
. . .
......
.
..
..
1 28
...
1 29
.
.
.....
. . . . . . . . . . . ... 1 29
. .
.
.
..........
..
. . 1 29
........
Определение координат текущего указателя в графическом
режи ме. . .
. . . .. . . . . . .
. . .
.
. . .
...
.
........
..
.
.
.
.
..
.
..
5 . 5 . 3 . Процедуры рисования линий . .
.
П роцедура Line
.... ........
.
...
.
..................
.
....
5.6. УДАЛЕНИЕ ГРАФИЧЕСКОЙ ИНФОРМАЦИИ С ЭКРАНА
5.7. ВЫВОД МНОГОУГОЛЬНИКОВ
.. .
. ....
..
..................
...........
.
...
..
В ы вод окрашенных прямоугольников . .
.
5.8. ВЫВОД КРИВЫХ ЛИНИЙ .... .....
.
..
.. . .......... . ....
....
Рисование дуг .
.
.
..
....
. .. . .
.
. . .
Рисование сектора круга
. .
...
..
...
.
........
.....
..
.
..
.
.
.
...........
....
.
..
..
. .
..
.
.
....
........ . .
.
........
.
....
Рисование элли птического сектора . . .
.
.
.
.
..
.
.
..
....
.
.
5 . 9 . 2 . Достоинства и недостатки . . . . . . . . .
..
..
..
. ..
...........
..........
. . .. .
.
. ... .
. .
.
.
. .
..
.
.....
6
.
....
1 37
. 1 40
.
1 42
. 1 43
.
.......
1 44
. . . .....
1 45
..........
1 45
.....
..
..
..
. .. ..
.
..........
.
..
..
.....
..
.
. .
...
....
.
......
.
.
....
.....
....
. . .
.
......
...
..
...
. . .
.
.
.. .
....................
... .
.
..
...
.
.........
1 46
1 46
.. 1 47
.. ... 147
. . . ...
.........
. . .
.
....
. . ..
...
.
. . . 1 46
.....
. . .
.....
..
.
..
.
. . . 1 47
.
..
.. .
.
1 48
..
1 48
..........
1 49
...
Размер памяти, необходимый для хранения изображени я
Скорость вывода изображения
1 36
. .. . 1 39
. . .
..........
. . .. . .. ...
...
........
. .
1 34
. . 1 37
.. . . . ....
. . .. .
.
1 31
..
. ................. 144
..............
...
..
..
............ ......
5.9. МЕТОДЫ ПРЕДСТАВЛЕНИЯ ГРАФИЧЕСКОЙ ИНФОРМАЦИИ ................... ...
5 .9 . 1 . Два метода- растровый и векторный .
...
... . . . ....... ..
Совместное использование прямых и кри в ых линий . .
.
... . .
..........
........... . ..
....
.
. 1 31
....
......
.
.
....
..............
. . ...
Рисование незакрашенного элл ипса
. ..
. ..
.
.......................
..
..
.................
Рисование закрашенного эллипса
..
.
.. .
...........
. . . .. . .
... . . . .
.....
.
.
....
.
..
.
..
.... . ..
.....
. .... . ...
.... . ..
......
. ...
.. ..
...
...
............
.......
.
........
. .. ......................
...
Рисование окружностей .
..
. .
.
...
Рисование многоугольни ков .
. .
...
.....
..
.
Зал и вка замкнутых областей
.
.....
........
....................... ........ . ........ . .. .
.
..
. .................. ...... ............
В ы в од нескрашенных п рямоугольни ков .
Рисование параллелепипеда . .
..
. . ..
.
.
Содержание
Качество n редставления изображения
. .
............
Возможности масштабирования....
5.1 О. ВЫВОД ТЕКСТА В ГРАФИЧЕСКОМ РЕЖИМЕ
.. . . . . .
..
..
.....
........ .
... ..... .
.
.
. .
..
. ....
.. .. .. .
. . . . .
.
. .
.. ......
.
. ..
..
.
.
. . . . . . . . 1 49
...
..
.
1 49
· · · · · о · · · · · · · о
.
. . . ..
. ...... ...
150
... .
..
5 . 1 О. 1 . Параметры визуальн о го представления
текстовой и нформаци и . . . . .
...
.
..
50 1 00 2. Н астройка шрифта
.
.. .
..
.
.....
. . . . . . . . . . . . . . . .. . . . .
..
.
.
..
.
.
..
.
..
.
.
. .
о . . о . . о . . о о о .
.. о
о
.
Установка и настройка шрифта. Процедура SetТextStyle .
Цвет текста . .
..
.
..
. . .. ..
..
.
.
.
...
.
.. . ..
...
...
.
.. . .
Тонкая настрой ка размеров шрифта .
5 . 1 0 . 3 . Процедуры вывода текста . . .
.
.
......
.
...
.
. .
.
.
.....
..
.. ...
.......
50 1 0 .4. О пределение размеров символов . .
.
. ..
... .
..
. . ..
. .
.
.
.. .
.
. .
.. . .
.... .
о.
.
.
.
5. 1 1. ИЗМЕНЕНИЕ ХАРАКТЕРИСТИК ЦВЕТА ...
.
... . .
.
.... .
..
..
..
. .
.
.
..
..
.
...
.
.
. .
..........
. . .
.
. . .. .
. .
.
. .
.
.
..
. .
. .. ..
....
..
.
.
..
.
.
.
.. ...
. ..
.
... .
1 51
..
..
1 55
. .
1 55
.
. ..
.
...
..
.
.
.... .. ..
.. ..
.
.
.
.
..
.
. . .. .
.... .
.
. . . . ..
.... .. .
.
. .
.
.. . .. .
. .
.
.
...
....
1 56
.
. . . 1 57
.
.
..
. .
. . .. . . . .
. .
. .. . . . . . . . . . . . . .
.. . . ...
. . ..
..
.. .. .. . .
. .
.. .
........... ..... .... ..
.
.
. ..
. . . .. . . . . . .. . . . . . .
. . .
Изменение цветовой палитры .
.
.. .. .. . .. ..
. ....
Методы хранения информации о цвете .
Представление цвета в Turbo Pascal . .
.
.
. 151
..
. . .
. . .. . .. . .
5 . 1 00 5 . Формати рование текста. Про цедура SetТextJustify
50 1 00 6 . Установка не стандартных шрифтов
1 50
о • • •• • о •••• о •••••••••••••• • • •••• • •• • •
....
.
...
1 59
. ..
1 61
.......
.
.
.
. .
. . ..
. .
. .
.
162
1 62
.
. . 1 63
1 64
. . .. .
5. 12. СПРАЙТЫ .......................................................................................................... 165
5. 1 20 10 Создан ие и использование спрайтов . . . . . . . . . .
. ..
5. 1 2. 2 . Спрайты с прозрачным фоном . . . . . . . . . . . . .
..
.
..
..
..
5. 13. УСТАНОВКА НЕСТАНДАРТНЫХ ГРАФИЧЕСКИХ РЕЖИМОВ..
..
. ..
..
.
...
.
. . ..
..
. .
. . . . . . .
ГЛАВА 7. ВЕТВЛЕНИЕ И ЗАЦИКЛИВАНИЕ
7. 1. ОПЕРАТОРЫ ВЕТВЛЕНИЯ .
. ..
.
о
. . .
. .. . .
.
. .
.
...
.......... . .... . ........
. ...
..... ...............
.. .
..
.
. .. .
..
.
. .
. .
1 65
.... . . .
. . . . . 1 79
..... .
.
.. .. .......
. . 185
...
.
. 189
о
. ..
..
. . .......
. .. .
о
. ..
..
. 191
.
. . . .
о •••• • • • •• • • •••• • • • о о о ••• •
..... . .
о.
. .
.
. ...
. . .
.
. ..
..
........
. . .. . . ......... ... . ..
.
..
.
1 92
. . .
. ....
.. . .
.
. .
1 92
. .. . .
..
..
.. .....
.
.
.
.
..
Вв од с переходом на новую строку . . . .
.
.
.
о ••••••••••• о •••••••••••••••••••••••••••••••
Ввод оди ночного символа
Контрольные воnросы и ответы . . . . . .
.
.
.
.
. .
.
..
. ...... . ....... .. ....... ....
Одновременный в вод нескольких значений . .
......
.
. .
.
..
..
. .
. ..... . .....................
Ввод последовательности символов . . .
Обычный ввод с кл авиатуры . . . . .
. .
. . . . .. .
...... ....
5.14. МНОГОСТРАНИЧНОСТЬ ГРАФИЧЕСКИХ РЕЖИМОВ . ...... ..... .....
ГЛАВА б. ВВОД ДАННЫХ.
ЧТЕНИЕ ИНФОРМАЦИИ С КЛАВИАТУРЫ ..
. .
.
.
.
.. . . . . .
. . . . . . . . . 1 94
.
. ... .
... . . .
.
. . .... . . . .
......
......... .. .. .
.
. .
. . .
.
.
.
. о.
. .
о о
.
1 95
. 1 97
.
.
... . 200
....... . .
. . ..
.
1 92
.
.
.. ..
.
....
200
. ..
7
Turbo Pasca/7.0
7.1.1. Условный оператор lf
....
. .
..
....
.
...
. . .. . .
..
Простая форма оператора lf . ..
.
. ..
.
..
...
. . .
..
...
....
..
.
. . . .
...
. .. .
..
.
. .
.
7.1.2. Составной оператор
.. .
.. . . . ...
.
.
7.1.3. Условный оператор Case
.
.
.
..
.
..
..
.
Простая форма оператора Case
.
. . . . .
.
..
.
..
....
.. .
. .
. .
..
. . .
.
. .. .
.
.
. . . ..
...
.. .. ..
.
.
Расширенная форма оператора Case
7.2. ОПЕРАТОРЫ ЗАЦИКЛИВАНИЯ
..
... .
..
.
. ..
.
. . .
.
... . . 201
.
... .
.
..
. ..
.
.
. .. .
.
. ..
. . .
...
.
..
..
.. . .
. . ....
. .
.
..
. ...
...
..
.
... 203
. . .
. 207
. . . ...
.
.
....
. . ..
.
.
. . .
.. ...... . ......... . . ... ... .
. . . . .. .
.. ... .. . .
. . ..
. .
..
. .
Расширенная форма оператора lf . . .. . . ... . .
.
..... . ..... . 201
.. .
. ....... . .
..
.
. . .
. .. .
..
...
.
. .
209
209
. ... . . 213
.
.
••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
7.2.1. Оператор цикла For...
. ... .....
. ......... . . . .. . .... .
.
.
..
..
.
. .
.
.
... .
. . . . . ..
. .
Стандартная форма цикла For . ... . . . . . . . . . ....
..
.
.
Оператор For с обратным отсчетом
7.2.2. Условные операторы цикла
.
...
..
..
. . ..
.........
..
Условный оператор цикла While
..
Do
.. .
..
.
.
....
.
.
.
...
.. .
....
..
.
.
. . ...
. .. . . .
.
.
.
. .
. 215
. . . . .
215
.... .. . . . ... 218
..
.
.
.
. .. . . . . . .... . . . . .. . 219
....
.
.
. .
....
...
..
214
.
. . ..
..
.
.
..
.
. .
.. .. .. . . .. .
.
.
..
.....
.
.
.
. . .. .. . 219
. .
.
..
.
.
Использование условных операторов цикла
в моделировании ..
.
......
. ...
......
.. . ..
.
.
. . .
...... . .
.
Условный оператор цикла Repeat... Until
7.2.3. Вложеннасть операторов циклов
ГЛАВА 8. ДВИЖЕНИЕ ОБЪЕКТА ПО ЭКРАНУ .
.
8.1. ПРАВИЛЬНАЯ ОРГАНИЗАЦИЯ ПРОГРАММЫ
..
.
...
..
.
. ..
. .
. . ....
.
..
.......
. . ..
.. .
...
.
.
....................... ..
.
. .. .. . .. . ... . . 223
..
.
.
.
.
.
.
.
.... . .. ..... .. . 228
. .
. ..
..
. .
. ...
.
....
..
. .
. ...... ...
.
.
.
. . .
.. 229
........ ...........
237
8.2. ОРГАНИЗАЦИЯ ДВИЖЕНИЯ О&ЪЕКТА ПО ЭКРАНУ
. ........... ...................... ..... ....... .. .......
8.2.1. Перемещение объектов .
.
. .. .. ...
. . ..
..
.
.
.....
..... .. ..
..
8.2.2. Управление перемещением объектов ....
Функция KeyPressed . . ...
.
..
.
237
............ .......... . ... ... .... . ... . ...... ....... .........
. . .
....
Управление объектами ... ..
.
.
... .
..
....
.
. . . . ..
.....
.
.
...
..
..
. .
..
.
.
.
... .. . . . .. 242
...
..... . . .
.... ... . ......
.
.
. .
.. . .
.. . . .
. .
.
.
.
. . . . . . .. . .
. ..
. . .... . .. . . ....
.
.
242
. . .
.
..
...
.
.
.
.. . . 248
.
.
.
... .. . 248
.
.
. .. .. ... 250
...
.
.
.
Использование клавиш, не имеющих
визуального представления . . . . .
..
..
8.2.3. Определение кодов клавиш.. . .
.
.
. . .
.
.....
...
. . . . .
.
.
. .
.
...
.. . .. .... . . . ... ... .. 255
. . . .
.
..
. .
. ... .
.
.
.
. .. .
.
.
. . . .
..
.
8.2.4. Одновременное движение нескольких объектов . ... .
.
.
.
. . .
...
.
.
.... .. .. 260
. .
.
.. ... .. . . 260
.
.
.
.
8.2.5. Определение "столкновения» движущихся объектов .. . . .. .. ... 263
..
8.3. ПОНЯТИЕ СТРУКТУРНОГО ПРОГРАММИРОВАНИЯ
ГЛАВА 9. ИСПОЛЬЗОВАНИЕ ПОДПРОГРАММ
9.1. ПРОЦЕДУРЫ
8
...
....
.
.
............
.....
.
..
.
.
.........
.
.... .
.
.
.
. .
.
..... ........
. 266
. .
.. .........
269
.....
......................
.
.
272
........................................................................................................
Содержание
9.2. ФУНКЦИИ
••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
9.3. ПРОЦЕДУРЫ И ФУНКЦИИ С ПАРАМЕТРАМИ
•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
9.4. ПРОЦЕДУРЫ И ФУНКЦИИ С ПАРАМЕТРАМИ-ПЕРЕМЕННЫМИ
КОНТРОЛЬНЫЕ ВОПРОСЫ И ОТВЕТЫ
280
•••••••••••••••••••••••••••••••
287
••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
288
292
•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
ГЛАВА 1 О. СЛОЖНЫЕ ТИПЫ ДАННЫХ
1 О. 1. МАССИВЫ
278
•••••••••••••••••••••••••••••••••••••••
9.5. ПОНЯТИЕ ПРОЦЕДУРНОГО (МОДУЛЬНОГО) ПРОГРАММИРОВАНИЯ
9.6. БИБЛИОТЕКИ ПРОЦЕДУР И ФУНКЦИЙ
275
.................
. .
..
.
......
.....
.
... .......................
294
•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••• .••••••••••••••••••••••• • ••••••••••••• . ••
1 О.1.1. Описание массивов .. .
...
. ..
.
......
.
...
.
.....
10.1.2. Использование массивов .. ..
.
. .
... . ..
.
. . ..
.
..
. .
. ..
.
....
.
.
..
.
.....
.
.
.....
.
. ..
. . . ......
...
....
.
... .
..
...
.
..
.
.......
...
.
...
.
.
.
. . . .. .
..
...
. .. . . .
. .. .
. .
. . .
.
. .
...
. . .
..
. .. . . . . . . . .
. ..
. . ..
. ... ... .
. . .
.....................
Упорядочивание массивов. Метод «nузырька»
10.1.4. Многомерные массивы
..
. .. . .
. . . . .
10.1.3. Стандартные операции с массивами .
Поиск элемента массива по критерию
. . ..
.
.
.
. . . . . . .. .
.. .
.
..
...
298
...
301
....
.
297
..
.
. .
....
295
.
.. . .
. 301
. ..
304
.
308
..
1 0.1.5. Особенности работы
с переменными типа String
....
. .
.
Операции с длиной строк .. ... .
..
Конкатенация ..
..
.....
Сравнение строк
..
............
. . . .
...
.
.
...
.
... .
.
.
..
... . . . . .. ..
... ..
........ . ... .
..
. . .
.
. ...
.
...
.
....
. . .. .
..
.
.
. . . .
.
.
..
. . . . .... .
.... ..
.
. ...
. ... . . .... 314
...
...
....
...
.
......
.... . .
...
.
.
.. . .
. .
..
...
.
..
.
. .
.
. . ....
..
.
.....
.
.
....
..
.....
... . .. . . . . .
.
. 314
......
.. ..
.
.. .
318
320
Вывод числовых данных в графическом режиме.
Преобразование чисел в строку . . . .
..
.
.
.
.......
.
...
....
.
... . . .
.....
Ввод текстовой информации в графическом режиме ..
Синтаксический разбор строк .
..
.......
. . ..
..
. .
..........
.. .........
10.2. ЗАПИСИ
..
.
.. . ..
. . .
.......
. . . . . . ..
.
Удаление, вставка и выделение подстрок из строки
Выделение числовой информации из строки
....
. .
. .
.
.........
. . . .
..
.....
.
.
324
327
...
. 328
........
. 330
..
. . .
321
.
.
.
••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
1 0.2.1. Описание записей . ......
.
..
10.2.2. Использование записей .
.
. . . ....
. . . ...
. . ..... . ... .
.
. .
.
.
. .
.. . . ..
.
. ..
..
.
...
. .. .
.
..
...
.. . . ..
.
..
.
.
. . . .. .
. . . .
Работа с полями экземпляров записей . .. .. .. .. .
. .
Работа с записями в целом
10.2.3. Массивы записей ....
...
...........
.
. . . .......
.
.
.
..
.........
.
.
.
.
..
..
.
.
.
..
.
..
.. ..
.
.. . ..
...
.
.
.
.
....
.
..
.
. . .
... . .
. . 335
.
. . 336
. .
.
.. .
....
. . .
.
...
. ...
....
... . . .
... .. . .
.. .. . . . ..
.
.
...................
.. . . .. . .
...
10.3. СОЭдАНИЕ НОВЫХ ТИПОВ дАННЫХ.
РАЗДЕЛ ОПИСАНИЯ ТИПОВ ТУРЕ .. . ..
.
.
. . .
.
.... . .
.
... . .
332
336
........
. 338
...
.
....
. 339
... .. .. ..... ....... .. .. З41
.
.
.
.
.
.
9
Turbo Pascal 7 . 0
10.4. ИСПОЛЬЗОВАНИЕ СЛОЖНЫХ ТИПОВ ДАННЫХ
ДЛЯ ОБМЕНА ИНФОРМАЦИЕЙ
.
З44
................. .............. ........... ...... .... . ......... .. ......
1 0 . 4 . 1 . Рисование многоугольников
.....
...
....
.... ...
. .
...
1 0 . 4 . 2 . Рисование закрашенного многоугольн и ка .
. . . . . . . . . . . . . . . . . . 344
.
...
.
.
.
.
.
.
.
.
.
. ...... ..... ..
.. . .
.
. .
..
346
. .
1 0 . 4 . 3 . Процедура GetArcCoords . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347
10.5. ПЕРЕМЕННЫЕ-УКАЗАТЕЛИ .
........ ....
..
...
. ......
...
.......
.. .... ....... ...
..
348
.. . .. ... ...... .... .. ..... .....
1 0 . 5 . 1 . О писание и инициализация
ти пизированных указателей . . . . . . . . . . . . . . . . . . . . . . . . .
..
О свобождение памяти
. . ... . .
. .
.
.
.... .
.
.
... . . .. ..
.
..
.
.
.
. ..
..
. ..
... ..
. .
. . . . . 349
...
.
..
..
..
. .
1 0 . 5 . 2 . Использование ти пизированных указателей . . . . . . . .
.
..
. . ..
.
.
.
. . . . . . . . . 350
. .
.
Операции с указателями как с переменны м и . . . . . . . . . . . . . . . . . .
.
..
..
..
Опе раци и с переменными, на которые ссылаются указатели
1 0.6. ИНТЕРВАЛЬНЫЕ ТИПЫ ДАННЫХ
..
.. .......
..
.
.
.
.
..
..
.
. .
.
.
.
35 1
. .
. ..
1 0 . 5 . 3 . Масси вы указателей . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
..
.
. . . . . . . . . . . . . . . . . . 350
.
..
354
356
357
...... ... ....................... ..... .... . . ...... .... .. ... .....
10.7. ПЕРЕЧИСЛИМЫЕ ТИПЫ ДАННЫХ ..........
. ... ............................. ......... .
359
.. ........... ...... ...
10.8. МНОЖЕСТВА ......................................................................................................360
1 0 . 8 . 1 . Описание и использование множеств .
.
...
.
.. . . .
... ..
.
... . .
. . . . . . . . . . . . . 360
.
1 0 . 8 . 2 . О пераци и над множествами . . . . . . . . . . . . . . . . . . . . . . . . . .
.
КОНТРОЛЬНЫЕ ВОПРОСЫ И ОТВЕТЫ
..
...... . ..... . ..
1 1. 1. СТРУКТУРАДИСКОВЫХ НАКОПИТЕЛЕЙ .......
. ....
..
..
..
.
. .
.
. .
....
.
.........
.. ............. ............. .
...
...
. .
..
.
. .
. . .
. .....
..
. ... .
1 1 . 2 . 3 . И спользован и е неполн ых и м ен файлов
...
.....
. . . . . . . . . 363
.
.
..
.. . . . .
.. .. ... .
.
...
...
. .
.
. . .. .. . . ..
.
....
..
368
. ............ ..
370
. . . . . . . . . . . . . . . . . 370
.
.
...
368
. .
. .
.
. .
.
.
.
.
. .
. ...
. . . . . . . 372
... . . .
. . . . . 372
.
.
.
.
..
.
.
.... ........ . ..
. .
..
.
1 1 . 5. 1 . Оп и сание файловой переменной . . . . . . . . . .
.
..
. ....
.. .... .
...
.
. .
. .
. . . . . . .
.
.
. .
..
.
.
. ... .... ..... .... ....
. .. .. .
1 1. 5 . 2 . Сопоставл е н и е файловой переменной
файлу на диске . .
.. . ... .
.. .... . .
. . . . . . . . . .
373
. 374
... ......... ... . . . ... .. . .......... ....
..... ............
.
365
............ ................
.
.
........................ .....
. .
..........
..... ............ ........ ... .. ....... .......... .......... . .... ... .....
1 1.5. МЕХАНИЗМ РАБОТЫ С ФАЙЛАМИ .......
.
.
..
......... .
.
10
. . .
..... ..... ...................
1 1 . 2. 2 . Использование расши рений . . . . . . . .
1 1.3. ПОНЯТИЕ ФАЙЛА В TURBO PASCAL
.
.. .. .......................... .
1 1 . 2. 1 . О сновы именования файлов
1 1.4. КЛАССИФИКАЦИЯ ФАЙЛОВ
.
... ...... .... ......... . ...... ....... ... .............. ... .. .. ... . ... .. . .. . . ...
ГЛАВА 1 1 . ИСПОЛЬЗОВАНИЕ ФАЙЛОВ
1 1.2. ИМЕНОВАНИЕ ФАЙЛОВ
.
.
.
. . . . . . . .
. . .. .
...
. . . ..
. .
. . . . . .
.
.
. .
. . .
...
З75
. .
375
. .
376
Содержание
1 1 . 5 . 3 . Открытие файла . .
..
...
.
1 1 . 5 . 4 . Чте н и е или запи сь файла .
1 1 . 5 . 5 . Закрытие файла . . . .
..
..
.......
.. .
. ..
.......
...
. ...... .
... . .
.......
. .
.....
. ..
......
.
. ...
. ...
.
... .
.. .
... .
.. ..
.. .
... ..
.
..
. ...
.
.
.
... .
.....
. .
..
..
..
. .
.. ...
.
. . ... . .....
.
.. .
.
. . .......... . .
. . . . 377
.
.
.
.
. ..
.
.
.
.. . .. . .
378
. 379
1 1.6. ЧТЕНИЕ И ЗАПИСЬ ФАЙЛОВ РАЗНОГО ТИПА ............................................................ 380
1 1 . 6 . 1 . Текстовые файлы . . .
.. . ...
.. . . .. .
..
..
.
.
....
.. . . .
.
1 1 . 6 . 2 . Двоичные типизированные файл ы . .
.
. .
...
1 1 . 6 . 3 . Двоичные нети п изи рованные файлы
.. . .
. .
..
.
.. .
. . .. .
..
. ...
.. ... ..
. ....
. ..
. . .. . . .
...
.
...
.
.
..
. .. .
. .. .
..
.
.
.
. ..
380
.. . .
382
...... . . . . .
385
. . ..
..
.
.
. .. . . .
.
.
.
.
.
.
.
1 1.7. ВСПОМОГАТЕЛЬНЫЕ ОПЕРАЦИИ С ФАЙЛАМИ.. .. . ... .... .. . . ... .. . .. . . .. . .. . .. .. .. 388
.
.
.
1 1 .7 . 1 . Оп р еделение размера файла . . .
.
.
.
.
.
. ......
1 1. 7 . 2. И з менени е текущего элемента . . .
. . .
.
.
.
.
....
.. .
.
.. .
....
..
..
.
..
. ...... ..
.
.
.. . .. .
. .
... .
.
.
..
.
..
.
.
. .. . .
..
. . ..
.
.
. ..
.
.. .
. .
. .. .
.
388
.
. . .. 393
.
. .
1 1.8. ДОБАВЛЕНИЕ ИНФОРМАЦИИ В ФАЙЛЫ .. . .... ............ . . .... . . ..... .. . .... . . . .. .. 394
.
.
.
.
.
.
.
.
.
.
..
1 1. 8 . 1 . Добавление и н формации в текстовые файл ы
1 1 . 8 . 2 . Добавление и н формаци и в двоич н ы е файлы
.. .
..
.
.
..
.
.
.
..
.
..
. . . . . . ..
. . .. . . .
.
. . .
.
.
394
. . .. .
. . . . 394
... . . .. . .
.
.
.
1 1.9. РАБОТА С ФАЙЛОВОЙ СИСТЕМОЙ .. . .. .. . . . ..... . .. . .. ........ ......... .. ... ..... .. . . ... 396
.
1 1 . 9 . 1 . Удал е н и е файлов
...
.
.
..
.
.
.
.
......
..
.
.
.
.
. .... .. . .....
.
..
.
..
1 1. 9. 2. П е ре и менование и перенос файлов
1 1. 9 . 3 . Копи ровани е файлов . . .
. ..
... . .. .
1 1. 9. 5 . П о и ск файлов . . . . . . . .
.
.
.
. ..
.
..
..
. .
.
.
.
.
.. .
..
....
...
.
.
.
. .
..
.
...
.
.
. . ... .
. ... . .
.
....... .
.... ...
...
.
.
.
.
.
.....................
.
.. .
.
.
.. ..
. .
.
. . .... . . . . . .
.
.
.
.
.
. . ..
.............
.
..
.
.
. .
. . .
1 2 . 1 . 1 . Динамические массивы .
.
.
.. .
.
.
.
. .. . .
.
..
..
..
.
.. . .
..
.
. ..
.
..
.
.
.
..
. .
1 2. 1 . 2 . Списки
. .
..
....
.
.
.
. .
..
.
.
.
.
.
.
. 396
..
Процесс создания списка .
.
.....
..
. ..
.. .
.. . .
.... . .
..
. .
......
.
.
..
Создание м одуля для работы со списком
.
.
.
. ..
. .
. . 399
. .
.
..
. . 400
.
.
.. .
.
..
.
.
.
..........
.
.. 404
. .... ... . .404
...
.
.
..
...
.
.
.
.
.. . . . .
.
.
... . .. . .
. . ....
....
. ....... .
...
.....
. . .. . . ..
397
.. .
. .
..
.
.
.
.
. .. .
..
.
.
.
. . . . .
.
.
.
.
.
.
.
.
.
.
. .
..
.
..... . . ...
12.2. ОСНОВЫ ОРГАНИЗАЦИИ СИСТЕМ УПРАВЛЕНИЯ &АЗАМИ ДАННЫХ ....... .... .. ...
.
.. . . . . .
. . .. . . .
. . . . ...
.
.
406
. . . 406
.. . . .
. .
.
.. . .............. . . .. ...... . .. . . . . . ...... .......... . . . .... ... . ....... .... .... . .. ... .
Понятие списка и его организация
396
.. . .
.... . . ... . . .
.
. . . .
. .
.
.
....... . .. .. . . 402
. . ... .
.
.. .
.
.. .
....
Массивы динамически распределяемых элементов
Динамически распределяемые масси вы ..
.
.. ..
. . .. . . .
. .
.. ..
. .
.
.
. . ... .. .
12. 1. ДИНАМИЧЕСКИЕ СТРУКТУРЫ ДАННЫХ . .. . . .. ... ..... .... .. .. .. . . .. ... . .. .
..
...
.
. . .. . . .
..
.
.
..
. ......... ...
.....
.
. ..
.
.. ....
. . . . . . . . . . .. . .
.
.
..
ГЛАВА 1 2. ОРГАНИЗАЦИЯ ХРАНЕНИЯ ИНФОРМАЦИИ.
ОСНОВЫ СУБД .. . . ..
.
..
.
.... . . . . ... .
. ..
..
. .
.. . ... . .
. .. . ..
КОНТРОЛЬНЫЕ ВОПРОСЫ И ОТВЕТЫ ... . . . .....
..
.
...
. . .
. ... ...
1 1. 9 4
. . Работа с каталогами
.
406
409
409
41 1
415
........ 421
...
11
Turbo Pascal 7 . 0
1 2 . 2 . 1 . Реализация п ростейшей СУ БД .
.......
. . . .
.
..
.
1 2 . 2 . 2 . Основы организаци и баз данных . . . . . . . . . . .
.
.
.
...
.
..
. .
....
..
.
. ...
.. .
. . ...
..
Отсутстви е избыточности как основное требовани е
Связи между табл ицами . . . . . . . . . . .
..
Прочее . . .. . . . . . . .
.
.
.
.
.
... .
.
.
... . . . ....
.
.
..
..
..
. . ..
.
.
...
. ..
. . . . . . . ..
.
..
.
. ... ..
.
. . 42 1
. .... .
.
. . 425
...
. . ....
.. .... . .. . .. . . .. . . .
..
. .. . .
....
..
..
. .
..
.
.
..
.
..
.
. .
.
425
428
. .
. . . . . . . . . . . . . . . . . . . . 429
....
.
.
.
.
. .....
КОНТРОЛЬНЫЕ ВОПРОСЫ И ОТВЕТЫ .
.... . ........ ... ...... .. ........ .. ..... .....
.
.
.
..
..
.
430
. ..... ......... ... ........
ГЛАВА 1 3. РЕКУРСИS1.................................................................................. 431
13. 1. ОСНОВНЫЕ ПОНЯТИЯ ... . . . .
.
.
..
..
... ..... . ... .... .... .. .
...
..
1 3 . 1 . 1 . Конечная рекурсия .
.
. . ..
.
..
..
.. . . . . .
.
.
.
.
. .
.
.
...
....
.. ... .
. ..
.
..
.
...
13.2. ИСПОЛЬЗОВАНИЕ РЕКУРСИИ ..
.
КОНТРОЛЬНЫЕ ВОПРОСЫ И ОТВЕТЫ
.... .... ...
...... .
.
...
.
.......
.
.
..
.
.
.
.
.. . ...
1 3 . 1. 2 . Бесконечная рекурсия . Понятие стека . . .
.
.. . .... . . ... .
...
.
.
...
.. . ...
. .
.......... .
.
..
..
....
....
... . ...
...
..
.
..
.
.
..
.
......... .. .. .... .
.
...
.....
.
.
.
..
.
..
....
.
...
433
.
.... 436
. ..
..
. . ..... . ..... .....
.. .
. . . . . 435
. . . .....
.. . .... . ..... .... . . .. . .... ..
.....
431
...
.
.....443
.. . ..
ГЛАВА 1 4. ИСПОЛЬЗОВАНИЕ ВСТРОЕННОГО АССЕМБЛЕРА .............................. 444
14. 1. ИСПОЛЬЗОВАНИЕ КОМАНД АССЕМБЛЕРА
В ПРОГРАММЕ . . ... . ...... .
.. . .
..
.
14.2. РЕГИСТРЫ ПРОЦЕССОРд
...
.
..
.
..
.
. ......
....
.
.
...
.. .
...... ....
...
. .. . . . .. .
...
.
.
.
.
.
..
.
..
. .
.....
..
.. .. . .. . ..... ....
... .
.
.
.
.
..
.
14.3. ОПЕРАЦИИ ПЕРЕМЕЩЕНИЯ ИНФОРМАЦИИ . . . . ... .... .. ......
.. .
14.4. ИСПОЛЬЗОВАНИЕ КОМАНД ПРОЦЕССОРд . .
.
.
..
.
..
...
.
.
.
.
.
... .. ..
.....
..
.
.
.
...
.
. .. .
. ... . . 445
....
. .. ..
...
.
.
.
.
.. . . .. . . ... ....
.
.
.
.
.
..
.
.. .... .. ..446
... .
.
.
.
..
.
. ..447
...
..
. ... . ... .... .. . .. .... .... ..448
.....
.
.
.
.
.
..
.
..
.
14.5. ВЫЗОВ СИСТЕМНЫХ ФУНКЦИЙ MS-DOS. ИСПОЛЬЗОВАНИЕ ПРЕРЫВАНИЙ . .. . ... ..
.
..
.
..449
...
14.6. ИСПОЛЬЗОВАНИЕ МЫШИ В ПРОГРАММАХ ТURВО PASCAL .. .. . . .... .. . .... . .. .... . 4 5 1
.
КОНТРОЛЬНЫЕ ВОПРОСЫ И ОТВЕТЫ .. .. . ..
..
.
.
..
.. . .. ......
....
..
.
.
..
..
. ... . . .
.. ...
..
..
.
.
.
..
.
.
.
.
.
. . . ..
...
..
.
..
.
.
..
....
.
.....456
...
ГЛАВА 1 5. ОБЪЕКТНО-ОРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ ................... 458
15. 1. ИНКАПСУЛЯЦИЯ .................................................................................................458
1 5 . 1 . 1 . Понятия и н капсуляции и объекта . . .
.
1 5 . 1. 2 . Динам ические объекты .
Конструктор и деструктор .
.....
... ..
..
.
...
....
..
.. . . .
...
..
. . .
.. .
.
.
.
..
.
...... .. .
...
.
.
. ..
. .....
.
.. ........ . .. . .. . ..
....
.
..
1 5 . 2. 1 . Понятие наследования . . .
.
12
.
.. .
..
..
..
..
. . .. ..... .
.
. .
.
..
.
...
. ..
.
...
.. . .
....
... .
.....
.
.
..
.. .
.
...
.
. .
..
. . ..
.....
.. .
.
....
. ..
..
.. .
458
463
467
....... .. . .. . .. .... ..47 1
....
. .. ..
.
....
. . . . .. . . . .
1 5 . 1 . 3 . Области види мости свойств и методов . . . . . .
15.2. НАСЛЕДОВАНИЕ . .
..
.
..
. ......
.
..
..
.
.
. . . .. ....
..
..
.
.
.
....
47 1
Содержание
15.2.2. Переоnределение методов .. .... .
..
.
15.2.3. Иерархия объектов . ... .. ... ...
.
.
.
.
.
. . .
...
....
.
. . ..
. . ..
.. .. .. . .
.
.
. .
.
.
. .
.
..
.
.
.
.
.
. . .
... . .
474
. .
484
.
. .
.... .. . .. 485
..
. .
.
491
.................................................................................................
КОНТРОЛЬНЫЕ ВОПРОСЫ И ОТВЕТЫ
. .. . ..... . . ....... ... ... . .
... . .... . . ... .......... ..... ........ .. ... .. . ..... ..... ...... ...... . ........ . .
ГЛАВА 16. КАЧЕСТВО ПРОГРАММНЫХ ПРОДУКТОВ
.
.....
•
.
.
. . . . . ..
15.4. ИСПОЛЬЗОВАНИЕ ООП ДЛЯ ПРОЕКТИРОВАНИЯ СЛОЖНЫХ СИСТЕМ
16.1
... .
.. ....... .... . .. .. ... ...... .
15. 2.4. Исnользование nереоnределенных методов . ...
15.3. ПОЛИМОРФИЗМ
.. .
ОФОРМЛЕНИЕ ПРОГРАММНЫХ ПРОДУКТОВ
..........
.
....
....... ............
16.1.1. Оформление исходного текста . ..... . . . .
.
.
.
.
.
.. . .
..
..
501
....
504
.....................
505
... .
..
..............
. . .
.....
.. . .
.
494
. ........ 506
.
16.1.2. Документирование.
Исnользование блок-схем . ...
.
. .
. .. .... . .. .. ..
. . ..
.
..
.
. .
.
.
. . .
...... .
.
.. .
. .....
.
. .
517
16.1.3. Пример оформления исходного текста
nрограммы и ее документирования ... .
.
16.2. ФУНКЦИОНАЛЬНОСТЬ
... . ...... . ................. ......... ..
16.2.1. Тестирование nрограммы .
....
..
.
. . . . .
. . ... ....... ..
.
. .
.
.
. . . .
....... . .... . .... .... . . ....... . ....
. ....
.
. .
...
.
....
. . .
. ..
.. .. .... .
.
.
. .
.
... .... 520
.
.......... . ..
. . . .
. .....
.
. .
527
527
Обработка ошибок. Исnользование директив комnилятора .... 528
.
Ошибки ввода информации .
.. ..
. .
.
. .. ...
.
.. .
. ..
..
.
. . . .
. . ... .
.
.
.
. . . .
.. .
.
. . . . . .
. 531
.
Ошибки графической системы ... . , ........................................... 535
.
16.2.2. Отладка. Исnользование встроенного отладчика . ... ... .... . . 536
.
Основы отладки nрограмм
. . . . . . . . . .
Установка точки останова .......
.
. . .
.
. . . . . . . . . . . . . . . . . . . . . . . . .
.
.
.
.
. .
.
. . . . . . . . . . . . . . . . . .
536
. . .. . ....... .. ...... . ... . . . 537
..
. .
..
..
.
. .
.
Пашагавое выnолнение nрограммы . . .. . .. . .......
.
Просмотр значений переменных ... .
.
.
. .
. . .
.
. .
... .
..
.
.
. ..
.
. . ..
. .
..
. . .
.
..
.
. .
. ...
.
..
. . ...
.
.
. . ..
. .
. .
..
.
.
...
.
.
...
.. . .. .
.
. .
. ...... .
. .. . . . . .
Изменение значений переменных .... . .. ..... .... . .
Досрочное прекращение программы . .
. .
.
. . .
..... . .
539
.. 540
. ... . .. 541
..
. . ..
.
.
. ...... 542
.
16.2.3. Доступ к большим объемам nамяти.
Использование защищенного режима процессара ... ...
.
. . .
.
. . . . . .
. 542
13
Turbo
Pascal 7.0
теория и практика nрограммирования
------Основы п рограмм и ро в а н и я
Предисловие
Компьютерная техн ика занимает все большее место в нашей жизни, помо
делать многие вещи быстрее, удобнее и качественнее. Однако компыо
тер - это всего лишь электронное устройство, которое просто выполняет
элеме нт ар ные команды, записанные на понятном ему языке. И для того,
чтобы он обладал теми возможностями (функциональностью) , к которым
мы так привыкли за последние несколько лет, нужны люди, которые бы
их реализовывали и поддерживали. Огромное количество и разнообразие
;iадач, решаемых компьютером, породило п оявле ни е повой профессии
программист (англ. Programmer - создающий программу). Соответственно,
все остальные люди по отнопrению к компьютерной технике называются
пользователями (англ. User - использующий) .
гая
-
Программирование является относительно повой областью деятельности,
всего несколько десятилетий. Н е которо е время после появлс
IIИЯ первых компьютеров к программистам предъявлялись весьма невы
сокие требования, и их работа сводилась к переводу алгоритмов, которые
разрабатывали технологи - специалисты в какой-либо области
в ма
шинные коды.
се возраст
--
-
Такого рода деятельность сейчас назьшастся оператор ЭВМ и подразуме
вает под собой всего лишь наличие элементарных навыков работы с ком
пыотером, что является заслугой программистов, создавших инструменты
(программы) , позволяющие организовать удобную работу пользователя и
не требующие его глубокой подготовки.
Со вре менны ми программистами решаются намного более сложные зада
чи. Например, разработка и реализация алгоритма решения поставленной
задачи лежит на плечах программиста. Это вызвано как усложнением са14
Предисловие
мого процесса программирован:ия, так и повышением общего уровня боль
шинства программистов в силу их специальной подготовки.
Одной из характерных черт программирования является то, что это при
кладпая область деятельности, то есть программирование имеет смысл
только в контексте какой-либо отрасли хозяйства - экономики, машино
строения, и так да.;1ее (в том числе и развлекательной, если говорить об иг
ровых программах). А с учетом необходимости программиста разрабаты
вать алгоритм, естественным образом связанный с данной отраслью,
появляется существеннос требование к специалистам этой профессии возможность быстрой адаптации в незнакомой области знаний и умение
общаться с заказчиком программнога продукта. При этом заказчик про
граммы, скорее всего, не сможет разговаривать с программистом на его
языке, да и не должен этого делать. Взаимопонимание должно быть забо
той программиста, иначе ему наверняка придется потратить большое коли
чество времени на выполнение никому н е нужно й раб от ы .
Круг отраслей, в которых используется программирование, постоянно рас
тет, вследствие чего появляется все больше инструментов программирова
ния, большинство из которых являются специализированными, то есть
предназиаченными для решения узких задач. Сама компыотериая техника
находится в со ст оян ии постоянного развития, поэто му в проrраммирова
нии все больше появляется собственных технологий, которые сразу же вхо
дят в повседневную жизнь, предоставляя програt\1Мистам новые возможности.
Таюп\I образом, программист должен постоянно находиться в процессе са
мообучения, как в области информационных технологий, чтобы идти в ногу
со временем и уметь использовать передовые инструменты программиро
вания, так и в области фундаментальных наук - физики, математики, эко
номики и так далее, чтобы понимать ставящиеся перед ним задачи и иметь
возможность их решать, причем быстро и эффективно.
Заметим, что программировапие сложно само по себе, и для его изучения
необходимо обладать некоторыми определенными свойствами мышления.
Не вдаваясь в подробности, скажем, что программист должен обладать ака
демическим складом ума. Люди с гуманитарным мышлением вряд ли смо
гут овладеть программировапием. Еще одна особенность программирова
ния состоит в том, что эта про ф ессия- творческая, а значит, не поддается
изучению через силу. Просто кто-то должен писать стихи, а кто-то - про
граммы для компьютерной техники. Говорят, что программист - это не про
фессия, а диагноз. И отчасти это верно.
Наша книга - это первый, хотя и достаточно большой, шаг в становлении
профессионального проrраммиета, и всего лишь первая книга, прочитанная
вами из десятков тех, которые еще предстоит прочитать. Мы надеемся, что
ваш первый шаг еделап в верном направлении. Желаем успеха!
15
Turbo Pascal 7 . 0
СтРУКТУРА книги
Изложение каждой темы в п а шей книге рассчитано на неподготовленпого
читателя. Все объясняется, начиная с основ рассматриваемого вопроса. Это
не значит, что в книге не рассматри ваю тся сложные вопросы. Примерно
половина изложенного материала непроста для понимания, но изучение
построено по припципу <<ОТ простого к сложному�, при этом вопросы, рас
смотренные в предыдущих разделах, закрепляются и уточняются в после
дующих. Параллельна с основным предметом, освещаются некоторые ин
тересные особенности исполыювания стандартных средств для создания
более качественных программных продуктов.
Задача нашей книги - изложение сведений, необходимых для работы про
граммиста и обучение основам профе ссии па примере языка программиро
вания Turbo Pascal 7 .0. Аргументы в пользу выбора именно этого языка про
сты
Pascal, как, впрочем, и некоторые другие языки программирования,
раз рабаты n ал ея для обучения программированию, но является практичес
ки единственным, который получил широкое распространение.
-
ПРИМЕЧАНИЕ.
Создателем языка Pascal является профессор Швейцарского федерального тех
нологического института ЕТН (Eidgeпoessische Technische Hochschule) Никлаус
Вир т (Niklaus К. Wirth), первый компиля тор Pascal был создан в 1970 г.
Необходимо отметить, что использование Turbo Pascal для профессиональ
ных целей сводится в настоящее время к поддержанию ранее написанных
программных продуктов.
Таким образом, вы, скорее всего, пс будете испол ьзов ат ь его в дальнейшем.
Однако подавляющее большинство методов программирования, изложен
ных в нашем издании, возможно, с пебольшими поправками, подойдет для
работы в других языках програм:мирования. Самым простым будет переход
на язык программирования Dclplli, построенный на основе Turbo Pascal и
являющийся одним: из самых развитых средств программирования на се
годняшний день.
Материал книги разбит на следующие главы:
Глава 1 явля ется вводной и содержит общие сведения, необходимые для
програм:мирования, такие как механизм работы переопального компью
тера и определение места нрограм:мирования в науке и технике. Если во
время прочтения данной главы что-то осталось непонятным в силу своей
сложности, не стоит расстраиваться - это действительно сложные вещи,
и к их рассмотрению можно буде т вернуться впоследствии. За более под
роб по й информацией по этим вонросам рекомендуем обратиться к спе
циализированным изданиям, в которых данные вопросы изложены более
16
Предисл овие
подробно. Наибольш ие проблем ы , видимо, будут вызывать такие термины,
как автоматизация и моделирование, изложенные очень упрощенно, с уче
том возможной неподготовлешюсти читателя в данной области. И все же
информация, приведеиная в этой главе, является, с нашей точки зрения,
в пол н е д остато чн о й для решения широкого круга задач, стоятцих перед
современным программистом.
Глава 2 сод ержит краткое описание основ работы с интегриров анными сре
дами разработчика, обсуждаются основные характеристики сред, а также
довольно подроб н о описывается ср ед а разработчика Turbo Pascal - основ
ного инструмента разработчика программ на данном языке пр ограммирова
ния. Среда разработчика может в ы з ы вать некоторые проблемы при работе
с ней, в силу своей нелокализованности, то есть использования английс
кого, а не русского языка в диалогах с п ол ьзователем. При э том диалоги
переполвены различными профессионаJIЫiыми понят иями , что еще более
затрудняет работу со средой. Данная глава призвана решить эти проблемы.
Глава 3 с одержит описание структуры пр ограммы и ее элементов, а также
методов работы с информацией. Это основы, об щи е для всех языков про
граммирования, вне зависимости от их функци о нальной направленности.
Материал данпой главы является необходимым для создания даже самых
простейших программ и должен быть усвоен в полном объеме. В этой главе
подробно описаны только некоторые, самые простые элементы программы,
остальные же изложены в последующих главах, поскольку невозможно до
ступно объяснить все понятия сразу.
Главы 4 , 5 и 6 посвящены взаимодействию программы с пользователем методам вывода ин формации на экран и ввода с клавиатуры ( т ак называе
мому консольному вводу/выв оду) . Это одни из самых больших глав нашей
книги, так как вывод информации однозначно определяет удобство работы
с ней пользователя.
В ар и ант ов напи с ания одной и той же п ро гра м мы может быть множество, и
каждая программа может име ть достоинства и недостатки, как с точки зре
ния про гр ам миста , так и с точки зрен ия пользователя. Однако программные
продукты создаются для работы пользователя, поэтому его удобство - ос
новной мотив принятия решения при выборе того или другого варианта ре
ализации программы. Пользовательский интерфейс - это именно то, что
пользователь называет программ ой, следовательно, эта часть программнаго
продукта не должна вызывать претензий. Изучение глав, посвященной вы
воду и вводу и н ф ормац и и, не является потраченным временем, так как ме
тоды вывода информации на экран пр акт и чески идентичны для всех язы
ков программирования и платформ, на которых выполняются программы.
Глава 7 содержит основы структурного программирования, опи
сывая методы ветвления и зацикливания програм м , б ез кото
рых не обойтись при со з д ании более или менее функциональ17
Turbo Pascal 7 . 0
наго приложения. Методы ветвления и зацикливания являются
фундаментальными основами программировапия и содержатся в боль
шинстве языков программирования, в том числе и в самых первых.
В главе 8 рассмотрена организация движения объектов по эк
рану, а также методы определения их •столкновения�, что по
может
разрабатывать
динамичные
игровые
программы.
Глава 9 содержит основы модульного программирования, объясняя пра
вила использования подпрограl\IМ, позволяющих более качественно раз
рабатывать программные продукты и использовать ранее созданные
фрагменты программ для разработки новых продуктов. Также в главе об
суждаются вопросы создания библиотек подпрограмм - процедур и функ
ций - для обмена фрагментами программ между разработчиками и ис
пользования одних и тех же подпрограмм в нескольких проектах в
нескольких проектах.
Глава 10 посвящена изучению сложных типов данных для более удобно
представления информации в программах. Основная се часть содержит
описание таких сложных типов данных как массивы, записи и указатели,
присущих практически всем языкам программирования. Расемотрепы ин
тервальные и нере<rислимые данные, а также множества.
го
Глава 11 содержит полную информацию об использовании файлов для дол
говременного хранения информации. В ней рассмотрены возможные типы
файлов, пояснены основные преимущества и недостатки тех или иных
файлов, и подробно изложе ны методы работы. Для более полного попи
мания вопроса в начале главы приведсна беглое описание структуры дис
ковых накопителей и файловой структуры, используемой операционной
системой MS-DOS. Помимо методовнепосредственной работы с файлами,
изложены сведения о работе с файловой системой, в том числе с ката.,тюгами.
Глава 12 является обзорной и содержит основы проектирования баз дан
ных и систем управления базами данных. Знакомство с данной главой по
может закрепить знания, полученные при изучении сложных типов данных
и файлов, а также получить базовое представление о структуре баз данных.
В качестве примера реализована простейшая база данных и система управ
ления ею, представляющая собой электронную записную книжку. Для рас
ширения кру го з ора на этом же примере рассмотрены некоторые правила
формирования реляционных баз данных, используемых в настоящее время
практически во всех серьезных программах автоматизации производств,
сферы услуг и других областей жизни, где необходимо хранение больших
объемов данных.
Глава 13 посвящена вереборным методам решения задач, в том числе опти
мизационных, с помощью рекурсивных подпрограмм. В качестве примера
приведсна решение задачи •Ход коня>> и в общих чертах описано решение
18
Предисл овие
так называемой «транспортной задачи в сетевой постановке� ( Cfu"fO реше
ние не приведсна в силу его объема).
Глава 14 описывает основы применения языка AsseшЬler на примере
встроенного ассемблера Turbo Pascal, в ней изложены основные сведения
об использовании некоторых функций процессара и операционной систе
мы. Глава является обзорной и не претендует на исчерпывающее описа
ние ассемблера, однако помогает лучше понять процессы, происходящие
в компьютере при выполнении программы, даже если она разработана с
использованием языка проrраммирования высокого уровня.
Глава 15 излагает основы объектно-ориентированного програ,"lмирования,
являющегося основной технологией разработки крупных программных
продуктов на сегодняшний день.
Глава 16 является заключитслъной и содержит неболыпие разделы, пос
вященные понятию «качества� программирования. Рассмотрены вопросы
оформления исходных текстов программ, документирования программных
продуктов, отладки и использования параметров компилятора для созда
ния более устойчивых программных продуктов.
Turbo P a s c a l
7.0
В веде н ие
1 . 1 ОСН О В Ы АВТО МАТ И ЗАЦИ И
Любая профессиональная деятельность человека состоит в припятни реше
ний для реализации какой-либо задачи. Совокупность всех задач, решае
мых человеком, можно разбить на три основные группы:
•
•
•
Творческие, в процессе решения которых, в осiюшюм, используется
интеллект и и нтуиция человека. В качестве примеров таких задач
можно пр иве сти любой вид творческой деятельности: изобразитель
ное искусство, поэзия и т.д.
Алгоритмические, выполняемые по жесткой схеме ( алгоритму). К дан
ной категории относятся такие задачи, как бухгалтерский у<Iет, различ
ные расчеты и другие задачи, решение которых передко регламенти
руется законодательством, внутр енними требованиями предприятий
или учебных заведений и т.д.
Смешанные, в процессе решения кот орых могут встречаться, как
алгоритмические, так и творческие этапы. Наиболее яркие примеры
задач такого рода - конструкторская и дизайнерская деятельность,
сочетающие в себе творческие этапы поиска нетрадиционных реше
ний и жесткие правила о ф ормления результата р аб оты в виде черте
жей, оригинал-макетов и нео бходимой документации.
Широкое распространение вычислительной техники, и особенно переа
нальных компьютеров, позволяет спять с •rеловека необходимость решения
некоторых трудоемких задач и припятня им стандартных решений.
Процесс решения задачи, в котором встречаются этапы, выпоm1яемые тех
ническими устройствами, называется автоматизированным. Сама деятель
ность по преобразованию процессов решения задач в автоматизированные
20
Глава 1 . Введение
называется автоматизацией. Основным достоинством автоматизированного
процесса решения задач является повышение производительности труда,
связанное с уменьшени ем рутинной работы, ускорением расчетных этапов
решения задачи, исключением ошибок расчетов, снижением психологичес
кой и физической нагрузки па человека.
В данном коптексте любую задачу можно рассматривать с точки зрения
возможности и с т еп е н и се автоматизации.
Под автоматизируемостью
понимается возможность а в т о м ат и з аци и данпой задачи в пекоторой сте
пени. Автоматизация процессов базируется на выявлении жесткой схемы
протекания процесса, поэтому, если такую схему составить невозможно,
автоматизация процесса исключена. Таким образом, алГоритмические за
дачи допусi<ают автоматизацию и являются автоматизируемыми. Сме
шанные задачи допускают автоматизацию лишь некоторых этапов их
решения и я в л яются частично автоматизируемыми. Творческие задачи
не допускают авто м ат и з аци и и , соответственно, автоматизируемыми не
являются.
Сл едует заметить, что когда говорят про автоматизируемость задачи, под
разумевают лишь теоретическую во:-Jможность автоматизации, тогда как
на практике данная задача автоматизации может не иметь решения. Од
нако с развитием техники и методологии автоматизации, теоретическая
автоматизируемость м ожет переходить в практическую.
В качестве примера можно привести программу, играющую в шахматы, со
здание которой н е ск о л ьк о десятилетий назад было невозмо жным из-за
недос т ато ч н ог о быстродействия в ычи слител ьных средств и малых объе
мов оперативной памяти, тогда как сейчас данная задача успешно решает
ся, и комныотср и гра е т в шахматы не хуже человека.
Еще одним препятстви
ем на пути автомап1за
ции является ее воамож
ная экономическая не
целесообразность. Если
затраты на автоматиза
цию какого-ли б о процес
са превьппают пр и быль
полученную в резу льтате
использования автома
тизированного п р оцесса
то такая автоматизация
не имеет смысла.
Творческая
Смешан ная
Н ет
Существует л и возможность
составл ения алго р итма?
Да
,
Существует ли э ко н о м ич еская
цел есообразность
авто матизаци и ?
,
Схема определения воз
можности автоматиза
ции иско торой задачи
представлена на рис. 1 .
Н ет
Да
Рис. 1 . Схема определения возможности
и целесообразности автоматизации
какой-либо задачи
21
Turbo Pascal 7 . 0
1 . 2 П РО ГРАМ М И РО ВАН И Е КАК ЧАСТЬ П Р О ЦЕССА
АВТОМАТИ ЗАЦИ И
В процессе авт о мати з ац ии используется широкий спектр технических ре
шений, таких как специальные электронные и механические устройства,
а также I<ампьютерная техника. Но вне зависимости от автоматизируемой
задачи и используемых для этого методов автоматизированная система
предполагает наличие в ней внутренней логики.
Логика системы может реализовываться непосредственно техническими
средствами для каждой конкретной системы (например, логика работы
двигателя внутреннего сгорания определяется сочетанием соответствую
щих механических и электронных устройств) , или в системе могут ис
пользоваться элементы широкого назначения, имеющие возможность из
менять свои свойства для решения конкретной задачи автоматизации.
Такие элементы называются программируемыми - работающими в соот
ветствии с заданной програ:ммой (алгоритмом) .
В общем виде, все программируемые устройства можно представить как
преобразователь, изменяющий входной поток информации и получающий
в результате этого изменения выходной поток информации. Процесс преоб
разования определяется еще одним потоком - программирующим (см. рис. 2).
Проrраммирующий поток несет в себе информацию о том, каким именно
образом должно происходитr:. преобра.з ованис входной информации в выход
ную, то есть содержит в себе некоторый алгоритм (программу).
Входной
информ а ционный
nоток
1---�
Выходной
и нфо р м а ционный
nот о к
Рис. 2. Общая схема программируемого устройства
Примерам простейшего преобразователя может служить обычный вы
ключатель, который под воздействием программирующего потока (вклю
чение/выключение) обла,.ТJ; ает свойством преобразовывать информацион
ный входпой поток в пустой выходной поток (в выключенном состоянии)
или в выходпой поток, идентичный входному (во включенном состоянии).
Одним из самых сложных преобразователей является компьютер, преоб
разующий входной поток информации, вводимой пользователем с клави
атуры, мыши и других устройств, в выходной в виде файлов, изображения
на экране или звуковых сигналов.
Теперь перейдем к рассмотрению того, что следует понимать под понятия
ми �программа» и �программирование».
22
Глава 1 . В ведение
Программой называется логически законченный набор инструкций пеко
торой среде (преобразователю ), созданной для автоматизации какого
либо процесса, а программированием - процесс постановки задачи авто
матизации, составленияалгоритма, написанияпрограммы, ее тестирования
(проверки соответствия поставленной задаче) и отладки (исправления
ошибок ) .
Таким образом, программирование - это составная часть процесса автомати
зации, связанная с настройкой программируемых устройств для реализации
процесса преобра:ювания входного информационного потока в выходной.
Приведем пример простой задачи автоматизации. Представим себе емкость
с водой, в которой должна поддерживаться определенная температура, на
пример, от 50 до 60 градусов Цельсия. Можно поддерживать температуру
с помощью оператора - человека, который будет следить за показаниями
термометра и включать или выключать нагревательный прибор, когда тем
пература выходит за пределы заданного диапа:юна. А можно автоматизи
ровать этот процесс с помощью устройства, которое будет получать инфор
мацию с термометра и управлять нагревательным прибором.
В случае внедрения такого устройства будет сокращено количество воз
можных ошибок, допускаемых за счет невнимательности оператора, а также
сиижены затраты на заработную плату оператора. Однако появятся новые
затраты - на обслуживание самой автоматизирующей системы.
На практике применяются значительно более сложные устройства. Однако
большинство из них работает именно по такой схеме - получение инфор
мации с датчиков, ее анализ и управление каким-либо процессом на основе
данных анализа.
1 . 3 М ОДЕЛ И РО ВАН И Е
Любой процесс, например, физический, а также какое-либо устройство
можно описать пекоторой совокушюстыо параметров и правил изменения
этих пара.'\1 етров. Такую совокупность называют математической моделью.
Основное на:шачение модели - изучение моделируемого процесса (уст
ройства) с помощью проведения эксперимента над моделью.
Экспериментом называется изменение каких-либо параметров модели
с целью изучения изменения других параметров . Соответственно, моде
лированием называют построение математической модели для процесса
или устройства и постан овку эксперимента над этой м оделью. Необхо
димо заметить, что для построения модели допускается выбирать не все
параметры моделируемого процесса или устройства, а только изучаемые
и те, которые могут на них существенно влиять.
23
Turbo Pascal 7 . 0
Поясним на примере, что такое математическая м одель и э к сперим ент н ад
пей. Допустим, имеется объект, который движется и з пункт а А в пункт Б с
постоянной скоро ст ыо v. Тогда в любой момент времени т положение объ
екта s (удаленность от пункта А) можно рассчитать по формуле: s = V · т.
Параметры s, v, т и формула для вычисления s будет называться моделью,
а расчет положения о бъ ек т а s по формуле будет являться постановкой экс
перимента над моделью.
G)
/
1
та
- - - - - - - - -
1
.с
s
Рис. 3.
Иллю страция
мод елируемого
ф изического
пр оце сса
Приведем более сложный пример. Рассмотрим процесс на
полнения цилиндрического стакана жидкостью с целью опре
деления высоты жидкости через некоторое время (см. рис. 3).
Допустим, стакан имеет постоянную по всей высоте площадь
п оперечного сечения S (м2 ) , расход жидкости не изменяется
с течением вр емспи и равен Q (ИЗ 1 с ) . Тогда при условии, что
изначалыю стакан был пуст, в момент времени t { с ) высота
в оды в стака п е h (и) будет составлять h
Q t/S.
=
·
Набор пар а.'\1 етров s, Q, t, h и выраженИе для высоты жид
ко с т и h я в ля ет ся математической моделью данного про
цесса. Для построения данной модели выбраны не все
параметры моделируемого процесса и устройств, которые
в этом процессе используются. Например, на стакан действует сил а тя жести , но он а не влияет на изменение высоты
жид к о с т и , поэтому не отражается на возможных р езультатах эксперимента и не в кл ю че н а в модель.
Также не учитывается возможное и сп ар е ние жидкости, хотя оно и вл и яет
на высоту жидкости в стакане. Од н ако мы пр е не брегае м данным пара.'\1ет
ром в силу его несущественности.
Теперь проведем над построеиной моделью э ксп ер им ент. Зададим все па
раметры мод ел и , кроме высоты ЖИДI(ости h : Q
1 о - • м-:• 1 с , t = 1 с ,
s
1 2 · 1 0 -·1
м2• Б результате изменения этих параметров моде
ли, происходит изменение другого параметр;;t - высоты: h = Q t / s =
=
=
1 0 -4 · 1 0 / 1 2 · 1 0 -4
=
8 · 1 0 -2 ( м ) =
8
( см ) .
·
Мы рассм отрели простейшую модель. На ирактике используются намного бо
лее сложные модели, содержащие сопrи па раметров и десятки правил их изме
нения. Постановка эксперимента над такими моделями не может быть вьшолне
на человеком, либо будет занимать слипшом много времени. Для эксперимента
над сложными моделями применяются компьютеры , рост производительности
которых позволяет все более и более усложнять модели в целях получения но
вых знаний. Основной инструмент реализации эксп ер имента с использованием
компьютера - програмl\шроваrrие. Таким образом, мы выяснили вторую основ
ную область приложения проrра.'\1мирования, помимо автоматизации - моде
лирование. Скорректируем определения проrра.'\1мы и программирования с уче
том возможностей их пр.именения для решения задачи м оделиров ания .
24
Глава 1 . Вв едение
Проrраммой называется логически законченный набор инструкций не
которой среде (преобразователю ), созданный для автоматизации или
моделирования какого-либо процесса или устройства, а программиро
ванием - процесс постановки задачи автоматизации или моделирова
ния, составления алгоритма, написания проrраммы, ее тестирования
(проверки соответствия поставленной задаче) и отладки (исправления
ошибок) .
При моделировании изучаемый процесс или устройство совершенно не
обязательно должны существовать в действительности. Н апример, при
проектировании нового космического корабля, чтобы изучить его пове
дение, можно либо построить опытный образец и запустить его в космос,
либо выявить воздействия окружающей среды на предполагаемое уст
ройство , описать их и само устройство в виде модели, и и сследовать по
в едение этой модели с теоретической точки зрения (поставить над н ей
эксперимент) .
Второй подход намного дешевле и, к тому же, позволяет попробовать теоре
тически те ситуации, которые тяжело создать в реальности в силу высокой
стоимости или несовершенства имеющихся технологий. Применительно к
космическому кораблю такой ситуацией может быть метеоритный поток:
даже если и можно запустить корабль в космос с целью исследования его
поведения, то совершенно необязателыю на его пути встретится этот поток,
а создать его специально нет возможности.
Интересным продуктом моделирования являются компьютерные игры, со
здающие некоторую, обычно невозможную на практике, си ту ацию В основе
игры лежит сценарий - фактически математическая модель, как и в любом
моделируемом процессе. Пользователь может вмешиваться в процесс раз
вития модели, задавая какие-либо условия, с целью достижения поставлен
ной цели, то есть проводить с моделью эксперимент.
.
Отметим еще раз, что в основе автоматизации лежит процесс, реально
существующий н а практике, а в основе моделирования - модель про
цесса, которого м ожет и н е существ овать в реальности (или еще н е су
ществоват ь ) .
1 . 4 . СТРУКТУРА П ЕРСО НАЛ ЬН О ГО КО М П ЬЮТЕРА
В определении программы указано, что для ее выполнения необходима не
которая среда, нааываемая средой выполнения программы. Наша цель изучение программирования переанального компьютера, поэтому мы не
будем рассматривать всего многообразия сред выполнения, а сконцентри-
руемся на той среде, которая существует именно в ПК (см. рис. 4).
25
Turbo Pascal 7 . 0
.- - - - - - - - - - - 1
1
1
1
1
1
1
1
1
1
1
1
L _��!:!�t":!:J!.0���!!. .J
Рис. 4. Общая схема устройства переанального компьютер а
Итак, переанальный компьютер представляет собой совокупность трех час
тей: внутренних устройств, внешних устройств и операционной системы,
связывающей между собой внутренние и внешние устройства посредством
специальных программ, называемых драйверами. Рассмотрим данные час
ти более подробно.
1 . 4 . 1 . В НУТРЕННИЕ УСТРОЙСТВА
Внутренние устройства физически размещены на так называемой материн
ской плате (MotЬer Boarcl) и осуш:ествляют основные действия, необходи
мые для работы компьютера, а именно начальную заrрузку (инициализацию),
а также загрузку и старт опер ационной системы. На этом функции внутрен
них устройств не заканчиваются, работа компьютера без них невозможна.
Основное внутреннее устройство - процессор, выполняющий все запуска
емые программы, причем к таким программам относится и операционная
система. Исключением можно считать специальные программы внешних
устройств, выполняемые самими внешними устройствами для обеспечения
собственной функциональности (например, модем может иметь собствен
ный процессор, обеспечивающий прием и передачу информации) .
Н е менее важное внугреннее устройство - BIOS (Ba.<;ic Input/Output System Базовая Система Ввода/Вывода) - представляет собой энергонезависимую
память, информация в которой не теряется при выключении Iшмпьютера
(такую память еще называют ПЗУ - постоянное запоминающее устройс
тво). BIOS содержит программу для начальной загрузки компьютера и ин
формацию, необходимую для обращения к стандартным устройствам, ис
пользуемым в процессе загрузки (например, I< монитору или клавиатуре).
Некоторые функции BIOS используются и в процессе дальнейшей работы.
Оперативная память (оперативное запоминающее устройство - О ЗУ) ис
пользуется для временного (до выключения компьютера) хранения инфор
мации. В ОЗУ хранятся выполняемые в данный момент времени програм
мы, в том числе и некоторые части операционной системы, а также данные,
с которыми работают эти программы.
26
Глава 1 . Введение
Шина данных представляет собой мост между всеми вышеперечисленны
ми устройствами и используется для персмещения потоков информации
от ощюго устройства к другому.
Кроме основных используется еще несколько десятков внутренних уст
ройств, таких Ka.I< контроллеры аппаратуры, используемые для подключения
внешних устройств, порты ввода/вывода информап:ии, генераторы тактовых
частот и множество других. Однако пааначепис всех этих устройств - под
держка работы основных.
1 . 4 . 2 . ВНЕШНИЕ УСТРОЙСТВА
Внешние устройства служат для обмена информшщей внутренних уст
ройств с пользователем или другими устройстВ<L.'\-IИ.
По применениш можно классифицировать внешние устройства следующим
образом:
•
Устройства отображения информации. К таким устройствам отно
сятся, например, мониторы и принтеры.
•
Устройства для ввода информации: клавиатуры, мыши, графические
планшеты, сканеры и др.
•
Устройства для хранения информации: жесткие диски (винчесте
ры), дисководы, CD-ROM'ы.
•
Устройства для обмена ин ф ормацией, например, модемы.
Данное деление довольно условно и некоторые устройства могут относИть
ся к нескольким группам. Например, с помощью звуковой карты можно вы
водить звуковую информацию на динамики, вводить ее с помощью микро
фона, а также сохранить, подключив к выходу звуковой карты какое-либо
записывающее устройство, например, магнитофон.
Следует заметить, что именно внешние устройства обеспечивают привыч
ные удобства компьютерной техники и обусловливают те широкие возмож
ности, вследствие которых она получила массовое распространение, в част
ности, в области автоматизации.
1 . 4 . 3 . ОnЕРАционнАя систЕМА
Операционная система - это совокупность программ, обеспечивающих
связь отдельных частей аппаратного обеспечения, а также проrраммноrо
обеспечения с аппаратным. Основная часть операционной системы - ядро,
определяющее общую функциональность системы и распределяющее про
дессорвое время между выполняемыми программами (в том числе и явля
ющимися частями самой системы).
27
Turbo Pascal 7 . 0
Помимо ядра, в состав операционной системы входит набор драйверов программ, обеспечивающих доступ опера:циошюй системы I< внешним ус
тройствам:, что, собственно, и позволяет операционной системе выполнять
задачи связи, указанные в определении.
С точки зрения пользователя, операционная система нужна для предостав
ления интерфейса к ресурсам компьютера. Вне зависимости от контекста,
в котором употребляется данный термин, интерфейсом называется сово
купность инструментов, которые можно использовать для обмена инфор
мацией, то есть получения доступа к чему-либо или для выполнения ка
ких-либо действий.
Например, приглашение операционной системы MS- D O S является ин
терфейсом, потому что представляет собой инструмент вызова системных
функций операционной системы, используемых пользователем для досту
па к носителям информации, запуска программ и получения сведений о со
стоянии системы. Рабочий стол операционной системы Windows и других
подобных ей систем, имеющих графическую оболочку, также является ин
терфейсом (такие интерфейсы называются пользовательскими).
С другой стороны, термин интерфейс можно применить к набору команд,
используемых для обмена информацией с внешним устройством, напри
мер, с модемом. Такие интерфейсы называют аппаратными. И, наконец, со
вокушюсть параметров, передаваемых программ е, и механизм вызова отде
льных ее частей, называется программным интерфейсом.
Таким образом, операционную систему можно представить как совокупность
механизмов для предоставления программных и пользовательских интер
фейсов, а также преобразования аппаратных интерфейсов в программвые
(эта функция реализуется драйверами) . Логическая схема взаимодействий
внешних устройств, операцщонной системы, программ и пользователя, а так
же используемых для взаимодействий интерфейсов представлена на рис. 5.
Как видно из рисую<а, внешние устройства взаимодействуют между собой
через аппаратные интерфейсы, определяемые самими устройствами. В ка
честве примера такого взаимодействия можно привести совместную ра
боту видеокарты и монитора. Программы взаимодействуют друг с другом
.
[ j �-Р������� j" П роrрамм н ы й 1
1
:
:
»:s
��
:1
1
1
1
:
и нтерфейс
i1
JS
�
��
��
� х�:s:
[ j�:;:�;�� ����;�-�
т
1
г -П-о-;.�;о в атепьский
Про грам м а
интерфейс
toa::l !
ф
��
��
�r; �
:1:
< :s:
о �
i 1 Внешнее устройство 1
� i
�
в
JS
u
�� ��
t:
- - - - -
1
1 Аnn а ратн ы й
1 интерфейс
О n е рацион ная
систе м а
... -__
r----....J
П ол ьзо ва тел ь
l
...,JI
:::�: т
-
а
п ол ьз о в т
интерфейс
--
- - - - - - .J
Рис. 5 . Взаимодействие ПК, операционной системы и пользователя
28
Глава 1 . Вв едение
через программные интерфейсы. Например, когда некоторая программа
вызывает Microsoft Word и открывает в нем документ, она использует про
граммный интерфейс Microsoft Word. Пользователь взаимодействует со
всеми частями переанального компьютера через интерфейс пользователя.
Самая сложная часть системы взаимодействий - это операционная систе
ма, которая:
•
предлагает программам для взаимодействия свой программный
интерфейс;
•
поддерживает программный интерфейс, используемый при взаимо
действии программ друг с другом;
•
обеспечивает вторичный програ.\1:мный интерфейс доступа к внешним
устройствам (получаемый в результате работы драйверов, созданных
для обращения к внешним устройствам по аппаратному интерфейсу
в ответ на обращение к самому драйверу по проrраммному интерфейсу).
Операционная система оправдывает свою сложность и немалые размеры
унификацией доступа программ к внешним устройствам. Результат ее ра
боты - возможность любой программы обратиться к внешнему устройству
на уровне запроса информации от операционной системы. Например, каж
дый модем может иметь св ои особенности аппаратного интерфейса, а про
граммвый интерфейс для работы с модемом, предлагаемый операционной
системой, одинаков для всех модемов.
И, наконец, пользователь взаимодействует со всеми частями переанального
компьютера через интерфейс пользователя. Программы реализуют пользо
вательский интерфейс с помощью устройств ввода/вывода, доступ к кото
рым получают через операционную систему. Внешние устройства позво
ляют пользователю воздействовать на их работу и получать информацию
с помощью механизмов, свойственных этим устройствам. При этом опера
ционная система осуществляет возможность пользовательского интерфейса
так же, как и программы, так как сама является совокупностью программ.
1 . 4 . 4 . М ЕХАНИЗМ РАБОТЫ ПЕР СОНАЛЬНОГО КОМПЬЮТЕРА
При включении компьютера подается питапис па материнскую плату, кото
рая перераспределяет е го по устройствам, расположенным н а пей, с целью
их в кл ю ч е н ия. В число данных устройств попадаст генератор частоты про
цсссора, в результате чего процессор начинает работать и обращается к
BIOS для получения программы инициализации. Программа инициализа
ции, считанная из BIOS в оперативную память и выполняемая процессо
ром, тестирует необходимые внутренние и внешние устройства. Если в про
цессе самотестирования найдены ошибки, то пользователю ПК выдается
об этом сообщение в виде информации па экране или звукового сигнала.
29
Turbo Pascal 7 . 0
После успешного окончания процедуры са.vютестирования происходит поиск
операционной системы и се загрузка. Операционная система должна нахо
диться па одном из носителей информации: на жестком диске, на CD-ROM'e,
на дискете или каком-либо другом съемном носителе. Порядок поиска опера
ционной системы определяется пастройками BIOS. Для изменения этих на
строек все системы BIOS снабжены специальной проrраммой, которая обыч
но называется BIOS Setпp (настройка BIOS), и вызывается при нажатии
пекоторой комбинации юrавиш при в кпючении или перезагрузке компьютера.
BIOS пытается найти операционную систему, считывая начальные области
дисков в последовательности, определенной в своих настройках. В случае
отрицательного результата поиска пользователю выдается сообщение о не
обходимости вставить носитель информации, содержащий операционную
систему.
В случае обнаружения операционной системы на каком-либо носителе,
BIOS отдает управление этой системе, то есть загружает инициализацион
ную часть операционной системы в оперативную память и передает ей уп
равление. Начиная с этого этапа функции BIOS используются только по
запросу выполняемых проrрамм, а процессом загрузки операционной сис
темы управляет инициализационная часть самой системы, выполняемая
процессором.
Далее инициализационная часть загружает всю необходимую для работы
операционной системы информацию, запускает драйверы устройств и про
грамму, реализующую пользовательский интерфейс. Так же могут запус
каться и другие программы, в том числе и не входящие в состав операцион
ной системы, например, Norton Cornrnandeг в MS- DOS, для более удобного
начала работы, или набор вспомогательных программ в Windows, например,
автоматическое подключение к сети Intcrnet, программа ICQ и т.д.
После полной загрузки операционной си стемы пользователь переанального
компьютера получает доступ к пользовательскому интерфейсу и может начи
нать работу, то есть запускать программы на выполнение и работать с ними.
1 . 5 . П РО ЦЕСС СОЗДАН И Я П РО ГРАМ М Ы И И Н СТРУМ ЕНТЫ
П РО ГРАМ М И РО ВАН И Я
ПРЕДСТАВЛЕНИЕ ПРОГРАММЫ
В предыдущих разделах мы ознакомились с попятиями автоматизации и
моделирования, выявили роль программирования в этих процессах и оп
ределили предмет нашего изучения - проrраммирование переанального
30
Глава 1 . Введение
компьютера. Также мы выяснили структуру переанального компьютера,
схему его работы и место программы в этой схеме. В данном разделе мы
более подробно рассмотрим, что такое программа, разберемся в процессе
создания программы и инструментах, которые при этом используются.
Итак, программа выполняется процессаром под управлением операцион
ной системы и имеет доступ к оборудованию через драйверы операцион
ной системы посредством программнога интерфейса, реализуемого драй
верами. Кроме того, каждая программа имеет возможность совместной
работы с другими програм:мами, также через использование программно
го интерфейса, предоставляемого ими и поддерживаемого операционной
системой.
Программа представляет собой zюо о _
о яя* О о
о
>
о ыPj r
набор единиц информации - I O_O ( O 9 0 u o j O " О 0 0 0 0 - 0 V
байтов, которыенесутв себелибо E_OъD_O з D_O>D_O_C_O@C_O ( C_DДB_D_G_O_G_O
G_OЬIF_O B F_O<F_O Ч G_OI H_O \H_O_H_OЭI _O, I_O
некоторую команду, известную
процессору, либо информацию, 7
необходимую для выполнения О ' _Оnф_О>_Ос_О Р_О О_ОУ_О " _О е ' _О О '
' _oa" _oи_o ' _O P_D н >_D_>_D1 >_own_oюo_o
этой команды. Если посмотреть Ng_OaNg_O
NiNL_O
на программу в таком виде, E_O J E_D } E_09>_0 0_0<_0D_O/_OИ_0 ' 1_0
можно подумать, что она явля Th i s l oad e r i s i n voked an d r e q u i r e d Ьу
Н ! ZХО_ё LH ! &_> O l б t D йVя
ется совершенно печитаб ель $ 0 PRO D E - ё
ной и не несет для человека ни
Рис. 6. Визуальное представление
какой информации (см. рис. 6).
программнаго кода
1
.
На самом деле эт о не совсем так, и есть немалое количество программистов,
способных написать работающую программу такими кодами без использо
вания стандартных инструментов программирования. Но такие случаи
очень редки и относятся только к самым маленьким программам, для кото
рых критичен размер и скорость работы. В качестве примера таких про
грамм можно привести различные взломщики простых зюцит, работаюп�их
на локальных переанальных компьютерах. В остальных же случаях про
граммы создаются в несколько этапов, а, собственно, процесс написания
программы (то есть получения кодов для процессора) автоматизирован
и выполняется специальными программами н а основе так называемого ис
ходного текста программы.
В начале данного раздела мы сказали о том, что программа не просто вы
полняется процессором, а выполняется под управлением операционной
системы. Это связано с тем, что в программе могут находиться команды,
предназначенные не для процессора, а для самой операционной системы.
Например, библиотека графических функций Wiпdows может использо
ваться Windоws-программами, но эти функции не поддерживаются напря
мую процессором, а требуют для своего выполнения дополнительных про
гра.�мных средств операционной системы Windows.
31
Turbo Pascal 7 . 0
ЭТАПЫ РАЗРАБОТКИ П РОГРАММЫ
Процесс разработки програ..\1мы состоит из следующих этапов:
1. Выбор той части процесса, которая должна автоматизироваться или
моделироваться с помощью программирования и постановка задачи.
2. Разработка алгоритма, то есть схемы протекания автоматизируемо
го или моделируемого процесса. Если при выполнении данного эта
па ра.<Iработки выявились факторы, прспятствующие возможности
автоматизации, следует вернуться к пу:нкту 1 .
3 . Реализация алгоритма. Данный этап состоит в написании исходного
текста программы на каком-либо языке программирования - спе
циальном языке для создания исходных текстов программ, исполь
зуемого затем специализированной программой для получения про
граммнаго кода для процессара и операционной системы. Вопросы
выбора конкретного языка программирования обсуждаются ниже.
4. Компиляция и построение програ.\1мы. Комnиляция (англ.
Compiliпg) - это процесс получения из исходного текста проrрам
мы некоторого промежуточного кода, называемого объектным
файлом, необходимого для построе1mя программы . Данную задачу
выполняют специализированные программы - комnиляторы ( англ.
Compiler - компилятор), настроенные на соответствующий язык
программирования или несколько языков програ..\1мирования сразу.
Если для построения программы используется несколько исход
ных текстов, то для каждого из них обычно создается объектный
файл. Далее полученные объектные файлы собираются в одну гото
вую програ..\1му. Этот процесс называется построением программы
или линковкой (англ. Linkiпg - соединение). Программу, выпол
няющую линковку, называют, соответственно, линковщиком (англ.
Liпker - линковщик). В некоторых случаях процессы компиляции
и линковки могут объединяться, тогда э то т сложный процесс такЖе
называют компиляцией.
После прохо:ждения всех этих этапов разработн:и программа готова к вы
полнению. Следует заметить, что после построения программа может со
стоять из одного или нескольких файлов, вне зависимости от количества
исходных текстов и объеrпных файлов. Далее начинается этап тестирова
ния - проверки соответствия полученной программы поставленной задаче
и отладки - выявления и исправления ошибок.
Виды ОШИБОК, ВОЗНИКАЮЩИ Х В ПРОЦЕССЕ РАЗРАБОТКИ П РОГРАММЫ
В процессе разработки программы могут встретиться следующие ошибки:
•
Синтаксические - связанные с неправильным использованием язы
ка программирования. Например, вместо команды языка W r i t e Ln
32
Глава 1 . В веден и е
использована несуществующая команда V r i t e L n . Данные ошиб
ки могут возникать только на этапе компиляции, компилятором
сразу же выдается сообщение о них, соответственно, такие ошибки
просто исправляются и больше не появляются, сели программист
не предпринимает попыток изменения исходных текстов програм
мы и дальнейшей перекомпиляции.
•
Логические - связанные с неправильной разработкой или реализа
цией алгоритма. Например, задача автоматизации состояла в расчете
корней квадратного уравнения, а полученная в результате разработ
ки программа вычисляет их неверно. Данные ошибки выявляются
в процессе тестирования программы. В случае обнаружения такого
рода ошибок, необходимо сначала вернуться к этапу реализации ал
горитма, а в случае отсутствия ошибок на этом этапе, придется пере
смотреть ра:iр аб о тку алгоритма с учетом найденных ошибок.
•
Динамические - связанные с некорректным использованием синтак
сически верных инструкций языка программирования. Например,
программа в начале своей работы обраш:ается к операционной системе
с требованием выделить ей для работы некоторое количество опера
тивной памяти, а после окончания своей работы не возвращает выде
ленную память обратно операционной системе. В таких случаях, через
несколько аапусков некорректно написанной программы (конкретное
количество запусков определяется свобощ1ыми ресурсами ком
пьютера и объемом nамяти, не освобождаемым программой), работа
всей системы в целом становится невозможной, что зачастую приво
дит к потере информации в других приложениях. Некоторые такие
ошибки могут выявляться через месяцы работы с програ.."'мой, соответственно,
они
Постановка задачи
,· ,
очень трудны в
+
с , ;_ , . -. · - - - - - - ·
обнаружении и уст
Разрзботка· алгори тма
��������--.---�--------���·
�-- ;
�> ; ,
,.,,-::;=-;- - - - - ::
ранении. Динами
Реализация :ал горит м а .
·
ческие ошибки об
:
· ���������
наруживаются на Г7���--------���
этапе выполнения
J
·, '
,.
программы и тре
�:
о,
Ком nиляция . Обнаружены · л и синтаксичеюкие ошибки?, ,
.. ,
буют возвращения
s,
нет
к этапу реализации
�::Т!
s,
алгоритма.
.•
·
1исхьднь�уексты lрСраммj
щ.. /:
Схемаразработкипрограм
1 . Линковка (nостроение nроrраммы)
мы с учетом исправления
возможных ошибок изоб
ражена на рис. 7.
�!
�:
�:...
�
Cll
...
:r,
"''
о,
1
1
1
1
1
- - - - - - -·
Рис . 7. Схема разрабо тки программы
2
Зак, 702
33
Turbo Pascal 7 О
.
ОСНОВНЫ Е И Н СТРУМЕНТЫ ПРОГРАММИРОВАНИЯ
При разработке программы используются следующие основные инстру
м енты про rра:ммирования (вспомогат ель ные программы ) :
•
Текстовый редактор - программа, используемая для создания ис
ходных текстов программ и сохранения их н а
каком-либо носителе.
•
Компилятор - пporpa;\t:Ma, создающая промежуточные объектные
файлы из исходных текстов програм м . Важнсйптая характеристика
компилятора - поддержка пекоторога я з ыка програм мирования.
Вопросы , связанные с языками программирования, обсуждаются
ниже.
•
Линковщик - программа, создающая из промежуточных объектных
файлов программу, исполняемую пекоторой средой .
•
Отладчик - программа для обнаружения логич е ских и динамичес
ких ошибок в программе, контролирующая выполнение р азрабаты
ваемой программы. Описанию отладчиков, их возможностям и ме
тодаi\.J: раб оты с ними посвящен отдельный раздел нашей книги.
В большинстве современных средств программирования реализован еще
один инструмент - интегрирован пая ср еда разраб отчи ка - программа,
объединяющая все вышеперечисленные и, в о зможно, еще некоторые инс
трументы, в целях повышения скорости и удобства разрабопш проrра:мм ы .
1 . 6 . В Ы БОР Я З Ы КА П РО ГРАМ М И РО ВАН И Я
Существует множество языков программирова:пия, различающихся по
предоставляемым возможностям . В ы б ор языка програм мирования для ре
шения к о нкретн ой задачи существенно влияет на качество програ:ммы, по
лучаемой в результате разработки , а также на с коро сть и удобство ССL'\1:ОГО
процесса разраб отки. С точки зре н ия возможностей, предоставляемых для
непосредствен н ой реализации алгоритма, а также свойств исполняемых
программ, получаемых в процессе разработки , можно определить несколь
к о критериев выбора языка проrраммирования (мы не претенду ем на ис
черпывающую классификацию всего многообразия языков программиро
вания, а лишь пытасмся определить н екоторые осншшые кр и т е рии выбора
конкретного языка для решения поставленной задачи).
П о УРОВНЮ ПРЕдОСТАВЛЯЕМЫХ ВОЗМ ОЖНОСТЕЙ (ФУНКЦ ИЙ Я ЗЫ КА)
По уровню предоставляемых возможностей (функций)
рования разделяются на:
34
языки
проrра:мми
Глава 1 . Введение
•
•
Языки проrр а!\fмир о вания низкого уровня, об е спечив ающие под
д ер жку простейших операций, обычно на уровне системных уст
ройств - процессора, памяти и т .д. Прим е рам такого языка является
AsseшЬler, сод е р жащий только команды перссылки единиц инфор
мации между регистрами процессара и областями памяти, а также
вызова системных функций операционной систе м ы.
Язы к и программирования высокого уровня, об еспечив аю щие под
держку сложных о пер ац и й , например, таких как получение инфор
мации из базы д ан н ых по запросу или вывод и н фор м ации на при
нтер. В р е зул ьтате использования данных языков получаются более
о б ъемные и менее быстрод ей ствующи е исполняемые проrраммы.
Однако это компенсируется высокой скоростью их разработки и
м еньшим количе ством ошибок, хотя бы вследствие малых объемов
исходных текстов. К таким языка..\1 относя тся С/С++, Turb o Pascal
и мн о ж еств о других. В язык высокого уровня может б ы ть ветрое
па п одд е р жк а языка ни з к ого уровня, что компенсирует отсутствие
в языках высокого уровня доступа к низкоуровневым операциям.
По ФУНКЦИОНАЛ ЬНОМУ НАЗНАЧ ЕНИЮ РАЗРАБАТЫВАЕМОЙ ПРОГРАММЫ
Исходя из функционального назначения р а..�раб аты в аемо й проrра."\lмы мож
но языки проrраммирования разделить на следующие группы:
•
Специализированные языки программироваиия, предназначе нны е
для решения узкого кру га задач. Например, языки FoxPro и Clipper
прим е ня ютс я для создания систем управления базами данных С У БД , с о отве т ств енн о с одержат б ол ее удо б ные высокоуровне
вые фун кц и и доступа к данн ы м зато не имеют н екотор ы х воз
можностей, необходимых, например, для программирования
трехмерной графики
,
.
•
Я зыки програм мирования широкого назначения, пр едназнач ен
ные дл я решения широкого круга задач. К таки м языкам относят
ся С/ С + + и ТшЬо Pascal. С по м о щью этих языков можно решатъ
практически любые задачи, однако некоторые из них, например,
с о зд ан и е СУБД п отр ебу ет намного большего времени и зн ан и й
разработчика, чем п ри использовании какого-либо специализиро
ванного языка программировапия. Однако, про б ле мы такого рода
решаются с помощью создания сп е ци ализ и р ов анных библиотек
функци й для языков широкого наз начения Данные библиотеки
сод е рж ат функции, обычно реал Изуе м ы е только в специализиро
в анных языках, и при этом не мешают использованию с о б ств енн ы х
функци й языка широкого назначе н ия . Такой подход реализуется
практич е ски во всех современных яз ы к ах программирования, на
прим ер в Delphi, Visual С++ или .Jаvа
.
,
35
Turbo Pascal 7 . 0
П о СРЕДЕ В ЫП ОЛ Н ЕНИЯ
По среде выполнения программы, получаемые в процессе разработки, мож
но разделить на две группы:
•
Откомпилироваш1ые nроrраммы - программы, исполняемые опера
ционной системой. Основная особенность откомпилированных про
грамм - принадлежиость пекоторой операционной системе. Под ка
кой именно операционной системой должна запускаться программа,
определяется компилятором, с помощью которого получена эта про
грамма. Программа может выполняться другой операционной сис
темой, если она поддерживает ту, для которой программа откомпи
лирована. Например, проrраммы, созданные для работы в MS-DOS,
успеiШiо выполняются в Windows (причем, иногда даже лучше, чем
в самой MS- DOS). Для откомпилированных про грам м можно ввести
деление по операционным системам, под управлением которых они
выполняются (например, под MS-DOS, Windows, OS/2 или Uпux).
•
Интерпретируемые программы - программы, выполняемые специальной программой - интерпретатором.
Особенностью интерпретируемых програ;\fм, в отличие от откомпилиро�
ванных программ, является понижешюе быстродействие и необходимость
паличия выпоJшяющей среды (интерпретатора). Это, безусловно, сужает
область их применения, а тшоке накладывает дополнительные требования
на ресурсы компьютера, в связи с тем, что интерпретатор также является
программой, причем обычно очень требовательной к ресурсам. Однако ин
терпретируемые программы получают ряд дополнительных возможностей,
недоступных откомпилировшшым программам, таких, ншrример, как ди
намическое изменение исходного текста программы самой программой во
время ее выполнения.
Откомпилировапная исполняемая программа может работать только в од
ной операционной системе, тогда как интерпретируемые работают в тех
операционных системах, для которых реализованы соответствующие ин
терпретаторы. Такой подход позволяет разрабатывать программу один раз
и выполнять ее под разными операционными системами без необходимости
каких-либо дополнительных изменений в исходных текстах.
Одним из примеров такого подхода является Java - язык программирова
ния, разработанный фирмой Sun. Программы, написанные нa java, выпол
няются практически под всеми операционными системами, так как широ
кое распростршrение Jаvа-программ, особенно в сети Internet, заставляет
разработчиков с ами х ОС реализовывать интерпретатор ] ava Q ava Virtual
Machine - виртуальная Jаvа-машина).
Компромиссным вариантом между откомпилировапными и интерпретируе
мыми программами является создшше нескольких компиляторов для одного
36
Глава 1 . Введен и е
языка программирования, но для разных операционных систем. Д анный под
ход сочетает в себе быстродействие откомпилировшшых программ и возмож
ность выполнения одной и той же программы без изменения исходных текс
тов под управлением разных опершJ;Ионных систем.
Примерам такого подхода служит система Delpru(Кylix фирмы Borland, в кото
рой програ1"мы, разработанные в Delphi для выполнения под управлением ОС
Windows, могут быть откомпилирова.IIЫ в Kylix для выпоmiеиия под ОС Unux.
П Р ОЧИЕ ПОКАЗАТЕЛИ
Одним из критериев выбора языка программирования может служить объ
ем зпшшй, необходимый для его использования. Нш1римср, при использо
вании специализированного языr<а программирования для создания СУБД,
разработчик должен обладать некоторыми знаниями построения баз дан
ных , а для разработки программ под ОС Windows, необходимо хорошо по
нимать сложную структуру Windows-нporpaмм и механ из м ы их взаимо
действия с другими програ.\1мами и операционн ой системой.
Наша цель - изучение основ проrраммирования на примере использования
Turbo Pascal 7 .0, разработанного фирмой Borland International - языка про
гра.\1мир ов ан ия высокого уровня и широкого назначения с объединенными
процессами компиляции и линковки. Получаемые в результате разработки
исполняемые программы являются откомпилированными и предназначены
для выполнения в операционн ой системе MS-DOS. Разработка програм
мных продуктов на Turbo Pas cal 7.0 требует минимальных знаний разработ
чика при довольно широких предоставляемых языком в озможн о стях , и по
этому данный язык идеален для начального изучения программирования.
В настоящее время програ.\1мные продукты для MS-DOS используются
редко и, соответственно, практически не разрабатываются. Подавляющее
большинство программ разрабатывается для Windows и Unix. Однако изу
чение программирования п од Windows или Unix осложнено немалым коли
чеством подробностей работы программ под управлением данных операци
онных систем. Поэтому, несмотря на отсутствие в MS- DOS возможностей,
предоставляемых современными операционными системами, разработка
программ в учебных целях для данной ОС наи более предпочтительна. Сам
Turbo Pascal разрабатыnалея для обучения школьников и студентов про
граммированию, поэтому легко поддается изложению по принципу �от
простого к сл о жн о му � , что делает его еще более привлекательным в качест
ве п ервого изучаемого языка прогр ам м ир ования.
Следует отметить, что, несмотря на свою простоту, Turbo Pascal в процессе свое
развития получил все инструменты, свойственные самым развиТЬIМ языка.\1
программирования широкого назначения для MS-DOS, и не уступает таким
профессиональным системам разработки программных продуктов как С/С++.
го
37
Turbo P a s c a l
7.0
И нтегри рова н н ая среда
разработч и ка Borland Pascal 7 . О
2 . 1 . В В ЕдЕН И Е
В предыдуп{еЙ главе мы выяснили, что процесс написания программы со
стоит в подготовке исходных текстов программы в одном или нескольких
файлах, их последующей компиляции в целях получения объектных фай
лов, а затем линковки объектных файлов для получения исполняемой про
граммы. Результатом этого процесса является создание исполняемой про
граммы из исходных текстов, содержащихся в нескольких файлах.
Практически всегда в процессе Iсомпиляции используются стандартные
подключаемые библиотеки фун кций - дополнительные файлы с исходны
ми текстами, созданными р азр аб отч и ком языка программирования, либо
третьей стороной. Для осуществления ко мпил яции исходных текстов про
грамм в исполняемые файлы используется компилятор (в стандартную
поставку Borland Pascal 7.0 входит программа-компилятор t p c . е х е (пра
вильное название - компилятор командной строки)).
Структура файлов в программе является иерархической, то есть одни фай
лы с исходными текстами ссылаются на другие. Соответственно, для того,
чтобы полностью откомпилировать программу, состоящую из нескольких
файлов (модулей), необходимо откомпилировать сначала те модули, кото
рые не ссылаются на другие, зате м те, которые ссылаются на уже отком
пилированные, и так далее, пока не будут получены все объектные файлы,
необходимые для построения исполняемой программы.
Естественно, что по мере роста объемов исходных текстов программ, програм
мнету все труднее держать в голове иерархическую структуру программы.
38
Глава 2 . И нтегрированная среда разработчи ка Borland Pascal 7 . 0
Еще труднее данный процесс становится, когда программнету приходится
р аэр аб аты в ат ь несколько программных пр оду кт ов параллсльно, особенно,
когда их р аэр аботка производится не одним человеком, а н е сколькими , что
является наиболее распространенным явлением в современном программи
ровании. К тому же, ко мпилятор I<амандrюй строки имеет более 30-ти пара
метров, использование которых сильн о затруднено в условиях отсутствия
какого-либо ди ал о га Таким образом, использование компилятора в чистом
виде, без вспомогательных ср едств пе обеспечивают в ы с окую .
.
,
Также неудобно и использование обычных текстовых редакторов для созда
ния исходных текстов программ, так как большинство существующих ре
дакторов не пр едн а..'l н аче н о для программирования. К неудобствам, встре
чающимся при р або те в т е кстов ых редакторах, можно отнести:
•
отсутствие оперативного доступа к справочной информации по язы
ку проrраммирования;
•
н е обходим ость сохранения всех внесенных изменений перед нача
лом компиляции;
•
оши бк и при разделении файловых ресурсов между редакторами
программой-компилятором ( о б ыч н о такие ошибки появляются
при разработке п р о гр ам м ных пр одуктов в м н о гоз ад а ч ных опера
ц и о н ны х системах - Windows, O S/2 , Unix и т.д.).
и
Для решения вышеописанных проблем практически все современные язы
ки программирования снабжаются так называемыми интегрированными
средами раэ работчик а (Integrated Developer's Environment - IDE), вюrючающими в себя:
·
•
Средс т в а подготовки исходных текстов программ, аналогичные
стандартным текстовым редакторам, однако имеющие более ши
рокие возможности именно для подготовки исходных текстов про
гр ам м . К таким в о з м ожностям относятся:
( выделение ключ ев ых слов в исход
теr<стах программ цветом или шрифтом);
синтаксическая подеветка
ных
•
автоматическая загрузка ранее редактируемых файлов при пе
резапуске интегрированной среды, что позволяет сконцентриро
ваться на р аз р аботк е программнаго продукта и не терять время
на поиск всех не о бх одимых для работы файлов;
•
контекстная помощь ( вы зов раэдела справочной системы, соот
ветствующего редактируемому в да�шый момент фрагменту текста);
•
множество других
програ..\.f мисту.
п о лезн ых
функций, облегчающих работу
39
Turbo Pascal 7 . 0
•
Встроенный компилятор, позволяющий откомпилировать все исход
ные тексты программы с учетом ее иерархической структуры, не по
кидая интегрированную среду разработчика.
•
Встроенный отладчик, позволяющий провести отладку программы,
также не покидая интегрированной среды.
Turbo Pascal 7 .О имеет достаточно развитую интегрированную среду разра
ботчика, наделенную практически всеми вышеописанными достоинствами
стандартной интегрированной среды. К недостаткам данной среды можно
отнести ее исполнение в текстовом режиме, а также использование только
английского языка, как в самой среде, так и в справочной системе. Однако
использование текстового режима в значительной степени экономит ресур
сы компьютера, необходимые для работы ра..'lрабатываемых программных
продуктов, а отсутствие локализации, хотя и снижает привлекательность
интегрированной среды для российских проrраммистов, но, с другой сторо
ны, вырабатывает необходимые навыки работы с технической документа
цией, подавляющее большинство которой публикуется именно на английс
ком языке. Кроме того, облегчается и ускоряется переход к новым версиям
используемых программных продуктов в силу отсутствия необходимости
дожидаться их русифиr<ации. Большинство программистов вообще предпо
читают не использовать локализованные версии продуктов, используемых
в разработке, даже если таковые и имеются.
Одним из недостатков языка Turbo Pascal является отсутствие понятия про
екта, объединяющего множество исходных текстов и промежуточных файлов
в одну логическую сущность. Это может вызывать ошибки при сохранении
файлов под новыми именами, а также при хранении файлов с одинаковы
ми именами в разных каталогах. Это заставляет внимательнее относиться
к структуре разрабатываемой программы и держать в голове больше инфор
мации. Однако интегрированная среда разработчика, входящая в стандарт
ную поставку Turbo Pascal, в векоторой степени решает и эту проблему.
Далее мы рассмотрим подробнее особенности интегрированной среды раз
работчика Turbo Pascal 7.0, более близко ознакомимся с возможностями,
предлагаемыми данной средой, а также научимся настраивать некоторые
ее параметры для того, чтобы обеспечить большее удобство работы в среде
и повысить качество разрабатываемых программных продуктов.
2 . 2 . УСТАН О В КА BORLAN D PASCAL 7 . 0
Стандартная поставка (дистрибутивный набор) Borland Pascal 7 .О включа
ет в себя 1 2 9 файлов, размещенных на 12-ти дискетах, либо одном СD-дис
ке. Также к стандартной поставке прилагается обновление Borland Pascal 7 .О
40
Глава 2. И нтегрированная среда разработч и ка Borland Pascal7.0
до версии 7.0 1 , размещенное на отдельной дискете или в отдельном катало
ге СD-диска. Соответственно, установка производится в два этапа: установ
ка Borland Pascal 7.0 и установка обновления.
2 . 2 . 1 . УСТАНОВКА ВЕРСИИ 7 . 0
Установка Borland Pascal 7.0 осуществляется запуском файла i n s t a l l .
е х е , р азмещенного на первой дискете дистрибутивного набора дискет или
СD-диске. После запуска программы установки i n s t a l l . ехе на экран выво
дятся краткие сведения о програi\1ме инсталляции и предупреждение о необ
ходимом для установки пространстве на диске. Для установки полнокомплек
nюй версии Borlaпd Pascal 7.0 со всеми возможностями, необходимо не менее
29 Мб свободного места на том логическом диске, на который устанавливает
ся Borlaпd Pascal. Также при установке средств разработки Borland Pascal
for Wiпdows необходимо порядка 200 Кб на системном диске Windows.
1 . После запуска программы i n s t a l l . ехе для продолжения уста
lювки нажмите клавишу �Entcr».
2. Далее необходимо указать диск, с которого производится установ
ка, нажать клавишу �Enter», указать путь к дистрибутивным фай
лам и нажать �Enter» еще раз. Если вы используете стандартный
дистрибутивный набор, не следует изменять данные параметры.
3. На экране появилось главное меню програ;\1мы инсталляции, поз
воляющее изменять состав устанавливаем01·о продукта и располо
жение отдельных его частей на диске (дисках). Главное меню инс
таллятора приведено на рис. 8. Изначалыю программа инсталляции
настроена на установку полной версии Turbo Pascal. Поэтому можно
перейти сра:-�у же к нун кту 5. Если же на машине недостаточно места
для установки полной версии (а усеченная версия Turbo Pascal 7.0,
облад.ающая всеми возможностями для работы в MS-DOS, занима
ет около 400 Кб) или по каким-либо причинам не должны устанав
ливаться некотор ые компоненты, можно воспользоваться гл ав ным
меню для изме нения состава устанавливаемого продукта .
..
·.
•. · ·· < . • • . . .
: в ьг}аnd . Past al d i r e c;tory '' . . : C' \;B POZ
�--' . . >
:,,:wi f! d_ow_s . < D:�_ r.ec :t�r.y��-:.� ·· ' : ,:, .
.;.: ; :::_ C_ - � - \�:r.NDQ�/s· .
Prq�:� r: am Man ag (:! г Gr.oup . ,
C:reaj;e :, . . . ·' · . • . . . , .
· ·
.
•
':
[ I)Qs' DPI4I wi n d o�ls
нos.t P l atfor:ms c · · · .
. · тarget Plat.foпns< <; · : :> : ·. [ .DQs· РРI'Ч , l'li i'J<jows.
, . ;_-�_:
. ·· . · . · · ·
] ;
]. ?
•
·
::
. ,
,
Рис . 8. Главное меню программы инсталляции
Turbo Pasca/ 7. 0
41
Turbo Pascal 7 . 0
4.
П ер см ещение по главному меню программы установки осущест
вляется клавишами-стрелками на клавиатуре, выбор различных
пунктов меню - кл ав и ш ей En te r, выход из под м еню в меню более
высокого уровня - клавишей E s c.
5. После установки всех необходимых параметров выб ер ите пункт
главного м еню S tart Ins tal lation и нажмите клавишу Enter,
далее следуйте указаниям программы установки.
ПУНКТЫ ГЛАВН ОГО МЕНЮ ПРОГРАМ МЫ УСТАНОВКИ
В гл авно м меню установки доступны следующие пункты:
•
Borland Pascal directory - вызов диалога вы б ора каталога, в кото
рый будет устанавливаться Turbo Pascal .
•
Windows Directory - вызов диалога изменения пу ти к к атал огу со
держащего системные файлы Windows. Изменение данного каталога
имеет смысл, если на данной м аш ин е будет пр о изв одит ься р азр абот
ка Win dо\v s приложе н ий
,
-
.
•
Program Manager Group - выбор возможности создания группы
программ на Рабочем столе Windows, сод ер ж аще м ярлыки ко всем
устанавливаемым программам ( Create - создавать группу про
грамм, Don't Create - не создавать) .
•
Host Platforms вьшов диалога вы б ор а интегрированных сред, в ко
торых б уд ет производиться разработка ваших программных продук
тов. В диалоге можно в ключитъ или выключить устан ов ку ф айлов
Tu rbo . е х е (интегрированная среда для построения Приложепий
реального времени), В Р . е х е (интегрированная среда для построения
приложений реального времени, приложений, в ып олняемых в за
щищеююм режиме, а также Windоws-приложений) и BPW . е х е (ан а
лог В Р . е х е , н о сама среда является Win d оws приложени ем)
--
-
•
.
Target Platforms - в ыз ов д и алог а в ы б ора пл атфор м , для которых
предполагается р аараб отка соб с тв енных пр огр аммных продуктов .
Диалог позволяет включить в спи сок устанавливаемых файлов не
обходи мые модули для написания D О S - п р илож ен ий реального вре
м ен и (Real Mode DOS support), D О S пр и лож ен и й , выполняемых
в з ащищ е нн ом режиме процессора (Protectcd Mode DOS (DPMI)
support), а т акже Wiпdоws-нриложепий (Windows support).
-
•
Product Component Options
вызов диалога настройки состава
д анн ом диалоге уже будет отклю
чена установка tiекоторых компонентов, соответствующих отклю
ченным в пункте меню H o s t P l a t f o rms интегрированным средам
и отюпоченным в пункте T a r g e t P l a t f o rm s платформам разра
ботки. Диалог настройки состава компонентов позволяет изменять
состав следующих групп компонентов:
-
у ст ан ав ливае м ых компонентов. В
42
Глава 2. И нтегрированная среда разработч и ка Borland Pascal 7 . 0
•
•
Command Line Compilers - компиляторы командной строки;
Online Help Files - файлы справочной системы, встраиваемой
в интегрированные ср ед ы р азработки вы бр анны е в пункте Host
Platforms;
,
•
Application Frameworks/Libraries - стандартные подключаемые
б и блио т еки для поддержки построения программ для пл атформ,
вы бр ан ных в пункте T a r g e t P l a t f o rm s ;
•
Turbo Debugger for DOSjWindows - набор о тл адчиков под раз
личные платформы, выбр анны е в п ункт е Target Platforms;
•
•
•
Windows based tools - наб ор специальных инструментов, подде
рживающих некоторые д о полнит ельны е возможности Windows;
DOS based tools дополнительные инструменты для написания
пр огр а."\rм под DOS;
-
Miscellaneous source code files - набор и сх одны х кодов стандар
библи о т ек Turbo Pascal 7.0;
тных
•
Online Documentation - краткая документация по некоторым
компонентам Тш·Ьо Pascal.
•
Example Options - вызов диалога настройки состава примеров для
компонентов, выбр анных в предыдущих пунктах меню.
•
Directory Options - вызов диалога настройки установочных ката
л огов практи<Iески для каждого комп он ент а выб р анн ого в предыду
щих пунктах.
,
2 . 2 . 2 . УстАновКА оБновлЕния BoRLAND PдscAL 7 . О
Запустите файл i n s t a l l . b a t из ком анд н ой строки D O S со следующими
параметрами:
•
•
К ат ал ог в ко т орый установлен Borland Pasca\ 7.0.
,
Каталог, в котором находятся системные файлы Windows.
Н апр им ер :
C : \ > i n s t a l l . ba t C : \ B PW C : \Wi ndows
2 . 3 . ЗАПУС К И НТ Е ГР И РО ВАН Н О Й С РЕДЫ
Для запуска инт е гриро ванн ой сред ы р азр аб о тчика необходимо выполнить
одну из следующих проrрамм, в ходящих в станд артную поставку Turb o
Pascal 7.0: t urbo . е х е или Ь р . е х е . В целом они выполняют одни и те же
43
Turbo Pascal 7 . 0
функции, однако интегрированная среда, запускаемая программой Ьр . е х е ,
является более повой, соответствешю, она более требовательна к ресурсам
компьютера, но и предлагает более развитые возможности.
Эти возможности относятся не к удобству раб оты в самой среде, а к средс
твам компиляции программ, таким как построение проrрамм, исполняемых
в защищенном режиме процессора. Таким образом, начинающим проrрам
мистам рекомендуется аапускать интегрированную ср еду, используя файл
turbo . e xe.
Запускать данные программы можно любым доступным вам способом.
Например, в среде Windows, возможно использование меню Пуск или
Проводника (см. рис. 9), а также любой Nоrtоn-образной файловой обо
лочки, например Far Maпager. Если же вы работаете в операционной сис
теме MS- DOS, то запуск интегрированной среды удобнее всего произво
дить либо из файловой оболочки, либо из командной строки.
Рис. 9. Варианты запуска интегрированной среды ТигЬо Pascal
Вне зависимости от того, с помощью какого файла была запущена интегриро
ванная среда, экран монитора примет вил, показанный на рис. 1 О. Основные
44
Глава 2. И нтегрированная среда разработчи ка Borland Pascal 7.0
компоненты интегрированной среды - это главное меню, находящееся в вер
хней части экрана, строка оперативной подсказки, находящаяся в нижней
части экрана и Рабочий стол, занимающий всю остальную область. О строке
оперативной подсказки стоит сказать только то, что в ней отображается
краткое описание действий, которые вы можете выполнить в данвый момент,
а также описание пункта меню, на котором в данный момент находится под
сnеченный указатель. Рабочий стол и главное меню заслуживают более под
робного описания.
Рис. 1 О . Интегрированная среда Turbo Pascal после запуска
2 . 4 . ВСТРО ЕН Н Ы Й РЕДАКТОР И НТЕГРИ РОВАН Н О Й С Р ЕД Ы
Рабочий стол представляет собой пространство, на котором может распола
гаться одно или несколько «окон» с исходными текстами разрабатываемой
проrраммы. В каждом окне редактируется текст одного файла, причем один
и тот же файл может быть открыт одновременно в нескольких окнах (хотя
делать это и не рекомендуется, в связи с частыми ошибками из-за несогла
сованности изменений, производимых с одним и тем же файлом в разных
окнах, но иногда это полезно для просмотра объемных текстов в нескольких
местах одновременно).
Окна с редактируемыми файлами могут иметь произвольные ра..1меры и по
ложение, а также частично или полностыо перскрывать друг друга. Работа
с окнами производится точно так же, как и в любой многооконной системе.
То есть, если при работе с интегрированной средой имеется возможность
45
Turbo Pascal 7 . 0
использования манипулятора мышь, можно передвигать окна с помощью
него, если же компыотср пе оборудован мьшiыо, либо она по каким-то при
чинам не работает, все дейетвия в интегрированной среде можно выполнить
с помощью главного меню и клавиатуры.
Интерфейс интегрированной среды тщательно продуман и реализован, ис
ходя из того, что пользователь будет использовать в своей работе преиму
щественно клавиатуру. В данном случае невозможно давать какие-либо со
веты, все зависит от личных предпочтений пользователя.
Итак, все пространство Рабочего стола занимает встроенный многоокон
н ый текстовый редактор иiiтегрированной среды, и м ею щий следующие ос
новные возможности:
•
•
быстрое переключепие между окнами с исходными текстами про
граммы без необходимости сохранения предварительно внесенных
изменений ( см. описание пупктов главного меню Wi ndow 1 N e x t ,
W i ndow 1 P r e v i o u s ) ;
из мене н и е расположения и размеров окон для более уд о бн ой органи
зации работы (см. описание пунктов главного м е н ю Wi ndow 1 S i z e/
Move, W i n dow 1 Z o om ) ;
•
отмена вежелательных из м ен е ний в каждом из окон встроенно
го редактора (см. описание пунктов главного меню E d i t 1 Undo,
E d i t 1 Redo ) ;
•
распечатка отдельных файлов (см. описание пунктов главного меню
Fi l e 1 P r i nt, F i l e 1 P r i n t e r s e t up ) ;
•
эффективное управление расположением и именованием файлов
с исходными текста.'\!:И программы (см. описание пунктов главного
меню F i l e 1 S ave, F i l e 1 S ave a s и Fi l e 1 S ave a l l ) ;
•
использование внутреннего буфера обмена фрагментами текс
та между окнами редактора (см. описание пунктов главного м еню
E d i t 1 Сору, Edi t 1 Cut, Edi t 1 C l e a r и Edi t 1 Pa s t e ) ;
•
удобная навигация по исходным текстам, а также автоматизация по
иска и замены текстовых фрагментов (см. описание пункта главного
меню S e a rch ) ;
•
настройка параметров интегрированной среды для более удобной
работы, включая автоматизацию часто выполняемых действий и
визуального представления среды (см. описание пунктов главного
меню Opt i o n s 1 E nvi ronme nt 1 Edi t o r и Opt i o n s 1 E nvi r o nme n t
1 Colors ).
Таким образом, несмотря на то, что юперфейс интегрированной среды раз
рабатыnалея достаточно давно (более десятилетия назад), она им еет все
46
Глава 2 . И нтегрированная среда разработч и ка Borland Pascal 7 . 0
необходимые для р аботы возможности, свойственные современным анало
гичным с ист ем ам .
Стандартны й вид срслы разработчика с несколькими откр ы тым и в р ед акто
ре файлами пред став л е н на рис. 1 1 .
Рис. 1 1 . Рабочий стол интегрированной среды Turbo Pasca/
2 . 5 . ГЛАВ Н О Е М Е Н Ю
Все де йств ия, выполняемые иптсгрировашюй средой, могут быть произве
дены с помощью соответствующих пунктов главного м ен ю , расположенно
го в верхней части экрана и в ыз ывае мог о нажатием клавиши Fl O или вы
бором нужного пункта меню м ыш ью . Главнос меню со стои т из следующих
основных пунктов-разделов:
File
. . . . . . . . . . . . . .. .
в данном пункте главного меню представлены функции,
управляющие файлом, открытым в активном окне тексто
вого редактора интегриров анн ой среды - такие, как созд а
вие нового и откр ытие существующего файл а, сохранение
файла на диске, печать файла, а также выход из интегриро
ванной среды и д руги е вспомогательные функции. Более
подр о бно все пункты главного меню рассмотр ены ниже.
Edi t . . . . . . . . . . .. . . . . представлены функции р аб оты с б у ф ером обмена интег
рировашюй среды, а также функции отката ( о т м е ны )
вежелательных измен ени й .
Search .......... функции , упрощающие навигацию по тексту в активном
окне, таки е, как пои ск подстро ки и другие .
47
Turbo Pascal 7 . 0
Run
.................. функции выполнения и отладки программ.
Compile . . . . . . . .
DeЬuq
функции компиляции - процесса получения исполняе
мых файлов ( * . е х е ) из исходных текстов программ.
.. . . . . . . . . . . . функции, облегчающие
ладки программ.
и
оптимизирующие процесс от
Tools . . ... . . . . . . .. вспомогательные инструменты, выполняющие неi<ото
рые функции, не включенные в интегрированную сре
ду, либо обладающие более широкими возможностями
по сравнению с ней, такие к ак Turbo AssemЬler, Turbo
Debugger и другие.
Options
.. . .. . . функции настройки интегрированной среды, такие как
настройки компиляции, линковки, отладки, а также
визуального представления интегрированной среды на
экране.
Window . . . . . . . ... функции, необходимые для организации окон текстового
редактора на экране для более эффективной работы с ис
ходными текстами.
Help . . . .. . . . ... . . . . .
вызов различных разделов справочной системы, а также
контекстной помощи (автоматический поиск в справоч
ной системе слова, на котором стоит текстовый курсор).
Далее мы рассмотрим более подробно основные пункты главного меню ин
тегрированной среды. Полное описание всех пунктов вы можете взять на
сайте издательства www.nit.com.ru. Нумерация рисунков далее используется
по полной версии описания, так что рисунки с 2 1 по 26 в книге отсутствуют,
- они отражают наименее употребляемые пункты меню и приведсны лишь
в полном описании.
ПРИМЕЧАНИЕ.
В св язи с естественными ограничениями на о бъем нашего издания мы не бу дем
приводить о писание ра боты с некото р ыми диалогам и типа диалого в открытия
и со хранения фа йлов , считая , что вы имеете некото р ый опыт использо вания
ко м пьютера и раб оты в просте й ших текстовых редакто рах . Также не приводятся
редко используемые диало ги.
2 . 5 . 1 ПодмЕню FILE
Существует определенный набор действий, необходимых для работы с любы
ми текстовыми докумсiпаJ\Ш. Исходные тексты проrрамм, несмотря па неко
торую свою специфику, не являются исключением. Такими действиями явля
ются создание файлов, содержащих тексты, открытие файлов для просмотра
или редактирования (изменения), сохранение измененных и созданных фай
лов под разными именами, а также их печать.
48
Глава 2. И нтегрированная среда разработчи ка Borland Pascal 7 . 0
Под м ен ю Fi.le (см. рис. 1 2 ) используется для управления файлами с ис
ходными текстами программ и содержит следую щие пун кт ы :
New . . . . . . . . . . . . . . . . . создание нового файла (не со
держащего никакого текста) и
о т крытие его в новом окне, но
вое окно становится активным.
Open .. . .. .. ......... открытие в новом окне уже име
ющегося на диск е файла, новое
окно становится акти вным.
S ave .. . . . . . . . . . . . . . сохранение на диске файла, от
крытого в активном окн е . При
этом имя сохраняемого файла
Рнс. 1 2. Подменю
File главного меню
не изменяется. Д ан н ы й пункт
м е ню раб о тает только для от - интегрированной среды
Turbo Pascal
крытых файлов, а не с о зд анных
командой New. Для новых файлов команда S ave вызы
вает вместо себя команду S ave as (см. ниже ) .
S ave a s . . . . . . . сохранение на диске файла, открытого в активном окне.
При э том можно изменить название файла и его распо
ложение па ди с к е с помощью диалога, показанного на
рис. 13. Как и во всех диалогах и н т е грирован ной сре
ды, персмещение между элементами ин т е рф е йса про
исходит при н аж атии клавиши �таЬ:i> , вы б ор элементов
списка и нажатие кнопок - клавишей � Enter:i>, ввод
строковых значений произво
дится обычными символьными
клавишами клавиатуры. В д ан
ном диалоге следует с помощью
клавиши � Tab:i> вы б р ать окно с
параметром, который вы хотите
изменить (имя файла в верхнем
окне или его расположение на
диске в окне посередине диало
га), затем внести изменения, пе
реключиться клавишей 4: Tab:i>
на кнопку 4: 0 К:» диалога и наРнс. 1 3. Диалоговое окно сохранения файла
жать клавишу �Enter».
с новым именем
S ave All
.....
сохранение н а диске всех открытых в данный момент
файлов (во всех окнах, нрисутствующих на рабоче м
столе ) . Если в одном из окон, расположенных на рабо
чем столе, открытый файл не имеет имени, будет вызван
диалог S ave as ( см. выше).
49
Turbo Pascal 7 . 0
. изменение текущего каталога. Текущим каталогом явля
ется тот каталог на диске, из которого запущена интегри
рованная среда, либо каталог, указанный в качестве ра
бочего в настройках ярлыка на рабочем столе Windows
(или другой оконной операционной системы), если вы
запускаете среду с помощью ярлыка. Все файлы, необхо
димые разрабатываемой программе, будут считываться
из текущего каталога. Следовательно, если вы запускаете
интегрированную среду не
из того каталога, где хранит
ся ваша программа, может
возникнуть необходимость
сменить текущий каталог.
Смена каталога происходит
с помощью диалога, пока
заиного на рис. 1 4 . Каталог
можно задать в виде пути в
верхнем окне диалога, либо
выбрать с помощью дерева
каталогов, размещенного в
1 4 . Диалоговое окно изменения
текущего каталога
центральном окне диалога.
Change di r
Рнс.
Pr i n t
.......
.
.
.. . . распечатка файла, открытого в активном окне.
.
.
Pr i n te r s e tup
DOS
Ex i t
s he l l
....
... .
....
..
.....
...
вызов диалога пастроек печати.
вызов командной строки операционной системы. Данпая
функция применяется, в основном, при работе в опера
циошюй системе DOS для выполнения действий, не пре
дусмотренных в интегрированной среде (создание и уда
ление каталогов, запуск других программ и т.д.) . После
завершения работы с командной строкой, следует на
брать « Exit>-> и нажать клавишу «Enter» .
выход из интегрированной среды. Если в момент выпол
нения выхода из среды в одном из окон текстового редакто
ра находится текст, содержащий несохраненные измене
ния, то на экране появится диалог, показанный на рис. 1 5.
Рнс. 1 5. Диалоговое окно
сохранения изменений
50
Глава 2. И нтегрированная среда разработчи ка B orland Pascal 7 . 0
2 . 5 . 2 . ПодмЕню Ео1т
В процессе работы с исходными текстами програм:м, так же как и с любы
ми текстовыми документами, часто применяются следующие операции,
облегчающие и ускоряющие пр о ц е сс разработки:
отмена посл едн и х в н е с е нных в тексты изменений
и перенос информации из одного текстового доку
мента в другой.
Подменю Edi t (см. рис. 1 6) использу ется для упро
редактирования исходных текстов проrрам
мы, реализует операции отмены изменений, р аботу
с внутренним бу ф ером обмена текстовыми фраг
ментами интегрированной среды и содержит следу
ющие пункты:
ще ния
Рис. 1 6. Подменю Edit
главного меню интегриро
ванной среды Turbo Pascal
Undo . . .. ... . . . ... . . ... отмена изменений, произведенных в активном окне в обрат
ном порядке (от последнего изменения к первому) . Коли
чество изменений, которые можно отменить, ограниченно,
все изменения, произведенные в искотором окне, стирают
ся при сохранении файла, открытого в даmюм окне.
Redo . . . . . . . . .... . . . . отмена последней операции Undo или Redo. Данная воз
можiюстъ используется при ухудшении результата после
вызова команды Undo или Redo.
Cut . . . . . . . .. . .... . . . . . . копирование в буфер выделенного фрагмента текста с од
новременным удалением данного фрагмента с экрана. Бу
фером называется область памяти интегрир ов анн ой сре
ды, в которой в каждый момент времени может находиться
не более одного фрагмента текста. Выделение фрагмента
текста во всех интерфейсных элементах интегрированной
среды производится персмещением текстового курсора
по тексту в активном окне при нажатой клавише Shift
либо последовательным нажатием комбинаций клавиш
Ctrl-k-b в н ач але фрагмента текста, который необходи
мо выделить, и Ctrl -k-k в конце фрагм ента. Вне зависи
мости от метода выделения фрагмента текста его цвет
должен измениться.
Сору . . . . . . . . . . . . . . копированис в буфер выделенного фрагмента текста
без удаления данного фрагмента с экрана.
Раз te . . . . . . . . . . . . вставка фрагмента текста из буфера. Текст из буфера
будет встав л е н в п о з и ц ию курсора в ак т и в но е окно.
При этом сам текст остается в буфере и его можно и с
поль:ювать повторно.
Clear ............. удаление выделенного фрагмента текста без помеще
ния его в буфер.
51
Turbo Pascal 7 . 0
Show clipboard ... вывод на экран окна, содержащего фрагмент т::;кста,
находящийся в данный момент в буфере интегрирован
ной среды. Данный фрагмент текста можно редактиро
вать, результаты этого редактирования немедленно бу
дут отражаться на содержании буфера.
2 . 5 . 3 . П одменю SEARCH
Рис. 1 7. Подменю Search
главного меню
ин тегриро ванной
среды Turbo Pascal
Основными инструментами персмещения
по тексту, помимо обычных возможностей
скроллинга (пролистывания), являются
поиск конкретного текстового фрагмента и
переход к строке текста по ее номеру. Для
исходных текстов программ полезной яв
ляется функция персмещения внутри текс
та I< последней найденной синтаксической
или динамической ошибке.
Подменю S e arch (р и с. 1 7 ) используется
для навигации по тексту программы. На
иболее употребимы следующие пункты:
Find . . . . . . . . . . . . . . поиск строки текста в активном окне. Н астройки поис
ка устанавливаются в диалоге, показаинам на рис. 1 8.
В разделе Op tions можно указать (поставить галоч
ки) , что пр и поиске должен учитываться регистр букв
в искомом слове (Case Sensi tive) , поиск должен
происходить только по целым словам, а не по частич
ным совпадениям (Whol e words only), специальные
символы должны восприниматься как искомый текст
(Regular expre s s i on ) . Раздел D irection опреде
ляет направление поиска: вниз по тексту от курсора
( Fo rward) или вверх (Backward) . В разделах S cope
и Origin задается область поиска: производить поиск в о всем тексте ак
тивного окна ( Gl obal)
или только в выделен
ном фрагменте текста
( S e l e cted tex t ) , ис
кать совпадения тек
ста от курсора ( From
curs or) или во всем
тексте вне зависимос
ти от положения кур
сора (Entire s cope ) .
Рис. 1 8. Диалоговое окно поиска под стройки Fiпd
52
Глава 2 . И нтегри рованная среда разработчи ка Borland Pascal 7 . 0
П РИ М ЕЧАН И Е ,
Для ознакомл ени я со специальн ы м и с имволами , и с п ользуем ы м и nр и nои с ке, об
ратитесь к соответствующему разделу nомощи . Этот раздел вызывается при на
жатии н а кнопку ди алога поиска.
Replace . . . . . . . поиск строки текста в активном окне и замена найденных
вхождений на другую строку. Настройки замены устанав
л ив ают ся в диалоге, показанном на рис. 19. В осиовном этот
диалог повторяет диалог поиска, за исключением несколь
ких дополнительных возможностей. В раздел Options
добавлен пункт Запрос
на замену (Prompt on
replace), определяю
щий, необходимо ли за
давать вопрос пользова
телю перед изменением
найденного вхождения
на другую строку. Также
возможность
имеется
произвести замену не од
ного вхождения после
вызова диалога, а всех,
находящихся в установ
ленной области поиска
Рис. 1 9 . Диалоговое окно замены
подс тро йки Replace
(кнопка Change all).
Search again
....
повторение последней операции поиска или замены.
2 . 5 . 4 . Подменю RuN
Одними из самых важных операций, используемых в процессе разработки
программы, являются запуск программы на выполнение и ее отладка.
Подменю Ruп (см. рис. 20) используется для управления выполнением и
пошаговой отладкой прогр амм и содержит следующие пункты:
Run
................
S tep over
....
компиляция исходного текста программы, находяще
гося в активном окне и ее выполнение без пошаговой
отл адки.
пошаговое выполнение программы без захода в процеду
ру, на которой программа была остановлена в результа
те пmпаговой отладки (то есть процедура выполняется
полностыо и без пошаговой отладки).
53
Turbo Pascal 7 . 0
Trace into . пошаговое выполнение программы с заходом в процеду
vп,тп,,�,..,, т:. программа была остан овлена в результате
пошаrовой отладки (то есть процедура
также будет выполняться по шагам) .
.
.
Go to cursor . . . выполнение програм
мы до строки, в которой располагается
курсор, затем программа остапавлива
ется для пошаговой отладки.
.
.
Program res e t . . закрытие програм
мы, находящейся в режиме пошаговой
отладки без ее нормального завершения.
Ркс. 20. Подменю Run главного меню
.
..
Parameters . вызов диалога ввода параметров проrраммы. Использо
вание данной команды эквивалентно вызову программы
из комаилной строки с передачей ей параметров:
..
C : > \ S t ar t . exe 2 H e l l o Wo r l d
2 . 5 . 5 . Подменю WJNDow
Подменю Window используется для конфигурирования представления
окон текстового редактора интегрированной среды (наказано на рис. 27)
и содержит следующие пупкты:
Tile . . . . . подбирает расположение окон на экране таким образом,
чтобы все они были полностью видны. Это касается как
окон с исходными текстами программ, так и вспомога
тельных окон типа Messages и Wa tch.
...
..
.....
Cascade . . . . подбирает расположение окон на экране таким образом,
чтобы окна с исходными текстами располагались друг
над другом.
.
Close all
..
.
....
закрытие всех окон, присутствующих на экране. Если в
момент выполнения данной команды в одном из окон
имеются несохраненные изменения, то па экран будет
выведен диалог, показа1:1иый на рис. 1 5 .
Refresh di splay . . персрисовка интегрированной среды. Данная
команда применяется для полной перерисовки среды
в случае, если она была частично или полностью затерта
выполняемой программой.
.
S i z e/Move
54
...
переход в режим персмещения или изменения размеров
активного окна. Персмещение окна в данном режиме
происходит с помощью клавиш-стрелок на клавиатуре,
Глава 2. И нтегрированная среда разработчи ка Borland Pascal 7 . 0
изменение размеров окна - с
помощью тех же клавиш при на
жатой клавише Shift. Выход из
данного режима осуществляется
нажатием клавиши Enter.
Zoom . . . . . .. . . . . . . . . изменение положения и разме
ров окна таким образом, чтобы
оно занимало всю область рабо
чего стола. Повторный вызов
данной команды возвращает положепие и размеры окна в предыдущее состояние.
Рнс. 2 7. Подменю Window
главного меню
Nex t . . . . . . . . . . . . . . переключевне между окнами в врямом направлении
по списку окон (список окон формируется по мере их
открытия) .
Previous . . . . . переключение между окнами
по списку окоп.
в
обратном направлении
Close . . . . . . . . . . . . . закрытие активного окна.
Lis t . . . . . . . . . . . . .. . . вывод н а экран диалога управления окнами, позволяю
щего выбрать некоторое окно из списка окон, сделать его
активным или удалить с рабочего стола. Если в момент
удаления окна с рабочего стола в нем имеются несохра
ненные изменения, то на экран будет выведеи диалог, по
казаиный иа рис. 15.
2 . 5 . 6 . П одменю H ELP
Немаловажной фуикцией любой иитегрироваиной среды является н аличие
справочной системы и удобство работы с ней. Справочная система Turbo
Pascal 7 .О содержит описание всех инструментов, как самого языка программи
рования, так и интегрированной среды. Работа со справочной системой осу
ществляется одинаково, вне зависимости от выбранного раэдела. Каждый раз
дел представляет собой некоторый текст, снабженный ссылками (выделенными
цветом словосочетаниями), с помощью которых может осуществляться пере
ход к другим разделам справочной системы. Такая структура наэывается m
пертекстом. Выбор ссылки производится нажатием на нее мышью или подве
дением на нее текстоного курсора и нажатием клавиши <iEnteг�. Для возврата
из подра..�дела справочной системы в ранее просматриваемый раздел использу
ется комбинация клавиш <<Alt- F 1 �.
Подменю Help (см. рис. 28) используется для доступа к различным разде
лам справочной системы и содержит следующие пункты:
55
Turbo Pascal 7 . 0
Contents ..... вызов окна с оглавлением справочной системы. Из дан
ного оглавления можно попасть в любой раздел справоч
ной системы.
Index . . . . . . . . . . . . вызов окна
ф авиту.
с оглавлением
спр ав о чной системы по ал
Topic search . .. вызов контекстной помощи. Контекстная помощь
предлагает п олучени е р аздела справочной системы по
слову, на котором находится курсор в активном окне
текстового ред акт ор а. Контекстная помощь вызывается
выбором пункта Help 1 Topic search глав
ного меню или нажатием комбинации клавиш
«Alt- F1 � прямо в окне редактора. Если для
выбранного слова не существует раздела спра
вочной сист е мы , на экран будет выведено ее
оглавление (аналогичное появляющемуся при
выборе пункта главного меню H e l p 1 I ndex),
в ко т ор ом выделяется понятие, синтакси
чески близкое к т ому, по которому запраши
вается п ом ощь . Таким образ ом , контекстная
помощь я вля е т ся полезной для выяснения
причин появления некоторых ошибок ком
пиляции. Одна из таких ошибок - Unknown
Рнс . 28. Подмен ю Help
identifier (:неизвестный иденти фикатор)
mа вного меню
- появляющаяся в случае неправильного
написания команды или недоступности библиотеки,
в которой д а н н ая команда находится. При вызове кон
т е к стной помощи по неправильно набранной команде
в появившемся о гл ав л ении , скорее всего, буд ет выделе
н о правилыюе написание к о м анд ы . В случае прав ильп о
го написания команды, по недоступности библиотеки, в
которой о н а нах оди т ся , в появившемся разделе справоч
но й системы можно определить название библиотеки,
которую необходимо п од кл ю чи т ь. Например, программа
содержит команду W r i t e Len, яnляющуюся неправиль
но написанной командой W r i t e Ln. Подведя к данн о му
слову ку р с о р и нажав комб и нацию клавиш «Alt- F 1 � . мы
п ол учи м оглавление справочной системы, в котором бу
дет выделен пункт W r i t е Ln.
Еще одной распространенной причиной вызова контекстной помощи яв
ляется изучение параметров команды с некоторым именем. Д анн ая необ
ходимосп, возникаст nслсдстnис того, что названия команд запоминаются
человеком лучше, чем их nараметры, о которых нужно помнить больше ин 56
Глава 2. И нтегрированная среда разработчи ка Borland Pascal 7.0
формации: названия, порядок и типы данных.
Previous topic . . . вызов окна справочной системы
л ом , открытым пол ь з оват ел ем .
Usinq help
..
с последним разде
вызов окна справочной системы с разделом, посвящен
ным использованию самой справочной системы.
Files . . . . . . . . . . . . . вызов диалога конфигурирования справочной системы.
Диалог п оз вол я ет подключить к стандар тн о й справоч
ной системе дополнительные файлы (с расширенИем
* . tph). Необходимость в подключении дополнитель
ных файлов может возникнуть, н апри мер , при исполь
зовании подключаемых модулей сторонних разработчи
ков, снабженных собственной справочной системой.
Compiler directi ves . . . . . вызов окна справочной системы с разделом,
посвященным директивам компилятору.
Procedures and functions . . . вызов окна спр авочн ой системы с разде
лом, посвященным продедур ам и фун кция..ч Turbo Pascal.
Reserved words . . . вызов окна справочной системы с разделом, посвя
щенным ключевым словам, используемым при програм
мировании на Turbo Pascal.
S tandard uni ts . . . вызов окна справочной системы с разделом, посвящен
ным стандартным п одключаемым модулям Turb o Pascal.
Turbo Pascal Lanquaqe . . . вызов окна справочной системы
лом, посвященным языку Tttrbo Pascal.
Error messaqes
с
разде
...
вызов окна справочной системы с разделом, поевя
сообщениям об ошибках , возникающих при I<ом
пиляции програ...чм и их вып олн е нии .
щепным
АЬоu t
. .
... . . . .....
вызов
среды.
оюш
с
ин фор м аци ей о
версии и н тегрир ов ан н ой
Справочная система содержит много интересных и полезных сведений о ра
с интегрированной средой и языком программирования Turbo Pascal, н е
вошедших в нашу книгу, поэтому рекомендуем пользоваться ей не только для
поиска ответов на конкретные вопросы, но и просто для общего развития.
Turbo Pascal де йствительн о содержит все необходимое для разработки про
грамм для MS-DOS, но для эффективного использования его возможностей
ими нужно овладеть. Справочная система ---- --- самый простой пуТI. для этого.
боте
57
Turbo P a s c al 7 . 0
О с н о в ы п р о г р а м м и р о в ан и я
Мы приступаем к изучению основ программирования. Весь излагаемый
в дальнейшем материал, хотя и относится в основном к языку програм
мирования Turbo Pascal, вполне применим к программированию вообще
на любом языке.
Для начала дадим еще одно определение программы, более удовлетворя
ющее потребностям именно разработки, а не выполнения программы в ка
кой-либо операционной системе. Итак, с точки зрения программирования,
программа - это непрерыв ный поток команд, выполняемых операцион
ной системой от начала до конца
.
ПРИМЕЧАНИЕ.
П риведе и н о е определение ни в коем сл уча е не подменя ет определения п р о г рам
м ы , р ас с м отренн ы е в предыдущих гл а в ах . П росто он о более к о рректн о отр ажает
сущн о сть про гр а м м ы с то ч ки з рения е е р азр а б отки .
Таким образом, основным свойством программы является ее непрерывное
движение (выполнение) от начала к логическому завершению. Это опреде
ляется самим назначением программы - решением пекоторой задачи, под
разумевающей получение какого-либо результата. Это не значит, что про
грамма всегда будет выпо;шяться одинаково в заранее заданное количество
шагов и с одним и тем же результатом.
Результат выпо;шения задачи зависит обычно от данных, вводимых
пользователем, а количество шагов, за которое выполняется програм
ма и путь, по которому идет выполнение, определяются специальными
операторами зацикливан ия и ветвле ния. При этом некоторые команды
из состава программы могут вообще не использоваться в данном сеансе
58
Глава 3. Основы программирования
ее работы. Например, представим себе игру, в
которой надо пройти по лабиринту с ловушка
ми. Если игрок будет действовать правильно,
то ловушка не сработает. Таким образом, часть
программы, отвечающая за л о в уш r< у, выпошfе
на не будет.
Чтобы немного представить, что из себя пред
ставляет зацикливание и ветвление, обратимся
к рис. 29. Н а нем изображена пекоторая про
грамма, состоящая из шести команд. После вы
Рис. 29 . Логическа я схема
полнения команды 1 выполняется команда 2,
некоторой программы.
однако далее управление не обязательно пере
дается команде 3 , а может вернуться к команде 1 , а далее опять к коман
де 2. Такой вариант выполнения программы и называется зацикливанием.
После выполнения команды 3 управление может передаться команде 4 или
команде 5 - это называется ветвлением. Следует заметить, что зациклива
ние является одним из проявлений ветвления и на низком уровне реализу
ется именно так. Однако в языка.х высокого уровня для реализации зацик
ливания применяются специальные операторы.
Использование ветвления и зацикливания требует отдельного рассмотре
ния и описано ниже. А пока паши програ..\f мы будут выполняться последо
вательно, реализовывать заложенные в них возможности и сразу же после
этого заканчиваться.
3 . 1 . ОС Н О В Н Ы Е ЭЛ Е М Е НТЫ П Р О ГРАМ М Ы
И АЛ ФАВ И Т Я З Ы КА
Итак, проrрамма, написанная па любом языке программировапия, пред
ставляет собой набор �попятных»- к ом п и лят ору команд, а также парамет
ров, необходимых для выполнения этих команд (некоторые команды могут
использоваться без параметров ).
Основными элементами программы являются:
•
•
Операторы - команды, определяющие структуру программы (на
пример, операторы ветвления и зацикливания ) или выполняющие
какие - ли бо действия (например, арифметические операции или
операции сравнения).
Ключевые слова - команды, используемые обычно для отделения
одних частей програымы от других. Ключевые слова предназнача
ются для компилятора, теряются в процессе построения исполняе
мой программы, и не выполняются в прямом смысле этого слова.
59
Turbo Pascal 7 . 0
•
Директивы компилятору - аналогичны ключевым словам, но воз
действуют не на программу и ее структуру, а па процесс компиля
ции и построения проrр аммы . Ч асть директив компилятору можно
установить с помощью главного меню интегрированной среды или
параметров компилятора к омандпо й строки. Однако использование
д ир е кт ив в тексте программы помогает использовать их избиратель
но не для всей проrраммы, а тол ьк о для отд ел ьных ее частей.
•
Переменные и константы - внутренние структуры проrраммы,
преднаэначенные для хранения, персмещения и других видов рабо
ты с информацией.
Процедуры и функции - команды яз ы к а программирования, встроешrые в не го или добавлешrые раэработчи ко м для приобретения
программой необходимой функциональности.
роцедура :
:
Именно процедуры и функции обычно выпал:
nрацедура 2 :
нкция
:
няются в качестве команд; о которых мы гово
:
:
Процедуры и фуttкции
:
р и л и n предыдущем разделе. Последователь
5}�����
���:��::� - ность выполнения процедур и функций, то есть
Н ачал о
структура проrраммы, определяется операторами и ключевыми словаi\Ш, а характер выполне
ния одних и тех же процсдур и функций в раз
личных ситуациях задается п ер с м енны ми и кон
стантами .
•
·-----------------------·
1
'
�-�--ПеРёМёННыеико�ёТа��--�
На рис. 30 н аглядн о показано, как под влия
нием операторов и ключевых слов набор про
Н ачало
ц еду р и функций приобретает структуру, зна
:
- - -L - - 1
1
Функция 1
комую на.� по рис. 29. П р и этом изначально
:
- - - :r_- - ....1
имеется н абор разрозненных процедур и фун
:
1 - Фу';;'кция2 - 1
к
ций . Затем, с помощью использования опе
1
1 Функция З 1 1 Процедура 1
раторов и ключевых слов, этот набор приобре
!: - - - - 1:.r:
.....
niioЦeдyp
a2 1
:
тает определенную структуру (формируется в
- - - т - - -'
:
нец
программу)
. А потом, под в ля ни е м заданных
:
Ко
1
1
� - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - персменных и констант, программа приобрета
Рис . ЭО. Структурирование
ет нужную функциопалыюсть и соответствую
команд с целью получения
щим
образом выполняется.
программы.
1- - - 1
1
:________________________
1
1
_ _ _
.:_-.r. li'J.:..
_:1._�_-_-_-.....
ПРИМЕЧАНИЕ.
Разработч ики Turbo Pascal делят все элементы программ ы н а операции - коман
ды, выполняемые п рограммой , и оп еранды - структуры дан ных, с кото р ы м и рабо
тают операции . М ы будем использовать нашу кла сс и ф и кацию , как более удобную
для изложе н и я . Хотя слово «оnеранд» будет использоваться нами для описания
дан ных, с кото р ы м и работают, например, арифмети ческие операто р ы .
Все вышеперечисленные элементы программы имеют свои уникальные
имена, называемые иде11тификаторами, по ко т о р ы м и используются
60
Гл ава 3. Ос н о вы п р о гр а м ми ро ван и я
при написании программы. Например, один из операторов ветвления прак
тически во всех языках программировапия имеет имя i f, а оператор зациi<ЛИВ а
ния - for, арифметич еская операция сJюжения обозначается символом +, пе
ремеiПIЬrе и константы ш1еют имена, определяемые р азработчиком и так далее.
Для назначения имен элементам программы (то есть для создания иденти
фикаторов) используются:
•
латинские алфавитные строчные и пропи сн ы е символы от �а� до �z�
и от �л� до <�:Z�. а также символ подчеркив ания <�:_� и цифры (но только
не в начале им ени ) ;
•
знаки ари фм етич е ски х операций: �+$> (сложение), �-$> (вычитание),
� * � (умножение), <�:/� (деление);
•
символы логической и арифметической группировки: �<� и <�: ) �.
Существует еще множество других сп еци альн ых символов, рассмотрение
которых в данном месте преждевремепно. Их н а з начени е будет объяснено
ниже, в соответствуютцих раэделах. Здесь же надо отм етить одно правило,
которое следует з ап омни ть : все команды в Тurbo Pascal должны заканчи
ваться точкой с запятой .
Правила формирования имен элементов программы будет рассмотрено
в разделе, п о с вящ енн о м пе р е м енп ым .
Обычно команды обозначаются одним английским словом или сокраще
нием от нескольких. Н апри ме р , в яэыке программирования Basic для вы
вода ин формации на экран использу ет ся команда p r i n t (от англцйскоrо
слова P r i nt - п ечат ать ) , а в языке проrраммирования С/С++ - команда
cp r i n t f (сокращение от C on s o l e P r i nt Forma t t e d - печать на экране
с з аданн ым форматом). Turbo Pascal не является исiшючением, и в нем так
же, как и в большинстве языков проrраммирования, для записи команд ис
пользуется именно английский язык.
П РИМЕЧАНИЕ.
Существуют языки nрогра м м и рован и я , в которых команды заn исываются н е на ан
гли йском языке, а , наnример, на русском . Однако такие языки n рограммирования
не nолуч или ш ирокого расnространения и исnользуются в основном для целей
обуч е н и я . П ре и мущество м англ и йского языка для nрогра м м и рования я вля ется его
краткость и лаконичность, а также его фактический статус м еждународного языка.
Следует отметить, что сильный уклон н сторону английского языка ни в коем
случае не накладывает ограничения на присутствие русских или каких
либо других национальных символов в пользовательском интерфейсе. На
оборот, не рекомендуется использовать и н о с тр анн ы е языки в интер фейс ах ,
предпа.:шаченных для российских п ользователей. Это отрицательно влияет
на удобство работы с про грам м ой и, с о отв е тст в ен н о , снижает колuчество
потенцuальных польз ов ател е й программнога продукта.
61
Turbo Pascal 7 . 0
3 . 2 . СТРУКТУРА П Р О ГРАМ М Ы
Программа н а языке Turbo Pascal состоит из разделов, каждый и з которых
начинается специальным ключевым словом, характерным для конкретного
раздела:
Program
З а г ол о в о к nро гр аммы
Us e s
Р а з дел nо д ключ е ния модул е й - би бли о т е к
д о n о л ни т ел ь ных nр о ц е дур и фун кций
LaЬel
Ра здел оnи с а ния ме т о к безусло в н о г о
n е р е хода
Cons t
Р а з дел оnисания к о н с т а нт
Тур е
Р а з дел о n и с а н и я т и n о в д а нных
Var
Р а зде л о n и с а н и я n ер еме нных
Procedure
Function
Р а зд е л о nи с а ния n о дnр о гр амм - n р о ц е дур
и функций , с одержа щих н е к о т орые эл е м е нт ы
л о г и ки программы
Вegin
Н ачало ра здела оnи с ания логики про граммы
End .
Кон е ц р а зде л а оnи с а н и я л о г и ки n р о г р а ммы
Р а зд ел о nи с ани я л о гики n р о г р аммы
Const . . . . .
Туре . . . . .
Var . . . . .
Любую програ..\f му можно представить в виде
двух частей (см. рис. 3 1 ): командной, описы
вающей логику програ..'У мы (то есть действия,
которые могут выполняться программой), и
структуры данных, с I<оторыми работает ко
мандная часть.
Структура данных описывается с помощью
разделов
описания констант, типов данных и
Рис. 3 1 . Командная часть
переменных, начинающихся соответственно
и структура данных
с I<лючевых слов Cons t, Туре и Var. Команв программе
дная часть представлена разделом описания логики про:rраммы, разделом
описания процедур и функций, а также разделом описания меток безуслов
ного перехода LaЬel. К проrрамма.t\1 могут быть подключены специальные
модули (рис. 3 1 ). Эти подключаемые модули представляют собой набор
62
Гл ава 3 . Ос н о вы п рогр а м м и р ов ан ия
процедур и функций, а также данных, с которыми те работают. Поэтому
при подключении модуля к пр огр ам м е изменяется и структура данных про
граммы, и командная часть.
Практически все вышеперечисленные разделы программы не являются
обязательными. Более того, использование раздела LaЬel, например, во
обще не желательно. Единственным обязательным разделом является раз
дел описания логики програ.'\1мы, в котором реализуется алгоритм решения
поставленной задачи. Данный раздел должен начинаться ключевым сл о в о м
Begin и заканчиваться ключевым словом End с точкой после него.
Ключевые слова, которыми начинаются разделы, уrсазываются только в том
случае, если соответствующий раздел содержит какую-либо информацию.
Например, если к программе необходимо под кл ю чи ть модуль, то следует
указать ключ е во е слово Uses и название подключаемого модуля, а если
модули не подключаются вообrце, то и ключевое слово Uses указывать не
нужно. Это относится и ко всем остальным разделам (кроме раздела описа
ния логики программы) .
Несмотря п а нсобязателыюсть раздела Program, в ес таки рекомендуется
включать заголовок во все программы. Заголовок программы не использу
ется в процессе выполнения программы и вообще теряется в процессе ее
компиляции и линковки, но зато позволяет при открытии исходного текс
та быстро о пр едел ить что эта программа делает. В данном разделе должно
присутствовать всего одно слово - название программы. Правила составле
ния имен вообще и для программы в частности описаны ниже при обсужде
нии перемепных и констант.
-
,
Более подробно на кажд о м из разделов программы мы о ст ан о вимся ниже,
а пока рассмотрим, как написатr,, сохранить и выполнить простейшую про
гра.'\1му, со стоя щую всего из одн ого раздела - раздела описания логики про
граммы.
3 . 3 . П РОСТ Е Й ШАЯ П РО ГРАМ МА
П ИШЕМ ТЕКСТ
П РОГРАММ Ы
Итак, обязательным разделом nрограммы на Turbo Pascal является раздел
описания логики програ:ммы. При этом все остальные разделы использо
вать не обязательно.
П РИМЕЧАНИЕ.
Р а здел о п и с ани я л ог и ки про г рамм ы об ыч но на зы вают тел ом п р о г рамм ы . Хотя
м ы и не буд ем и с п оль з овать данн ы й термин , е го н уж н о п о м нит ь.
63
Turbo Pascal 7 . 0
Таким образом, простейшая программ а выглядит так, как в листинге 00 1 .
Begin
{ начало р а з д е л а опис ания л о гики пр о гр аммы }
End .
{ к онец раздела опи с а ния ло гики пр о гр аммы }
Данная программа успешно компилируется, стр оится и выполняется, но
ничего не делает. Несмотря на то, что и так понятно, что делает програ:м:ма,
стоит добавить к ней заголовок в виде кл ю чев о го слова Proqram и назва
ния программы. В качестве названия программы мы в ы б ер ем словосочета
ние Simple Program (простейшая прогр амм а) Более п одр об но правила на
значения имен элем е нтам программы описаны ниже, а пока заметим, что
имена ие могут содержать пробелов, иначе компилятор распознает такое
имя как два слова, поэтому s imp l е P r o g r am п рид ется написать без пробе
ла между словами: S i mp l e P r o g r am (см. листиш 002).
.
Program
S imp l e Program;
{ з аголовок
имя
проrраммы ,
проrра..'1МЬ!
-
Simp l eProgram}
Begin
{ начало р а здела описания ло гики пр о гр аммы }
End .
{ к онец р а з д е л а опис ания л о гики пр о rр аммы }
СОЗ ДАЕМ , СОХРАН ЯЕМ И ЗАПУСКАЕМ ПРОГРАММУ
С ПОМО ЩЬЮ И НТЕГРИРОВАННОЙ С Р ЕДЫ
Теперь рассмо т р и м на данном прим ере как раб о т ать с интегрированной
средой для напи сания, сохранения и выполнения программы:
,
Шаr
1 . З апустит е интегрированную среду. Возможные варианты запуска
среды описаны в рааделе, посвященном интегрированной среде.
Шаг 2.
Если интегрированная среда з апущ е н а в п е рв ы й раз после ее уста
новки, на рабочеl\I столе буд ет размещено всего одно окно текстово
го редактора, не содержащее никакого текста. В заголовке этого
окна находится имя файла, о ткр ыт ого в нем - NONAMEOO.PAS
это аначит, что данный файл еще нигде не сохранен.
-
Шаг 3.
среда запускается не в первый раз и установлено автосо
ранение настроек рабочего стола (с помощью пункта главного
меню Options i Environmenti Preferences ), то на рабочем столе будут
открыты окна с файлами, которые р ед акти р ов ались в т еч е н ие про
шлого се ан с а р аб оты со с р едой В этом случае н ео бходим о нажать
клавишу • F 1 0 $> для вызова главного меню, с помощью клавиш
стр ел ок подвести подсвеченный ука затель к пункту меню File, наЕсли
х
.
64
Глава 3. Ос н ов ы n рогр а м м и ров ани я
жать клав ишу �Enter� . и в появ и в ш емся меню выбрать пункт New.
Результат будет таким же, как и в предыдущем пункте - откроется
пустое окно текстового редактора.
Шаг 4.
Шаг
Наберите програм:му, представлен н ую в листинге 002 в пустом
окне текстового редактора, проверьте ее на наличие ошибок: клю
чевые слова Program, Begin и End должны быть окрашены бе
лым цветом. Если цвет какого-либо из этих слов не изменился (ос
тался желтым), оно н абрано неправильно. S i mp l e P r o g r am
должно быть написано в одно слово - без пробела. После ключе
вого слова End должна стоять точка. Комментарии, находящиеся
справа от про граммы и заключенные в фигурные скобки, набирать
не обязат е льно. После названия программы S imp l e Prog ram
должна стоять точка с запятой.
5. Сохрани ть п р ог рамму можно в любое время работы с ней. Однако
рекомендуется делать это перед каждым ее запуском, так как во вре
мя выполнения программы может произойти �зависание� компью
тера, и в этом случае сохранение программы будет уже невозможно .
П РИ М ЕЧАНИ Е .
Д е й ств ительн о , реко мендуется сохранят ь п р о г рамму п еред кажды м ее з апуском ,
особе н но , есл и с м ом ента п редыдущего сохран ен ия в н ей п р ои з в еде но м ного
изм е не н и й . Од нако н е стоит устанавл ивать соответствующую н астро й ку среды
Editor files (это м ожн о сделать с п ом ощью пун кта главн ого м ен ю Options 1 Environ
m eпt l Preferences) . Это мож ет п р и вести к сохран ен и ю нежелател ьн ых изм е н ени й в
п р ограмме . Сохран я йте файл ы перед запуско м вруч ную - н ажати е м клав иш и F2.
Если в ы рабо тае те с и нтегри рован н о й средой в сети , то в р езул ьтате с бо я в работе
сер в е ра также м ожет n ро и зойти зависание вашего ко м п ьютера. Поэтому хо ро шая
п ри в ы ч ка - сохранять редакти руем ые фай лы п осле каждого и з м е н е н и я ( п ри м ер но
п осле на бора или и сп равлен ия трех строк). П осч итайте сам и : чтоб ы нажа ть на кл а
в и шу F2 двести раз, нужн о n р им е р но дв е м и н уты , а чтобы восстан о в и т ь потеря н
н ы е изм е н е ния , которы е вн осил ись в тече н ие получаса, потре буется н е м е н е е пят
надцати м и нут, н е считая потрачен н ых н ер в о в и утомлен и я от н е нужно й раб оты .
Сохранение программы производится нажатием клавиши �F2� ил и
выбором пунктов главного меню File 1 S ave или File 1 S ave as
(см. описание соответствующих пунктов меню) . Вне зависимос
ти от выбран н о го варианта, при сохранении текста в первый раз,
на эк ра н е понвится диалог сохранения файла с новым именем
(см. о п иса н и е пункта главного меню File 1 S ave as ) .
При работе с Turbo Pascal необходимо назначать файлам имена дли
ной не более восьми символов, причем все символы должны быть
латинские (можно использовать символ подчеркивания: � � ). Рас
ширение файлов должно быть pas. Вне зависимости от регистра,
в котором используются символы, составляющие имя файла, его
имя в результате будет состояп> только из строчных символов.
_
3
Зах. 702
65
Turbo Pascal 7 . 0
В нашем случае можно назвать файл p s imp l e .p a s . После сохра
нения файла на диске, в верхней части окна, в котором он открыт,
появится его имя.
Шаr 6.
Теперь можно запустить программу. Данное действие производит
ся с помощью выбора пункта главного меню Run 1 Run или нажати
ем комбинации клавиш � ctrl-F9�. Если программа набрана непра
вилыю, то на экране появится сообщение компилятора об ошибке
(см. строку па красном фоне в верхней части экрана на рис. 32).
Например, в данном случае неправилыю написано ключевое слово
Begin - добавлена лишняя буква s .
Следует заметить, что сообще
ние об оши б ке, на первый
взгляд, не соответствует самой
ошибке (Begin expected
отсутствует ключевое слово
Begin), ведь слово Begin есть,
просто оно написано непра
вильно. Однако у компилятора
Рис. 32. Сообщение об ошибке компиляции
своя логика: он не пытается оп
ределить, что программист хотел написать, а ищет то, что должно
быть написано. В данном случае после заголовка должно присутс
твовать ключсвое слово Begin, а его нет, об этом информация и
выдается. Будьте внимательны при наборе программы, а в случае по
явления ошибок пытайтесь думать о причине их возникновения
формально - как это делает компилятор.
В случае отсутствия синтаксических ошибок программа успешно выпол
Iштся. При этом на экране ничего не появится, это можно проконтроли
ровать с помощью выбора пункта главного меню DeЬug 1 User s creen
или нажатия комбинации клавиш <<Alt-I•S � . Этот прием стоит запом
нить - в дальнейшем он нам часто будет нужен для просмотра того, что
программа вывела на экран. А пока з результате выполнения данной ко
манды мы увидим ту информацию, к от о р ая находилась на экране до за
пуска интегрированной среды. Для возврата обратно в интегрированную
среду следует нажать любую клавишу.
Итак, мы получили основные знания о том, что представляет собой про
грамма, написанная на языке Turbo Pascal. Мы также написали простейшую
программу, набрали ее текст, сохранили в файле на диске и выполнили, воз
можно, исправив появившисся ошибки. При этом мы сталкивались в ос
новном с ключевыми словами - Begin, End, Program - а также именем,
придуманным нами для на:шания программы - S imp l e P r o g r am. Далее
мы рассмотрим приемы работы с данными в программе и будем иметь дело
с персменными и константами.
66
Гл ава 3. Ос н о вы n рограмм ировани я
3 . 4. П ЕР Е М ЕН Н Ы Е
3 . 4 . 1 . ПОНЯ ТИЕ ПЕРЕМЕННОЙ .
КлАССИФИКАЦИЯ дАНН Ы Х, ИСПОЛЬЗУЕ М ЫХ В ПРОГРАММ Е
Программа создается для того, чтобы работать с какой-либо информацией.
С точки з рения программы все данные, используемые в ней, можно разбить
на три группы:
•
получаемые программой извне. К таким данным
относится вся ин формация, в водимая пользователем, а также вся ин
формация, получеiПiая по модему, от сканера или от каких-либо других
устройств.
•
Выходные данные
•
Внутренние данные
Входные да1mые
-
выдаваемые программой в результате ее рабо
ты. К таким данн ым относятся изображения на экране или принтере,
отправленные по модему данные, а также информация, сохраненная
на жестком диске.
-
это данные, хранимые программой в оперативной памяти с целью иреобразования входных данных в выходные.
-
Следует заметить, что не все входные данны е , полученные проrраммой, ста
нут внутренними. Например, при вводе пароля пользователем введенная
строка является входными данными, одн ако если параль введен неверно, то
программа не будет размещать данную строку в памяти. То же самое можно
сказать и про выходные данные. Программа, выдающая квадраты чисел, х:ра
нящихся в качестве внутренней информации, не обязательно должна хранить
еще и tами квадраты этих чисел, а может просто вычислять их при выводе.
,
ПРИМЕ'IАНИЕ.
На самом дел е , э т о н е с о в с е м т а к . Е с л и п р о г р а м м а что-л и б о в ы в одит, н а n р и м е р ,
на экран , то д а н н а я и н формация хран ится в оn ерати в н о й nамяти , то есть я вл я
ется внутрен н и м и дан н ы м и п рограм м ы . Но я з ы ки nрогра м м и р о в а н и я в ысокого
уро в н я скры вают от n р о гра м м и ста н екото р ы е nросте й ш и е о n е раци и и nозвол я ют
не задум ы в аться о то м , как эти о n е рации в ы n ол н я ются и где хранятся результа
ты их в ы n ол н е н и я . П р и наnисан и и n рограм м ы н а
Turbo Pascal совершен н о кор
ректно будет требование от n рограм м ы в ы вести на экран резул ьтат в ы ч и с л е н и я
в ы ражен и я 1 0* 1 0 . П р и э т о м n рограм м м ету н е нужно заботиться о то м , где будет
хран иться результат в ы ч и сл е н и я до его вы в ода.
На рис. 33 в общем виде показан
процесс работы прогр ам мы с инфор
мацией. Входпая информация пос
тупает в программу. Некоторая ее
часть становится внутренней (пока
зано толстой стрелкой), а остальная
Входная
информация
Рис . 33. СХема движения информации
в программе
67
Turbo Pascal 7 . 0
входная инфор м ация т еряется (тонки е стр е лки) . Далее внутр и программы
происходит изменение внутренних данных, о бусловл енное алгоритмом
программы. Затем, пекоторая часть внутренних данных становится выход
ными данными ( толстая стрел ка) остальные внутренние данные теряются
(тонкая с тр ел к а)
,
.
К работе с входным и выходным п отокам и информац ии мы пер ейд ем поз
же, а пока р аз бер е мся в том, каким именно обр аз о м программы хр анят свои
внутр енни е данн ы е .
Все внутренние данные программы хранятся в сп еци аль ных структурах,
называемых переменными. Переменпая
это п о им ен о в анн ая область
опер ативной памяти. Программа о бр ащается к п ер сменн ы м по их именам
(идентификаторам) и им е нно таким о бр азо м р аб от ает с дан ными Имена
пер с мен ных задаются программистом на этапе р азр аботки пр ограммы
-
.
.
3 . 4 . 2 . П РАВИЛА НАЗНАЧ ЕНИЯ ИМЕН
В Turbo Pascal используются следующие пр авила назначения имен:
•
Имена персменных должны пред ставл ять собой одно слово, состоя
щее из строчных или прописпых латинских символов, причем строч
ные и п р о пи с н ы е символы не различаются между собой. Также
д опус ти мо использование символа •подчерюша.ние� ( • _ �) и ци фр
в лю б о м месте имени, за исключением е г о н ачал а
.
•
Два ра..<Jных элем ента прогрЭJ'\1.МЫ не могут иметь одинаковые имена,
то есть имя, назначаемое п ерем енн ой должно быть уникальным в пре
делах програ.'\1 МЫ. В случае попытки опи сания н апри м ер двух пер с
менных с одинаковыми имена..\([и, компилято ром будет вьщана ошибка
Dup1ica te Iden tifier ( повторяющийся иденти фикатор ) В скобках
будет указано имя переменной, которая описыв ается повторн о .
,
,
,
.
•
Длина им ен и назначаемого лю б о му элементу п рограм мы не долж
на превышать 63-х символов.
,
,
Рассм отри м при м ер ы пр авил ь н ого
составления
имен переменных:
Name
А
В12
I sMyAge i s 1 4
MyName
А2
в 12
i smyage i s 1 4
My_Name
А4 1 4
В12
I s_my_age_i s_1 4
Теперь р ассм отр и м примеры испраrшлъпого составления имен переменных:
Beqin
68
. . . . .. . ..
является ключевым сл ов ом языка Pascal, поэтому имя
данной п ер е м енно й не удовлетворяет т р е бов анию уни
калыюсти в пределах программы.
Глава 3. Основы n рогра ммир ования
beqin . . . . . . . . . поскольку ТнrЬо Pascal не разл ич ает строчных и пропис
ных букв, это то же самое ключевое слово Beqin, просто
напи с анно е с маленькой буквы.
Мой Возрас'I:'
_
• • •
и мя
содержит не л ати н ски е символы.
Nam . е . . . . . . . . .
в имени п е р см е нн ой используется нсдопустимый символ - точка.
Му Name
и м я представляет собой два слова.
MyName
_
• • • • • •
имя начинается с символа п одч ер кивания
• • • • •
«_ »-.
1 2 I sМyAqe . . имя начинается с цифры.
.
П РИМЕЧАНИЕ.
Age м ожно вместо n е р в о й буквы А и сnользо вать рус
Частая о ш и бка - и сnользова н и е русских символов, n охожих п о наnисанию на ла
тинские, н а n р и м е р , в и м е н и
ский с и м вол . Визуал ьно nолуч е н н ы й результат н е будет отличаться от желаем ого ,
однако исnользование такого и м е н и н едоnуст и м о . Найдя та кое и м я в тексте nро
гра м м ы , ко м n ил ятор в ыдает ошибку Syntax error (с и нтаксическая о ш и бка ) . Во из
бежа н и е такого рода недоразум е н и й рекомендуется исnол ьзовать nрогра м м ы - ру
с и ф и катор ы , устанавл ивающие шрифты , в которы х наnисан и е русских и латин с ких
с и м вол о в разл ичается .
Не будем приводить пример слишком длинного имени, содержащего более
63-х символов, так как это не является грубой ошибкой. На самом деле, дли
на имени може т превышать 63 символ а и составлять, например, 95, но зна
чимыми все равно будут только первые 63. Э т о значит, что если две перс
менные с раз ными длинными именами с од ер ж ат в качестве первых 63-х
символов одну и ту же последователыюстъ, то эти персменные считаются
компилятором идентичными. Соответственно, при попытке описания вто
рой из этих переменной будет в ыд ан о сообщение о нарушении уникальнос
ти имени (Duplicate Identifier).
,
3 . 4 . 3 . Т ипы ДАнн ых
Все данные, с ко тор ым и работает программа, хранятся в виде переменных
областей оперативной п амя ти доступ к которы м осуществляется по имени.
-
,
Оп еративную память можно представить как массив ячеек, в каждой из ко
торых может храниться единица информации, наз ываем ая байтом. Вся ин
формация, хранимая компьюте р о м представляется числами, а одна ячейка
оперативной памяти может содержать одн о целое число от О до 255. Однако
языки программирования высокого уровня предо ст авл яют возможность
использования и чисел, больших 255, а также отдельных символов, строк и
еще множества других видов ин ф о рмации
,
.
69
Turbo Pascal 7 . 0
Мы не буд ем останавливаться на подробностях
хранения этих видов информации в памяти, а
только заметим, что для хранения разных видов
информации необходимо разное количество яче
ек памяти . На рис . 34 изображена схема опера
Рис. 34. Оп ера тивная память
тивной паi\1ЯТИ в виде совокупности ячеек (байкак совокупность я че ек.
то в). Разные виды информации могут занимать
разное количество ячеек (ячейки, заполненные информацией, закрашены).
Кроме того, некоторые ячейки могут быть свободны, то есть в данный мо
мент времени не с одержать инфор}.·fаi{ИИ (белы е ячейки на рисунке).
·
Для того чтобы автоматически выполнялось преобразование числовой ин
формации, хранимой в п ам яти , в вид, нужный программе, при описании
переменной компилятору необходимо указать, какого типа информация
находится в данной переменной.
Итак, переменвые описываются в разделе описания переменных, который начи
нается с ключевого слова Var. При этом указывается имя переменной и ее тип:
Var
< Имя п ер еменной >
< Т ип пер е менной > ;
П РИМЕЧАНИ Е .
Здес ь и далее треуг оль н ы е с ко б ки у ка зы ва ют н а н ео б ход и мость ис п ол ьзо ван ия
ка кого-л и б о иден т и ф и катора. Н а что и ме н н о с с ыла ется да н н ы й ид е н т и ф икато р ,
указы вает ся в н ут р и ск о б ок. Н ап рим е р , в п ри вед е н н о м н иж е оп иса н и и в м есто в ы
раж е н и я < И м я пере м е н н о й > долж ен б ыть ука з ан иде нти ф и като р , кото ры й в даль
н е й ш ем б уде т и с п ол ьзо ватьс я ка к и мя п ере м е н н о й . Э т о ка к р а з то м е сто в п ро
гр а м м е , н ач и н ая с ко то р ого да н н ы й иде нти ф и катор м ожет испол ьзо в ать ся , то е сть
нач ал о о бл а сти видимост и иденти ф и като ра .
В качестве Имени nеременной можно исполъзовать любое имя, соответс
твующее вышеприведенным правил ам , а Тиn nеременной может быть
следующим:
Byte . . . . . . . . . . . . . . . . каждая персменная данного типа может содержать одно
целое число в диапазоне от О до 255;
In teger
... . . ...
каждая персменная данного типа может содержать одно
целое число в диапаз о н е от -32768 до +32767.
Word . . . . . . . . .. каждая персменная д анного типа может содержать одно
цело е число в диапазоне от О до +65535.
Longin t
.......
каждая персменная данного типа может содержать одно
целое число в диапазоне от -2 1 4 7 483648 до + 2 14 7 483647.
Real . . . . . . . . . . . . . . . . каждая в ер см енн ая данного типа может содержать одно
вещественное число в диапазоне от -2.9 * 1 039 до 1 .7* 1 038•
Точность храпения чисел - 1 1 знаков после запятой.
70
Глава 3 . Осн о вы п р о граммир о в ан и я
Char
..........
значениями персменных данного типа являются одиноч
ные символы. В любой момент выполнения программы
в персменной данного типа может храниться только
один символ.
S trinq . . . . . . ... . . персменные данного типа содержат строки длиной до
255-ти символов. В целях экономии памяти можно после
названия типа S t r i ng указывать в квадратных скобках
максимальное количество символов, которое программа
будет хранить в описываемой переменной: s trinq [ 1 0 ] в данной переменной не может храниться более десяти
символов.
Boolean . . . . . . . . логические переменные, имеющие всего два значенця:
True (истина) и False (ложь).
В языке Turbo Pascal имеется еще множество разных типов. О некоторых
из них мы будем говорить ниже, а пока вполне достаточно восьми описан
ных. Рассмотрим примеры описания персменных (см. листинг 003).
Program
VarUs ing1 ;
{ з а г о л о в о к пр о гр аммы ,
А:
имя про граммы - VarU s i n g l }
{ на ч а л о раздела опи с аJrnя п е р еменных }
Var
Int eger ;
{ о пи с а ни е п ер е м ен н о й типа
I n t eger с и мен ем А }
Begin
{ начало раздепа описания логики программы}
End .
{ конец раздела опис ания логики пр о гр аммы }
Данная программа не содержит выполняемых команд (раздел описания
логики программы пуст). Однако, в отличие от простейшей программы,
она имеет потенциальную возможность работы с данными, структура кото
рых описана в разделе описания переменных, начинающимся с ключевого
слова Var. Структура данных состоит из одной переменной типа In teqer,
в которой в каждый момент времени при выполнении программы может
находиться одно целое число в диапазоне от -32768 до +32767 (см. опи
сание типа данных I n t e g e r) . Теперь рассмотрим более сложный пример
(см. листинг 004).
имя программы - VarUs ing2
Program VarUs ing2 ;
{ з аголовок программы ,
Var
{ начало раздепа описания переменных }
А:
V:
Int eger ;
{ описание п ер еменной типа
Real ;
{ опис ание переменной типа R e a l
Name :
String [ 2 0 ] ; { oпиc aни e п ер еменной типа
Name
и
I n t ege r с именем А }
с именем V }
S t r ing с именем
мак симальным р а змером 2 0
симв о л о в }
71
Turbo Pascal 7 . 0
Greeting :
String ;
{ опис а.ние
п ер ем е нн о й
типа
S t r ing с именем
Greet ing и максимальным размером 2 5 5
Ch :
UserAge :
симв олов }
{ о пис ани е п ер еменной 'l"Ипа Char с именем Ch }
Char ;
Integer ;
{ опис ани е п ер еменной типа I n t e g e r
с именем Us e rAg e }
Begin
{ н ачало ра здела опис ания л о гики пр о гр аммы }
End .
{ к онец р а з д ела описания л о гики про гр аммы }
Существует возможносп. описать н ескол ько персменных одного типа в од
ной строке. Такое описание выглядит следующим об р азом:
Var
<Имя переменной> ,
.
. . . . .
,
<Имя переменной>
:
<ТИП леременной> ;
Рассмотрим еще один пример оп и с ания персменных (см. листинг 005).
Program vaз:usingЗ ;
Var
а,
Ь, с:
xl , х2 :
{ з аголовок программы ,
{ опи с ани е
Real ;
с
Int eger ;
RootPr e s ent s :
имя программы -
VarUs ingЗ }
{ н а ч а л о р а з д е л а оnис ания лерем ен ных }
трех леременных
именами а ,
тиnа Real
Ь и с}
{ о пи с а ни е д вух пер еменных тиn а I n t e ge r
с именами x l и х2 }
Boo l e an ;
{ оnисание одной лер еменной типа B o o l ean
с
именем Ro o t P r e s ent s }
Begin
{ н ачало р а з дела опис ания л о гики лр о гр аммы }
End .
{ к онец р а з дела
опис ания л о гики nр о гр аммы }
В данном разделе мы научились описывать структуру данных нашей про
граммы. Сл едующий шаг -- з анесение д анн ых в о п и сан ную структуру и пе
ремещение их из одних персменных в други е .
3 . 4 . 4 . ОПЕРАТОР ПР И СВАИВАНИЯ .
С о вм Ести мост ь т и п о в ДАн н ых
ПРОСТЕЙШЕЕ ИСПОЛ ЬЗОВАН И Е ОПЕРАТОРА П Р ИСВАИ ВАНИЯ .
Совместимость ти пов
Оператор присnаивания позволяет придать пен:оторое значение переменной,
предварительно описанпой в разделе описания персменных Var. Оп ер ато р
пр исв аив ан ия всегда находится в разделе оп исания логики пр огр аммы или
является составной частью п р оц едур и функций, состоит из д воеточ и я и
знака �равно» и им е ет следующий вид:
72
Глава 3. Основы п рограмми р ования
: =
<Имя п е р еменной>
< З начение п ер еменной> ;
В качестве Имени переиенной должно использоваться имя одной из пере
менных, описанных в разделе Var, а в качестве З начения: переиенной
одно из следующих выражений:
•
Значение, соответствующее типу изменяемой переменной.
•
Выражение, результат вычислеция которого имеет тип, соответству
ющий типу изменяемой перемеппой.
•
Переменная, тип которой соответствует типу данной переменной.
С точки зрения оператора присnаивания типы Изие ня:еиой переиенной
и З начении: переменной считаются соответствующими друг другу, если
З начение переменной входит в подмножество возможных значений Из
иени:еиой переменно й . Тем не менее, в Turbo P.ascal существуют специ
альные средства (процедуры), позволяющие преобразовывать одни типы
данных в другие (подробнее о них читайте в следующих главах):
chr ......... преобразует символьное значение в числовое;
ord . . . преобразует числовое значение в символьное;
преобразует вещественное число в целое путем отсечения
trunc
дробной ч асти;
преобразует вещественное число в целое путем округления.
round
.
..
...
...
...
Рассмотрим примеры правильного и неправильного использования опера
тора присnаивания на примере (см. листинг 006).
Program As s i gnment l ;
{ з а г оловок прог р аммы ,
имя
пр о гр аммы - A s s i gnment l }
{ начало р а з д е л а опис ания пер еменных }
Var
R2 :
Rl ,
Real ;
{ опи с а н и е
двух
с именами R l
Il ,
I2 :
пер еменных
типа
и R2 }
Int eger ; { oпиc aниe д вух пер еменных типа
Rea1
I n t eger
с им е н а ми Il и I 2 }
B o o l e an ;
Rl i sMoreThanR2 :
одной
{ опис ани е
с
S t r i ng ;
S:
п ер еменной
им е н ем R 1 I sMor eThanR2 }
типа
B o o l ean
{ опис ание одной переменной типа S t r i ng
с им е н ем S }
Ch :
Char ;
{ опи с а ни е
одной п ер еменной тип а
Char
с именем Ch }
Begin
Rl
: =
1 . 25 ;
{ н ач ал о
р а з дел а
{ п еременная
опис ания
логики
проrр аммы }
Rl тип а R e a l мож е т иметь
в ещ е с т в енн о е значение }
73
Turbo Pascal 7 . О
R2
: =·
2 . 33;
{ л ер еменная R2 тиnа R e a 1 может иметь
в ещ е с т в енн о е з начени е }
R2
: =
3;
{ л ер е м е н н ая
знач ение ,
: =
R2
R1 ;
R2
Rea1
тиnа
хотя
в
памяти
хр аниться как в е щ е ст в е нн о е
{ в ещ е с т в енная
люб о е
может
данн о е
:
целое
будет
3 . 00 }
п ер еменная
R2
хр анимо е
з нач ение ,
иметь
з н а ч ение
может
в
принимать
п ер ем е нн о й
R1 ,
так как они имеют один и т о т же тип данных }
I1
: =
4;
{ л е р е м енн а я I l ти п а Int e g e r мож е т иметь
целое значение , так как оно входит в множество
в о зможных значений I n t e g e r }
I1
: =
4 . 38;
{ лер еменная I l
типа
I n t e g e r не м о ж е т
иметь в ещ е с т в енно е з н ач ени е }
I2
: =
10 ;
{ п е р ем е нн а я I 2 типа I n t e g e r може'I"
иметь цел о е знач ение
I1
: =
I2 ;
хр анимо е в п ер еменной I2
люб о е значени е ,
TOL'O
I1
: =
R2 ;
}
{ л ер еменная I l т иn а I n t e g e r мож е т иметь
ж е тиnа }
{ хотя з н ач ением п ер еменной R2 является
число 3 ,
то
ест
ь
в памяти оно хранится как 3 . 0 0 ,
каквеществ енно е ,
поэтому п ер еменн ой
I l нель з я прис в ои·гь данное з н а ч е ни е }
s
:=
' Россиs: ' ;
{ леременная S типа S t ri ng может иметь своим
зна ч ением с троку симв ол о в }
Ch
: =
'Z' ;
Ch
: =
' Россия ' ; { п еременная Ch типа Char не может иметь с в о им
Ch
:=
S;
{ п еременная Ch типа Char может иметь с в о им
значением один симв о л }
знач ением с троку
{ пер еменная
Ch
симв о л о в }
типа
Char
не
может
име т ь
с в о им
значением строку симв о ло в }
s
:=
10;
R 1 I sMoreThanR2
{ пер еменная
S
типа
String
не
может
. иметь
в качестве с в о е г о з нач ения число }
: =
True ;
{ п ер еменная Rl i sMor eThanR2 типа B o o l e a n
м о ж е т иметь в кач е с т в е с в о е г о з н ач ения
R 1 I sMoreThanR2
логич е с к о е з н а ч е ни е True
: =
( и стина ) }
15 ;
{ п ер еменная R l i sMor eThanR2 типа Bo o l e an
не может имет ь в качестве своего значения число }
R1I sMoreТhanR2
: =
I1;
{ п ер еменная Rl i s Mo r eThanR2 типа B o o l ean
н е мож етиметь в кач е с т в е с в о е г о з н ач ения
числ о ,
End .
с одержащееся в л ер ем енн о й I l тиnа I n t e g e r }
{ конец р а з дела опис ания ло гики пр о граммы }
В данном примере мы использовали оператор присв аивания в простейшем
вид е , когда в качестве нового значения изменяем ой пер ем енной использу
ется либо прямо задаваемое в тексте значение, либо значение другой пе
р е м енной . Отметим, что стр оконые (типа S t r i n g ) и символьные (типа
74
Глава 3. Основы програм м и ро вания
Char) значения указываются в одинарных кавычках. При этом значением
переменной в рсаультатс вьшшшсния оператора п р и с п аи в ания будет строка
(символ для персменных типа Cha r) без кавычек.
П РИ М ЕЧАНИЕ.
Есл и п оп ытаться зан ести в п еремен ную ти па Stri п g стро ку, содержащую оди
нарную кав ы ч ку, на п р и м е р , та к: А : = ' М ое имя ' М ихаил " , то ко м п илятор распоз
нает вторую кавы ч ку как закрывающую и в ыдаст сообще н и е о б отсутствии точ
ки с запято й , зака н ч и вающей оп ератор п р и с в а и ва н и я . Что б ы дан ная о ш и бка не
воз н и кала , рекоме ндуется испол ьзовать в знач е н и ях строковых и с и м в ол ь н ы х
п е р е м е н н ы х двой н ы е кав ыч ки , кото р ы е распознаются ком п илято р о м как обыч
н ы е с и м в о л ы : А : = ' М ое и м я " М ихаил'" . В случае н е обходи м ости и с п ол ьзован и я
и м е н н о оди н а р н о й кав ы ч ки в кач е стве знач е н и я п е р е м ен н о й , ее нужно н а п и
сать д в а раза подряд: А : = ' Мое и м я " М ихаил ' " , тогда две идущие п одряд оди
н арн ы е кавычки будут расп ознан ы как оди н с и м вол оди н а р н ой кав ы ч к и , я в л я ю
щи йся з н а ч е н и е м п е р е м ен н ой (константы ) , а н е к а к раздел итель н ый элемент
п р огра м м ы .
АР И Ф М ЕТИЧЕС КИЕ И Л ОГИ Ч Е СКИ Е ВЫ РАЖЕН И Я
В ОПЕРАТОРАХ ПРИСВАИВАНИЯ
Теперь рассмотрим примеры использования оператора присваивания, ког
да в качестве правой части (присваиваемого значения) используются ариф
метические и логические выражения.
Арифметическое выражение
это выражение, состоящее иа целочислен
ных или вещественных перемсш rых и числовых значений, соединенных
между собой арифметическими операторами сложения � + � , вычитания • - � ,
умножения � * • и деления �;�. Также допустимо использование скобок. При
оритет одн их арифметических операций над другими и измене ние приори
тетоn при использовании скобок в ари ф метических выражениях соответс
твуют обычным математичесr,им правилам. Н апр имер , значение выражения
1 0 * 2 0 + 1 8 составляет 2 1 8 , а 1 0 * ( 2 0 + 1 8 )
3 8 0.
-
=
При использовании арифметических выражений в качестве значений, при
спаиваемых перем ен ны м необходимо следить за типом результата этих
выражений. Например, при сложении двух персменных типа I n t e g e r, ре
зультирующ е е значение может выходить за пределы множества значений
типа I nt e g e r (см. листинг 007).
,
Program Incorr e c tAs s i gnment l ;
Var
Il ,
{ з аголовок программы , имя про граммы - I n c o r r e c tAs s i gnment l }
{ начало р а з д е л а опис ания пер еменных }
I2 ,
IЗ :
I nt eger i
{ описание 'l'p ex п ер еменных
с им енами I l ,
I2
и
·rипа
Int e g e r
IЗ }
75
Turbo Pascal 7 . 0
Beg i n
Il
{ н а ч ал о
: =
р аздела
о п и с а н и я л о г и ки пр о гр аммы }
пр и с в о е н и е п е р е м е н н о й I l з н а ч е н и я 3 0 0 0 0 }
30000 ;
{
I 2 значения 3 0 0 0 0 }
п р и с в о е н и я п е р е ме н н о й
I 3 з н а че н и я I l + I 2 = 3 0 0 0 0 + 3 0 0 0 0
60000,
выходяще г о з а пре делы множе с т в а т и п а I n t e g e r }
I2
: =
30000 ;
I3
:=
Il
+
{ пр и с в о е н и е
I 2 ; { п о пы т к а
п е р е ме н н о й
н е корр е к т н о г о
=
{ к он е ц р а здела о п и с а н и я л о г и ки п р о г р аммы }
E nd .
Еще одна особенность вычисления арифметических в ы р аж е н ий состоит
в том, что, если в нем используется деление, то результат выражения всег
да является вещественным числом, то есть тип результата такого выраже
ния будет Re a l , даже если деление может быть произведено без остатка.
Пример некорректной ситуации, связанной с этим, приведен в листинге
Program
As s i gnment2 ;
{ з а г оло в о к п р о г р аммы ,
I ncorre c t
I n c o r r e c tA s s i gnrne n t 2 }
I2 ,
I3 :
I n teger ;
{ описание
с
: =
30000 ;
I2
: =
30000 ;
I3
: =
I 1 / I2 ;
име н ами
трех
Il,
п е р еме н н ы х типа
и IЗ}
Integer
I2
{ начало р а з д е л а о п и с а ни я л о г и к и п р о гр аммы }
п е р ем е н н о й I l з н а ч е н и я 3 0 0 0 0 }
{ п р и с в о е н и е п е р еме н н о й ! 2 з н а ч е н и я 3 0 0 0 0 }
{ п о п ы т к а н е к о рр е кт н о г о п ри с в о е ни я п е р еменной
Begi n
I1
имя пр о гр а ммы -
{ на ч а л о р а здела о п и с а н и я п ер е м е нных }
Var
Il ,
008.
{ при с в о е ние
I3
зна
че ни я
Il/!2
=
3 0 0 0 0 /3 0 0 0 0
=
1 . 00,
вых о д яuщ г о за п р е д е лы множе с т в а типа I n t e ge r ,
та к
как
в выражении и с п ол ь зуе т с я д е л е ни е ,
с л е до в а т е л ь н о ,
тип
р е зул ь т а т а
а в т оматиче с ки с т а н о в и т с я Re a l }
в ыр а ж е н и я
{ ко н е ц р а здела о п и с а н и я л о гики п р о г р аммы }
End .
П РИ М ЕЧАНИЕ.
При поп ытке ком п иляции такой програм мы выдается ошибка Туре mismatch ( не
соответствие типов ) , поэто му ошибки такого рода п р о сто обнаружить и исправить,
в отличие от ош ибок в ыхода результата в ыражения за п редел ы диапазона возмож
ных значен и й , я вляющихся динамич еским и , то есть появля ющихся в п р оцессе вы
полнения п рограммы и зависящих от хода ее вы полнения.
Логические
выражения -
это выражения, состоящие из у с л о в и й и ло
( и ме ющ и х тип B o o 1 e an ) , соединенных м е жду со
операторами AND ( • И • ), OR ( 4 ИЛ И � ) и NOT ( •НЕ• ) .
гических персменных
бой логическими
Значение такого выражения имеет тип B o o 1 e an.
76
Условия, используемые
Глава 3. Основы п рогра м м и р ования
в л огич е с ких выражениях, состоят из п е р с м е нн ы х и знач е н и й , соединен
ных с помощью операторов условий � Б ОЛ Ь Ш Е • ( > ) , � МЕ Н Ь Ш Е• (<),
�РА В Н О » ( = ) , � н Е Б ОЛЫПЕ• ( < = ) , � н Е МЕНЫПЕ>> ( > = ) и �нЕ РАВ
Н О » (<> ) . Р а с см о т ри м несколько примеров условий:
10 > 5
10 < 5
2 0 >= 2 0
2 0 <= 2 0
У сл о в и е ,
У сл о в и е ,
Усло вие ,
з н а ч е н и е T ru e ( и с т и н а )
з н а ч е н и е Fa l s e ( л о жь )
з н а ч е ни е T r u e ( и с т и н а )
з н ач е н и е T r u e ( и с т и н а )
Усл о в и е ,
з н а ч е ни е
У сл о в и е ,
2 0 <= 1 9
Fa l s e
( л ожь )
Логический оператор AND для двух логических значений (значения , с к о
торыми работают любые о п е р ат о ры , называют операiЩами) возвращает
истинное зн ач е ни е ( т rue ) , если оба л ог ич е ски е значения истинны; е сл и
одно из значений ложно, то оператор AND возвращает значение Fal s e .
Н апример, в ы раж ен ие T rue AN D T rue является истинным (имеет значе
ние True ) , а выражение T rue AND Fa l s e - ложно. Следует з аметить, что
от перестановки операндов при использовани и логических о п е рат о р ов ре
зультат выражения не м е н я ет с я . Таким образом, выражение Fal s e AND
T rue
также ложно.
Оп ератор OR, также использующий два о п ер ан да, возвращает истинное зна
чение в случ ае , если хо тя бы один из операндов имеет истинное значение.
Н ап ри м ер , выражение T rue OR Fal s e является истинным, а выражение
Fal se OR Fal se - л ож н о .
Логический оператор NOT раб отает с одним операндом и в озвращае т значе
ние Fal se, ес л и операнд имеет истинное значение и принимает истинное
значение, если о п ер анд имеет зна•rение Fal s e . Таким образом, NOT T rue
=
Fal se, а NOT Fal s e = T rue.
Так же как и арифметические оп ер аторы , логические операторы имеют
п р иорит ет ы , определяющ;ие порядок выполнения операторов. Так, на
ивысшим приор и тет о м обладает о п ер ат ор NOT, затем идет оператор AND,
наименьший п р и орит е т имеет оператор OR. Н апри мер , выражение NOT
True AND Fal s e является ложным, потому что спача.тrа выполняется опе
ратор NOT : NOT T rue AND Fal s e = Fal s e AND Fal s e = Fal s e. Если бы
оператор AND выполня.Лся раньше о п ер атор а NOT , то з наче ни е данного вы
ражения было бы истинно: NOT T rue AND Fal s e = · NOT Fal s e = T rue.
Однако это не так. Также допустимо использование кругл ы х скобок для
и зм ен ен ия п оряд к а выполнения оп ерат ор ов : NOT ( T rue AND Fal s e ) =
NOT Fal s e
=
T rue .
Теперь р ассмотрим пр имер ы логических в ы р аже ний с использованием ус
л ови й и логических опе р ат ор ов :
(10 > 5)
AND ( 1 0 > 7 )
Логическое выражение, со стоящее из
истинных условий: ( 1 0
>
5)
и
( 10
>
двух
7).
77
Turbo Pascal 7 . 0
Соответственно, п о правила.-..r рабоn.т
тора AND, результат
(10 < 5)
OR
ние тru е .
(10 > 5)
Логическое
в ыр ажени е,
( 1о
>
р або ты
состоящее из двух
5 ) и истинного
) . Соответственно, по правилам
оператора OR, р езульт ат выражения
условий: ложного
( 1О
опера
выражения имеет значе
5
<
имеет значение True.
NOT
( 2 0 >= 2 0 )
Логическое выражение, состоящее из одного
истинного условия. По правилам
работы опе
р атора NOT, значение данного выражения
Fal s e .
В приведеиных ниже примерах (см. листинг 009) для присвоения значений ло
Bool ean) используются логические вы
гическим переменным (имеющим тип
ражения, содержащие условия, логические опер аторы и условные переменные.
Program As s i gnment 2 ;
{ з а г о л о в о к nр о гр аммы ,
ИJ!."..Я
nр о гр аммы - As s i gmnent 2 }
{ начало р а з дела оnис ания n ер еменных }
Var
Il ,
I2 :
Int eger ; { опис ание
двух переменных типа I n t e g e r
с именами I 1 и I 2 }
А:
{ опис ание п ер еменной типа B o o l ean с име н ем А }
Boolean ;
I lMoreThani 2 :
Boo l e an ;
{ оп и с ание
пер еменной
типа
B o o l ean
с
именем
I 1Mor eThan i 2 }
{ начало р а з дела опис ания л о гики программы }
Begin
I1
: =
10;
I2
:=
5;
I 1MoreThani 2
{ прис в о ение nеременной I 1 знач ения 1 0 }
{ nри с в о ение n ер еменной I 2
:=
(I1
>
знач ения 5 }
I2 ) ;
{ прис в о ение п ер еменной I 1Mor eThan i 2
логич е с к о г о выражения ( I 1
>
знач е ния
I 2 ) . данн о е выраж ение
ис тинно , т . к . 1 0 > 5 . Таким о бра з ом , I 1MoreThan i 2
име е т значение Tru e }
Il
: =
10;
I2
:=
20;
I 1MoreThani 2
{ nри с в о ени е переменной I l значения 1 0 }
{ прис в о ени е пер еменной I 2 знач ения 2 0 }
: =
(I1
>
I2 ) ;
{ при с в о ение переменной I 1Mo r eThan i 2
л о гич е с к о г о вь�аж ения ( I 1
ложно ,
т.к.
I 1Mor eThan i 2
А
: =
True ;
I 1MoreThani 2
: =
10
=
<
2О ,
Fal s e
>
с л е д о в а·г ельно ,
}
{ nрис в о ение nеременной А з н ач ения Tru e }
(I1
>
I2 )
AND
(А) ;
{ при с в о ени е переменной I 1Mor eThan i 2
78
знач ения
I 2 ) . Данн о е выраж ение
значения
Глава 3. Основ ы n рограм ми р ования
л о гич е с к о г о
(Il
выраж ения
>
I2)
(А) .
and
данн о е
вь-р аж ение ложно по пр авилам прим ен ения л о г ич е с к о г о
о п ер а т ор а AND ,
из
I 1MoreThani 2
: =
т.к.
(I1
(I1
>
I2 )
OR
=
Fa1 s e ,
т.е.
один
(А) ;
( пр и с в о ение переменной
ло гиче с к о г о
в ыр а ж ения
в ыр ажение и с тинно по
л о гиче с к о г о
т.е.
один
I 1Mo r eThan i 2
>
( I1
or
I2 )
з н а ч ения
(А) .
Данн о е
пр а в и л ам примен ения
опер а т о р а OR ,
из
операнд о в
( к о н е ц ра з д е л а
End .
> I2 )
операнд о в н е является и с тинным }
т.к.
А
=
T ru e ,
является и с тинным }
опи с а ния л о гики пр о гр аммы }
МЕХАНИЗМ РАБОТЫ ОПЕРАТОРА ПРИСВАИ ВАНИ Я
Работа оператора присnаивания состоит из двух последовательных этапов:
В ычисление выражения, ст оящего в прав ой части.
1.
2.
Присвоение переменной, стоящей в левой части, значения, полу-
ченного в пункте
1.
Таким образом, из-за того, что процесс присвоеимя состоит из двух разде
льных этапов, в левой и правой части оператора п ри с n аив ани я может нахо
диться одна и та же переменная. Расс м отр и м пример (см. л и сти н г 0 1 0) .
Program As s i gnment З ;
( з а г о л о в о к пр о гр аммы , имя пр огр аммы - A s s i gnment З }
( н ачало р а з д е л а
Var
I1 :
Int eger ;
Begin
I1
I1
: =
: =
( опи с ание
( на ч а л о р а з дела
18;
I1
+
12 ;
типа
Integer
( при с в о ен.ие пер еменной
I1
знач ения
I1
з н а ч е ния
п еременной
Т аким о б р а з ом ,
( I 1. + 1 2 )
в р е зуль т а т е
п ер еменная
=
с
именем
I1}
опис ания л о гики пр о гр аммы }
{ пр и с в о ение
к оманды ,
End .
опис ания п ер еменных }
п ер еменной
18 }
(I1
+ 12 ) .
в ып о л н е ния данной
I 1 п о луч а е т з н а ч ение
30}
( конец р а здела
опи с а ния л о гики пр о граммы}
Поясним кажущуюся некорректность выражения I1
: =
I1 + 1 2 . С точки
зрения математики такое выражение действительно недопустимо. Но оно
не является математичесi<и:м - это к ом анд а языка программирования, вы
полняемая в два этапа, на первом из которых прои сх од ит вычисление выра
жения, стоящего в пр ав о й части: I 1 + 12
=
3О,
а
на втором - присвоение
полученного знач е ния пе р еме нн ой I 1 . Таким образом, данное выражение
вполне корректно .
Отметим, ч т о вне зависимости от того, использовался ли оп ерат ор присваи
вания для занесения значения в п е рсм ен ную или нет, персменная все р ав н о
79
Turbo Pascal 7 . 0
будет иметь какое-либо значение. Это св язан о с тем, что ф изически пере
представляет с обой совокупность я ч еек памяти, в которых не мо
жет ничего не храниться. Таким образом, рекомендуется в нач ал е програм
мы инициализировать все персменные - заносить в них н е к отор ые
начальные значения. Обычно в к ач е с т в е начальных значений для числовых
пер с ме н ных (переменных т ип а I n t e g e r, B y t e и т.д.) используется значе
ние О, а для строковых - пустая стрш<а: ". Рассмотрим два примера: риско
ванное и сп о л ьзов ани е оператора присваивания и некорректное его исполь
:ювание (см. листинг 0 1 1 и 0 1 2).
менпая
ЛИСТИНГ 0 1 1 . РИСКОВАННОЕ ИСПОЛЬЗОВАНИЕ ОПЕРАТОРА ПРИСВАИВАНИЯ
Program As s i gnment 4 ;
{ з а г о л о в ок прогр аммы ,
Var
имя
пр о гр аммы - As s i gnmen t 4 }
{ н ачало р а з дела опи с ания пер еменных }
I:
Intege r ;
{ описание переменной типа I n t e g e r с име н ем I .
L:
Longint ;
{ опис ание пер еменной типа L o ng i n t с именем L .
З н а ч ение переменной н е и з в е с тн о }
З н а ч ение п ер еме н н ой н е и з в е стно }
Begin
L
: =
I
: =
опи с ания ЛОI'ИКИ пр ограммы }
{ на ч а л о р а здела
105 ;
{ пр и с в о ение переменной L з н ач ения 1 0 5 }
L;
{ прис в о ение переменной
I
з н ачения переменной L .
Данн о е при с в о ение к орр ектн о ,
переменной L
( 105 }
так к ак з начение
входит в мно ж е с т в о · в о зможных
з н ач ений типа I n t e g e r }
{ к онец р а з д е л а опис ания л о гики пр о гр аммы }
End .
Хотя приведенный пример и корректен пе рекомендуется использовать тако
го рода присвоения в своих программах, так как на этапе выполнения програм
мы в переменной типа Long i nt может оказаться число, выходящее за преде
лы множества допустимых значений типа изменяемой п е р еме нной Д анная
опшбка является динаl\-rической, зависит от хода выполнения программы, и,
соответственно, трудна в об наружении и исправлении. Одной из причин по
явления такого з нач ения в переменпой может быть отсутствие ее инициализа
ции. Именно такая ситуация продемонстрирована в листинге 0 1 2.
,
.
ЛИСТИНГ 0 1 2. НЕКОРРЕКТНОЕ ИСПОЛЬЗОВАНИЕ ОПЕРАТОРА ПРИСВАИВАНИЯ
Program Inc orre ctAs s i gnment З ;
{ з а г о л о в о к про граммы ,
имя
пр о гр аммы
-
I n c o rr e c tA s s i gnment З }
Var
I:
{ начало р а здела опис ания п е р еменных }
Int e ger ;
{ описание
переменной
типа
Int eger
с
именем
I .
с
име н ем
L.
Знач ение п ер еменной н е и з в е стно }
L:
Longint ;
{ описание
переменной
типа
L o ng i n t
З н а ч ение п ер еменной н е и з в е стно }
80
Гл ава 3. Основ ы п рограмм ирования
Begin
I
: =
L;
End .
{ начало р а з д ела оnис ания ло гики про гр аммы }
{ nрис в о ение nеременной I значения nеременной L .
Данно е прис в о ение нек орр ектно , так как значение
nер еменной L не и з в е с тно и, в о зможно , не
входит в мно ж е ст во в о зможных з начений тиnа
I n t e g e r . Наnример , з начение nеременной L мож ет
быть 5 5 0 0 0 , а данное число не может являт ь с я
значением n ер еменной тиnа I n t e g e r }
{ к онец р а здела оnис ания ло гики программы }
В этом примере во время выполнения оператора присnаивания I : = L з н ач е
L неизвестно и зависит от того, что находилось в ячейках
памяти, занимаемых данной перемешюй, до запуска программы. В боль
шинстве случаев данная переменпая будет содержать О, но могут возник
ние переменной
нутъ случаи, когда это не так.
Еще труднее будет обнаружить ошибку в случае использования неинициа
лизированной переменной в арифметическом или л огич еском выражении.
3 . 5 . КО Н СТАНТЫ
ОБЩИЕ ПОЛОЖЕНИЯ
Помимо персменных для описания данных в программе используются пос
тоянные выражения (константы) . Константы - это выражения любого до
пустимого в языке программирования ти па, определяемые программистом
на этапе написания программы и не меняющиеся в процессе выполнения
программы. Постоянные выражения, так же как и переменные, м огут иметь
имя, по которому используются во всех выражениях. Как и переменные,
константы имеют тип данных, х о т я обычно он
задается
не программист ом
,
а определяется автоматически компилятором.
Основным свойством постоянных выражений, отличающих их от пере
менных, является неизменность значения константы в о время выполнения
программы. Постоянные выражения получают свое значение на этапе напи
сан ия
п
р о гр а м м ы и
н е меняются в процессе выполнения
пр о гр амм ы
.
Более
того, константы вообще теряются в процессе компиляции и в исполняемой
программе оказывается только значение постоянного выражения.
Константы описываются в разделе описания констант, начинающемся с клю
чевого
слова Cons t.
Описание константы имеет следующий вид:
Const
<Имя к о н с т анты>
< З начение константы> ;
81
Turbo Pascal 7 . 0
В к а че с т в е Имени константы используется любое имя, уд о в л ет в ор яю
щее п р ав ил ам именования элементов программы, а в качестве З начении
Turbo Pascal , на
логическое. При этом тип постоянного в ыра
жения указывать не нужн о так как ко м п ил я тор м о ж е т опр ед е ли ть его само
стоятельно. Рассмотрим примеры о п и сан ия констант ( см. л и ст и н г 0 1 3) .
константы
-
любое выражение, тип которого допустим в
пример, арифметическое или
,
Листинг 0 1 З. ОписАние констАНт
Program C on s t ant s 1 ;
{ з аг о л о в о к nр о гр аммы , имя nр ограммы - C o n s t ant s 1 }
Con s t
{ начало р а з д ел а оnис ания конс тант }
iC1
=
10;
{ оnис ание константы с именем i C 1 и з н ач ением 1 0 .
Комnилятор
iC2
40000;
а в томатич е с ки
так
расnознает
тиn
как
n о с т оянн о е
данн о е
данной
константы
как
By t e ,
вь�а жение
(10)
является целым числом в интервале
О Т 0 ДО 2 5 5 }
{ оnис ание константы с именем i C 2 и з н а ч е ни ем
40000 .
Комnилятор а в т оматич е с ки р а с n о з н а е т тиn
данной константы как L o n g i n t ,
п о с т оянн о е выраж ение
числом ,
(40000)
так как данное
является ц е лым
не nоnад а е т в инт ер в а л з нач ений типа
I n t e g e r от - 3 2 7 6 8 д о + 3 2 7 6 7 ,
н о nоnадает
в инт ер в ал знач ений тиnа Longint }
R
1 . 0;
{ оnис ание константы с именем R и знач ением 1 .
Н е смо тря на т о ,
что константе nри с в аи в а е т с я
ц е л о е значени е ,
комnилятор автоматич е ски
р а с n о з н а е т тиn данной к о н с т анты как R e a l ,
как данн о е n о с тоянн о е в ыр а ж ение
(1. 0)
так
с од ер жит
д е сятичную точку }
Begin
{ начало р а здела оnис ания л о гики nр ограммы }
End .
{ к онец р а з д ел а оnи с ания л о гики nр оrраммы }
В этом примере константам присnаиваются простые значения, однако во з
можно описание констант, представляющих со бо й значения более сложных
выражений (арифметических и л и логических) , в т о м числе и
в своем составе другие константы (см. листинг 0 1 4).
содержащих
ЛИСТИНГ 0 1 4. ОПИСАНИЕ КОНСТАНТ
Program Con s t ant s 2 ;
{ з а г о л о в о к nр ограммы , имя nр ограммы - C on s t ant s 2 }
Con s t
iC1
{ начало р а з д ела оnис ания конс'I·ан·г }
=
10;
{ оnис ание константы с именем i C 1 и знач ением 1 0 .
Комnилятор автоматич е ски р а с п о з н а е •г ·rип данной
к о н с т анты как By t e ,
82
так как данн о е n о с т оянн о е
Глава 3. Основы п рограм м и ровани я
выражение
(10)
является целым числом в интервале
ОТ 0 Д О 2 5 5 }
4 0 * 2 0 0 0 ; { опис ание к о н с танты с именем i C 2 .
iC2
Компилято р
а в т оматиче ски р а сп о з н а е т тип данной к о н с т анты
как Long i n t ,
так как данн о е п о с тоянн о е выраж ени е
(40
80000 )
* 2000
=
является целым числом ,
не попадает в инт ер в а л допустимых з н а ч ений типа
Integer ,
но попадает в инт ер в а л з н ач ений типа
Long i nt }
i C2 / 1 0 ;
rС З
{ описание к о н с т анты с именем r С З ,
в выр аж ении ,
причем
nр едставляемом конс тантой ,
используется другая к о н с т анта .
Комnилятор
а в т оматич е с ки
д анной
как R e a l ,
расnознает
тиn
к о н с т анты
так как данн о е n о с тоянн о е выраж ение
( iC2 / 1 0 = 4 0
*
2000/10
в е щ е с т в енным числом
=
8000 . 00 )
является
( и з - з а nрименения
дел ения в выр а ж ении ) , и поnадает в инт ер в а л
д о пу с тимых знач ений тиnа R e a l }
S * rC З ;
rC 4
{ описание конст анты с имен ем r C 4 .
Комnилятор
автоматич е с ки р а с n о з н а е т тиn данной к о н с т анты
как R e a l ,
( 5 * rC 3 )
0 . 1*10 ;
RC S
так как данн о е n о с тоянн о е выр а ж ение
являет с я в ещ е с т в енным чи с л ом и з - з а
применения в ещ е с т в енного числа ( я вляюще г о с я
значени ем константы r С З ) в выр а ж ении }
{ описание к о н с т анты с именем rC 5 . Н е смо тря на т о ,
что з н ач ение выраж ения 0 . 1 * 1 0 р а в н я е т с я 1 ,
е с т ь цел ому числу ,
то
к омnилятор а в т оматич е с ки
р а сn о з н а е т тиn данной конст анты к а к R e a l ,
как данн о е п о с тоянн о е выр а ж ение
так
( 0 . 1*10)
явля ется в ещ е с т в енным числом из - з а исnоль з о в ания
в
выр а ж ении в ещ е с т в енно го ч и с л а
(0 .1) }
Begin
{ н ачало р а з д е л а оnис ания л о гики пр о гр аммы }
End .
{ к онец р а з д ела опис ания л о гики пр огр аммы }
Таким образом, в правых частях описаний кон стант может присутство
вать в ы р а ж е н и е любой слож н ости , включающее в себя все ранее описан
ные кон станты.
Ан ал о ги ч н ы м образом описываются логические посто
янные выражения, результат вычисл ения которых имеет тип
(см. л и ст и н г
ЛИСТИНГ 0 1 5 .
Boolean
0 1 5) .
ОПИСАНИЕ КОНСТАНТ
Program Cons t ant s З ;
{ з а г о л о в о к пр о гр аммы , имя про граммы Con s t
iC1
C o n s t an t s З }
{ н ачало р а з дела оnис ания к о н с т ант }
=
100;
{ опис ание константы с именем i C l и з н а чением 1 0 0 .
Компилятор а в томатич е с ки р а с n о з н а е т тип данной
конст анты как Byt e ,
так к а к данн о е п о с тоянн о е
83
Turbo Pascal 7 . 0
выраж ение
IC2
1000;
является
( 1. 0 0 )
инт ер в а л е доnу стимых знач ений типа By t e }
и
знач ением 1 0 0 0 .
{ опи с а ние конс танты
с
так как
данн о е
является
Tru e ;
це лым
чи с л ом
как I n t e g e r ,
инт ер в а л е
им е н ем
( 1000 )
д о nу с тимых
Ь С З и знач ением
Компилятор а в т оматич е ски р а с п о з н а е т тип
ко н с т ант ы как B o o l ean ,
постоянно е
выраж ение
знач ением }
iC1 <
в
знач ений типа I n t e g e r }
данной
ЬС4
к о н с '!' аН'I'Ы
п о с тоянн о е в ыр а ж ение
{ описание константы с
True .
iC2
именем
Компилятор а втомати ч е с к и
р а с п о з н а е т т и п д анн о й
ьс з
числом
ц елым
в
( True )
·r·ак как данное
является
i С 2 ; { опи с а ни е константы с именем Ь С 4 .
л о гич е с ким
Компилятор
а в томатич е ски р а с п о з н а е т тип данной к о н е т аты
как B o o l e an ,
выр а ж ение
так как данн о е п о с тоянн о е
( iC1
<
iC2
= 100
<
1000
является логиче ским знач ени ем }
= Tru e )
Begin
{ начало р а з д ела опис ания
End .
{ к онец р а з д е л а опис ания л о гики пр о г р аммы }
л о гики
пр ограммы }
М ЕТОДИКА ИСПОЛЬЗОВАН ИЯ КОНСТАНТ
Константы являются вспомогательными структурами данных, содержат
значения, присвоеиные им на этапе разработки программы, и применяются,
в основном, для синхронизации других структур данных. Поясним на при
мере. Допустим, разрабатывается программа для психологического тести
рования, содержащая 20 вопросов и по 5 вариантов ответа на кажд ы й воп
рос . Про гр ам му необходимо использовать для сравнения результатов
тестирования 1 5 -ти ч ел овек . Соответственно, структура данных программы
должна быть разработана таким образом, чтобы одновременно хранить дан
ные о б ответах 1 5-ти пользователей на 20 вопр о с ов , причем ответом являет
ся число от 1 до 5, каждое из которых д ол ж н о храниться в одн о й перемен
ной типа Byte. Итого, на.."\1: необх оди ма память в размере 1 5 * 20=300
п ер с менных типа Byte.
Ключевые числа в наш е й программе - 20 ( к оли ч ест во вопросов), 1 5 (ко
личество пользователей) и 300 (произведение количества пользователей
на количество воп р о с ов ) . Эти три числа будут часто использов аться в пред
полагаемой программе - в тех ее частях, которые описывают структуру
данных, выводят вопросы на экран, считывают ответы пользователей, со
храняют их в подготовленной структуре данных, вычисляют некоторы й ре
зультат для каждого п ользовате л я и сравнивают п рот е стиров анн ы х пользо
вателей между собой .
Здесь мо гут возникнуть некоторые трудности. Например, при выделении
памяти под структуру данных можно ошибиться и вместо необходимых 300
ячеек получить, например, 200 ячеек. Тогда программе не хватит памяти
84
Глава 3 . Основы n рограм м и рования
для хранения результатов тестирования, и она закончится ошибкой. При
этом результаты тестирования пользователей, на ответы которых хватило
памяти, будут утеряны, и им придется проходить тестирование заново.
Ошибки такого рода легко устраняются в процессе отладки разрабатывае
мой проrраммы, особенно если программа не очень большая.
Сложнее будет модифицировать программу для работы, например, 30-ти
пользователей . Для этого нужно будет исправить все части проrраммы, ко
торые используют для своей работы количество пользователей (было 1 5,
стало 30) и произведение количества пользователей на количество воп
росов (было 300, стало 600). Данные части программы могут находиться
на расстоянии сотен строк друг от друга или вообще в разных модулях.
При внесении таких изменений неминуемы ошибки. Например, можно ис
править не все необходимые фрагменты кода, или при использовании авто
матической замены по всему тексту, исправить число 300 на 600, в том мес
те, где число 300 является не количеством ячеек памяти, а, например,
максимальным количеством баллов.
Проблемы такого рода решаются введением в программу констант. Для
данного примера может быть использована следующая структура констант
(см. листинг 0 1 6).
Листинг 0 1 6. ОписАНИЕ констАнт
Program C on s t ant s 4 ;
имя
з аголов ок nр ограммы ,
Con s t
Users
=
Que s t i ons
15;
=
{ оnис ани е
·-
C on s t an t s 4 }
·
к о н с т анты
с
=
2 0 ; { оnи с ание константы с
5;
{ оnис ание к о н с танты с
с од ержащей колич е с т в о
на к аждый в оnр о с
MemoryS i z e
имен ем
U s e r s , с одержащей
(15) }
именем Qu e s t i on s ,
в оnр о с о в ( 2 0 ) }
именем Var i ant s ,
в арианто в о тв е т о в
колич е с тв о nоль з о в ателей
с од ержащей колич е с т в о
Var i ant s
Users
*
(5) }
Que s t i ons ;
{ оnисание
константы
необходимое
с
имен ем
количество
ответов nользователей на
=
Begin
nро гр аммы
{ начало р а з д е л а оnи с ания кон с т ант }
15 * 20
=
ячеек
Memo:rySi z e ,
nамяти
воnросы
содержащей
для
(Users
*
хран ения
Questions
300 ) }
{ начало р а з дела оnи с ания л о гики nр огр аммы }
{ и сnоль з о в ание
к о н с т ант
Va r i an t s
Memo ry S i z e
и
Users ,
для
Qu e s t i on s ,
выnолн ения
н е о бходимых действий }
End .
{ конец р а з дела оnис ания л о гики nр огр аммы }
Далее, в программе должны использоваться не числовые значения парамет
ров 15 (Количество пользователей), 20 (Количество вопросов), 5 (Количество
85
Turbo Pasca\ 7 . 0
вариантов ответов на вопрос) и 300 (Размер памяти), а константы по име
нам, соотв е тстве н но : U s e r s , Que s t i on s , Va r i a n t s и Memo r y S i z e . Тогда
при необходимости изменения какого-либо из этих параметров достаточно
изменить только значение константы, которая его представляет, и переком
п и лировать программу. Например, мы хотим изменить количество тестиру
емых пользователей с 1 5 на 30. Тогда приведенная программа будет выгля
деть так, как это показано в листинге 0 1 7.
Листинг О 1 7. ОписАние констАнт
Program Cons t ant s 5 ;
{ з а г о л о в о к пр о граммы , имя пр ограммы - C o n s t an t s 5 }
Const
Users
{ начало р а здела опис ания конс тант }
=
30;
{ опис ание конст анты с именем U s e r s ,
=
2 0 ; { опи с ание константы с именем Qu e s t i on s ,
(3О) }
содерж ащей новое колич е С 'l' В О поль з о в ат е л ей
Que s t i ons
с о д ер ж ащей колич е с т в о вопр о с о в
(20) ,
о с тавляем б е з и змен ения }
Vari ant s
5;
{ опис ание конст анты с именем Var i an t s ,
с одер ж ащей колич е с т в о в ариант о в о т в е т о в н а
к аждый в опр о с
MemoryS i z e
(5) ,
о с т а в ляем б е з и з менения }
U s e r s * Que s t i ons ;
{ опис ани е конст анты с именем Mem o ry S i z e ,
с одержащей н о в о е нео бходимо е колич е с т в о ячеек
памяти для хр ан ения· о т в е т о в пол ь з о в а т ел е й
н а вопросы
( Us e r s
* Qu e s t i on s =
30
*
20
=
600 ) .
П ер е с читыв а е т с я автоматич е с ки при к омпиляции
пр о гр аммы }
Begin
{ начало р а з д е л а опи с ания л о гики пр о гр аммы }
{ и споль з о в ание констант U s e r s ,
Qu e s t i on s ,
V a r i ant s и Memo ry S i z e для выполн ения н е о бходимых
действий остается
без
изменения ,
испол ь зую�г с я новые знач ения }
End .
но
а втоматиче ски
{ к онец р а з д ела опис ания л о гики пр огр аммы }
Таким образом, трудоемкий процесс поиска и изменения числовых зна
чений в тексте программы превращается в простое изменение нескольких
значений констант. При этом все остальные части программы, работающие
со значениями констант ч е р е з имена, автоматически будут использовать
новые значения.
БЕЗ Ы МЯ Н Н Ы Е КОНСТАНТЫ
И , наконец, з аме т им , что константы могут использоваться без имени. Рас
смотрим следующий пример (см. листинг 0 1 8).
86
Глава 3 . О снов ы п рограм м и рования
Листинг 0 1 8 . ОписАНИЕ констАнт
P rogram C ons t ant s б ;
{ з а г о л о в о к прогр аммы , имя пр о гр аммы - C o n s t an t s б }
Const
{ н ач а л о ра здела опи с ания к он с т а н т }
MyName
' МИХаил ' ;
{ опи с ание к о н с т анты типа S t r i ng с име н ем
MyNarne и знач ением
Var
' Михаил ' }
{ начало р а з д е л а опис ания п ер еменных }
U s e rName :
S t ring ;
{ опи с ание п ер еменной типа S t rin с именем U s e rNarne }
Begin
U s e rName
{ начало р а з д е ла оnи с ания л о гики nр о гр аммы }
: =
MyName ;
{ nри с в о ение пер еменной Us e rNarne з н а ч е ния
к о н с т анты MyNarne }
U s e rName
. -
' Мария ' ;
{ nри с в о ение переменной Us erNarne знач ения ' Мария ' }
End .
{ к он ец р а з д е л а опис ания л о гики nро гр аммы }
В данной программе используются три константы: одна - с именем MyN ame
и значением «Ми х аил», вторая - без имени и с тем же самым значением,
которое и присваивается константе MyName , третья - без имени, со значе
нием «Ма р и я » присваивается переменной U s e rName.
Использования констант без имени следует избегать в силу возможности по
явления вышеописанных проблем. Однако в разделе описания констант, ког
да мы создаем в программе структуру данных, без безымянных констант не
обойтись. Должны же откуда-то появиться значения описываемых констант.
Хотя компилятор и способен автоматически определять тип описываемой
константы, програ."-1мист мож ет указать его явно. Данная возможность редко
используется, по иногда необходимость в ней существует. Рассмотрим про
грамму, в которой описывается константа с именем rC l , имеющая значение
5. При автоматическом определении типа данной константы она будет иметь
тип Byte, так как ее значение является целочисленным и попадает в диапа
зон допустимых значений типа Byte. Но мы укажем компилятору, что тип
данной константы должен быть Rea l . Константы, описанные с указанием
типа, называются типизированными и могут быть изменены в процессе вы
полнения програi\-IМЫ, так же каr� И обычные персменные (см. листинг 0 1 9) .
ЛИСТИНГ 0 1 9. ОПИСАНИЕ КОНСТАНТЫ С ЗАДАННЫМ ТИПОМ
Program Cons t ant s 7 ;
{ з аг о л о в о к nро граммы , имя nр о гр аммы - C on s t an t s 7 }
Const
NUmЬ e r :
{ на ч а л о ра з д е л а опис ания констант }
Real
5;
{ опис ание к о н с т анты типа R e a l с име н ем NurnЬ e r
и знач ением 5 . 0 0 }
87
Turbo Pascal 7 . 0
Begin
RDnЬer
{ н ачало
:=
15 . 5 ;
р а з дела опис ания логики программы }
{ пр и с в о ение
End .
типи з ир о в анной к о н с т а н т е
15 . 5}
значения
{ к онец р а з д е л а
NumЬ e r
опис ания л о гики пр ограммы }
3 . 6 С И СТЕМ Ы С Ч И СЛ ЕН И Я
ДВОИЧНАЯ СИСТЕМА СЧИСЛ ЕНИЯ
И так, мы уже говорили, что все данные представляются числами, которые
находятся в ячейках памяти, называемых байтами. В одном байте может
храниться число от О до 255, и сейчас мы разберемся, почему.
Физически оперативное запоминающее устройство представляет собой со
вокупность электронных элементов, способных держать в себе некоторый
электрический заряд. Когда заряд находится в этом элементе, говорят, что
он содержит в себе число 1 . Если заряда в элементе нет, то считают, что в
этом элементе находится О. Данные элементы называются битами ( англ. Bit
- частица, кусок).
Таким образом, вся информация во всех электронных устройствах пред
ставляется набором нулей и единиц. Система счисления, в которой для за
писи чисел используются только два числа (О и 1 ) называется двоичной. То
есть электронные устройства, на физическом уровне, используют двоичную
систему счисления. Для того, чтобы можно было хранить в памяти числа,
большие, чем 1 или меньшие, чем О, биты объединяются в более сложные
структуры - байты (англ. Byte) , содержащие по 8 бит. Соответственно, чис
ло, хранимое в одном байте и записанное в двоичной системе, представляет
собой последовательность восьми цифр, каждая из которых является нулем
или единицей. Н апример: 1 1 1 00 1 1 0 или 0000000 1 .
Различные системы счисления не имели бы смЫсла, если бы нельзя было
перевести число из одной системы в другую. Существуют совершенно оп
ределенные правила перевода чисел из двоичной системы счисления в де
сятичную, которую мы используем в повседневной жизни, и обратно в дво
ичную.
Рассмотрим правила перевода чисел из двоичной системы в десятичную.
Запишем какое-либо число в двоичной системе:
Ч и сло:
о
о
о
о
Пронумеруем биты справа налево, причем нумерацию начнем с нуля:
Ч и сло :
Номер би та :
88
1
7
о
6
о
5
о
4
1
1
3
2
о
1
о
Глава 3. Основы п рогра м м и рования
Подпишем под каждым битом результат возведения числа 2 в степень, рав
ную номеру бита:
Ч исло:
Н омер бита:
Степень 2 - ки :
1
7
1 28
О
О
5
4
3
б4
32
16
8
б
О
2
4
О
1
2
1
О
Умножим данные числа па значения, находящиеся в соответствующих им
битах:
Ч и сло :
1
7
Номер бита :
1 28
Степень 2 - ки :
П роизведе н и е : 1 28
о
о
б4
о
б
о
1
1
4
3
32
1б
о
о
8
8
2
4
4
5
о
2
1
о
о
Сложим данные произведения, получив искомое число в десятичной системе счисления:
1 28 + о + о + о + 8 + 4 + 1
=
141
Теперь рассмотрим, почему число, хранимое в байте, н е может превышать
255. Составим 8-битное число, состоящее из единиц: 1 1 1 1 1 1 1 1 . Очевидно,
что это максимальное число из всех возможных 8-битных. П ереведем его в
десятичную систему счисления:
Ч исло :
7
Н омер бита :
Степень 2 - ки :
1 28
П роизведе н и е : 1 28
1
б
5
б4
б4
32
32
1
1
4
1б
3
8
2
4
1
2
1б
8
4
2
о
1
1
Сложив числа из нижней строки, получаем: 1 2 8 + 64 + 32 + 1 6 + 8 + 4 + 2 +
255, что и требовалось доказать.
Аналоrичиым образом рассмотрим, почему мииимальное число, хранимое
в байте, является нулем. Составим 8-битное число, состоящее из нулей:
00000000. Очевидно, что это минимальное число из всех возможных 8-бит
ных. Переведем cro в десятичную систему счисления:
+ 1
=
о
о
П роизведен и е : о
о
Ч и сло :
Номер бита :
Степень 2 - ки :
7
1 28
6
64
о
о
о
32
4
16
3
8
о
о
о
5
о
о
о
4
1
2
о
о
о
о
2
Сложив числа из нижней строки, получаем: О + О + О + О + О + О + О + О О.
Теперь научимся переводить числа из десятичной системы в двоичную.
Возьмем какое-либо число, например, 1 4 1 . Будем делить ero на 2 до тех пор,
пока результат от деления не станет равным О. При этом остатки, которые
будут получаться при каждом делении, мы будем записывать в строку спра
ва налево. Итак, разделив 1 4 1 на 2, получаем число 70 в качестве результата
=
89
Turbo Pascal 7 . 0
и остаток 1 . Начинаем записывать остатки: 1 . Далее, делим 70 на 2 , полу
чаем 35 и остаток О. Дополняем список остатков слева: 0 1 . Далее, делим 35
на 2, получаем 1 7 и остаток 1 , дополняем список остатков слева: 1 0 1 . И так
далее, пока результат деления не станет равным О.
Таким образом, в результате последовательной записи остатков мы получа
ем число в двоичной системе: 1 0 00 1 1 0 1 .
Биты могут объединяться н е только п о 8 единиц, н о и в более крупные
структуры. Например, можно записать 1 6-битное число: 1 О 1 00000 1 1 1 О 1. 1. 1 О,
или 32-битное: 1 0 1 00000 1 1 1 0 1 1 1 0 1 0 1 00000 1 1 1 0 1 1 1 0, и так далее. Попробу
ем перевести 1 0-битное число 1 1 0 0 1 1 000 1 из двоичной системы в десяти
чную.
Число:
1
9
Номер бита :
Сте пе н ь 2 - к и : 5 1 2
Произ в еден ие : 5 1 2
1
8
о
256
256
1 28
о
7
о
6
64
о
1
5
32
32
1
4
16
16
о
о
о
3
8
2
4
2
о
о
о
1
о
Сложив числа из нижней строки, получаем: 5 1 2 + 256 + О + О + 3 2 + 1 6 + О
817.
+о+о + 1
=
Д РУГИЕ СИСТЕМЫ СЧИСЛЕН ИЯ
Кроме двоичной и десятичной систем счисления в проrраммировании при
меняются и другие, например, шестнадцатеричная или восьмеричная. Во
обще, любое число можно записать в любой системе счисления. Н апример,
в третичной системе счисления (правильно говорить: система счисления по
основанию 3) число может выглядеть так: 2 0 0 1 22, в системе счисления по
основанию 4: 332 1 О, и так далее.
Правила перевода числа из любой системы счисления в десятичную ана
логичны рассмотренным правилам для двоичной системы, за исключением
того, что вместо степеней числа 2, входящих в суммируемые произведения,
используются степени оснований соответствующей системы счисления.
Например, переведем число 22 1 О из системы счисления по основанию 3 в
систему счисления по основанию 1 0 (десятичную) .
Turbo Pascal 7 . 0
В ы в од и н ф о р м а ц и и
в т е к с то в о м р е ж и м е
4 . 1 . В ЗАИ М О ДЕ Й СТВ И Е С П ОЛ ЬЗО ВАТЕЛ ЕМ
Большинство программ так или иначе взаимодействуют с пользователем
с целью получения входной информации и выдачи результатов своей ра
боты (выходной информации). Простейшими видами взаимодействия яв
ляются вывод информации на экран и считывание информации, вводимой
пользователем с клавиатуры. Все команды ввода и вывода информации
должны располагаться в разделе описания логики программы Beg i n . . . En d
или являться составной частью процедур и функций.
Мы пристуiыем t< изучению возможностей Turbo Pascal по обмену информа
цией с пользователем. Несмотря на то, что процедуры и функции, заложенные
в Turbo Pascal, специфичны для данного языка программирования, знания, по
лученные при изучении данной главы, будут необходимы и при освоении дру
гих языков програ.'\1мирования, так как методы обмена информацией являются
одинаковыми для всех программ, работающих на переопальных компьютерах.
Для начала рассмотрим методы вывода информации на экран. Экран перео
пального компьютера может находиться в двух режимах - текстовом и гра
фическом. Текстовый режим прост в использовании, однако предоставляет
довольно узкий набор возможностей представления информации. В графичес
ком режиме программа может вывести любую информацию в пределах фанта
зии програ..'-!миста, но работать с графическим режимом значительно сложнее.
Еще сложнее реализовывать программы, осуществляющие возможности вво
да пользователем информации, особенно при работе с графическим режимом
экрана. Мы будем изу<rать материал в порядке возрастания его сложности,
91
Turbo Pascal 7 . 0
поэтому сначала рассмотрим вывод информации на экран в текстовом режи
ме, затем вывод па экран в графическом режиме, а затем ввод информации.
4 . 2 . М ЕХАН И З М ОТО БРАЖЕН И Я ТЕКСТО ВО Й И Н ФО Р МАЦИ И
Н А ЭКРАН Е М О Н ИТОРА
Экран в текстовом режиме представляет собой прямоугольное поле, запол
ненное ячейками (см. рис. 35), состоящее из 25 текстовых строк по 80 ячеек
в каждой строке. В одной из ячеек находится теi<стовый курсор (каретка)
мигающий указатель, показывающий, из какой позиции будет выводиться
информация.
Информация, выводимая на экран
текстовом режиме, может быть
1�
"
о
представлена в виде символов. Все
..
::;
го в Turbo Pascal предусмотрено ис
()
"'
о
пользование 256 ра:шичных сим
а.
t;
волов,
из которых может быть
"'
составлена текстовая информация.
В каждую ячейку поля можно вы
вести один символ. При выводе
�
символа в ячейку, где уже находит
80 с и мвол ов
ся символ (ячейка не пуста) , предыРис. 35. Экран в тек стов ом режиме
дущий символ стирается, а в данной
ячейке отображается новый символ. Возможностей вывода графических
объектов (точек, линий и т.д.) в текстовом режиме не предусмотрено.
Текстовый курс ор ( карет ка
'1'
u
r b о
в
Р а s с а 1
s
\1)
4 . 3 . П РОЦЕДУРЫ В Ы ВОДА И Н ФОРМАЦИ И
П РОЦ ЕДУРА WRITE
Вывод информации на экран в текстовом режиме осуществляется продеду
рой Wr i te ( англ. Write - писать), имеющей следующий вид:
Wr i t е ( <Выв од:имая инф ормация > ) ;
Данная продедура выводит информацию на экран в символьном виде из те
кущего положения курсора слева направо. Если выводимая строка символов
не помещается по ширине, то она будет перенесена на новую строку. Если
при этом вывод осуществлялся в самую нижнюю строку, то все строки экра
на будут сдвинуты вверх, в результате чего самая верхняя строка пропадет,
92
Глава 4 . Вывод и нформаци и в т екстово м режим е
а внизу экрана появится пустая строка, в которую и будет продолжаться вы
вод (такой сдвиг строк называется скроллингом) .
В качестве Выв одикой ин ф ормации могут использоваться персменные
или константы, предварительно описанные в соответствующих разделах.
При этом персменные используются по имени, а константы либо по имени,
либо задаются непосредственно значением. Рассмотрим примеры использо
вания процедуры Wr i te. Начнем с простейшего варианта (см. листинг 020).
Листинг 020. ИспользовАНИЕ ПРОЦЕДУРЫ WнtтЕ
Program Text Print l ;
{ з а г о л о в о к пр о граммы , имя пр о гр аммы - T ex t P r i nt l }
Begin
{ н ачало р а з д ела опи с ания л о гики прогр аммы }
Wri t е ( ' Прив е т ,
Мир ! ! ! ' ) ;
{ вывод значения б е зыменной к о н с т анты типа S t r i n g .
Строка выв одится из п о з иции кур с ор а
Константа з ад а е т с я знач ением }
End .
( к ар е тки ) .
{ кон ец р а з д е л а опи с ания л о гики пр ограммы }
В данном примере па экран выводится строка «При в е т , Мир ! ! ! » (без
кавычек). Информация выводится начиная с того места, где находится кур
сор. После вывода строки курсор персмещается в ячейку, следующую за
той, в которой располагается последний выведенный символ (см. рис. 36).
После выполнения программы информация, выведенная на экран, не сти
рается, и состояние экрана можно проконтролировать, нажав комбинацию
клавиш �Alt-F5� или выбрав пункт главного меню Debug 1 U s e r s c r een.
Если запустить программу еще раз, то будет выведена та ж е самая строка и
на экране их будет две - друг за другом (см. рис. 37).
Теперь напишем аналогичную программу, но в качестве выводимой инфор
мации будет использоваться значение константы, описанной в разделе опи
сания констант (см. листинг 02 1 ) .
Рис. 3 6. Результаты работы
Рнс. 3 7. Результат работы
программы TextPrint 1
программы TextPrint2
Листинг 02 1 . ИспользовАНИЕ ПРОЦЕДУРЫ WRtТE
Program Text Print 2 ;
Con s t
Gre e t ing
{ з а г о л о в о к пр о граммы , имя пр огр аммы - T ext P r i n t 2 }
{ н ачало р а з д е л а опис ания к о н с 'l'аН'l' }
' Прив е т ,
МИр ! ! ! ' ;
{ опис ание констан·гы с именем Gr e e t i пg . Компиля·гор
автоматич е с ки р а с п о з fl а е т тип данной к о н с т анты как
93
Turbo Pascal 7 . 0
S t r i ng ,
т а к как ее з н ачение з а ключено в к а вычки }
{ н ачало р а здела оnис ания л о гики nро г раммы }
Begin
Writ e ( Greeting ) ; { вывод на экран знач ения конст анты с именем
G r e e t i ng .
{ к ар е тк и ) .
Строка выводит ся и з n о з иции кур с ор а
Константа з ад а е т с я имен ем }
{ к онец р а з де л а опис ания л о гики пр огр аммы }
End .
Распространенной ошибкой является заключение имен констант и пере
менных, используемых в процедуре Wr i te, в кавычки :
Wr i t e {
'
G r e e t i ng ' )
В результате выполнения данной программы на экран
будет выведена строка « Gr e e t i n g » (см. рис. 38). Таким
образом, необходимо внимательно следить за использо
ванием аргументов процедуры Wr i te.
Ку рс ор
G г е е t
i
n
l g l�
Рис . ЗВ . Название
контанты ошибоч
но заключено в
кавычки
;
Рассмотрим еще один пример, где в качестве информа
ции, выводимой на экран, будет использоваться значение
переменной, заранее присвоеиное ей (см. листинг 022).
Листинг 0 2 2 . ИспользовАНИЕ ПРОЦЕДУРЫ WRITE
P rogram Text P r i nt 4 ;
{ з а г о л о в о к nро гр аммы , имя nр о гр аммы - Text P r i nt 4 }
{ начало р а з д ел а оnи с ания констант }
Const
Greet ing
' Прив е т ,
sGreet ing :
МИр ! ! ! ' ;
{ н ачало р а з д е л а опис ания п ер еменных }
Var
S t r i ng [ 1 4 ] ;
{ опи с ание
s G r e e t i ng .
с имв оло в ,
Максимально
S t ring
в о зможное
с
име н ем
колич е с т в о
хранимых в данной п ер еменной - 1 4 }
{ начало р а з д ел а оп � с ания ло гики пр о гр аммы }
Begin
sGreet ing
одной переменной типа
: =
Gre e t ing ;
{ nри с в о ение п ер еменной s G r e e t i n g з н ач ения
конст анты G r e e t i n g
{ ' Прив ет ,
Мир ! ! ! ' ) }
Wri t e ( sGre e t ing ) ;
{ вывод на экран знач ения переменной s G r e e t i n g .
Стр о к а выводится из п о з иции кур с ор а
End .
{ к аретки ) }
{ к онец р а з д е л а опис ания л о гики nр о гр аммы }
П РОЦЕДУРА WRITELN . ВЫВОД С ПЕРЕХОДОМ НА Н ОВУЮ СТ РОКУ
Основным неудобетвам процедуры Wr i te является то, что курсор остается
в той строке экрана, где находится последний символ выведенной информа
ции. То есть, для того, чтобы вывести какую-либо информацию с новой
строки, нужно заполнить до конца предыдущую. Это возможно, если зара
нее иавестно, с ко лько символов уже выведено на экран. Однако в некоторых
94
Глава 4 . Вывод и нформ аци и в тек стовом режиме
случаях программа не может получить такую информацию. Например, про
грамма, выводящая па э кр ан кв адр аты чисел, введенных пол ьз о в ат еле м не
может определить, сколько символов занимает на экране то или иное чи сло
,
.
ПРИМЕЧАНИЕ.
Э т о н е м н ого н адум а н н ы й п р и м е р . Н а с а м о м деле п рогра м м а м ожет о п ределить,
сколько с и м волов будет за н и м ать ч и сл о , хра н и м о е , н ап р и м е р , в п е р е м е н н о й типа
l nteger, и даже м ожет уп равлять ф о рм атом в ы в ода этого ч и сл а н а экран . Однако
это требует довол ь н о сложн ого ал горитма.
К тому же вообще не известно, в каком положении находился курсор в на
чале работы программы. Для решения таких проблем предназначена про
дедура Wr i teLn (англ. Write Line - вывести линию ) , имеющая таКие же
параметры, как и процедура Write:
Wri t е Ln ( < Выв одимая инф ормация > ) ;
В
отличие от процедуры Wr i te продедура Wr i teLn после вывода инфор
мации пе р см е щ ает курсор в начало следующей строки. При этом информа
ция выводится не с новой строки, а так же как и в случае Wr i te, из поло
жения курсора. Рассмотрим пример использования процедуры Wr i teLn
для вывода и н ф о р м ац и и с повой строки (см. листинг 023).
Листинг 023.
ИсnользовАНиЕ nРоцедУРы WRtтELN
Program Text Print S ;
Begin
{ з аг о л о в о к про гр аммы , имя пр о гр аммы
-
Text P r i n t 5 }
{ н ач а л о р а здела опи с ания л о гики пр о гр аммы }
Wri t e Ln ( ' Пepвaя с троха ' ) ;
{ вы в о д знач ения б е з ыменной к о н с т анты типа S t r i ng
с о з н а ч ением
' П ервая строка ' .
из п о з иции кур с ор а ,
Строка выв одит с я
з а т ем кур с ор п ер е в о ди т с я
в н а ч а л о следующей с троки }
Wr i t e Ln ( ' B т opaя с троха ' ) ;
{ вы в о д з н ач ения б е з ыменной к о н с т анты типа S t r i n g
с о з н а ч е нием
' Вторая строка ' .
С т р о к а выводится
и з п о з иции кур с ор а , т о е с ть с новой строки ,
кур с ор
End .
п е р е в одится
в
начало
с л едующей
з ат ем
строки }
{ к онец р а здела опи с ания ло гики прогр аммы }
В результате выполнения данной проrраммы, надпись « П е р в а я с т р о к а »
из положения курсора, а « В т о р а я с т р о ка » - с новой строки.
в ы води т ся
Если процедура Wr i teLn и спол ь з уе т ся без параметров, то никакой ин
формации на экран не в ы в одит ся , а курсор персмещается на новую строку.
Н ап рим ер , если в пр ед ыдуще м примере следую ще й строкой после Begin
написать Wr i teLn ; то и первая и вторая надписи будут выведены с новой
с т роки
.
95
Turbo Pascal 7 . 0
ВЫВ ОД Н ЕСКОЛЬ КИ Х ЗНАЧЕНИЙ ОДНОВРЕМЕННО
В случае необходимости в процедурах Wr i te и Wr i teLn можно указывать
несколько параметров, раэделенных запятыми:
Wri t е ( <Выводимая инф ормация > ,
. . . ,
WritеLn ( <Выводимая информация> ,
<Выв одимая информация> ) ;
. . . ,
<Выводимая информация> ) ;
Рассмотрим пример использования процедур вывода с несколькими пара
метрами ( с м . листинг 024).
Л истинг 024.
ИспользовАние ПРОЦЕДУР WRITE и
WRIТELN
Program Text P r i nt 7 ;
{ з а г о л о в о к пр о гр аммы ,
MyAge
имя
пр огр аммы - Text P r i n t 7 }
{ н ачало р а з дела опи с ания конс тант }
Const
24 ;
{ опис ание константы с именем MyAge и з н а ч ением 2 4 .
Компилятор автоматиче ски р а с п о з н а е т тип данной
константы как By t e ,
выр аж ение
(24)
так как данн о е п о с т оянное
является ц елым ч и с л ом в интер в а л е
допус тимых знач ений т и п а Byt e }
{ начало р а з дела опис ания л о гики пр о гр аммы }
Begin
{ вы з о в пр оцедуры Wri t eLn б е з п араметр о в .
Wri t e Ln ;
Выв одимая на экран информация о т су т с т ву ет ,
кур с ор п ер е в одится в начало н о в о й с тр о ки }
Wri t e Ln ( ' Meня з о вут Михаил ' ) ;
Wri t e ( ' МНe
'
MyAge ,
'
года ' ) ;
{ по сл е д о в а т ел ьный вывод з н ач ения б е з ыменной
с тр о к с в ой конс танты с о з н ач ением ' Мне ' , з н ачения
целочисл енной константы с именем MyAg e
и б е з ыменной строк о вой константы со
(24) ,
знач ением
Вся с трока выводится из п о з иции кур с ор а ,
' года ' .
после
вывода кур с ор о с та е т с я в к онце выв еденной с троки }
End .
{ конец р а з дела опис ания л о гики пр оrраммы }
Результат работы данной программы представлен на рис. 39. Первая строка
является значением одной константы, а вторая сформирована п оследова
тельным выводом значений трех констант.
В процедурах Wr i te и Wr i teLn может испол ь з о в аться л ю б ое количес
тво параметров любой сложности, например, допустимо использование
арифметических выражений. Например, следуюп.щя процедура выводит
па экран квадрат числа 1 5 (см. рис. 4 0 ) :
Wri t e Ln ( ' Kв aдpaт числа 1 5
=
'
,
15*15 ) ;
{ по с л е д о в а т ельный вывод с тр о ки ' Кв адр а т числа 1 5
и знач ения арифметич е с к о г о выр а ж ения
( то есть 2 2 5 ) }
96
15*15
=
'
Глава 4. В ы вод информаци и в т екстовом режи м е
Рис. 40. Резул ьта т работы
Рис . З 9 . Результат работы
программы TextPrint7
программы TextPrint8
Отметим, что хорошим стилем в программировании считается, когда конс
тю-па задается не просто значением, а имеет имя (см. листинг 025).
Листинг 025.
ИсnользовАние сложных выРАЖЕНий
Program Text Print 9 ;
{ з а г о л о в о к nр о гр аммы , имя nр о гр аммы - Text P r i n t 9 }
Cons t
NumЬer
Begin
{ н ачало р а з д ел а оnис ания к о н с т ан т }
15;
{ оnис ани е конс танты с именем Numb e r ,
тиnом By t e
и з н ач ени ем 1 5 }
{ н ач ало р а з дела оnис ания л о гики nр ограммы }
Wr i t e Ln ( ) ;
{ n ер е в о д кур с ора на н о вую с троку }
Wr i t eLn { ' Kвaдpaт числа ' , NumЬer , ' = ' , NumЬe r * NumЬe r ) ;
{ по с л ед о в а т ельный вывод с тр оки
знач ения конс танты Numb e r
(15) ,
' Кв адра т чи с л а ' ,
и з н ач ения
арифме т и ч е с к о г о выражения Numb e r * Numb e r
End .
( то е с ть 1 5
*
15
=
225) }
{ к онец р а з дела опи с ания л о гики пр о г р аммы }
В результате использования именованной ко нстанты , повысилась чита
белыюсть исходного текста программы и упростилось изменение данной
программы. Например, если бы мы хотели изменить программу так, чтобы
выдавался квадрат не числа 1 5 , а числа 20, то следовало бы изменить текст
предыдущей программы в трех местах, а новую программу - только в од
ном - в описании константы.
4 . 4 . УП РАВ Л ЕН И Е Р ЕЖИ МАМ И В Ы ВОДА И Н ФОР М А Ц И И
Основное требование для любого пользовательского интерфейса - удобс
тво р аб оты с ним. В понятие удобства работы входит цветовое и шрифтовое
оформление информации, представленной на экране, а также р аспол о же
ние различных частей информации относительно друг друга. При исполь
зовании текстового режима влиять на шрифтовое оформление невозможно,
шрифт всегда является таким, каким его устанавливает операционная сис
тем а или, нап р име р , программы русификации. Однако возможностей рабо
ты с цветом и расположением информации на экране вполне достаточно,
чтобы пользователю было удобно работать с программой.
4 Зах. 702
97
Turbo Pascal 7 . 0
Процедуры, управляющие представлением информации на экране в тексто
вом режиме, собраны в стандартном (поставляемым с Turbo Pascal) модуле
CRT. Для использования возможностей данного модуля его необходимо под
ключить к программе в разделе подключения модулей U s e s (см. листинг 026).
Листинг 026. ПодключЕНИЕ к ПРОГРАММЕ модУля CRT
Program Мodul e l ;
Begin
{ з а г ол о в ок пр о гр аммы , имя пр о гр аммы - Modu l e l }
{ начало р а здела подключения модул ей }
{ подключ ение модуля CRT }
{ начало р а здела опис ания л о гики пр о гр аммы }
End .
{ конец р а з д ел а опис ания л о гики пр о гр аммы }
Uses
CRT ;
Далее мы рассмотрим процедуры и функции управления выводом инфор
мации на экран в текстовом режиме, содержащиеся в модуле CRT, а также
некоторые вспомогательные функции.
4 . 4 . 1 . ОчистКА ЭКРАНА. П РоцЕдУРА CLRSCR
Наэвание процедуры C l. r S c r является сокращением от Clear Screen ( англ . )
- очистить экран. Реэультатом выполнения данной процедуры является
удаление всех символов, присутствующих на экране, и персмещение карет
ки в верхний левый угол экрана.
Процедуру C l. r S c r рекомендуется вызывать в начале и в конце проrраммы.
В начале - чтобы информация, оставшаяся от других программ, не мешала
пользователю, а в конце - чтобы информация, выведенная вашей програi\1:
мой, не мешала работе с другими программами.
4 . 4 . 2 . ФУНКЦИЯ READKEY
Функция Rea d.Кey (от англ. Read Кеу - читать клавИшу) предлагает более
развитые возможности, чем нужны нам в данный момент - она позволяет
дождаться нажатия пользователем какой-либо клавиши и затем опреде
лить, какая клавиша была нажата. На основе данной функции обычно ре
ализуется интерактивность программ - возможность пользователя влиять
на процесс работы програ.\1МЫ. А пока мы будем использовать данную фун
кцию для организации паузы в проrрамме.
После передачи управления данной функции программа приостанавлива
ется до нажатия пользователем какой-либо символьной или управляющей
клавиши (в список таких клавиш не входят клавиши �shift'-> , �Alt'-> и � ctrl '-> ,
�capsLock'-> , �NumLock'-> и �scrollLock'->, а также �PrintScreen'-> и все специ
ализированные клавиши, предназначенные для работы в Windows). Пояс
ним использование функции Rea d.Кey на примере (см. листинг 027).
98
Глава 4 . В ывод и нформации в текстовом режи ме
Листинг 027.
Использоедние ФУнкции
READKEY
P rogram Wai t ingForu s e r ;
{ з аголовок программы , имя nрограммы - Wa i t ingForUs er }
Uses
CRT ;
Begin
C l rS c r ;
{ начало р а з д е л а подключ ения модулей }
{ подключение модуля СR'Г }
{ н ачало р а здела опис ания л о гики пр огр аммы }
{ очистка экрана }
Wr i t e Ln ( ' Baм нравитс я чистый э хран ? ' ) ;
{ вывод ·г е к с т о в ой инф ормации }
Wr i t е ( ' Ниче г о не мешает работ е ' ) ;
{ вывод т е к с т о в о й инф ормации }
Wr i t e ( '
с нашей программой ! ' ) ;
{ в ывод •г е к с т о в о й инф ормации }
Re adKey ;
{ пр о грамма при о с танавли в а е т с я до н а ж а тия
п ол ь з о в а т е л ем кла виши .
вывед енная на э кран ,
C l rS c r ;
End .
При э т ом вся инф ормация ,
в идна }
{ очи стка экран а }
{ к онец р а з д е л а опис ания л о гики пр о граммы ,
инф ормация , которая выводил а с ь на э кр ан в пр оц е с с е
р а б оты про граммы ,
удален а }
4 . 4 . 3 . П РОЦЕДУР Ы РАБОТ Ы С ЦВЕТОМ
Ц вЕТ ТЕКСТА . П РОЦЕДУРА TEXТCOLOR
В любой момент времени выполнения программы, экран в текстовом ре
жиме имеет две цветовых характеристики: текущий цвет выводимого текс
та и теi< ущ ий цвет фона выводимого текста. Эти характеристики показьша
ют, какой цвет будут иметь символы, выводимые на экран процедурами
Wr i te и Wr i teLn, и на каком фоне они будут отображены.
Для изменения текущего цвета отображаемого текста используется продеду
ра TextCo l o r (англ. Text color - цвет текста), имеющая следующий вид:
TextCo l o r ( < H oмep цв е т а > ) ;
В качестве Ноиера цвета используется число от О до 1 5, заданное пере
менной или константой (по имени или по значению). Для всех возможных
цветов в модуле C RT описаны константы. Рассмотрим цвета (см. табл. 1 ),
которые можно использовать при выводе на экран, номера, которые им со
ответствуют, и константы, которые можно использовать вместо этих чисел.
О б р атим внимание на то, что процедура TextC o l o r устанавливает цвет только
Символы, уже
находящиеся на экране, сохр анят с в о й цвет. В следующем примере, строка тек
ста выводится красным цветом (см . л и ст и н г 028).
тех символов, которые будут выводиться после ее выполнения .
99
Turbo Pascal 7 . 0
Таблица 1 . Цвета, исполъзуемые для вывода ииформации u a экраи, и соот
ветствующие u.;w ко11стаиты модуля CRT
j
Цвет
Черный
r--·
Синий
.
Конста нта
модуля
Номер
о
Blar:k
BltJe
Green
Зел е н ы й
Мор1:кой
З
воnны
......
4
Красный
ФиолР.товыi1
CRT
.Суан
.. .. .
Red
. . .. . .
.... . . .... . .. ............. .. ....
.
. . .. .
.......... ---------��----------···-"···-··-· -···-·--·-········· ··----------·--··-··"·-·-·······---···
········· · · ······ · · · · · -
Светло -синиИ
Свtнrю - :нт в н ы й
+
·
- --
--
Свlнлы�l м о р с к n й Вt:tлны
············· ···· · ·······- -----·--·-····················-·····--··---------·
Св �тло -крас:ный
�� � r'. Т.!.'5'. : � � ':'.:1 '?!.5'.':'.'?''.'
::
-- . . . . - - - - - · - · · · - - · · · - · · - · · · · - - · - - - · - · · - -········-···-·-·
_
.
.
-
.
.
Ж елт ы й
1
т
-·············· : ·
Бнлый
·
1
..;.;_"----
12
ljgl1tRecl
. . ! �.. .. . . . .�:.i�!'.:t.��-�11..�.�-�-� . . ......
· ··-··· ---------- -------··-·····-···
' .: .
I
Dar k C.>r a y
Lig i1 I BIL1e
9
..... .
..
..
.
14
·-··-····--··-··--··-··--··-··--····----·-··-·-··-·· ---··-··-··--·-
15
Листинг 028. ИзМЕНЕНИЕ ЦВЕТА выводимого тЕкстА
Program RedText l ; { з аголовок про граммы ,
Uses
---·-·····-·····-······--·······-·····-··--····
8
Те м н о - серый
-
Ligl1tGray
7
Светло - с е р ы й
·--
Magenta
5
.
··--······--·······--···
.
Yellow
-··-··-----··-·-·----··-·····
\.VIlite
имя программы - RedText l }
{ начало р а з д е л а подключ ения модул е й }
CRT ;
{ подключ ение модуля CRT }
Begin
{ начало р а з д ела опис ания л о гики пр оrраммы }
ClrScr ;
Text C o l or { 4 ) ;
{ очистка экран а }
{ у с т а н о в к а в к а ч е с т в е текущ е г о ц в е т а с номером 4
( кр а сный ) .
Н ачина я с э т о г о м е с т а ,
вся
инф ормация
буд е т выводиться кр а с ным цв етом }
Wr i t e ( ' Kpacиый т екс т ' ) ;
{ вы в о д т е к с т о в ой инф ормации .
Симв олы имеют
кр а сный цв е т , так к а к именно он является т е кущим }
ReadKey ;
{ пр о гр амма прио стана влив а ет с я до н а ж атия
п о ль з о в а т е л ем кла виши . При этом вся информа ция ,
вывед енная на экран .,
ClrSc r ;
видна }
{ очис тка экр ан а }
End .
{ к онец р а з д е л а опи с ания л о гики пр о гр аммы .
Инф ормация , которая выв одил а с ь на э кран
р а б оты пр о граммы ,
В приведеином
пр оце с с е
текущего цвета текста используется
так как снижает читабельность программы,
поэтому рекомсндуетс:я использовать вместо номеров цветов соответствующие
им константы. Например, красному цвету соответствует константа Red Соот
ветственно оператор задания цвета в предыдущем примере лущ.пе записать как:
примере
для
в
удалена }
установки
н ом ер цвета. Однако это неудобно,
Text C o l o r { Re d } ;
1 00
Глава 4. В ы вод и нформации в т екстово м режи ме
Т ЕКУЩИЙ ЦВЕТ ФОНА . П РОЦ ЕДУРА TEXТBACKG ROU N D
Вторая цветовая характеристика выводимого на экран текста - текутций
ф о н а . Для изменения т екуще г о цвета фона используется про д едур а
Textвac k Groun d (англ. Text Background - фон текста) , имеющая следу
ющий вид:
цвет
Text B a c kGround ( < H oмep ц в е т а > ) ;
Для цвета ф она могут использоваться первые восемь цв е т ов из шестнадца
ти д о с ту п н ы х в текстовом режиме ( с м . табл. 1 ). О т м етим, что цвет фона, так
же как и цв ет текста, является текущей характеристикой, поэт ому проце
дура Tex tBac kGroun d влияет на цвет ф она только тех символов, которые
выводятся после ее вызова.
В следующем примере строк а текста «Ка кую музыку вы
в оди т ся кр а с н ы м цв е т ом на черном фоне (см. листинг 029).
люби т е ? »
вы
ЛИСТИНГ 029. ИЗМЕНЕНИЕ ЦВЕТА ВЫВОДИМОГО ТЕКСТА И ФОНА, НА КОТОРЫЙ ВЫВОДИТСЯ ТЕКСТ
Program RedOnB l ack ;
{ з а г о л о в о к про гр аммы , имя про граммы - RedOnB l ack }
Uses
CRT ;
Begin
ClrScr ;
{ начало р а з дела п одключ ения модул ей }
{ подключ ение модуля C RT }
{ начало р а з д е л а опис ания л о гики про граммы }
{ очистка экрана }
Text C o l or ( Red ) ; { y cтaнoвкa в кач е с т в е текущ е г о ц в е т а ,
с о от в е т с т ву е т конс танта Red
с этого места ,
к о т о р ому
( кр а сный ) .
Начиная
в с я информация буде т выводиться
кр а с ным ц в е т ом }
Text BackGround ( B l a c k ) ;
{ у с т ан о в к а ч ерно г о ц в е т а в к ач е с т в е т екущ е г о
для фона
( и с пользу е т с я к о н с ·ганта B l a c k ,
с о о т в е т с твующая ч ерному ц в е ту ) .
места ,
Н ачиная с э т о г о
в с я информация буд е т выводиться
на ч ерном ф о н е }
Wri t e ( ' Kaxyю музыку вы любит е ? ' ) ;
{ вывод т е к с т о вой информации .
кр а с ный ц в е т ,
т е кущим ,
ReadKey ;
и выв одят ся на ч ерном ф о н е }
{ пр о гр амма при о с т ан а в ли в а ется до н а ж а тия
поль з о в ат е л ем кла виши .
выведенная на экран ,
Clrscr ;
End .
Симв олы имеют
так к а к кр а с ный ц в е т явля е т с я
При этом вся инф ормация ,
видн а }
{ очистка экрана }
{ к онец р а з д ел а опис ания л о гики пр о гр аммы ,
инф ормация ,
котор ая выв одил а с ь на э кран
в пр оце с с е р а б о ты пр о гр аммы ,
удалена }
1 01
Turbo Pascal 7 . 0
КУЛЬТУРА ЦВЕТОВО ГО ОФОРМЛЕНИЯ
Цветовые характеристики экрана в текстовом режиме не являются прина
длежащими только текущей программе, а влияют на вывод всей информа
ции на экран вообще. Это значит, что после окончания выполнения про
гра.'\fмы текущие настройки цвета текста и фона, на который выводится
текст, сохраняются. Например, после выполнения программы, представ
ленпой в предыдущем примере, все остальные программы будут выводить
свою информацию красным цветом на черном фоне. Это не касается про
грамм, которые изменят текущие цветовые характеристи ки перед выводом
информации.
Еще один интер е сный момент: процедура C l rS cr, стирающая информацию
с экрана, закрашивает весь экран текущим цветом фона. Это также может
привести к нежелательным последствиям для цветового оформления поль
зовательского интерфейса.
Например, мы уж е говорили о том, что в начале программы рекомендует
ся вызывать C l r S c r для удаления с экрана иенужиого текста, оставше
гася после выполнения других программ. Однако результатом выполнения
этой процедуры будет экран, окрашенный в текущий цвет фона. При этом
предыдущая программа могла установить его таким, что он совершенно не
подходит для наших целей. Таким образом, чтобы избежать неприятных нео
жидашюстей перед вызовом C l rScr необходимо настроить текущие цвет а
.
А поск ольку это правило выполняют не все программы, то после своего вы
полнения ваша программа должна, кроме удаления с экрана информации,
выведенной в процессе работы, установить цвета текста и фона, которые яв
ляются стандартными. Стандартными цветами принято считать белый цвет
для текста и черный - для фона:
TextColor (White ) ; { y c тaнoвкa б е л о г о ц в е т а в к ач е с т в е т е кущ е г о )
TextвackGround ( B l a c k ) ;
{ у с т ан о в к а черн о г о ц в е т а в к ач е с т в е т е ку щ е г о
C l rS c r ;
д л я фона )
{ очистка экрана . Экран о кр ашив а е т с я в ч ерный ц в е т .
В с е пр о граммы , выполняющи е с я по с л е з а в ершения
данной , будут испол ь з о в ать с т андартную ц в е т о ву ю
г амму )
В завершении данного раздела отметим некоторые требования к изображе
нию, выводимому на экран, вне зависимости от того, текстовый режим ис
пользуется или графический:
1 . Изображение должно быть устойчивым. Если объекты, выводимые
на экран, слишком быстро персмещаются или мигают, пользовате
лю трудно следить за ними Затрудненное восприятие интерфейса
приводит к быстрому утомлению пользователя и, соответственно,
невозможности долгой работы с программой.
.
1 02
Глава 4 . В ы вод и нформации в т ексто вом режи м е
2 . Изображение должно быть четким и контрастным. Если какие
либо элементы интерфейса размыты, пользователю неудобно на
блюдать за ними. Единственным размытым элементом интерфейса
может быть фоновое изображение, так как нет необходимости об
ращать на него внимание. Более того, резкое фоновое изображение
снижает обтцую контрастность.
3. Выбор цветовой гаммы определяется назначе нием программы.
В настоящее время существует огромное количество литературы,
в которой доступно изложены основы дизайна и, в частности, шриф
тового и цветового оформления продукции. Приведем несколько
удобных для восприятия цветовых сочетаний: белый или желтый
цвет на черном фоне, белый цвет на красном фоне (и наоборот),
красный цвет на черном фоне (но не наоборот) . Еще одним удоб
ным сочетанием является белый цвет на синем фоне, однако реко
мендуется избегать излишнего сине-фиолетового светового потока,
так как это неблагаприятно влияет на зрение пользователя. Отме
тим, что программист в процессе разработки и отладки программы
тоже является пользователем.
Если программа не удовлетворяет изложенным требованиям, то, скорее
всего, полъзователь выберет для работы аналогичную проrрамму, но с более
качественным интерфейсом.
4 . 4 . 4 . УПРАВЛЕНИЕ РАСПОЛОЖЕНИЕМ И НФОРМАЦИИ .
П РоцедУРА GoToXY
Мы уже умеем несколъкими способами влиять на расположение текстовой
информации. Так для того, чтобы стрш<а текста выводилась в начале но
вой экранной строки, перед ее выводом следует использовать процедуру
Wr i teLn (возможно, без параметров); а чтобы вывести строку не от нача
ла экранной строки, а с некоторым отступом, можно перед ней напечатать
с помощью процедуры Wr i te необходимое количество пробелов. Однако
данные методы не обеспечивают даже минимального удобства работы.
Рассмотрим пример программы, выводящей строку « С т р о к а , выр о в
н е н н а я п о ц е н тру» так, чтобы эта строка оказалась посередине экрана
(см. листинг 030) . Таким образом, данная строка должна находиться в эк
ранной строке с номером 1 2 (всего на экране 25 строк, следовательно, сере
дина экрана 25/2 � 1 2) .
П о горизонтали первый символ выводимой строки должен находиться в пози
ции номер 25 (всего в экранной строке 80 символов, выводимая строка зани
мает 29 символов, следовательно, свободного места в экранпой строке остает
ся 80 29 51 символов, слева и справа от выводимой строки свободного места
должно быть поровну, то естъ 5 1 /2 25.5 примерно получаем позицию 25).
-
=
=
1 03
Turbo Pascal 7 . 0
ЛИСТИНГ 030. УПРАВЛЕНИЕ ПОЛОЖЕНИЕМ ВЫВОДИМОЙ ИНФОРМАЦИИ
Program C ent e rтext l ;
{ з аг о л о в о к прогр аммы , имя пр о гр аммы - C en t erText 1 }
Uses
CRT ;
Begin
{ начало ра здела подключ ения модулей }
{ подключение модуля CRT }
{ :начало раздела опис ания л о гики пр о гр аммы }
TextBac kGround ( B l a c k ) ;
{ у с т а н о в к а ч ерн о г о ц в е т а в кач е с т в е т е куще г о
для ф о н а ( и спользуется
к о н ст а н т а B l a c k ,
с о о т в е ·г с 'I· вуiощая ч ерному ц в е ту ) }
Text C o l o r ( Whi t e ) ; { у становка б е л о г о ц в е т а в к ач е с т в е
текущ е г о для т е к с т а }
ClrScr;
{ очистка экр ана .
ч ерный ,
П о с к ольку текущий ц в е т ф о н а -
то в е с ь экран буд е т окрашен этим ц в е т о м }
Wri t e Ln ;
Wri t e Ln ;
Wr i t e Ln ;
Wr i t eLn ;
Wr i t eLn ;
Wr i t e Ln ;
Wri t eLn ;
Wri t eLn ;
Wri t e Ln ;
Wr i t e Ln ;
{ п ер е в одим строку 1 1 р а з ,
и с п о л ь зуя пр оцедуру
Wri t eLn б е з п араметр о в с о о т в е т с т вующ е е
колич е с т в о р а з }
Wri t e Ln ;
{ т еп ер ь С 'Iрока 1 2 является т е кущей и инф ормация
будет выв одиться в н е е }
1
wri t e ( '
)
;
{ в ыв одим 2 4 пр о б ела ,
с о от в е т с т в енно ,
каретка
п ер емеша ется в п о з ицию 2 5 }
Wri t e { ' C тpoкa ,
ReadKey ;
выровненная по центру ' ) ;
{ выв одим с •гроку }
{ пр о гр амма при о с танавли в а ет с я до нажатия
пол ь з о в а телем клавиши }
ClrScr;
{ оч и с т к а экрана .
цвет .
Экр ан окраши в а е т с я в ч ерный
В с е пр огр аммы ,
з а в ершения д анной ,
выполняющи е с я п о с л е
будут исполь з о в а т ь
ст андартную ц в е т о вую г амму }
End .
{ конец р а з д е л а опи с ания л о гики пр ограммы ,
инф ормация ,
к о т орая выв одил а с ь на экран
в пр оц е с с е р а б о ты пр о гр аммы ,
М одуль CRT
удалена }
сод ержит более развитые ср едств а для расположения текстовой
Пр о д едур а Go toXY (англ. G o to Х, У - переместить в
точку с координатами координат ы Х, У) позволяет переместить к ар е тку в
любую часть экрана. Д анный о п е рат о р используется с двумя параметра:ми,
определяющими новое положение кар е тк и и в ы глядит следующим образом:
ин формаци и на экран е .
,
1 04
Глава 4 . В ы вод и н ф о рмаци и в т екстовом р ежи ме
Gоt оХУ ( < Г ориз онтальная к о ордината > ,
<В ертикальная к о ордин а т а > ) ;
Вер'Х'ика.п:ьнан: координа'Х'а определяет н о м ер экранной строки, в кото
рую должна п ер с м ест ить ся каретка и может принимать значение от О ( п ер
вая ст р ок а) до 23 ( последняя строка). Горизон'Х'а.п:ьнан: координа'Х'а оп
ределяет положение каретки в новой строке от левого края экрана и может
изменяться от О ( самое левое п оложе ние ) до 79 ( самое пр ав о е положение ) .
Таким образом, программу, приведеиную в пред ыдуще м примере, можно
реализовать следующим образом (см. ли ст и н г 03 1 ) .
ЛИСТИНГ 03 1 . УПРАВЛЕНИЕ ПОЛОЖЕНИЕМ ВЫВОДИМОЙ ИНФОРМАЦИИ
Program C ent erтext 2 ;
Uses
CRT ;
Begin
Text BackGround ( Bl ac k ) ;
Text C o l or ( Wh i t e ) ;
C l rS c r ;
{ очистка
ч ерный ,
GotoXY ( 2 4 ,
экрана .
П о с кол ьку
1 1 ) ; { п еремещение каре'I'КИ в С 'I'року 1 1
о т с ч е т строк в ед е т с я о т О ,
1 2 - я с тр ок а )
кр ая экрана ) }
Wri t e ( ' C тpoкa ,
-
( н апомним ,
Ч 'I' О
поэ тому э т о буд ет
и в с им в о л н омер
э т о буд е т 2 5 -ый с имвол в
24
строке
( а на л о г и чн о ,
от л е в о г о
выровненная по центру ' ) ;
{ выв одим
ReadKey ;
т екущий ц в е т фона
то в е с ь экран будет окр а ш е н этим ц в е т о м }
с т р о ку
из п о з иции кар е тки }
{ пр о rрамма при о с танавлив а е т с я до нажатия
поль з о в а т е л ем клавиши }
{ о чи с т к а экрана . Экран о кр а ш ив а е т с я в ч ерный ц в е т .
C l rS c r ;
В с е про граММЬI ,
данной ,
выполняющи е с я п о с л е з а в ерш ения
будут исполь з о в а ть с т андартну ю ц в е т о вую
г амму }
End .
4 . 4 . 5 . ОПРЕДЕЛЕНИЕ ПОЛОЖЕНИЯ КУРСОРА.
П РОЦЕДУРЫ WHEREX и WHEREY
Иногда в оз н и каю т ситуации, когда программе необходимо определить по
ложение курсора. Это может понадобиться, например, при одновременном
выводе ин фор м аци и и чтении с тр ок введенных пользователем, к от оры е
отображаются на экране автоматически (так называемый ввод с эхом). Воз
можности Turbo Pascal по вводу информации мы будем изучать позже, по
этому в данный момент рассмотрим простой пример па определение поло
,
жения каретки.
1 05
Tu rbo Pascal 7 . 0
Напишем програ.J\1му, которая будет выводить на экран д в е строки: « П ер в а я
с т р о к а » и « В т ор а я с т р о к а » , причем вторая строка будет выводиться
так, чтобы затереть последние два символа первой. Для решения данной за
дачи, необходимо вывести первую строку на экран процедурой Wri teLn,
определить координаты каретки, затем передвинуть ее в ту же экранную
строку, но на два символа левее, то есть на предпоследний символ выведен
ной строки, и вывести вторую строку процедурой Wri te.
Для определения положения каретки в модуль CRT включены функции
(анrл. Where Х - где горизонтальная координата?) и WhereY
(англ. Where У - где вертикальная координата?) . Данные функции служат
для определения, соответственно, горизонтальной и вертикальной коорди
наты текущего положения каретки.
WhereX
Отличия функций от процедур заслуживают особого внимания и обсужда
ются в разделе, описывающим создание собственных процедур и функций,
а пока будем относиться к функциям как к переменным, описанньrм в мо
дуле CRT и содержащим в каждый момент времени выполнения программы
какие-либо значения. Какое значение содержится в этой -«переменной� , оп
ределяется назначением функции. Например, функция ReadКey, рассмот
ренная выше, возвращает значение нажатой пользователем клавиши, а фун
кция Whe reX - горизонтальную координату каретки.
Нам необходимо сохранить значения координат каретки в своих внутрен
них переменных, следовательно, мы будем использовать функции Whe reX
и WhereY в правых частях оператора присваивания. Текст программы при
веден в листинге 032
Л ИСТИНГ
032. УПРАВЛЕНИЕ ПОЛОЖЕНИЕМ ВЫВОДИМОЙ ИНФОРМАЦИИ
Program S e c ondEra s e s F i r s t l ;
{ з аголовок пр ограммы ,
имя nр о гр аммы -
S e c ondEra s e s F i r s t l }
{ начало р а з д е л а подключ ения мо.цулей }
Uses
CRT ;
{ подключение модуля CRT }
Var
Х,
{ н ачало р а з дела опи с ания пер еменных }
У:
Int eger ;
Begin
{ опис ание двух n ер еменных типа I n t e g e r с имен ами
х и У}
{ н ачало р а з дела опи с ания ло гики пр о гр аммы }
Text C o l o r ( Whi t e ) ;
{ у с тановка б ел о г о цвета в кач е с т в е т екущ е г о
для тек ст а }
Text BackGround ( B l a c k ) ;
{ у с тановка ч ерного ц в е т а в кач е с т в е т е кущ е г о
для фона }
Wri t e Ln ;
{ у становка каретки в н о вую с тр о ку }
Wri t e ( ' Пepв aя с трока ' ) ;
{ в ывод первой с троки }
106
Гл ава 4. В ы вод и н формаци и в т екстов ом режи ме
Х
: =
Whe reX ;
{ з ан о с им гори з онт альную к о ордина ту к ар е тки
в пер еменную Х }
У
. - WhereY ;
х
: =
{ з аносим в ертикал ьную ко ордина ту каретки
в переменную У }
х
-
2;
{ уменьша ем значение пер еменной Х на 2 .
Д анный
оператор при с в аи в ания р а б от а е т в д в а этапа вычи сление знач ения выраж ения Х - 2 и при с в о ение
этого значения переменной Х }
Got oXY ( Х , У ) ;
{ у с танавлив а ем к ар етку в н о в о е положение - н а д в а
симв ола л е в е е пр едыдущ е г о }
Wri t e ( ' B т opaя с трока ' ) ;
{ вывод второй с тр о ки }
ReadKey ;
{ программа при о станавли в ается до н а ж а тия
C l rS c r ;
{ очистка экран а }
End .
{ к онец р а з д е л а опи с ания л о гики пр о гр аммы }
пол ь з о в ателем клавиши }
Результатом работы программы будет строка текста « П ер в а я с т р о Е т о
с т р о к а » , выведенная с новой экранной строки, в н е зависимости от
того, где находился курсор до начала работы проrраммы.
рая
Рассмотрим фрагмент проrраммы, в котором определяются координаты ка
ретки и осуществляется ее перенос на новое место:
х
: =
Whe reX ;
{ получение гориз онтальной ко ординаты к ар е 'I'КИ }
WhereY ;
{ получение в ертикальной к о ординаты каретки }
х
: =
· -
у
х
-
Got oXY ( Х ,
2;
{ уменьшение знач ения пер еменно й ,
в которой
хр анится г ориз онтальная к о ордин а т а ,
У) ;
на 2 }
{ п ер емещение каретки в н о в о е положени е }
Попробуем упростить, объединив получение горизонтальной координаты
и ее уменьшение:
Х
: =
Wherex - 2 ; { по луч ение гориз онтальной к о ордин а ты к а р е тки
У
: =
Whe reY ;
с одн о вр еменным е е уменьшением н а 2 }
Got oXY ( X ,
У) ;
{ получ ение
в ертикальной к о ордин аты каре'гки }
{ п еремещение к ар е тки в н о в о е п о л о ж е ни е }
Теперь переменной Х присваивается н е значение, возвращаемое функци
ей Whe rex, как в предыдущем варианте, а сразу же необходимая новая
горизонтальная координата каретки (уменьшенная на 2 ) . Данный фраг
мент можно упростить еще больше, используя в качестве параметров про
цедуры Go toXY не персменные х и У, а сразу же значения, которые им
присваивались:
Got oXY ( WhereX - 2 , WhereY ) ;
{ п ер емещение к а р е тки
в
н о в о е положени е , смещенн о е
по гориз онтали в л е в о н а д в а с им в о л а о т н о с ительно
пр едыдуще г о полож ения }
1 07
Turbo Pascal 7 . 0
Значения выражений, использованных в качестве параметров процедуры
, будут автомати чески рассчитаны при вызове этой пр о цед ур ы и,
с о от вет с твенн о данный фрагмент по своей фупкционаJiыrости не б уд ет от
личаться от н ач ал ьн о г о варианта, однако оп имеет некоторые плюсы.
Go toXY
,
Рекомендуется всегда пытаться упрощать п р о rр аммы уменьшая количест
Это при в оди т к повышению ч ит аб ел ьности программы и дает бо
лее широкую сво боду де й ствий оrnимизатору, встроенному в компилятор.
В данном случае мы получили возможность отказаться от использования
п ерс м енных Х и У, в ко тор ых ранее хранили промежуточные значения пара
метров для процедуры Go toXY.
во стр ок
,
.
Теп е р ь пр о бл е му хранения этих значений р е ш ает компилятор. Скорее все
го, новый вариант программы будет р аб о т ать бы стре е так как промежуточ
ная информация может быть размещена программой в регистрах процессо
ра, которые также яв ляют ся ячейками памяти, но доступ к ни м происходит
значительно быстрее, чем к О З У.
,
,
В результате упрощения программа принимает следующий вид (см. лис
тинг 033).
ЛИСТИНГ 033, УПРОЩЕНИЕ ПРОГРАММЫ
Program S e c ondEras e s F i r s t 2 ;
Uses
CRT ;
Begin
{ начало р а з д е л а nодключ ения модулей }
{ подключ ение модуля CRT }
{ начало раздела оnис ания л о rики пр о rраммы }
TextCo l o r ( Whi t e ) ;
Text BackGround ( B l a ck ) ;
Wri t e Ln ;
{ у становка каретки в н о вую с тр о ку }
Wri t e ( ' Пepвaя с трока ' ) ;
{ вывод nервой строки }
Got oXY ( WhereX - 2 , WhereY ) ;
{ у с тана влив а ем кар етку в н о в о е n о л о ж е н и е на д в а симв ола л е в е е nредыдущего с nомощью
nередачи nр оцедур е G o t oXY арифме тич е с ких
выр а ж е ний ,
с одержащих вызовы функций
Wh e r e X и \'lhereY }
Wr i t e ( ' Вт орая с трока ' ) ;
ReadKey ;
{ вывод в т орой строки }
{ nрио с тановка до нажатия поль з о в а т е л ем к л а виши }
ClrScr;
{ очистка экрана }
End .
{ конец р а з дела оnи с ания л о rики nроrраммы }
На этом и зуч е н и е возможностей модуля CRT не зак онч ено однако пока они
нам не понадобятся. Остальные полезные п р оц едуры и фун кции данного
модуля будут расем отр епы ниже, по мере появления в них необходимости.
А мы переходим к изучению графич еских возможностей языка Turbo Pascal.
,
1 08
Turbo P a s c a l 7 . 0
Гр а ф и к а в
Tu rbo Pascal .
В ы в од и н ф о р м а ци и
в г р а ф и ч е с ко м ре ж и м е
5 . 1 . ОС Н О В Ы РАБОТЫ
С ГРАФ И Ч ЕС КИ М И РЕЖИ М А М И
Как мы уже отмечали, вывод информации на экран, находящийся в гр афи
ческом режиме, гораздо сложнее вывода на экран в текстовом режиме. Это
обусловлено многообразием как самих графических режимов, так и мето
дов их физической реализации внутренними устройствами ПК. Графичес
кие карты, поддерживающие работу монитора, прошли в своем развитии
немалый путь от простейших текстовых режимов, используемых первыми
переанальными компьютерами, до сложных графических, обеспечивающих
огромное количество возможностей для организации пользовательского
интерфейса. К таким возможностям относится, например, использование
3D-ускорителей, встроенных в графические карты или используемых как
отдельные внутренние устройства.
ПРИМЕЧАНИЕ.
3 D -ус ко рители со здан ы для пов ы ш е н и я качества и с кор ости в ы вода трехме рных
сце н , и спользуемых в н екоторых п рограм мах ) .
В процессе эволюции методов вывода информации н а экран текстовые ре
жи м ы практически не прете рп ели никаких изменений и являются такими
же, как были десятилетие назад. Поэтому все графические карты работают
с ними одинаково. Заметим, что начальная загрузка ПК
и
инициализация
1 09
Turbo Pascal 7 . 0
любой операционной системы начинается именно в текстовом режиме, вне
зависимости от того, имеет ли данная операционная система графическую
оболочку или нет. Это обусловлено в первую очередь стандартизованнос
тыо графичесrшх карт в смысле использования текстового режима экрана.
Отсутствие развития текстовых режимов легко объяснить: вывод текстовой
информации не требует высокой скорости, поскольку пользователь может
читать текст с экрана лишь с определенной скоростью. Причем эта скорость
по компьютерным мерка.\:1 очень невелика и компьютеры могли ее обеспе
чить еще много лет назад.
По-другому обстоит дело с графическими объектами. Изображения, выво
димые на экран, несут для пользователя очень мало информации, однако
хранение их описаний требует большого объема оперативной памяти, а пос
троение и вывод занимает довольно много процессарного времени. Таким
образом, возникает проблема недостаточного быстродействия. Производи
тели внутренних устройств решают данную проблему по-разному, следс
твием чего являются отличия в работе с разными внутренними устройства
ми, то есть различные аппаратные интерфейсы устройств.
Мы уже обсуждали вопросы, связанные с аппаратными интерфейсами, и го
ворили, что обычные прикладные программы их не используют, а обраща
ются к устройствам через програ.\:lмные интерфейсы драйверов, единые
для разных устройств. Однако операционная система MS- D O S не имеет
собственных драйверов для полноценной работы с возможностями графи
ческого вывода, поэтому программы, созданные для выполнения в пей,
должны запускать драйвер самостоятельно. Приложепия, написанные на
Turbo Pascal, как раз и попадают в их число.
Для поддержки различных графических режимов для разных графических
карт в комплект поставки Turbo Pascal входят специапьные драйвера, наэы
ваемые ВGI-драйверами (BGI - Borland Graphics Interface - Графический
интерфей с Borland). Некоторые из этих драйверов входят в поставку 11Irbo
Pascal, а некоторые создаются сторонними разработчиюL'\Ш для собственных
целей и распространяются в основном свободно, например через сеть Internet.
Вопросы подключения драйверов к программе мы рассмотрим немного
ниже, а пока разберемся в многообразии графических режимов. Экран в гра
фическом режиме, вне зависимости от типа режима, а также устройства, ко
торое обеспечивает данный режим, и фирмы-производителя данного уст
ройства, представляет собой прямоугольную сетку точеr< ( пикселей) , каждая
из которых может в любой момент времени выполнения программы иметь
некоторый цвет. Все устройства, содержащие в своем названии аббревиату
ру •ЗD•, то есть имеющие возможности вывода трехмерных изображений,
на самом деле переводят эти трехмерные изображения в двухмерные проецируют их на экран. Таким образом, графические режимы могут отли
чаться друг от друга всего по двум параметрам: разрешению и цветности.
1 10
Глава 5. Графи ка в Turbo Pascal . В ы вод и н ф о рмаци и в граф и ческом режиме
Разрешением называется количество точек, помещающихся н а экране
по горизонтали и вертикали. Основными используемыми р азрешения
ми являются: 3 2 0 х 2 0 0 (данное выражение читается так: « 3 2 0 на 2 0 0 • )
640х480, 8 0 0 х 60 0 и 1 024х768. Когда про разрешение говорят « 3 2 0 х 2 0 0 » ,
это значит, ч т о на экране располагается 320 точек по горизонтали и 2 0 0
точек по в ертикали.
,
Цветностью называется максимальное количество разных цветов, которые
могут присутствовать на экране одновременно. Цветность определяется ко
личеством памяти, отводимой для хранения цвета каждой точки, и мето
дом хранения этого цвета. Подробности хранения информации о цвете мы
рассмотрим ниже, а пока приведем наиболее часто используемые цветности
графических режимов: 1 6 цветов, 256 цветов, 65536 цветов (такие режимы
называются Hi Color - высокоцветные режимы) и 1 67772 1 6 цветов (такие
режимы носят название True Color - режимы реального цвета).
Для начала мы будем использовать в наших программах один из самых про
стых (по подключению) графическихрежимов - реж:им с разрешением 640х480
и цветностью 1 6. Данный режим поддерживается всеми современными ком
пыотерами, вывод информации в нем происходит достаточно быстро, а ограни
чение по количеству цветов первое время не будет мешать нашей работе.
5 . 2 . И Н И ЦИАЛ И ЗАЦИ Я И ЗАКРЫТИ Е ГРАФ И Ч ЕС КО ГО Р ЕЖИ МА
М одул ь G RAPH и Его под ключ Ени Е
Графические средства Turbo Pascal достаточно широки и практически не ус
тупают в озможностям современных языков проrраммирования, в том чис
ле и разработанным для создания программ под Windows. В графическом
режиме можно выводить широкий спектр объектов: точки, линии, много
угольники, окружности и их дуги, изображения, созданные как самой про
rраммой, так и какими-либо другими средствами.
Процедуры и функции, предназначенные для работы с графическими ре
жимами, собраны в стандартном (поставляемым с Turbo Pascal) модуле
Graph. Для использования данного модуля его, как и любой другой исполь
зуемый модуль, необходимо подключить в разделе подключения модулей
Uses (см. листинг 034).
ЛИСТИНГ 0 3 4 . ПодКЛЮЧЕНИЕ К ПРОГРАММЕ МОДУЛЯ GRAPH
Program Modul e 2 ;
{ з а г оловок nр ограммы ,
Us e s
имя nр ограммы
-
Modu l e 2 }
{ начало ра здела подключения моду л е й }
111
Turbo Pasca/ 7 . 0
Graph ;
{ подк люч ени е модуля G r aph }
Begin
{ начало р а з д ела опис ания л о гики пр о гр аммы }
End .
{ к он ец р а з д е л а опи с ания л о гики nр о г р аммы }
Ч т о б ы граф и чески с о б ъекты могли выводиться на экран, нужно п е ре в е ст и
его в графич е ский режим - инициализировать, запустив соответствую
щий драйвер. Для использования режима 640х480х 1 6 п редн аз н ачен
стандартный драйвер Turbo Pascal, кот орый имеет имя Ega Vga .bgi и н ахо
дится в подк ат ал оге BGI кат ал ог а, в который установлен ТнrЬо Pascal .
И Н ИЦИАЛИЗАЦИЯ ГРАФИЧЕСКО ГО РЕЖИМА . П РОЦЕДУРА I NITG RAPH
Инициалиаалия гр афическо г о режима пронаводится вы�-ювом проц едуры
Ini tGraph, и м еющей сл едующий вид :
InitGraph ( <Hoмep драйв ера> , <Номер режима> , <Путь к файлу драйв ера> ) ;
П рограмма, написанная на ТшЬо Pascal, может во время своего выполне
ния обращаться к нескольким др ай в ерам (по очереди). Для этого ав тома
тически созд ает ся так называемая таблица драйверов. И з н ач ал ьн а в ней
находя т ся только стандартные драйверы, в т о м числе и E g a V g a . b g i . Про
гр амм а также имеет доступ к функциям, подгружающим в т а б лицу другие
драйверы. Данные функции описаны ниже, а пока нам достаточно знать, что
др айвер EgaVga.b g i , используемый для установки нужного нам режима
640х480х 1 6, уже занесен в таблицу.
Параметры процедуры InitGraph таковы:
1 . Параметр Номер драйвера. В качестве Номера драйвера дол ж
н а использов аться цел о ч исл е н н ая переме нпая ( не константа! ) , име
ющая св оим значением номер необходимого драйвера в т аблице
драйверов. Если передать в к ачестве этого п ар аметр а переменную,
содержащую нулевое значение, драйвер будет определен автомати
чески . Для всех совр е менных (в ыпущен ны х за последн и е полтора
десятилетия) графических карт автоматически определенным драй
вером как раз и будет EgaVga .bg i . Так как автоматическое опреде
ление драйвер а - са.'\1ыЙ распространенный путь иници ал и з ации
граф ического режим а , в модул е Graph оп ис ан а целочисленная кон
стан т а с именем Detect, содержащая О. Данную кон ст ан ту можно
использовать для зан е се ния нулевого значения в переменную, ко
торая затем используется в качестве пар аметр а Номера драйвера
проц едуры In i tGraph.
2.
1 12
Параметр Номер режима. В кач е стве параметра Номер режима
дол жн а использоваться целочисленная переменная, содержащая
допустимый номер графического режима для данного графическо
го др айвер а. В нашем случае (для режима 640х480х 1 6) использует-
Глава 5 . Графика в Turbo Pasca l . В ы вод и нформации в графическом режи ме
ся значение О. Не рекомендуется использовать для занесения этого
значения в персменную константу Detect. Хотя это и не повлияет
на синтаксическую правильиость программы и процесс ее работы,
однако это не корректно, так как константа Detect указывает на
автоматическое распознавание параметров устройства. Эаметим,
что 1urbo Pascal реализован не только в операционной системе MS
D O S , но и, например, в ОС UNIX, значением константы Det e c t
является не О , а 1 2 8 . Таким образом, при переносе программы из
M S - D O S в UNIX она потеряет работоспособность в связи с отсутс
твием графического режима с номером 1 2 8 .
3. Параметр П}"l'ь к ф айлу драйвера. Графические драйверы Turbo
Pascal могут находиться в любом месте файловой системы: в стан
дартном каталоге, выбранном при установке, .в I<аталоге с исходным
текстом программы и вообще в любом другом каталоге. Таким обра
зом, программа во время инициализации не может обнаружить его
самостоятельно. Для указания расположения файла с графическим
драйвером служит параметр Путь к ф айл у драйв ера. Данный
параметр должен являться переменпой или константой (заданной
либо по имени, либо пепосредственным значением) строкового типа
(типа S tring) и содержать путь к файлу драйвера без ука..1ания его
имени. Например, если графический драйвер находится в стандарт
ном каталоге, а сам Turbo Pascal установлен на диск с : в каталог
BPW, то путь к файлу драйвера будет выглядеть следующим обра
зом: ' С : \BPW\BGI ' .
Относительно последнего параметра нужно отметить, что, если файл драй
вера находится в каталоге вместе с разрабатываемой программой, что случа
ется более часто, в качестве параметра Должна быть указана пустая строка:
' ' . Поясним, почему файл с драйвером часто находится в одном каталоге
с программой, которая его использует. Это связано с тем, что Turbo Pascal
установлен не на все компьютеры, на которых может выполняться разраба
тываемая программа, то есть у конечного пользователя может не оказаться
графического драйвера, следовательно, он не сможет выполнить программу.
Для избежания такой ситуации файл с графическим драйвером принято
прилагать к программнему продукту и сохранять его, например, в одном ка
талоге с исполняемым файлом. Стоит отметить, что в качестве парамет
ра Путь к ф айлу драйв ера может использоваться любой допустимый
в M S - D O S путь, при этом каталог, из которого запущена программа, будет
являться текущим. Например, значение параметра может выглядеть следую
щим образом: ' . . \ . . \Dri vers \BGI ' , то есть использовать ссылку на ка
талог более высокого уровня относительно текущего. К именам файлов и
путям к ним мы еще вернемся при обсуждении создания своих файлов.
Таким образом, простейшая программа, инициализирующая графический
режим, выглядит так, как это показано в листинге 035.
1 13
Turbo Pascal 7 . 0
Л ИСТИНГ 035. ИНИЦИАЛИЗАЦИЯ ГРАФИЧЕСКОГО РЕЖИМА
Program U s eGraphi c s 1 ;
{ з аголовок про граммы , имя про граммы - U s eGraprl i c s l }
{ н ач а л о р а з дела n одключ ения модул ей }
Use s
{ п одключ ение модуля Graph }
Graph ;
{ н ачало р а здела опи с ания nеременных }
Var
GraphD river ,
GraphМode :
Intege r ;
{ опи с ание двух целочисл енных пер еменных :
GraphD r i v e r - для передачи в к а ч е с т в е п ар ам е тр а ,
опред еляющего номер гр афич е с к о г о др а й в ер а ,
и GraphМode - для передачи в к ач е с т в е параметр а ,
определяющего номер графич е с к о г о р ежима }
{ начало р а здела опис ания ло гики nр ограммы }
Begin
GraphDriver
: =
Det e c t ;
{ при с в о ени е пер еменной GraphD r i v e r з н а ч ения О
ч ер е з испол ь з о в ание конс танты D e t e c t модуля
Gr aph для на глядн о с ти }
GraphМode
: =
О ; { прис в о ение переменной Gr aphМode знач ения О ,
определяющего нео бходимый графич е с кий р ежим 6 4 0 х 4 8 0 х l б цветов }
Init Graph ( GraphDrive r ,
GraphМode ,
' ' ) ;
{ вы з о в nр оцедуры I n i t Graph ,
опред еляющей дра й в ер ,
а в т оматич е с ки
подходящий для вид е о
у с тр о й с тв а , у с тановленн о г о н а к омnьютер е ;
з апу с кающей др айвер и инициали з ирующей
графич е с кий р ежим с номером О }
End .
{ к онец р а з дела опис ания ло гики nр огр аммы }
Приведеиная выше программа работает следующим образом: в памяти
находятся две целочисленные переменные, которым в начале програм
мы присваиваются нулевые значения, причем переменной G r aphMode
значение присваивается непосредственным указанием ( G r a phMode : =0 ) ,
а переменной G r a p h D r i v e r - через использование константы D etect
(G r a ph D r i v e r : =De t e ct). Далее вызывается продедура I n i t G r aph, ко
торая выполняет следующие действия:
1 . Анализирует первый переданный ей параметр с целью определе
ния, какой драйвер из таблицы драйверов необходимо запустить.
Обнаружив нулевое значение данного параметра, определяет воз
можности графической карты, установленной на компьютере.
2. Выбирает драйвер из таблицы драйверов, который соответствует
возможностям графической карты, и запускает его.
3. Обращается к драйверу с требованием инициализировать графи
ческий режим.
После этого, если не случилось никаких ошибок, экран готов к выводу гра
фической информации. Тем не менее программа сразу же заканчивается
1 14
Глава 5 . Графика в Tu rbo Pascal . В ы вод информации в граф и че с ком режиме
и все, что увидит пользователь, - это удаление информации с экрана, кото
рое всегда nроисходит при смене режима экрана. Однако так будет не всег
да, а только при запуске программы из оболочки, которая восстанавливает
режим экрана после запуска программ (так делает, например, Windows).
Если же программа запущена не из такой оболочки, а, например, из Norton
Comm aшler, то пользователь увидит предложение нажать на клавитпу
Ent e r для окончательного выхода из програм:мы ( P r e s s Ent e r t o r e t urn
t o Norton C omma n d e r
нажмите �Enter� для возвращения в Norton
Commander).
-
ЗАКРЫТИ Е ГРАФ ИЧЕСКОГО РЕЖИМА. П РОЦЕДУРА CLOSEGRAPH
В графическом режиме, тат< же как и в текстовом, существует понятие теку
щего цвета (мы поговорим об этом ниже), и если данный цвет в результате
изменения его программ ой совпадет с цветом фона, на который выводится
надпись P r e s s E n t e r to r e t u r n to N o r t o n Comm a n d e r, то пользова
тель не увидит сообщения и решит, что компьютер завис. Чтобы избежатъ
данной ситуации, в м оду ле Graph предусмотрена процедура C l o s eGraph
(от англ. Close Graphics - закрыть графику) без параметров, закрывающая
графический режим и восстанавливающая предыдущий текстовый:
C l o s eGraph ;
Таким образом, рекомендуется вызывать дан ну ю процедуру в конце про
граммы, когда графический режим уже не будет использоваться. Соответс
твенно предыдущий пример должен заканчиваться строками:
C l o s eGraph ;
End .
{ з акр ы в а ем гр афич е с кий р е жим }
{ к онец р а здела о п и с ания л о гики пр о г р аммы }
П РИМЕЧАНИЕ.
Чтоб ы вы смо гл и • nочувствовать» граф ически й режи м , м ежду о п е раторам и и н и
циал и з ации графического режима Ini tGraph ( GraphDrive r , GraphМode ,
" )
и з а кр ыти я графического режи ма Cl oseGraph встав ьте , н а п р и м е р , фун кци ю
ReadКey, рассмотренну ранее . П р и этом о братите в н и ма н и е , что фун кция ReadКey
н аходится в модуле CRT , которы й необходи мо подкл юч ить в месте с модулем
Graph . Для этого в ра зделе п одключения модулей us e s их нужно ука з ать через з а
п ятую (в л юбом порядке ) .
В ОЗМОЖН Ы Е ПРОБЛЕМЫ
И
ИХ РЕШЕНИЯ
Итак, после выполнения процедуры I n i t G r aph экран переводится в гра
фический р ежим и готов к выводу графических объектов. Однако в мо
мент выполнения данной процедуры могут возникнуть некоторые ошиб1 15
Turbo Pascal 7 . 0
ки. Самая распространенная из них состоит в невозможности поиска
графического драйвера E g aV g a . b g i (или другого, если первый параметр
процедуры Ini tGraph имеет неиулевое значение).
Если программа не может обнаружить драйвер, то ошибка не появляется
сразу же. Мы увидим ее при попытке вывести на экран графический о б ъ е кт .
Вместо вывода объекта в текстовом режиме экрана (графический в едь не
установился) будет выведено сообщение: «BGI E r r o r : G r a p h i c s 11o t
initiali zed
( u s e I n i t G r aph ) » - « Ошибка графического интерфей
са: доступ к гр афиче ским функциям невозможен (используйте процсдуру
InitGraph) � . Мы опять столкнулись с фор м ал ьн ы м подходом программ
к ошибкам: процедура I n i t G raph выполнена, по графический режим не
установлен. Однако нам рекомендуют все-таки использовать процедуру
Ini tGraph.
Бороться с данной ошибкой легко - необходимо проверить коррект
ность третьего параметра процедуры Ini tGraph, то ес т ь правильиость
пути к графическому драйверу. Ос т ал ьные ошибки встречаются к р а й н е
редко и требуют уникального подхода к их устранению, поэтому рас
сматривать их здесь бесполезно.
5 . 3 . ПАРАМ ЕТ Р Ы ГРАФ И Ч ЕСКИ Х О БЪЕКТО В
И ИХ З АдАН И Е
5 . 3 . 1 . ОБЩИЕ ПОЛОЖЕНИЯ
Сраау отметим, что в графическом режиме недопустимо использова
ние ранее рассмотренных процедур текстового вывода Wri te, Wri teLn,
ClrS cr, Go toXY, TextColor и TextBackground. Их использование как
минимум не приведет ни к какому результату, а выаов некоторых процедур
может привести к зависанию
компьютера. Это не значит, что
в графическом режиме не су
щ е с тву е т возможностей вывода
текста, наоборот, у программис
та намного больше возможнос
тей вывода текст а в гра ф ич е с
ком режиме, чем в текстовом
(см. рис. 4 1 , 1 02 , 1 03, 1 04 ) , но
ДЛЯ ЭТОГО ИСПОЛЬЗ У ЮТСЯ специ
Рис. 4 1 . Пример использования текста
в графическом режиме
1 16
альные процедуры, содержащи
сся в модуле Graph.
Глава 5 . Графика в Tu rbo Pasca l . В ыв од и н ф о рмаци и в граф и че с ком режим е
111rbo Pascal имеет довольно широкий набор графических о бъе ктов . Ср еди
можно выделить следую щи е группы:
•
т очки и линии;
них
•
з ам кнут ы е многоугольники и изометрические проекции куб а;
•
о кружн ости , круги,
•
те к ст ;
•
эл
л ипсы , дуги и сектора;
сл ож н ы е изображения, состоящие из любого сочетания вы ш еп ер е численных объектов.
Все гр афич е с ки е объекты являются плоскими, то е сть существуют в двух
мерном пространстве. Таким образом, каждая точка выводимого объек
та имеет всего две к оорд ин аты - по горизонтали (х) и по вертикали (У).
Кон фигурац ия ф и гур задается опорными точками - точками, однозначно
определяющими п ол о ж ение и форму ф игуры . Например, для построения
отрезка прямой ли нии достаточно двух опорных точек - начала и к о н ца
отрезка, а для ломаной линии н е о б х одим о указать все точки, в кот о р ы х про
и сх од и т излом.
Для п о ст р о ения некоторь1х фигур н аряду с опорными точками могут зада
ваться дополнительные параметры. Так, для построения окруж н о сти н е об
ходимо задать од ну опорную точку - центр окружности и один дополни
тельный параметр - радиус окружности.
Визуальное пр ед ст ав ле н и е всех объектов, за исключени
ем текста, определяется двумя пар а;\1 етр ами : обводкой линией контура ф и гур ы и заливкой - заполнением
внутренней области фигуры. Н ап ри мер , при выводе пря
моугольника его ра;\1.ка рисуется с помоrцью обводки, а
внутренняя область - заливкой (см. рис. 42).
Визуалыюе п р ед ст ав л ени е текста определяется п арам е т
шриф т а , используемого для в ы в од а , и будет обсуж
рами
даться н иже, в рааделе, по свяiц е нп о м выводу текстовой
информации. Пока же рассмотрим методы р аб оты с об водко й и заливко й .
Рис. 42. Структура
графическо го
объекта
5 . 3 . 2 . ОБВОДКА
О б в од к а является тек ущ им параметром, то есть влияет только на те
о б ъ е кт ы , которые выводятся па экран по сл е ее изменения, и характе
ризуется тремя параметрами - толщиной, стилем (порядком и длиной
ш тр и х о в , и э к о т о р ы х состоит выводимая линия) и ц в е т о м . Рассмотрим
д а н н ы е п а р ам е тр ы .
1 17
Turbo Pascal 7 . 0
ЦвЕТ о Б водки . П РОЦЕДУРА SEТCOLOR
Цвет обводки устанавливается продедурой S e tColor (от англ. S e t
Color - установить цвет) , находящейся в модуле Graph:
S e t C o l o r ( <H oмep ц в е т а > ) ;
Параметр Номер цве'J!а эквивалентен аналогичному параметру процеду
ры TextColor модуля CRT, то есть может являться целочисленной пере
менной или константой, имеющей значение от О до 15, причем константа
может задаваться либо именем, либо непосредственным значением. Цвета
в графическом режиме являются такими же, как и в текстовом, поэтому до
пустимо использование цветовых констант Black, Blue, Green, Cyan и т.д.
модуля CRT. Напомним, что для использования цветовых констант модуль
CRT должен быть подключен к программе в разделе подключения модулей.
Интересной особенностью графического режима является использование
цвета с н ом ер ом О (константа Black ) , который является фоновым, вне за
висимости от того, какой именно цвет имеет сам фон. В результате, если
цвет обводки установлен в О, выводимые объекты, имеющие обводку такого
цвета, не будут видны на экране, а сотрут изображение, находящееся в том
месте, куда они выводятся, то есть на экран вообще нельзя вывести изоб
ражение черного цвета. Вместо него можно воспользоваться темно-серым
цветом (константа DarkGray ) или переопределить какой-либо другой цвет
с помощью процедуры SetRGBPalette, описанной ниже.
Л истинг 036. ИзмЕНЕНИЕ цвЕТА оБводки
Program ChangeCo l o r ;
{ з а г о л о в ок прогр аммы , имя про гр аммы - ChangeC o l o r }
{ н ачало р а з д ела подключения модулей }
Uses
Graph ,
{ подключ ение модул ей Gr aph и CRT }
CRT ;
{ н ачало р а з дела опи с ания п ер еменных }
Var
GraphDrive r ,
GraphМode :
Intege r ;
{ опи с ание двух целочисл енных леременных :
Gr aphDriver- для передачи в к а ч е с т в е параметр а ,
опр еделяющ е г о номер графич е с к о г о др айв ер а ,
и Gr aphМode - для n ер е д ачи в к а ч е с т в е параметр а ,
опр еделяющ е г о номер графич е с к о г о р ежима }
{ начало раздела опис ания л о г ики программы }
Begin
GraphDriver
: =
Detect ;
{ при с в о ение п ер еменной GraphDr i v e r з н ач ения О
с исполь з о в анием конст анты D e t e c t модуля G r aph
GraphМode
.-
для на глядн о с ти }
О ; { пр и с в о ение пер еменной GraphМo de знач ения О ,
опр еделяющ е г о необходимый графич е с кий р ежим 6 4 0 х 4 8 0хl б ц в е т о в }
1 18
Глава 5. Графи ка в Turbo Pascal . Вывод и нформации в графи ческом режи м е
InitGraph { GraphDri ver ,
GraphMo d e ,
' ' ) ;
{ вы з о в пр оцедуры I n i t Gr aph ,
опр еделяющей драйвер ,
у с тройств а ,
а в т ома'I•ич е с ки
подходящий для вид е о
у с тановл енно го н а комnьютер е ;
з а пу с к ающей др айвер и инициализ ирующей
гр афич е с кий р ежим с н омером О }
S e t C o l or ( Re d ) ;
{ у становка н о в о г о текущего ц в е т а о б в одки
кра сн о г о
( для указ ания ц в е т а и споль з о в ан а
константа Red ) }
{ пр о гр амма прио стана влив а е т с я до наж атия
ReadKey ;
пол ь з о в ателем клавиши }
C l o s eGraph ;
{ з акры в а ем гр а фич е с кий режим }
End .
{ конец р а з дела опи с ания ло гики пр ограммы }
ТолщинА и стиль линии о s вод ки
Для изменения толщины и стиля обводки используется процедура
SetLineS tyle (анrл. Set Line Style - установить тип линии) , имеющая
следующий вид:
Se tLine S tyl e ( < Стиль линии > ,
<Обра з ец с тиля > ,
<'Голщин а > ) ;
Все параметры процедуры SetLineStyle должны являться целочислен
ными персменными или константами.
П РИМЕЧАНИЕ.
Н ачи ная с этого места , м ы больше н е будем п овторять, что есл и в кач естве пара
м етра до пусти мо и сп ол ьзован и е константы , а не тол ько перем е н но й ( ка к , н ап р и
м е р , в п р оцедуре l n itGraph ) , то константу м ожн о испол ьзо вать л и бо по и м ен и , л и б о
н еп осредствен н ы м з начен и ем . В ыб ор м етода указан и я - дело в куса п рогра м м и с
та, но следует запо м н ить, что есл и ка кая-л и б о кон станта и сп ол ьзуется в програм
м е хотя б ы дважд ы , то лучш е п рисво ить ей и м я .
Параметр Т олщина определяет толщину обводки и должен принимать зна
чение 1 (тонкая линия) или 3 (толстая линия). Для повышения читабель
ности программ, в модуле Graph описаны две константы: NormWidth = 1
для устюювi<:и тонкой линии и ThickWidth = 3 для установки толстой
линии.
Параметр C'J!ИJIЬ линии определяет порядок чередования штрихов, кото
рыми рисуется обводка, и их длину. Значение данного параметра должно
быть следующим:
О .
сплошная линия,
1
.
.
пунктирная линия,
2
.
.
. штрих-пунктирная линия,
3
.
штриховая линия,
4 .
определяемая использующей программ ой
(работа с этим стилем описана ниже).
. .
. . . . . . . . . . . .
. . . .
. . . . . .
. . . .
. . .
. . . . . . . . .
.
. . .
. . .
. .
. . . . .
. . . . . . . . . . . . .
1 19
Turbo Pasca/ 7 . 0
SetuneStyle(Solidln, О , NormWidth)
Для повышения читаб ельности п р огр амм и
использования процедуры
1 SetLineStyle(Solidln, О, ThickWidth) 1 Se tLineS tyle указывать стиль линии можно, соответственно, использ уя константы
r················· · · · · · · · · · · · · · · · · · · · · · · ·· -.
: setuneStyle(DottedLn, о, NormWidth) : SolidLn, DottedLn, CenterLn, D ashedLn
l' . . . . . . . . . . . . . . . . . . . . .. и UserBi tLn. Примеры использования разsetLineStyle(DottedLn , о , ThickWidth) • ных типов о б водки показаны н а р ис. 43 .
•
б олее удо б ного
·------------------------------------------·
• • • • • • • • • • • • • • • • • • • • •
#
б
стили использ у ется
Г set;:;es;,le(Cen-;erLn, o:-N;;;;w-;;щ� l П ар аметр О разец
- - - - - - - - - - - только совместно со стилем Us e rBi tLn
- · - · - · - · - · - ·
• setuneStyle(CenterLn, о , ThickWidth) 1
для указания осо б ых стилеи линии. Е сли
· · - · - · - · - · - · �
ук а занныл с т и л ь линии отличается от
- -- - - --------- -.
:-�e_:L�e�ty
� ��h:_d�:_? :...N. �':w��J .J UserBi tLn, то данны й пар амет р не использ у ется и, соответственно, м ожет иметь лю
�··••••••••••••
1 SetuneStyle(DashedLn, О, ThickWidth) 1
б ое ЗН ачение .
. _ _ _ _ _ _ _ _ _ _ _ _ _ ""
u
�
v
Рис. 43. Применение различных
стилей обвод ки
П р имер изменений хар актер истик текущей
о б водн:и приведен в листинге 037.
Л ИСТИНГ 0 3 7 . ИЗМЕНЕНИЕ ХАРАКТЕРИСТИК ТЕКУЩЕЙ ОБВОДКИ
Program ChangeLineS tyl e l ;
{ з а г о л о в о к про граммы , имя пр о гр аммы ChangeL i n e S ty l e l }
{ н ачало р а з дела п одключ ения модУл ей }
{ подключ ение модУлей Graph и CRT }
{ начало р а з д ела опис ания п ер еменных }
Uses
Graph ,
CRT ;
Var
GraphDriver ,
GraphDriver
. - Det e c t ;
{ прис в о ени е переменной GraphD r i v e r знач ения О
с исполь з о в анием конс танты D e t e c t МОдУЛЯ G r aph
для на глядно сти }
. - О ; { при с в о ение п ер еменной GraphМode знач ения О ,
определяющ е г о необходимый графич е с кий р ежим 6 4 0х4 8 0 х l б ц в е то в }
Ini tGraph ( GraphDrive r ,
S e t C o l o r ( Red ) ;
1 20
Int e ger ;
{ опис ание двух ц елочи с л енных п ер еменных :
GraphD r i v e r - для пер едачи в к ач е с т в е п ар аметра ,
опред еляющ е г о номер графич е с к о г о др а й в ер а ,
и G r aphМo de - для пер едачи в к ач е с т в е параметра ,
определяющего номер графич е с к о г о режима }
{ начало р а з д ела опис ания ло гики пр огр аммы }
Begin
GraphМode
GraphМode :
GraphМode ,
' ' ) ;
{ вы з о в пр оцедУры I n i t Graph , а в томатич е с ки
опр ед еляющей драйв ер , подходящий
для видеоу с тр о й с т в а , у с тановленн о г о н а к омпьютер е ;
з апу ск ающей др айвер и инициали з ирующей
графич е с кий режим с номером 0 }
{ у с т ановка н о в о г о т е кущего ц в е т а о б в одки
кра с н о г о ( для указ ания ц в е т а исполь з о в а н а
константа Red ) }
Глава 5. Графика в Turbo Pascal . В ы вод и нформации в графиче с ком режи ме
SetLineStyl e ( CenterLn , О , Thi ckWidth ) ;
{ у становка т екущей толщины линии ( Th i c kWi dth т о л с т ая линия ) и с тиля линии ( C en t e rLn штрихпунктирная линия ) , параме'.rр Обра з ец с тиля
игнориру ется , поэтому можно з адать люб о е знач ение ,
в данном с лу ч а е - О )
{ пр о грамма при о с т ана вли в а е т с я до н а ж а тия
ReadKey ;
поль з о в ателем кла виши )
{ з акрыв а ем гр афич е с кий р ежим )
C l o s eGraph ;
End .
{ к онец р а з д е л а опис ания ло гики пр о гр аммы )
Однако если параметр
с�иль
линии
имеет значение UserBi tLn, то для
установки стиля л ини и используется параметр О бразец с�иля:. Для пони
смысла параметра о бразец с�я: необходимо иметь представле
ние о системах счисления. Их описание было приведено в третьей главе.
мания
П РОГРАМ М Н О ОП РЕДЕЛЯЕМЫ Е СТИЛИ ОБВОДКИ
Когда параметр С�иль линии данной процедуры равен UserBi tLn, все
процедуры построения обводr<И, способные использовать текущие парамет
ры вывода линии, рассматривают двоичное представление пара.\1 етра О б
разец с�иля: (несмотря на то, что данный параметр задается числом в де
сятичной системе). Двоичные представления пара..\1етра выкладываются
друг за другом. Причем та.\1, где значение очередного бита равняется едини
це, точка рисуется на экране, а там, где бит нулевой - точка не рисуется.
Для указания образца используется 1 6-битовое число. Н апример, в качест
ве О бразца с�иля: можно использовать число 255, двоичное 1 6-битовое
представление которого - 00000000 1 1 1 1 1 1 1 1 . Соответственно, линия, вы
водимая по данному образцу, будет состоять из отрезков одинаковой длины
(по 8 точек) через одинаковые интервалы (также по 8 точек). Еще раз об
ратим внимание, что задавать в качестве данного параметра нужно число
в десятичной системе счисления, а рассматриваться оно будет в двоичной.
Рассмотрим пример установки параметров текущей обводки (см. лис
тинг 038) зеленого цвета повышенной толщины и начертания, задаваемого
программно изменяемым шаблоном, рассмотренным выше.
ЛИСТИНГ 038. УСТАНОВКА ПРОГРАММНО ОПРЕДЕЛЯЕМОЙ ТЕКУЩЕЙ ОБВОДКИ
Program ChangeLineStyl e 2 ;
Us e s
Graph ,
Var
{ з а г о л о в ок программы , имя пр о гр аммы Chang e L i n e S ty l e 2 )
{ начало р а з дела п одключения моду л е й )
CRT ;
GraphDriver ,
{ под к люч ени е модул ей Graph и CRT )
{ н ачало ра здела опис ания п ер еменных )
Integer ;
GraphМode :
{ опи с ание двух целочис л енных пер еменных :
Graph D r i v e r - для пер едачи в кач е с т в е п ар аметра ,
опр ед еляюще г о номер графич е с к о г о др а й в ер а ,
1 21
Turbo Pascal 7 . 0
и Gr aphMode - для передачи в к а ч е с т в е параметра ,
Begin
GraphDriver
GraphМode
: =
:
опр еделяющего номер гр афич е с к о г о р е жима }
{ начало р а з д ел а опис ания л о гики программы }
= Det e c t ;
{ при с в о ени е пер еменной GraphD r i v e r знач ения О
с исполь з о в анием константы D e t e c t модуля
Graph для наглядно с ти }
О ; { при с в о ение переменной Gr aphМode знач ения О ,
опр ед еляющ е г о н е о бходимый гра фич е с кий р ежим б 4 0х4 8 0х1 б цветов }
GraphМode , ' ' ) ;
{ вы з о в процедуры I n i t Gr aph , а в т оматич е с ки
определяющей др айв ер , подходящий для виде о
у с тр о й с т в а , у с т ановл енн о г о н а компьютер е ;
Ini t Graph ( GraphDrive r ,
з апу скающей драйвер и инициали з ирующей
гр афич е с кий р ежим с н омером О }
SetColor ( Green ) ; { у становка н о в о г о т е кущего ц в е т а о б в одки
з ел е н о г о ( для у к а з ания ц в е т а исполь з о в ан а
константа G r e en ) }
S e t LineStyl e ( Us erB i t Ln , 2 5 5 , ThickWidth ) ;
{ у с тановка текущей толщины линии ( Th i c kW i dth толстая линия ) и с тиля линии ( U s e rB i t L n исполь з о в ать шаблон ) , шаблон , з аданный числом 2 5 5 ,
р а с сматри в а е т с я как 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 , то е с ть
пунктирная линия по 8 точек ч ер е з такие ж е
интер в алы }
ReadKey ;
{ пр о гр амма прио станавли в а е т с я до н а ж атия
поль з о в ат е л ем клавиши }
C l o s eGraph ;
{ з акры в а ем графич е с кий режим }
End .
{ конец р а з дела опис ания л о гики программы }
5 . 3 . 3 . ЗАЛИВКА
З АДАНИ Е СТИЛЯ И ЦВЕТА З АЛ И ВКИ
Заливка, так же как и обводка, является текущим параметром, то есть влияет
только на те объекты, которые выводятся на экран после ее изменения. За
ливка характеризуется двумя параметрами - стилем (некоторым шаблонным
рисунком, которым заполняются внутренние области объектов) и цветом.
Обе характеристики устанавливаются процедурой SetFillStyle (апгл.
Set Fill S tyle - установить стиль заливки), им еюще й следующий вид:
S e t F i l l Styl e ( < O бp a з eц з аливки > ,
<Цвет з аливки> ) ;
П араметр Цв е� з апив ки является целочисленной переменпой или конс
тантой, имеющей значение от О до 15, и используется аналогично парамет
ру Номер цве�а процедуры SetColor. Напомним, что цвет с номером О
является фоновым, и объекты, имеющие заливку с таким цветом, будут
при выводе на экран стирать изображение, находящееся под ними.
1 22
Глава 5. Графика в Tu rbo Pascal . Вы вод и нформации в графическом режи ме
Параметр О бразец з апивки представляет собой целочисленную персмен
ную или константу, имеющую значение от О до 12. Образцы заливки с номе
рами от О до 1 1 являются стандартными (изначально заложенными в Turbo
Pascal). Образец с номером 1 2 определяет изменяемую заливку. Для удобс
тва использования процедуры SetFillStyle и повышения читабельности
программ в модуле Graph оп и с аны специальные константы, имеющие зна
чения, соответственно, от О до 1 2 . Рассмотрим заливки (см. табл. 2 ) , кото
рые используются при выводе на экран, номера, которые им соответствуют,
и константы, которые можно использовать вместо этих номеров.
Таблица 2. Стандартные стШtи заливки и соответствующие
ты модуля Graph
Заливка
.....!:19!1.�'з..� . .Г.?.Р.1::'.�.?..':1.!.�!.1-�-�!�-···--····-····--····-··-···-····.
Полосы накл о н н ы е тон к и е
Полосы
накл о н н ы е толстые
Пол осы обрат н ы е накл о н н ы е оче н ь толстые
''''''''''''''''''''''' '' ''''''''''''''''''''''''''''''' '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''н
чередующиеся
''''''''''''''''''''''''''''''''''''''''-'''''''''''''''''''''''''''
?.... . . .
______" __
З
4
...
5
. _
' '''''''''''''''''''''''''''""""""""""""""""
---�i!�.�!:i.l _l __.... .... ... . .......... ....... .
LtSiasi1Fill
Slashf-1 11
BkSiзshRII
LtBkSiasll FII I
----i
t
----------+----1----'-...:..: · ·.-'::-----l
.�. -------- .':'.-а-л-?-� .':1.�я. . �Р. .'!..:. н
J-..-=-'--..':I.а. . . ... . .. . .... .....
��
.. .... � .. .
. . .
. .
..
. .
.
.
.
.... . .. . ... . . . - . ....
l rl terleaveFill
9
10
Wid eDotFil l
Точки р�ие
Точки част ы е
Close DotFil l
11
�;;�;
Полосы обратн ые наkлонные
Проrраммно оn ределяемая зали вка
(то н ка я · толста я · то н ка я )
6
констан
Константа
Номер
···------·-----··---·--..---··------·- ·---· -· --..- ·-- ·
им.
;
:�:;:��
12
UsfнFill
Примеры заливок представлены на рис. 44 (каждое число выведено с залив
кой соответствую1цеrо номера).
Рис . 44. Использование ра зличных с тилей заливки
Рассмотрим пример установки параметров текущей заливки в виде ячеек
сершо цвета (см. 9 на рис. 44). Текст примера приведен в листинге 039.
1 23
Turbo Pascal 7 . 0
ЛИСТИНГ 039. И ЗМЕНЕНИЕ ХАРАКТЕРИСТИК ТЕКУЩЕЙ ЗАЛИВКИ
Program Change F i 1 1 Styl e 1 ;
{ з а г о л о в о к nр огр аммы ,
имя nр о гр аммы -
ChangeF i l l S ty l e l }
Uses
Graph ,
{ начало р а здела nодключения моду л е й }
CRT ;
{ подключение модулей Graph и CRT }
Var
{ начало р а з дела опис ания п ер еменных }
GraphDriver ,
GraphМode :
Int e ger ;
{ опис ание двух цел очи сленных пер еменных :
G r aphDriver - для п ер едачи в кач е с т в е параметр а ,
опр ед еляющ е г о номер графич е с к о г о др айв ер а ,
и G raphМo de - для п ередачи в кач е с т в е параметра ,
оnр ед еляющ е г о номер графич е с к о г о р ежима }
Begin
{ начало р а з д ел а опис ания л о гики nр о гр аммы }
GraphDriver
: =
Det e c t ;
{ прис в о ение переменной G r aphD r i v e r з н ач ения О
с испол ь з о в анием конс танты D e t e c t модуля
Gr aph для на глядн о с ти }
GraphМode
: =
О ; { nрис в о ение п еременной G r aphМode знач ения О ,
опр еделяющ е г о н е о бходи��й графич е с кий р ежим
6 4 0 х4 8 0 х1 6 цвето в }
Init Graph { GraphDrive r ,
GraphМode ,
' ' ) ;
{ вы з о в nр оцедуры I n i t Gr aph ,
опр ед еляющей др айвер ,
у с тройств а ,
автоматич е с ки
подходящий для вид е о
установленного на к омпьютер е ;
з а пу с к ающей др а й в ер и инициали з ирующ ей
графич е с кий р ежим с н омером О }
S e t F i l l S tyl e { I nt e r l e aveF i l l ,
Gray ) ;
{ у с тановка т е кущей з аливки с ер о г о ц в е т а
( опр еделяет ся вт орьм параметром ,
в качестве
которого испол ь з о вана константа Gray модуля CRT )
и нач ертанием в вид е яч е е к ( п ервый параметр ,
в к ач е с т в е котор о г о исполь з о в а н а константа.
Int e r l e aveF i l l модуля Graph ) }
ReadKey ;
{ проrрамм а nриостанавлив а е т с я до наж атия
поль з о в ат е л ем клавиши }
C l o s eGraph ;
{ з акрыв а ем графич е с кий р е жим }
End .
{ конец р а з дела опис ания л о гики nр ограммы }
ПРОГРАМ МНО О ПРЕДЕЛЯЕМЫЕ СТИЛИ ЗАЛИВКИ
Мы уже научились изменять цвет и стиль текущей заливки с помощью прtще
дуры SetFillStyle при использовании стандартных стилей заливки (с но
мерами от О до 1 1 ). Что касается программно определяемого стиля с номером
12, то обсуждение некоторых аспектов метода его установки выходит за пре
делы знаний, которыми мы обладаем на данный момент. Однако мы все же
рассмотрим, как установить собственную заливку, а для начала раэберсмся,
что именно представляет собой процесс заполнения графического объекта.
1 24
Глава 5 . Граф и ка в Tu rbo Pasca l . Вы вод и нформации в графиче с ком режиме
Допустим, мы собираемся вывести на экран прямоугольник, заполненный
заливкой. При вызове процедуры, выводящей прямоугольник на экран,
наша программа автоматически обращается к подпрограмме заливки гра
фических объектов. Нам не нужно для этого ничего делать, кроме предва
ритеJiьного выбора самой за..ч:ивки продедурой SetFi l l S tyle.
ПРИМЕЧАНИЕ.
Здесь м ы видим очередное n роявление высокоуро вневости Tu rbo Pascal . Ведь
на любо м я з ыке н и зко го уро в н я , наnример AssemЫer, п од nр о грам м у з ал и вки и
ее вызов п р и ходится реал и з о в ы вать самостоятел ь н о , что связано с разраб откой
слож ного алгоритма и передачей бол ьшого объема и н формации в такую п одnро
гра м му.
Подпрограмма заливки использует для своей работы шаблон заливки.
С шаблонами мы уже знакомы - это те самые стандартные стили заливок,
рассмотренные нами выше. Однако заливку можно установить и самостоя
тельно. Шаблон заливки представляет собой квадратную область размером
В па 8 точек, заполненную точками одного цвета. Именно такими квадрата
ми и заполняются внутренние области объектов.
Для создания и установки текущим нестандартного шаблона заливки ис
пользуется процедура S e tFillPa ttern (от англ. Set Fill Pattern - устано
вить образец заливки), имеющая два параметра:
S et F i l l P a t t e rn ( <Шaблoн з аливки> ,
< Ц в е т з аливки> ) ;
Параметр Цвет з алив ки используется так же, как и аналогичные пара
метры, используемые в процедурах, устанавливающих какие-либо цвето
вые характеристики. Параметр Ша блон з аливки представляет собой сово
купность восьми чисел, определяющих начертание, соответственно, восьми
горизонтальных полос квадрата шаблона. Данные числа имеют такой же
смысл, как и обраэец обводки, эа исключением того, что являются Восьми
битовыми (то есть могут иметь значения от О до 255), а не шестнадцатиби
товыми, как в случае S e tLineS tyle. В качестве пара.'\l!етра должна исполь
эоваться типиэированная константа, предварительно описанная в разделе
описания констант Con s t следующим образом:
Con s t
<Имя к о н с ·ганты> :
F i l l P a t t e rnТype
( <По л о с а 1 > ,
. . . ,
< П ол о с а 2 > ,
< П ол о с а 8 > ) ;
Далее имя описанпой константы задается в качестве первого параметра
процедуры SetFillPattern.
Рассмотрим пример. Допустим, нам необходимо установить текущую
заливку белого цвета в виде латинской буквы « F'-> . Н арисуем квадрат
8х8 и заполним его единицами там, где в шаблоне должны присутство
вать точки , и н улями там, где точек быть не должно.
1 25
Turbo Pascal 7 . 0
М ы получили восемь чисел, записанных в двоич
ной системе счисления. Персводя их в десятичную
систем� получаем: О, 1 24, 96, 96, 1 2 0, 96, 96, 0. Если
теперь воспользоваться данпой заливкой, выведя
на экран фигуру, имеющую внутреннюю область, то
это будет выглядеть так, как пока.зано на рис. 45.
Рис . 45. Нестандартная
заливка
Напишем программу, устанавливающую такую
ливку ( СМ. ЛИСТИНГ 040).
за
ЛИСТИНГ 040. УСТАНОВКА ПРОГРАММНО ОПРЕДЕЛЯЕМОЙ ТЕКУЩЕЙ ЗАЛИВКИ
Program ChangeF i l l Styl e 2 ;
{ з а г о л о в о к nрогр аммы ,
имя nро граммы -
ChangeF i 1 1 S ty l e 2 }
Uses
Graph ,
{ начало р а з дела подключ ения модул е й }
CRT ;
{ подключение модул ей Graph и C RT }
Con s t
Patt ern :
{ начало р а з дела опис ания к о н с т ант )
F i l l P att ernТype
{ опис ание
=
(0,
124 ,
96,
типи зиров анной
96 ,
120 ,
в кач е с т в е знач ения в о с емь чи с ел ,
шаблон
Var
з аполн ения
для
96,
константы ,
нового
96 ,
О) ;
с о д ержащей
опр еделяющих
с тиля
з аливки }
{ начало р а з д е л а опис ания п ер еменных }
GraphDrive r ,
GraphМode :
Integer ;
{ опис ание двух целочисл енных п ер еменных :
Gr aphD r i v e r - для передачи в к ач е с т в е параметр а ,
опр ед еляющ е г о номер графич е с к о г о др а й в ер а ,
и G raphМo de - для перед ачи в к ач е с т в е параметра ,
опр е д еляющ е г о номер графич е с к о г о р е жима }
Begin
{ начало р а з д ела опис ания л о гики nр ограммы }
GraphDriver
: =
Detec t ;
{ nр и с в о ение п ер еменной GraphDriver знач ения О
с и с п о ль з о в анием к о н с т анты D e t e c t модуля G raph
для на глядн о с ти }
GraphМode
: =
О ; { при с в о ение п ер еменной GraphМode знач ения О ,
опр еделяющего необх одимый графич е с кий р ежим 6 4 0х 4 8 0 х 1 6 ц в е т о в }
Ini t Graph ( GraphDriver ,
GraphМode ,
' ' ) ;
{ вы з о в nроц едуры I n i t Gr aph ,
опр ед еляющей драйвер ,
для видеоу с трой с тв а ,
на компьют ере ;
а в томатич е ски
подходящий
у с т ановл енно г о
з апу скающей др айв ер
и инициализ ирующей графич е ский р ежим с номером 0 }
Red ) ;
Set F i l l P a t t ern ( Patt ern ,
{ с о з дание н о в о г о с тиля з аливки на о с н о в е шаблона
з аполнения ,
S e t F i l l Styl e ( Us e rFi l l ,
хранящ е г о с я в конс танте P a t t e rn }
LightGray ) ;
{ у с тано в к а т екущей з аливки nр о граммно
опр еделяемо г о стиля ( в к ач е с т в е пер в о г о пар аметра
1 26
Глава 5 . Граф и ка в Tu rbo Pascal . В ывод и н формаци и в графическом режи ме
исполь з о в ана
к о н с т анта
U s e rF i l l
модуля
Graph ) ,
ц в е т з аливки у ж е у с тановлен и не м о ж е т быть
изменен данной пр оцедурой .
Таким о бр а з ом ,
второй пар аметр игнориру е т с я ,
и з аливка
не буд ет иметь с ерый ц в е т }
ReadKey ;
{ пр о грамма приостанавли в а е т с я до н а ж атия
поль з о в ат е л ем кла виши }
C l o s eGraph ;
{ з акрыв а ем графич е с кий режим }
End .
{ к онец р а з д е л а опис ания л о гики пр о гр аммы }
5 . 3 . 4 . Ц ВЕТ ФОНА
И, наконец, рассмотрим последнюю характеристику экрана в графическом
режиме - цвет фона,- имеющую некоторые отличия от аналогичного па
раметра текстового режима. Цветом фона в графике называется область
экрана, на которую еще не выводилось изображение. Цвет фона не являет
ся текущей характеристикой, то есть при его смене результат отображается
на экране немедленно.
Для изменения цвета фона используется процедура SetBkColor (англ.
Set Back Color - установить фоновый цвет), имеющая всего один уже
хорошо знакомый на.'\<!: параметр Номер цвета:
SetBkC o l o r ( < H oмep ц в е т а > ) ;
5 .4 . КОО РДИ Н АТ Н АЯ П Л ОС КОСТ Ь
Экран в графическом режиме представляет собой прямоугольник, запол
ненный точками, которые еще называют пикселями (см. рис. 46). В мо
мент инициализации графического режима точки имеют черный цвет
(будем называть его фоновым) , а при выводе на экран объектов изменяют
свой цвет таким образом, чтобы объект
Увели"'ение горизонтал ьной координаты
отобразить.
Физически точки являются прямо
угольными, поэтому задача вывода на
экран, например, гладкой наклонной
прямой, невыполнима. При желании
эффект сглаживания изображения до
стигается выводом рядом с объектом,
который должен выглядеть гладким,
более светлой или более темной линии
( в зависимости от фона, на который вы
водится сглаживаемое изображение) .
Рис. 46. Экран в графическом режиме
1 27
Turbo Pascal 7 . 0
Между точками экрана имеется некоторое свободное пространство, недо
стушюе для вывода информации, размер которого зависит от использу
емого монитора (чем меньше интервалы между пикселями - тем лучше
монитор) . Данные отличия мониторов нисколько не влияют на перено
симость программ с одного компьютера на другой, и программист может
быть уверен, что конечный пользователь увидит то же самое изображение,
что видит он.
Экран монитора - устройство плоское, поэтому для определения положе
ния точки (пикселя) на экране достаточно всего двух координат - горизон
тальной (Х) и вертикальной (У).
В большинстве операционных систем принят отсчет координат от левого
верхнего угла экрана. При этом левая верхняя точка будет иметь нулевые
координаты как по горизонтали (х=О), так и по вертикали (У=О). Соот
ветственно, горизонтальная координата увеличивается вправо, а верти
кал:ьная - вниз. Первое время мы будем работать с разрешением экрана
640х480 точек, поэтому правая нижняя точка будет иметь координаты
(х=639, У=479) . Точка, находящаяся в центре экрана, будет иметь коорди
наты (х=З 1 9, У=239).
Теперь мы достаточно знаем о строении экрана и методах настройки его
характеристик, поэтому можем перейти к и зучению вывода графических
объектов.
5 . 5 . В Ы ВОД ТОЧ ЕК И Л И Н И Й
5 . 5 . 1 . В ы вод точЕк
Для вывода на экран точки (то есть, фактически, для изменения цвета како
го-либо пикселя) используется процедура PutPixel (от англ. Рнt Рiхеl
установить пиксель ) , вызываемая с тремя параметрами: Гориз о и'.l'альной
координа'.l' ой точки, цвет которой необходимо изменитъ, ее Вер'.l'икаль
но й координа'.l'о й и Ноиером цве'.l'а, который точка должна иметь:
Рut Рiхе l ( < Гориз онтальная ко ордин а т а > , < В ертикальная к о ординат а > ,
< Н омер ц в е т а > ) ;
Все параметры данной процедуры должны быть целочисленными перемен
пыми или константами. Например:
Put P i x e l ( S O ,
100 ,
Red ) ;
{ и зменение ц в е т а точки с координатами
( X= S O ,
1 28
Y=l O O )
на кра с ный }
Глава 5 . Графи ка в Turbo Pasca l . В ы вод и н формации в графиче с ком режи ме
Напомним, что фоном в графическом режиме считается область экрана, на
которую еще не выводилась информация, то есть если сначала вывести точ
ки определенного цвета (кроме нулевого), а потом изменить цвет фона, то
точки никуда не исчезнут.
5 . 5 . 2 . РАБОТА с ТЕКУЩИМ УКАЗАТЕЛЕМ
П о нятиЕ ТЕКУ ЩЕго УКАЗАТЕЛЯ
В графическом режиме имеется анаJюг текстового курсора (каретки), нося
щий название текущего указателя (от анrл. Current Point - СР). В отличие
от каретки СР не виден на экране, но имеет те же самые функции - опре
деляет позицию экрана, из которой будет производиться вывод некоторых
графических объектов.
Работа с текущим указателем осуществляется аналогично рисованию ка
рандашом на бумаге - карандаш может быть опущен или поднят, соот
ветственно, при персмещении оставляет за собой линию или не оставляет
(см. рис. 47: на левом рисунке каран
даш опущен на бумагу и, смещаясь, ос
тавляет за собой линию, далее каран
даш поднимается и смещается влево,
не оставляя линии) . Цвет выводимой
линии определяется рассмотренной
Рис. 47. Приемы работы
выше продедурой SetColor, а стиль с текущим указателем
продедурой S e tLineS tyle.
П РОЦЕДУРЫ СМЕЩЕНИЯ ТЕКУЩЕГО УКАЗАТЕЛЯ
Изначально после инициализации графического режима текущий указа
тель находится в левом верхнем углу экрана, то есть в точн:е с координатами
(Х= О , У= О ) . Его перемещение в заданную точку без рисования линии (эта
операция аналогична двум действиям - поднять карандаш и персместить
его в новое положение) осуществляется продедурой MoveTo (англ. Move
То - персместить в ... ) :
. . .
МоvеТо ( < Г о р и з онтальная к о ордин а т а > ,
< В ертикальная ко ордина т а > ) ;
В результате выполнения данной процедуры текущий указатель смещается
в точку, заданную параметрами Горизонта.n:ьна• координата и Верти
JСа.n:ьна• координата.
Иногда требуется сместить текущий указатель в точку, расположенную на
заданном расстоянии от его текущего положения. Для этого используется
5
Зах. 702
1 29
Turbo Pascal 7 . О
процедура MoveRel. (англ . Move Rel.ative - п ер с м е сти ть относительно)
с двумя параметрами, определяющими с м е щен и е с Р относительно текуще
го положения по гори зон т ал и и по вертикали:
МоvеRе l ( < Г ор и з онтальн о е смещени е > ,
< В ертикально е смещени е > ) ;
Данная процедура т р ебует некоторых пояснений. Дело в том, что ее пар а
метры могут иметь отрицательные значения, означающие, что п е р с м ещени е
текущего указателя должно происходить в направлении уменьшения соот
ветствуюуцих к о ордин ат . То естъ отрицательное значение п ар ам е тра Гори
зонтальное смещение заставляет текущий указателъ сместиться влево
на I<аличество точек, равное модулю значения, нах:одящегося в д анном па
раметре. Аналогична ситуац ия с п ар ам етром Вертикальное смещение.
Рассмотрим п р и м ер персмещения текущего у каэат еля в точку с к о о рд ин а
тами (X= l O O , У= 6 7 ) , а затем в положение, паходящееся па две точки л евее
и три точки вьппе данного положения, то есть в точку с координатами Х= 9 8 ,
У= б 4 ( см . листинг 04 1 ).
Листинг 041
•
ПеРемещение теКУщего УКАЗАТЕЛЯ
Program MovePoint e r l ;
{ з а г о л о в о к про граммы , имя пр о гр аммы - Move P o i n t e r l }
Uses
Graph ,
{ на ч а л о р а з д е л а подключ ения модул ей }
CRT ;
{ подключ ение модулей Graph и C RT }
Var
{ на ч а л о р а з д е л а опис ания п ер еменных }
GraphDrive r ,
GraphМode :
{ опис ание
Int eger ;
двух
GraphDri v e r
·
· -
целочисл енных п ер еменных :
для п ер едачи в к ач е с т в е пар аметра ,
опред еляющ е г о номер графич е с к о г о др а й в ер а ,
и Gr aphМo de - для п ер ед ачи в к ач е с т в е пар аметр а ,
опр е д е ляющ е г о номер графич е с к о г о р е жима }
{ на ч а л о р а з д е ла опис ания л о гики пр о гр аммы }
Begin
GraphDr iver
: =
De t e c t ;
{ пр и с в о ение п ер еменной GraphD r i v e r з н ач ения О
с и с п о л ь з о в анием к о н с т анты D e t e c t модуля
Graph для н а глядн о с ти }
GraphМode
:=
О ; { пр и с в о ение п ер еменной GraphМode з н а ч ения О ,
опред еляющ е г о н е о бх одимый гра фич е с кий р е жим 6 4 0 х 4 8 0 х l б цветов }
Init Graph ( GraphDriver ,
GraphМode ,
' ' ) ;
{ вы з о в пр оцедуры I n i t G r aph ,
о пр е д е ляющей др айв ер ,
а в т оматич е с ки
подходящий
для видеоу с тройс т в а , у с т а н о в л енно г о на компьютере ;
з а пу с к ающей др а й в ер и иници ализирующей
графич е с кий р е жим с номером О }
MoveTo ( 1 0 0 , 6 7 ) ; { п ер емещение т е куще г о ука з а т еля в точку
с к о ордина т ами
130
(100 ,
67 ) }
Глава 5 . Граф и ка в Tu rbo Pascal . Вы вод и н ф о рмаци и в граф и ч еском режиме
MoveRel ( - 2 , - 3 ) ; { п ер емещение текуще г о ука з а теля в по л о ж е ни е ,
находящееся на две точки л е в е е и три точки
выше н а с тоящего полож ения ,
с к о ординатами
( Х= 9 8 ,
т о есть в т очку
У= 6 4 ) }
{ пр о гр амма при о с тана влив а е т с я до н аж атия
ReadKey ;
поль з о в ат е л ем кла виши }
C l o s eGraph ;
{ з акрыв а ем гра.фич е с кий р ежим }
End .
{ к онец р а з д е л а опис ания л о гики пр о гр аммы }
Такого ж е результата можно было добиться, восп ользовавшись продедурой
MoveTo, как наказано в следующем примере:
MoveTo ( 1 0 0 , 6 7 ) ;
{ п ер емещение текущего у к а з ателя в точку
с к о ординатами
MoveTo ( 9 8 , 6 4 ) ;
(100 ,
67 ) }
{ п еремещение текущ е г о ука з ат еля в точку
с к о ординат ами
(Х=9 8 ,
У= 6 4 ) }
О П РЕДЕЛ ЕН И Е КООРД И Н АТ ТЕКУЩЕГО УКАЗАТЕЛЯ В ГРАФИЧ ЕСКО М РЕЖИ М Е
Так ж е как и для каретки в текстовом режиме, в модуль Graph включены
функции для определения текущего положения СР. Функция GetX (англ.
Get Х - получить Х) возвращает горизон т ал ь ную координ ату СР, а фун к
ция GetY (англ. Get У - получить У) - вертикальную. Обе фун к ции вызы
ваются без параметров:
Х
: =
GetX ;
{ з ан е с ение в п ер еменную Х з н ач ения ,
равного
гориз онтальной ко ордин а т е С Р }
У
. -
GetY ;
{ з ан е с ение в п еременну ю У знач ения ,
равного
в е р тик а льн ой к о ордин а т е С Р }
5 . 5 . 3 . П РО Ц ЕДУР Ы РИСОВАНИЯ ЛИНИ Й
Процедуры MoveTo и MoveRel. персмещают текупщй указатель без к аки х
либо изменений на экр ане , но есть аналогичные процедуры, рисующие при
персмещении СР линию текущего цвета и ст иля . Итак, продедура LineTo
(апгл. Line То . . . - линия в ... ) персмещает текущий указатель в точку, задан
ную параметрами данной процедуры, оставляя за собой линию:
L i nе То ( < Г ори з он т ал ь ная ко ордин ата > ,
<В ертикальная к о ордин а т а > ) ;
Эта операция алалогична такой последовательности действий: опустить ка
рандаш и персместить его в заданное положение.
И наконец, продедура LineRel. ( англ . Line Relative - персместить относи
тельно) персмещает текущий указатель в положение, заданное смещением,
указанным в качестве параметров, предварительно •опустив карандаш� :
LinеRе l ( < Г ори з онт а л ь н о е смещени е > ,
< В ертикальное смещени е > ) ;
131
Turbo Pascal 7 . 0
Рассмотрим программу, выводящую на экран изображение, показаинос
н а рис. 48. Данный рисунок строится по пяти опорным точкам, их коор
динаты подписаны на рисунке.
Х=З20, У=10
t
Х=10, У=170
Х=6ЗО, У=170
Рис. 4 В . Изображение « Конв ерт»
П РИМЕЧАНИЕ.
П еред те м как садить с я за н а п и сан ие п р о гр а м м ы , в ы водя щей какое - л ибо слож
н о е и зо б р аж е н и е , рекоме н дуетс я на ри с о в ат ь его н а л и сте м илл и м етров о й бум а
ги , за п и сат ь коорди на ты о п о р н ы х точек ф и гур и п р одум ат ь п о с л едов ател ьн о ст ь
в ы в ода о тдел ьн ых эл е м ентов изоб р ажен и я .
Мы будем рисовать конвертик от левой нижней точки, имеющей коорди
наты (X= l O , У= 4 7 0 ), персместив туда текущий указатель с помощью про
цедуры Моvет о . Далее будет использоваться только процедура LineRel,
с помощью которой будут прорисованы все остальные линии, образующие
фигуру. Последовательность рисования показана на рисунке тонкими ли
ниями.
И так, линия 1 рисуется в результате смещения текущего указателя вверх проце
дурой LineRel ( параметр Горизонтальное смещение - нулевой, пара.�етр
Вертикальное с:кещение - отрицательный и равный 1 7 0 - 4 7 0 = - 3 0 0 ) ;
линия 2 - смещением С Р на (32 0 - 1 0 = 3 1 0 , 1 0 - 1 7 0 = - 1 6 0 ) , и так
далее. Текст программы приведен в листинге 042.
ЛИСТИНГ 042. ПОСТРОЕНИЕ ИЗОБРАЖЕНИЯ <<КОНВЕРТ))
Program Cover 1 ; { з а г о л о в о к про граммы ,
Uses
Graph ,
CRT ;
Var
GraphDrive r ,
имя пр ограммы - C ov e r l }
{ нач а л о ра здела подключения модул ей }
{ подключ ение модул ей G raph и CRT }
{ начало р а з д е л а оnис ания nеременных }
GraphМode :
Int eger ;
{ оnис ани е двух целочисл енных nер еменных :
G r aphD r i ve r - для nер едачи в каче с т в е nар аметр а ,
1 32
Глава 5 . Графика в Turbo Pascal . В ы вод и н ф ормаци и в граф и ческом режи м е
о пр е д е ляющ е г о номер
гр афич е с к о г о др а й в е ра ,
и Gr aphМo d e - для n ер едачи в к ач е с т в е nараметр а ,
о пр ед е ляющ е г о номер
Begin
{ н ачало р а з д е л а
GraphDrive r
: =
графич е с к о г о р ежима }
оnис ания л о гики пр о гр аммы }
Det e c t ;
{ прис в о ение n е р еменной GraphD r i v e r
с
и с n о л ь з о в анием
к о н с т анты
Detect
з н а ч ения
модуля
О
Graph
для н а глядн о с ти }
GraphМode
:=
О ; { nри с в о ение nеременной G raphMo d e з н а ч ения О ,
оnр е д еляющ е г о н е обх одимый
графич е с кий р е жим -
6 4 0 х 4 8 0х l б цветов }
InitGraph { GraphDrive r ,
GraphМode ,
' ' } ;
{ вы з о в процедуры I n i t G r aph ,
опред еляющей др айв ер ,
а в т оматич е с ки
n одх одящий
для вид е оу с тр о й с т в а , у с т ан о в л енн о г о н а комn ь ю т е р е
з аnу с к а ющей др айв ер и иници ализ ирующ ей графич е с кий
р ежим с
номером
0}
S etBkC o l or { Whi t e } ;
{установка
белого цвета
в к ач е с т в е
т екущ е г о
для фона }
S et C o l o r ( DarkGray ) ;
( у с т ан о в к а т емн о - с ер о г о ц в е т а в
качестве
т е кущ е г о для выводимых линий }
S e t LineStyl e ( S o l i dLn ,
Thi c kWidth } ;
О ,
{ у становка
т е кущих толщины линии
т о л с т ая линия )
линия ) ,
nараметр Обра з ец с тиля и г нориру е т с я ,
n о э т ому можно
з адать
в д анном слу ч а е MoveTo { 1 0 , 4 7 0 } ;
( Th i c kW i dth -
( S o l i di,n - сnл ошная
и стиля линии
лю б о е
з н ач е н и е ,
О}
{ смещение т е куще го у ка з а т ел я в
л е вую нижнюю
точку рисунк а }
L i neRe l { 0 , - 3 0 0 } ;
{ nрорисовка линии 1 ( сnлошная , толстая , темно- с ерая ) }
LineRe l ( З l 0 , - 1 6 0 } ;
( nрорисовка линии 2 ( сnлошная , толстая , т емно - с ерая ) }
LineRe l ( 3 1 0 , 1 6 0 } ;
{ nрорис о вка линии 3 ( сnлошная , толстая , темно- с ерая ) }
LineRe l ( O , З O O } ; { nр ори с о в ка линии 4
( с nлошная ,
толстая ,
( с nл ошн а я ,
т о л с т ая ,
т емно - с ерая ) }
LineRe l ( - 6 2 0 , 0 } ; { пpopи c o в кa
линии
5
т емно - с ерая ) }
S e t LineS tyl e { C ent erLn ,
О,
Thi c kWidth } ;
{ у с т а н о в к а т е кущей т олщины линии
т о л с т а я линия )
и с тиля линии
штрихnунктирная линия ) ,
игнориру е т с я ,
значени е ,
в
парам е тр О бр а з ец с тиля
n о э т ому можно
з адать лю б о е
данном с луч а е - О }
LineRel ( 62 0 , - 3 0 0 } ; ( np opи c o в к a линии
т о л с тая ,
( Th i c kW i d t h -
( C en t e r Ln -
б
( штрих - nунктирна я ,
темно - с ерая ) }
1 33
Tu rbo Pascal 7 . 0
S e t LineStyl e ( S o l i dLn ,
О,
Thi ckWidth ) ;
{ у с т ан о в к а т екущей толщины линии
и с тиля линии
т о л с т ая линия )
линия ) ,
{ Th i c kW i d t h
-
{ S o l i dLn - с пл ошная
параметр Обр а з ец с тиля игн ориру е т с я ,
поэт ому можно з адать л ю б о е з н а ч е ни е ,
в
д а нн ом
случ а е - 0 }
LineRe l ( - 6 2 0 , 0 ) ; { пp opи c o в к a линии 7
{ спло шн ая ,
толстая ,
темно - с ерая ) }
S e t LineStyl e ( CenterLn ,
О,
Thi ckWidth ) ;
{ у с т ан о в к а т екущей т олщины линии
т о л с т а я линия )
и с тиля линии
штрихпунк тирная
игнориру е•rся ,
з н а ч е ни е ,
линия ) ,
пар аметр
-
О бр а з ец
с тиля
поэтому м о ж но з адать лю б о е
в данном с луч а е - 0 }
LinеRе1 ( 6 2 0 , 3 0 0 ) ; { прори с о в к а линии 8
т о л с т ая ,
{ Thi c kWi d t h -
{ C en t e rLn
( штрих - пунктирная ,
т емн о - с ер ая ) }
ReadKey ;
{ пр о гр амма прио с танав ли в а е т с я д о н а ж а тия
C l o s eGraph ;
{ з а кр ы в а ем графич е с кий р е ж им }
End .
{ к онец р а з д е л а опис ания л о гики пр о гр аммы }
поль з о в а т е л ем клавиши }
П РОЦ ЕДУ РА LINE
Закончим обсуждение методов вывода линий на экран описанием процеду
ры Line (от англ. Line - линия), позволяющей вывести отрезок прямой за
один вызов данной процедуры:
Linе ( < Гори з онт альная ко ордина т а 1 > ,
< В ертикальная ко орди н а т а 1 > ,
< Г ори з онт альная к о ордин а т а 2 > , < В ертикальная к о ордин а т а 2 > ) ;
Процедура Line выводит отрезок, соединяющий две точки - начальную,
имеющую координаты Горизонтальная: координата 1 и Вертикаль
ная: координата 1 , и конечную, имеющую координаты Гориз онталь
ная: координата 2 и Вертикальная: координата 2 .
Реализуем программу, строящую изображение, показанное на рис. 48 с ис
пользованием процедуры Line, а не процедур персмещения текущего
указателя, вызывавшихся в предыдущем варианте данной программы
(см. листинг 043 ) .
ЛИСТИНГ 043 . ПОСТРОЕНИЕ ИЗОБРАЖЕНИЯ «КОНВЕРТ»
Program Cove r 1 ; { з а г о л о в о к пр о гр аммы ,
Uses
Graph ,
имя программы
{ на ч а л о р а з дела подключения модулей }
CRT ;
Var
GraphDrive r ,
--
Cover1 }
( подключ ение модулей Graph и CRT }
{ на ч а л о р а з д е л а опис ания п ер еменных }
GraphМode :
Int eger ;
{ оп и с ание двух целочисл енных переменных :
1 34
Глава 5 . Граф и ка в Tu rbo Pascal. В ы вод и н ф ормаци и в граф и ческом режи м е
GraphDr iver
-
д л я nередачи в к а ч е с т в е nараметра ,
оnр еделяющ е г о номер гр афич е с к о г о др а й в ер а ,
и GraphМode
-
для передачи в к а ч е с т в е п ар аметр а ,
опр еделяющ е г о номер гр афич е с к о г о р ежима }
{ н ачало р а з д ела опис ания л о гики пр оrраммы }
Begin
GraphDr iver
: =
De t e c t ;
{ прис в о ение переменной G r aphDriver з н ач ения О
с и с п о ль з о в анием константы Det e c t модуля
Graph для наглядно сти }
GraphМode
: =
О ; { пр и с в о ение переменной GraphМo d e з н а ч ения О ,
опр е д е ляюще го н е о бходимый графич е с кий р ежим
-
6 4 0 х 4 8 0 х 1 6 цветов }
Ini tGraph ( GraphDr iver ,
GraphМode ,
' ' ) ;
{ вы з о в пр оцедуры I n i t G r aph ,
определяющей ,пр а й в ер ,
а в т ом а тич е с ки
п о дходящий
для вид е оу строй с т в а , у с тановленн о г о
на компьютер е ; з апу скающей др ай в ер
и инициализ ирующей графич е с кий р е ж им
с номером О }
S e t B kC o l o r ( Wh i t e ) ;
{ установка белого цвета в качестве т екущ е г о для фона }
S e t C o l o r ( DarkGray ) ;
{ у с т ан о в к а т емно - с ер о г о ц в е т а в к ач е с т в е
т екуще г о для выводимых линий }
S e t Li n e S tyl e ( S o l i dLn ,
Thi ckWi dth ) ;
О,
{ у с т а н о в к а т е кущих т о лщины линии
толстая линия )
линия ) ,
и с тиля линии
( Th i c kW i d t h
-
( S o l i dLn - спл ошная
п ар аметр Обр а з ец с тиля игнориру е т ся ,
п о э т ому можно з адать люб о е з н ач ени е ,
в данном случ а е - 0 }
Line ( 1 0 ,
470 ,
10 ,
17 0 ) ;
{ пр ори с о в к а линии 1 }
L i ne ( 1 0 ,
170 ,
320 ,
10) ;
{ пр ори с овка линии 2 }
Line ( 3 2 0 ,
10 ,
630 ,
17 0 ) ;
{ прори с о вка линии 3 }
Line ( 6 3 0 ,
170 ,
Line ( 6 3 0 ,
Line ( 1 0 ,
470 ,
170 ,
630 ,
4 7 0 ) ; { прори с о вка линии 4 }
10 ,
470 ) ;
{ пр ори с о вк а линии 5 }
630 ,
17 0 ) ;
{ пр ори с о вка линии 7 }
S e t LineStyl e ( C ent erLn ,
О,
Thi c kWi dth ) ;
{ у с тановка т е кущей т олщины линии
'l'О л с т ая линия )
и с тиля линии
штрихпунктирная линия ) ,
с тиля игн ориру е т с я ,
люб о е з начение ,
-
п араметр Обра з ец
п о эт ому можно з ад а т ь
в данном случ а е - 0 }
Line ( 1 0 ,
470 ,
630 ,
17 0 ) ;
{ пр ори с о в ка линии б }
Line ( 1 0 ,
170 ,
630 ,
47 0 ) ;
{ пр ори с овка линии 8 }
ReadKey ;
( Thi c kWi dt 11
( C en t e rLn
{ пр о гр амма при о с т анавли в а е т с я д о н а ж атия
п о ль з о в а т е л ем клавиши }
C l o s eGraph ;
{ з акрыв а ем графич е с кий р ежим }
End .
{ к онец р а з д е л а опис ания л о гики лр ограммы }
1 35
Tu rbo Pascal 7 . О
Таким образом, одного и того ж е результата можно достичь разными мето
дами, выбор, какой из них использовать, остается за программистом. Одна
ко всегда стоит искать такой путь реализации программы, который придает
ей большую гибкость. Например, если мы захотим сместить наш конверт на
три точки вправо, во втором варианте программы придется увеличить все
горизонтальные коор ди наты в вызовах процедуры L i ne, то есть получается
по два исправления на каждую из восьми процедур, итого - шестнадцать
исправлений. А чтобы сместить изображение в первом варианте пршрам
мьr, необходимо будет изменить только один параметр в одной процедуре
Моvето, которая устанавливает начальную точку конверта. При этом вто
рая программа содержит меньше строк, соответственно, в нее проще вно
сить исправления, связанные, например, с изменением конфигурации изоб
ражения, если они понадобятся.
Рассмотрим изображение на рис. 49. Это тот же самый конверт, но левая
и
правая
м ен и ть
вертикаль.ные линии продлены вверх. Соответственно, чтобы из
программу Cove r l так, чтобы она выводила такое изображение,
придется изменить параметры во всех используемых процедурах L i neRe l. .
А изменение программы Cove r 2 будет заключаться только в замене пара
метров двух процедур Li ne (по одному в каждой процедуре).
Х=320, У=1 0
Х=1 0, У= 1 0
t
Х=630, У=1 0
Х=630. У= 1 70
Х= 1 0, У= 1 70
Х=630, У=470
l
t
Рис . 49. Измененное изображение конверта
Вообще чем шире и подробнее программист представляет себе поставлен
ную задачу, тем меньше времени он потратит на ее возможные изменения.
А изменение программ - неизменный спутник программирования.
5 . 6 . УдАЛ Е Н И Е ГРАФИ Ч ЕС КО Й И Н ФО РМАЦИ И С ЭКРА Н А
Для удаления всех р ан е е выведенных на экран объектов, в модуле Graph
предусмотрена процедура C l. e arDev i ce, вызываемая без параметров:
C l e a rDevi c e ;
1 36
Глава 5 . Графи ка в Turbo Pasca l . В ы вод и н формаци и в графиче ском режиме
Обратим внимание на то, что экран очищается полностью, то есть, если не
обходимо удалить не все изображение, а только его часть, при использова
нии процедуры C l earDev i ce придется восстановить ту часть изображе
ния, которую удалять было не нужно.
Например, чтобы у прорисованного конверта (см. рис. 48) стереть только
внутренние линии, придется сначала стереть весь конверт, а потом заново
вывести внешние линии. При этом восстановление изображения занимает
некоторое время, что негативно сказывается на удобстве работы с програм:
мой, так как возникает нежелательный эффект мигания (изображение
пустой экран - изображение) . Поэтому, где это возможно, рекомендуется
не использовать процедуру C l earDev i ce, а стирать изображение таким же
изображением, выводимым поверх первоначального, но другого цвета
(обычно фонового).
В качестве альтернативы процедуре C l earDev i ce можно предложить вы
вод прямоугольника, имеющего сплошную заливку цвета с номером О . Та
кой подход может быть полезен, чтобы стереть не все изображение, а только
его часть, например все, кроме меню. Причем нулевой цвет стоит использо
вать, когда нужно получить на экране область с фоном, во всех остальных
случаях можно использовать и другие цвета.
5 . 7 . В Ы В ОД М Н О ГОУГОЛ Ь Н И КО В
Вообш;е говоря, любой многоугольник можно построить с помощью вы
шеописанных процедур Моvето, L i neтo, MoveRe l , L i neRe l и L i ne (на
пример, при рисовании конверта фактически строился прямоугольник).
Однако многоугольники являются часто употребляемыми при построении
изображений фигурами, поэтому созданы процедуры, упрощающие их вы
вод. Рассмотрим процедуры модуля G raph , используемые для вывода пря
моугольников, параллелепипедов и многоугольников.
ВЫВОД Н ЕОКРАШЕНН ЬIХ П Р ЯМОУГОЛЬНИКОВ . П РОЦЕДУРА RECТANGLE
Для вывода прямоугольника со сторонами, параллельными сторонам экра
на, используется продедура Re c tang l e (англ.
пик ) , имеющая следующий вид:
Rec tang l e -
прямоуголь
Rесtаngl е ( < Гориз онтальная координата l > , < В ертикальная ко ординат а l > ,
< Г ориз онтальная к о ордин а т а 2 > , < В ертикальн а я к о ордина т а 2 > } ;
Данная продедура имеет параметры, аналогичные параметрам процеду
ры L i ne , определяющие расположение одной из диагоналей прямоуголь
ника. Для в ывода прямоугольника используется текущий цвет и стиль
1 37
Turbo Pascal 7 . 0
обводк и , устанавливаемые соответственно процедурами
S e tL i ne S ty l e , зал и вка у данной фигур ы от сут с твует .
S e tC o l o r
и
Рассмотрим изображение, покаэанное на рис. 50. Это изображение состоит
из двух прямоугольников (помечены цифрам и 1 и 2) и трех линий (помече
ны цифр ами 3, 4 и 5). При выводе прямоугольников использованы толстые
сплошные линии т е мно - с ер о г о цве т а, а для вывода линий установлена тон
кая текущая обводка такого же цвета. В связи с тем, что толстые и топкие
линии слишком сильно отличаются друг от друга, ли ни ю средней толщины
будем рисовать пут е м вывода двух тонких л иний , расположенных рядом.
Таким образом, рядом с каждой линией (3, 4, 5) вы ведены такие же линии
(тонкие темно-серые). Для линий 1 и 2 дублирующие линии выводятся па
одну т очку правее, а для ли нии 3 дублирующая лин ия находится на точку
ни же . В р езультате линии 2, 3 и 4 имеют двойную толщ ину ( а не тройную или
одинарную, J(ак это могло бы быть при использовании стандартных обводок).
Текст п р о гр ам мы , реализующей п ост р о е н и е изображения <е< Окно� , при
Беден в листинге 044.
Х=600, У= 1 60
Х=600, У=450
5
Х=620, У=470
Х=240, У=450
Рис. 50. Изображение «Окно»
ЛИСТИНГ 044 . ПОСТРОЕНИЕ ИЗОБРАЖЕНИЯ <<ОКНО»
Program Windowl ;
Us e s
Graph , CRT ;
Var
GraphDrive r ,
{ з аголовок
пр ограммы ,
имя
пр о гр аммы
-
Window l }
{ н ачало р а з дела подключ ения модулей }
{ подключ ение модулей Graph и CRT }
{ начало р а з д е л а опи с ания п ер еменных }
GraphМode : Int e ger ;
{ опис ание двух целочисл енных п е р еменных :
G r aphD r i v e r - для передачи в к ач е с т в е параме'l'р а ,
опр ед еляющ е г о номер графич е с к о г о др а й в ер а ,
и GraphМode - для пер едачи в к ач е с т в е параметра ,
опр еделяющ е г о номер графич е с к о г о р е жима }
Begin
1 38
{ начало р а з д е л а опи с ания л о гики пр о гр аммы }
Глава 5 . Графика в Tu rbo Pascal . В ы вод и нформ аци и в графи ческом режи ме
GraphDriver
: =
Det e c t ;
{ пр и с в о ение
с
пе ременной
и с п о ль з о в анием
G r aphD r i v e r
к о н с т анты
Detect
з н а ч ения
модуля
О
Graph
для н а глядн о с ти }
GraphМode
. -
О ; { при с в о ение переменной Gr aphМo de з н ач ения О ,
опр ед е ляющ е г о н е о бходимый гр афич е с кий р ежим
6 4 0 х 4 8 0 х l б цветов }
Ini tGraph ( GraphDriver , GraphМode , ' ' } ;
{ вы з о в пр оцедуры I n i t G r aph ,
опр е д е ляющей др айв ер ,
у с тр о й с т в а ,
а в т ома·r·ич е с ки
подходящий для вид е о
у с тановленн о г о н а к омпьют ер е ;
з апу с кающей др а й в ер и инициализирующе й
графич е с кий р ежим с номером 0 }
{ у с тано в к а б е л о г о ц в е т а в к ач е с т в е
SetBkColor (White } ;
S e t C o l o r ( DarkGray ) ;
текущ е г о для фо н а }
{ у с т а н о в к а темно - с ер о г о ц в е т а в к а ч е с т в е
S e t Line S tyl e ( S o l idLn ,
т екуще г о д л я выводимых линий }
О , Thi c kWidth } ;
{ у с т ан о в к а т е кущей т олщины линии
т о л с т ая линия )
линия ) ,
и стиля линии
( Thi c kW i dth
( S o l i dLn - спл ошная
пар аметр Обр а з ец с тиля игн ориру ет с я ,
поэ•rому можно з адать люб о е з н ач ение ,
в данном
случ а е - 0 }
Rectangl e ( 2 0 ,
10 ,
620 ,
470) ;
{ вывод прямоу г ольника
1}
Rectang l e ( 4 0 , 2 0 , 6 0 0 , 4 5 0 ) ; { вывод прямоуг ольника 2 }
SetLineS tyl e ( S o l idLn , О , NormWi dth } ;
{ у становка т еку щей т олщины линии
т о н к а я линия )
линия ) ,
и стиля линии
( No rmWi d t h
( S o l i dLn - сплошная
п ар аметр Обр а з ец с тиля игн ориру е т с я ,
п о э т ому можно з адать люб о е значени е ,
в д а нн ом
с луч а е - О }
Line ( 2 4 0 ,
Line ( 2 4 1 ,
20,
20 ,
240 ,
241 ,
450 ) ;
450 ) ;
{ вывод линии 3 }
{ вы в од ду блирующей линии
для линии 3 ( на т очку пр а в е е ) }
Line ( 4 4 0 ,
20 ,
440 ,
450 ) ;
{ вывод линии 5 }
Line ( 4 4 1 ,
20 ,
441 ,
450 ) ;
{ вы в од ду блирующей линии
Line ( 4 4 0 ,
160 ,
Line ( 4 4 0 ,
161 ,
для линии 5
600 ,
600 ,
160} ;
161} ;
( на т очку пр а в е е ) }
{ вывод линии 4 }
{ вывод ду блирующей линии
для линии 4
( на т очку ниж е ) }
ReadKey ;
{ пр о гр амма при о с т анавли в а е т ся до наж атия
поль з о в а т ел ем кла виши }
C l o s eGraph ;
{ з акрыв а ем графич е с кий р е жим }
End .
{ конец р а здела опис ания л о гики про граммы }
В ы вод о кРАШЕ н н ых П РЯ МОУrол ьн и ков . ПРОЦЕДУРА BAR
Для заполнения прямоугольной области заливкой, текущие характеристи
процедур ой S e t F i l l S ty l e , используется проце
ки которой у с т ано в лены
дура Bar (англ. Bar - брусок), созданная для совместного использования с
описанной ранее п р о ц едур о й Re c tang l e:
1 39
Turbo Pascal 7 . 0
Ваr ( < Г ори з о нтальная ко ордината
1>,
< Г ориз онтальная к о ордина т а 2 > ,
< В ертикальная к о ордин ата
1>,
< В ертикальная к о ордин а т а 2 > ) ;
Параметры процедуры Bar имеют тот же смысл, что и у процедуры
Rectangle, однако действие, выполняемое процедурой Bar, иное : она за
полняет текущей заливкой прямоугольную область , задаваемую диагона
лью, однако данная область не имеет обводки (см. рис. 5 1 ) .
Рис. 5 1 . Изо бражение окнас использованием заливки
РисовАние
ПАРАЛЛЕЛ Е П И П ЕДА .
П РОЦЕДУРА BARЗD
Процедура BarЗD ( англ Bar
брусок; 3D, 3-Dimensi o nal
трехмер
ный) выводит на экран изометрическую проекцию параллелепипеда
(см. рис. 52 ) и выглядит следующим образом:
.
-
-
BarЗD ( < Г ор и з онтальная к о ордината 1 > , < В ертикальная к о ордин а т а 1 > ,
< Г ориз онтальная ко ордината 2 > , < В ертикальная к о ордина т а 2 > ,
< Г лу б ин а > ,
< Н е о бходимо сть вывода в ерхней грани> ) ;
Пары пар а.\-l етров Горизонтальная координата 1 , Вертикальная к о
ордината 1 и Горизонтальная координата 2 , Вертикальная коор
дината 2 задают положение передней грани параллелепипеда на экране.
Параметр Глу б ина задает длину боковой грани в точках.
Параметр Нео б ходимость вывода верхней rорани представляет собой
логическую (тип а Во о 1 е an) константу или переменную и определяет, будут
ли верхняя и задняя грани выводиться на экран. Если значение данного па
ра.'vl:етра True, то грани выводятся (см. рис. 52 слева) , а если Fal se, то грани
не выводятся (см. рис. 52 справа). Для повышения читабельности программ
при использовании процедуры BarЗD в модуле G raph описаны константы
TopOn True (выводить верхнюю грань) и TopOff Fal se (не выводить
верхнюю грань ) .
=
1 40
=
Глава 5 . Граф и ка в Turbo Pascal . В ывод и нформаци и в графическом режи ме
При выводе всех линий, огра
ничивающих грани параллеле
пипеда, используются текущие
н астройки стиля и цвета обвод
ки, предварительно заданные
процедурами SetLine S tyle
и SetColor. Стиль и цвет
заполнения передней грани
определяет текущая заливка,
установленная процедурами
SetFillStyle и, возможно,
SetFillPa ttern.
/
/
/
/
/
- - - - - - -
- -;1
/ 1
1
/
/
1
/
1
/
1
1
1
1
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
1
1
1
1
1
1
1
1
1
Р�с. 52. Рисование параплелепипеда
Рассмотрим программу (см. листинг 045), выводящую два параллелепипе
на рис. 52.
да, ноказанных
ЛИСТИНГ 045. П ОСТРОЕНИЕ ПАРАЛЛЕЛЕПИПЕДОВ
Program З D_Ваrs ; { з а г ол о в о к пр ограммы ,
Uses
Graph ,
имя пр огр аммы - З D_B ar s }
{ начало р а з дела подключ ения модул ей }
CRT ;
{ подключ ение модулей Graph и CRT }
Var
{ начало р а з д ела опис ания п ер еменных }
Intege r ;
GraphDrive r ,
GraphМode :
{ описание двух целочисл енных пер еменных :
GraphDr i v e r - для п ередачи в к а ч е с т в е параметр а ,
опр ед еляющ е г о номер графич е с к о г о др а й в ер а ,
и GraphМode - для передачи в кач е с т в е параметра ,
опр ед еляющ е г о номер графич е ск о г о р еж има }
Begin
GraphDriver
· -
{ н ачало р а з д ела опис ания л огики пр ограммы )
Det e c t ;
{ прис в о ение п ер еменной G r aphDr i v e r знач ения О
с испол ь з о в анием конс танты D e t e c t модуля G raph
для на глядн о с ти }
GraphМode
: =
О ; { при с в о ение пер еменной Gr aphМo de з н а ч е ния О ,
опр еделяющ е г о н е обходимый графич е с кий р ежим
-
6 4 0 х 4 8 0 х l б цвето в )
I ni tGraph ( GraphDrive r , GraphМode , ' ' ) ;
{ вы з о в пр оцедуры I n i t G raph ,
ав томатич е ски
опр е деляющей драйв ер , подходящий
для видеоустройства , установленного на компьютер е ;
з апу с к ающей др а й в ер и инициализ ирующе й
гр афический р ежим с номером 0 )
S e t BkCol or ( Wh i t e ) ;
{ у с тановка б елого цвета в кач е с т в е текущего для фона )
L i ghtGray ) ;
S e t F i l l Styl e ( Int e r l e aveF i l l ,
{ у с т ан о в к а т екущей з аливки с в етло - с ер о г о ц в ета
( константа L i gh t G r ay модуля CRT ) и с ш а б л оном
з аполнения в виде ячеек
( ко н с т анта
I n t e r l e aveF i l l модуля Graph ) )
141
Turbo Pascal 7 . 0
S e t C o l o r ( DarkGray ) ;
{ у с т ан о в к а темн о - с ер о г о ц в е т а в к ач е с т в е
т е кущ е г о для выводимых линий }
S e t LineStyl e ( Cent erLn ,
О,
Thi c kWidth ) ;
{ у с т ановка т е кущей то лщины линии
т о л с т а я линия )
и стиля линии
штрих- пунктирная линия ) ,
игнориру ется ,
значени е ,
Bar3D ( 1 0 ,
17 0 ,
210 ,
370 ,
( Th i c kW i dth
( C en t e r L n
-
-
парам е тр О бр а з ец с тиля
п о э т ому можно з ад а т ь л ю б о е
в д а нном случ а е - О }
100 ,
TopOn ) ;
{ вы в о д л е в о г о параллел епипеда с в ерхней
гранью
( в к ач е с т в е п ар аметра Н е о бх о дим о с т ь
вывода в ерхней г р а н и ук а з ана к о н с т ант а TopOn
модуля Graph ) }
Bar3D ( 3 3 0 ,
17 0 ,
530 ,
370 ,
100 ,
TopO f f ) ;
{ вы в о д пр а в о г о п аралл ел епипеда б е з в ерхней
грани
( в к ач е с т в е параметра Н е о бходимо с т ь в ы в о д а
в ерхней г р а н и ука з ан а к о н с т а н т а TopO f f
модуля Graph ) }
ReadKey ;
{ пр о гр амма прио с т анавлив а е т с я до н а ж а тия
пол ь з о в а т е л ем кла виши .
Поль з о в а т ел ь видит б елый
экран и кр а с ную гориз онтальную линию }
C l o s eGraph ;
{ з акрыв а ем графиче ский р ежим )
End .
{ конец р а здела опис ания л о гики пр оrр аммы )
Обратим внимание на особенность процедуры BarЗD, отличающую ее
от процедуры Bar. Разница состоит в том, что передняя грань выводи
мого параллелепипсда имеет и обводку, и :iаполнение, т огда как при ис
пользовании процедуры Bar обводка не выводится.
Таким образом, процедуру BarЗD удобно использовать для рисования пря
моугольников с закрашенной внутренней областью, задавая в качестве па
раметра Глубина нулевое значение.
РИСОВАНИ Е МНОГОУГОЛЬНИКОВ . П Р ОЦЕДУРЫ DRAWPOLY И FtLLPOLY
Процедуры DrawPoly и FillPoly (англ. Draw Polygon - рисовать мно
гоугольник и Fi l led Polygon - заполненный многоугольник) предна
значены для вывода многоугольников (полигонов) - фигур, состоящих из
нескольких точек, соединенных отрезками. Многоугольник,
Д�
�::: � ::: �)
выводимый продедурой DrawPoly, имеет только обводку, а
,з"����'.
многоугольники, выводимые процедурой Fill Poly - и об
4�����'
водку,
и заливку (см. рис. 5 3 ) . Обсуждение этих процедур
А:;ШШ��ОII>
� ::: ::: ::: � ::: ::: ::: ::: ::: ::: :::�
" � " " " " " " " " " " " " " "'
в данный момент преждевременно, так как обе они использу·�·�
ют параметры еще не рассмотренного нами типа данных
Рис. 53.
Массивов. Соответственно, мы вернемся к обсуждению
Многоугольник
с заливкой
построения многоугольников при обсуждении массивов.
.. ..�
1 42
-
Глава 5 . Граф и ка в Turbo Pascal . Вывод информ ации в графи ч еском режи ме
ЗАЛИВКА ЗА М КН УТЫХ О БЛ АСТЕ Й .
Процедура
П Р О Ц ЕДУРА
fLOODfiLL
( англ. F l o o d F i l l - на
для заполнения проиа
вольной области текущей заливкой. Заполняемая
область должна быть замкнута и ограничена ли
нией одного цвета (см. рис. 54 ) . Это единственные
ограничения на правила построения граничной
линии, а построена она может быть любыми достушrыми средствами.
поmrять)
F l o o dF i l l
предназначена
Рнс. 54. З аливка
произвольной области
Для своей работы процедура F l o o dF i l l требует следующей информации:
координаты точки, находящейся внутри области, которую необходимо за
полнить, и цвет гр ан и цы этой области . Заполнение о б л а с т и нач и нается иа
указанной точки, что существенно для создания качественного изображе
ния. Дело в том, что заливка произвольной фигуры является сложным алго
ритмом и работает довольно медленно, поэтому пользователь может наблю
дать процесс заливки некоторых б ол ып и х и сложных фигур. Рекомендуется
в качестве внутренней точки, из которой начинается процесс заполнения
области, указывать самую верхнюю или самую нижнюю точку заполняемой
области. В процессе заливки уничтожается вся информация, находящаяся
в н утр и ааливасмой области.
Итак, про цедура F l o o dF i l l в ы гляд ит следующим образом:
F l oodF i l l ( < Г ориз онтальная ко ордина"г а > , < В ертикальная к о ордин а т а > ,
< U в е т границы> ) ;
Параметры
Горизонтальная
I<оордината
и
Вертиi<альная
I<оорди
ната задают положение точки внутри заполняемой области,
параметр Цвет
границы определяет, соответственно, цвет границы, по которой процеду
рой F l oo dFi l l будет опознана заливаемая область.
Хотелось бы отметить, что сели заливка может быть выполнена другими
процедурами, стоит использовать именно их, а не F l o o dF i 1 1 . Однако
иногда без данной процедуры просто не обойтись.
Приведем основн ые ошибки, которые могут встретиться при работе с
связанные в осповном с формальным подходом подпрограммы
заливки к определению границ заполняемой области:
F 1 o o dF i l l ,
•
Область не замкнута, соответственно, заливка �вытекает� за преде
лы предполагаемой программистом области и занимает следующую
возможную область или весь экран. При
вытекании заливки необходимо проверить
целостность области. На рис. 55 предпола
галось залить внутреннюю область. Кругом
Рнс. 55. Заливка
показава начальная точка заливки (на са
незамкнутой области.
мом деле она не присутствует на рисунке).
Вариант 1
1 43
Turbo Pascal 7 . 0
Рис. 56. Заливка
незамкнутой области.
Вариант 2
Рис. 57. Заливка области
из точки, имеющей
цвет границы
В связи с тем, что заливаемая область окаэалась не
замкнутой, заливка вытекла в следующую область.
Если бы и следующая область не была бы замкну
той, залитым оказался бы весь экран.
•
Замкнутая область построена разрывной ли
нией, например, штрих-пунктирной (см. рис. 56),
что недопустимо. В данном случае придется уста
новить обводку сплошной линией, а затем залить
ее и обвести заново линией необходимого типа.
•
В качестве начальной точки заливки указана
точка, имеющая цвет границы, определяющей
область заполнения. В этом случае процедура
FloodFill считает, что область уже заполнена,
и заканчивает работу, не произведя никаких из
менений (см. рис. 57).
•
Частая ошибка - некорректное задание пара
метров процедуры FloodFi ll, когда, например,
Рис. 58. Заливка
вместо цвета границы, до которой нужно зали
с н еправильным цветом
вать фигуру, указывается цвет, которым нужно
границы
заливать (а на самом деле он задается процеду
рой S e tFi l l S tyle). В этом случае процедура FloodFi ll будет
искать границу с цветом, который задан параметром, и, скорее все
го, зальет весь экран (см. рис. 58) .
5 . 8 . В Ы ВОД КРИ В ЫХ Л И Н И Й
РИСОВАНИ Е ОКРУЖНОСТЕЙ
Для вывода на экран окружности (без внутренней области, выводится толь
ко обводка) предназначена процедура Circle (англ. Circle - окружность)
модуля Graph, имеющая следующие параметры:
С i r с l е ( < Г ориз онтальная ко ордина т а > ,
< В ертикальная к о ординат а > ,
< Р а диу с > } ;
Координаты центра окружности задаются парой параметров Горизок
'l'алькаR координа'l'а и Вер'l'икальнаR координа'l'а, радиус окружнос
ти - параметром Радиус (см. рис. 59). Цвет выводимой окружности опре
деляется текущим цветом обводки, установленным процедурой SetColor.
Н едостатком процедуры Circle и вообще всех процедур модуля Graph,
выводящих кривые линии, является невозможность повлиять на стиль
1 44
Глава 5 . Графика в Tu rbo Pasca l . Вывод и нформации в графи ч еском режим е
линии, которой выводится окружность - линия
всегда сплошная , однако ее толщина задается стан
дартно - процедурой S e tLine S tyle.
=
Х = Горизонтальная координата
У Вертикальна� координата
Рис. 59. Вывод
окружности
РисовАНИ Е дУг
Процедура Arc (апгл. Arc - дуга) аналогична п роцедуре C i r c l e , но выво
дит не полную окружность, а только ее дугу, заданную начальным и конеч
ным углом (см. рис. 60):
Arc ( < Гориз онтальная
< Н а чальный у г о л > ,
к о ор дин а т а > ,
< В ертикальная
<Конечный у го л > ,
к оордината> ,
< Р адиу с > ) ;
Параметры Начальный yro.n и Конеч ный
отсчитываются в градусах, против часо
вой стрелки, от горизонтального направления
вправо (пунктирная линия на рис. 60).
yro.n
При использовании процедуры Arc допусти
мо использование Начальноrо yr.na, боль
шего, чем Конеч ный yro.n. Если в рассмот
ренном примере поменять местами значения
начального и конечного угла, то на экран будет
выведена другая часть этой же окружности.
Кон ечн ый угол
Х
У
=
=
Горизонтальная координата
Вертикаль на� координата
Рис. 60. Вывод
дуги окружности
РисовАНИ Е СЕКТОРА КРУГА
Для вывода не дуги окружности, а сектора круга (см. рис. 6 1 )
Graph предусмотрена процедура, аналогичная процедуре A r c :
в
модуле
Р i е S l i с е ( < Г ориз онтальная к о ординат а > , < В ертик альная к о ордината> ,
<Нач альный у г о л > ,
<Конечный у г о л > ,
Процедура PieS l i ce (англ. Slice Pie - отре
зать сектор) рисует сектор круга, используя
текущие параметры заливки. Ограничиваю
щая линия выводится в зависимости от пара
метров текущей обводки. Если для текущей
обводки используется сплошная линия (зада
ваемая константой S o l i dLn) , то выводится и
дуга, ограничивающая сектор, и линии ради
усов. Если же стиль линии отличен от сплош
ного, то выводятся только линии радиусов.
< Р адиу с > ) ;
Х = Горизонтальн ая координата
У = В ерти кал ь н ая ко ордин ата
Рис. 6 1 . Вывод
сектора окружности
1 45
Turbo Pascal 7 . 0
Р ИСОВАН И Е ЗАКРАШЕННОГО ЭЛЛИПСА
Процедура Fil lE l l ipse (анrл. Filled Ellipse - закраrпеппый эллипс)
предназначена для вывода закрашенного эллипса. Эллипс строится по од
ной опорной точке (центра эллипса) и двум радиусам (горизонтальному и
вертикальному) (см. рис. 62):
F i 1 1 Е 1 1 iр s е ( <Гориз онтальнаяко ординат а > ,
<Вертикальная к о ордината > ,
< Х - Радиу с > ,
<У- Радиу с > ) ;
Для заполнения внутренней области эллипса
используется текущая заливка, цвет и толщина
Рис. 62. Вывод
обводящей
линии определяется параметрами те
закраш е нно го эллипса
кущей обводки, установленными, соответствен
но, процедурами S e tColor и S e tLine S tyle. Обводящая линия всегда
является сплошной, вне зависимости от стиля лииии текущей обводки .
Р ИСОВАНИ Е НЕЗАКРА ШЕННОГО ЭЛЛИПСА
Процедура E l l ip s e ( англ. Ellipse - эллипс) аналогична процедуре
Arc, но в отличие от нее выводит не дугу окружности, а дугу эллипса
(см. рис. 6 3 ) , поэтому вместо одного параметра Радиус, так же как и
процедура F i l lE l l ip s e , имеет два параметра: Х -радиус и У -радиус,
задающих соответственно горизонтальный и вертикальный радиусы
эллипса.
Е l l iр s е ( < Г ори з онтал ьнаяк о ордин а т а > ,
< В ертик альная к о ординат а > ,
< Н а.ч альный у г о л > ,
<Конечный у г о л > ,
<Х - Р адиу с > ,
<У - Р адиу с > ) ;
На экран выводится только дуга, то есть внутрен
няя область эллипса не ааполняется. Как и во всех
Рис. 6 3 . Вывод
остальных процедурах вывода кривых линий,
дуги эллипса
имеется возможность повлиять только на толщину и цвет выводимой линии, стиль линии изменить невозможно - данные
процедуры всегда используют сплошные линии.
Р ИСОВАНИ Е ЭЛЛИ ПТИЧЕСКО ГО СЕКТОРА
Процедура Sector ( англ. Sector - сектор) аналогичнапроцедуре PieSlice,
имеет такие же правила заполнения внутренней области и прорисовки
1 46
Глава 5 . Графика в Tu rbo Pasca l . В ы вод и н формаци и в графич еском режиме
обводки, но выводит сектор эллипса, а не круга
(см. рис. 64) , и, соответственно, принимает в ка
честве параметров два радиуса вместо одного:
S е с t о r ( < Г ориз онтальная координат а > ,
<В ертикальная к о ордин а т а >
< Н а чальный у г о л > ,
<Кон ечный у г ол > ,
< Х - Р адиу с > ,
< У - Р адиу с > ) ;
Рнс. б4. Вывод
сектора эллипса
СОВМЕСТНОЕ ИСПОЛЬЗОВАНИ Е ПРЯ МЫХ И КРИВЫХ Л И Н И Й
Посмотрим на рис. 65. Данное изображение содержит шесть линий, одна
из которых - кривая и является дугой эллипса, построенной процедурой
E1.1.ipse, а все остальные - прямые и являются линиями, построенными
процедурой Line. Полученная область закрашена с помощью процедуры
F1.oodFi1.1..
Основная сложность построения таких рисунков состоит в расчете координат
точек для отрезков 2 и 6. Координаты легко определяются для дуг окружноетей через координаты центра, радиус и углы,
которые задаются при построении дуги, од
6
нако при использовании дуг эллипса с угла
ми, не кратными 90" (то есть о·, 90", 1 80" и
270"), определить координаты очень тяже4
ло. Для облегчения этой задачи предусмотре на процсдура Ge tArcCoords ( англ. Get Рис. 65. Совместное использование
Arc Coordinates
получить координаты
кривых линий и отрезков
дуги) , однако се единственный параметр
имеет тип данных, который еще не рассмотрен нами. Таким образом, мы
вернемся к процедуре GetArcCoords при изучении типа данных Запись.
-
5 . 9 . М ЕТОД Ы П Р ЕДСТАВ Л Е Н И Я ГРАФИ Ч ЕСКО Й И Н ФО Р МАЦИ И
5 . 9 . 1 . ДВА МЕТОДА - РАСТРОВЫЙ И ВЕКТОРНЫЙ
Для храпения графической информации любого рода используется два
метода (вида формата) - векторный и растровый. В растровом формате
изображение или какой-либо другой графический объект представляется
матрицей точек (прямоугольником, заполненным точками). В векторном фор
мате каждая линия изображения представляется в математической форме,
1 47
Turbo Pascal 7 . О
Изображение задано растром
......
�
-
1 1 1
-
1'..
;;;;
'
Изобоаженив заnано вектооа
�
Рис. 66. Два метода
представления
определяющей положение и форму линии. Та
кие описания линий и называют векторами.
На рис. 66 слева изображение символа -. г. за
дано в растровом виде, прямоугольником раз
мером 4х6, заполненным точками. Некоторые
из них имеют цвет и, соответственно, опреде
ляют начертание символа. На том же рисунке
справа изображение символа -« Г� задано двумя
векторами, каждый из которых задается всего
двумя точками - начальной и конечной.
графических объектов
5 . 9 . 2 . ДостоинствА и Н ЕДОСТАТКИ
Каждый метод представления информации имеет свои достоинства и недо
статки, которые можно разделить на несколько групп.
РАЗМ ЕР ПАМЯТИ , Н ЕОБХОДИМЫЙ ДЛЯ ХРАНЕНИ Я ИЗОБРАЖЕНИЯ
Ра.."' мер памяти, требуемой для хранения изображения в растровом форма
те, определяется количеством точек в данном изображении и количеством
байтов, необходимых для хранения одной точки. Для описания растрового
изображения, показаинаго на рис. 67, при хранении цвета точки в трех бай
тах (именно столько требуется для хранения цвета True Color) необходимо
4 * 6 *3=72 байта. Для хранения такого же векторного изображения требует
ся по четыре байта на каждый вектор для хранения положения начальной и
конечной точек вектора и по три байта на каждый вектор для хранения его
цвета. Итого получается (4+3) * 2= 1 4 байтов.
Казалось бы, разница не велика. Однако при изменении размеров изобра
жений, например, в десять раз по ширине и в десять раз по высоте размер
растрового изображения изменяется пропорционально изменению ли
нейных размеров, то есть для нашего примера в 1 0 0 раз (72 00 байт). При
этом объем памяти, необходимый для хранения векторного изображения,
не изменяется.
Но векторные изображения не всегда имеют меньший размер, чем раст
ровые. Например, для представления каждой точки фотографии, в связи
с отсутствием непрерывных по цвету фрагментов в изображениях такого
рода, потребуется один вектор, то есть семь байт, а для хранения той же фо
тографии в растровом виде на каждую точку потребуется только три бай
та, соответственно, векторное изображение будет занимать более чем в два
раза больше места, чем растровое. Это делает неоправданным использова
ние векторных форматов для хранения фотографических снимков.
1 48
Глава 5 . Графика в Turbo Pascal . Вывод и н формаци и в графическом режи ме
СКОРОСТЬ ВЫВОДА ИЗОБРАЖЕНИЯ
Скорость вывода растрового изображения зависит только от количества то
чек, содержащихся в нем, и определяется быстродействием компьютера,
тогда как при выводе векторного изображения осуществляется ряд допол
нительных операций, связанных с персводом векторного изображения в его
растровое представление. Таким образом, скорость вывода векторного изоб
ражения зависит от количества векторов, которые его составляют, и их
сложности. Чем больше векторов нужно вывести и чем они сложнее, тем
дольше изображение выводится на экран.
КАЧЕСТВО П РЕдСТАВЛЕНИЯ ИЗОБРАЖЕНИ Я
Качество растрового изображения не может измениться в процессе вы
вода, тогда как качество векторного изображения зависит от алгоритма,
переводящего его из векторной формы в растровую. Н апример, при пос
троении кривых линий используется множество
операций округления для того, чтобы из непре
рывной кривой, заданной математическим уравне
нием, получить целочисленные координаты точек
для вывода.
Разные алгоритмы (и даже одни и те же алгоритмы
на разных компьютерах) могут выдавать немного
различные результаты для каждой просчитываемой
точки. Таким образом, изображение может иметь
некоторые погрешности, особенно заметные при
использовании маленьких изображений.
Рнс. 67. Одно и то же
иэображение э�ано
разными методами
ВоЗМОЖНОСТИ МАС ШТАБИРОВАНИЯ
Рассмотрим прямую наклонную линию, заданную в растровом виде и в век
торном (см. рис. 67).
Допустим, мы собираемся увеличить масштаб
представления линий на обоих рисунках в два
раза. Так как растровое изображение задается
точками, то каждая точка изображения будет уве
личена в размерах в два раза по ширине и в два
раза по высоте и будет занимать четыре точки ( см.
рис. 68), что значительно ухудшает качество изоб
ражения. А при таком же увеличении векторного
изображения изменяются только параметры век
тора, а подпрограмма прорисовки, переводящая
вектор в растр, построит линию на экране заново,
при этом качество изображения не ухудшится.
Рнс. 68.
Масштабирование
иэображений, э�анных
разными ме тодами
1 49
Tu rbo Pascal 7 . 0
Такая особенность векторных изображений играет большую роль при
выводе их на печатающие устройства, которые сильно отличаются друг
от друга по разрешению (количеству точек, которое печатающее ус
тройство может вывести на один дюйм поверхности бумаги - Dot Per
Inch - D P I ) .
Растровые изображения создаются для печати на устройстве с конкрет
ным разрешением, и качество выводимых изображений не ухудшается и
не улучшается при использовании более качественного устройства вы
вода (с более высоким разрешением) , тогда как векторные изображения
не ориентированы на конкретное разрешение, и их качество при выводе
улучшается с увеличением разрешения печатающего устройства.
5 . 1 О. В Ы ВОД ТЕКСТА В ГРАФ И Ч ЕС КО М РЕЖИ М Е
5 . 1 0 . 1 . ПАРАМЕТРЫ ВИЗУАЛЬНОГО ПРЕДСТАВЛЕНИЯ
ТЕКСТОВОЙ ИНФОРМ АЦИИ
Возможности вывода тен:ста в графическом режиме знаЧительн о более
широки, чем в текстовом. Представление текстовой информации на эк
рапе в графическом режиме определяется совокупностью нескольких
характеристик:
•
Начертание символов
форма и взаимное расположение линий,
из которых состоят символы (см. рис. 69).
•
Размер символов. Символы одинакового начертания могут иметь
разный размер (см. рис. 69).
-
•
Выравнивание относительно точки вывода. Вывод текста производится из пекоторой опорной точки. При этом имеется воз
можность уr<азать, какой именн о точкой
(левой, правой или центральной для вырав
нивания по горизонтальной оси и верхней,
нижней или центральной для вертикальной
Текст , выровн еt-r н ы й
оси) текст будет касаться опорной точки . Та
л
му
кра
ю
по ево
ким образом, можно достичь выравнивания
Текст , выровненный
по п р а в ому краю
нескольких строк текста по правому или ле
Горизонтал ьный те кст
вому краю , а также по центру (см. рис. 6 9 ) .
Рис. 6 9. Параметры
визуального представления
текста в графическом режиме
1 50
Направление в ывода символов. Текстов ые
строки можно выводить, слева направо или сни
зу вверх (см. рис. 69).
•
Глава 5 . Графика в Tu rbo Pascal. В ы вод информаци и в графическом режи ме
5 . 1 0 . 2 . НАСТРОЙКА Ш РИФТА
Совокупность информации о начертании (форме и взаимном расположе
нии линий) нсiюторого набора разных символов (например, букв русского
алфавита о т <tA� до <tЯ� и от �а� до �я� или букв латинского алфавита от
�л� до � z � и от �а� до �z� ) называется шрифтом. Различные программы
хранят шрифты в разных форматах и по-разному их испош,зуют. В Turbo
Pascal шрифт хранится в со б ственном векторном формате, который назы
вается ВGI-шрифт. Вместе с дистрибутивным набором Turbo Pascal постав
ляется десять файлов с B GI -шрифтами, причем ни один из них не содержит
русских символов. Однако имеется возможность подключить к свое й про
грамме шрифты, разработанные сторонними фирмами.
ВGI-шрифты хранятся в файлах с расширением CHR, например, файл со
стандартным В GI-шрифтом Sans Serif имeeт имя на диске s ans . chr.
В программе шрифтом называется совокупность информации о начерта
нии символов и их размерах. Разница в подходе к понятию шрифта с точки
зрения програ.'iмы и файла, в котором хранится шрифт, обусловлена век
торной природой используемых в 'П1rЬо Pascal шрифтов.
Действительно, для того чтобы описать начертание символа в векторном
виде, совершенно необязательно знать высоту и ширину самого символа,
достаточно иметь информацию о соотношении ширины и высоты.
С другой стороны, при выводе символа на экран происходит его перевод
из векторной формы в растровую, для чего необходимо знать размеры сим
вола. А если бы в Turbo Pascal для п р едставления шрифтов использовался
растровый формат, то для каждого набора размеров символа пришлось бы
хранить описание его начертания.
УСТАНОВКА И НАСТ РОЙКА ШРИФТА. П РОЦЕДУРА S ЕТТ ЕХТSТУL Е
lllрифт является текущей характеристикой, то есть определяет начертание
и размеры символов, которые выводятся на экран после его смены. Установ
ка текущего шрифта осуществляется процедурой SetTextS tyle:
S et тext Styl e ( < H oмep шрифт а > ,
< Наnра в л е ни е > ,
< Р а змер
символо в > ) ;
Рассмотрим параметры данной процедуры.
•
Параметр Номер
шри ф та .
В момент запуска программы, написанной на ТнrЬо Pascal, она име
ет доступ к одному растровому шрифту, установленному в качестве
системного (это тот же самый шрифт, который используется для
вывода информации в текстовом режиме) , и девяти векторным
шрифтам. Для выбора одного из десяти этих шрифтов ( о н и называ
ются предустановленными, так как доступны без дополнительной
151
Turbo Pascal 7 . 0
@1 2 3 4
5 6 78 9
Рис. 70. Использование различных
шрифтов при выводе текста
в графическом режиме
инициализации) необходимо передать
соответствующее ему значение в качест
ве параметра Н о м е р шри ф т а (примеры
начертаний символов предустановлен
ных шрифтов наказаны на рис. 7 0 ) . Для
удобства работы и повышения читабель
ности программ в модуле G r aph для рас
трового и четырех векторных предуста
новленных шрифтов описаны константы
(см. табл . 3).
Таблица 3 . Предустановлеииые векторные шрифты и соответствующие и.м
коистаиты модуля Graph
Назван ие wрифта
Номер wрифта
Константа
Имя файпа
System ( С и сте м н ы й растров ы й )
о
Defa u ltFont
Triplex (Трой н о й )
1
Tri p l exFont
tri p . c h r
S m a l l ( М ел ки й )
2
Smaii Font
litt . c h r
Sans Serif
3
SansSerifFont
san s . c h r
G othic ( Готи чески й )
4
Goth i c Font
g oth . c h r
Scri pt ( П исьмен н ы й )
5
-
s c ri . c h r
Simple ( П р я м о й )
6
-
simp.chr
Triplex Script (Трой н ой н а кл о н н ы й )
7
-
tsc r . c h r
Lcom ( П р я м о й двой н о й )
8
-
lcom . ch r
Euro
9
-
euro.chr
-
ПРИМЕЧАНИЕ,
Мы затрудняемся сказать , п очему в модуле Graph такие константы н е о писаны
и для остальных пяти ш рифто в . Если в программ е часто используются предус
тановл е н н ы е ш рифты , для которых в модуле Graph не описаны константы , мож
н о сделать это самостоятельно в разделе описания констант Const. Например,
Cons t ScriptFont
5.
=
Файл с в е кт о рн ы м тприфтом, уст ан ав ливае м ы м в качестве текутцсго,
должен находиться в рабочем каталоге програ.� мы, то есть в том ка
талоге, откуда программа запускается.
В комплект поставки Turbo Pascal входит еще один файл с B GI
шрифтом - bold . ch r (жирный). Однако он не является предус
тановленным, то есть к нему нельзя просто обрат и ть ся по номеру.
Установка дополнительных шрифтов описана ниже.
152
Глава 5 . Графика в Tu rbo Pascal. Вывод и нформаци и в граф и ческом режи ме
•
Параметр Направление .
Вывод текста может происходить в двух направлениях: по горизон
тали (слева напр аво) и по вертикали (снизу вверх) . П араметр На
правление определяет метод вывода и должен иметь значение О
для вывода текста по горизонт али или 1 для вывода текста по в е р т и
кали. В качестве значений данного параметра можно использовать
константы HorizDir=O и VertDir= l .
•
П араметр Разкер сиив олов .
Парам етр Разкер сиив ол ов определяет увеличение или уменьше
ние выводимых символов относительно некоторой базовой высоты
символов, зависящей от конкретного шрифта. Для стандартных,
поставляемых с Turbo Pascal шрифтов , базовая высота символа ко
леблется от 30 до 35 точек, за исключением шрифтов Sma l l (8 то
чек) и E u r o (55 точек).
Над каждым символом имеется свободное пространство, равное
примерно трети общей высоты, которое также входит в расчет разме
ра символа. Справа от
символа также нахо
дится свободное про
странство, размер которога определяется для �
каждого символа ин ::;�
дивидуалыю. Делается
это таким образом , m
чтобы для одного значения параметра Р а з
�
ме р
сим в оло в
ши
рины всех символов
шрифта были одина
ковые (см. рис. 7 1 ) .
•
Параметр
Рис. 7 1 . Параметры символа
Разкер сиив олов.
Параметр Разкер сииволов м о жет принимать значения от О до
1.0. П р и этом значение 4 указ ыв ает на необходимость использовать
базовый размер при выводе символов, значения 3, 2 и 1 уменьшают
высоту с имволов , а значения от 5 до 10 - ув еличивают. Коэффици
щп уменьшен ия и увеличения зависит от исполь зуемого шрифта и
определяется практическим путем - перебором возможных значе
ний параметра Разкер сиив олов.
Вышесказанное не касается растрового шрифта (с номером 0). Данный
шрифт является системным, то есть уст ан овле нным до з апуска программы.
Соответственно, его н ачертание и т акие характеристики, как интерв алы,
1 53
Turbo Pascal 7 . 0
определяются программой, установившей его (например, русификатором) .
Растровый шрифт имеет базовую высоту символа 8 точек. Для данного
шрифта параметр Размер символов может принимать любые целочис
ленные значения, причем при увеличении параметра на единицу размер
выводимых символов увеличивается на базовую высоту, то есть на 8 точек.
Таким о бр аэ о м, нулевое значение параметра Размер символов для р ас
трового шрифта устанавливает текущим шр и фт размером 8 х 8, значение,
равное единице - 1 6х 1 6, и так далее.
Напишем программу, устанавливающую текущим готический шрифт (пре
дустановленный с номером 4 и константой Gothi c Fo n t ) . Режим вывода
символов - горизонтальный слева направо, размер символов - уменьшен
ный (используем в качестве параметра Размер символов число 3). Текст
программы приведен в листинге 046.
ЛИСТИНГ 046. УСТАНОВКА ТЕКУЩЕГО ШРИФТА
Program S e t Font l ;
{ з а г о л о в о к программы ,
Uses
Graph ,
имя прогр аммы
-
S e t F o nt l }
{ начало р а здела п о дключ ения модул ей }
CRT ;
{ подключ ение модулей Graph и CRT }
{ начало р а з д е л а опис ания п е р еменных }
Var
GraphDrive r ,
GraphМode :
Int eger ;
{ оnи с ание двух целочисл енных nер еменных :
Gr aphD r i v e r - для nередачи в к ач е с т в е п ар аметр а ,
опред еляюще го номер графич е с к о г о др а й в ер а ,
и GraphМode - для передачи в к ач е с т в е nараметр а ,
опр е д е ляюще г о н омер графич е с к о г о р еж има }
Begin
{ н ачало р а з д е л а опис ания л о гики nр о г р аммы }
GraphDriver
: =
Det e c t ;
{ nрис в о ен и е n ер еменной GraphD r i v e r з н ач ения О
с
исnол ь з о в анием
к о н с т анты
Det e c t
модуля
G r aph
для н а глядн о с т и }
GraphМode
: =
О ; { пр и с в о ение пе р еменной Q r aphМode з н а ч ения О ,
оnр еделяющ е г о н е о бходимый графич е ский р е жим
-
6 4 0 х 4 8 0 х l б цветов }
Ini tGraph ( GraphDriver , GraphМode , ' ' ) ;
{ вы з о в пр оцедуры I n i t Graph , а в т оматич е с ки
оnр е д еляющей др айв ер , n о дх одящий
для вид е оу с тройства , у с т а н о вленного н а компью т ер е ;
з аnу ск ающей др айвер и иници али з ирующ ей
графич е с кий р ежим с н омером О }
S e t C o l o r ( B lue ) ; { у с т а н о в к а син е г о ц в е т а в к ач е с т в е т е кущего
для выводимых линий }
S e t Text S tyl e ( Gothi c F ont ,
Hori z Di r ,
3) ;
{ у с т а н о в к а т екущ е г о шри ф т а G o th i c
к о н с т анта Goth i c F ont ) ,
наnр а в л е ния
( и с n о ль з о в ан а
гори з онтальн о г о
( и сnоль з о в ан а константа H o r i z D i r )
с уменьшенным р а змером ( и с п ол ь з о в ана к о н с танта 3 ) }
1 54
Глава 5 . Графи ка в Turbo Pascal . В ы вод информ аци и в графическом режи ме
{ про гр амма при о станавли в а е т с я до н а ж атия
ReadKey ;
поль з о в а т ел ем кла виши }
C l o s eGraph ;
{ з а крыв а ем графич е с кий р ежим }
End .
{ конец р а з д е л а опис ания л о гики пр о гр аммы }
Ц ВЕТ ТЕКСТА
Цвет текста, выводимого на экран в графическом режиме, соответствует
цвету текущей обводки, задаваемому продедурой SetCo1.or.
TOH КASI Н АСТРОЙКА РАЗМЕРОВ ШРИФТА
Продедура S e tTextS ty1.e разрешает увеличивать pa.''J Mep символов вектор
ных шрифтов не более чем в 1 О раз. Для более тонкой настройки размеров
символов и отмены ограничения на максимальное увеличение размеров ис
пользуется продедура SetUserCharSi ze (от англ. Set User Char S i z e
установить желаемый размер символов), которая отменяет размер симво
лов, установленный для текущего шрифта продедурой S e t T e x t S t y l e , и
устанавливает новый размер на основе базовых. Новые раамеры задаются
четырьмя параметрами, по два на высоту и ширину. Эти параметры указыва
ют, во сколько раз необходимо умевыпить и увеличить соответствующий
базовый ра:змер:
•
S etUs e rCharS i z e { <Yвeличeниe п о гориз онтали > ,
<Уменьшение по г ориз онтали> ,
<Увеличение по в ертикали > ,
<Уменьшение по в ертикали> ) ;
Все парам:етры процедуры задаются положительными целочисленными пе
ременными или константами. Выполнение данной процедуры происходит
следующим образом: базовая ширина символа умножается на значение па
раметра Увеличение no I."оризонтапи, а затем делится на значение пара
метра Уменьшение no I."Оризонтапи. То же самое происходит с высотой
символа, только используется вторая пара параметров. Благодаря разделе
нию коэффициентов на уменьшающие и увеличивающие можно изменять
размер шрифта в дробное число раз, например в 1 ,5 раза.
Например, чтобы увеличить ширину символа в два раза и уменьшающую
высоту в полтора раза необходимо выбрать следующие значения пара
метров: Ув еличение no I."оризонтали
2 (увеличить в два раза) ,
Уменьшение no I."оризонта.пи - 1 (не уменьшать) , Увеличение no
в ертикали
3 (увеличить в три раза), Уменьшение no в ертикали
2 (уменьшить в два раза). Таким образом вызов процедуры s e t u s e rchar
s i z e будет выглядеть следующим образом:
-
--
S e tUs erCharS i z e ( 2 ,
-
1,
3 ,
2) ;
1 55
Turbo Pascal 7 . 0
5 . 1 0 . 3 . П РОЦЕДУРЫ ВЫВОДА ТЕКСТА
В предыдущих разделах мы рассмотрели основные параметры текста, вы
водимого на экран в графическом режиме, а теперь научимся выводить сам
текст. Итак, для вывода текста в модуле Gr aph предусмотрены две проце
дуры: Outтext (англ. Text Out - вывести текст), выводящая строку текста
так, чтобы опорная точка выводимой строки находилась в позиции текуще
го указателя ( С Р) , и OutTextxY (апгл. T e x t Out i n ХУ - вывести текст в
точку с координатами Х, У), задающая положение опорной точки дополни
тельной парой параметров.
�;-tr�_l!fj_-�:==
Охватывающии nря м оуг ол ьник
Рис. 72. Параметры текстовой строки
в графическом режиме
Опорной точкой для строки тек
ста по умолчанию является левая
верхняя точка прямоугольпика,
охватывающего строку (см. рис.
72). Напомним, что в этот пря
моугольник войдет пустое про
странство сверху и справа, что
важно учитывать при выборе по
ложения опорной точки.
Процедура Ou tтex t имеет один параметр, который может задаваться
константой или переменной какого-либо символьного типа ( S t r i n g
или C h a r ) :
Оutтехt ( <Выв о димая инф ормация > ) ;
Процедура OutTextxY имеет еще два параметра - Горизон�апьнаи к о
и Вер�икапьнаи координа'l'а,
определяющих положение
опорной точки. Данные параметры могут задаваться целочисленными кон
стантами или переменными:
ордина�а
-
ОutтехtХУ ( < Гориз онтальная координат а > ,
< В ертик альная ко ордин а т а > ,
<Выв одимая инф ормация> ) ;
Напишем программу (см. листинг 047), выводящую на экран две строки
символов: « S t r i n g 1» и « S t r i n g 2 » (см. рис. 73). Первая строка будет
выводиться из положения текущего указа
теля процедурой OutText, причем текущий
указатель будет заранее персмещен в точку
Strin g 1
с координатами (X= l O O , Y= l O O ) . Для того
Stri ng 2
чтобы можно было определить положение с Р
визуально, его смещение будем производить
процедурой LineTo, оставляющей за собой
линию. Затем отобразим вторую строку так,
чтобы
ее опорная точка имела координаты
Ре
льтат
Рис. 73.
работы
зу
программы Graph Text 1
(X= l O O , У= l З О ) .
�
1 56
Глава 5 . Графика в Tu rbo Pascal. В ы вод и нформ ации в графическом режи ме
Листинг 047. Вывод текстА
Program GraphText 1 ;
{ з а г о л о в о к пр о граммы ,
имя пр огр аммы - GraphT ex t l }
{ начало р а з дела подключения моду л е Й }
{ подключ ение модул ей Graph и C RT }
CRT ;
{ начало р а з дела опис ания пер еменных }
Var
GraphDriver , GraphМode : Int eger ;
{ опис ани е двух целочисл енных п ер еменных }
{ начало р а з дела опис ания л о гики пр ограммы }
Begin
GraphDriver : = Det ec t ;
{ прис в о ение переменной GraphDr i v e r з н а ч ения О }
GraphМode : = О ; { пр и с в о ение переменной GraphМode знач ения О }
Ini t Graph ( GraphDriver , GraphМode , ' ' } ;
{ инициали з ация гр а фич е с к о г о р ежима }
S e t Co l o r ( DarkGray } ;
{ у с тановка т екущ е г о ц в е т а для линий и т е к с т а }
S etтextStyl e ( Tripl exFont , Hori z Di r , 0 } ;
{ у с тановка т е куще г о шрифта Trip l ex
гори з онтальн о г о направл ения б а з о в о г о р а змера
( и споль з о в ана конст ан'!'а О ) }
LineTo { 10 0 , 1 0 0 ) ; { п ер емещение С Р в точку ( X = l O O , Y = l O O ) .
Н а экране появляется отр е з ок и з точки ( 0 , О )
Uses
Graph ,
в точку ( 1 0 0 , 1 0 0 ) }
Outтext ( ' St ring 1 ' } ;
{ вы в о д строки и з положения С Р }
OutTextXY { 1 0 0 , 1 3 0 , ' St ring 2 ' } ;
{ вывод с троки , опорная точка которой име ет
C l o s eGraph ;
ко ординаты ( 1 0 0 , 1 3 0 ) }
{ пр о гр амма при о с танавли в а е т с я до н а ж атия
поль з о в ат е л ем клавиши }
{ з акры в а ем графич е с кий р ежим }
End .
{ конец р а з д е л а опи с ания л о гики пр о гр аммы }
ReadKey ;
5 . 1 0 . 4 . ОnРЕДЕЛЕНИЕ РАЗМЕРОВ символов
В предыдущем примере две строки выведены друг под другом. Такой эф
фект достигнут подбором координат второй строки. Однако перебор вари
антов для выяснения правильного расположения строки - довольно трудо
емкая операция, особенно при выводе нескольких строк.
Для такого рода задач предназначены функции определения размеров
текстовых строк TextWidth (от англ. Text Width - ширина текста) и
TextHeigh t (от англ. Text Height - высота текста), выдающие разме
ры строки, заданной им в качестве параметра.
Размеры строк рассчитываются исходя из предположения, что они будут
выводиться с использованием текущего шрифта.
TextWidth ( < Cтpoкa> ) ;
TextHe i ght ( < Cтp o к a > ) ;
1 57
Turbo Pascal 7 . 0
Совершенное владение методами вывода текстовой информации необходи
мо для построения качественного пользовательского интерфейса. В качес
тве примера напишем программу (см. листинг 048), выводящую на экран
строку и обводящую ее прямоугольником так, как это показало на рис. 72.
ЛИСТИНГ 0 4 8 . Вывод СТРОКИ ТЕКСТА В ПРЯМОУГОЛЬНОЙ РАМКЕ
Program GraphText 4 ;
{ з а г о л о в о к пр огр аммы , имя про гр аммы - Gr aphTex t 4 }
{ н ачало р а здела подключ ения модул ей }
CRT ;
{ подключ ение модулей Graph и CRT }
Const
{ н ач а л о р а з дела опис ания конс тант }
х = 10;
{ опис ание константы Х , с о д ержащей г ориз онтальную
к о ордин ату вывода о б еих с трок }
у
{ опис ание константы У , с о д ержащей в ертик альную
50;
к о ординату вывода первой с троки }
s
' Pa s c a l ! ' ; { опис ание с трокавой константы , имеющей
з начение ' P a s c a l ! ' }
Var
{ н ач а л о р а з дела опис ания перем енных }
GraphDrive r , GraphМode : Int eger ;
{ опис ание двух целочи с л енных п ер еменных }
Begin
{ н ач а л о р а з д ела опис ания л о гики пр ограммы }
GraphDriver : = Det e c t ;
{ пр и с в о ение п еременной GraphD r i v e r знач ения 0 }
GraphМode : = О ; { пр и с в о ение переменной GraphМode з н ач ения О }
Init Graph ( GraphDriver , GraphМode , ' ' ) ;
{ иници ализ ация гр афич е с к о г о р е жима }
S e t C o l o r ( DarkGray ) ;
{ у с тановка текущ е г о ц в е т а для линий и т е к с та }
S e t тext Styl e ( Gothi c F ont , Hori zDir , 0 ) ;
Uses
Graph ,
{ у с т ан о в к а т екуще г о шрифта G o t h i c
гориз он'l'ального напр а в л ения б а з о в о г о р а змера
( и споль з о в ан а константа 0 ) }
Out T extXY ( X , У , S ) ;
{ вывод с троки , з аданной конс тантой S , опорная
точка имеет к о ординаты ( 1 0 , 5 0 ) }
R e c t angl e ( X , У , X+TextWidth ( S ) , Y+TextHei ght ( S ) ) ;
{ вывод охватывающ е г о прямоу г о л ьника в о кру г
т е к с т а . Л е в ая в ерхняя точка прямоу гольника
с о вп а д а ет с опорной точкой с тр оки т е к с т а ,
а пр а в ая нижняя смещена относительно н е е
на ширину и высоту с тр оки т е к с т а }
ReadKey ;
{ пр о грамма при о с танавли в а е т с я до н а ж атия
поль з о в ателем клавиши }
C l o s eGraph ;
{ з акрыв а ем графич е с кий р ежим }
End .
{ к онец р а з дела опис ания л о гики пр о гр аммы }
Результат выполнения приведеиной программы немного не соответствует
нашим ожиданиям: охватывающий прямоугольник пересекает надпись. Од
нако не стоит искать ошибку - программа написана правильно. Готический
1 58
Глава 5 . Графи ка в Tu rbo Pasca l . В ы вод и нформации в графич еском режи ме
шрифт является декоративным, а с такими шрифтами проблемы в работе
встречаются везде, даже в операционной системе Windows, несмотря на то,
что одна из ее основных задач - стандартизация методов работы с пользо
вательским интерфейсом.
Если декоративный шрифт используется для вывода заголовков или каких
либо других надписей, задача которых - бросаться в глаза, то некорректное
определение размеров шрифта, скорее всего, не испортит внешнего вида
программы. А для вывода информационного текста декоративные шрифты
использовать не рекомендуется в силу их низкой читабельности.
5 . 1 0 . 5 . ФоРМАТИРОВАНИЕ тЕкстА.
П РоцЕдУРА SЕтТЕХтJusт1FY
При описании процедур вывода текста Outтext и OutTextxY было ука
зано, что опорная точка текстовой строки находится в левом верхнем углу
прямоугольника, охватывающего строку. Такое положение опорной точ
ки задано по умолчанию, но его можно изменить с помощью процедуры
Se tTextJus tify:
S e tTextJu s t i fy ( < Bыp a внивaниe по гори з онтали > ,
< Выр авнив ани е по в ертикали> ) ;
Параметр Выравнив ание no rориз ои'l'али задает расположение опор
ной точки относительно строки по горизонтали. Возможные значения дан
ного параметра следующие:
0: строка касается опорной точки своим левым краем;
1: строка касается опорной точки своим центром;
2 : строка касается опорной точки своим правым краем.
Вместо числовых значений параметра можно
использовать соответствующие константы мо
дуля Graph: L e f t T e x t=O, C e nt e r T ex t = 1 и
R i g h t T e x t =2.
Таким образом, возможны девять вариантов
выравнивания текста, определяемые раэличны
ми сочетаниями значений параметров Вырав
нивание no rоризои'l'али и Выравнив ание
no в ер'l'икали (на рис. 7 4 по казаны различные
варианты вывода одной и той же строки в за
висимости от установленного выравнивания) .
Рис . 74. Варианты положения
текстовой строки отно с итель но
точки вывода
Наиболее часто используемое форматирование текста, отличное от стан
дартного, - выравнивание по центру (см. рис. 7 5 ) . Приведем пример
1 59
Turbo Pascal 7 . 0
программы (см. листинг 049), отображающей такую над
пись. Три строки текста будут выводиться по очереди,
при этом выравнивание по горизонтали будет задано
от центра (горизонтальная координата опорной точки
находится посередине строки) , а выравнивание по вер
тикали - по верхнему краю (вертикальная координ ат а
опорной точки соответствует верхней части строки) .
Turbo Pascal
is my fi rst
Lang uage
Рис. 75. Текст.
выровненный
по ц ентру
Л истинг 049.
Вывод текстд
Program GraphText S ;
{ з аголо в ок пр о гр аммы , имя программы - G r aphT ext 5 }
{ начало р а здела подключения модул ей }
Graph , CRT ;
{ подключ ение модулей Graph и C RT }
Var
{ начало р а здела опи с ания переменных }
GraphDriver , GraphМode : Int e g e r ;
{ опис ание двух целочисл енных п ер еменных }
Begin
{ начало р а з д ел а опис ания л о гики пр ограммы }
GraphDriver : = D e t e c t ;
Uses
{ пр и с в о ение пер еменной G r aphD r i v e r знач ения 0 }
GraphМode
: =
О ; { прис в о ени е пер еменной GraphМode з нач ения 0 }
Ini tGraph ( GraphDrive r ,
GraphМode ,
' ' ) ;
{ инициализ ация гр афич е с к о г о р е жима }
SetColor ( DarkGray ) ;
{ у с тано вка текущ е г о цв е т а для линий и т е к с т а }
S e tText Styl e ( S ans S eri fFont , Hori z Dir , О ) ;
{ у с т ано вк а текущего шрифта S an s S e r i f
гори з онтальн о г о напр а в л ения б а з о в о г о р а змера
( испол ь з о в ана константа 0 ) }
S e t TextJu s t i fy ( C ent e rText , TopText ) ;
{ у с тановка текущ его выр а внив ания :
гориз онтальное - по центру ( исполь з о в ана
константа C ent erтext ) , в ертикально е - по в ерхн ему
кр аю ( и спольз о в ана кон с т анта TopText ) }
OutтextXY ( 3 2 0 , 8 0 , ' ТUrbo P a s c a l ' ) ;
{ выв од перв ой с троки , опорная точка име е т
ко ординаты 3 2 0 , 8 0 , с трока к а с а ет с я опорной
Out TextXY ( 3 2 0 ,
точки п о г ориз онтали - ц ентром ,
в ерхним краем }
2 4 0 , ' i s my f i r s t ' ) ;
OutTextXY ( 3 2 0 ,
{ вывод второй с троки ,
к а к и у п ервой }
4 0 0 , ' Language ' ) ;
п о в ертикали
в ыр а внив ани е т а к о е ж е ,
C l o s eGraph ;
{ вывод тр етьей с троки , выра внивание т а к о е ж е ,
как и у предыдущих }
{ про грамма при о с т ана влив а е т с я до наж атия
поль з о в а т е л ем клавиши }
{ з акры в а ем графич е с кий режим}
End .
{ к онец р а здела опис ания л о г ики пр о гр аммы }
ReadKey ;
1 60
Глава 5 . Графика в Turbo Pascal . Вы вод инфор м аци и в графическо м режи м е
5 . 1 0 . 6 . УСТАНОВКА НЕСТАНДАРТНЫХ ШРИФТОВ
В стандартной поставке Turbo Pascal можно подобрать шрифт к програм
ме практически любого назначения. Однако у всех этих шрифтов есть один
общий недостаток - они не содержат русских символов. Это достаточно
существенный недостаток, чтобы отказаться от предустановленных шриф
тов в пользу других, изготовленных третьей стороной. В настоящее время
создано довольно большое количество русифицированных ВGI-шрифтов,
а также программ для их разработки (все это можно найти в сети Internet) .
Для того чтобы подключить шрифт к проrрамме, необходимо воспользо
ваться функцией Ins tallUserFont, получающей в качестве параметра
название файла с В GI-шрифтом на диске и возвращающей номер, по кото
рому подключенный шрифт можно исполыювать:
Ins t a l lUs erFont ( <Имя
файла
с ВGI - шрифтом> ) ;
Имя файла указывается без расширения, при этом расширение должно быть
chr. Сам файл должен находиться в текущем каталоге проrраммы, как и все
остальные шрифты.
Рассмотрим установку дополнительных шрифтов на примере шрифта
B o l d, поставляемого с Turbo Pascal, но не включенного в список предуста
новленных шрифтов. Изменим предыдущий пример так, чтобы строки вы
водились не шрифтом S a n s S e r i f, а шрифтом B o l d :
Var
I n teger ;
F o n tNumЬe r :
{ о п и с а н и е ц е л о ч и с л е н н о й п е р ем е н н о й дл я х р а н е н и я
н оме р а
нового
у с т а н о в ки
Begin
шри ф т а ,
шри ф т а
{ н а ч а л о р а з де л а
:=
G r a ph D r i v e r
G r ap h M o d e
: =
О;
п олуче н н о г о
п р о ц е дур о й
п о сл е
I n s t a l l U s e r Fo n t }
о пи с а н и я л о г и ки
п р о г р аммы }
D e t ec t ;
{ пр и с в о е ни е п е р е ме н н ой G r a p h Dr i v e r з н а ч е н и я 0 }
{ при с в о е н и е
I n i tGraph ( G r a ph D r i ve r ,
п е р еме н н о й
G r a p hMo d e ,
{ иници а л и з а ц и я
G r aphMo de
з н а ч е ни я
0}
'' ) ;
г р а ф ич е с к о г о р е жима }
SetColor ( Da r kG r a y ) ;
{ ус т а н о в к а
Fo n t N um
: =
т е куще г о
цвета
дл я л и н и й
и
те кста }
I n s ta l l U s erFont ( ' b o l d ' ) ;
{ у с т ан о в ка шри ф т а , х р а н яще г о с я в ф а й л е b o l d . c h r
в т ом ж е к а т ал о г е ,
и
занесение
номе р а
ч т о и вып о л н я ема я п р о г р амма ,
нового
шр и ф т а
в
п е р еме нную
F o n t Num }
За."\fетим, что существуют локализованные (русифицированные) версии
стаrщартных предустановленных шрифтов. Файлы с такими шрифтами мо
гут быть скопированы поверх стандартных и, соответственно, будут подrру
жатъся автоматически, то есть их дополнительная установка процедурой
Ins tallUserFont не требуется.
6
Зак. 702
1 61
Turbo Pascal 7 . 0
5 . 1 1 . И З М ЕН ЕН И Е ХАРАКТЕРИ СТИ К ЦВ ЕТА
М ЕТОДЫ ХРАН ЕНИЯ И НФОРМАЦИ И О ЦВЕТЕ
Для хранения информации о цветовых характеристиках какого-либо объек
та используется несколько методов (цветовых моделей, моделей цветовос
произведения) . Мы не будем рассматривать всего их многообразия, а оста
новимся лишь на двух основных - RGB и СМУК. Эти цветовые модели
представляют любой цвет через несколько базовых цветов, взятых в опре
деленной пропорции.
В цветовой модели RGB используются следующие базовые цвета: красный
(Red), зеленый (Green) и синий (Blue). Название цветовой модели и состо
ит из первых букв базовых цветов. Такая модель называется аддитивной,
так как основана на сложеиии базовых цветов для получения представ
ления необходимого цвета. Получение цвета в модели RGB можно пред
ставить как сложение трех лучей света (см. рис. 76) - красного, зеленого
и синего. В зависимости от интенсивности (яркости) входных лучей на
выходе может получаться разный
результирующий цвет. Чем боль
ше интенсивность лучей базовых
цветов, тем ярче результирующий
цвет. Например, если интенсив
ность всех трех лучей нулевая, то
результирующий цвет будет чер
Син ий л у ч ( В )
ным. А если интенсивность крас
ного и синего лучей нулевая, а
Рис. 76. Формирование цвета в модели
зеленого луча - невелика, то по
цветовоепроизведения RGB
лучится темно-зеленый цвет.
При увеличении интенсивности зеленого луча результирующий цвет ста
новится все ярче и приближается к ярко-зеленому. Если теперь постепенно
увеличивать интенсивность красного луча, то результирующий цвет будет
становиться светлее и меняться от ярко-зеленого к желтому через грязно
желтый. Аналогично, если смешиваются красный и синий цвета, получают
ся различные оттенки фиолетового, если смешиваются зеленый и синий оттенки цвета морской волны. И , наконец, заметим, что если все лучи имеют
одинаковые интенсивности, то результирующий цвет будет являться оттен
ком серого (предельные случаи - белый для максимальных интеисивнос
тей и черный - для минимальных).
Цветовая модель RGB применима для устройств типа монитора, поверхность
которых может излучать световую волну, а изначально является черной.
В цветовой модели СМУК используются цвета морской волны (cyan ) , фи
олетовый (Ma g e n t a ) , желтый (Ye l l ow ) и черный (Ыа сК).
1 62
Глава 5 . Графика в Tu rbo Pascal . В ы вод и нформ аци и в графи ческом режи м е
П РИМЕЧАНИЕ.
Ч е р н ы й цвет ( B iack) обозн ачается в м одел и СМУК н е буквой В , а букв о й К, чтоб ы
и збежать испол ьзования си м вола В, зан ятого для обознач е н и я с и н его цвета ( B i u e )
в м одел и R G B .
Модель СМУК является не аддитивной моделью цветовоспроизведения,
а разностной (субтрактивной), основанной па логлощении цвета одних
цветовых составляющих другими составляющими (см. рис. 77). Процесс
создания цвета в такой модели можно представить как смешение прозрач
ных чернил. Чем больше красящего вещества содержится в чернилах, тем
меньше света отражается от поверхности, на которую чернила нанесены.
Соответственно, чем больше чернил
нанесено на поверхность, тем ближе
результирующий цвет к черному, а чем
меньше чернил на поверхности или
чем меньше красящего вещества в чер
нилах, тем ближе цвет к прозрачному.
Фиолетовый цвет (М)
Тон результирующего цвета, так же как
и в модели RGB, зависит от цветовых Рис. 77. Формирование цвета в модели
цветово епроизведения СМ УК
составляющих.
Черный цвет добавлен к данной модели для улучшения качества его выво
да, так как при выводе черного цвета с помощью смешения чернил не до
стигается нужная чистота (в результате смешения всех трех чернил обычно
получается грязно-коричневый, а не черный цвет) . Заметим, что при выво
де изображения на черную поверхность его не будет видно.
Модель СМУК используется для цветопередачи на отражающих поверхнос
тях, а не излучающих ( как RGB). Это значит, что модель СМУК используется
в печатных процессах, так как лист бумаги как раз и является той отражаю
щей поверхностью.
П РЕдСТАВЛЕНИЕ ЦВЕТА в TURBO PASCAL
Вне зависимости от разрешения и цветности графического режима в Tu.rbo
Pascal для представления цвета используется модель RGB. Однако есть не
которые особенности работы с разными графическими режимами. С точки
зрения хранения цветовой информации эr<рапа графические режимы де
лятся на индексированные и неиндексированные.
К индексированным режимам относятся те, которые для определения цве
та точки на экране используют таблицу цветов (палитру) . Так устроены все
графические режимы с цветностью до 256 цветов включительно.
К неиндексированным режимам относятся те, которые хранят цвета точек не в
таблице, а вместе с точка.\1 и. Например, в режимах T rue Co l o r на одну точку
1 63
Turb.o Pa$cal 7 . 0
экрана выделяется 3 байта, т о есть 2 4 бита, в которых и размещена информа
ция о цвете точки. На каждую составляющую приходится по 8 бит, таким об
разом, интенсивность каждой составляющей может изменяться от О до 255.
ИзмЕНЕН И Е цвЕТовой П АЛ ИТРЫ
Мы используем индексированный режим 640х480х 1 6 . Таблица цветов, со
ответственно, содержит в себе 1 6 цветов, цветовые составляющие которых
заданы так, чтобы соответствовать цветам, используемым в текстовом ре
жиме (такая конфигурация цветов называется системной палитрой) . Одна
ко можно изменить составляющие какого-либо из этих цветов с помощью
процедуры S e tRGBPalette :
S e t RGBPa l e t t e ( <H oмep ц в е т а > ,
< Кр а сная ц в е т о в ая с о с та в ляющая > ,
< З еленая ц в е т о в ая с о с т а вляющая > ,
< Синяя ц в е т о в ая с о с т авляющая> ) ;
Параметр Н омер ц в е т а определяет номер цвета в палитре, для которого
необходимо изменить цветовые составляющие.
П РИМЕЧАНИЕ.
В качестве значения параметра Нокер цве'Х'а все так же может б ыть использо
вана одна из кон стант м одуля CRT: Black, Blue, Cyan и т. д. Таким образо м , цвету,
которому соответствует константа Blue (син и й ) , можно назначить такие цветовые
составля ющи е , что он будет красны м .
Параметры
КраснаR
цветоваR
cocтaвJIRIOIЦЗ.R,
З еленаR
цв етоваR
и CиHRR цветоваR cocтaвJIRIOIЦЗ.R определяют ин
тенсивности соответственно красной, зеленой и синей цветовых составля
ющих в новом цвете и должны являться целочисленными константами или
переменными, имеющими значения от О до 63.
со ставл5ПС1Цё1R
После вызова процедуры S e tRGBPale tte вся информация, выведенная
на экран с использованием изменяемого цвета, приобретет заново установ
ленный цвет. Например:
SetRGBPa l e t t e ( Green ,
45 ,
50 ,
48) ;
{ изменение ц в е т о вых с о с т а в ляющих ц в е т а , з аданного
к о н с т а нт о й G r e en .
ц в етом ,
Все о бъ екты ,
выв еденны е э т им
при о б р е т ают н о вый ц в е т }
Обратите внимание, что помощью процедуры S e tRGBPal e t te в гра
фическом режиме 6 4 0 х 4 8 0 х 1 6 можно изменить цветовые составляющие
не для всех цветов, а только для цветов с номерами О, 1, 2 , 3, 4, 5 и 7.
1 64
Глава 5 . Графи ка в Turbo Pascal. Вывод и нформаци и в графическом режи ме
5 . 1 2 . С П РАЙТЫ
5 . 1 2 . 1 . СОЗДАНИЕ И ИСПОЛЬЗОВАНИЕ СП РАЙТОВ
Графическис процедуры Turbo Pascal характеризуются довольно низким
быстродействием. Это плата за независимость инструментов графическо
го вывода от аппаратуры, входящей в состав компьютера, на котором бу
дет выполняться разработанная программа. Медленнее всех работают про
цедуры заливки свободной области FloodFill и вывода текста outтext
(OutтextXY ) , но, в зависимости от сложности изображения, и другие про
цедуры могут сильно влиять на время вывода.
Медленно выполняемые операции рисования и повышенная сложность
объекта приводят к тому, что пользователь видит процесс построения
композиции на экране. Если при этом изображение персрисовывается
достаточно часто, например, при движении, то такая ситуация совер
птенно недопустима. Одним из вариантов ретпения данной проблемы
является упрощение рисунка, однако это не всегда возможно, так как
графические объекты на экране должны отвечать общей функциональ
ности приложения.
Стандартным методом ускорения вывода объектов на экран является ис
пользование спрайтов - прямоугольных растровых изображений, хра
нимых в памяти и выводимых в любой момент времени выполнения про
граммы в любое место экрана . Ускорение происходит за счет того, что
при многократном выводе одного и того же изображения оно не просчи
тывается каждый раз заново, а хранится в оперативной памяти и просто
копируется на экран, когда необходимо. В обычном же случае изображе
ние при выводе каждый раз просчитывается заново, поэтому вывод и про
исходит относительно медленно.
Использование спра:йтов - непростая задача, работа с ними производит
ся в несколько этапов, а некорректное использование спрайтов может
привести к серьезным последствиям для работоспособности системы. К
тому же спра:йты не решают вышеописанную проблему полностью: на ком
пьютере АТ 486 спра:йт, занимающий треть экрана, выводится около секун
ды, так что пользователь также может видеть процесс вывода.
Однако прорисовка спрайта происходит все же намного быстрее, чем вывод
объекта обычными процедурами рисования, потому что с точi<И зрения сис
темы это более простая операция, состоятцая в последовательном выводе
прямоугольной области, заполненной точками, и не подрааумевающая ка
кого-либо сложного алгоритма, как, например, при рисовании наклонного
отрезка или окружности.
1 65
Tu rbo Pascal 7 . 0
Рассмотрим порядок работы с о спрайтами кратко (см. рис. 78), а потом по
ясним каждый этап более подробно.
ЭТАПЫ РАБОТЫ СО СПРАЙТОМ
1 . Создание на экране изображения спрайта.
П р и создании изо б р аж ения могут быть исполь
зованы обычные процедуры вывода графичес
ких объектов. И з об р аж ение может иметь лю
бую сложность и включать в себя любые цвета.
Экран
Память
Память
2. Определение размера оперативной памя
ти, необходимой для хранения спрайта, и ее
выделение. В ыд ел ен и е памяти состоит в р е
зервировании за нашей пр ограм м о й пекотаро
го объема оперативной памяти, определяемого
площадью прямоугольника, о х в ат ывающ е го
изображение. Память находится в распоряже
нии программы до того момента, пока она ее
не освободит.
3. Создание спрайта в памяти на основе
построенного на экране изображения. ИзобРнс. 78. Этапы работы
ражели е, подготовленное в пун к т е 1 , копирусо спрайтами
ется в пам я ть , выделенную в пункт е 2 . В момент завершения копирования спрайт считается созданным и бу
дет находиться в памяти до ее освобождения или до замены его
другим спрайтом.
4. Копирование спрайта из памяти на экран. Вывод спрайта м о ж ет
производиться в любое место экрана произволыюе количество раз.
После копирования изображения спрайта из памяти на экран оно
не удаляется из памяти и может быть использовано повторно.
5. Освобождение памяти, занятой под спрайт. Освобождение п амяти
состоит в уведомл ен ии операционной сист ем ы о том, что память,
зар езе р в ир ованная дл я программы, б ольше не будет ей использо
ваться. При этом спрайт удаляется из памяти, а копии спрайта, уже
выведенные на экран, не стираются с него.
П одГОТОВКА ИЗОБРАЖЕН ИЯ И ОПРЕдЕЛЕНИЕ РАЗМЕРА ПАМЯТИ
ДЛЯ Х РАНЕНИЯ СПРАЙТА
Как было сказано выше, для подготовки изображения спрайта можно ис
пользовать любые графические процедуры. Единственное ограничение
накладывается на размеры изображения ( т очн ее на размеры его охватыва
ющего прямоугольника) . Поясним, чем в ы з ван о это о гран и ч ен и е
.
1 66
Глава 5 . Гра ф и ка в Turbo Pasca l . В ывод и нформ аци и в графическом режи ме
Размер оперативной памяти, в которую можно поместить спрайт, не должен
превышать 65535 байт. Это системнос ограничение операционной системы
MS- D O S . Объем памяти, необходимый для хранения информации об одной
точке, определяется цветностью графического режима. Н апример, для хра
нения одной точки с цветностью True Color требуется 3 байта, с цветностью
Hi Color - 2 байта, а с цветностью 1 6 - половина байта, то есть в каждый
байт записывается информация о двух точках. Также каждый спрайт резер
вирует 6 байт для внутреннего использования, например, для определения
ширины и высоты изображения. Таким образом, охватывающий прямо
угольник спрайта может содержать не более (65535 - 6) * 2 = 131058 точек.
На самом деле это число подходит не для всех сочетаний ширины и высо
ты охватывающего прямоугольника и расчетный размер обычно превышает
реально возможный, поэтому лучше не пытаться использовать максималь
но большие спрайты. Вообще не рекомендуется использовать спрайты, раз
меры которых превышают 200х200, потому что такие изо браже н ия долго
выводятся на экран.
Определение размера памяти, необходимой для хранения спрайта, произ
водится функцией ImageSi ze:
ImageSi z e { < Гориз онтальная координата 1 > 1 <Вертикальная ко ордината 1 > 1
<Гориз онтальная координата 2 > 1 <Вертикальная координата 2 > ) ;
Параметры, используемые данной функцией, аналогичны параметрам про
цедуры Rectangle и задают левую верхнюю и правую нижнюю точки ох
ватывающего прямоугольника.
Приведем пример программы, определяющей размер оперативной памя
ти, необходимой для хранения спрайта с размерами изображения 1 50х200
(см. листинг 050). Заметим, что объем памяти зависит не от расположения
охватывающего прямоугольника па экране, а только от его размеров.
Л ИСТИНГ 050. ОПРЕДЕЛЕНИЕ ПАМЯТИ, НЕОБХОДИМОЙ ДЛЯ ХРАНЕНИЯ СПРАЙТА
Program G e t t ingSpri t e S i z e ;
{ з а г о л о в о к пр о гр аммы ,
имя пр о гр аммы -
G e t t i ng S p r i t e S i z e }
Uses
Graph 1
{ н ачало р а з д е л а подключ ения модул ей }
CRT ;
{ подключ ение модулей Graph и CRT }
Var
{ начало р а з д е л а опис ания п ер еменных }
GraphDrive r 1
GraphМode :
Int e ger ;
{ опи с ани е двух ц е л очи с л енных п ер еменных }
Spri t e S i z e :
Word ;
{ описание переменной для хр анения о бъема памяти }
Begin
GraphDriver
{ н ачало раздела опис ания л о гики программы }
. - Det e c t ;
{ при с в о ение п ер еменной GraphD r i v e r з н ач е ния О }
1 67
Turbo Pascal 7 . 0
GraphМode
О;
: =
{ nр и с в о ение n еременной GraphMo de з н а ч ения О }
GraphМode , ' ' ) ;
{ инициали з ация графич е с к о г о р ежима }
ImageSi z e ( l O , 1 0 , 1 6 0 , 2 1 0 ) ;
{ nрис в о ение n ер еменной Spr i t e S i z e знач ения
функции ImageS i z e , в о з вращающей р а змер
n амяти , н е о бходимой для хр ан ения сnр айта
ра змером 1 5 0 х 2 0 0 }
{ nр о гр амма nри о с т анавлив а е т с я до н а ж а тия
nоль з о в ат ел ем клавиши }
{ з акры в а ем графич е с кий р ежим }
InitGraph ( GraphDriver ,
Spri t e S i z e
: =
ReadKey ;
C l o s eGraph ;
End .
{ конец р а з д е л а оnис ания л о гики nрограммы }
ОСНОВЫ РАБОТЫ
1
С
ОП ЕРАТИВНОЙ ПАМЯТЬЮ
Сегмекr 0_(64К}_
,
Сегмекr
1 (64К}
о 1 2 3 4 5 6 о 1 2 3 4 5 6 о 1 2
7 8 9
7 8 9 ...
7 8 IJ!fj . . .
5 6 о 1 2
7 8 9
о 1 2 3 4 5 6 о 1 2 3
7 8 9 ...
7 8 9 ...
Байт с адресом
[1
: 9]
\
Рис. 79 . Структура
оперативной памяти
[ <Н омер с е гмент а >
Оперативную память переанального компьюте
ра можно представить в виде совокупности бай
тов (см. рис. 79), разбитых на сегменты - облас
ти памяти размером 65536 байт ( 64 килобайта,
64Кб). Таким образом, для указания того, какой
номер в сегменте имеет некоторый байт, необхо
димо использовать 1 6-битовое число (или 2-бай
товое, что одно и то же). Для указания номера
сегмента также применяются двухбайтовые чис
ла. Таким образом для указания конкретного
места в памяти используется 4 байта, а адрес байта принято записывать так:
<Смещение в с е гмент е > ]
Размер сегмента накладывает множество ограничений на программы в
MS-DOS. Например, сегмент, выделенный программе для хранения данных
(его называют, соответственно, сегмент данных - Data Segment), так же как
и все сегменты, занимает 64 килобайта, следовательно, появляется ограниче
ние на количество переменных, описанных в програ..'\fме, точнее, на суммар
ный объем памяти, который они занимают. Таким образом, в программе, на
пример, можно описать всего 32768 персменных типа I nt e g e r (переменные
данного типа занимают по два байта (на самом деле еще меньше, так как в
сегменте данных хранится также и другая информация, в том числе размеща
емая автоматически)) или 255 персменных типа S t r i n g (занимают по 256
байт). Ограничение на размер памяти, занимаемой спрайтом, имеет то же са
мое обоснование - спрайт не может занимать более одного сегмента памяти.
П РИМЕЧАНИЕ.
Н етрудно подсч итать теоретический м аксимал ь ный объем ОЗУ п р и та ком методе ад
реса ции (дв а б а йта для определения номера сегмента и два б а йта для определения
смещен ия в сегменте ) . М а ксимально воз можное количество сегментов (65536) следу
ет умножить н а р азмер сегмента (также 6553 6 ) , в резул ьтате чего получ аем 4294967296
ба йт, то есть 41 94304 килоб айт, то есть 4096 мегаб айт, то есть 4 гигаб а йта .
1 68
Глава 5 . Графика в Turbo Pascal. В ы вод информации в графическом режи ме
Мы уже выяснили, что ограниченный размер спрайта не создаст особых
трудностей в работе, однако ограничение на размер сегмента данных не поз
волит создать даже несколько спрайтов одновременно. Решить проблему
хранения больших объемов информации позволяет другой вид памяти динамическая, которая еще наэывается Неар-память (от англ. Неар - куча).
Свое второе название эта память получила из-за того, что место в ней выде
ляется всем программам, работающим в данный момент, вперемешку.
Размер данной памяти изначально составляет 640 килобайт (то есть 1 0 сег
ментов ) . Однако к моменту запуска программы ее уже намного меньше
в силу того, что она может использоваться и интегрированной средой, из ко
торой запускается программа, и, например, Nortoп Commaпder, из которого,
возможно, была запущена интегрированная среда, а также другими про
граммами, работающими на машине, например, русификатором.
Для работы с Неар-памятью исполь
зуются персменные типа Pointer,
хранящие в качестве своих значений
четырехбайтовые адреса областей
Неар-памяти, выделенных программе. Такие персменные называют ссы
лочными или переменными-указате
лями, так как они сами находятся в
одних областях памяти (например,
в сегменте данных), а ссылаются на
другие (см. рис. 80). Подробнее об
указателях читайте в п. 9.5.
Для запроса к операционной системе
на выделение памяти программе ис
пользуется процедура Getмem.:
GеtМеm ( < С с ыл о чная п е р еменная> ,
Пе р еме нная ти па Pointer
ссылает с я на байт
с адресом [1 : 9]
се rмelfТ данных
Неар -nам ять
"
о 1 00М1 В6
7 8 9 ...
1\
\1
о 1 2 3 4 5
7 8 9 ...
6 о
о 1 2 3 4 5
7 8 9 ..
6 о 1
) 2 3 4 5
...
7 8
6 о
7
1 2
8
9
2 3 4 5 6 о 1 2
7 8 9
7 8 9 .
Рис . В О . Механизм работы
ссылочных переменных
< Р а змер п амяти> ) ;
В качестве параметра С сы.nочная nеренеиная должна использоваться
персменная типа Pointer, предварительно описанная в разделе описания
персменных Var в обычном порядке. Под эту перемешrую еще пе должно
быть выделено Неар-памяти, иначе предыдущая ссылка, хранящаяся в этой
переменной, будет утеряна и программа утратит возможность возвратить
память в операционную систему после своего завершения, что приведет
к накоплению зарезервированной памяти, не используемой никакими про
граммами, и рано или поздно система перестанет быть работоспособной.
П РИМЕЧАНИЕ.
Д аже п р и в н и м ательной р а б оте с Н е а р - п а мят ь ю в о в р е м я отл ад ки п р огр а м м н е
удается из б ежать о ш ибок , поэ тому и нтегриров а н н ая среда , о ч е н ь чувствител ь н а я
к н едостатку п амя ти , в ыда ст сооб щен и е о н ехв атке п а м я ти для р а бо т ы . О ч е н ь ч а с
то п осле п оя влен и я та кого соо б щен ия и нтегр и р о в а н н ая среда уже не м оже т с о
хран ить и зм е н е н и я , п р о и з в еде н н ы е в п р о гр а м м е , п оэтому п р и р аботе с Н е а р- п а
м ятью р еком е н дуется сохр а нять п рогр а м м у перед кажд ы м за пуско м .
1 69
Turbo Pascal 7 . 0
Параметр Размер па.:мя:ти задается целочисленной переменной или кон
стантой, содержащей размер памяти в байтах, который операционная сис
тема должна выделить в Неар-памяти. В случае удачного выполнения про
цедуры Getмem в Неар-памяти резервирустел месторазмером, заданным
параметром Размер па.:мя:ти, и ссылка на начало зарезервированной об
ласти заносится в переменную, указанную в качестве п а р ам етр а Ссыл оч
ная: перемеииая:.
Перед завершением программы или ранее, если выделенная память уже
не будет использоваться, необходимо уведомить систему об освобожде
нии зарезервированпой памяти. Очищать память при этом не нужно: дру
гая программа, которая получит эту же область, просто заполнит ее свои
ми данными. Для уведомления системы об освобождении памяти
используется продедура FreeMem, имеющая такие же параметры, как и
процедура Ge tMem:
FrееМеm ( < С сыл очная переменная > ,
< Р а змер памяти> ) ;
В качестве параметра Ссылочная: перемеииая: должна исполъзоваться
переменная, под которую уже выделена память процедурой Ge tмem. Раз
мер освобождаемой памяти, задаваемый параметром Размер па.:мя:'I.'и, дол
жен соответствовать размеру зарезервированной памяти, иначе она будет
освобождена пе полностью, что аналогично отсутствию освобождения, рас
смотренному выше.
Рассмотрим программу, резервирующую область Неар-памяти размером
1 00 байт, а затем освобождающую ее (см. листинг 05 1 ) .
Л истинг 0 5 1 . РдБотд с НЕАР-nдмятью
Program He apMemoryl ;
{ з аг о л о в о к пр огр аммы , имя пр о гр аммы - Н е арМепю .rу l }
{ начало р а з д е л а опис ания пер еменных }
Var
MyМemory :
P o i nt e r ;
{ опис ани е с сылочной п ер еменной тип а P o i n t e r
для выдел ения п о д н е е Н е ар - п амяти }
Begin
{ начало раздела опис ания л о гики пр о гр аммы }
Wri t e Ln ( ' Для выделения памяти нажнит е клавишу ' ) ;
{ вывод с о о бщ ения о н е о б х одимо с т и нажать к л а в ишу }
ReadKey ;
GetMem ( MyMemory ,
{ ожидание нажатия поль з о в ат е л ем клавиши }
100 ) ;
{ п олуч ение с сылки на п амять р а змер ом
1 0 0 б айт ,
с сылк а з аписыв а е т с я в
п ер еменную MyMerno ry }
с с ыл очную
Wr i t e Ln ( ' Пaмят ь успешно з ар е з ервирована ! ' ) ;
{ вывод с о о б щ ения о б у спешном полу ч ении п амя·ги }
Wri t e Ln ( ' Для о с в о б ождения памяти нажните клавишу ' ) ;
{ вывод с о о бщения о н е о бходимо с ти н а ж а т ь к л а в ишу }
1 70
Глава 5 . Гра ф и ка в Turbo Pascal. В ы вод и нформ аци и в графи ческом режи ме
ReadKey ;
{ ожидание н а ж атия поль з о в а т ел ем к л авиши }
Fre eMem ( МуМеmоrу ,
1ОО ) ;
{ о с в о б о ждение п амяти ,
з аданной с сылкой ,
хранимой в пер еменн ой MyMemo ry .
О с в о б ождается
память р а змер ом 1 0 0 б айт }
Wr i t eLn ( ' Пaмят ь успешно о с в о б ождена ! ' ) ;
{ вывод с о о бщения о б у с п ешном п олуч ении п амяти }
Wri t eLn ( ' Дnя з а в ершения программы нажните клавишу ' ) ;
{ вывод с о о бщения о н е о бходимо с ти наж а т ь клавишу }
ReadKey ;
{ о жид ани е наж атия поль з о в ат е л ем кла виши }
End .
{ конец р а з д е л а опи с ания л о гики программы }
ВыдЕЛЕНИЕ ПАМЯТИ ДЛЯ ХРАНЕНИЯ СПРАЙТА И ЕЕ ОСВОБОЖДЕН И Е
Выделение памяти под спрайт ничем не отличается от предыдущего при
мера, за исключением того, что размер памяти должен быть предваритель
но получен от функции Image S i z e (см. листинг 052). Заметим также, что
предыдущая программа работала в текстовом режиме, что недопустимо
при использовании функции Image S i z e .
Л ИСТИНГ 052. РЕЗЕРВИРОВАНИЕ ПАМЯТИ ДЛ Я ХРАНЕНИЯ СПРАЙТА
Program H eapMemory2 ;
{ з а г о л о в о к пр о граммы , имя пр о граммы - H e apMemory 2 }
{ н ачало р а з д е л а п одключ ения модул ей }
CRT ;
{ подключение модулей G raph и CRT }
Var
{ начало р а з д е л а опи с ания пер еменных }
GraphDriver , GraphМode : Int e ger ;
{ опи с ание двух цел очи с л енных пер еменных }
Spri t e S i z e : Word ;
{ описание переменной для хр анения о б ъ ем а п амяти }
SprMemory : P o i nt e r ;
{ опи с ание с сылочной п ер еменной типа P o i n t e r
для выдел ения п о д н е е Н е ар - п амяти , н е о бходимой
для хр анения с пр айт а }
Begin
{ н ачало раздела опис ания л о гики пр ограммы }
GraphDr ive r : = D e t e c t ;
Uses
Graph ,
{ прис в о ени е пер еменно й G r aphD r i v e r з н а ч ения 0 }
{ пр и с в о ение переменной Gr aphМo de знач ения О }
InitGraph ( GraphDriver , GraphМode , ' ' ) ;
{ инициализ ация графич е с к о г о р ежима }
Spri t e S i z e : = Imag e S i z e ( 1 0 , 1 0 , 1 6 0 , 2 1 0 ) ;
GraphМode : = O ;
{ при с в о ение п ер еменной Sp r i t e S i z e з н а ч ения
функции Image S i z e , в о з вращающей р а змер
памяти , н е о бходимой для хр анения спрайта
ра змер ом 1 5 0 х 2 0 0 }
GetMem ( SprMemory , Spri t e S i z e ) ;
{ п олучение с сылки на память ра змером , з аданным
знач ением пер еменной Spr i t e S i z e , с сылк а
з апи с ы в а ется в с сыл очную пер еменкую SprM emo ry }
171
Turbo Pascal 7 . 0
FreeMem ( SprMemory ,
Spr i t e S i z e ) ;
{ о с в о б ождение памяти ,
з аданной с сылкой ,
в n ер еменной Sp rMemory .
ра змером ,
хранимой
О с в о б о ж д а е т с я память
з аданным знач ени ем nеременн о й
Sp r i t e S i z e ,
то е с ть р а змер о с в о б ожда емой п амят и
р а в ен ра змеру з ар е з ервир о в анн ой }
SetColor ( DarkGray ) ;
{ у становка текущ е г о ц в е т а для выв одим о г о т е к с т а }
S et Text Styl e ( De f au l t Font ,
Hori z Di r ,
0) ;
{ у с тано в к а с и с т емно г о
шр и ф т а
в к ач е с т в е т е куще г о ,
( и споль з о в ан а константа D e f au l t F o n t ) }
OutTextXY ( 1 0 ,
1 0 , ' Програмиа выполнена ! ' ) ;
{ вывод с о о бщения об усn ешном выnолн ении
в с ех действий }
{ пр о грамма nриостана вли в а е т с я до н а.ж атия
ReadKey ;
пол ь з о в ателем кл авиши }
C l o s eGraph ;
{ з а кр ываем графич е ский р ежим }
End .
{ к онец р а з дела опис ания л о г ики nр о граммы }
Распространешюй ошибкой является последовательное выделение памяти
под спрайты разных размеров с использованием одной и той же перемен
ной, в которой размер хранится. Допустим, первый спрайт занимает в памя
ти 3000 байт. Программа вьщеляет память, необходимую для его хранения,
и размер этой памяти сохраняет в переменной. Затем выделяется память
под спрайт, занимающий 5000 байт, и р аз м е р выделенной памяти сохраня
ется в той же переменной. Тогда освобождение памяти, занятой под второй
спрайт, будет корректным, так как системе будет передан запрос на осво
бождение 5000 байт. Однако освобождение памяти, занятой под первый
спрайт, некорректно, так как будет произведена попытка освободить боль
ше места (5000 байт) , чем зарезервировано (3000 байт). Программа прервет
свое выполнение, и будет выдана ошибка E rror 2 0 4 : Inva1id Pointe r
Operation - Оши б к а 2 0 4 : Н е к орр е к т н а я о п ер аци я с о с сыл о ч н ой
п ер еме н н ой .
Во избежание ошибок такого рода рекомендуется для каждой ссылочной пе
ременной создавать св ою цел очи сл е нную переменную, имеющую похожее
имя. Например, для первого спрайта персменные могут называться S p r l
и S p r S i z e l , а для второго - S p r 2 и S p r S i z e 2 . Покажем та:r<ой прием на
примере (см. листинг 053).
Л ИСТИНГ
053.
РЕЗЕРВИРОВАНИЕ ПАМЯТИ ДЛ Я ХРАНЕНИЯ СПРАЙТА
Program HeapMemory2 ;
{ з а г о л о в о к программы ,
Graph ,
1 72
имя
nро граммы - HeapMemory2 }
{ начало р а з дела подключ ения модУл е й }
Uses
CRT ;
{ подключ ение модУл ей Graph и CRT }
Глава 5. Гра ф и ка в Turbo Pascal . В ывод и нформаци и в графическом режи ме
Var
{ начало р а здела опис ания п ер еменных }
GraphDriver ,
GraphМode :
Int eger ;
{ опис ание двух целочисл енных п ер еменных }
SprS i z e 1 ,
SprSi z e 2 : Word ;
{ опис ание двух переменных для хр анения
р а змер о в двух спрайто в }
Spr1 ,
Spr2 :
Point er ;
{ описание двух с с ыл очных п ер еменных
для выдел ения под них Неар-памяти ,
нео бходимой для хр анения спрайт о в }
Begin
{ н ачало р а здела опи с ания ло гики пр оrраММЫ }
GraphDriver
: =
De t e c t ;
{ прис в о ение п ер еменной GraphDr i v e r з н ач ения О }
GraphМode
: =
О ; { прис в о ение пер еменной GraphМode з н а ч ения 0 }
Init Graph ( GraphDriver ,
GraphМode ,
' ' ) ;
{ инициализ ация графич е с к о г о р е жима }
Spr S i z e 1 : = ImageS i z e ( 1 0 ,
10 ,
160 ,
2 10 ) ;
{ при с в о ение переменной Sp r S i z e l з н а ч ения
функции Ima g e S i z e ,
в о з вращающей р а змер п амяти ,
н е о бходимой для хр ан ения п ер в о г о спрайта }
SprS i z e 2 : = ImageS i z e ( 1 0 0 ,
100 ,
180 ,
2 14 ) ;
{ пр и с в о ение п ер еменной Spr S i z e 2 з н а ч ения
функции Ima g e S i z e ,
в о з вращающей р а змер памяти ,
н е о бходимой для хранения в т ор о г о спр айта }
GetMem ( Sp r 1 ,
SprS i z e 1 ) ;
{ получение с сылки на память р а змером ,
з а д анным значением пер еменной Sp r S i z e l ,
с сылка з апи с ы в а е т с я в с с ылочную п ер еменную Sp r l }
GetMem ( Spr2 ,
SprS i z e 2 ) ;
{ по луч ени е с сылки н а память р а змер ом ,
з аданным з н ач ением пер еменной Spr S i z e 2 ,
с с ылка
з аписыв а е т с я в с с ылочную п ер еменную Spr2 }
FreeMem ( Spr1 ,
SprS i z e 1 ) ;
{ о с в о б ождение памяти ,
з аданной с сылкой ,
хр анимой в пер еменной S p r l
память ра змером ,
Spr S i z e l ,
.
О с в о б ожда е '!'СЯ
з аданным знач ением п ер еменной
т о е с ть р а змер о с в о б ожда емой памя'l'И
р а в ен размеру з ар е з ервир о в анной }
FreeMem ( Sp r 2 ,
SprS i z e 2 ) ;
{ о с в о б о ждение памяти ,
з аданной с с ылкой ,
хр анимой
в п ер еменной Spr2 . О с в о б ож д а е т с я память р а змером ,
з аданным знач ением п е р еменной Spr S i z e 2 ,
то е с ть
р а змер о с в о б ождаемой памяти р а в ен р а змеру
з ар е з ервир о в анной }
ReadKey ;
{ пр о rр амм а при о с т ан а в ли в а е т с я до н а ж а тия
C l o s eGraph ;
{ з акрываем графич е с кий режим }
End .
{ ко н ец р а з д е л а опис ания л о гики пр огр аммы }
пол ь з о в а т е л ем клавиши }
1 73
Turbo Pascal 7 . 0
СозДАние с n РАйТА в пдмят и
Для копирования изображения спрайта с экрана в память используется про
целура Ge timage, им е ю щ ая параметры, аналогичные параметрам процеду
ры Ima g e S i z e , задающим прямоугольную область, в которой находится
изображение, подготовленное для спрайта, и еще один параметр, указываю
щий, в какую область памяти необходимо поместить изображение:
Gеt imаgе ( < Гориз онтальная координата l > , < В ертикальная ко ордината l > ,
< Г ор и з онт альная ко ордината 2 > , < В ертик альная к о ордина •I•а 2 > ,
< С сылочная пе ременная> л ) ;
Обратим внимание на символ л, используемый после параметра Ссьшоч
Данный символ является оператором разыменования,
показывающим, что для сохранения спрайта должна использоваться не не
ременная, за,п;анная в качестве параметра Ссьшочнаи nеременнаи, а об
ласть памяти, которая вьщелена под нее.
наи nеременнаи.
Необходимо внимательно следить за наличием оператора разыменования,
так как при его отсутствии информация о спрайте будет записана по адресу
ссылочной переменной, а поскольку ее размера (всего четыре байта) не хва
тит для хранения спрайта (как минимум десять байт), то данные будут зане
сены в переменные, находящиеся после ссылочной переменной в сегменте
данных. В результате этого их значения будут некорректно изменены, что
может привести к неработоспособности программы.
ВЫВОД СПРАЙТА НА Э КРАН
Копирование изображения спрайта из памяти на экран осуществляется
продедурой Pu timage:
Рut imаgе ( < Гориз онтальная ко ординат а > , < В ертик альная ко ордина�· а > ,
< С сылочная пер еменная> л ,
<Метод выв о д а > ) ;
Опорной точкой изображения спрайта является его верхний левый угол,
его расположение на экране при выводе определяется парой параметров
Горизонтальна• координата и Вертикальна• координата. Размеры
спрайта уже известны системе, поэтому задавать их нет необходимости.
Параметр Ссьшочнаи nеременнаи определяет область памяти, в которой
находится информация о выводимом спрайте. После переменной, указанной
в качестве этого параметра, необходимо использовать оператор разымено
вывания л , чтобы указать в качестве области хранения спрайта не ссылоч
ную переменную, а область Неар-памяти, на которую персменная ссылается.
Параметр Метод выs ода опр ед еля е т операцию, производимую с каждой
точкой спрайта при выводе ее на экран. В данных операциях могут участво
вать не только точки спрайта, но и точки экрана, на которые они попадают
1 74
Глава 5 . Граф и ка в Tu rbo Pasca l . В ы вод и нформации в графи ческом режи ме
при выводе. Этим достигаются некоторые интересные эффекты. П араметр
выв ода может являться целочисленпой переменной или копетап
той и иметь одно из следующих значений:
Mer:t�oд
•
Значение О или специально описанные в модуле Graph константы
Normal.Pu t и CopyPut ( I<акую из этих констант использовать, не име
ет значения). При таком значении параметра Меr:t�од вывода изобра
жение копируется на э кр ан без изменений, затирая все, что находится
в прямоуrольнике, на который попадает спрайт.
•
З на ч ение 1 или специально описанную в модуле Graph констан
ту XORPut . При выводе для каждой точки спрайта с ее цветом и
цветом точки экрана, на которую она выводится, производится по
битовая операция XOR, которая для двух одинаковых битов аргу·
ментов возвращает нулевое значение, а для двух р азных - единицу.
Например:
Точка фона:
Точка спрайта:
Результат:
1 1 00
1010
0110
XO R
Операция XOR непредсказуемым образом влияет н а цветовое
оформление изображения, в зависимости от того, на какой фон
это изображение выводится. Однако у данной операции есть инте
ресное свойство: если с полученным результатом выражения и од
ним из аргументов этого выражения повторно провести операцию
XOR, то в р езультате будет получен второй аргумент. Проверим это
свойство на нашем примере:
Результат:
Точка спрайта:
Точка фона:
0110
1010
1 1 00
XO R
Об р атим о сть операции XOR широко используется для простей шсrо
шифрования информации, когда с некоторой последовательнос
тью символов последовательно проводится операция XOR, в ре
зультате чего теряется информативность последовательности. Для
восстановления информативности необходимо произвести анало
гичную процедуру еще раз. При выводе спрайтов операцию XOR
используют для удаления спрайта с экрана и восстановления пре
дыдущего изображения. То есть если вывести спрайт на экран с ис
пользованием метода XOR, а потом повторить эту процедуру еще
раз, то на месте спрайта останется изображение, которое было до
его первоначального вывода.
Если выводить спрайт на черный фон, то его внешний вид не изме
нится и будет таким же, как и при выводе без использования поби
товых операций. Покажем это:
1 75
Turbo Pascal 7 . 0
Черный фон:
Точка спрайта:
Результат эквивалентен выводимой точке спрайта:
0000
1О1О
1010
XOR
Если повторить процедуру вывода спрайта, то мы получим черный фон:
Точка спрайта:
Точка спрайта:
Результат эквивалентен черному фону:
•
1010
1010
0000
XOR
Значение 2 или описанную в модуле Graph константу ORPut. При
выводе для каждой точки спрайта с ее цветом и цветом точки эк
рана, на которую она выводится, производится побитовая операция
OR (логическое сложение), которая возвращает единицу для двух
соответствующих битов, если хотя бы один из них имеет единичное
значение. Например:
Точка фона:
Точка спрайта:
Результ ат:
1 1 00
1010
1 1 10
OR
Эффеi<том использования операции OR при выводе спрайта будет его
частичная прозрачность, то есть сквозь выведенный спрайт будет вид
но изображение, которое является более ярким, чем выводимый спрайт,
хотя бы по некоторым цветовым составляющим. Например, сквозь
красное изображение будет видно зеленое, потому что у зеленого изоб
ражения есть более интенсивная цветовая составляющая - зеленая.
Сквозь черное изображение фон будет виден полностью, а сквозь бе
лое изображение не будет видно ничего. Таким образом, чем темнее
выводимый по методу ORPut спрайт, тем выше его прозрачность.
•
Значение 3 или описанную в модуле Graph константу AND Put. При
выводе для каждой точки спрайта с ее цветом и цветом точки экра
на, на которую она выводится, производится побитовая операция
AND (логическое умножение). Эта операция возвращает единицу для
двух соответствующих битов, только если они оба имеют единичное
значение. Например:
Точка фона:
Точка спрайта:
Результат:
1 1 00
1010
1 000
AND
Результат, достигаемый методом вывода логического умножения, мож
но описать как фильтрацию цвета фонового изображения. Те точки
фона, которые имеют цветовые составляющие, пересека.ющиеся с цве
товыми составляющими спрайта, остаются на экране, а цветовые со
ставляющие фоновых точек, не присутствующие в соответствующих
точках спрайта, удаляются.
1 76
Глава 5 . Графика в Turbo Pascal . В ы вод и нформаци и в графи ческом режи ме
•
Значение 4 или описанную в модуле Graph константу NOTPu t. При
выводе для каждой точки спрайта ее цветовые составляющие инвер
тируются (изменяются на противоположные), точки фона при этом
не учитываются. Например:
Точка спрайта:
Результат:
1 1 00
00 1 1
NOT
Изображение, выведенное с использованием инверсии, будет напо
минать негатив фотографии.
И, наконец, рассмотрим пример работы со
спрайтами (см. листинг 054). Для изобра
жения спрайта подготовим иаображение
теннисной ракетки, наказанное на рис. 8 1 ,
и создадим спрайт. Далее выведем н а экран
и з обр аж ения пяти мячиков (пример мячика
также показав на рис. 8 1 ) и н ал о жим на них
спрайт пять раз с использованием методов
вывода Norma1Put, XORPut, ORPu t, ANDPu t
и NOTPut.
Рис. 8 1 . Изображение
ракетки и мячика
Л ИСТИНГ 054. РАБОТА СО СПРАЙТАМИ
Program Spri t e s ; { з а г о л о в о к про граммы ,
Uses
Graph ,
имя пр огр аммы - S p r i t e s }
{ начало р а з д е л а подключ ения модул е й }
CRT ;
{ по дключ ение модул ей Graph и CRT }
{ начало р а з д ел а опи с ания п ер еменных }
GraphМode : Int e g e r ;
Var
GraphDr iver ,
{ опи с ание двух целочисл енных п ер еменных }
{ опис ание пер еменной для хр ан ения р а змера спрайт а }
Spr : P o i nt e r ;
{ опис ание с сылочной переменной для выдел ения
под н е е Н е ар - памяти , н е о бходимой для
хр анения спрайта }
Begin
{ начало р а з д ела опис ания л о гики про г р аммы }
GraphDriver . - Det e c t ;
SprS i z e : Word ;
{ при с в о ение п ер еменной GraphD r i v e r знач ения О }
GraphМode
: =
О ; { прис в о ение переменной GraphМode знач ения О }
InitGraph ( GraphDrive r ,
GraphМode , ' ' ) ;
{ инициализ ация графич е ск о г о р ежима }
SetLineStyl e ( S o l i dLn , О , Thi c kWidth ) ;
{ у с тановка о б в одки в виде т о л с т о й сплошной линии }
S e t C o l o r ( DarkGray ) ;
{ т екущий ц в е т для линий - т емн о - с ерый }
Li ghtGray ) ;
{ у становка клетчатой з аливки с в етло - с ер о г о ц в е т а }
7 0 , 3 5 0 , О , TopO f f ) ;
S e t F i l l S tyl e ( Hat chF i l l ,
Bar З D ( S O ,
200 ,
{ вывод ручки рак етки с о б в одкой и з аливкой
( параллел епип ед без в ерхн ей грани ) }.
1 77
Tu rbo Pascal 7 . 0
S e t F i l l Styl e ( Hat chFi l l , Ye l l ow ) ;
{ у с тановка кл етчатой з аливки ж е л т о г о ц в е т а }
F i l l E l l ip s e ( б O ,
110 ,
50 ,
100 ) ;
{ вывод в т орой ч а с ти рак етки ,
как и у ручки )
SprS i z e : = Image S i z e ( 1 0 , 1 0 , 1 1 0 ,
о б в одка - т акая ж е ,
350 ) ;
{ оnр еделение н е о бходимо г о р а змера cnp aй•r a }
GetMem ( Spr ,
SprS i z e ) ;
Get image ( 1 0 ,
{ выделение Н е ар - n амяти з аданн о г о р а змер а )
1 1 0 , 3 5 0 , Spr л ) ;
10 ,
{ к оnир о в ание и з о браж ения в nамять
для с о з дания спрайта )
ReadKey ;
{ пр о гр амма при о с т анавлив а е т с я до н а ж а тия
nоль з о в ат е л ем кла виши -- д а ем в о зможно с т ь
по ль з о в ат елю n о смотр еть н а и з о бр а ж е ни е ,
на о с н о в е котор о г о буде т с о з дан сnрайт )
C l e arDevi c e ;
{ и з о браж ение б ольше не ну жно - оно хр анится
в nамяти , удаляем все
S e t LineStyl e ( S o l i dLn , О , NormWi dth ) ;
с экр ана )
{ у с т ан о в к а текущей о б в одки
в виде тонкой сnлошной линии }
S e t C o l o r ( Li ghtGray ) ;
{ т екущий ц в е т для линий - с в етло - с ерый }
S et F i l l Styl e ( S l a shF i l l , Red ) ;
{ у с тановка штрихо в ой з а ливки кр а с н о г о ц в е т а }
S e t BkCo l o r ( Gr e en ) ;
{ и зменение ц в е т а фона на з ел еный
р е зультат виден сразу ж е }
SetRGBP a l e t t e ( Green , О , 1 0 , О ) ;
{ и зменение ц в е т о вых с о с т а в ляющих з ел е н о г о
ц в е т а - д е л а ем е г о оч ень т емным }
F i 1 1 E l l ip s e ( 7 0 , 1 0 0 , 4 0 , 3 4 ) ;
F i 1 1 E l l ip s e ( 1 9 0 , 1 0 0 , 4 0 , 3 4 ) ;
F i 1 1 El l ip s e ( 3 1 0 ,
100 ,
40 ,
F i l 1 E l l ip s e ( 4 3 0 ,
100 ,
40 ,
34 ) ;
34 ) ;
FillEllipse ( S S O ,
100 ,
40,
34 ) ;
{ вывод пяти мячико в }
ReadKey ;
{ пр о гр амма nри о с т анавлив а е т ся до н а ж а тия
поль з о в а т е л ем кла виши - д а ем в о зможно с т ь
поль з о в ат елю nо смотр еть н а и з о бр а ж ения мячико в ,
n о к а они н е исnорчены с nр айт ами }
Put image ( 4 0 ,
70,
Sprл , Normal Put ) ;
Put image ( 1 6 0 ,
70 ,
Spr л ,
XORPut ) ;
Put image ( 2 8 0 ,
70 ,
Sprл ,
ORPut ) ;
Put image ( 4 0 0 ,
70,
Sprл , ANDPut ) ;
Put image ( 5 2 0 ,
70,
Spr л ,
NOTPut ) ;
{ вывод nяти спр ай т о в н а мячики ,
каждый спрайт
выводится р а з ными методами }
Fre eMem ( Spr ,
SprS i z e ) ;
{ о с в о б ождение м е с т а ,
з анят о г о п о д сnр айт ,
и з о браж ение на экране не меня е т с я }
1 78
Глава 5 . Графи ка в Turbo Pascal . В ы вод и нформации в графическом режим е
ReadKey ;
{ про г рамма прио с тана влив а е т с я до н аж атия
пол ь з о в а т е л ем кла виши - д а ем в о з можн о с ть
поль з о в ат елю по смотр еть на р е зу ль тат выв ода
спрайто в на мячики }
C l o s eGraph ;
{ з а крыва ем графич е с кий р ежим }
End .
{ к онец р а з д ела опи с ания л о г ики пр о гр а ммы }
В завершение заметим, что оператор разыменовывания л используется толь
ко в процедурах копирования изображения спрайта с экрана в память и об
ратно процедурами Getimage и Putimage. При использовании процедур
Getмem и FreeMem оператор разыменовывания не указывается. Это вызва
но тем, что продедурам копирования изображения необходима информация
о самом изображении, а не о ссылочной переменной, которая указывает
на область памяти, где изображение находится. В то время как процедуры
работы с Неар-памятью Ge tмem и FreeMem должны получать доступ к не
ременной-указателю с целью его модификации ( продедура Ge tмem заносит
в персменную-указатель ссылку на полученную от операционной системы
область памяти) и чтения адреса памяти (процедура FreeМem читает значе
ние ссылочной переменной для получения адреса выделенной области памя
ти и передачи его операционной системе в запросе на освобождение памяти).
5 . 1 2 . 2 . СП РАЙ ТЫ С ПРОЗРАЧНЫМ ФОНОМ
ОБЩИЕ ПОЛОЖЕНИЯ И ОПРЕДЕЛЕНИЯ
Спрайты являются очень полезным инструментом при создании программ с
графическим интерфейсом. У нас еще будет возможность убедиться в этом
при изучении методов движения объектов по экрану, где без спрайтов прак
тически не обойтись. Однако спрайты имеют некоторые недостатки. Самый
большой из них заключается в том, что спрайт - это всегда прямоугольное
изображение вне зависимости от того, что на нем изображено на самом деле.
В предыдущем примере мы видели (см. рис. 82),
как мячики частично затираются не только по
лезной частью спрайта, то есть ракеткой, но и фо
новой частью тоже. Это не ошибка графической
библиотеки, просто система не знает, что считать
у спрайта фоном, не подлежащим выводу. Для ре
шения проблемы нет стандартных средств, однако
можно репrить ее самостоятельно; используя пара
метр Метод выв ода процедуры Putimage.
Рассмотрим, как можно самостоятельно реализо
вать спрайт с �прозрачным� фоном. Для начала введем несколько определений.
Рнс. 82. Затирание
фонового изображения
охватывающим
прямоугольником спрайта
1 79
Turbo Pascal 7 . 0
Спрайт с прозрачным фоном - спрайт, имеющий область, называемую фо
ном, которая не отображается на экране при выводе спрайта (см. рис. 83).
Как именно задается такая фоновая область, мы разберемся ниже.
•"Сnрайт с nроэрачным Фоном"
"Картинка"
Картинка - изображение будуще
го спрайта, построенное по следующим правилам:
• те области спрайта, которые яв
ляются фоном, то есть не предна
значены для вывода па экран вмес
те с остальными частями спрайта,
должны иметь черный цвет;
"Маска"
•
.,Экран дО вывода спрайта
те области, которые являются не
посредственно изображением, име
ют цвета, которые они должны иметь
в результате вывода спрайта с про
зрачным фоном на экран.
Маска
изображение будущего
спрайта, построенное по следую
щим правилам:
-
• те области, которые являются
фоном, имеют белый цвет;
8Экран после вывода сnрайта
Рис. 83. Создание спрайта
с прозрачным ф оном
те области, которые являются не
посредственно изображением, име
ют черный цвет вне аависимости от
того, какой цвет они должны иметь
на самом деле.
•
Фоновое изображение прямоугольная область экрана, на которую будет
выводиться спрайт (не путать с фоном спрайта) .
-
Подготовленное место фоновое изображение, модифицированное по сле
дующим правилам (обведено пунктирной рамкой на рис. 83):
-
•
те области, на которые должен будет выводиться фон спрайта, долж
ны остаться такими же, как и до вывода спрайта;
•
те области, на которые будет выводиться непосредствепное изобра
жение спрайта, должны быть черными.
СОЗ ДАНИ Е И ИСПОЛЬЗОВАНИ Е СПРАЙТОВ С ПРОЗРАЧНЫМ ФОНОМ
Процесс создания и использования спрайта с прозрачным фоном состоит
из следующих этапов:
1 80
Глава 5 . Графи ка в Tu rbo Pascal. В ы вод и нформации в графическом режи ме
1 . Создание спрайта-картинки . Происходит, как создание обычного
спрайта, то есть включает в себя:
•
вывод изображения для картинки на экран;
•
определение объема памяти, необходимого для хранения
спрайта-картинки;
•
создание спрайта в памяти;
•
удаление спрайта из памяти в случае отсутствия необходимое�
ти его дальнейшего использования.
2. Создание спрайта-маски. Происходит аналогично, то есть включа
ет в себя:
•
вывод изображения для маски на экран;
•
определение объема памяти, необходимого для хранения
спрайта -маски;
•
создание спрайта в памяти;
•
удаление спрайта из памяти в случае отсутствия необходимос
ти его дальнейшего использования.
3. Создание на экране подготовленного места.
К моменту выполнения этого пункта на экране уже имеется какое�
либо изображение (фоновое изображение); на которое должен
быть выведен спрайт с прозрачным фоном, то есть только та часть
спрайта, которая содержит полезное изображение. Создание под
готовленного места на экране происходит путем вывода спрайта
маски на фоновое изображение с использованием параметра Ме'l'од
вывода процедуры Putimaqe, равного AND Put.
Поясним , почему в результате вывода маски на фоновое изобра
жение по методу AND получается подготовленное место. Маска
состоит из двух цветов - черного и белого, поэтому рассмотрим
по отдельности, как изменяют фоновое изображение черная и бе�
лая часть маски.
Допустим, на экран с какой�либо информацией выводится белая
часть маски, то есть фоновая область спрайта с прозрачным фоном:
Цветная rочка экрана:
Белая точка маски:
Результат:
1 1 00
1111
1 1 00
AND
Точка экрана до вывода маски.
Таким образом, при выводе белой части маски, соответствующей
фону спрайта с прозрачным фоном, на экран по методу AND изобра
жение, которое было на экране до этого, остается прежним. То есть
такой вывод удовлетворяет определению подготовленного места.
1 81
Turbo Pascal 7 . 0
Теперь рассмотрим, как изменяется фоновое изображение при
выводе на него черной части маски, соответствующей полезному
изображению спрайта с прозрачным фоном:
Цветпая точка экрана:
Черная точка маски:
Результат:
1 1 00
0000
0000
AND
Черная точка.
Таким образом, при выводе черной части маски на экран по методу
ANDPut изображение, которое было на экране до этого, закрашива
ется черным цветом. То есть вывод черной части маски удовлетво
ряет определению подготовленного места.
Обобщим: при выводе маски на фоновое изображение по методу
AND па экран выводится только черная часть маски, соответствую
щая полезному изображению спрайта, а белая часть, соответствую
щая фоновой области спрайта, не производит с фоновым изобра
жением никаких изменений. В результате фоновое изображение
становится подготовленным местом.
4. Вывод на экран полезной части изображения.
Завершающим этапом вывода спрайта с прозрачным фоном на фо
новое изображение является вывод спрайта-картинки на подго
товленное место по методу OR, то есть с использованием константы
ORPut в процедуре Putimaqe.
Поясним, почему в результате вывода картинки на подготовлен
ное место по методу OR получается искомое изображение спрайта
с прозрачным фоном. Изображение картинки состоит из двух об
ластей - черной, соответствующей фону спрайта, и цветной, содер
жащей полезное изображение спрайта. Рассмотрим по отдельности,
что происходит при выводе этих областей.
Допустим, на подготовле1mое место выводится черная область кар
тинки. Эта черная часть картинки, соответствующая фону спрайта,
попадает на то место экрана, которое нельзя затирать. При этом та
часть подготовленного места, на которую выводится черная об
ласть картинки, может содержать любые цвета:
Цветная точка экрана:
Черная точка картинки :
Результат:
1 1 00
OR
0000
1 1 00 Точка экрана до вывода картинки, что аналогично точке экрана
до вывода маски.
Таким образом, при выводе черной части картинки на подготовлен
ное место по методу OR изображение, которое было на экране до
этого, остается прежним. То есть такой вывод не затирает ту часть
1 82
Глава 5 . Графика в Turbo Pascal. Вывод и нформации в графи ческом режи м е
экрана, на которую попадает фоновая область спрайта. Теперь рас
смотрим вывод на подготовленное место цветпой части картинки.
Цветная часть картинки, соответствующая изображению спрайта
с прозрачным фоном, попадает на черную часть подготовленного
места, что обусловлено предварительным выводом Iia него маски
(см. предыдутций пункт).
Черная точка экрана:
Цветная точка картинки:
Результат:
0000
OR
1 1 00
1 1 00 Цветная точка картинки.
Таким образом, при выводе цветной час
ти картинки, соответствующей полезному
изображению спрайта, по методу OR, на
экран выводится эта цветная часть без изменений.
В завершение приведем пример создания спрайта
с прозрачным фоном. Изображением спрайта бу
дет белое кольцо, внутренняя область которого за
полнена краепой сплошной залиш,ой (см. рис. 84).
Для создания рисунка, состоящего из двух таких
колец, создадим спрайт с прозрачным фоном и вы
ведем его на экран два раза. Текст программы при
веден в листинге 055.
,
Q
с
Сnрайт
nроэрач н ым фоном
--·�
м",
ас:::;
ка
"_
·__
-
"К а ртинка ··
Рнс. 8 4. Изображение
кольца и в спомогательных
спрайтов
ЛИСТИНГ 0 5 5 . СОЗДАНИЕ И ИСПОЛЬЗОВАНИЕ СПРАЙТА С ПРОЗРАЧНЫМ ФОНОМ
Program Transparent Spri t e ;
{ з аголовок про граммы ,
имя пр о гр аммы -
Transparent Spr i t e }
Us e s
Graph ,
{ начало р а здела подключ ения модул ей }
CRT ;
{ подключение модулей Graph и CRT }
Var
{ начало р а здела опис ания перем енных }
GraphDriver ,
GraphМode :
Int eger ;
{ опис ание двух целочисл енных пер еменных }
SprS i z e : Word ; { оnис ание n ер еменной для хр анения р а змера
спрайта ,
р а змеры к артинки и м а с ки с о впадают ,
так как их охв атыв ающи е nрямоу гольники имеют
одинако вые р а змеры }
P i c ture , Ma s k :
Point e r ;
{ опис ание с сылочных nеременных для выдел ения
nод них Н е ар - памяти ,
н е о бходимой для хр ан ения
спрайтов с картинкой и маской }
Begin
GraphDriver
{ начало р а з дела опис ания л о гики nрогр аммы }
: =
Det e c t ;
{ прис в о ение nеременной GraphDr i v e r з н ач ения 0 }
1 83
Turbo Pascal 7 . 0
GraphМode
: =
О;
{ при с в о ение переменной Gr aphMode знач ения О }
GraphМode , ' ' ) ;
{ инициализ ация графич е с к о г о р е жима }
S e t Line S tyl e ( S o l i dLn , О , Thi ckWidth ) ;
{ у становка толС'l'ОЙ сплошной 'I' екущей о б в одки }
SetColor (Whit e ) ; { у становка для о б в одки белого ц в е т а }
S e t F i l l S tyl e ( S o l i dF i l l , Red ) ;
{ у с т ановка сплошной кр асной т екущей з аливки }
F i l 1 E l l ip s e ( 1 0 0 , 1 0 0 , 9 0 , 9 0 ) ;
{ вывод внешнего круга кольца , кру г име е т толстую
б е лую о б в одку и кр а с ную спл ошную з аливку }
S e t F i l l Styl e ( S o l idFi l l , B l a ck ) ;
{ у с тановка сплошной ч ерной текущей з аливки }
Fil1Ellipse ( 1 0 0 , 1 0 0 , 7 0 , 7 0 ) ;
{ вывод внутренн е г о круга кольца , круг име ет
толстую б е лую о б в одку и ч ерную сплошную з аливку }
SprS i z e : = Image S i z e ( 9 , 9 , 1 9 1 , 1 9 1 ) ;
{ опр еделение р а змер а п амяти , н е о бходимой
для хр анения картинки или ма с ки }
GetMem ( P i cture , SprS i z e ) ;
{ выделение памяти для хр ан ения картинки }
Get image ( 9 , 9 , 1 9 1 , 1 9 1 , P i cture A ) ;
{ к опир о в ание спрайта - хартинки в п амят ь }
{ пр о грамма при о с т анавлив ается до наж атия
ReadKey ;
поль з о в ателем кла виши - д а ем в о зможн о с т ь
п ол ь з о в а т елю по смотр еть на и з о браж ени е картинки }
S et F i l l Styl e ( S o l i dF i l l , Whi t e ) ;
{ у становка сплошной б е лой т е кущей з аливки }
Bar ( 9 , 9 , 1 9 1 , 1 9 1 ) ;
{ вывод б ел о г о прямоугольник а , з а тирающ е г о
пр едыдущее и з о браж ение ( картинки ) и я вляющ е г о с я
фоном для маски }
SetColor ( Black ) ; { у становка ч ерного цвета в кач е с т в е т е кущег о }
S e t F i l l S tyl e ( So l idF i l l , B l a ck ) ;
{ у с т ановка ч ерной сплошной текущей з аливки }
F i l 1 E l l ip s e ( 1 0 0 , 1 0 0 , 9 0 , 9 0 ) ;
{ вывод внешнего круга кольца ч ерным ц в е т ом
( и о б в одка , и з аливка ) }
S et F i l l Styl e ( S o l i dF i l l , Whi t e ) ;
{ у с т ановка сплошной б елой т екущей з аливки }
F i l 1 E l l ip s e ( 1 0 0 , 1 0 0 , 7 0 , 7 0 ) ;
{ вывод внутренн е г о кру г а кольца б елым ц в етом
с ч ерной о б в одкой }
GetMem ( Ma s k , SprSi z e ) ;
{ выделение памяти для хр анения м а с ки ,
р а змер уже подсчитан ране е }
Get image ( 9 , 9 , 1 9 1 , 1 9 1 , мa skA ) ;
{ с о з дание в памяти спрайта -ма с ки }
ReadKey ;
{ пр о грамма при о с танавлив а е т с я до н а ж атия
пол ь з о в а т ел ем кла виши - д а ем в о зможно с т ь
Ini tGraph ( GraphDriver ,
·
поль з о вателю по смотр еть на и з о браж ение маски }
1 84
Глава 5 . Графика в Turbo Pascal . В ы вод и н формации в граф и ческом режи м е
C l e arDevi c e ;
{ с тир а ем с экрана и з о бра ж ение ма ски оно у ж е хр анится в памяти }
Set F i l l Styl e ( S o l idFi l l , Blue ) ;
{ у с т а н о в к а синей сплошной т екущей з а ли в ки }
Bar ( O , О , 6 3 9 , 4 7 9 ) ;
{ вы в о д прямоу г о льника во в е с ь экран }
S etRGBPa l e t t e ( B lue , О , О , 1 0 ) ;
{ и зменим ц в е т прямоуг ольника на б о л е е т емный }
Put image ( 5 0 , 5 0 , Ma s k л , ANDPut ) ;
{ вы в о д масхи для п ер в о г о кольца }
Putimage ( 5 0 , 5 0 , P i cture л , ORPut ) ;
{ вы в о д картинки для п ер в о г о к о л ьца }
Putimage ( 2 5 0 , 5 0 , Ma sk л , ANDPut ) ;
{ вы в о д масхи для в т ор о г о к ольца }
Putimage ( 2 5 0 , 5 0 , P i c ture л , ORPut ) ;
{ вывод картинки для в т ор о г о к о л ьца }
FreeMem ( P i cture , SprS i z e ) ;
{ о с в о б ождение памяти , з анятой картинкой }
Fre eMem ( Ma s k , SprS i z e ) ;
{ о с в о бождени е п амяти , з анЯ"l'ОЙ мас кой }
{ пр о грамма прио станавлив а е т с я до н аж атия
ReadKey ;
п о ль з о в а т ел ем клавиши - даем в о зможн о с т ь
поль з о в а телю п о см отр еть к о н е ч н о е и з о б р а ж е ни е
( дв а кольца р ядом , ч ер е з внутр енни е ч а с ти
колец виден ф он ) }
{ з акрыв а ем графич е с кий р е ж им }
C l o s eGraph ;
End .
{ к он ец р а з д е л а опис ания л о гики про гр аммы }
5 . 1 3 . УСТАН О В КА Н ЕСТАНДАРТН ЫХ ГРАФИ Ч ЕС КИХ Р ЕЖ И М О В
Используемый нами графический режим 640х480х 1 6 не обеспечивает не
обходимых возможностей для создания качественного пользовательского
интерфейса. О сновным ограничением является, конечно же, недостаточное
количество возможных цветов. Такие узкие возможности Turbo Pascal в об
ласти графики связаны с тем, что во времена его разработки и широкого
использования наиболее используемыми мониторами являлись монито
ры стандарта EGA (Enhanccd Graphic Array
Расширенный графический
массив), которые не могли поддерживать цветность графических режимов
более 1 6. Таким образом, не было необходимости разрабатывать драйвера
для более многоцветных графических режимов. Поскольку в данный мо
мент Turbo Pascal фактически не поддерживается фирмой-разработчиком
Borland International, его инсталляционные версии не обновляются, а сле
довательно, и не содержат никаких новых возможностей.
-
Однако Turbo Pas cal до сих пор используется для разработки программнаго
обеспечения, а также очень широко в целях обучения программированию.
Поэтому язык уже давно обладает специальными библиотеками, значи
тельно расширяющими его базовые функции, доступные после установки
1 85
Turbo Pascal 7 . 0
стандартного инсталляционноrо набора. Одним из видов таких расшире
ний являются графические ВGI-драйвера, поддерживающие современные
стандартные режимы вплоть до Hi Color и True color.
Одним из многочисленных драйверов является BGI 2 5 6 (разработчиком
драйвера BG I 2 5 б является фирма Kпight Software) позволяющий исполь
зовать все вышеописанные процедуры и функции в режимах с цветностью
2 5 6, которой вполне достаточно для реализации графических приложений
практически любой сложности. При этом драйвер позволяет устанавливать
разрешение экрана вплоть до 1 280х 1 024.
,
Рассмотрим, как установить данный или любой другой В GI -драйвер для
получения доступа к нему из процедуры Ini. tGraph. Файл с драйвером
(в данном случае файл имеет имя bgi 2 5 6 . b g i ) должен находиться в теку
щем каталоге проrраммы. Что бы система назначила новому драйверу номер
в таблице драйверов, необходимо вызвать функцию Ins tallUserDri.ver,
имеющую следующий вид:
Ins t a l lUs e rDriver ( < Имя файла > ,
<Функция инициализ ации > ) ;
Параметр И1о1 ф айла должен являться строкавой конетаптой или пере
менной, содержащей имя файла с драйвером на диске без расширения. Для
рассматриваемого нами драйвера таким именем будет bqi. 2 5 б .
Параметр +уихция: инициализ ации содержит ссылку на фующию ини
циализации драйвера, которая может поставляться вместе с файлом драй
вера для определения оборудования. Данпая ситуация очень редка, и, в час
тности, драйвер BGI256 не имеет такой функции. В этом случае в качестве
значения параметра +унхция: инициализации указывается ключевое сло
во ni.l (англ. Nil - ничего, ноль), означающее, что ссылка, передаваемая
функции Ins tallUserDri.ver, является пустой.
П РИМЕЧАНИЕ.
В G I -драй вера м ожно найти в сети l nternet, воспользовавш ись какой -л ибо те кс
товой п оисковой системой (например, RamЫer. ru ) , задав ключевые слова поиска
Pascal и BGI . Также м ожно воспользоваться систем ой для поиска файл о в ( напри
мер, FileSearc h . r u ) , задав в качестве шаблона поиска файл ов * . bgi или bgi* . *.
Функция Ins tallUserDri.ver возвращает целочисленное значение, оп
ределяющее номер нового драйвера в таблице драйверов. Возвращенное
значение необходимо сохранить в какой-либо переменной, чтобы потом пе
редать процедуре Ini. tGraph в качестве пара,\оlетра Номер драйв ера.
Листинг 056. ДоБАВЛЕНИЕ дРАйВЕРА в ТАБЛИцУ дРАйВЕРов
Program AddDrive r ;
{ з а г о л о в о к про гр аммы ,
Us e s
Graph ,
1 86
имя пр ограммы
{ н ачало р а з д ел а подключ ения моду л е й }
CRT ;
{ п одключ ение модул ей Graph и CRT }
-
AddD r i v e r }
Глава 5 . Графика в Turbo Pascal. В ывод и нформации в графическом режи м е
Var
{ начало р а з д е л а опи с ания переменных }
GraphDriver :
I nt e g e r ;
{ опи с ание п ер еменной ,
пр едн а з нач енной
для хран ения номер а н о в о г о др а й в ер а
в � а блиц е драйв ер о в }
{ н ачало раздела опи с ания л о гики пр огр аммы }
GraphDriver : = In s t a l lUserDriver ( ' BG I 2 5 6 ' , ni l ) ;
Begin
{ до б а в л ение н о в о г о др айв ер а , хранящ е г о с я в файле
с именем bgi 2 5 6 . bg i , и при с в о ени е пер еменн ой
GraphD r i v e r е г о номер а в та блице др айверо в .
Функция инициали з ации н е и с п о л ь зу е т с я }
Wri t e Ln ( ' Hoмep драйв ера :
' ,
GraphDriver ) ;
{ вывод на экран строки
' Н омер др айвера '
и
з ат ем номера др ай в ер а , при с в о еино г о при
д о б а в л ении в т а блицу др ай в ер о в }
Re adКey ;
{ да ем поль з о в ателю в о зможн о с т ь п о смотр еть
на номер дра й в ера , пока пр о гр амма н е з ак ончила с ь }
End .
{ к онец р а з дела опи с ания ло гики пр о гр аммы }
Таким образом, использование нестандартных драйверов аналогично ис
пользованию нестандартных шрифтов и не представляет особого труда.
При установке драйвера, отличного от E g a V g a .b g i , параметр Номер р е
процедуры I n i t G r aph заслуживает особого рассмотрения. Для каж
дого драйвера существует собственный набор возможных значений данного
параметра. Этот набор, собственно, и определяет вид графического режима,
который будет установлен в результате работы процедуры I n i t G r aph, то
есть его разрешение и цветность. Список возможных з нач е ни й параметра
Номер р е жима и виды графических режимов, поддерживаемые драйвером
BGI 2 5 6 , которые соответствуют значениям параметра, представлены в табл. 4.
жима
Таблица 4. М1lогоцветиые режима драйвера B G/256
Номер режи ма
Разрешение и цветность
1
640х400х256
о
2
3
4
5
320х200х256
640х480х256
800х600х256
1 024х768х256
2048х1 024х256
Как видно из таблицы, все графические режимы имеют цветность 256, а раз
решение находится в диапазоне от 320х200 до 2048х 1 024. Такая цветность
(256) вполне приемлема для создания качественных программ. Какое имен
но раэреrпение стоит подбирать, определяется задачами программы. Напри
мер, для реализации текстового редактора вряд ли подойдет разрешение
320х200, так как для нормального представления символа на экране требует
ся как минимум восемь точек (в высоту), а лучше - четырнадцать. Соответс1 87
Turbo Pascal 7 . 0
твенно, при данном разрешении пользователь может увидеть на экр ане около
двадцати строк текста (при размере символа восемь точек и расстоянии меж
ду строка;v.rи - ишерлиньяжем - две точки). С учетом того, что на экране
будет располагаться дополнительная информация и элементы управления
редактором, пользоваться такой программой будет неудобно.
С другой стороны, если установить разрешение 2048х 1 024 точек, то не каж
дый пользователь сможет выполнить программу, так как данный графичес
кий режим поддерживается не всеми мониторами.
Есть еще один нюанс. Для того чтобы меньше напрягать зрение пользователя,
монитор должен поддерживать определенную частоту развертки (количество
обновлений изображения на экране в секунду). Рекомендуемая ч астота развер�
тки, безопасная для здоровья - 80 ... 1 00 Гц. При повышении разрешения гра
фического режима частота развертки уменьшается и изображение на экране
начинает мерцать, что негативно сказывается на адоровьс и работоспособности
пользователя. Еще раз заметим, что программист во время отладки программы
также является пользователем. Tai<: что не стоит гнаться за режимами с высо
кими разрешениями - все должно быть в меру и соответствовать функцио
налыюсти программы, эффективно решать задачу, поставлепную перед ней.
Наконец, заметим, что размеры монитора не могут измениться, но разные
графические режимы содержат разное количество точек по горизонтали и
вертикали. Более того, у разных графических режимов может быть разнос
отношение горизонтальной и вертикальной характеристик разрешения.
Допустим, программа выводит на экран прямоугольник размером 1 00х 1 00
точек. При разрешении 640х480 на 1 5-дюймовом мониторе размер данно
го квадрата будет составлять примерно 4.6х4.6 сантиметров. Если такой же
квадрат ( 1 00 х 1 00 точек) вывести при разрешении 320х200, то его реальный
размер будет составлять 9.2х 1 1 .2 5 сантиметров, то есть при изменении раз
решения могут измениться пропорции изображений. Это особенно критич
но, r<огда в качестве изображений используются окружности, так как они
превращаются в эллипсы. Таким образом, в начале разработки программы
необходимо тщательно продумать пользовательский интерфейс и, в част
ности, разрешение графического режима, которое будет использоваться.
Приведем пример программы (см. листинг 057), устанавливающей графи
ческий режим 640х480 х 2 5 6 и использующей драйвер BG I 2 5 6, хранящий
ся в файле b g i 2 5 6 . bgi в текущем каталоге программы. Для установки
именно такого разрешения программа будет использоватъ значение 2 в ка
честве значения параметра Номер режима процедуры Ini tGraph.
Л ИСТИНГ
057,
УСТАНОВКА МНОГОЦВЕТНОГО ГРАФИЧЕСКОГО РЕЖИМА
Program U s e 2 5 6Color s ;
{ з а г о л о в о к пр о граммы ,
Us e s
1 88
имя
пр о граммы - U s e 2 5 6 C o l o r s }
{ начало р а здела подключ ения модул е й }
Глава 5 . Графика в Turbo Pascal . В ы вод информ аци и в графическом режи м е
Graph ,
CRT ;
{ подключ ение модул ей Graph и C RT }
Var
{ начало р а здела опис ания п ер еменных }
GraphDrive r :
I nt eger ;
{ описание п ер еменной , пр едн а з на ч енной для хр анения
номера н о в о г о др айвера в т а блице др а й в ер о в }
GraphМode :
Int eger ;
{ опи с ание п ер еменной ,
пр едн а з нач енной для
пер едачи знач ения парам е тр а Н омер р ежима }
Begin
{ начало раздела опис ания ло гики пр огр аммы }
GraphDrive r : = In s t a 1 1Us e rDriver ( ' BG I 2 5 б ' ,
ni l ) ;
{ до б а в л ение н о в о г о др а й в ер а ,
хр анящ е г о с я
в ф а й л е с именем b g i 2 5 6 . bg i ,
и при с в о ение
п ер еменной Graph D r i v e r его номера
в та блице др айв ер о в }
GraphМode
:= 2;
{ прис в о ение пер еменной GraphМode значения 2 }
InitGraph ( GraphDrive r ,
GraphМode ,
' ' ) ;
{ иници ализ ация графич е ск о г о р е жима с номером 2
( опр еделяется знач ением п ер еменной G r aphМode )
с испол ь з о в ани ем др а й в ер а BG I 2 5 6
( опр еделя е т с я
з н а ч ени ем переменной GraphDr i v e r ,
п олуч енным
при добавлении нового драйвера в та блицу драйверо в ) }
S e t RGBP a l e t t e ( l O ,
50 ,
50 ,
0) ;
{ и зменение ц в е т овых характ ери с тик ц в е т а
номер 1 0 - т е п ерь он т емно - ж елтый }
S e t F i l l S t yl e ( S o l i dF i l l ,
10 ) ;
{ у становка сплошной т е кущей з аливки
т емно - ж елтого цвета
Bar ( l O ,
10 ,
630 ,
( с номером 1 0 ) }
470 ) ;
{ вы в од прямоу г ольника ,
з акр ашенн о г о
т е кущей з аливкой }
S e t Text Styl e ( Gothi c Font ,
Hori z Di r ,
5) ;
{ у становка текущ е г о шрифт а :
г о тич е с кий ,
гори з онт альный , у в еличенного р а змер а }
S e t TextJu s t i fy ( C ent erText ,
C ent e rText ) ;
{ у становка выра внив ания т е к с т а :
п о ц ентру
для г ориз онтали и в ертикали }
OutTextXY ( 3 2 0 ,
240 ,
' 6 4 0Х4 8 0 Х2 5 6 ! ! ! ' ) ;
{ вывод с троки т е к с т а по центру экран а }
Re adKey ;
{ ожидание нажатия на кла вишу }
End .
{ к онец р а з д ела опис ания ло гики пр о гр аммы }
5 . 1 4 . М Н О ГОСТРАН И Ч Н ОСТЬ ГРАФ И Ч ЕСКИХ Р ЕЖ И М О В
Некоторые графические режимы поддерживают многостраничнос ть
возможность одновременпой работы с несколькими графическими стра
ницами (виртуальными экранами, находящимися в опер ативной памяти) ,
-
1 89
Tu rbo Pascal 7 . 0
из которых реально видна только одна. При этом вывод графических объ
ектов может осуществляться как па видимую страницу, так и па иевиди
мую, а затем можно быстро сделать видимой ту страницу, которая до этого
не была видимой. Такая возможность была разработана для решения уже
рассмотренной нами проблемы мигания изображения при его смене. С ис
пользованием мноrостраничности можно выводить мигающее изображе
ние на невидимую страницу, а затем, сменив видимую страницу, наказы
вать построенное изображение пользователю. Итак, появляются еще две
текущие характеристики экрана в графическом режиме:
•
активная страница, на которую происходит вывод;
•
видимая страница, которая реально отображается на экране.
Для смены активной страницы используется процедура S e tActive Page .
В качестве параметра этой функции указывается номер страницы, на кото
рую должна выводиться графическая информация:
SetAct ivePage ( <H oмep с тр аницы> ) ;
Для смены видимой страницы используется процедура SetVi sual Page,
имеющая п арам е тр определяютци й номер страницы, которая должна быть
отображена на экран:
,
S e tVi sual Page ( <H oмep с тр аницы> ) ;
Страницы пронумерованы начиная с нуля, и для разных графических ре
жимов может использоваться разное их количество. В свя з и с развитием
компьютерной техники на некоторых новых графических картах данные
процедуры работают некорректно, поэтому их использование не рекомен
дуется. Причем это несмотря на то, что многостраничность является очень
полезной функцией и полностью спимает проблему пежелательпых визу
альных эффет<тов при выводе больших и сложных изображений.
Tur bo P a s c a l 7 . 0
В в од да н н ых .
Ч т е н и е и н ф о р м а ци и
с кл а в и а тур ы
Мы уже говорили о том, что программа предназначена для преобразова
ния некоторого входного потока информации в выходной по определен
ному алгоритму. Часть методов представления выходной информации
нами уже рассмотрена - это вывод текста и графической информации на
экран. Другая часть будет рассмотрена ниже - это сохранение информа
ции в файлах.
Настало время перейти к изучению возможно стей и приемов работы
с входной информацией, основными видами которой являются ввод
пользователем последовательностей символов при помощи клавиатуры
и мыши, а также получение программой информации из файлов, запи
санных н а соответствующих носителях.
Работа с файлами, в связи с повышенной сложностью данного вопроса,
обсуждается ниже в разделе, полностью посвященном файлам, работа с
мышью рассмотрена в разделе, посвященном основам работы с языком ас
семблера. В данном же разделе мы научимся получать информацию с кла
виатуры.
Итак, пользователь может передать какую-либо информацию в про грамму,
написанную на Turbo Pascal, всего двумя способами:
•
путем ввода последовательности символов,
•
путем ввода одиночных символов.
191
Turbo Pascal 7 . 0
Ввод послЕДовАтЕль ности символ ов
Этот процесс выглядит следующим образом: программа вызывает проде
дуру чтения данных с клавиатуры и приостанавливается до тех пор, пока
пользователь не нажмет на клавишу � Enter�. Все это время пользователь
может набирать на клавиатуре любые символьr. Сразу же после нажатия на
какую-либо клавишу символ, который ей соответствует, отображается на
экране в позиции каретки (такой метод ввода имеет название ввод с эхом).
Соответстnенно, использовать такой метод ввода информации с клавиату
ры можно только в текстовом режиме, так как в графическом режиме визу
альные эффекты работы процедуры ввода непредсказуемы.
При наборе строки допустимо использование клавиши �вackSpace�, стира
ющей символ, находящийся слева от каретки. После нажатия пользователем
клавиши �Enter� введенная им строка попадает в некоторую переменную,
описанную в программе, и программа может работать с ней в обычном по
рядке, то есть выводить на экран или использовать в различных выражениях.
ОБЫЧН Ы Й ВВОД С КЛАВИАТУРЫ
Продедура ввода информации с клавиатуры называется Read (англ. Read
читать) и имеет вид, напоминающий процедуру W r i t e :
Rеаd ( <Приемник информации > ) ;
В качестве параметра Приемних ин ф ормации может использоваться пе
ременная любого из числовых и символьных типов, например Integer,
Rea1, S tring или Char. В качестве данного параметра не могут исполь
зоваться персменные ссылочных типов, например Pointer, и логические
персменные типа Boo1ean. Это правило обусловлено тем, что пользователь
не может корректно вnести их значения в связи с отсутствием у таких пе
ременных визуального представления. Также в качестве данного пара..'-i ет
ра нельзя использовать константы, потому что значения констант не могут
быть и:iменены в процессе выполнения программы. Это не касается типи
зированных констант, которые являются по сути персменными с заранее
заданными значениями.
ОдНОВРЕМЕН Н Ы Й ВВОД Н ЕСКОЛЬКИХ ЗНАЧЕНИЙ
Если необходимо последовательно ввести значения нескольких перемепных,
процедуру Read разрешается вызывать с любым количеством параметров:
Rеаd ( <Пр и емник информации 1 > ,
. . . ,
<При емник инф ормации n > ) ;
В этом случае после ввода значения очередной переменной пользователь
сразу же переходит I< вводу значения следующей и так далее, пока не бу
дут заполнены значениями все персменные из заданного списка. При вводе
1 92
Глава 6. Ввод дан н ых. Чтен и е и нфор м ации с кл авиатуры
числовых данных таким методом разрешается ввести значения персменных
через пробел, пе подтверждая каждое значение нажатием -клавиши • Enter•,
а подтвердить ввод можно после его полного завершения. Перед вызовом
процедуры Read рекомендуется вывести на экран строку, информирующую
пользователя о том, какую именно информацию он должен ввести. Поэтому
использование процедуры Read с несколькими параметрами нежелатель
но, так как после ввода очередного значения пользователь может не знать,
что именно нужно вводить далее.
Рассмотрим пример работы с процедурой ввода Read. Напишем программу,
которая запрашивает у пользователя его имя, сохраняет введенную пользо
вателем последовательность символов в переменной и затем выдает пользо
вателю приветствие с использованием его имени (см. листинг 058).
Л ИСТИНГ 058, Ввод ДАННЫХ В ТЕКСТОВОМ РЕЖИМЕ
Program ReadName l ;
{ з аголовок программы , имя пр ограммы - R eadName l }
{ начало р а здела подключ ения модул ей }
Us_e s
{ подключ ение модуля CRT }
{ начало р а здела опис ания переменных }
CRT ;
Var
U s e rName :
S t ring ;
{ опис ани е строковой п ер еменной для хр ан ения
имени поль з о в ат еля }
{ начало р а здела опис ания л о гики про гр аммы }
Begin
ClrScr ;
{ очистка экрана }
Wri t е ( ' Вв едите
в аше ими :
' ) ;
{ с о о бщени е поль з о в ателю о н е о бходим о с ти в в е с ти
с в о е имя , пер еход на но вую с троку не пр ои з в о
дится , чтобы поль з о в атель начал в в одить с в о е имя
в той же строк е , где находит ся приглашение
ко в в оду }
Read ( U s e rName ) ; { получ ение с троки , вводимой поль з о в ат е л ем ,
и з ан е с ение ее в пер еменную U s e rName }
{ п ер евод кар етки на новую с троку }
Wri t eLn ;
Wr i t е ( ' Здрав с т вуйте ,
' ,
U s e rName ) ;
{ по с л едоват ельный вывод с тр оки ' З др а в с твуйт е ,
и имени поль з о вателя , хр анящегося в пер еменной
U s e rName }
ReadKey ;
{ о жидани е нажатия поль з о в ателем клавиши }
End .
{ конец р а здела опис ания логики пр о гр аммы }
Результат работы программы представлен н а рис. 85.
Рис. 85. Результат рабо ты пр о граммы ReadName 1
7 Зах. 702
1 93
Turbo Pascal 7 . 0
Ввод С П ЕРЕХОДОМ Н А НОВУЮ СТРОКУ
Процедура Read обладает одной особенностью - I<orдa вводятся несколь
ко текстовых строк подряд, все строки, кроме первой, не считываются. Это
связано с тем, что первый вызов Read оставляет после себя таr< называемый
маркер конца строки, из-за которого все остальные вызовы Read считают,
что пользователь нажимает клавишу -«Enter�, вводя пустую строку. Для из
бежания такой ситуации существует процедура Read.Ln, не оставляющая
маркера конца строки:
Rе аdLn ( <При емник информации 1 > ,
<Приемник инф ормации n> ) ;
Использование процедуры Read.Ln аналогично использованию Read Рас
смотрим пример программы, запрашивающей у пользователя имя и фами
лию, а затем приветствующую его с использованием введенной информа
ции (см. листинг 059).
Л ИСТИНГ 0 5 9 . Ввод ДАННЫХ В ТЕКСТОВОМ РЕЖИМЕ
Pro gram Re adName 2 ;
{ з а г о л о в о к nр о гр аммы ,
Uses
CRT ;
{ подключ ение модуля CRT }
Var
U s e rName :
имя пр ограммы - R e a dNarne 2 }
{ н ачало р а здела п о дключ ения моду л ей }
{ н ачало р а здела опис ания п ер еменных }
S t r i ng ;
{ описание строкавой пер еменной для хр а н е ния
имени п ол ь з о в а т еля }
U s erSurName :
String ;
{ опи с ание строка в о й пер еменной для хр ан ения
ф амилии п о ль з о в а т е л я }
Begin
{ н ачало р а з д е ла опис ания л о гики nр о гр аммы }
ClrScr;
{ очистка экрана }
' ) ;
Wri t е ( ' Введите ваше имя :
{ с о о бщени е пол ь з о в ателю о н е о бходимо с ти в в е с ти
с в о е имя ,
дится ,
п ереход на н о ву ю строку не nр ои з в о
ч т о б ы п о ль з о в ат ел ь начал в в одить с в о е имя
в той ж е с тр ок е , где находит с я nригл ашение ко вв оду }
Re adLn ( Us e rName ) ;
{ nо лучение строки ,
в в о димой п о л ь з о в а т е л ем ,
и з ан е с ение ее в п е р еменную U s e rNarne }
Wri t eLn ;
{ n ер е в о д к ар етки на н о вую с тр о ку }
Wri t е ( ' Вв едите вашу фамилию :
' ) ;
{ с о о бщение поль з о в а ·гелю о н е о бх о димо с т и в в е с ·ги
с в ою ф амилию ,
п ереход н а н о вую с троку н е
пр о и з в одит ся ,
ч т о б ы поль з о в ат ел ь начал в в одить
с в о е имя в той ж е строке ,
приглашение ко в в о ду }
1 94
где н а х о ди т с я
Глава 6 . В вод дан н ых. Ч т е н и е и нформ аци и с клав иатуры
ReadLn ( Us e r SurName ) ;
{ получ ение строки ,
в в одимой поль з о в а т е л ем ,
и з ан е с ение е е в пер еменную U s e r Su rName }
Wri t eLn ;
{ п еревод к ар е тки на н о вую строку }
Wr i t е ( ' З дра в с твуйт е ,
' , U s e rName ,
'
' ,
U s erSurName ) ;
{ по следо в ат ельный вывод с троки
имени пол ь з о в а т еля ,
U s erName ,
' З др а в с т вуйт е ,
'
хр анящ е г о с я в пер еменной
пр о б ела для р а з дел ения имени и
ф амилии и фамилии поль з о в а т еля ,
хр анящейся
в п ер еменной U s e rSurName }
ReadKey ;
{ ожидание нажатия поль з о в ат ел ем к л а в иши }
End .
{ к онец р а з дела опи с ания ло гики пр ограммы }
Результат работы программы представлен на рис. 86. Как было отмечено
выше, в качестве параметра Приемних ин ф ормации может быть использо
вана переменная любого типа данных, имеющего визуальное представление.
Таким образом, разрешается, например, вводить значения целочисленных
переменных, например типа Integer.
Рис. 86 . Результат работы программы ReadName2
Ввод оди но ч но го си м волА
Ввод одиночного символа производится уже знакомой нам функцией
Read.Кey модуля CRT:
ReadKey ;
Функция Read.Кey вызывается без параметров, ждет нажатия клавиши
пользователем и возвращает значение типа Char, соответствующее нажа
той клавише. При этом не происходит эхового вывода введенного симво
ла на экран, поэтому функция Read.Кey может использоваться при работе
в графическом режиме экрана. Рассмотрим пример работы с данной фун
кцией (см. листинг 060).
Листинг 060. Ввод символд в текстовом РЕЖиме
Program Readchar ;
{ з аг о л о в о к пр огр аммы ,
Uses
CRT ;
Var
имя пр ограммы - R e a dCha r }
{ н ачало р а здела подключ ения моду л е й }
{ подключ ение модуля CRT }
{ начало р а з д е л а опис ания п ер еменных }
1 95
Turbo Pascal 7 . О
Ch :
{ оnисание nер еменной для хр анения символа ,
Char ;
в в еденн о г о nоль з о в ат е л ем )
Begin
{ начало р а з д ела оnис ания л огики nр ограммы )
C l rScr ;
{ очистка экрана )
Wri t e Ln ( ' Haжии т e хлавишу ! ' ) ;
{ с о о бщение nоль з о в ателю о н е о бходимо с ти
нажать клавишу )
Ch
: =
ReadКey ;
{ ожидание нажатия nоль з о в а т ел ем к л а в иши
и з ан е с ение символа ,
клавише ,
с о от в е т с т вующ е г о нажатой
в п ер еменную Ch }
Wri t e ( ' ВЪХ иажапи клавишу
1
,
Ch ) ;
{ по с л е д о в ательный вывод с троки
клавишу
'
и симв ола ,
' Вы н а жали
с о от в е т с т вующе г о к л а више ,
нажатой поль з о в ателем )
ReadKey ;
{ ожидани е нажатия поль з о в ателем клавиши )
End .
{ конец р а з дела опис ания л о гики nрогр аммы )
И такая же программа, но работающая в графическом режиме, представле
на в листинге 06 1 .
ЛИСТИНГ 06 1 .
В вод СИМВОЛА
В ГРАФИЧЕСКОМ РЕЖИМЕ
Program Transparent Spri t e ;
{ з а г о л о в о к nр о rр аммы ,
имя nр о граммы -
Tran sparent Spr i t e )
{ начало р а з д е л а подключ ения модул ей )
uses
Graph ,
{ подключение модулей Graph и CRT )
CRT ;
{ н ачало р а здела опис ания пер еменных )
Var
GraphМode :
GraphDriver ,
Int eger ;
{ опис ание двух целочисл енных п ер еменных )
Ch :
{ описание п ер еменной для хр анения с им в о л а ,
Char ;
в в еденн о г о пол ь з о в ат е л е м )
{ начало р а здела опис ания ло гики nр огр аммы )
Begin
GraphDriver
: =
Det e c t ;
{ nрис в о ени е п ер еменной G r aphD r i v e r з н ач ения
GraphМode
: =
О ; { nрис в о ение п ер еменной GraphМo de з н а ч ения О )
InitGraph ( GraphDriver ,
GraphМode ,
' ' ) ;
{ инициализ ация гр а фич е с к о г о р ежима )
OUtTextXY ( 1 0 ,
10 ,
' Нажните хлавишу ! ' ) ;
{ с о о бщение поль з о в ателю о н е о бходимо с ти
нажать кла вишу )
Ch
: =
ReadKey ;
{ ожидание наж атия поль з о в ателем к л а в иши и
з ан е с ение
клавише ,
OutтextXY ( 1 0 ,
40,
симв ола ,
' Вы иажапи клавишу ' ) ;
{ выво д стр оки
OutTextXY ( 1 5 0 ,
40 ,
с о о т в е т ствующ е г о н а ж а т о й
в переменную C h )
' Вы нажали клавишу ' )
Ch ) ;
{ вы в о д симв ол а ,
с о от в е т с т вующ е г о н а ж а т о й
п о ль з о в ателем клавише )
1 96
0)
Глава 6 . Ввод данных. Чтение инфор м аци и с кл авиатуры
{ пр о rрамма прио станавли в а е т с я до нажатия
ReadKey ;
польз о в а т е л ем кла в иши - д а ем в о змож н о с т ь
пол ь з о в ателю по смотр еть н а р е зультат
р а б оты пр оrр аммы }
C l o s eGraph ;
{ з акрыв а ем графич е с кий режим}
End .
{ конец р а з дела опис ания ло г ики пр оrраммы }
Таким образом, вводить данные с клавиатуры очень просто. Н амного слож
нее их анализировать и выполнять какие-либо действия на основе опреде
ленных полученных значений. Однако в этом и состоит задача проrр аммиро �
вания - разработка и реализация алгоритма, работающего с информацией,
и именно этому посвящена следующая глава.
КоНТРОЛЬНЫЕ ВОПРОСЫ
И
ОТВЕТЫ
В КАКИХ РЕЖИМАХ МОЖЕТ ОСУЩЕСТВЛЯТЬСЯ ВЫВОД ИНФОРМАЦИИ?
В ы в од и н ф о рмации н а экран может осуществляться двумя м етода м и - в виде
сим волов в текстовом режи м е экрана и в в иде граф ических объектов в граф ичес·
ком режи м е работы . П р и этом в граф ич еском режи м е , так же как и в текстов ом,
существует возможность в ы вода текста.
НАЗОВИТЕ ОСНОВНЫЕ ПРОЦЕДУРЫ, ПРЕДНАЗНАЧЕННЫЕ ДЛЯ ВЫВОДА ИНФОРМАЦИИ В ТЕК
СТОВОМ РЕЖИМЕ.
Осн о в н ы м и п р о цедура м и , п р едназ н ач е н н ы м и для у п р а вл е н и я и н ф о р м а ц и е й
н а э к р а н е в тексто в о м режи м е , я вл я ются : W r i te
и W r i t e L n для в ы в ода с и м
в ол о в н а экран , тextc o l o r и тextвackground для у п р а вл е н и я цвета м и с и м
в о л о в и ф о н а , G o t oXY д л я п о з и цио н и ро в а н и я каретки - указателя , п о ка з ы ва ю
щего , и з какого м е ста будет в ы в одиться и н ф о р м а ция .
КАк В
TURBO PASCAL ОСУЩЕСТВЛЯЕТСЯ
ПЕРЕХОД В ГРАФИЧЕСКИЙ РЕЖИМ?
Для получ е н и я возможности в ывода граф ичес ких объектов н еобход и м о устано
вить ( и н и циализировать) граф ический режим экрана . Для этого п редназначена
процедура Ini tGraph, устанавли вающая графический режи м , загружая драйвер
граф ическо го режи ма, зада н н ы й через один из nараметров . Кром е стандартных
драй веров, можно использо вать дополн ител ь н ы е , устанавливая их п ро цедурой
I n s t a l lUserDrive r .
КАКИЕ О&ЪЕКТЫ МОЖНО ВЫВОДИТЬ В ГРАФИЧЕСКОМ РЕЖИМЕ? П ЕРЕЧИСЛИТЕ СООТВЕТС
ТВУЮЩИЕ П РОЦЕДУРЫ .
В графическо м режи м е доступ н ы для вывода следующие объекты: точки ( в ы во
дятся п р о цедурой PutPixe l ) , отрезки (Move T o , Lineтo, MoveRe l , LineRe l , Line ) ,
п р я м оугол ь н и ки (Rec tangle
(DrawPoly
и ваr ) , параллел е п и п еды (ваrЗD ) , м н о гоугол ьники
и F i l l Po ly) , окружности ( C i r cl e ) , дуги окружн остей (Arc ) , секторы
1 97
Turbo Pascal 7 . 0
круга ( P ie S l i c e ) , элл ипсы и их дуги ( E l l ip s e ) , секторы элл и п со в ( S e c t o r ) . Ха
рактер исти кам и в и зуальн о го п редставл е н ия граф ических объекто в я в л я ются
об водка , стил ь и тол щина которо й устанавли вается п роцедуро й s e tL i ne s tyl e ,
а цвет - п ро цедурой s e t C o l o r ; и зали вка, стиль и цвет кото ро й устанавл и вается
п роцедуро й S e t F i l l S tyl e . Кро м е стандартных стил ей обводки и зал и в к и , м ож
но исп ользо вать собствен н ы е , устанавл и вае м ы е соответстве н н о п р о цедурами
S e tL i ne S tyle и S e tFi l l P a t t e r n .
КАКИМ ОБРАЗОМ ОСУЩЕСТВЛЯЕТСЯ ВЫВОД ТЕКСТОВОЙ ИНФОРМАЦИИ В ГРАФИЧЕСКОМ
РЕЖИМЕ?
Turbo Pascal обладает развитым и возможностя м и вывода текстовой и н ф о рмации
на экран в граф ическом режим е . Текст выводится на экран из позици и текущего
указателя ( С Р ) процедурой Ou tText или из л юбой позиции п роцедуро й OutTextxY .
Существует возм ожн ость форматирования текста ( вырав н и ва н и я относител ьно
позиции в ывода ) , текущие парам етры которого устанавли ваются п р о цедурой
S e tтextJu s t i fy. Характеристикам и сим в олов , выводим ых в графическом режи
м е , я вля ются их цвет, устан авливаемый процедуро й s e t c o l o r , и начертан и е , оп
ределяемое текущи м шрифто м . Текущий ш рифт устанавли вается п роцедуро й
S e tтext S ty l e , при этом можно измен ить стандартные разм еры с и м волов с помо
щью п роцедуры S e tUs erChar S i z e . Кро м е стандартных, поставл я е м ых с Tu rbo
Pascal ш р и фтов, м ожно использовать дополнител ьные , устанавл ивая их с помо
щью процедуры I n s t a 1 1 U s e rFont.
КАКИМ ОБРАЗОМ В ТЕКСТОВОМ РЕЖИМЕ ПРОИЗВОДИТСЯ ЗАдАНИЕ ( ИЗМЕНЕНИЕ) ЦВЕТА
ВЫВОДИМОГО ТЕКСТА И ФОНА1 НА КОТОРОМ ОН ОТОБРАЖАЕТСЯ?
В т екстовом режим е для задания цвета выводи мого текста испол ьзуется проце
дура тex t c o l o r . Дпя изменения текущего цвета фона исп ользуется процедура
TextBackGr ound.
КАКИЕ ПРОЦЕДУРЫ ОТВЕЧАЮТ ЗА ОЧИСТКУ ЭКРАНА?
За о ч истку экрана в текстовом режиме отвечает про цедура
ском режим е - C l e arDevi c e .
ClrScr,
а в графиче
Что ПРЕДСТАВЛЯЮТ СОБОЙ СПРАЙТЫ И ЧЕМ ОБУСЛОВЛЕНО ИХ ИСПОЛЬЗОВАНИЕ?
Для ускорен ия вывода сложн ых объе ктов п редназначены специал ь н ы е структу
ры , хран и мые в памяти - спрайты . Работа со спрайтам и м н огоэтапна и состоит
в выводе и зображения будущего спрайта на экран стандартны м и п роцедурам и
рисования , определении размера операти вной памяти , необходи м о й для хране
ния спрайта ( фун кция Image s :L z e ) , выделении операти вной пам яти ( п р о цедура
Ge tмem ) , копи ровани и изоб ражения в память (процедура G e t i mage ) , использова
нии спрайта ( коп ирован ии из памяти на экран процедурой Put image ) и , наконец,
удален и и сп райта из памяти ( п роцедура FreeМem ) .
КАКИМ ОБРАЗОМ ПРОИЗВОДИТСЯ СОЗДАНИЕ СП РАЙТОВ С ПРОЗРАЧНЫМ ФОНОМ?
Для достижения некоторых эффектов вывод изображения спрайта н а экран может
осуществляться с использованием битовых операций AN D, O R , XOR , N OT над точками
1 98
Глава 6 . Ввод данных. Чтен и е и н формации с клав иатуры
сnрайта и фона, на которы й он вы водится . Одним из nриложе н и й б ито вых оnераци й
я вл я ется создани е и исnользован и е сnрайтов , и м е ющих н е которую ф оновую об
л асть , н е выводимую на экран ( так называе м ы й nрозрач н ый фон). Для создан ия тако
го сnрайта н ео бходи мо создать два всnомогател ьн ых изо б раж е н ия - ма с ку (АND
м аску) и карти н ку ( О R м а ску )
-
.
КАКИМ ОБРАЗОМ МОЖНО КОРРЕКТИРОВАТЬ ЦВЕТОВУЮ ПАЛИТРУ СРЕДСТВАМИ TURBO
PASCAL?
Цвета, исnользуе м ые n ри выводе инфор м ации на экран в графическом режи ме ,
n оддаются коррекци и nроцедурой Se tRGBPa l e t t e , nозволя ю щей задать одному
из в оз м ожн ых цветов новые цветовые составля ющие в соответстви и с м оделью
n редставлен ия цвета R G B .
С П ОМОЩЬЮ КАКИХ ПРОЦЕДУР ПРОГРАММА МОЖЕТ ПОЛУ'IАТЬ ИНФОРМАЦИЮ, ВВОДИМУЮ
ПОЛЬЗОВАТЕЛЕМ С КЛАВИАТУРЫ?
В текстово м режи м е доnусти м о исn ользован ие n роцедур Read и ReadLn , nозво
ля ющих ввести значение n ере м ен н ой любого ти nа данн ых, и м ею щего ви зуальное
представление, и функции Read.Кey, возвращающей значение ти nа Char, соот
ветствующее н ажатой nользователе м клавише . В графическом режи ме доступна
только фун кция Read.Кey.
Turbo Pascal 7 . 0
Ветвление и заци кл и ван и е
Вспомним ранее приведеиное определение программы: программа
это
непрерывный поток команд, выполняемых операционной системой от на
чала до конца. Также мы говорили, что путь, по которому выполняется про
грамма, определяется операторами зацикливания и ветвления, и некоторые
команды из состава програ.'\fмЫ могут вообще не использоваться, а некото
рые использоваться несколько раз.
-
7 . 1 . О П ЕРАТО Р Ы В ЕТВЛ ЕН И Я
Представим себе железнодорожное полотно и поезд, который п о нему дви
жется. Допустим, на каждой шпале полотна написана какая-нибудь ко
манда. Тогда совокупность команд на всем полотне будет являться про
граммой, а поезд, движущийся по нему, будет аналогичен операционной
Команда 1 системе, которая считывает команды в пекото
ом,.а,..,.
2 рой последовательности и затем выполняет их.
.."а'-=
. нд
к""
__.,
= \ -+
•
t
_
Команда З
__:.:
К::::
ом::а::..:.
::: нд
""а'-'
4
Команда 5
,_
= ..
Команда 6
Команда 7
Команда 8
Команда 9
Команда 1 0
Команда 1 1
1
Команда 1 2
Команда 1 3
КомаНда 1 4
Команда 1 5
Рис. 88. Программа аналогична
железнодорожному полотну
200
На рис. 88 показана программа, состоящая из
1 7 -ти команд, однако выполнены они будут не
все, так как команды с номерами от 6 до 1 1 и
от 1 2 до 1 7 находятся на разных ветках (нача
ло движения показано жирной стрелкой). По
какому из двух возможных путей будет вы
полняться программа, определяется положе
нием стрелки (показава флажком на рисунке).
Эта стрелка и является для программы опе
ратором ветвления. Таким образом, реально
Глава 7. Ветвл е н и е и заци кл и вание
выполняемая программа будет включать в себя либо команды с номерами
1 , 2, 3, 4, 5, 6, 7, 8, 9, 1 0 и 1 1 , либо команды с номерами 1 , 2, 3, 4, 5, 1 2 , 1 3 , 1 4 ,
1 5, 1 6 и 1 7. Вполне возможна более сложная структура программы. Реаль
ные программы используют сотни операторов ветвления для реализации
необходимой функциональности.
В Turbo Pascal предусмотрено два оператора ветвления, и оба они в своей осно
ве имеют пекоторое условие (логическое выражение), определяющее направ
ление выполнения программы. Такие операторы еще называют условными.
7 . 1 . 1 . УСЛОВНЫЙ ОПЕРАТОР IF
ПРОСТАЯ ФОРМА ОПЕРАТОРА I F
Условный оператор I f . . . Then (от англ. If. . . Тhen - Если ... То) позволяет
выполнить какую-либо команду (процедуру, функцию, или оператор) в
зависимости от истинности или ложности некоторого выражения, и имеет
следующий вид:
If <Ус л о в и е > Тhen <Команд а > ;
В качестве Ус.повии оператора :r f может использоваться логическое выра
жение любой сложности, в том числе содержащее персменные и константы,
а также логические операторы AND , OR и NOT, рассмотренные выше. В ка
честве Команды, выполняемой в случае истинности Ус.повии, может ис
пользоваться любая процедура или функция, а также какой-либо оператор,
в том числе и условный.
Рассмотрим проrрамму, которая, в зависимости от введенного пользовате
лем возраста, выдает па экран некоторую строку (см. листинг 0 62 ) . Если
возраст, введенный пользователем, ме
J = - CirScr;
нее 7-ми, то на экран будет выведена
Т = - wrRе('Введите Ваш возраст: ');
строка « Вы е ще с о в сем р е б е н о к » ,
== - ReadLn(UserAge);
== - wrneLn;
а, если более 60-ти - то строка « Вы ,
lf UserAge < 7 Then
наверное ,
n е н си о н е р » . Таким об
разом, программа будет содержать два
условных оператора I f - один, прове
ряющий, не меньше ли введенный
пользователем возраст семи, а вто
рой - не превышает ли он шестидеся
ти. В качестве команд, выполняющихся
в случае истинности условий, приме
- ReadKey;
нсны nроцедуры Wri te, выводящие
соответствующие строки на экран ( схе
Рис. 8 9 . Схема про граммы
ма программы приведсна на рис. 89).
WhoAre You 1
==
20 1
Turbo Pascal 7 . 0
Л ИСТИНГ 062.
РЕАКЦИЯ НА ВВОД ИНФОРМАЦИИ
Program WhoAreYou l ;
{ з а г о л о в ок пр о граммы , имя про гр аммы - WhoAreYou l }
Uses
{ н ачало ра здела подключ ения моду л е й }
CRT ;
{ подключ ение модуля CRT }
Var
{ начало р а з дела опис ания пер еменных }
U s e rAge : Byt e ; { опис ание целочисленной пер еменной для хр а н е ния
в о з р а с т а поль з о в а т еля }
Begin
{ начало раздела опи с ания л о гики пр о гр аммы }
C l rS c r ;
{ очистка экр ана }
Wri t е ( ' Вв едит е в аш в о зраст : ' ) ;
{ с о о бщение поль з о в а т елю о н е о бходим о с ти в в е с ти
с в о й в о зр а с т , переход на н о вую с тр о ку н е
пр о и з в одится , чтобы поль з о в а т е л ь начал в в о дить
с в о е имя в той ж е с тр ок е , где находится
при г л аmение к о в в о ду }
ReadLn ( Us erAge ) ; { получ ение числ о в о г о знач ения , в в одим о г о
п о л ь з о в а т е л ем , и з ан е с е н и е е г о в п ер еменную
U s e rAg e }
Wri t eLn ;
{ п ер еход на н о вую с тр оку }
I f U s e rAge < 7 Then
Wri t e ( ' ВЪI: еще с о в с ем р е б енок ' ) ;
{ ср а в н ение знач ения п ер еменной U s e rAge с
конс тантой 7 , и вывод с троки ' Вы еще с о в с ем
р е б енок ' , в случа е , если значение п ер еменн о й
U s e rAge мен е е 7 -ми }
If U s e rAge > 6 0 Then
Wri t e ( ' Вы , нав ерное , пенсионер ' ) ;
{ вывод с троки ' вы , н а в ерн о е , пенсионер ' , в случа е ,
ReadKey ;
е сли з н а.ч: ение п ер еменной U s e rAge б о л ь ш е 6 0 }
{ ожид ани е наж атия поль з о в ат е л ем клавиши }
End .
{ к онец р а з д е л а опи с ания л о гики пр о граммы }
Приведеиная программа имеет один существенный недостаток: если поль
зователь введет значение, не удо влетворяющ е е ни одному из условий, то на
экран ни чего пе буде т выведено . Н апр имер , значение переменной U s e rAge
будет 1 5 . Тогда строка «Вы еще с о в с е м р е б е н о к» пе будет выведена,
так как условие U s e rAge < 7 не является и ст и нным, а строк а «Вы , н а
в е р н о е , п е н си о н е р » н е будет выведена, так как н е является истинным
условие U s e rAg e > 6 0 .
Изменим программу так, чтобы в случае, если ведеиное число попадает в ин
тервал значений от 7 до 60, на экран выводилась строка « Вы в п ол н ом р а с
ц в е т е сил ! » . Для этого пон ад об ится сложное условие, состоящее и з двух
частей, соединенных логическим оператором AND. Первой частью условия
буд ет выражение U s e rAge >= 7 , а второй - выражение U s e rAge <= 6 0 :
( U s e rAg e >= 7 ) AND ( U s e rAg e <= 6 0 ) . В случ ае , если оба выражения ис
ТИIПIЫ, по правилам выполнения логического оператора AN D, сложное вы
ражение также будет истинно. Текст программы приведен в листинге 063.
202
Глава 7. В етвл е н и е и заци кл и вание
Листинг 063. РЕАКЦия НА ввод ИНФОРМАЦии.
ИСПОЛЬЗОВАНИЕ СЛОЖНЫХ УСЛОВИЙ
В ОПЕРАТОРЕ I F
Program WhoAreYou 2 ;
uses
CRT ;
Var
U s e rAge :
Begin
ClrS c r ;
{ з а г о л о в о к nр о гр аммы , имя nр о гр аммы - WhoAr eYou2 }
{ начало р а здела подключ ения модул е й }
{ nодключ ени е модуля CRT }
{ начало ра здела опи с ания nеременных }
Byt e ; { оnис ание целочисл енной nеременной для хр анения
в о зр а с т а nоль з о в а т еля }
{ начало ра здела оnис ания л о гики nр о граммы }
{ о чистка экрана }
Wri t е ( ' В в едите в аш в о зрас т :
' ) ;
{ с о о бщение nоль з о в ателю о н е о бходимо с ти
в в е с "I'И с в о й в о зр а с 'l' , nереход на н о вую с тр оку
не прои з в одится , чтобы nоль з о в ат е л ь начал
в в одить с в о е имя в той ж е с тро к е , г д е находит с я
при г л а ш ени е ко в в оду }
ReadLn ( Us erAge ) ; { п олуч ение числ о в о г о знач ения , в в одимо г о
поль з о в ат е л ем , и з ан е с ение е г о в п ер еменную
Us e rAg e }
Wri t eLn ;
{ п ер е в од с тр оки }
I f U s e rAge < 7 Then
Wr i t e { ' Вы еще с о в с ем р е б енок ' ) ;
{ ср а внение знач ения п ер еменной U s e rAge
с конс тантой 7 , и вывод с троки ' Вы еще
с о в с ем р е б енок ' , в с луч а е , е сли з н ач ени е
пер еменной U s erAg e м е н е е 7 -ми }
If U s e rAge
Wri t e ( ' Bы ,
>
6 0 Then
нав ерно е ,
пенсионер ' ) ;
{ вывод строки ' Вы , на в ерн о е , пенсионер ' ,
в с луча е , е сли знач ение переменной
U s e :r·Age б ольше 6 0 }
7 ) AND ( Us e rAge < = 6 0 ) Then
I f ( Us e rAge > =
Wri t e ( ' Bы в полном расцв е т е сил ! ' ) ;
ReadKey ;
End .
{ вывод с троки ' Вы в п олном р а сцв е·r е сил ! ' ,
в случ а е , е сли знач ени е п ер еменной U s e rAge
б о л ьше либо р а вно 7 и , nри э т ом , м еньше
либ о равно 6 0 }
{ ожидани е нажатия поль з о в а т е л ем кла виши }
{ кон ец раздела опис ания л о гики nро гр аммы }
Следует заметить, что на экране не может появиться несколько строк од
новремешю, потому что все три условия являются взаимоисключающими,
то есть, если одно из них истинно, то все остальные ложны.
РАСШИ РЕН НАЯ ФОРМА ОПЕРАТОРА I F
Рассмотрим е щ е одну программу (см. листинг 064), реагирующую на ввод
информации пользователем. Попросим ввести оценку, которую наиболее
203
Turbo Pascal 7 . 0
часто, по его мнению, пользователь получает в школе. Если введенное зна
чение равно 5, то выведем па экран строку «Вы о тлични к ! », для осталь
ных значений будем выводить строку « Вы не о тличник . . . ».
Л ИСТИНГ
064. РЕАКЦИЯ НА ВВОД ИНФОРМАЦИИ
Program WhoAreYou З ;
{ з а го л о в ок про граммы , имя пр огр аммы - WhoA:r·eYouЗ }
{ начало р а з д ела подключ ения модул ей }
Uses
{ подключение модуля CRT }
CRT ;
{ начало р а з д е л а опис ания пер еменных }
var
Mark :
{ описание целочисленной переменной для хр а н е ния
Byt e ;
в в еденн о г о поль з о в ат е л ем знач ения }
Begin
{ начало р а з д е л а опис ания л о гики пр о гр аммы }
ClrScr;
{ очистка экр ан а }
Wri t e ( ' Kaкy.ю оценку вм попучаете чаще в с е г о ? :
' ) ;
{ с о о бщение поль з о в ателю о н е о бходимо сти в в е сти
оценку ,
пер еход на новую с троку не прои з в одится ,
чтобы поль з о в атель начал в в одить с в ою оц енку в
той ж е с троке , где находится приг л аmение ко в в о ду }
( по лучение число в о г о знач ения ,
ReadLn ( Mark ) ;
в а т е л ем ,
{ п ер е в од стр оки }
Wri t eLn ;
=
I f Mark
в в одим о г о поль з о
и з ан е с ение е г о в пер еменную U s e rAg e }
5 Then Wri t e ( ' Вм отличник ! ' ) ;
{ вывод н а экран строки «Вы отличник» ,
в случ а е ,
е с ли в в еденн о е поль з о в а'l· ел ем з н ачение р авно 5 }
< >
I f Mark
5 Then Wri t e ( ' Bм не отличник . . . ' ) ;
{ вывод н а экран строки «Вы н е о тличник . . . » ,
в случ а е ,
если в в еденн о е поль з о в а т е л ем
знач ение не равно 5 }
ReadKey ;
{ ожидание наж атия поль з о в ателем клавиши }
End .
{ конец р а з д е л а опис ания л о гики пр о гр аммы }
t
= - clrScr;
=
- Write('Кaкиe Вы получаете оценки?: ' ) ;
= - Readln(Mark) ;
= - Write Ln;
lf Mark
=
lf Mark
5
Then
< > 5 Then
= - ReadKey;
Рис. 90. Схема программы
WhoAreYouЗ
204
Схема данной программы показана
на рис. 9 0 . Вне зависимости от значе
ния переменной M a r k, введенного
пользователем, программа выдаст на
экран какую-либо из двух возмож
ных строк.
Ситуация, когда в случае истинности
условия необходимо выдать один ре
зультат, а в случае ложности - другой,
встречается достаточно часто, поэтому
предусмотрена модификация услов
ного оператора I f, для использования
в таких целях:
Глава 7 . Ветвле н и е и з аци кл ивание
I f <Ус л о в и е > Then <Команда 1 > E l s e <Команда 2 > ;
Условный оператор I f в расширенном виде с использованием кщочевого
слова El s е ( англ. Else - иначе), выполняет Коиаиду 1 в случае истиннос
ти Условии, или Коиаиду 2 в случае ложности Условии.
Так, в предыдущей программе можно использовать не два взаимоисключа
ющих условия M a r k = S и Mar k<>S, а одно Ma r k= S , в зависимости от истин
ности или ложности которого выполняются разные действия:
If Mark
=
5 Then Wri t e ( ' ВЫ отпичних ! ' )
E l s e Wri t e ( ' Bы н е отличник . . .
' ) ;
{ вывод на экран с тр оки «Вы о тличник» в с луч а е ,
ReadKey ;
е с ли в в еденно е польз о в а т е л ем значение равно 5 ,
и с тр оки «Вы н е о тличник» в случ а е л о жно с ти
данного у с л о вия }
{ ожидание нажатия поль з о в ателем клавиши }
End .
{ к онец р а з д ел а оnис ания л о гики про гр аммы }
Несмотря на то, что действия, выполняе
мые программой, аналогичны действиям
предъщущей программы, она имеет не
много другую схему (см. рис. 9 1 ). Новая
<--хема является более простой, соответс
твенно программа, имеющая такую схе
му, - более читабельна и лучше приспо
соблева для внесения в нее изменений.
1
т
· ·
- crrScr;
" ·
- write('Kaкиe Вы получаете оценки?: ');
• '
- ReadLn(Mark) ;
..,...__
Writelл;
r
lf Mark = 5
- Else Write('Bы не отличник. . . ');
Then Write('Bы отличник! ');
Еще одно достоинство использоваРис. 9 1 . схема программы
ния расширенного варианта оператос использованием расширенного
в арианта оператора tf
ра I f - уменьшение общего количеств а команд в программе (в нашем случае, при переходе на новую схему,
из программы пропал условный оператор с условием Ma r k< > S ) .
Заметим, что перед ключевым словом E l s e недопустимо использование
точки с запятой, означающей окончание оператора, так как это ключсвое
слово, так же как и If и Then, входит в его состав. Точка с запятой указы
вается только после полного завершения оператора, то есть после Коианды
2 (в данном случае Коиаидой 2 является вызов процедуры с параметром
« ВЫ Н е
О ТЛ И Ч Н И К
•
•
•
»
).
Написание условного оператора If в одну или в две строки зависит от вкуса
программиста и длины самого оператора - в ТшЬо Pascal строки с командами
не должны превышать 1 27-ми символов, включая и используемые в командах
пробелы. В случае превышения максимальной длины строки выдается ошибка
Error 1 1 :
Line too lonq - Ошибка
11 :
Слишком дли н н а я
строка .
И в завершение обсуждения условного оператора I f рассмотрим возмож
ность использования другого условного оператора If в качестве Команды,
205
Turbo Pascal 7 . 0
выполняемой после ключевого слова Then. Усложним предыдущую про
гра.\fму так, чтобы она на основе той же самой введенной оценки выдавала
три возможных результата: « Вы о тличник ! » (если введено значение 5),
« Вы х о р оши с т ! » (если введено значение 4) или « Т а к учи т ь с я н е л ь
з я ! » (если введено какое-либо другое значение). Тогда процесс выбора от
вета должен быть таким:
1. Проверка введенного значения на равенство 5-ти. Если введеннос
значение равно 5-ти, то вывод на экран строки «Вы о тлични к ! »,
иначе - переходим к пункту 2 .
2 . Проверка введенного значения н а равенство 4-ем. Если введенное
значение равно 4-ем, то вывод на экран строки « Вы х ор о ши с т ! »,
иначе - переходим к пункту 3.
3. Вывод строки « Т а к
учи т ь с я нель з я ! » .
- clrScr;
- Write('Kaкиe В ы nолучаете оценки?: ');
- Rвa dlл(Ma rk);
r
- writeLn;
AW'k--
lf Mark
1--18�-
r
=
5
=4
Then Write('Bы отлич ник! ' );
Else lf Mark
Схема программы приведсна на
рис. 92. Рассмотрим подробно дви
жение по схеме сверху вниз. Снача
ла выполняются процедуры, орга
пользователем
кизующие ввод
значения:
• очистка экрана;
• вывод подсказки о том, что имен
но необходимо ввести;
Then Write('Bы хорошист l ' ) ;
•
ввод значения переменной Mark
и перевод каретки на новую строку.
- ReadKey;
Рис. 92. Схема программы
WhoAгe You5
Далее начинается часть программы,
реализующая ана..тшз введенного
значения.
Первая развилка - определение, является ли пользователь отличником (ус
ловный оператор I f, проверяющий истинность выражения Ma r k
5 ) Если
значение переменной Ma r k равно 5, то выполняется левая ветка программы,
выводящая на экран строку «Вы о тличник ! » . Далее выполняется процедура
ReadКey и программа заканчивается. Если же значение переменной Ma r k
не равно 5, то выполняется правая ветка, содержащая в себе еще одну развилку.
=
.
Вторая развилка - определение, является ли пользователь хорошистом
(условный оператор I f, проверяющий истинность выражения Ma r k
4 ).
Если значение переменной Ma r k равно 4, то выполняется левая ветка про
граммы, выводящая на экран строку « Вы х ороши с т ! �. Далее выполняется
процедура ReadКey и программа заканчивается. Если же значение пере
менной Mar k не равно 4, то выполняется правая ветка, выводящая на экран
строку « Т а к учи т ь с я н е л ь з я ! » . Далее, как и в предыдущих случаях,
выполняется процедура ReadКey и программа заканчивается.
=
206
Глава 7 . Ве твле н и е и заци кл и вание
Сама программа занимает значительно меньше места, чем ее описание
(см . листиш 0 6 5 ) .
ЛИСТИНГ
065.
ИСПОЛЬЗОВАНИЕ ВЛОЖЕННЫХ ОПЕРАТОРОВ
IF
Program WhoAreYou S ;
{ з а г о л о в о к про граммы , имя пр огр аммы - Wh oAr e Y ou 4 }
{ н ачало р а з дела п одключения моду л е й }
Uses
{ подключ ение модуля CRT }
CRT ;
{ н ачало р а з дела опис ания п ер еменных }
Var
Mark :
Byt e ;
{ опис ание целочисл енной переменной для хран ения
в в еденн о г о поль з о в ат е л ем знач ения }
Begin
{ начало р а з дела опис ания л о гики пр ограммы }
C l rS c r ;
{ о чистка экр ан а }
Wri t e ( ' Kaкиe вы получаете оценки? :
' ) ;
{ с о о бщени е поль з о в ат елю о н е о бходимо сти
в в е сти оценку }
ReadLn ( Mark ) ;
{ получение число в о г о з н ач ения ,
в а т ел ем ,
{ п ер е в од с тр оки }
Wri t e Ln ;
If Mark
в в одим о г о поль з о
и з ан е с ение е г о в пер еменну ю U s e rAg e }
5
Then Wri t e ( ' Bы отличник ! ' )
E l s e I f Mark
=
4
Then Wr i t e ( ' Bы хорошис т ! ' )
E l s e Wr i t e ( ' Tax учит ь с я нель з я ! ' ) ;
{ р е ализ ация проц е с с а выбора о т в е т а }
ReadKey ;
{ ожидание наж атия пол ь з о в а•r е л ем к л а в иши }
End .
{ к онец р а з д е л а опис ания л о г ики пр огр аммы }
7 . 1 2 . СОСТАВНОЙ ОПЕРАТОР
.
После ключевого слова Then в условном операторе I f выполняется только
одна команда, стоящая после него. Остальные же строки являются частью
программы и выполняются вне зависимости от условных операторов, стоя
щих перед ними, и вне зависимости от того, что пары соответствующих друг
другу строк выровнены в программе так, что находятся друг под другом.
Тем не менее бывает необходимо выполнить не одну, а несколько операций
в зависимости от истинности того или иного условия. Можно, конечно, на
писать по одному условному оператору с одинаковым условием для каждой
операции из набора, но это не самый удобный способ.
В Turbo Pasca] предусмотрена возможность указать компилятору, что не
которая группа команд должна восприниматься как одна команда. Эта воз
можность реализуется так называемым составным оператором, состоящим
из ключевых слов begin и end, охватывающих фрагмент исходного текста
программы, который необходимо считать одной командой:
207
Turbo Pascal 7 . 0
{ начало с о с т а в н о г о оператор а }
begin
<Команда 1 > ;
<Команда 2 > ;
<Команда N> ;
{ окончание с о с т а в н о г о оператор а }
end ;
В качестве Кома нд, используемых в составном операторе, могут использо
ваться любые команды, допустимые в Turbo Pascal, в том числе условные
операторы, а также сами составные операторы ( вложенные ) .
Пример использования составного оператора приведен в листинге 066.
ЛИСТИНГ 066. ИСПОЛЬЗОВАНИЕ СОСТАВНОГО ОПЕРАТОРА
Program Choos eYourМu s i c 2 ;
{ з а г о л о в ок пр ограммы , имя про гр аммы Cho o s eYourMu s i c 2 }
{ начало р а здела п одключ ения модул е й }
{ подключ ени е модуля CRT }
{ начало р а з дела опис ания п ер еменных }
Uses
CRT ;
Var
GroupName :
S t r ing ;
{ опис ание с тр о к с в ой п ер еменной для хр ан ения
в в еденног о поль з о в а т ел ем н а з в ания }
{ начало р а з д е л а опи с ания л о гики пр огр аммы }
Begin
{ очистка э кр ана }
ClrS c r ;
Wri te ( ' Вв едит е наз в ание группы : ' ) ;
{ с о о бщение поль з о в ателю о н е о бходим о с ти
в в е с ти на з в ание группы }
Re adLn ( GroupName ) ;
{ получ ение числ о в о г о з н ачения , в в одим о г о
поль з о в ателем , и з а н е с ени е его в п ер еменную
U s e rAg e }
{ п ер е в од с троки }
Wri t eLn ;
If
GroupName
=
' Апис а '
{ е сли поль з о в ателем в в едена с тр о к а
{ начало с о с тавного оператор а }
Then begin
' Ал ис а ' }
Wri t e Ln ( ' Kт o - т o бьется в поле ' ) ;
Wri t e Ln ( ' Kт o - т o в грязь лицом ' ) ;
{ оконч ание с о с т авного опер а т ор а }
end ;
I f GroupName
Then begin
=
' Ария '
{ е с ли поль з о в а т ел ем в в едена с тр о к а
{ начало с о с тавного оператор а }
' Ария ' }
Wri t e Ln ( ' He в с ек в олчатам ' ) ;
Wri t eLn ( ' Cтaть в олками ' ) ;
end ;
If
( GroupName
<>
{ окончание с о с тавног о оператор а }
' Аписа ' ) AND ( GroupName < > ' Ария ' )
Тhen Wri t e Ln ( ' Toлькo Алиса или Ария ! ' ) ;
{ е сли в в еденная стр о к а н е ' Али с а ' и н е ' Ария • ,
то выд а ем с о о бщение о н е о бходимо с т и в в одить
строки только ' Али с а ' или ' Ария ' }
208
Гл а в а 7. Ветв л е н и е и з аци клив а н и е
Wri t eLn ;
ReadKey ;
{ nер е в о д с троки }
{ ожидание наж атия nольз ов а т елем клавиши }
End .
{ конец р а здела оnис ания л огики nр ограмм }
И напоследок заметим, что если пользователь введет значение •ария• ма
ленькими буква.'\1и, то программа выдаст ему сообщение о том, что нужно
вводить « Т о л ь ко Ал и с а или Ария ! ». Это проявление формального
подхода программы к информации, так как с точки зрения внутреннего
представления данных, строки « ария» и «Ария» различаются набором
символов. Как более корректно сравнить две строки, имеющие одинаковые
значения с точки зрения пользователя, мы обсудим ниже, при рассмотре
нии операций со строками.
7 1 3 УслОВНЫЙ ОПЕРАТОР CASE
.
.
.
П Р ОСТАЯ ФОРМА ОПЕРАТОРА CASE
Допустим нам нужно написать программу выводящей на экран окруж
ность, ожидающую нажатия клавиши пользователем, и, в случае, если
нажата клавиша R, смещающей окружность вправо, а если нажата клави
ша L то влево. Можно было бы для этого воспользоваться двумя услов
ными операторами If:
-
•
один на проверку нажатия клавиши R с последующими действиями
по перемещению окружности вправо
•
другой - на проверку нажатия клавиши L с последующими действиями по перемещению окружности влево.
Однако для подобных ситуаций множественного выбора в Turbo Pascal пре
дусмотрен специальный оператор Case, позволяющий в своем заголовке
указать переменную, на основе различных значений которой должны про
изводиться какие-либо действия, а затем описать сами действия (команды),
привязав их к конкретным значениям:
C a s e <Анализиру емая nеременная> Of
{ з а г о л о в о к оnератора
множ е с т в енного в ы б ора }
< З начение 1 > :
<Команда 1 > ;
{ знач ение nеременной и команда ,
< З начение 2 > :
<Команда 2 > ;
{ з начение nеременной и к оманда ,
< З начение N> :
<Команда N> ;
{ з нач ение n ер еменно й и к оманд а ,
с о о т в етст вующая данному знач ению }
End ;
с о о т в е т с т вующая данному знач ению }
с о о т в ет с т вующая данному знач ению }
{ окончание оnератор а }
209
Tu rbo Pascal 7 . 0
В качестве
соответствующих конкретным значениям Анализи
могут использоваться любые процедуры, функции,
операторы (в том числе и условные операторы, и операторы множественно
го выбора), а также составные операторы.
Команд,
руемо й переменно й ,
П РИМЕЧАНИЕ.
Замети м , что с и м волы R и r отл и чаются друг о т друга , позтому н аж имать клав и шу
необходимо п ри в кл юч е н н о м режи м е CapsLock, л и б о с одн о в р ем ен н ы м нажа тием
и удержание м клав и ш и Shift.
В листинге 0 67 приведен код программы перемещения окружности впра
по нажатиям клавиш R и L. Направление персмещения окруж
ности производится с помощью оператора множественного выбора C a s e .
Смещение окружности происходит путем е е последовательного стирания
в предыдущем положении (выводом такой же окружности, по черного
цвета) и вывода в новом положении.
во- влево
ЛИСТИНГ 067. РЕАЛИЗАЦИЯ ПРОСТЕЙШЕГО ДВИЖЕНИЯ (ИСПОЛЬЗОВАНИЕ ОПЕРАТОРА CASE)
Program MoveC i rc l e З ;
{ з аголовок лр о гр аммы , имя пр огр аммы - Move C i r c l e З }
{ н ачало ра здела n одключ ения модулей }
CRT ;
{ подключ ение модулей G r aph и CRT }
Var
{ начало р а здела оnис ания леременных }
GraphDriver , GraphМode : Int ege r ;
{ оnи с ание двух целочи с л енных лер еменных }
Ch : Cha r ;
{ оnи с ание леременной для хран ения сим в ол а ,
в в еденн о г о nоль з о в ат е л ем }
Begin
{ н ачало р а з д ела оnис ания л о гики лр ограммы }
GraphDriver : = Det e c t ;
{ лрис в о ени е лер еменной GraphD r i v e r з н а ч ения 0 }
GraphМode : = О ; { при с в о ение леременной GraphМode знач ения 0 }
Ini tGraph ( GraphDrive r , GraphМode , ' ' ) ;
{ инициализ ация графич е с к о г о р ежима }
S e t LineStyl e ( S o l i dLn , О , Thi c kWidth ) ;
{ у становка сnлошной т о л с т о й о б в одки }
S e t C o l o r ( Red ) ;
{ у с тановка кр а с н о г о ц в е т а для в ы в одимых
линий и т е к с т а }
OutTextXY ( l O , 1 0 , ' Нажните R для смещения впра в о ' ) ;
{ с о о бщение nоль з о в ателю о н е о бходим о с ти н а ж а т ь
кл авишу R д л я смещения о кружн о с ти вnр а в о }
OutTextXY ( l O , 2 0 , ' Нажните L для смещения влев о ' ) ;
{ с о о бщение nоль з о в ателю о н е о бходимо сти н а ж а т ь
кла виn� L д л я смещения о кружн о с ти в л е в о }
C i rc l e ( 3 2 0 , 3 0 0 , 7 0 ) ;
{ в ывод лерв оначально г о полож ения окружно сти }
Ch : = Re adKey ;
{ ожидание нажа тия nоль з о в ат е л ем клавиши и
з ан е с ение симв ола , с о от в е т с т вующ е г о нажатой
Uses
Graph ,
клавиш е ,
210
в лерсменную Ch }
Глав а 7 . В е твлени е и заци кл и вание
c a s e Ch O f
'R' :
begin
{ е сли п ер еменная Ch име е т з начение R ,
начин а е т выполняться с о с т а вной о п е р а т ор }
S e t C o l or ( B l a ck ) ;
{ у с т ановка ч ерного ц в е т а для линий }
C i rc l e ( 3 2 0 ,
300 ,
70) ;
{ стир а ем окру ж но с ть пут ем е е п о в т орной
пр орис о вки цв е т ом ф о н а }
S e t C o l o r ( Red ) ;
{ у с ·rановка кр а с н о г о ц в е т а для линий }
Circle ( S б O ,
300 ,
70) ;
{ вы в о д окружно с ти на н о в ом м е с т е }
end ;
'L' :
begin
{ ок ончание с о с т а в н о г о о п ер а т ор а }
{ е сли п ер еменная Ch име е т з н ачение L ,
начин а е т выпо лнять с я с о с та в н о й о п е р а т ор }
S e t C o l or ( B l a ck ) ;
{ у с тановка ч ерного ц в е т а для линий }
C i rc l e ( 3 2 0 ,
300 ,
70) ;
{ с тир а ем окру ж но с ть пу тем е е п о в т орной
пр ор и с о вки ц в е т ом ф о н а }
S e t C o l o r ( Re d ) ;
{ у с тановка кр а с н о г о ц в е т а для линий }
C i rc l e ( S O ,
300 ,
70) ;
{ вы в о д окружно с ти на н о в ом м е с т е }
end ;
End ;
ReadKey ;
{ окончание с о с тавного оператор а }
{ окончание оператора множе с т в ен н о г о в ы б ор а }
{ пр о гр амма при о с т анавлив а е т с я до н а ж атия
поль з о в ателем клавиши - д а ем в о зможн о с т ь
поль з о в а т елю п о смотр е т ь н а р е зу л ь т а т
р а б о т ы прогр аммы }
C l o s eGraph ;
{ з акрыв а ем графич е с кий р е жим }
End .
{ к онец р а з дела опис ания ло гики пр огр аммы }
Такой вариант программы придаст ей большую гибкость при дальнейших
изменениях, например, при смене имени Ана.пиsируе:мой пере:менной ,
а также в некоторых случаях довольно сильно упрощает структуру про
граммы, что повышает ее читабельность.
Еще одним достоинством оператора Case по сравнению с набором идущих
друг за другом условных операторов I f, является повышение быстродейс
·rвия программы. Объясняется это тем, что оператор Case заканчивается сра
зу же после определения команды, которую необходимо выполнить, а опера
торы If будут выполняться друг за другом, даже если это уже и не нужно.
Например, если при выполнении нашей программы пользователь нажал
клавишу R, то проверка переменной Ch на равенство ее значения ' L ' уже
не имеет смысла, и оператор Case не будет выполнять такую проверку, тогда
как последовательность условных операторов If будет выполнена полно
стью, поскольку они являются самостоятельными субъектам и программы.
21 1
Turbo Pascal 7 . 0
А сейчас попробуем упростить программу, сократив в ней количество строк.
Заметим, что все составные операторы, перемещающие окружности, со
держат одни и те же процедуры, но используют в одной из них, рисующей
окружность в новом месте, разные параметры. Если описать переменную,
которая будет определять новое положение окружности, то в операторе
множественного выбора д о ст ат очно будет только изменять ее значение со
ответствующим образом, а осуществлять перемещение понадобится один
раз - после изменения данной переменной. Текст упрощенного варианта
программы приведен в листинге 068.
Л истинг 068. Редnиздция nРостейшего движения
Program Move C i rc l e 4 ;
{ з аголовок nро граммы , имя nр о граммы - MoveC i r c l e 4 }
Uses
{ начало раздела nодключ е ния модул е й }
Graph ,
CRT ;
{ nодключ ение модулей Gr aph и CRT }
Var
{ начало раздела оnи с ания n ер еменных }
GraphМode :
GraphDriver ,
Int eger ;
{ оnи с ание д вух ц елочи с л енных n ер ем енных }
Ch :
{ оnи с ание n ер еменной для хранения симв о л а ,
Char ;
в в еденного nоль з о в а т е л ем }
{ оnис ание целочисл енной n ер еменной }
Int e g e r ;
Х:
Begin
{ начало раздела оnис ания ло гики nро гр аммы }
GraphDriver
: =
Detect ;
{ nри с в о ение n ер еменной GraphD r i v e r з н ач ения О }
GraphМode
х
: =
О ; { nрис в о ение nеременной GraphМo de з н а ч ения 0 }
: =
320;
{ nри с в о ение n ер еменной Х начально г о з н ач ения
е сли nоль з о в атель нажмет не ту клавишу ,
значение не и зменит с я и н о в а я окруж н о с т ь
буд е т в ы в е д е н а в эту к о ординату }
Ini tGraph ( GraphDriver ,
GraphМode ,
' ' ) ;
{ инициализ ация графич е с к о г о р е жима }
S e t L ineStyl e ( S o l i dLn ,
О,
Thi c kWidth ) ;
{ у с т ановка сnлошной т о л с т ой о б в одки }
SetColor ( Red ) ;
{ у становка кр а сного ц в е т а для выв одимых
линий и текста }
OutтextXY ( 1 0 ,
10 ,
' Нажните R для смещения вправо ' ) ;
{ с о о бщение nоль з ов а т елю о н е о бходимо сти н а ж а т ь
клавишу R д л я смещения окружн о с ти в nр ав о }
OUt TextXY ( 1 0 ,
20,
' Нажните L для смещения влев о ' ) ;
{ с о о бщение nоль з о в ателю о н е о бходимо сти н а ж а т ь
кла в ишу L д л я смещения о кружно с ти вле в о }
C i rc l e ( 3 2 0 ,
300 ,
70) ;
{ вы в о д nервоначальн о r о nолож ения окружн о с ти }
Ch
: = ReadKey ;
{ ожидание наж атия nоль з о в ат е л ем клавиши и
з а н е с ение симв ол а ,
с о о т в е т с твующ е г о нажатой
клавише в n ер еменную C h }
212
Глава 7. Ветвление и заци кл и вание
C a s e Ch O f
'R' :
Х
560;
: =
{ е сли п ер еменная Ch име е т знач ение R ,
у в еличи в а ем значение Х }
'L' :
Х
80;
: =
если пер еменная Ch име ет з н а ч ение L ,
уменьшаем знач ение Х }
End ;
{ окончание оператора множ е с т в енно г о выбор а }
SetColor ( B lack ) ; { у с тановка ч ерного ц в е т а для линий }
C i rc l e ( 3 2 0 ,
300 ,
70) ;
{ ст ир а ем окружность пут ем е е п о вторной
прорис о вки ц в етом фона }
S e t C o l o r { Red ) ;
Circ l e ( X ,
300 ,
{ у становка кр а с н о г о ц в е т а для линий }
70) ;
{ вы в о д окружности на н о в ом м е с т е ,
опр еделяемой
пер еменной Х }
ReadKey ;
{ приостановка про гр аммы }
C l o s eGraph ;
{ з а кры в а ем графич е с кий р е ж им }
End .
{ к онец р а з дела опи с ания л о гики пр о г р аммы }
Аналогичным образом можно реализовать реакцию программы н а нажатие
других клавиш, например, u - для смещения окружности вверх, или D - для
смещения окружности вниз. В результате получится последовательность
условных операторов, каждый из которых выполняет некоторые действия,
соответствующие определенной нажатой клавише, на основе сравнения
значения одной и той же переменной с какой-либо константой.
РАСШИ РЕННАЯ ФОРМА ОПЕРАТОРА CASE
Оператор множественного выбора Case, так же как и условный I f, имеет
возможность выполнения определенной команды, в случае, если Аиапизи
руеиан переиеииан имеет значение, не встречающееся в заданном списке.
Для указания такой команды в операторе Case используется секция Else:
C a s e <Анализ иру емая переменная> O f
{ з аголовок оператора
мно ж е с т в енно г о выбор а }
< З н а ч е ние 1 > :
<Команда 1 > ;
{ з начение п ер еменной и к оманда ,
< З начение 2 > :
<Команда 2 > ;
{ з нач ение п ер еменной и команд а ,
с о о т в е т с твующая данному з н а ч ению }
с о о т в е т с т вующая данному з н а ч е нию }
.
.
.
.
.
..
.
.
.
.
.
< З начение N> :
<Команда N> ;
{ з начение п еременной и команд а ,
с о о т в е т с твующая данному знач ению }
E l s e < Команда N+ 1 >
{ к оманда «по умолчанию» }
End ;
{ окончани е опер а т ор а }
При использовании секции E l s e в операторе C a s e Коиаида N+ l вы
полняется в случае, если Аиапизируеиан: переиеииан: имеет значение,
не равное З иачеииR:И от 1 до N .
213
Turbo Pascal 7 . 0
Например в предыдущем примере можно модифицировать оператор C a s e
таким образом, чтобы при па:жатии пользователем клавиши, отличной о т L
или R, на экран выводилось сообщение « Т ол ь ко L и л и R ! ! ! » :
Ch
: =
Re adKey ;
{ ожидание нажатия поль з о в ат ел ем кл авиши и
з ан е с ение симв о л а ,
к л а више ,
с о о т в е т с т вующе r о нажатой
в пер еменную C h }
Case Ch Of
'R' :
Х
: =
5 6 0 ; { е сли пер еменн ая Ch име ет з н а ч ение R ,
'L' :
х
:=
80;
у в еличи в а ем знач ени е Х }
{ е сли переменн а я Ch име ет значение L ,
уменьша ем знач ение Х }
E l s e OutTextXY ( l O ,
30 ,
' Только R или L l ! ! ' )
{ е сли нажата клавиша ,
отличная о т L и R ,
т о выда ем с о о бщение о пр а вильных кла вишах }
End ;
{ окончание оператор а мно ж е с т в енноrо выбора }
SetColor ( Black ) ; { у ст а н о в к а ч ерноrо ц в е т а для линий }
Таким образом, мы ознакомились с оператором множественного выбора
и заодно с организацией простейшего движения объектов по экрану. Ос
новным недостатком нашей программы является то, что сдвиг объекта
может выполниться только один раз , причем только если пользователь
нажмет нужную клавишу. При нажатии клавиш, отличных от R и L, дви
жения не происходит.
Для того, чтобы объект мог персместиться на несколько шагов, необходимо
�эациклить� ту часть программы, которая занимается его перемещением,
то есть определением направления персмещения (условный оператор мно
жественного выбора) и непосредственной перерисовкой изображения (вы
зов четырех процедур после окончания оператора Case). Методы зацикли
вания мы разберем в следующем разделе.
7 . 2 . О П ЕРАТО Р Ы ЗАЦ И КЛ И ВАН И Я
Рнс . 93. За циклив а ние в программе
214
Для повторения пекоторой команды
заданное количество раз используют
ся так называемые операторы цикла.
Продолжая аналогию программы с
железнодорожными путями, зацикли
вание можно представить кольцом
(см. рис. 93), на которое поезд попада
ет и движется по нему (возможно, не
сколько раз), а потом, выйдя из коль
ца, продолжает движение дальше.
Глава 7. В ет влен и е и зац и кл и ван и е
Выполнение программы, представленной на рис. 93, может проходить:
•
по командам 1 , 2 , 3, 1 2 , 13, 1 4 (без зацикливания);
•
1 , 2 , 3, один или несколько раэ 4 1 1 (зацикливание), а затем однократно 1 2 , 1 3, 14.
...
Перед каждым заходом в кольцо (в том числе и в первый раэ) проверяется
некоторое условие, определяющее, нужно ли зайти в кольцо (и выполнить
команды 4 . 1 1 ) или нужно перейти I< следующему фрагменту программы
(команды 1 2 , 13, 1 4) . Место в программе, где происходит выбор направле
ния выполнения программы, показано флажком.
.
.
,
Существует несколько операторов цикла, которые отличаются друг от дру
га тем, как именно определяется направление выполнения программы. Со
ответственно, выделяется две группы операторов цикла:
•
Операторы цикла со счетчиком циклов испольэуются для зацикли
вания фрагмента программы в случае, когда еще до выполнения цик
ла (может быть, даже в процессе разработки программы) известно,
сколько раз должен повториться данный фрагмент. К таким задачам
можно отнести, например, вывод пекоторога количества одинаковых
изображений на экран. Данную группу циклов представляет опера
тор For, выполняющий некоторую команду (фрагмент програ..\1 мы)
заданное количество раз.
•
Операторы цикла с условием (условные операторы цикла) ис
пользуются для организации зацикливания в случае, когда заранее
неизвестно, сколько раз должен выполниться зацикливаемый фраг
мент для достижения поставленной цели. Например, каждый этап
игры-лабиринта должен заканчиваться не через заранее эаданное
количество выполнений некоторого фрагмента программы, а только
когда пользователь достигнет выхода из лабиринта. Данную группу
циклов представляют два оператора цикла - While . . Do и Repea t
Un til, определяющие необходимость повторения цикла н а основе
некоторого условного выражения. При этом значение условного вы
ражения должно изменяться в результате очередного выполнения
зацикленного фрагмента программы.
.
. . .
7. 2 . 1 О п ЕРАТОР циклА FoR
.
СтАНДАРТНАЯ ФОРМА ци кл А FoR
Оператор цикла со счетчиком циклов For . . To . . Do ( англ. For. . To . . Do От . . До . . Выполнить . . . ) выполняет некоторую Команду заданное количес
тво раз:
. . .
For < С ч е тчик цикл а >
: =
<Начальное значение>
То < К о н е ч н о е з н ачени е > Do < К оманд а > ;
215
Turbo Pascal 7 . 0
В качестве Счетчика цикпа используется переменпая любого целочис
лешюго типа ( I n t e g e r, B y t e , W o r d), а в качестве Начапьного з начении
и Конечного значении - любые допустимые для типа Счетчика цик
па значения.
В качестве Команды могут использоваться любые процедуры, функции
и операторы Turbo Pascal (в том числе условные, составные и операторы
цикла).
Рассмотрим механизм работы оператора For:
1 . Пр и св о е н и е переменной, заданной в качестве Счетчика
значения, заданного в качестве Начапьного значении.
ЦИJCJia
2. Проверка, не является ли значение Счетчика ЦИICJia большим,
чем значение, заданное в качестве Конечного значении. В слу
чае, если Счетчик циJCJia не превышает Конечного значении,
выполняется Команда и значение счетчика цикла увеличивается
на единицу. Если же Счетчик циJCJia превышает Конечное зна
чение, то выполнение оператора заканчивается.
3. Возврат к пункту 2 .
Заметим, что н а каждом проходе •кольца� программа имеет возможность
определить номер этого прохода, обращаясь к переменной, заданной в ка
честве Счетчика ЦИJCJia.
Количество проходов вычисляется по формуле:
Конечное значение - Начальное значение +
Строка
Строка
Стро ка
Строка
Строка
UseFor 1
Л ИСТИНГ 069.
Рассмотрим простейший пример использования опера
тора цикла For для вывода 5-ти строк текста на экран.
В качестве Начапьного значении используем 1 , в ка
ч е ст в е Конечного значении - 5, соответственно, по
лучим 5 1 + 1 5 проходов цикла. В качестве выполня
емой Кома нды будем использовать процедуру Wri teLn
с параметром ' С т р о к а ' . Результат работы программы
представлен на рис. 94, а ее текст - в листинге 069.
-
Рис . 94. Результат
ра бо ты программы
=
И СПОЛЬЗОВАНИЕ ОПЕРАТОРА ЦИКЛА
FoR
Program UseForl ; { з а г о л о в о к nр о граммы ,
Uses
имя nр о гр аммы
-
Us eForl }
{ начало р а з д ел а nодключ ения модул ей }
CRT ;
var
i:
1.
{ nодключ ени е модуля CRT }
{ н ачало р а з д е л а оnис ания n ер еменных }
Int eger ;
{ оnисание целочисл енной nер еменной
для исnоль з о в ания в кач е с т в е с ч етчика цикл а }
Begin
{ н ачало р а з д е л а оnи с ания л о гики nр о гр аммы }
ClrScr ;
{ очистка экрана }
216
Глава 7. В ет вле н и е и заци кл и вание
For i : = l То 5 Do Writ e Ln ( ' Cтpoкa ' ) ;
{ выnолнение оnер а т ор а цикл а F o r ,
ReadKey ;
nеременная i
является с ч етчиком цикла и nринимает n о с л едо
в а т ельные знач ения от 1 до 5 ( т о е с т ь 1 , 2 , 3 ,
4 , 5 ) ; для кажд о г о знач ения переменной - сч етчика
цикла выnолняется nр оцедура Wr i t e Ln , выв одящая
на экран строку ' С тр ока ' }
{ nри о с т а нов ка nро граммы }
End .
{ конец р а здела оnи с ания л о гики пр ограммы }
Поясним механизм выполнения программы:
1. Очистка экрана.
2. Присвоение переменной i значения 1 , заданного в качестве Н а
чаль н а г о з н а ч е ни я . Сравнение значения переменной i со зна
чением, заданным в качестве Кон е ч н о г о з н а ч е ни я ( 5 ) . Так как
значение переменной i меньше, чем 5, то выполняется команда
W r i t e Ln ( ' С трока ' ) .
3. Увеличение значения переменной i на 1 (теперь i = 2 ) и срав
нение нового з н ачен ия с Ко н е ч ным з н а ч е ни ем. Так как зна
чение переменной i меньше, чем 5, то выполняется команда
Wri t e Ln ( ' С трока ' ) .
4. Увеличение значения переменной i на 1 (теперь i = З ) и срав
нение нового значения с Ко н е ч ным з н а ч е ни ем. Так как зна
чение переменной i меньше, чем 5, то выполняется команда
Wri t e Ln ( ' С трока ' ) .
5. Увеличение значения переменной i на 1 (теперь i = 4 ) и срав
нение нового значения с Ко н е ч ным з н а ч е ни ем. Так как зна
чение переменной i меньше, чем 5, то выполняется команда
Wri t e Ln ( ' С трока ' ) .
6. Увеличение значения переменной i на 1 (теперь i = 5 ) и срав
нение нового значения с Ко н е ч ным з н а ч е ни ем. Так как зна
чение переменной i не больше, чем 5, то выполняется команда
W r i t e Ln ( ' С трока ' ) .
7. Увеличение значения переменной i на 1 (теперь i = б) и сравнение
нового значения с Конечным з н а ч е ни ем. Так как значение пере
менной i больше, чем 5, то команда Wr i t e Ln ( ' С т р о к а ' ) не вы
полняется, а управление передается следующей за оператором For
команде. При этом значение переменной i уменьшается на еди
ницу, таким образом, после завершения оператора цикла значение
счетчика цикла равняется Кон е ч н ому з н а ч е нию.
8. Ожидание нажатия пользователем клавиши. Завершение работы
программы.
217
Turbo Pascal 7 . О
Стро к а
Строк а
Строка
Строка
Строка
1
2
3
4
5
Рис. 95 . Результат
работы программы
UseFor2
Что бы рядом с каждой строкой выводился ее номер
(см. рис. 95) достаточно лишь пеМJюго подправить опе
ратор вывода в цикле:
For i : =l
5 D o Wri teLn ( ' C т p o к a
То
{ в ып о л н е н и е
я вл я е т с я
значения
и
принима е т
1 до 5
от
i) ;
п е р еме н н а я
( то
есть
i
п о сл е д о
1,
2,
3,
; для каждо г о з н а ч е н и я п е р еме н н о й - с ч е т чи к а
ци кл а выполн я е т с я п р о ц е дур а
на
For ,
цикла
с ч е т ч и к ом цикла
в а т е л ь ные
4, 5)
оператора
'
э кр а н
с т р о ку
п е р еме н н о й
' С тр о к а
'
Wr i t e Ln ,
и
т е куще е
выв о д ящая
значение
цикла }
ОПЕРАТОР fOR С ОБРАТН Ы М ОТСЧ ЕТОМ
В некоторых программах требуется организовывать циклы, в которых зна
чение некоторой переменной не увеличивается, как в цикле For To Do,
а последовательно уменьшается.
• • .
• • .
Для организации циклов с обратным отсчетом существует модификация
оператора For вида:
For < С ч е тчик цикл а >
: =
<Н ачальное значение>
Downтo <Конечное значени е > Do < Команда> ;
При использовании цикла For с ключевым словом DownTo, а не То, на каж
дом шаге цикла происходит не увеличение Счетчика цикла на единицу,
а уменьшение до Конечноrоо значения:.
Таким образом, чтобы в предыдущем примере строки выводились в обрат
ном порядке - 4 Строка 6•, 4 Строка 5•, . , 4Строка 1 • , - можно изменить вид
оператора цикла так, чтобы значение Счетчика цикл а изменялось в об
ратном направлении (см. листинг 070).
..
Листинг 070. ИспользовАНИЕ опЕРАТОРА циклА FoR
Program UseFor4 ; { з а г оловок про граммы ,
Uses
CRT ;
Var
i:
имя
пр ограммы - U s e F o r 4 }
{ начало р а з дела подключ ения модул ей }
{ подключ ение модуля CRT }
{ начало р а з д е л а опис ания п ер еменных }
Int eger ;
{ опис ание целочисл енной переменной для
исполь з о в ания в кач е с т в е сч етчика цикл а }
Begin
{ начало р а з дела опи с ания л о г ики пр огр аммы }
ClrScr;
{ очистка экрана }
For i : = S Downтo 1 Do Wr i t eLn ( ' Cтpoxa
'
,
i) ;
{ выполнение оператора цикла F o r ,
п е р еменная i
является с ч е тчиком цикл а и принима е т п о с л еда -
218
Глава 7 . В ет влен и е и зац и кл и ван и е
в а т ельные знач ения от
2,
1) ;
5 до
1
( то е с т ь 5 ,
4,
3 ,
для каждого знач ения п ер еменной - с ч е тчика
цикла выполня ется пр оцедура Wri t eLn ,
на экран с троку
' Строка
'
выв одящая
и з н а ч е н и е сч етчика i }
ReadKey ;
{ прио с тановка пр ограммы }
End .
{ к онец р а з д е л а опис ания л о гики пр о гр аммы }
7 2 2 УСЛОВН ЫЕ ОПЕРАТОРЫ ЦИКЛА
.
.
.
Мы уже пытались реализовать простейшее персмещение объекта по экрану
в зависимости от нажатой пользователем клавиши. Написанная нами про
грамма ожидала нажатия пользователем клавиши и смещала объект, ана
лизируя, какая клавиша была нажата. Однако такое смещение можно было
провести всег о один раз, после чего програ.\1ма закапчива.лась.
Теперь, когда мы изучили работу с операторами цикла, можно модифици
ровать программу так, чтобы смещение объекта происходило несколько
раз. Для этого необходимо зациклить фрагмент проrраммы, ожидающий
ввода пользователя, анализирующий нажатую клавишу, и персмещающий
объект. Но оператор цикла For требует, чтобы количество проходов цикла
было задано заранее. Это, естественно, нам не подходит, потому что заранее
не может быть известно, сколько раз пользователь захочет персместить
объек и когда именно должна закончиться программа.
Для зацикливания фрагментов программ таким образом, чтобы выход
из цикла происходил не через заранее заданное количество проходов
цикла, а в соответствии с некоторым условием, например, используются
условные операторы цикла.
УСЛОВНЫЙ
О П ЕРАТОР ЦИ КЛА
WHILE
Do
• • •
Условный оператор цикла While Do предназначен для зацикливания
фрагмента программы таким образом, что перед очередным (в том числе и
первым) проходом зацикливаемого фрагмента происходит проверка необ
ходимости его прохода. Данный оператор называется условным операто
ром цикла с предусловием и имеет следующий вид:
. . .
Whi l e <Ус л о в и е > D o <Команд а > ;
Параметр Условие строится по правилам, аналогичным У с л о в ию, исполь
зуемому в условном операторе I f, а правила использования зацикливаемой
Команды аналогичны правилам, описанным для оператора цикла Fo r .
Рассмотрим рис. 9 6 . Начиная движение, программа выполняет команды 1 ,
2 и 3. Далее проверяется условие, и , в зависимости о т его истинности или
ложности, выполняются, соответственно, либо команды кольца 4 . 1 1 (после
.
.
219
Turbo Pascal 7 . 0
чего опять проверлетел истинность условия) , либо команды 1 2, 1 3, 14.
Таким образом, команды кольца могут вообще н и разу н е выполниться
(при ложности условия).
Для демонстрации работы условного оператора цикла с предусловием напи
шем программу (см. листинг 07 1 ), выводящую квадраты всех целых чисел,
начиная с введенного пользователем
и заканчивая 1 . введенного пользова
телем значения до 1 . Для этого опи
шем переменную N, в которую поль
зователь введет число. Далее опишем
цикл с предусловием, зацикливающий
следующую последовательность дейс
твий: вывод на экран квадрата числа N
и уменьшение значения N на единицу.
Условием необходимости очередного
Рис. 96. Условный оператор
выполнения зацикленной Коианды
цикла с предусловием
будет являться выражение N > О .
ЛИСТИНГ 07 1 . ИСПОЛЬЗОВАНИЕ ОПЕРАТОРА ЦИКЛА WHILE
Program U s eWhi l e l ;
{ з а г о л о в о к пр о граммы , имя пр ограммы - U s eWh i l e l }
{ начало р а з дела подключ ения модул ей }
Uses
CRT ;
{ по дключ ени е модуля CRT }
{ начало р а з дела опи с ания п ер еменных }
Var
{ опис ание целочисл енной пер еменной для
N : Int eger ;
хр ан ения знач ения , в в еденн о г о поль з о в а т е л ем }
Begin
{ начало р а здела опис ания л о гики пр о гр аммы }
ClrScr;
{ очистка экр ана }
Wri t е ( ' Введите чисnо : ' ) ;
{ пр едложение в в е с ти чи с л о }
ReadLn ( N ) ;
{ з ан е с ение числа , в в еденн о г о поль з о в а т е л ем ,
в пер еменную N }
{ у с л о вный оператор цикла с пр еду сл о в и ем }
Whi l e N > О do
begin
{ начало з ацикл енн о г о с о с т а в н о г о опер а т ор а }
writein (N * N) ; { вывод квадрата очередного значения переменной N}
N := N
end ;
ReadKey ;
End .
-
1;
{ уменьшение знач ения пер еменной N на единицу }
{ окончание з ацикл енн о г о с о с та в н о г о опер а т ор а }
{ приостановка пр ограммы }
{ конец р а з дела опи с ания л огики пр о гр аммы }
Рассмотрим последовательность действий, выполняемых програ..ч мой:
1. Очистка экрана.
2. Приглашение пользователя к вводу числового значения.
3. Занесение введенного пользователем числового значения в пере
менную N. Допустим, пользователь ввел число О.
220
Глава 7. В етвле н и е и заци кл ива н и е
4. Проверка истинности условия N> O в условном операторе цикла
Whil.e. Так как значение переменной N=O, то данное условие ложно,
и, соответственно, зацикленный составной оператор не выполняет
ся, а управление передается команде, находящейся после составно
го оператора (это команда ReadКey) .
5. Выполнение команды ReadКey - ожидание нажатия па клавишу.
Завершение проrраммы.
Это как раз тот случай, когда зацикливаемая команда (в данном случае со
ставной оператор) не выполняется ни разу. Теперь рассмотрим, как будет
работать проrрамма, если пользователь введет, иапример, число 3:
1 . Очистка экрана.
2 . Приглашение пользователя к вводу числового значения.
3. Занесение введенного пользователем числового значения в перс
менную N. Допустим, пользователь ввел число 3.
4. Проверка истинности условия N > O в условном операторе цикла
Whil.e. Так как значение переменной N= З , то данное условие истин
но, поэтому управление передается составному оператору, который
является зацикливаемой командой. На экран выводится значение
выражения N * N, то есть 9. Значение переменной N уменьшается на
единицу (N : =N- 1 ) и получает значение N= 2 .
5 . Проверка истинности условия N>O в условном операторе цикла
Whil.e. Так как значепие_ перемешюй N= 2 , то данное условие истин
но, поэтому управление передается составному оператору, который
является зацикливаемой командой. На экран выводится значение
выражения N * N, то есть 4 . Значение переменной N уменьшается
на единицу (N : =N- 1 ) и получает значение N = 1 .
6 . Проверка истинности условия N > O в условном операторе цикла
Whil.e. Так как значение переменной N= 1 , то данное условие истин
но, поэтому управление передается составному оператору, который
является зацикливаемой командой. На экран выводится значение
выражения N * N, то есть 9. Значение переменной N уменьшается
на единицу (N : =N- 1 ) и получает значение N = O .
7. Проверка истинности условия N > O в условном операторе цикла
Whil.e. Так как значение переменной N= O , то данное условие ложно,
и, соответственно, зацикленный составной оператор не выполняет
ся, а управление передается команде, находящейся после составно
го оператора (это команда ReadКey ).
8. Выполнение команды ReadКey - ожидание нажатия на клавишу.
Завершение программы.
Заметим, что такую программу можно было написать и с использованием
оператора цикла For с обратным отсчетом (см. листинг 072).
22 1
Turbo Pascal 7 . 0
Л ИСТИНГ 072 . ИСПОЛЬЗОВАНИЕ ОПЕРАТОРА ЦИКЛА FOR ВМЕСТО WHILE
Program UseForS ; { з а г о л о в о к nр ограммы ,
Uses
имя
nр о гр аммы - Us eWh i l e S }
{ н ачало ра здела nодключ ения модул ей }
CRT ;
{ nодключ ени е модуля CRT }
Var
{ начало р а з д е л а оnис ания nер еменных }
N:
Int eger ;
{ оnис ани е целочисл енной nер еменной для
I:
Int e ge r ;
{ оnис ание целочисленной nеременной для
хр анения зн ач ения ,
в в еденн о г о nоль з о в ат е л ем }
исnоль з о в ания в кач е с т в е с ч е тчика цикл а }
Begin
{ н ачало р а з д е л а оnис ания л о гики nр ограммы }
ClrScr ;
{ очистка экрана }
Wr i t е ( ' Вв едите число :
') ;
{ nр едлож ение в в е сти число }
ReadLn ( N ) ;
{ з ан е с ени е чи сла ,
в в еденн о г о nоль з о в а ·r· е л ем ,
в n ер еменную N }
For I : =N Downтo 1 Do
{ у сл о вный оnератор цикл а с nр е ду с л о вием }
Wri t e Ln ( I
*
I) ;
{ вывод кв адрата очередного знач ения
пер еменной N }
ReadKey ;
{ nр и о с т ановка nр огр аммы }
End .
{ конец р а з д е л а опи с ания ло гики пр огр аммы }
Как видим, программа получилась значительно проще, хотя в ней исполь
зовано больше переменных. Теперь изменим програ1\1му так, чтобы выводи
лисЪ квадраты не для всех чисел от введенного до 1 , как ранее, а только для
тех, квадраты которых больше введенного пользователем значения. Напри
мер, для введенного значения 5 получим последовательность чисел не 25,
1 6, 9, 4, 1, ·а только 25, 1 6, 9. Для значения 1 О - 1 00 , 8 1 , 64, 49, 36, 25, 1 6, а для
значения 2 - 4.
Для этого необходимо изменить условие прохождения очередного цик
ла N > O на N * N > N . Однако переменпая N содержит введенное пользовате
лем значение только до первого прохода зацикленного оператора. В связи
с этим, чтобы условие было корректным, необходимо сохранить началь
ное значение переменной N в другой переменной (назовем ее N l ) и прово
дить сравнение квадрата текущего числа именно с ней: N * N > N 1 . Текст
программы приведен в листинге 073.
Л ИСТИНГ 073. ИсПОЛЬЗОВАНИЕ ОПЕРАТОРА ЦИКЛА WHILE
Program us eWhi l e 2 ;
{ з а г о л о в о к пр о граммы ,
Uses
CRT ;
Var
N:
имя
пр ограммы - U s eWh i l e 2 }
{ начало р а з дела nодключ ения модул е й }
{ по дключ ени е модуля CRT }
{ начало р а з д е л а оnис ания n е р еменных }
Integer ;
{ оnис ание целочисленной nеременной для хр анения
знач ения , в в еденн о г о nоль з о в а т е л ем и е г о измен ения }
222
Глава 7. В ет влен и е и заци кл и ван и е
{ опис а ние целочисленной пер еменной }
Nl : Int eger ;
Begin
{ начало р а з д ел а опис ания л о гики пр о г р аммы }
C l rS c r ;
{ оч и с т к а экрана }
Wri t е ( ' Введи т е чи сло : 1 ) ;
{ предлож ение в в е сти числ о }
{ з ан е с ение числа , в в еденн о г о п о ль з о в а т е л ем ,
Re adLn ( N ) ;
Nl
: =
в пер еменную N }
{ с охранение з н ач ения , в в еденно г о п о ль з о в ат е л ем ,
для и с п о ль з о в ания в у с л о вии оператора Wh i l e }
Nl dо { у с л о вный оператор цикла с пр еду с л о в и ем }
N;
Whi le N*N >
begin
{ начало з ацикленн о г о с о с т а в н о г о о п ер а т ор а }
WriteLn ( N * N ) ; { вывод к в адр а т а очередн о г о знач ения
N := N
end ;
ReadKey ;
-
п ер еменной N }
{ уменьшение знач ения п ер еменной N на единицу }
{ окончание з ацикл енн о г о с о с т а в н о г о оператор а }
1;
{ пр и о с т а н о в к а пр о гр аммы }
{ к онец р а з д е л а опис ания ло гики прогр аммы }
End .
В таком варианте программы проявляются достоинства оператора While
перед For, так как аналогичная программа, но без использования условного
оператора цикла подразумевает написание довольно сложного алгоритма
определения Конечного значенин: изменения переменной-счетчика.
И СПОЛ ЬЗОВАН ИЕ УСЛОВНЫХ ОПЕРАТОРОВ Ц ИКЛА В МОДЕЛИРОВАН И И
Условные операторы цикла имеют ши
рокое применение для решения задач,
аналитическое решение которых мо
жет быть очень сложным. Рассмотрим
тело, брошенное со скоростью V ( м / с )
под углом А к гориэопту. Ускорение
свободного падения g будем считать
равным 9 . 8 м/ с2• Наша задача - оп
ределить примерную дальность полета
тела D до момента его падения на зем
лю (см. рис. 97) в зависимости от на
чальных значений скорости v и угла А.
у
Тр ае кто р и я п олет а
Vy
х
Vx
D
Рис. 9 7. Иллюс трация к ма тематиче ской
модели поле та тела , брошенного
под углом к горизон ту
Таким образом, математическая модель, представляющая данный процесс,
будет состоять из следующих параметров:
V .
.
А
. . . .
. . . . .
. . . . . . . . . .
Vx . . . .
Vy
q
..
. .
.
.
. . .
. . . . . .
. . . . . . . . . .
. . . . . . .
угол, под которым брошено тело;
. проекция текущей скорости на ось х;
• • • • • • • • • • . • • • •
..
начальная скорость;
проекция текущей скорости на ось У;
, . . . . . ускорение свободного падения;
223
Turbo Pascal 7 . 0
dT
н
D
.
• • . • • . • • • • • • • • •
........
. . .. ..
.
.
интервал дискретизации;
. . . текущая высота тела;
.
.
.
• • • • • • • • • • • • • • • • •
текущая дальность полета тела.
За каждую единицу времени полета, называемую интервалом дискретиза
ции, высота тела Н изменяется на значение Vy* dT, дальность полета тела D
на значение Vx * dT, а проекция скорости на ось У уменьшается на значение
g * dT . Начальные значения высоты и дальности - нулевые: Н= О, D= O , а зна
чения скорости v и угла А вводятся пользователем.
Постановка эксперимента над математической моделью с помощью про
граммы будет включать следующие этапы:
1 . Инициализация всех параметров модели начальными значениями,
в
том числе ввод пользователем значений скорости V и угла А.
2. Расчет значений проекций скорости v на оси координат, Vx и Vy.
Для этого воспользуемся стандартными функциями Turbo Pascal
S in (вычисляющей синус заданного угла) и Cos (вычисляющей
косинус заданного угла) . Особенность данных функций состоит
в том, что их единственный параметр - угол, синус или косинус
которого требуется рассчитать - задается в радианах, тогда как
пользователю удобнее вводить угол в градусах. Таким образом,
считая, что пользователь ввел угол в градусах, в функции S in и
Cos необходимо подставлять не значение переменной А, содер
жащей введенный пользователем угол, а выражение А/ 1 8 О * 3 1 4 .
Вместо значения 3 1 4 можно использовать стандартную конс
танту P I , содержащую данное число. Таким образом, проекция
скорости v на ось Х рассчитывается по формулам:
-
.
.
Vx
Vy
=
=
V
V
*
C o s ( A/ 1 8 0
*
PI ) ;
*
S i n ( A/ 1 8 0
*
PI ) .
3. В случае, если высота тела неотрицательна (Н>= О), моделируем
смещение тела. Если высота тела меньше либо равна нулю, то это
значит, что результат достигнут, тело находится в конце траектории,
а значит, следует закончить программу, выведя па экран результат
расчета дальности полета D.
Расчет текущей высоты Н и дальности D по формулам:
D
=
Н
=
D
+
Vx
*
dT ;
Н + Vy * dT .
Расчет изменения проекции скорости Vy с учетом ускорения сво
бодного падения по формуле:
Vy
224
=
Vy
-
g
*
dT .
Глава 7. Ветвлен и е и заци кл и вание
Пункт 3 предложенной схемы зацикливается с помощью условного опе
ратора цикла W h i l e , в качестве У сл о в и я которого используется выра
жение Н>= О .
Л ИСТИНГ 074. ПРИМЕР ПРОГРАММНОГО МОДЕЛИРОВАНИЯ ФИЗИЧЕСКОГО ПРОЦЕССА
Program Flight 1 ; { з а г о л о в о к пр о граммы ,
us e s
имя пр о гр аммы - F l i ght l }
{ начало р а з д ел а подключ ения моду л е й }
CRT ;
{ п одключение модуля CRT }
Const
{ начало р а з д е л а опис ания к о нс т ант }
g = 9 . 8;
{ у с корение с в о б одно г о падения }
dT
{ интервал дискретиз ации }
1;
=
Var
{ н ач а л о р а з д е л а опис ания п ер ем енных }
V:
Real ;
{ начальная с к ор о с ть т ел а }
А:
Real ;
{угол ,
vx ,
D:
Н,
Real ;
Vy :
Real ;
под к о т орым бр ошено т е л о }
{ пр о е кции скорости на о с и к о ордин а т }
{ т екущи е в ы с о т а и дально с т ь }
Begin
{ начало р а з д ела опис ания л о гики лр огр аммы }
ClrSc r ;
{ очистка э кр ан а }
Wri t е ( ' Вв едите скорос т ь
(м/с ) :
' ) ;
{ пр едло ж ение в в е сти с к ор о с т ь }
ReadLn ( V ) ;
{ з ан е с ение чи с л а ,
в в еденн о г о п о ль з о в а т е л ем ,
в п ер еменную V }
Wri t е ( ' В ведите угол
( град . ) :
' ) ;
{ пр едложение в в е с ти у г о л ,
под к о т орым
бр ошено т е л о }
ReadLn ( A ) ;
{ з ан е с ение числа ,
в в еденн о г о поль з о в ат ел ем ,
в п ер еменную А }
Н
D
VX
:= О;
О;
: =
: =
V * Cos ( A/ 1 8 0
* PI ) ;
Vy : = V * S i n ( A / 1 8 0 * P I ) ;
{ прис в о ение начальных знач ений пер еменным Н и D ,
р а с ч е т про екций скор о с ти н а оси к о ординат }
Wh i l e Н >= О do
{ у с л о в ный оператор цикл а ,
оператор в случае ,
выполняющий с о с т а вной
е с ли т е кущая в ы с о т а о бъ е к т а
н е о трицательн а }
begin
{ начало з ацикл енн о г о с о с т а в н о г о о п ер а т ор а }
Н
:= Н
+
Vy * dT ;
D
:= D
+
Vx
Vy : = Vy
end ;
-
*
dT ;
g * dT ;
{ оч ер едной р а с ч ет параметр о в модели }
{ окончание з ацикл енн о г о с о с т а в н о г о оператор а }
Wri t е Ln ( ' Дальность :
'
,
D) ;
{ вы в о д дальн о с ти ,
получ енной в р е зуль т а т е
моделир о в ания }
ReadKey ;
{ лриостановка лр огр аммы }
End .
{ конец р а з д е л а опи с ания л о гики пр огр аммы }
8
За:в:. 702
225
Tu rbo Pascal 7 . 0
Итак, приведеиная программа (см. листинг 1 1 0) пересчитывает параметры
высоты, дальности и вертикальной скор о сти до тех пор, пока высота пе ста
нет меныпей или равной нулю, это означает, что тело упало па землю. Резуль
тат вычисления будет неточен, так как обычно выход из цикла осуществляет
ся при значении высоты Н меньшей нуля, что означает �зарывание:�> тела в
землю. Это происходит из-за слишком большого интервала дискретизации.
Фактически программа сч ит ает, что объект летит н е по параболе, как это
происходит в жизни, а по ломанной, причем точки излома определяются самой программой на каждом шаге цикла
у
(см. рис. 98). Чем меньше интервал дис
кретизации - тем точнее результат, по
лучаемый при постановке эксперимента
над моделью , но больше время проведе
ния эксперимента.
L------ч+х
dT"B
Рис. 9 8. Возникновение погрешности
расчета при постановке
программнога эксперимента
Для данной модели можно выбрать ин
тервал дискретизации, равный, напри
мер, 0.00000 1 , что даст довольно высо
кую точность вычисления при довольно
малом времени работы программы.
Но рассмотренная на.'\Ш задача определения дальности полета тела, брошенно
го п од угл ом к горизонту, имеет довольно простое анапитическое решение , поэ
тому написание такой програ.'Wмы не имеет особого смысла - леrче было бы
осуществить расчет по известной формуле, в результате чего получилась бы
бы стро работающая программа, вьща:ющая точный результат, которого все рав
но н евоз мож н о достичь, даже очень сильно уменьшая интервал дискретизации.
Однако можно приблизять нашу задачу к рсапыюсти, добавив испольаование
в рассмотренном процессе динамического сопротивления среды, уменьшаю
щего скорость движения объекта пропорционально самой скорости. Допустим,
коэффициент сопротивления в будет равен 0.0 1 , что означает снижение скоро
сти на каждом шаге расчета на одну сотую долю этой скорости. Таким образом,
нам необходимо изменять вертикальную проекцию скорости не только с уче
том ускорения свободного падения, но и с учетом сопротивления среды, дом
ножая полученную на каждом шаге скорость на 0.99. То же самое должно про
исходить и с горизонта..тr ьной проекцией скорости. Чтобы решить такую задачу
анапитически, необходимо обладать более глубокими знаниями математики,
а именно, уметь дифференцировать и интегрировать функции. Рассмотрим
программу, моделирующую такой физический процесс (см. листинг 075).
ЛИСТИНГ 075.
ПРИМЕР ПРОГРдММНОГО МОДЕЛИРОВАНИЯ СЛОЖНОГО ФИЗИЧЕСКОГО ПРОЦЕССА
Program F l i ght 2 ; { з а г о л о в о к пр ограммы ,
Uses
CRT ;
226
имя
про гр аммы - F l i gh t 2 }
{ н ачало р а з д ела подключения модул ей }
{ п одключ ени е модуля CRT }
Глава 7. В ет влен и е и зац и кл иван и е
{ начало р а з д ела опис ания к о н с т ан т }
Const
g
9.8;
=
{ у скорение с в о б одно г о пад ения }
dT = 1 ;
в
{ интер в ал дискр етиз ации }
0 . 99 ;
=
{ коэффициент уменьш ения скор о с ти и з - з а
с опр отивл ения ср еды }
Var
{ начало р а з д ел а опис ания пер еменных }
V:
Real ;
А:
Real ;
Vx , vy :
Н,
D:
{ н ач альная скор о с т ь т е л а }
{угол ,
Rea l ;
Real ;
под которым брошено т е л о }
{ пр о е кции скоро с ти на о с и координ а т }
{ т екущие высота и дально с т ь }
Begin
{ н ачало р а з дела опи с ания ло гики пр о гр аммы }
ClrScr ;
{ очистка экр ан а }
Wr i t е ( ' В в е дите скорос т ь :
');
{ пр едложение в в е с ·ги с коро с т ь }
{ з ан е с ение числа ,
ReadLn ( V ) ;
в в еденн о г о поль з о в а т ел ем ,
в п ер еменную V }
Wri t е ( ' В в е дите угол :
' ) ;
{ пр едлож ени е в в е с ти угол ,
под к о т орым
брошено тело }
{ з ан е с ение чи с л а ,
ReadLn ( A ) ;
в в еденн о г о п о ль з о в а т е л ем ,
в пер еменную А }
Н
:= О;
D
О;
: =
Vx
. - V * Cos ( A/ 1 8 0
Vy
: =
V *
S i n ( A/ 1 8 0
PI ) ;
*
* PI ) ;
{ прис в о ение начальных знач ений п ер еменным Н и D ,
р а с ч е т пр оекций скоро сти на о с и ко ординат }
Whi l e Н >= О do
{ у сло вный оператор цикла ,
опер а т ор в с луча е ,
выполняющий с о с т а вной
е с ли т екущая высота объекта
н е о трицат ельна }
begin
{ начало з ацикл енн о г о с о с т а в н о г о оператор а }
Н
: =
Н
D
: =
D
vy
Vx
vy
: =
: =
+
vy
*
dT ;
+ Vx * dT ;
vy - g * dT ;
Vx
*
В;
: = vy * В ;
{ о ч ер едной р а с ч е т параметр о в моде ли ,
в том чи с л е и с уч етом динамич е с к о г о
с опр отивл ения ср еды ,
end ;
в которой движ е т с я о бъект }
{ окончание з ацикл енн о г о с о с т а в н о г о опер атор а }
Wri t е Ln ( ' Дальнос т ъ :
'
,
D) ;
{ вы в о д дальн о с ти ,
получ енной в р е зу л ь т а т е
моделир о в ания }
ReadKey ;
{ приостановка пр о гр аммы }
End .
{ конец р а з дела опис ания логики проrраммы }
Таким образом, программа, моделирующая значительно более сложный
процесс, выглядит не намного сложнее проrраммы, моделирующей прос
той процесс.
227
Turbo Pascal 7 . О
УСЛОВНЫЙ
О П Е РАТОР ЦИКЛА
REPEAT
• • •
UNTIL
В некот орых програ.чмах необходимо реализовать зацикливание таким об
ра:юм, чтобы Команда, выполняемая на каждом шаге цикла, была выавана
хотя бы один раз . Это относится, например, к меню. Пользователь может
выйти из меню, выбрав соответствующий пункт этого м еню (если такой
предусмотрен) или нажав клавишу �Esc:» . Однако, вне зависимости от же
лания или п ежелания продолжать работу с программой, пользователь дол
жен сначала это меню увидеть.
q1
оманды кольца
4"" 1 4
Рис . 99 . Усл овный оператор
ц икла с пос тусловием
Такого рода зацикливание организуется с
помощью условных операторов цикла с
постусловием, в которых необходимость
выполнения зацикленного фрагмента про
граммы определяется не перед, а после вы
полнения шага цикла. Таким образом, га
рантируется хотя бы однократное выполнение зацикленного фрагмента программы
99
сво з (см. рис. : команды кольца обойти н
можно, а выход из кольца возможен только
после как минимум одного его прохода) .
В ТнrЬо Pascal предусмотрен один условный оператор цикла с постуслови
ем - Repeat Until (анrл. Repeat . . . Until - Повторять ... До тех пор, пока
не ... ), имеющий следующий вид:
• • •
Repeat
< Фр а гмент пр о гр аммы>
Unt i l <Ус л о в и е > ;
Зацикленный Фра:t"Мен'l' проl"раммы выполняется один раз, затем про
веряется Условие , находятцееся после ключевого слова Un til и в случае
его истинности управление передается команде, следующей за оператором
цикла. В случае ложности Условии зацикленный Фра:t"Мен'l' проl"раммы
повторяется еще раз, и т.д. В качестве Фра:t"Мен'l'а проl"раммы может ис
пользоваться любое количество л юб ых команд ТнrЬо Pascal, при этом нет
необходимости объединять их составным оператором.
Так же как и во всех условных операторах, в Repea t un til можно приме
нять сложные условия, содержащие переменные, константы и логические
операторы (см. листинг 076).
• • •
Л ИСТИНГ 076. ОЖИДАНИЕ НАЖАТИЯ КОНКРЕТНОЙ КЛАВИШИ БЕЗ УЧЕТА РЕГИСТРА
Program Us eRU2 ; { з а г о л о в о к пр ограммы ,
Uses
CRT ;
Var
228
имя пр огр аммы - U s eRU2 }
{ начало р а з д е л а п одключ ения модул ей }
{ п одключ ени е модуля C RT }
{ начало р а з д ела опи с а ния п ер еменных }
Глава 7 . Ветвление и заци кл и вание
Ch :
{ п ер еменная для хр анения нажатой клавиши }
Char ;
Begin
{ начало р а з дела опис ания л о гики пр о гр аммы }
C l rS c r ;
{ очистка экрана }
Repeat
{ н ачало оператора цикл а }
Wri t е ( ' Нажмите Q ! ' ) ;
{ пр едло жение нажать клавишу Q }
Ch
: =
Re adKey ; { ожидани е нажатия и з ан е с ение симв ола
в п еременную }
Unt i l
( Ch
=
'Q' )
OR
( Ch
=
'q' ) ;
{ у с л о в и е выхода и з цикл а }
Wri t e Ln ( ' Cпacибo ! ! l ' ) ;
ReadKey ;
{ пр и о с т а н о в к а пр о гр аммы }
End .
{ к онец р а з дела опи с ания л о гики про гр аммы }
В этой программе условие выхода из цикла по нажатию на клавишу Q пос
троено таким образом, чтобы пользователь мог н ажимать не только заглав
ную б у кв у Q, но строчную q. Для этого условие должно с о ст оять из двух
частей, соединенных логическим оператором O R: ( Ch= ' Q ' ) O R ( Ch= ' q ' ) .
Такое условие будет истинным, если переменпая Ch будет содержать либо
символ Q, либо символ q
Заметим, что при использовании логических операторов AND OR и NOT необ
ходи мо заключать в круглые скобки операнды, используемые в таких выра
жениях, чтобы избежать путаницы с одноименными бинарными оператора
ми. Например, выражение А AND в рассматривается компилятором как
логическое, только если оба операнда А и в являются логическими перемен
ными (типа Boolean). Если же одна из персменных является, например, це
лочисленной, оператор AND рассматривается как бинарный, то есть произво
дящий побитовое умножение (рассмотренное нами при изучении спрайтов).
,
Таким образом, при использовании условия типа А > 5 AND в < 3, счита
ется, что оператор AND используется как бинарный, соответственно, в связи
с его высоким приоритетом, данное выражение будет рассматриваться как
А > ( 5 AND В ) < 3, то есть будет являться синтаксически неверным.
Однако при использовании выражения (А > 5 ) AND ( в < 3 ) приоритет
выполняемых операций определяется скобками. Сначала рассматриваются
выражения А > 5 и В < 3 , являю1циеся условиями и, следователъно,
имеющими значения типа Boolean. Соответственно, оператор AND в таких
выражениях будет рассматриваться, как логический, и данные выражения
могут быть использованы в качестве условий.
7 . 2 . 3 . 8ЛОЖЕННОСТЬ ОПЕРАТОРОВ ЦИКЛОВ
При описании условных операторов и операторов цикла мы говорили, что
в качестве Команды внутри этих операторов могут использоваться любые
команды Turbo Pascal, в том числе условные операторы и операторы цикла.
229
Turbo Pascal 7 . 0
Когда какой-либо оператор используется в качестве Ком а н ды, выполняе
мой таким же оператором, говорят, что данный оператор является вложен
ным. Вложенные условные операторы мы уже рассматривали, а теперь рас
смотрим как используются вложенные операторы цикла.
Для демонстрации возможностей вложенпас т и
операторов цикла напишем программу, выводя
щую па экран таблицу умножения ( см. рис. 1 00).
Для простоты реализуем программу в тексто
вом режиме. При выводе такой таблицы после
довательным позиционированием ( G o t oXY) и
печатью на экране (W r i t e ) чисел потребуется
Рис. 1 00. Таблица умножения
довольно большая программа. Она должна бу
дет содержать, соответственно, 81 операцию позиционирования и 8 1
операцию вывода числа, в которой к тому же появится огромное коли
чество оrпибок.
1
2
3
4
5
6
7
8
9
2
4
6
8
10
12
14
16
18
4
3
6
8
9
12
12 16
1 5 20
18 24
21 28
24 32
27 36
6
5
10 12
15 18
20 24
25 30
30 36
35 42
40 48
45 54
7
14
21
28
35
42
49
56
63
8
16
24
32
40
48
56
64
72
9
18
27
36
45
54
63
72
81
Однако если внимательно рассмотреть таблицу построчно, то видно, что
каждая строка представляет собой ряд чисел, причем каждое число это
го ряда задано по определенным правилам . Проще всего вывести верх
ний ряд таблицы: 1 , 2, 3 , 4 , 5, 6, 7 , 8, 9. Для этого можно в оспользоваться
оператором цикла со счетчиком , установив пределы изменения счетчи
ка от 1 до 9 и выводя на каждом проходе цикла значения переменной
счетчика.
Допустим переменная, используемая в качестве счетчика, имеет имя Х. Тог
да вывод верхней строки будет выглядеть следующим образом:
For Х
: =
1 То
9 Do Wr i t e ( X ) ;
Однако в случае такого использования цикла мы получим последователь
ность чисел, между которыми не будет интервалов: 1 23456789. Для реше
ния проблемы можно после каждого числа выводить пробел:
For Х
: =
1 То 9 Do Wri t e ( X ,
•
'
) ;
В ре зул ьт ат е вьшолп ения т акого цикла получим строку � 1 2 3 4 5 6 7 8 9 � .
Для первой строки такой метод вывода подходит, но в остальных стро
ках находятся числа, содержащие более чем один символ. П оэтому в
каждой строке, начиная с векоторого места, появится сдвиг относитель
но предыдущей, и числа в столбцах не будут выровнены. Если все числа
в таблице будут занимать ровно три символа (включая пробелы), то все
столбцы будут ровными. Для этого число 1 должно выводиться, напри
мер, в третий символ строки 1 (для этого можно применить процедуру
G o t oXY ( 3 1 1 ) ) , число 2 - в шестой символ строки 1 ( G o t oX Y ( 6, 1 ) ) ,
число 3 в девятый ( G o t oXY ( 9 1 1 ) ) и так далее. Обобщим: число но
мер х должно выводиться в позицию номер Х* 3 первой строки
( Go t o X Y ( X * 3 , 1 ) ) .
-
230
Глава 7. В етвлен и е и зац и кл и ван и е
ПРИМЕЧАНИ Е.
Об ра ти те в н и м а н и е , ч то и с п ол ьзова н и е лю б ых о перат оров ц и кл а тр е б уе т ш и р око
го вз гляда на де й ств и я , ко то ры е до л ж н а вы п ол н я ть про г р а м м а , п оэто м у п о и с к пути
за ц и кл и в а н и я ф ра г м е нта п р ограм м ы о б ы ч н о п ро и сх од ит та к: сн а ч ал а нуж н о в ы я с
н ит ь п о сл едо вател ьно ст ь вы пол н я е мых пр о г раммой д е й ст в и й , а зате м ф о р м ал и
з оват ь их, зап и с а в в о б щем в иде. Есл и не удается ка к им -л и б о о б разо м о б о б щ и т ь
де й ств и я , в ы п олняе м ые п рограмм о й , о перат о р ци кл а и с п ол ьзо в ат ь н е воз м ож н о .
Итак, для вывода первой строки необходимо использовать такой оператор
цикла:
For Х : = 1 То 9 Dо { оп ер атор цикла }
begin
{ начало с о с т ав н ог о оператор а )
Got oXY ( X * 3 , 1 ) ;
{ по з иционир о в ани е к аретки )
Wr i t e ( X ) ;
{ вывод чи с л а )
end ;
{ окончани е оператора цикла )
Теперь рассмотрим остальные строки проrраммы. Вторая строка представ
ляет собой ряд чисел 2, 4, 6, 8, 1 0, 1 2, 14, 1 6, 1 8. Выводиться они должны в те
же горизонтальные координаты, что и числа первой строки таблицы, но не
в первую экранную строку, а во вторую. При этом выводиться должно уже
не число х, как для первой строки, а число х*2:
For Х : = 1 То 9 Dо { опер атор цикл а )
Begin
{ н ачало с о с т а в н о г о опер а т ор а }
Got oXY ( X * 3 , 2 ) ;
{ по з иционир о в ани е каретки
Wri t e ( X * 2 ) ;
{ вывод чис л а }
end ;
{ оконч ани е опер атора цикл а )
Можно таким образом вывести и все остальные строки, изменяя номер экран
ной строки и коэффициент, на который умножается номер числа в строке. Но
можно еще больше упростить проrра.'d:му. Рассмотрим последовательность
номеров экранных строк, соответствующих строка.'\1 таблицы. Разумеется,
последовательность номеров представляется рядом чисел 1 , 2, 3, 4, 5, 6, 7, 8, 9.
Далее, рассмотрим последовательность коэффициентов, используемых при
умножении номера выводимого числа ( Х ) : 1 , 2, 3, 4, 5, 6, 7, 8, 9. То есть полу
чена такая же последовательность. ТакИм образом, введя некоторую перс
менную У, содержащую номер выводимой строки таблицы, можно скаэать,
что строка таблицы с номером У должна выводиться с помощью оператора
цикла, имеющего следующий вид:
For Х : = 1 То 9 Do { опер атор цикл а )
Begin
{ начало с о с т а в н о г о оператора }
Got oXY ( X * 3 , У ) ;
{ п о з иционир о в ани е кар е тки )
Wri t e ( X * У ) ;
end ;
{ вывод чи с л а )
{ окончани е оператора цикл а )
23 1
Tu rbo Pascal 7 . О
Теперь осталось только выполнить этот оператор цикла в другом операторе
цикла, и з м е ня ю щ ем переменпую У последовательно от 1 до 9 :
For У
: = 1 То 9 Do
. . . ;
Итак, фрагмент программы, выводящий таблицу умножения на экран пол
ностью, выглядит следующим образом:
For У
: = 1 то 9 Do
{ оператор цикл а для п о с л е д о в а т е л ь н о г о
измен ения пер еменной У )
1 То 9 Do
{ оп ер а'гор цикла для п о с л е д о в а т ельно г о
и змен ения переменной Х )
Begin
{ начало с о с т авного оnер атор а )
Got oXY ( X * 3 , У ) ;
{ nо з иционир о в ание каре тки )
Writ e ( X * У ) ; { вывод числа )
For Х
:=
end ;
{ окончание оnератора цикл а )
Осталось сказать, что при такой организации программы, оператор цикла
со счетчиком У называют внешним циклом, а оператор цикла со счетчи
ком х
вложенным. Полностью текст программы, выводящей таблицу
умножения, представлен в листинге 077.
-
Л истинг 077 . Вывод ТАБлицы Умножения
Program Mu l t TaЬl e 1 ;
{ з а г о л о в о к пр о граммы ,
имя
nр ограммы - Mu l t TaЬ l e 1 }
{ начало р а з д е л а n одключ ения модул ей )
Uses
{ подключ ение модуля CRT }
CRT ;
{ начало р а здела оnи с ания пер еменных )
Var
Int eger ; { n ер еменные для исполь з о в ания в к ач е с т в е
Х, У:
сч етчик о в }
{ начало р а з д е л а оnис ания логики пр о гр аммы }
Begin
C l rS c r ;
For У
{ очис•rка экр ан а }
: = 1 то 9 Do
{ оператор цикла для п о с л е д о в а т ел ь н о г о
For Х
:=
измен ения переменной У )
1 т о 9 Do
{ оператор цикла для n о с л едо в а т ел ь н о г о
измен ения переменной Х }
Begin
Got oXY ( X *
{ начало с о ставного опер а т ор а }
3,
У) ;
{ nо з иционир о в ание к ар етки }
Writ e ( X * У ) ; { вывод числ а }
end ;
{ окончание оnератор а цикл а }
ReadKey ;
{ приостановка пр огр аммы )
End .
{ конец р а з дела опи с ания ло гики пр ограммы }
232
Глава 7 . В етвле н и е и заци кл ивание
Кроме уменьшения объема программы, при использовании циклов дости
для изменения размеров табли
цы на экране достаточно изменить только Ко н е ч ные з н а ч е н и я в опера
торах циклов; для того, чтобы столбцы таблицы смотрелись более редкими,
достаточно поменять множитель 3 в процедуре G o t oXY на какой-либо
другой. Изменим программу так, чтобы выводилась таблица умножения
размером 1 9х 2 5 , а ширина каждого столбца равнялась четырем символам
(см. листинг 078).
гается очень боль шая гибкость. Нап р и м е р ,
ЛИСТИНГ 078.
ВЫВОД ТАБЛИЦЫ УМНОЖЕНИЯ (с ИЗМЕНЕННЫМИ ВНЕШНИМИ ПАРАМЕТРАМИ )
Program Mul t TaЬl e 2 ;
{ з а г оло в ок пр о гр аммы , имя пр о гр аммы - Mu l t TaЬl e 2 }
Uses
{ начало р а з дела подключ ения модул ей }
CRT ;
{ подключ ение мо дуля CRT }
Var
{ начало р а з дела опи с ания п еременных }
х,
У:
Int e ger ; { п ер еменные для исполь з о в ания
в к ач е с т в е с ч етчик о в }
Begin
{ начал о р а з дела опи с ания л о гики пр ограммы }
ClrScr;
For У
{ очистка э кр ан а }
: =
1 то 1 9 Do
{ оператор цикла для п о сл е до в ательно г о
изменения переменной У }
For Х
: =
1 Т о 2 5 Do
{ оператор цикл а для п о с л е д о в а т ельно г о
измен ения пер еменной Х }
B e gin
{ начал о с о с т а в но г о опер а т ор а }
GotoXY (X*4 , У) ; { п о з ициониро в ание каретки }
Wri t e ( X *Y ) ;
end ;
{ выв од числ а }
{ окончани е опер а т ор а цикл а }
ReadKey ;
{ приостановка пр о гр аммы }
End .
{ к онец р а з дела опис ания л о гики пр о гр �шы }
Изменено всего три параметра, а результат при этом достигнут очень боль
шой. Если бы каждое число таблицЫ выводилось отдельно, то для новых
строк и столбцов пришлось бы дописывать новые команды вывода.
Напишем еще одну программу, персбирающую все возможные сочетания
цвета текста и фона и въшодящую строку текста для каждого сочетания. Эту
задачу мы также решим с помощью вложенных циклов (см. листинг 079) .
Во внешнем цикле будет происходить изменение переменной B a c k, опреде
ляющей цвет фона выводимой строки, а во вложенном цикле - изменение
nерсменной F o r e , определяющей цвет выводимых символов. Б качестве
зацикленной Команды используем составной оператор, изменяющий теку
щие цвета фона и текста и выводящей строку вида 4:А/ В�, где А - значение
п е ременной Fo r e, а В - значение переменной B a c k.
233
Turbo Pascal 7 . 0
Таким образом, получим экран, заполненный идущими подряд строка.\1и:
OjO 1 /0 2/0 и так далее, что означает пулевой цвет на пулевом, первый па
нулевом, второй на нулевом ... пятнадцатый на нулевом, нулевой на первом,
первый на первом ...
ЛИСТИНГ 079. П ЕРЕБОР ВОЗМОЖНЫХ ЦВЕТОВЫХ СОЧЕТАНИЙ В ТЕКСТОВОМ РЕЖИМЕ
Program C o l o r s ; { з а г ол о в о к пр ограммы ,
Uses
CRT ;
{ п одключ ени е модуля CRT }
Var
Fore ,
им я пр ограммы - C o l o r s }
{ н ачал о р а з д ел а п одключения модул ей }
{ н ачало р а з дела опи с ания п ер еменных }
Back :
Byt e ;
{ п ер еменные для исполь з о в ания
в к ач е с т в е счетчик о в }
Begin
{ н ачало р а здела опи с ания л о гики пр о гр аммы }
Text Col or ( Whi t e ) ;
Text BackGround ( Bl a ck ) ;
ClrScr ;
For Back
{ у с т ановка с т андартных цв ет о в для фона и т е к с т а ,
:=
з а т ем очи с т к а экран а }
О То 1 5 Do
{ в н ешний цикл ,
сче тчик цикла опр еделяе т
номер ц в е т а для фона }
For Fore
: =
О То 1 5 Do
{ в лож енный цикл ,
с ч е тчик цикл а опр еделяет
номер ц в е т а для текста }
begin
{ начало з ацикл енн о г о с о с т а вн о г о опера т ор а }
Text Color ( Fore ) ;
TextвackGround ( Back ) ;
{ у с т ан о в к а текущ ег о ц в е т а ф он а и т е к с т а }
Wr i t e ( '
'
Fore ,
'/' ,
Back ,
'
{ вывод с тр оки ,
' )
показыв ающей ,
н а к а к ом ф он е
каким цв е т ом выводятся симв олы }
end ;
ReadKey ;
{ ок онч ание с о с т авного оператор а }
{ пр и о с т ановка пр огр аммы }
тext c o l or ( Whi t e ) ;
Text BackGround ( B l a ck ) ;
C l rS c r ;
{ в о с с т ановл ение с т андартных ц в е т о в и
End .
{ к он е ц р а з д ела опи с ания л о гики пр о гр аммы }
очис тк а экрана }
Глава 7. В етвле н и е и зацикл и вание
КОНТРОЛЬНЫЕ ВОПРОСЫ И ОТВЕТЫ
8
ЧЕМ ЗАКЛЮЧАЕТСЯ ПРИНЦИП СТРУКТУРНОГО ПРОГРАММИРОВАНИЯ?
Путь , п о которо му в ы nолня ется n ро грамм а, о n р еделя ется о n ер атора м и з аци кл и
в а н и я и вет влен ия , и н е котор ы е команды из состава n р ограм м ы м о гут в ооб ще
не и сnол ьзоваться , а н е которы е - и сnол ьзоваться н ескол ько раз . Таки е оn е рато
р ы н азываются структурными , а n рограм м и рован и е с их и с n ол ьзован и е м -
стр уктур н ы м . П р и э то м n р о г р а м м а и м еет одну н ач ал ь ную точ ку (то ч ку входа )
и одну ил и нескол ько кон е ч н ых точ е к ( точ е к выхода) .
КАКИЕ ОПЕРАТОРЫ ВЕТВЛЕНИЯ ПРЕДУСМОТРЕНЫ В TURBO PASCAL?
В Tu rbo Pascal n редусм отре но два о n е ратора ветвлен и я , lf . . . Then . . . Eise и C as e . . .
Else , о б а о н и в своей основе и м е ют некоторое усло в и е (ло гич е с кое в ы раже н и е ) ,
о n редел я ю щее наnравлен и е в ы n ол н е н ия n ро грам м ы . Дан н ы е о n ерато р ы также
назы вают услов н ы м и .
ДАйТЕ КРАТКОЕ ОПИСАНИЕ ОПЕРАТОРА ВЕТВЛЕНИЯ
IF.
Оnер атор lf nозволяет в зав и си м ости от и сти н н ости ил и лож н ости некоторого
усло в и я , в ы nолнить л иб о команду, указанную nосле кл ю ч е вого сло ва The n , л и б о
ком анду, указан ную nосле ключевого слова Else . В качестве в ы nол н я емых в зави
си мости от и сти нности ил и л ожности условия команд можн о ис n ол ьзо вать любые
доnусти м ы е команды Tu rbo Pasca l , в том ч и сле и составн ы е опе ратор ы - несколь
ко команд, объедин е н н ых ключе в ы м и словами begin и end.
ДАйТЕ КРАТКОЕ ОПИСАНИЕ ОПЕРАТОРА ВЕТВЛЕНИЯ CASE.
О п е рато р Case nоз воля ет п рове рить знач е н и е п ереме н н ой на равенство одн о му
из зад ан н ых с п иском значен и й , и в случ ае найд е н н о го соответствия в ы п ол н ить
ко м анду, соответствующую подходя щему знач е н и ю . Е сли з нач е н и е ан ал и з и руе
м о й п е рем е н н ой н е соответствует н и одн о му знач е н и ю и з зад ан н о го сп иска , в ы
n ол н я ется команда, сл едующая п осле кл ючевого слова Else .
Что ИЗ СЕБЯ П РЕДСТАВЛЯЕТ И ДЛЯ ЧЕГО ПРЕДНАЗНАЧЕН ОПЕРАТОР ЦИКЛА foR?
Для ор ган изации повторе н и я некоторой команды , в том ч и сл е и составн о го о n е
ратора, испол ьзуются так называем ы е оператор ы цикла . Есл и дан ную команду
н еобходи м о в ы nолн ить н е кото рое кол ич ество раз , не зави ся щее от событи й , n ро
и сходя щих в нутр и заци кл и ваемо й команды , и сп ользуется о перато р ци кла For. . .
То . . . Do, в ы п олн я ю щи й ф рагмент п рограм м ы с одн о в р е м е н н ы м п оследовател ь
н ы м увел ич е н и ем н екоторой n еременной от н е которого начал ьн о го зн ач е н и я до
н екоторого конечного. Также возможн о и сп ользо ван ие его м одиф и кации , в ы п ол
н я ю ще й ум еньшение пер ем енной - сч етчи ка .
Что ТАКОЕ УСЛОВНЫЕ ОПЕРАТОРЫ ЦИКЛА И КАКИЕ ОНИ БЫВАЮТ В TURBO PASCAL?
Когда о к о н чан и е ц и кл и ческого п овто рен и я ф ра гм ента n р о грам м ы должн о о n ре
дел я ться л о ги кой сам о го фрагм е нта , ис п ол ьзуются усл о в н ы е о n е р ато р ы ци кла ,
235
Turbo Pascal 7 . 0
в которых количество в ы полн ени й заци клен н о й команды заранее н е и з вестно , а за
в е р ш е н и е ци кла определя ется н е которым условием , в кото р о м м о гут использо
ваться п е р е м е н н ы е , изме н я емые в зацикле н н ом фрагменте . Существует два ус
л о в н ых о п ератора ци кла - оператор ци кл а Whi l e . . . Do с п р едусл о в и е м , то есть
осуществля ющи й п роверку необходим ости очередн ого повто р е н ия перед сам и м
п о вторен и е м , и оператор ци кла Repeat . . . Until с постусло в и ем , осуществля ющий
проверку н е обходи мости очередного п о вторения зацикл е н н о й ко манды после в ы
п ол н е н ия п р едыдущего п овторе н ия .
КАКОЕ ПРИМЕНЕКИЕ НАШЛИ ОПЕРАТОРЫ ЦИКЛА В МОДЕЛИРОВАНИИ ЗАДАЧ ( ПРОЦЕССОВ ) ?
Оп е ратор ы цикла и м е ют ш и рокое п р и м ен е н и е в м одел и рован и и задач , анал ити
ч еское решение которых м ожет быть очень сл ожн ы м . П р и этом п р и меня ется оди н
и тот же м етод м одел и рования дл я л юб ых задач - разби е н и е м одели руе мого
п р оцесса н а н есколько шаго в , п р ичем н а каждом шаге п р о цесс с ч итается л и н ей
н ы м , а п р и увел иче н и и кол ичества шагов м одел и руем ый п роцесс стан о вится бл и
з о к к реальному.
МОГУТ ЛИ УСЛОВНЫЕ ОПЕРАТОРЫ И ОПЕРАТОРЫ ЦИКЛА БЫТЬ ВЛОЖЕННЫМИ ДРУГ В ДРУГА?
Ч асто и сп ользуемой особе н н остью усл о в н ых о п ераторов и о п ераторов ци кла я в
л я ется вложен н о сть - возможность использован ия о пе рато р о в ци кла в качестве
зацикл и ваемого други м о ператором цикла фрагмента п р о грам м ы для р е ш е н и я
задач п е р ебо р н ого характера. И спользова н и е вложен ности усло в н ых о п е раторов
позволя ет ре ал изо вать ал горитм ы сложного анализа каких-л иб о параметр о в .
П ЕРЕЧИСЛИТЕ ОСНОВНЫЕ ЗАДАЧИ, ДЛЯ РЕШЕНИЯ КОТОРЫХ ИСПОЛЬЗУЮТСЯ ОПЕРАТОРЫ
ЦИКЛА И ОПЕРАТОРЫ ВЕТВЛЕНИЯ.
Операторы ци кла п р и м е ня ются для орган изации програм м , и м е ю щих меню, с це
л ь ю органи зации заци кл иван ия ме н ю таки м об разом , чтобы разл ич н ы е части п р о
грам м ы в ы полн ял и сь п о запросу пользователя , в ыби рающе го н е обходи м ы е пун к
ты этого м е н ю . В насто я щей главе рассм отр е н ы о с н о в н ы е м етоды движе н ия
объектов по э крану, сам ы м развиты м из которых я вляется о п исание движе н и я
объекта с п о м о щью м атематич еской м одели , в кл ючающей в себя п араметр ы , о п
ределя ющие текущее положен и е объе кта и нап равле н ие е го движе н ия на следую
щ е м шаге движе н ия ( изм е н е н и е коо рдинат о бъе кта) . С п о м о щь ю усл о в н ых о п е ра
то ров в таких задачах можно реал изо вать изм е н е н и е парам етров нап равл е н ия
движе н и я , нап р и м е р , в п р едельн ых экранных коорди натах или п р и каких-ли бо
действиях пользо вател я . С помощью условных о п е раторов ци кла м ожно достаточ
н о п р о сто о п р еделить м ом ент столкн о вен и я двух объектов , что н е обходим о п рак
тически в каждой про грам м е , м одел ирующей некото ры й ф изич ески й п роцесс,
н ап р и м е р , при созда н и и игровых програм м . П р и м е н е н и е операто р о в цикла в м о
дел и рован и и рассмотре н о в одно м из п редыдущих вопросов .
236
Turbo P a s c a l 7 . 0
Движе н и е объекта по экрану
8 . 1 . П РАВИЛ Ь НАЯ О РГАН И ЗАЦ И Я П РО ГРАМ М Ы
В настоящее время пользователи практически всегда имеют возможность
выбратi> из нескольких программ, выполняющих одни и те же функции, ту,
которая по каким-либо причинам нравится им больше всего. Поэтому
каждый вновь создаваемый программный продукт должен быть конку
рентоспособным.
Одним из основных параметров конкурентоспособности программы явля
ется пользовательский интерфейс, так как это первое, с чем сталкивается
пользователь, начиная работу с программой. Если интерфейс неудобен
или непонятен, то пользователь, скорее всего, откажется от работы с такой
программой. Это, конечно, не касается программ, которые являются уни
кальными по выполняемым задачам, так как если программу невозможно
заменить другой, то приходится работать с той, которая есть. Однако при
разработке продукта не следует учитывать этот фактор и создавать менее
к ачественную программу, чем это возможно, так как в любой момент может
появиться аналогичная программа, более удобная пользователю, а отвое
вать место на рынке, конкурируя с хорошим программным продуктом, к ко
торому пользователи уже привыкли, очень тяжело.
В качестве примера можно привести операционную систему O S/2, которая
начинала создаваться совместно фирмами Microsoft и IBM, а затем разви
валась только фирмой IBM. Основной конкурент этой операционной сис
темы
Microsoft Windows, которая довольно долгое время (до появления
Windows 2000) уступала по возможностям IВМ OS/2. Однако использова
ние OS/2 является более сложным, чем использование Windows, поэтому
подавляющее большинство пользователей во всем мире предпочитают ра
ботать именно с Windows, а не 0Sj2.
-
237
Turbo Pascal 7 . 0
П РИМЕЧАНИЕ.
На са м о м деле, неудобство и нтерфейса - н е еди нств е н н ы й и н е главн ы й факто р ,
о n ределя ющи й малую исnол ьзуемость 05/2. Скорее всего, гла в н ой n р и ч и н ой я в
ля ется б о л е е интен с и в н о е n р одвижен и е ф и р м о й Microsoft с воей о n ерацио н ной
си стем ы н а р ы н к е , одн и м из м етодов кото р ого было созда н и е м н ожества n р о
грам м н ых n р одукто в , н е обходи м ых nользователя м .
Так ая ж е ситуация наблюдается с операционной системой UNIX. Раньше
UNIX считалась профессиональной системой. При этом она имела неудоб
вый пользовательский интерфейс, малое количество программ, необходи
мых пользователю для работы, и подразумевала глубокую подготовку поль
зователя. Сейчас UNIX обладает всем необходимым для работы обычного
пользователя, но все уже привыкли к Windows. Соответственно, чтобы пе
рейти па UNIX, в ней должно быть что-то такое, что заинтересует пользова
телей настолько, чтобы отказаться от привычной рабочей среды.
В условиях рыночной экономики никто не может навязать пользователю
использование конкретного программнога продукта - неважно, операци
онной системы, текстового редактора или какого-либо другого. Пользова
тель практически самостоятелен в своем выборе. При этом недостаточное
распространение программнога продукта не принесет разработчику ожида
емой прибыли или даже не покроет затрат на разработку. Соответственно,
тот, кто пишет �плохие� программы, не будет иметь возможность улучшать
их впоследствии. Таким образом, программный продукт должен отвечать
самым высоким требованиям уже на этапе разработки.
П РИМЕЧАНИЕ.
В дан н о м случае, «nлохие» означает «Не н ра в я щиеся nользователю » , то есть оцен
к а довол ь н о субъекти в н а . Можн о создать замечательную nр огра м м у, удобную во
в сех отн о ш е н иях, n олностью в ы n олня ющую свои фун кци и , н о о на н е n о н равится
n ол ьзовател я м . П р и этом н е качеств е н н ы й nр одукт м ожет по каким - л и бо n р и ч и нам
nользо вателя м нравиться .
Понимание того, какой должна быть программа, приходит с опытом. А пока
рассмотрим основные требования, которым должна отвечать любая про
грамм а того уровня, которого мы достигли на данный момент.
1. Исполнение програ.i\1МЫ в графическом режиме в большинстве случа
ев предпочтительнее, чем в текстовом. Иногда, в свяэи с невозможнос
ТЪЮ в графическом режиме экрана ввести стандартными процедурами
числовое или строконое значение, некоторые программы переключа
ют на время ввода экран в текстовый режим. Такой подход совершен
но недопустим, так как занимает на новых мониторах значительное
время, имеет неприяrnые визуальные эффекты и издает на некоторых
мониторах довольно резкий звук. Как организовать ввод персменных
любого типа в Iрафическом режиме, мы рассмотрим ниже.
238
Глава 8 . Движен и е объекта по экрану
2. Программа должна использовать цвета, не утомляющие пользова
теля. Этот вопрос уже обсуждался нами выше.
3. Выбор разрешения графического режима должен определяться
не желанием программиста показать свои знания, а исключитель
но функциональностыо программы. Данный вопрос также уже
рассмотрен нами при изучении многоцветных графических режи
мов. Вообще использование любых атрибутов и элементов в про
грамме должно отвечать принципу сНеобходимость и Достаточ
ность�. то есть программа должна делать все то, что от нее
требуется, и при этом не делать ничего лишнего.
4. При построении интерфейса должен использоваться язык, родной
для пользователя. Наверняка большинство российских пользовате
лей хочет работать с программой на русском языке, а не па английс
ком, и тем более, не на китайском. То же можно сказать и про китай
ских пользователей - им не подходит програ.."\lма на русском языке.
5. Программа обязательно должна иметь справочную систему (в ка
ком-либо виде). Если программа невелика, то отдельной спра
вочной системы ей не нужно. Однако пользователь в любой мо
мент своей работы должен четко нанимать, каких действий
требует от него программа. В качестве примера можно привести
игру-эмулятор полета, в которой неясна задача, либо методы уп
равления самолетом - использование такой программы невоз
можно, а значит, долгий труд разработчиков пропал даром.
6. Практически любая программа должна иметь главное меню, появ
ляющееся сразу же после запуска программы. Выход из программы
после завершения работы с нею, должен производиться пользовате
лем осознанно, с использованием этого же меню.
Существует еще множество требований, накладываемых на программы. На
пример, если в программе используется звук, то должна быть возможность
его отключения - некоторые пользователи любят работать в тишине. Уни
версальных правил создания привлекательных программ не существует,
поэтому, когда необходимо сделать выбор между несколькими вариантами
реализации одной и той же возможности, руководствоваться следует ис
ключительно здравым смыслом.
Обратим внимание на последние два пункта списка. Итак, в начале работы
программы должно появляться меню, а выход из программы должен осу
ществляться при выборе одного из его пунктов. Реализуем программу в гра
фическом режиме, основной ее частью будет оператор цикла Repea t
Until, зацикливающий следующие действия:
•
очистка экрана;
. . .
•
вывод меню (списка возможных действий) и подсказки пользова
телю, какими клавишами он может воспользоваться для выбора
пунктов меню;
239
Tu rbo Pascal 7 . 0
ожидание нажатия на клавишу;
•
анализ пажатой клавиши с помощью условного оператора множес
твенного выбора C a s e , и выполнение действий, соответствующих
выбранному пупкту.
•
Меню будет состоять из трех пунктов
(см. рис. 1 0 1 ):
1 . Игра.
2. Помощь.
3. Выход.
Выбор пункта меню должен происхо
дить нажатием клавиши, соответствую
щей номеру пункта (то есть для выбора
первого пункта следует нажать клави
шу 1, для второго - 2, для третьего - 3).
Рис. 1 0 1 . Главное меню
программы Ма iпМе пи
При выборе пункта 1 ( •Игра>> ) на экране будет появляться надпись •Игра»
и предложение нажать для продолжения любую клавишу (см. рис. 1 02).
После нажатия пользователем клавипш программа возвращается обратно
в главное меню.
При выборе пункта 2 ( •Помощьi>) на экране будет появляться надпись
•Помощь>.> и предложение нажать для продолжения любую клавишу (см.
рис. 1 03). После нажатия пользователем клавиши программа возвращается
обратно в главное меню.
Рис. 1 03. Результат выбора
Рис. 1 02. Результат выбора
пункта м еню «Помощь"
пункта меню «Игра »
Л ИСТИНГ
080. ОРГАНИЗАЦИЯ РАБОТЫ
Program Mainмenu ;
Uses
CRT ,
Var
240
Graph ;
С ПРОГРАММОЙ
ЧЕРЕЗ ГЛАВНОЕ МЕНЮ
Глава 8 . Движе н и е объекта по э крану
Gd , Gm : Intеgеr ; { п ер еменные для передачи процедур е I n i tGraph }
Ch :
Char ;
{ пер еменная для хр ан ения нажатой кл а виши }
Begin
Gd
: =
Det e c t ;
Gm
: =
О;
Ini tGraph ( Gd ,
Gm ,
' ' ) ;
{ иници али з ация графич е с к о г о р ежима }
Repeat
{ н ачало г ла вно го цикл а }
S e t BkCo l o r ( DarkGray ) ;
SetColor ( Whi t e ) ;
C l e arDevi c e ;
{ у с т ан о в к а цв е т а фона и симв о ло в и очи с т к а э крана }
S e t Text S tyl e ( Tripl exFont ,
S e tText Ju s t i fy ( Left Text ,
Hori z Di r ,
б) ;
TopText ) ;
outтextXY ( 1 2 0 ,
120 ,
'1.
Игра ' ) ;
OUtTextXY ( 1 2 0 ,
170 ,
'2.
Помощь ' ) ;
outтextXY ( 1 2 0 ,
220 ,
'3.
выход ' ) ;
{ вывод пункто в меню }
S e t Text S tyl e ( Smal l F ont , Hori z Di r ,
SetтextJu s t i fy ( Ri ghtText ,
б) ;
Bott omтext ) ;
OUtTextXY ( б 3 9 , 4 б 9 , ' для выбора нужного пуик'J;'а иажии 'l' е 1 , 2 или 3 ' ) ;
{ вывод подска з ки о клавишах }
Ch
: =
ReadKey ;
{ анали з нажатой кла в иши }
C a s e Ch O f
'1' :
{ о жидание нажатия на кл а вишу }
Ьegin
{ е сли нажата клавиша 1 ,
то в ы в о дим с л о в о «И гр а »
и п о д с к а з ку о н е о бходимо с ти н а ж а т ь лю бую кл а в ишу }
C l earDevi c e ;
S etтextStyl e ( Trip l exFont ,
SetтextJu s t i fy ( Cent erText ,
OutтextXY ( 3 2 0 ,
240 ,
10 ) ;
Cent erтext ) ;
' Игра ' ) ;
S etTextStyl e ( Sma l lF ont ,
Hori zDir ,
S e tTextJu s t i fy ( Ri ghtText ,
OutтextXY ( б 3 9 , 4 б 9 ,
Hor i z D i r ,
б) ;
Bottomтext ) ;
' для продолжения иажии'l' е любую клавишу ' ) ;
ReadKey ;
end ;
'2' :
Ьegin
{ е сли нажата клавиша 2 ,
т о в ы в о дим с л о в о
«Помощь» и подска з ку о н е о бходимо сти н а ж а т ь
лю бу ю кл а в ишу }
C l e arDevi c e ;
S e t Text Styl e ( Tripl exFont ,
SetTextJu s t i fy ( Cent erтext ,
OutTextXY ( 3 2 0 ,
240 ,
10 ) ;
C ent erText ) ;
' Помощь ' ) ;
Setтext S tyl e ( Sma l 1 Font ,
Hor i z D i r ,
SetTextJu s t i fy ( Ri ghtText ,
Out TextXY ( б 3 9 , 4 б 9 ,
Hor i zDir ,
б) ;
Bottomтext ) ;
' Для продолжения иажии 'l' е любую клавишу ' ) ;
ReadKey ;
end ;
end ;
Unt i l Ch
' 3 ' ; { у сл о в и е выхода из цикл а }
End .
24 1
Turbo Pascal 7 . 0
8 . 2 . О РГАН И ЗАЦИ Я ДВ ИЖЕН И Я О БЪЕКТА П О Э КРАНУ
8 . 2 . 1 . П ЕРЕМЕЩЕНИЕ ОБЪЕКТОВ
Мы уже рассматривали программу, которая имеет возможность передви
гать объект по экрану. Однако методы движения, использованные в ней,
настолько примитивны, что даже не поддаются улучшению. Сейчас мы рас
смотрим, как правильно организовать движение объекта по экрану.
В основе любого движения лежит изменение некоторых параметров. Оче
видно, что для объекта, находящегося на экране, основными параметрами
будут его координаты х и У. Движение объекта можно задать двумя путями:
-
1.
Траекторией движения объекта, то есть последовательности его
координат (XI' У1), (Х2, У2), (Х3, У3)
(Xn, У0). С помощью такого
метода можно задать, например, траекторию движения часового в
тактической военной игре, передвигающегося по отрезку прямой
сначала в одну сторону, а потом обратно.
•••
2.
Смещением координат в единицу времени. Для этого используют
ся две дополнительные переменные: dX для определения необхо
димого смещения по горизонтали (изменения координаты Х объек
та) и dY для определения необходимого смещения по вертикали
(изменения координаты У объекта). А для того, чтобы произвести
персмещение объекта используется пара операторов присваивания:
-
-
Х
У
: =
Х
+
dX ;
: = У + dY .
Рассмотрим пример программы, персмещающей символ из левого верхнего
угла экрана под углом 45° вниз и вправо на десять шагов (см. листинг 0 8 1 ) .
Для этого используем оператор цикла For, причем персменная-счетчик и
будет задавать очередные координаты объекта (так как объект смещается
под углом 45°, то горизонтальная координата будет равна вертикальной, по
этому для зад а ния обеих координат достаточно всего одной переменной).
Л ИСТИНГ 081 . ДВИЖЕНИЕ ОБЬЕКТд ПО ЗАДАННОЙ ТРАЕКТОРИИ
Program MoveObj e c t 1 ;
Uses
CRT ;
Var
ХУ :
Byt e ;
{ п ер еменн а я ,
опр еделяющ а я к о ордин а ты о бъе к т а )
Begin
C l rS c r ;
For Х У
: =
1 т о 1 0 Do
{ оп ер а т ор цикл а дл я и змен ения к о ордин а т о б ъ ект а )
242
Гл ава 8 . Движе н и е о бъекта по э крану
{ начало з ацикл енн о г о с о с т а вн о г о оп ер а т ор а }
Begin
GotoXY ( XY , ХУ ) ; { по з иционир о в ани е к ар етки }
Wri t e ( ' * ' } ;
{ выв од о бъ екта }
end ;
{ оконч ани е з ацикл енн о г о оп ератор а }
End .
Таким образом, персменная-счетчик цикла последовательно изменяется от 1
до 1 О, соответственно, задавая пары координат объекта ( 1 , 1 ) , (2, 2) ... ( 1 О, 1 0).
На каждом Iпare цикла объект (символ * ) выводится в новые координаты.
Скорее всего, само движение б удет незаметно в сил у высокой скорости пе
ремещения. Поэтому можно воспользоваться процедурой Del.ay модуля
C RT , приостанавливающей программу на количество миллисекунд, задан
ное в качестве ее параметра:
D е l ау ( < Вр емя з адержки > ) ;
Соответственно, чтобы смещение объекта происходило примерно раз в се
кунду, необходимо перед каждым выводом объекта вызывать процедур у за
держки, задавая параметр Вреия з адержки, равный 1 000 миллисекунд
(см. листинг 082 ) .
Л ИСТИНГ 082. ДВИЖЕНИЕ ОБЪЕКТА П О ЗАДАННОЙ ТРАЕКТОРИИ . ИСПОЛЬЗОВАНИЕ ЗАДЕРЖКИ
Program Move0bj ec t 2 ;
Us e s
CRT ;
Var
ХУ :
Byt e ;
{ п ер еменная с имен ем ХУ ,
опр еделяющая
ко ординаты о бъ екта }
Begin
ClrScr;
For ХУ
: =
1 То 1 0 Do
{ оператор цикл а для измен ени я к о ордин а т о бъ екта }
Begin
{ начало з ацикл енн о г о с о с т а в н о г о оператор а }
D e l ay ( 1 0 0 0 ) ;
{ з ад ержк а на 1 с екунду
( 1 0 0 0 миллис екунд } }
GotoXY ( XY , ХУ ) ; { по з иционир о в ание к ар е тки }
{ вывод о бъ екта }
Wri t e ( ' * ' ) ;
end ;
{ окончани е з ацикл енн о г о оператор а }
End .
В рассмотренной программе есть несколько недостатков. Во-первых, объ
ект оставляет за собой след. Такая проблема легко решается стиранием
объеi<та в предыдущих координатах перед его очередным выводом (выво
дом пробела на его место в текстовом режиме, или закрашенного прямо
угольника в графическом). Во-вторых, такая схема движения объектов не
подразумевает его взаимодействия с другими объектами и пользователем,
так как последовательность координат жестко задается оператором цикла
243
Turbo Pascal 7 . 0
и не может быть изменена до завершения цикла. Эта проблема достаточно
серьезна и заставляет в большинстве случаев вообще отказаться от такой
схемы движения.
Более развитым методом персмещения объекта является задание траекто
рии движения через дополнительные параметры, определяющие изменение
координат объекта на каждый шаг его перемещения. Рассмотрим персме
щение объекта таким методом с двух точек зрения - персмещение объекта
вследствие управления им пользователем и самостоятельного персмещения
объекта по заданным правилам.
Рассмотрим рис. 1 04. На нем изображен некоторый объект (показан чер
ным прямоугольником), находящийся в точке с координатами (Х, У). Ха
рактеристиками движения объекта являются смещения по горизонтальной
и вертикальной осям - dX и dY. Если с иското
рой периодичностью стирать объект, изменять
dХ
dY
(Х, У )
его координаты Х и У на, соответственно, dX и dY,
га затем снова выводить объект n точку с уже из
мененными координатами (Х, У), то будет полу
�'.,J
чен эффект движения объекта по экрану. На пер
вом шаге такого процесса объект персместится
(X+dX, Y+dY)
в положение, показаинос пунктирным прямоРис. 104. Модель
угольником, затем будет двигаться вдоль пункдвижения объекта
тирной линии.
'
г
,,
',
,
,
"
�-
',,
Покажем такое движение на примере. Опишем персменные х, У , dX и dY и
присвоим им начальные значения: Х = 1 0 , У = 1 0 , dX = 1 , dY = 1 . Таким
образом, начальная точка движения объекта имеет координаты (X= l O ,
Y= l O ) , направление движения объекта - вправо и вниз, а з а каждый шаг
движения объект смещается па одну точку вправо и па одну точку вниз. На
каждом шаге объекта программа будет ожидать нажатия на клавишу, и за
вершится, когда будет нажата клавиша Q. Соответственно, движение долж
но быть организовано с помощью условного оператора цикла Repea t . . .
Until, который закончится, когда переменная, в которой находится значе
ние последней нажатой пользователем клавиши, будет иметь значение ' Q '
(см. листинг 083).
ЛИСТИНГ 083. ДВИЖЕНИЕ ОБЪЕКТА, ЗАДАННОЕ ПАРАМЕТРАМИ
Program MoveObj e c t З ;
Uses
CRT ;
var
Х, У,
dX ,
dY :
Int eger ;
{ n еременные ,
оnределяющи е nоло ж ение и
наnр а в л ени е движ ения о бъек т а }
Ch :
244
Char ;
{ n еременная для хр анения н а ж атой кл а виши }
Глава 8 . Движени е объекта по экрану
Begin
C l rS c r ;
х
у
: =
10;
:=
10;
dX
1;
:=
dY
1;
:=
{ прис в о ение начальных з н а ч ений пар аметрам
о бъект а )
Repeat
{ оп ера тор цикл а для мн о г ократн о г о
п о в т ор ения фрагмента пр о гр аммы }
Got oXY ( X ,
Wri t e ( '
х
х
: =
У
У
: =
У) ;
) ;
'
+
dX ;
+
dY ;
{ по з иционир о в ание каретки }
{ с тир ание о бъе кта }
{ и зменени е ко ордина т о бъ екта с у ч е т ом параметров
dX и dY ,
Got oXY ( X ,
У) ;
Wr i t e ( ' * ' ) ;
Ch
: =
{ в ы вод о бъекта в н о в о е положени е )
ReadKey ;
Unt i 1 Ch
=
опр ед еляющих напр а в л ение движ ения }
{ по з иционир о в ание к ар етки }
{ ожидание н а ж атия на к л а в ишу }
'Q' ;
{ у с лови е выхода и з цикл а }
End .
И так, объект движется вправо вниз до тех пор, пока пользователь н е нажмет
клавишу Q. Начиная с пекотарого места, координаты Х и У начнут превышать
значения, допустимые для экранных координат. Для того чтобы объект не
перемещался за пределы экрана, следует изменить траекторию его движения
при приближении к нижней части экрана. То есть, когда объект имеет коор
динату по оси У большую или равную 24, направление его движения нуж
но изменить. Например, задать параметры изменения координат, равными
dX :
1 (вправо), dY :
- 1 (вверх). На экране это будет выглядеть как
отражение объекта от нижней части экрана под углом 90" (см. рис. 1 05).
=
=
Данное изменение параметров движения должно происходить в том же са
мом цикле, где реализовано само движение, и наиболее удачное место для
тан:ой проверки - перед фрагментом программы, в котором происходит из
менение координат Х и У (см. листинг 084).
Л ИСТИНГ 0 8 4 . ДВИЖЕНИЕ ОБЪЕКТА, ЗАДАННОЕ ПАРАМЕТРАМИ
Program Move0bj e c t 4 ;
Uses
CRT ;
Var
Х, У,
dX ,
dY :
Int eger ;
{ п ер еменны е ,
определяющи е п о л о ж ение и
напр а в л ение движ ения о бъ ек т а )
Ch :
Char ;
{ пер еменная для хр ан ения н а ж а т о й к л а в иши )
Begin
C l rS c r ;
х
: =
10;
245
Turbo Pascal 7 . 0
у
10;
: =
dX
:=
1;
dY
:=
1;
{ при с в о ение нача льных з начений п ар аметр ам объект а }
{ оп ер а т ор цикл а для мног окр ат но го п о в т ор ения
Repeat
фр агмент а пр о гр аммы }
If У
2 4 Then dY
=
:=
-1;
{ и зменение н апр авл ения движ ения о бъ е к т а в
случ а е ,
е сли он д о с тиг нижней гр аницы экр ана .
Пар аметр dX не и зменя ет с я
Got oXY ( X , У ) ;
{ п о з иционир о в ание кар е тки }
Wri t e ( '
{ с тир ание о бъект а }
) ;
'
Х
: =
Х
+
dX ;
У
: =
У
+
dY ;
У) ;
Wr i t e ( ' * ' ) ;
Ch
рис .
105 ) }
{ и зменение координат о бъ е кта с у ч е т ом параметр о в
d X и dY ,
Got oXY ( X ,
( см .
определяющих направл ение д в и ж ения }
{ по з иционир о в ание кар е тки }
{ вывод о бъект а в но в о е полож ение }
ReadKey ; { ожидание наж атия на кла вишу }
: =
Unt i 1 Ch
=
' Q ' ; { у с л о в и е выхода и з цикл а }
End .
Теперь, когда объект будет находиться в нижней строке экрана, произойдет
смена направления его движения (обусловленная выполнением оператора
присnаивания dy : = - 1 ) , и объект начнет двигаться
/ '
вправо и вверх. Б результате такого движения ко
"
�', ,'dx
/
ординаты объекта опять выйдут за допустимые пре
L1
делы - объект будет пытаться выйти за верхнюю
часть экрана. Для того, чтобы этого не произошло,
необходимо изменить направление движения объ
/Траектория движения
екта (см. рис. 1 06), присвоив параметру dY другое
Рнс. 1 06 . "О тражение "
значение: dY :
1 . Таким образом, в цикле, оргаобъекта от верхней
низующем движение объекта, появится еще один
части экрана
условный оператор I f:
=1
dY = -1
dY = 1 ',
j'dX =
'·
=
If У
1 Then dY
=
:= 1;
Однако не будем торопиться и посмотрим, как можно упростить програм
му. При касании объектом нижнего края экрана, параметр dY изменяется
с 1 на 1 а при касании верхнего края экрана, параметр dY изменяется
с - 1 в 1 . То есть можно сказать, что при касании объектом нижней или
верхней границы, параметр dY должен изменять свое значение на проти
воположное:
-
If
(У
,
=
24 )
OR
(У = 1 )
Then d Y
: =
- dY ;
Н етруд п о заметить, что при выбранном н ами п р авиле отражения объ
екта от краев экрана (угол п адения равен углу отражени я ) , необходи
мо изменять только параметр движения dY, а пар аметр dX остается
246
Гл ава 8 . Движен и е объекта по экрану
неизменным, вне зависимости от направления
движения объекта. Аналогичным об р а з ом реша
ется проблема превышения допустимых значений
горизонтальной координаты объекта (см. рис.
1 07 ) : для того, чтобы • оттолкнуть� объект от вер
тикальных к ра е в экрана, следует просто изменить
параметр, определяющий горизонтальное смеще
ние объекта:
(Х
If
=
OR
79 )
(Х
=
Then dX
1)
dY = -\_
tdY = -1
_ / 4 dX = 1 dX = -1...J,
,'
'
', dY = -1
::1
dX = -1
'
,,
dY = -1 ,'
'
�
dX = 1
Рис. 1 07. "Отражение "
о бъекта от боковых
частей экрана
- dX ;
: =
Итак, п р авильный вариант проrраммы, в которой движу1.цийся объект
не может выйти за пределы экрана выглядит так, как это показано в лис
тинге 085.
ЛИСТИНГ 085. ДВ ИЖЕНИЕ ОБЬЕКТА, ЗАДАННОЕ ПАРАМЕТРАМИ . ЗЕРКАЛЬНОЕ ОТРАЖЕНИЕ О Т КРАЕВ
Program MoveOb j e c t 5 ;
Us e s
CRT ;
Var
Х,
У,
dX ,
dY :
Int e ger ;
{ п ер еменные ,
опр еделяющи е положение и
напр а в л ение движ ения объект а }
Ch :
Char ;
{ п ер еменная для хран ения н а ж а т ой клавиши }
Begin
ClrScr ;
х
у
: =
10;
: =
10;
dX
:=
1;
dY
: =
1;
{ при с в о ение нач альных значений пар аметр ам объект а }
Repeat
{ оператор цикла для многокр а т н о г о п о в т о р е ния
фр агмента программы }
If
(У
24 )
OR (У
=
1)
Then dY
:=
-dY ;
{ и зменение напр а в л ения движ ения о бъ е к т а
в с луча е ,
If
(Х
79)
е сли он д о с тиг нижн ей границы экрана .
Пар аметр dX не и зменя е т с я }
OR ( Х = 1 ) Then dX : = - dX ;
{ и зменение напр а в л ения движ ения о бъ е к т а
в случа е ,
е с л и он д о с тиг нижн ей границы экрана .
Пар аметр dX не изменя е т с я }
Got oXY ( X ,
Wri t e ( '
х
У
·
-
: =
У) ;
' ) ;
х + dX ;
У
+
dY ;
{ по з ициониров ание каре тки }
{ с тир ание о бъект а }
{ изменение ко ординат о бъекта с у ч е т ом параметр о в
dX и dY ,
Got oXY ( X ,
У) ;
Wri t e ( ' * ' ) ;
опред еляющих напр а в л ение движ ения }
{ по зиционир о в ание кар е тки }
{ вывод объекта в н о в о е положени е }
247
Turbo Pascal 7 . 0
Ch
: =
ReadKey ; { ожидание наж а тия на кла вишу }
Unt i l Ch
=
' Q ' ; { у с л овие в ыхода из цикл а }
End .
Вернемся к теме мигающего изображения на экране. В данной программе
изображение не мигает из-за использования текстового режима, малого
размера самого изображения (всего один символ) и больших пауз между
передвижениями объекта (ожидание нажатия на клавишу). Однако про
грамма содержит фрагмент, в котором существует вероятность появления
мигания. Это та часть программы, которая выполняется, когда объект уже
удален с ЭI<рана, но еще не выведен в новом положении.
В данном случае между удалением и новым выводом объекта выполняется
всего два оператора присваивания, что практически гарантирует отсутствие
мигания изображения, даже в случае использования графического режима
и объектов средних размеров.
8 . 2 . 2 . УПРАВЛЕНИЕ ПЕРЕМЕЩЕНИЕМ О&ЪЕКТОВ
ФУНКЦ ИЯ KEYPRESSED
Все программы, которые мы рассматривали до этого, для выяснения наме
рений пользователя использовали функцию ReadКey модуля CRT, позво
ляющую занести в символьную персменную значение, соответствующее
нажатой пользователем клавише. Однако для этого программа должна при
остановиться, в результате чего прекращается движение объектов, что недо
пустимо для некоторых задач.
Для решения этой проблемы в модуле CRT предусмотрена функция
KeyPressed ( англ. Кеу Is Pressed - клавиша нажата) без параметров,
определяющая была ли нажата клавиша. Эта функция возвращает значе
ние типа T r u e в случае, если клавиша нажата, и F a l s e - если клавиша
не нажата:
Key P r e s s e d ;
Таким обрааом, если в программе нежелатсльна пауаа при считывании на
жатой клавиши, можно не считывать ее, если значение, возвращаемое фун
кцией KeyPres sed ложно. Для того, чтобы считывать значение нажатой
клавиши, можно воспользоваться следующей конструкцией:
If
Key P r e s s e d Then Ch
: =
R e a dKey ;
Изменим предыдущий пример так, чтобы объект перемещался по экрану
самостоятельно, пока пользователь не пажмет клавишу Q (см. листинг 086).
Для этого воспользуемся вышеприведенной конструкцией.
248
Глава 8. Движе н ие объекта по экрану
Л ИСТИНГ 086. ДВИЖЕНИЕ ОБЪЕКТА, ЗАДАННОЕ
ПАРАМЕТРАМИ
Program MoveObj e c t б ;
Uses
CRT ;
Var
Х, У,
Ch :
dX ,
dY :
Int e ge r ;
Cha r ;
Begin
ClrScr;
х
у
: =
10;
:=
10 ;
dX
: =
1;
dY
: =
Ch
: =
1;
, , .
,
Repeat
{ nрис в о ение начального з нач ения n ер еменной Ch }
If
(У
=
24 )
OR
(У
1)
Then dY
: =
- dY ;
If
(Х
=
79)
OR
(Х
1)
Then dX
: =
- dX ;
Got oXY ( X , У ) ;
;
Wri t e ( 1 1 )
х
У
: =
: =
х
У
+
dX ;
+
dY ;
Got oXY ( X 1 У ) ;
1
Wr i t e ( 1 * ) ;
De l ay ( 1 0 0 0 ) ;
{ nо с л е вывода объекта - n ау з а н а 1 с екунду }
I f KeyPre s s ed Then Ch
: =
ReadKey ;
{ значение нажатой клавиши оnред еля е т с я только
в том случае ,
е сли кл а в иша нажата ,
ожидание
наж атия н е nрои з в одит ся }
Unt i l Ch
=
1
Q'
;
End .
При отсутствии ожидания нажатия клавиши в программе понадобилось
еще несколько изменений. Во-первых, объект стал передвигаться по экра
ну слишком быстро, поэтому после его вывода мы используем процедуру
задержки Del.ay. Параметр процедуры задан таким ( 1 00 0 миллисекунд),
что задержка будет длиться около секунды.
ПРИ МЕЧАНИЕ.
На новых машинах с высокой производительностью процедура Delay м ожет ра б о
тать некорректно, поэтому значение параметра данной процедуры иногда прихо
дится увеличивать, например, до 1 0000.
Заметим, что процедура задержки не должна вызываться в тот момент, ког
да объект уже стерт с экрана, по еще не выведен на него, иначе соотношение
времени присутствия и отсутствия объекта на экране будет таким, что поль
зователь не увидит объект вообще.
249
Turbo Pascal 7 . 0
Во-вторых, при такой организации программы, как минимум во время пер
вого прохода цикла, пользователь не успеет нажать на клавишу, а значит
персменная Ch будет содержать значение, полученное в начале программы.
Так как память выделяется программам по очереди, то паша программа для
храпения персменных может получить сегмент памяти, в котором уже иахо
дятся какие-либо данные , оставп.тиеся от ранее выполпявп.rихся программ.
Мы уже обсуждали данную проблему, и говорили, что все персменные тре
буют инициализации (присвоения начальных значений) в начале програ.'\f
мы. В качестве инициализации переменной Ch использовано присвоение
Ch :
' . Если такого присвоения не произнести, то значение перемен
ной Ch может быть любым, например, ' Q ' , что повлечет за собой выход
из программы после первого прохода цикла, хотя пользователь еще не на
жал на соответствующую клавишу. Самое страшное в подобных ошибках их дина.'\fическая природа, то есть программа может быть тщательно протес
тирована и запущена сотню раз, а данная ошибка появится на сто первый.
=
УПРАВЛЕНИЕ ОБЪ Е КТАМИ
Для управления персмещением объеr<тов можно использовать клавиату
ру, причем движение управляемого объекта строится по той же схеме, что
и свободное движение, рассмотренное нами ранее. На рис. 1 08 изображен
объект, имеющий координаты Н и v.
П РИМЕЧАНИЕ.
М ы целенаправленно используем здесь о бозначения Н , V. d H и dV, а не Х, У, dX и dY,
как в предыдущих при мерах, чтобы nри дал ьнейшем объединении программ с раз
н ы м и объектами не возникла проблема пересечения имен переменных.
Направление его движения задается дополнительными параметрами dH
(изменение горизонтальной координаты) и dV (изменение вертикальной
координаты). Обычно объекты, управляемые пользователем, должны пере
меi.цаться по экрану либо в горизонтальном, либо в вертикальном направле
нии, поэтому в каждый момент времени один из параметров dH и dV должен
равняться нулю. В начале программы оба параметра нулевые, поэтому объ
ект не перемещается, затем пользователь может нажимать на какие-либо
клавиши, в результате чего будут изменяться параметры dH и dV, вызывая,
соответственно, персмещение объекта.
Основа такого движения - зацикливание фрагмента программы, выполня
ющего следующие действия:
1 . Чтен ие символа, соответствующего н ажатой пользователем клавипrе.
2. Анализ нажатой клавиши. Для управления объектом будем ис
пользовать клавиши: а - смещение влево, s - смещение вправо,
250
Гл ава 8 . Движе н и е объекта по экрану
смещение вверх и z смещение вниз. Для персмещения объ
екта необходимо изменить параметры смещения dH и dV следую
щим образом:
w
-
-
•
нажата клавиша а: dH
смещаться);
•
нажата клавиша
смещаться);
•
нажата кл:авиша w: dH
dV
-1 (вверх);
-1 (влево), dV
1 (вправо), dV
dH
s:
О (по вертикали не
=
О (по вертикали не
О (по горизонтали не смещаться),
=
•
нажата клавюна
dV
1 (вниз).
z:
dH
=
О (по горизонтали не смеiцаться),
=
3. Стирание объекта в текущих координатах Н и v.
4. Изменение текущих координат Н и V:
Н
:
=
Н
+
dH, V
:
=
V
+
dV.
5. Вывод объекта в новых координатах.
Текст программы приведен в листинге 087.
Л ИСТИНГ 087. ДВИЖЕНИЕ ОБЪЕКТА. РЕАЛИЗАЦИЯ НЕПРЕРЫВНОГО УПРАВЛЕНИЯ
Program MoveObj e c t 7 ;
Uses
CRT ;
Var
Н, v,
dН ,
dV :
Int e ger ;
{ пар аме тры о бъекта }
Ch :
Cha r ;
Begin
C l rS c r ;
н
: =
v
10;
: =9 9 9 9
dH
:=
О;
dV
: =
О;
Ch
: =
'
10;
'
;
{ инициализ ация n араметр о в }
Repeat
I f KeyP re s s e d Then Ch
: =
ReadKey ;
{ считыв ание нажатой клавиши ,
c a s e Ch O f
е с ли она нажата }
{ анализ нажатой кла виши }
begin
'а' :
dH
: =
-1;
dV
:=
О;
end ;
's' :
begin
dН
: =
1;
dV
:=
О;
25 1
Turbo Pascal 7 . 0
end ;
'w' :
begin
dН
: =
О;
dV
: =
-1;
end ;
'z' :
begin
dН
: =
О;
dV
: =
1;
end ;
end ;
Got oXY ( H , V ) ;
Wr i t e ( '
н
н
: =
V
V
: =
' ) ;
+
dН ;
+
dV ;
{ удаление о бъект а }
{ и змен ени е т е ку щих к о ордина т )
Got oXY ( H , V ) ;
Wri t e ( ' * ' ) ;
{ вывод о бъект а в н о в о е по л о ж ение и пауз а )
' Q ' ; { у с л о вие з а в ершения цикла }
De l ay ( 1 0 0 0 0 ) ;
Unt i l Ch
=
End .
Движение объекта в данной программе является непрерывным, то есть
после того, как направление движения изменено, объект начинает двигать
ся и изменяет направление только после очередного нажатия на клавишу.
Непрерывность движения основана на том, что после нажатия на клавишу
ее значение заносится в персменную Ch и остается там до тех пор, пока не
будет нажата другая клавиша.
Однако выполнение цикла в это время продолжается, выполняется опе
ратор множественного выбора, устанавливающий параметры dH и dV (все
время одни и те же), а также на каждом шаге происходит приращение ко
ординат Н и V. Если движение объекта не должно быть непрерывным, то
можно изменить программу следующим образом (см. листинг 088):
1. Если клавиша не нажата, присваивать переменной Ch какое-либо
нейтралъное значение, например, пробел.
2. В анализ значения переменной Ch добавить обнуление персменных
dH и dV в случае, если персменная Ch имеет данное значение.
ЛИСТИНГ 088. ДВИЖЕНИЕ ОБЪЕКТА, УПРАВЛЯЕМОЕ ПОЛЬЗОВАТЕЛЕМ
Program MoveObj e c t 8 ;
Uвев
CRT ;
Var
Н, v,
Ch :
Begin
ClrScr ;
252
dН ,
Char ;
dV :
Int e g e r ;
Глава 8 . Движе н ие объекта по э крану
н : = 10;
v
10;
:=
. -
О;
dV : =
О;
Ch
1
dH
:=
1;
Repeat
If KeyPre s s ed
Then Ch
: = ReadKey
E l s e Ch : =
1
{ считыв ание нажатой кла виши , е сли о н а н а ж а т а }
1 ; { е сли клавиша не нажата , n ер еменной Ch
при с в аи в а е т ся знач ение nро б ел }
Ca s e Ch O f
'а' :
{ анализ нажатой клавиши }
begin
dН : = - 1 ;
dV
:=
О;
end ;
's' :
begin
dН
: = 1;
dV
:=
О;
end ;
1W' :
begin
dН
:= О;
dV : = - 1 ;
end ;
'z' :
begin
dН : = О ;
dV
:= 1;
end ;
1
'
:
begin
dH : = О ;
dV
:= О;
end ;
{ е сли з н ач ение n ер еменной Ch
-
nр о б ел ,
то о бъект нужно о с т ановить }
end ;
Got oXY ( H , V ) ;
Wri t e ( '
н : = н
V := V
' ) ;
+
dН ;
+
dV ;
Got oXY ( H , V ) ;
Wri te ( ' * ' ) ;
De l ay ( 1 0 0 0 ) ;
1Q' ;
Unt i l Ch =
End .
Итак, объект будет полностью контролироваться пользователем, то есть
при нажат ой клавише двигаться, а в остальное время - нет.
В приведеиной программе изменение положения объект а ничем не огр ани
чено. Следовательно, может возникнуть ситуация, когда координаты объекта
253
Turbo Pascal 7 . 0
выйдуг з а пределы допустимых значений. При свободном движении объекта
проверка на корректность изменения положения объекта производилась пе
ред самим изменением, путем корректировки параметров dX и dY.
Однако при управлении объектом с клавиатуры такая проверка будет очень
сложна, так как придется еще проверять направление движения объекта. В
данном случае удобнее сначала изменить координаты Н и V, а затем прове
рить их корректность. Это довольно просто: например, если горизонтальная
координата превышает 79, то ее нужно сделать равной 79-ти, если горизон
тальпая координата меньше 1, то ее нужно сделать равной 1, аналогично для
вертикальной координаты:
If н
7 9 Then н
>
: = 79 ;
I f Н < 1 Then Н : = 1 ;
I f v > 2 4 Then v : = 2 4 ;
I f V < 1 Then V
:=
1;
И последнее замечание. Если движение объекта осуществляется н е непре
рывно, то в использовании процедуры Delay нет необходимости. Если же
движение является непрерывным, то секундная пауза мешает управлению
объектом.
В данном случае лучше всего поместить вызов процедуры Delay там, где в
результате анализа состояния клавиши (нажата/не нажата) выясняется, что
клавиша не нажата (см. листинг 089). Таким образом, если пользователь не
нажимает клавишу, объект двигается медленно, а если нажимает - быстро.
Л ИСТИНГ 089. ДВИЖЕНИЕ ОБЪЕКТА, ЗАДАННОЕ ПАРАМЕТРАМИ
Program Move0bj e c t 9 ;
Uses
CRT ;
Var
Н, V,
Ch :
dН ,
dV :
Int eger ;
Char ;
Begin
ClrScr;
н
: = 10;
v
:= 10;
dН
:=
О;
dV
:=
О;
Ch
:=
'
' ;
Repeat
If KeyPre s s ed
Then Ch
: = ReadKey
{ считывание н аж а т ой кл а виши ,
е сли она н а ж а т а }
E l s e De l ay ( 1 0 0 0 ) ;
{ е сли кл а виша не н аж а т а ,
пр о и з в одит с я с е кундная
з адерж к а пр о rр аммы }
254
Глава 8 . Движен и е объекта по экрану
{ ан а л и з н ажа то й кла в иши }
case Ch Of
'а' :
begin
dH
: =
-1;
dV
:=
О;
end ;
's' :
begin
dH
: =
1;
dV
:=
О;
end ;
'w' :
begin
dН
: =
О;
dV
: =
-1;
end ;
' z ' :
begin
dH
: =
О;
dV
: =
1;
end ;
end ;
Got oXY ( H , V ) ;
Wri t e { '
н
н
' ) ;
+
dН ;
V
+
dV ;
If Н
>
7 9 Then Н
If Н
<
1 Then Н
If V
>
2 4 Then V
If v
<
V
: =
: =
: =
:=
: =
79;
1;
24 ;
1 Then v : = 1 ;
{ анали з ко р р е ктнос т и ко ордин а т о б ъ е кт а }
Got oXY { H , V ) ;
Wri t e { ' * ' ) ;
Unt i l Ch
=
'Q' ;
End .
И СПОЛЬЗОВА Н И Е КЛАВИШ , Н Е ИМЕЮЩИХ ВИЗУАЛ Ь Н ОГО ПРЕДСТАВЛЕ Н ИЯ
Символьные клавиши не очень удобны для пользователя в связи с их нело
гичным расположением в смысле передвижения объектов. Соответственно,
их использование должно сводиться к минимуму. Для персмещения чего
либо на клавиатуре имеются клавиши-стрелки, а для отмены каких-либо
действий предназначена клавиша « Е s с», для быстрого доступа к функциям
программ - ф ункциональные кл ав и ши « F l . . . F 1 2 » . Однако их использо
вание в программах затрудняется отсутствием визуалыюга представления,
вследствие чего невозможно проверить значение символьной переменной
на равенство таким кл авиш ам.
Однако всем перечисленным и некоторым другим клавишам все же сопос
символы
на экран. Например, кл авише �Enter� сопоставлен символ � Перевод стро
ки�, добавляемый к строке при выводе ее процедурой W r i t e Ln. Естествен
но, что его нельзя использовать в условном опер аторе.
т ав ле ны некоторые символы, просто нет возможности вывести эти
255
Turbo Pascal 7 . 0
Совокупность всех символов, в том числе и н е имеющих визуального пред
ставления, представляет собой так называемую таблицу символов. Пос
кольку каждый символ в такой таблице имеет свой номер (код), таблицы
символов еще называют кодировками. В зависимости от количества сим
волов в таблицах и их взаимного расположения выделяют различные ко
дир о в ки .
В компьютерах
I вм РС АТ
используется кодировка, называемая ASC:I :I .
ПРИМЕЧАНИЕ,
ASCI I
American Standard Code for l nformation l nterchange американский стан
дарт об мена информацией . О бычно nроизносится по- русски , как «АС К И - 2 » (с уда
рением на « И » ) .
-
-
Первые 1 28 символов данной кодировки содержат английские буквы и уп
равляющие символы, типа перевода строки и возврата каретки, и называются
стандартной кодировкой ASCII. Также используется еще 1 2 8 символов,
предстаnляющие национальные символы и символы псевдографиrш. Эта вто
рая часть кодировки называется расширенной кодировкой ASCII. Расши
ренные кодировки составляются отдельно для каждого языка и имеют номер.
Для русского языка создана расширенная АSСП-кодировка с номером 866.
Таким образом, в расширенной кодировке ASCII доступно 256 символов и
любой клавише, пажатой на клавиатуре, сопоставляется один из символов
кодировки. В Turbo Pascal предусмотрена возможность использования сим
волов, не имеющих визуального представления, через их номера в таблице
символов. Для указания необходимости использования символа с некото
рым номером предназначен оператор #, имеющий следующий вид:
# < Н омер симв о л а >
или аналогичная функция Chr:
Chr ( < H oмep символа > )
Приведем пример программы (см. листинг 090), ожидающей нажатия кла
виши E s c с использованием оператора #. При этом будем иметь ввиду, что
клавише E s c в таблице ASCII сопоставляется символ с номером 27.
Л иСТИНГ 090. ИСПОЛЬЗОВАНИЕ УПРАВЛЯЮЩИХ КЛАВИШ. ОПЕРАТОР #
Program Wa i tForE s c ap e l ;
Uses
CRT ;
Var
Ch :
Begin
256
Char ;
{ п ер еменная для хр анения н ажатой к л а виши }
Глава 8. Движе н и е объекта по экрану
{ нач ал о опер ат ор а цикл а }
Repeat
Wri t e Ln ( ' Haжиит e клавишу Е ве ' ) ;
Ch
: =
{ подска з к а о н е о бходим о с ти н аж ать к л а вишу E s c }
ReadKey ; { ожидание н ажа тия кл а виши }
unt i l Ch
=
# 2 7 ; { у с л о в и е з а в ершения цикл а - код с им в о л а ,
с о о т в ет с твующего на ж а т о й кл а више ,
ра вняет ся 2 7 - ми }
End .
И такой же пример, но с использованием не оператора #, а функции Chr
представлен в листинге 09 1 .
Л истинг
09 1 .
ИсnользовАНИЕ УПРАВляющих КЛАВИ Ш . функция
СнR
Program Wai t ForE s e ape 2 ;
Uses
CRT ;
Var
Ch :
Char ;
{ п ер еменная для хр анения н а ж ат ой кл а виши }
Begin
{ н а ч ал о опер а тор а цикл а }
Repeat
Wri t eLn ( ' Haжиит e клавишу Е в е ' ) ;
Ch
: =
{ подск а з к а о н е о бходимо с ти на ж а ть кл а вишу E s c }
Re adKey ; { ожидание на ж а тия кл а виши }
unt i l Ch
=
Chr ( 2 7 ) ;
{ у с л о в и е з ав ерш ения цикл а - код симв о ла ,
с о от в ет с твующе г о на жа т о й кла више ,
ра вня ет ся 2 7 - ми }
End .
Однако 25 6-ти символов н е хватает для того, чтобы представить все воз
можные комбинации клавиш. Поэтому некоторым клавишам, например
клавишам-стрелкам и функциональным клавишам сопоставляется по два
символа, первый из которых имеет AS C I I -кoд, равный нулю. Коды сим
волов, соответствующие некоторым управляющим клавишам приведсны
в табл. 5 .
Таким образом, клавише-стрелке �влево� соответствует два кода - первый
(О) и второй (75), аналогичный коду клавиши Н (латинская). Для того, чтобы
корректно определять, какая именно клавиша нажата, необходима предвари
тельная проверка на наличие нулевого кода перед анализируемым значением
нажатой клавиши. Такую проверку удобно реализовать вложенным опе
ратором множественного выбора Case. В качестве примера приведем про
грамму (см. листинг 092 ), реагирующую некоторым образом на нажатие
клавиш-стрелок (управляющие клавиши) , а также пробела и символьной
клавиши �А• латинская (обычные клавиши). Выход из программы органи
зуем по нажатию �Esc�.
9 З ах . 7fY2
257
Turbo Pascal 7 . 0
ЛИСТИНГ 092. ИСПОЛЬЗОВАНИЕ УПРАВЛЯЮЩИХ И ОБЫЧНЫХ КЛАВИШ ОДНОВРЕМЕННО
Program What i s P re s s e d ;
Uses
CRT ;
Var
Ch : Cha r ;
{ п ер еменная для хр ан ения нажатой кла виши }
Begin
Wri teLn ( ' Haжкит e с трелку , пробел , А или E s c ' ) ;
{ по д с к а з к а о в о зможных клавишах }
{ начало оператора цикл а }
Repeat
{ с читывание кла виши , общее для упр а в ляющих
Ch : = ReadKey ;
и о бычных }
C a s e Ch O f
{ анализ нажатой клавиши }
# 0 : begin
{ е сли код симв о л а - О , то з н ачит н а ж а ·r а
упр а в ляющая кла виша , то е с т ь можно с р а з у ж е
считат ь е щ е одно значени е }
Ch : = ReadKey ; { считы в а ем е г о }
C a s e Ch O f
{ и анали з ируем в о б ычном порядке в т о р о й код
окончание анализ а п ер в о г о кода ( 0 ) }
# 7 5 : Wr i t e Ln ( ' влeв o ' ) ;
# 7 7 : Wr i t eLn ( ' впpaв o ' ) ;
# 7 2 : Wri t e Ln ( ' в в epx ' ) ;
# 8 0 : Wri t e Ln ( ' вниз ' ) ;
end ;
end ;
' ' : Wr i t e Ln ( ' пpoб eл ' ) ;
{ анализ о с тал ьных клавиш , выполня е т с я ,
е с ли п ервый код не 0 }
' А ' : Wri t e Ln ( ' А ' ) ;
Else
Wri t e Ln ( ' Toлькo с трелки , про б ел , А или E s c ' ) ;
{ е сли нажата н епр еду смотренная клавиша вывод подсказки еще р а з }
end ;
Unt i l Ch
# 2 7 ; { у сл о в и е з а в ершения цикл а - н а ж а т а кл а в иш а E s c }
End .
Применим изученные возможности к программе, реализующей движение
объекта, управляемого клавиатурой. Будем теперь вместо символьных
клавиш �а>.>, �s:�>, �W:!>, �Z:!> использовать для перемещения объекта клави
ши-стрелки. Предусмотрим дополнительно остановку объекта по нажатию
пробела. Завершение программы будем производить по клавише �Esc>.>, а не
� Q>.> (см. листинг 093).
Листинг 093.
УпРАВЛЕНИЕ движЕниЕм оБъЕктА с помощью УПРАвляющих
И ОБЫЧНЫХ КЛАВИШ ОДНОВРЕМЕННО
Program MoveObj e c t 9 ;
Uses
CRT ;
Var
258
Глава 8. Дв ижен и е объекта по э крану
Н , V , dН ,
Ch : Char ;
Begin
dV :
Int eger ;
C l rS c r ;
н : = 10;
v := 10;
dH : = О ;
dV : = О ;
Ch : = 1 1 ;
Repeat
If KeyPre s s ed
Then Ch : = ReadKey
{ считыв ани е нажатой кл авиши , е сли она на жат а }
E l s e De l ay ( 1 0 0 0 ) ;
{ е сли клавиша не н аж ат а , nро и з в одит с я с екундная
з адержка лр ограммы }
C a s e Ch O f
{ в н ешний оnератор мно ж е с т в енн о г о в ыб ора ,
р е а ли зующий анализ n ер в о г о кода н а ж а т о й
кла виши ( или един с т в енно г о , е сли э т о
символьная кла виша ) }
{ е сли л ервый код кла виши - О }
# 0 : begin
Ch : = ReadKey ; { nо в т орно е с читыв ание нажатой клавиши }
C a s e Ch O f
{ влож енный оn ератор C a s e , о суще с т вляющий анализ
уnра вляющей клавиши }
# 7 5 : begin
dН : = - 1 ;
dV : = О ;
end ;
# 7 7 : begin
dН : = 1 ;
dV : = О ;
end ;
# 7 2 : begin
dН : = О ;
dV : = - 1 ;
end ;
# 8 0 : begin
dН : = О ;
dV : = 1 ;
end ;
end ;
end ;
1
1 : begin
dН : = О ;
dV : = О ;
end ;
end ;
{ оконч ание анали з а уnр а вляющей к л а в иши }
{ окончани е о бр а б о тки n ерв о г о к о да ,
е сли он был нул е в ым }
{ о бр а б отка nро б ел а - о б ычной с им в о л ьной клавиши }
{ окончани е анали з а нажатой клавиши }
Got oXY ( H , V ) ;
Wri t e ( 1 1 ) ;
н : = н + dН ;
V := V
+
dV ;
259
Turbo Pascal 7 . 0
If Н
7 9 Then Н
>
If н
<
If v
If V
79 ;
: =
: =
>
1 Then н
2 4 Then v
<
1 Then V
: =
1;
24 ;
: =
1;
Got oXY ( H , V ) ;
Wri t e ( ' * ' ) ;
unt i l Ch
=
#27 ;
{ у с л о в и е з а в ершени я цикла нажати е клавиши E s c
( код 2 7 ) }
End .
8 . 2 . 3. ОnРЕдЕЛЕНИЕ кодов клдвиш
Для определения кода любого символа можно использовать функцию O rd,
возвращающую код символа, заданного ей в качестве параметра:
Оrd ( < С имв ол > )
В качестве параметра Сиквоп должна использоваться константа или пере
менпая типа Char.
Приведем программу (см. листинг 094), выдающую коды нажатых клавиш
до тех пор, пока не будет нажата клавиша Esc (ее код 27).
Л ИСТИНГ 094. ОПРЕДЕЛЕНИЕ КОДА НАЖАТОЙ КЛАВИШИ
Program GetKeyCode ;
Uses
CRT ;
Var
Ch :
Char ;
Begin
Repeat
Ch
:=
{ начал о у сло в н о г о опера'l'ора цик л а }
ReadKey ; { ожидание наж атия на клавишу }
Wri t e Ln ( Ord ( Ch ) ,
'
-
' ,
Ch ) ;
{ выв од стр оки вида
' Код клавиши '
-
' Симв ол ,
с о отв ет с т вующий к л авише ' }
Unt i l Ch
# 2 7 ; { у сло в и е вых ода из цик л а - наж атие к л а в иши
с код ом 2 7 ,
то есть E s c }
End .
8 . 2 . 4 . ОдНОВРЕМЕННОЕ ДВИЖЕНИЕ НЕСКОЛЬКИХ ОБЪЕКТОВ
Попробуем совместить оба рассмотренных ранее вида движения - управ
ляемого пользователем объекта и свободно движущегося ( см. рис. 1 09).
Совместное движение объектов происходит по следующей схеме:
1. Инициализация параметров, определяющих положение и направ
ление движения обоих объектов: х, У, Н, v, dX, dY, dH, dV.
260
Глава 8. Движе н и е объекта по экрану
2. Циклическое повторение операций чтения информации с клавиа
туры, ее анализа и перевывода обоих объектов:
•
чтение нажатой клавипш, если нажатие произошло;
•
анализ нажатой клавиши и соответствующее изменение пара
метров dH и dV;
•
удаление управляемого объекта, изменение его координат н
и v с учетом направления движения dH и dV, проверка допус
тимости полученных координат, их корректировка в случае
необходимости, и вывод объекта в новое положение;
•
анализ координат Х и У свободно движущеrося объекта, кор
ректировка направления его движения dX и dY в случае не
обходимости, удаление объекта с экрана, пересчет координат
и вывод объекта в новое положение.
Распространенпой ошибкой начинающих программистов является попыт
ка скопировать одну программу в конец другой для достижения эффекта
одновременного движения нескольких объектов. Это совершенно недопус
тимо, так как если просто скопировать текст одной программы после завер
шающего программу ключевого слова End, то добавленный фрагмент будет
просто проигнорирован компилятором, а если скопировать цикл движения
одной программы после цикла движения второй, объекты будут двигаться
по очереди, но не одновременно. Таким образом, движение обоих объектов
должно происходить в одном и том же операторе цикла.
Приведем пример программы, осуществляющей движение объектов, показан
ным на рис. 1 09. Программу реализуем в графическом режиме, стирание объ
ектов будем производить повторным их рисованием, но фоновыми цветами.
Для того, чтобы управляемый объект перемеп.�;ался быстрее, чем свободно
движущийся, параметры его движения dH и dV будем устанавливать равны
ми по модулю два, а не единицы, как в предыдущих примерах. Для сниже
ния скорости вывода применим процедуру Delay в теле цикла без всяких
условий (см. листинг 095). Так как координатное пространство графическо
го режима намного шире, чем текстового, предельные значения координат
объектов Х, У, Н и V необходимо изменить.
Л ИСТИНГ 0 9 5 . СОВМЕСТНОЕ ДВИЖЕНИЕ НЕСКОЛЬКИХ ОБЪЕКТОВ
Program MoveObj ec t s ;
Uses
CRT , Graph ;
Var
Gd , Gm : Integer ;
{ перем енны е д л я иници ал из а ции гр а фич е с к о г о р е жима }
Н , V , dН , dV : Integer ;
{ переменны е - п ар аме тры движения упра в ля емо г о объект а }
26 1
Turbo Pascal 7 . 0
У,
Х,
Ch :
dX ,
dY :
Int eger ;
{ п еременн ы е - п ар аметр ы движен ия с в о б одно г о о б ъ е к т а }
{ пер еменн а я д ля хр ан ения на ж а т ой кл а в иши }
Char ;
Begin
Gd
: =
De t e c t ;
Gm
: =
О;
I n i t Graph ( Gd ,
Gm ,
' ' ) ;
{ инициа л и з ация г ра фиче с к о г о р е жима }
S e tBkC o l o r ( Whit e ) ;
н
v
: =
50;
:=
50;
dН
:=
О;
dV
: =
О;
х
у
: =
100;
: =
100;
dX
:=
1;
dY
:=
1;
Ch
:=
'
{ и ници а л и з ац ия в с е х п ер ем енных }
{ н ач ало ци кла движ ения }
';
Repeat
I f KeyP re s s ed Then Ch
: =
ReadKey ;
{ считыв ание наж ат ой кл а виши ,
е с л и на ж а т ие пр ои з ошл о }
{ ан а л и з н аж ато й кл авиши }
{ е с л и на ж а т а упра в ля юща я кл а виша . . . }
Ch : = Re adКey ;
{ с ч и т ыв ание в т ор о г о к ода на ж а т о й кл а виши и
C a s e Ch O f
е г о ана л и з - изменение п араме тр о в движ ени я
C a s e Ch O f
#0 :
begin
у пра в ля емо г о о бъ е кт а }
#7 5 :
begin
dН
: =
-2;
dV
:=
О;
end ;
#77 :
begin
dН
: =
2;
dV
: =
О;
end ;
#72 :
begin
dH
: =
dV
: =
О;
-2;
end ;
#80 :
begin
dH
: =
О;
dV
:=
2;
end ;
end ;
{ о к онч ание ан а л и з а упр а в л яющ е й кл авиши }
end ;
'
262
' :
begin
dН
: =
О;
dV
: =
О;
Гл ава 8 . Движен и е объекта по экрану
{ е сли н а ж а т а не упр а вляющ а я к л а в иш а ,
end ;
а пр о б ел - о с т ановка объект а }
end ;
{ окончание анали з а нажатой клавиши }
SetColor ( Wh i t e ) ;
S e t F i l l S tyl e ( Sol i dF i l l , Whi t e ) ;
F i l l E l l ip s e ( H , V ,
н : = н + dН ;
V
: =
10 ,
10 ) ;
V + dV ;
If Н
>=
6 2 0 Then Н
If Н
<=
2 0 Then Н
620;
: =
20;
:=
If V
>=
4 6 0 Then V
If v
<=
2 0 Then v
460;
:=
20;
:=
S e t F i l l Styl e ( S o l i dF i l l ,
F i l l E l l ip s e ( H ,
V,
10 ,
Red ) ;
10) ;
{ уд а л ени е с экрана упр а вляемо г о о бъекта ,
изменение е г о ко ордин ат , их корр ектир о в к а
в с луча е н е о бходимо с ти , и в ы в о д о бъекта
If
(У
>=
44 0 )
в н о в о е положение }
OR ( У < = 4 0 ) Then dY
: =
- dY ;
If
(Х
>=
600)
OR
:=
- dX ;
(Х
<=
40)
Then dX
S e t C o l o r ( Whi t e ) ;
Re c t angl e ( X , У ,
Х
: =
Х + dX ;
У
Х+ 5 0 , У+ З О ) ;
: =
У + dY ;
S e t C o l o r ( DarkGray ) ;
R e c t angl e ( X ,
У , Х+ 5 0 , У + З О ) ;
{ и зменение направл ения движ ения с в о б одн о г о
объекта
( е сли э т о н е о бходимо ) ,
с э кр ана ,
De l ay ( l O O O ) ;
Unt i l Ch
=
#27 ;
удал ение е г о
и зменение е г о ко ордин ат ,
и вывод
объекта в н о в ом полож ении }
{ с е кундная з адержка }
{ у с л о в и е з а в ершения цикла - нажатие кла виши E s c }
End .
Практически в н:аждой программе, осуществляющей движение нескольких
объектов, будь то модель реального физического процесса или игровая про
грамма, часто бывает необходимо определить момент столкновения некото
рых объектов друг с другом.
8 . 2 . 5 . ОnРЕдЕЛЕНИЕ <<столкновЕния» двиЖУщи хся оБъЕктов
Для простейшего определения 4СТолкновения:�> рассмотренных нами объ
ектов, необходимо проверить, не попадают ли координаты управляемого
объекта (круга) в некоторый Охватывающий прямоугольник (см. рис. 1 1 0).
Его размеры и положение зависят от прямоугольника, охватывающего вто
рой объект, и радиуса управляемого объекта.
Допустим, первый объект является прямоугольным и имеет координа
ты Х , У, X + W i d t h , Y + H e i gh t , а второй объект (круг) имеет координаты
263
Turbo Pascal 7 . О
и радиус R . Тогда координаты охватывающего прямоугольника будут
( X - R, Y - R, X + W i d t h + R, Y + H e i gh t + R) .
н, v
Столкновением объен:тов можно считать ситуацию, когда координаты цент
ра круга (Н, V) находятся внутри полученного охватывающего прям оуголь
ника, то есть:
- ·
•
координата Н больше, чем X - R и при этом меньше, чем X+Width+R;
•
координата v больше чем Y-R и при этом меньше, чем Y+He i ght + R;
,
Модифицируем предыдущий пример так, чтобы при столкновении объек
тов в правом верхнем углу экрана загаралея на одну секунду зеленый круг
(ем. листинг 096).
ЛИСТИНГ 0 9 6 . ОПРЕДЕЛЕНИЕ СТОЛКНОВЕНИЯ ОБЪЕКТО В
Program Obj ectCol l i s i on ;
Uses
CRT ,
Graph ;
Var
Gm :
Gd ,
I nt e ge r ;
н , v , dН ,
х , У , dX ,
Ch :
dV :
Int eger ;
dY :
Int e ger ;
Cha r ;
Begin
Gd
: = De t e c t ;
Gm : = О ;
Init Graph ( Gd ,
Gm ,
S e t BkColor ( Wh i t e ) ;
'') ;
н : = 50;
v
:=
50;
dН
:=
О;
dV
:=
О;
х
: = 100 ;
у
: = 100;
dX
:= 1;
dY
:= 1;
Ch
:=
'
';
Repeat
If KeyPre s s ed Тhen Ch
C a s e Ch O f
#0 :
begin
Ch
: = Re adKey ;
C a s e Ch O f
# 7 5 : begin
dН
: = -2;
dV
:= О;
end ;
264
. - ReadKey ;
Глава 8 . Движе н ие объекта по экрану
#77 :
dН :
dV :
end ;
=
=
begin
2;
О;
#7 2 :
begin
dН : = О ;
dV : = - 2 ;
end ;
#80 :
begin
dН : = О ;
dV : = 2 ;
end ;
end ;
end ;
1
1 :
begin
dH : = О ;
dV : = О ;
end ;
end ;
SetColor ( Whi t e ) ;
S e t F i l l S t y l e ( So l i dF i l l 1 Whi t e ) ;
F i l 1 E l l ip s e ( H 1 V 1 1 0 , 1 0 ) ;
н : = н + dН ;
V : = V + dV ;
I f н >= 6 2 0 Then н : = 6 2 0 ;
I f н < = 2 0 Then н : = 2 0 ;
I f V > = 4 6 0 Then V : = 4 6 0 ;
I f V < = 2 0 Then V : = 2 0 ;
S e t F i l l Styl e ( Sol i dF i l l , Red ) ;
F i l l E l l ip s e ( H , V , 1 0 , 1 0 ) ;
I f ( У > = 4 4 0 ) OR ( У < = 4 0 ) Then dY : = - dY ;
I f ( Х > = 6 0 0 ) OR ( Х < = 4 0 ) Then dX : = - dX ;
SetColor ( Whi t e ) ;
R e c t angl e ( X , У , X+ S O , У+ З О ) ;
Х : = Х + dX ; У : = У + dY ;
S e t Co l o r ( DarkGray ) ;
Re c t angl e ( X , У , X+ S O , У+ З О ) ;
If
( Н > Х - 1 0 ) AND
( Н < Х + 5 0 + 1 0 ) AND
( V > У - 1 0 ) AND
(V < У + 3 0 + 1 0 )
{ е с ли вып о л н я е т ся у с л о в и е с т о лк н о в ени я }
Then begin
S e t F i l l S t y l e ( So l i dF i l l , Green ) ;
F i l 1E l l ip s e ( 6 3 0 , 1 0 , 1 0 , 1 0 ) ;
Delay ( 1 0 0 0 ) ;
S et F i l l S t yl e ( S o l idFi l l , Whi t e ) ;
F i l 1 E l l ip s e ( 6 3 0 , 1 0 , 1 0 , 1 0 ) ;
end ;
{ р и су ем в пр а в ом в ерхн ем у г лу з ел е ный кру г ,
д ел а ем пау зу н а с е кунду и с тир а ем кру г }
De l ay ( 1 0 0 0 ) ;
Unt i l Ch = # 2 7 ;
End .
265
Turbo Pascal 7 . 0
Аналогичным образом проверяется столкновение двух прямоугольных
объектов (см. рис. 1 1 1 ) . Вообще, для определения охватывающего прямо
угольника необходимо:
1. Нарисовать первый объект.
2. Нарисовать второй объект столько раз и таким образом, чтобы он
касался первого со всех его сторон.
3. Провести прямоугольник по всем опорным точкам всех экземпляров второго объекта, выведенных рядом с первым.
По данной схеме можно определить охватывающий прямоугольник для
объектов любой конфигурации. Однако иногда можно применитъ более
точные и быстрые методы. Например, столкновение двух объектов, имею
щих форму круга, проще всего определить по расстоянию между точками
их центров (если расстояние меньше суммы радиусов, то объекты столкну
лисЪ - см. рис. 1 1 2).
ПРИМЕЧАНИЕ.
Р ассто я н и е между двумя точ кам и в ы ч исляется п о известн о й ф о рм ул е : . Ис
пол ьзуя функцию Sq rt, возвращающую квадратн ы й ко р е н ь значен и я , зада н н о
го в качестве параметра , для двух окружн остей с центрам и (Х, У) и ( Н , V) дл я
нахожде н и я расстоя н и я м ежду центра м и , можно использовать в ы раже н и е
S q rt ( (X - Н ) * (Х - Н ) + (У - V)*(Y - V) ) .
8 . 3 . П О Н Я Т И Е СТРУКТУРН О ГО П РО Г РАМ М И РО ВАН И Я
Операторы ветвления и зацикливания формируют структуру программы,
поэтому называются структурными. Соответственно, программирование
с использованием таких операторов также называется структурным. До
широкого распространения программирования для формирования структу
ры программы использовались операторы бузусловнаго перехода. В Turbo
Pascal также предусмотрен такой оператор, имеющий следующий вид:
Goto <Метка б е зу с л о вн о г о п ер ехода > ;
б е зу сл о в н о г о n е р е х ода являются идентификаторами, описы
ваемыми в разделе описания меток LaЬel:
Ме т ки
Lab e l
{ начало р а з де л а опис ания меток }
< Имя метки > ;
Имеется возможность описания нескольких меток в одной строке:
Label
{ начало р а здела опис ания меток }
< Имя метки
266
1>,
. . . ,
<Имя метки n > ;
Глава 8 . Движе н и е объекта по экрану
Для установки метки безусловного перехода в каком-либо месте програм
мы необходимо указать имя метки с двоеточием:
<Имя метки > :
Результатом работы оператора безусловного перехода G o t o будет выпол
нение команды, следующей в программе сразу же за меткой. Рассмотрим
пример (см. листинг 097) .
Листинг 097. ИспользовАНИЕ ОПЕРАТОРА Gото
Program DoNotDo i t ;
Labe l
{ начало р а з дела опис ания меток
б е зу с л о в н о г о перехода }
Al ;
{ опис ани е метки б е зу с л о в н о г о перехода с именем Al }
Begin
Wri t eLn ;
{ п ер е в од с троки }
Wri t e Ln ( ' C тpoкa 1 ' ) ;
{ вывод на экран с троки «Строка 1 » }
Goto Al ;
{ б е зу с л о вный пер еход к команде ,
н аходящейся
з а меткой Al }
Wri t eLn ( ' C тpoкa 2 ' ) ;
{ вывод на экран с троки «Строка 2 » ;
эта команда н е выполня е т с я }
Al :
{ у с тановлена метка Al }
Wri t eLn ( ' C тpoкa 3 ' ) ;
{ в ывод на экран с троки «Строка 3 » }
End .
Результатом выполнения приведеиной программы будет вывод на экран
двух строк: « С т р о к а 1 » и « С т р о к а 3 » . Строка « С т р о ка 2 » не будет
выведена на экран, так как находится между оператором безусловного пе
рехода и. меткой, на которую осуществляется переход.
Оператор Goto является атавизмом и его использование - плохой тон про
граi\fМирования. Любую программу можно написать без его использования,
только с помощью структурных операторов. В Turbo Pascal данный опера
тор предусмотрен для тех программистов, которые к нему привыкли и не
могут отказаться от его использования.
Поясним, почему не рекомендуется использование оператора безусловного
перехода. Структурное программирование предназначено для упрощения
программ и приближения их к языку, более свойственному человеку, опе
рирующему крупными логическими попятиями, такими как �выполнить
несколько раз>> или �выполнять, пока условие истинно�. Оператор же G o t o
запутывает программу и вносит в нее хаос, передавая управление командам,
которые па первый взгляд никак не связаны между собой. Поня'i.ъ структу
РУ такой программы бывает крайне сложно даже тому, кто ее написал.
267
Turbo
P a s c a l 7.0
г л а в а
И с п о л ь зо в а н и е
п одп р о гра м м
При написании программ часто возникает ситуация, когда оди н и тот же
фрагмент програм мы повторяется несколько раз. Такие повторения уве
личивают объем исходного текста программы и выполняемого файла, по
лучаемого в результате компиляци и . Соответственно, с нижается читабель
ность программы и повышается время ее компиляции . Частично убрать
повторения фрагментов можно с помощью их зацикливания, однако это
не всегда возможно.
Рас с м отр и м к в ад р ат н о е урав н е н и е
вида у = ах2 + Ь х + с . Н а п о м ни м ,
что графи к такой фун кци и п редстав
ляет собой п араболу, ветви которой
м о гут быть н а п ра вл е н ы в верх и л и
в н и з (см . р и с . 1 1 3 ) . Направление ветвей зависит от коэффициента а: если
а > О , то ветви направлены вверх, если
а < О , то ветви н аправлены в н и з , есл и
а = О , то квадратичная функция превращается в л и н е й ную.
v
Вет в и п арабол ы напра в ле н ы вв ерх
х
Рис.
1 1 З. Гра фик пара болы
В зависимости от положения параболы она м ожет пересекать ось х в
одном месте , в двух местах либо не пересекать ее вообще ( с м . рис. 1 1 4) .
Горизонтальные координаты точек,
у
в которых п арабола пересекает ось
х, н азы вают корнями квадратного
уравнения ах2 + Ьх + с = О . Для
в ы ч и сле н ия к о р н е й квадратн ого
уравнения существуют формулье
( -Ь
Х2
+
sqrt ( D ) ) / { 2 * а ) ;
х
( -Ь - sqrt ( D ) ) / { 2 * а ) ;
где параметр D, н азываемый диск
ри м и нанто м , выч исляется как:
D
=
Ь*Ь
-
4 *а*с .
Рис. 1 1 4 . Изменение количества
корней пара болы в зависимости от
положения вершины относительно оси Х
269
Turbo Pascal 7 . 0
При рассмотрении квадратного уравнения обычно требуется ответить на
два вопроса:
1 . Сколько корней имеет уравнение.
2 . Какие значен и я имеют корни , есл и они есть.
Для того чтобы определить, сколько корней имеет уравнение, необходи
мо проанал изировать дискри ми нант: если D>O, то уравнение имеет два
корня , если D=O , то уравнение и меет один корень, а если D<O, то корней
нет. Далее, в случае если корн и имеются , их следует вычислить по вы
шеприведенн ы м формулам .
Н апишем программу (см. листинг 1 35), определяющую количество корней
квадратного уравнения и вычисляющую их. Программа будет производить
такой анализ для двух уравнений , имеющих следующие коэффициенты :
Коэф фициен'l' :
Уравнение
1:
Уравнение
2:
а
2
1
ь
12
5
с
11
200
Для анализа каждого уравнения будут производиться следующие действия:
1 . Заполнение коэффициентов а , Ь и с, для которых п р едварительно
должны быть оп исаны одноименные переменные ти п а Real , значе
ниями , соответствующими рассматриваемому уравнени ю . То есть
а : = 2 , ь : = 1 2 , с : = 1 1 для первого уравнения и а : = 1 , Ь : = 5 , с : = 2 0 0 для второго.
2 . Вычисление дискриминанта по формуле Ь *Ь
4 *а *с и занесение
результата дан ного выражения в предварительно описанную пере
менную D тип а Rea l .
3 . Анализ дискриминанта с помощью трех вложенных друг в друга ус
ловных операторов I f , в результате которого на экран должна выво
диться и нформация о том , сколько корней имеет очередное квадрат
ное уравнение и их значения.
-
:я�ч�;:.,,.. г •• 1'з �;••:��·y,.:�����·��.• ·l<�.�.;.�.�,• ���i\�:�r���"�:r��·�·�,���.�.�i:�:;���·:шt'1i1;;:t:::f�!�f
Program Root s l ;
Uses
CRT ;
Va r
а,
Ь,
с:
Real ;
D, Xl , Х2 : Real ;
Begin
ClrScr;
а
:=
ь
:=
270
2;
12 ;
{ п е р емен ные
д л я х р а н е н и я к о э ффици е н т о в }
д л я х р а н е н и я д и с крими н а н т а и
вычи с л е н ны х к о р н е й }
{ переме н ные
Гл ава 9 . Ис п ол ьзование п одпрограм м
{ з аполнение ко э ффици е н т о в дл я п е р в о г о ур а в н е ни я }
{ вычи с л е н и е д и с крими н а н т а }
If
{ е сли дискрими нант ме н ь ше нул я , выво д с о о бщения
о б о т су т с твии к о р н ей }
Wri t eLn ( ' Уравнение корней не имеет ' )
E l s e I f D = О Then
begin
Х1 : = -Ь/ ( 2 * а ) ;
Writ eLn ( ' Уравнение имеет один корень : ' ) ;
Wri t eLn ( ' Х = '
Х1 ) ;
end
{ е сли д и с крими н а н т не мен ь ше нул я , то п р о в е р к а
н а р а в е н с т в о нулю . Е сли д и с крими н а н т р а в е н
нулю , т о вычи с л е н и е е д и н с т в е н н о г о к о р н я и
выво д е г о на э кра н }
Else
{ е сли д и с крими н а н т не мен ь ше нул я и н е р а в е н
нулю , з н а чит , о н бол ь ше нул я , с о о т в е т с т в е н н о ,
вычи сление д ву х корне й ура в н е н и я и выв о д и х
н а э кр а н }
begin
Х1 : = ( -Ь + sqrt ( D ) ) / ( 2 * а ) ;
Х2 : = ( -Ь - sqrt ( D ) ) / ( 2 * а ) ;
Wri teLn ( ' Уравнение имеет один корень : ' ) ;
Х1 ) ;
Wri t eLn ( ' Х1 =
WriteLn ( ' Х2 = '
Х2 ) ;
end ;
а : = 1;
ь := 5;
{ за п олнение ко э ффициентов дл я в торо г о ур а в н е ния }
с : = 200 ;
D : = Ь*Ь - 4 * а * с ;
I f D < О Тhen
{ вычи с л е н и е д и с крими н а н т а и а н ал и з т о ч н о
т а к о й же , к а к и д л я п е р в о г о ур а в н е ни я }
Wri t eLn ( ' Уравнение корней не имеет ' )
E l s e I f D = О Then
begin
Х1 : = - Ь / ( 2 * а ) ;
Wri t eLn ( ' Уравнение имеет один корень : ' ) ;
Wri t eLn ( ' Х = '
Х1 ) ;
end
Else
begin
Х1 : = ( -Ь + sqrt ( D ) ) / ( 2 * а ) ;
Х2 : = ( -Ь - sqrt ( D ) ) / ( 2 * а ) ;
Writ eLn ( ' Уравнение имеет два корня: : ' ) ;
WriteLn ( ' X1 = '
Х1) ;
WriteLn ( ' X2 = '
Х2 ) ;
end ;
ReadKey ;
End .
с
D
11;
Ь*Ь - 4 *а*с ;
D < О Тhen
:=
:=
,
,
,
,
27 1
Turbo Pascal 7 . 0
Таким образом , приведеиная программа содержит один и тот же фраг
мент (выч исл е н и е дискри м инанта и его анализ) , п овторяющийся два
раза - для каждого уравнения. М одифицировать програм му для избежа
ния повторяемости с помощью зацикливания не представляется возмож
н ы м , так как значения коэффициентов н е поддаются описанию с помо
щью како й -л и б о схем ы . П р и добавл е н и и а н ал и з а е ще н ескол ь к и х
уравнений в программу для каждого из н их необходимо реализовать один
и тот же фрагмент с анализо м . Н есмотря н а то что это делается обыч
н ы м копиро ванием фрагмента текста из одного места программы в дру
гое , ошибок из-за невнимательности не избежать.
Для структурирования программ ы в целях повышения читабельности ,
с н ижен ия объе м а исходн ого текста и резул ьтирующего в ы полняемого
файла, а также для повышения удобства разработки программ применя
ются так называемые подпрограммы - это логически законченные фраг
менты программ , которые могут вызываться из основной программы по имени.
В Turbo Pascal возможно использование двух видов подпрограмм - про
цедур и функций . Особенности тех и других мы рассмотрим н иже, а пока
замети м , что мы уже исп ользовали и процедуры (например, GotoXY ил и
PieSlice} , и функци и (например, ReadКey или :КeyPre s sed} .
9 . 1 . П ро цедур ы
Итак, процедура - это логически законченная часть программы, описываемая
отдельно от раздела описания логики программы и вызываемая по имени, уни
кальному в пределах программы. Процедуры, так же как и программа, имеют
сложную структуру, включающую в себя разделы описания переменных, кон
стант, типов и так далее. Единственное, чем отличается по структуре процеду
ра от программы, - в ней нет раздела подключения модулей.
Procedure
<Имя> ; З а голо в о к процедуры
Label
Р а здел о п и с а н и я ме т о к бе зусло в н о г о n е р е х о д а
Con s t
Туре
Р а здел о пи с а ни я к о н с т а н т
Р а здел о п и с а ния т и п о в д а н ных
Var
Р а здел о п и с а н и я n е р емен ных
P ro ce dure
Funct i on
be g in
end ;
272
Ра здел описания подnрограмм - процедур и функций ,
с одержащих н е к о т орые элеме н т ы логики п р о ц е дуры
Н а ч ал о р а здела о п и с а н и я л о ги ки проце дуры
Р а здел оnисания логики проце дуры
Ко не ц р а здела о n и с а н и я логики п р о ц е дуры
Глава 9 . Испол ьзование под програм м
Все разделы процедуры используются аналогично таким же разделам
програм м ы , но при этом метки безусловного перехода, константы , тип ы
дан ных, переме нные, процедуры и функц и и , описан н ы е в процедуре,
я вляются локальными, то есть доступны только из п роцедуры , в кото
рой они описан ы . При этом все перечисленные элементы самой про
граммы доступны в процедуре точно так же , как и в разделе о писания
логики самой программ ы .
Допустим , в процедуре и программе описана переменная с одним и тем
же именем , что допустимо, тогда при обращении к данному имени из раз
дела описания логики программы будет использована переменная , описан
ная в разделе описания переменных программ ы , а при обращении к это
му же имени из раздела оп исания логики процедуры будет использована
переменная, описанная в разделе описания логики процедуры .
Структуры , о п исан н ы е в разделах оп исания п рограмм ы , а не процедур
и фун кций , н азываются глобальными.
Возвращаясь к предыдущему примеру, можно понять: самое простое при
менение процедур - это создание п роцедуры из фрагмента, который
повторяется в программе несколько раз (см . листинг 1 3 6 ) .
Program Root s 2 ;
Uses
CRT ;
Va r
а , Ь , с : Real ;
D, Xl, Х2 : Real ;
{ п е р еме н ные д л я х р а н е н и я ко э ффици е н т о в }
{ п е р еме н ные д л я х р а н е н и я д и с крими н а н т а и
вычи с л е н ны х к о р н е й }
Proc edure Wri t eRoot s ;
{ заголовок проце дуры , имя проце дуры - WriteRoots }
begin
{ н а ч а л о р а з д е л а о п и с а н и я л о г и ки п р о ц е д уры }
{ р а з д ел о п и с а н и я л о г и к и п р о ц е д уры вычи с л е н и е д и с крими н а н т а и е г о а н али з }
I f D < О Then Writ eLn ( ' Уравнение I<орней не имеет ' )
E l s e I f D = О Then
begin
D
:=
Ь*Ь
Xl
: =
-
4 *а*с ;
-Ь/ ( 2
* а) ;
Wri teLn ( ' Уравнение имеет
WriteLn ( ' X
=
'
,
один
I<орень : • ) ;
Xl ) ;
end
Else
begin
Xl
: =
( -Ь
+
sqrt ( D ) ) / ( 2
* а) ;
273
Turbo Pascal 7 . 0
Х2
: =
( -Ь
sqrt ( D } ) / ( 2
-
*
а) ;
Wri t eLn ( ' Урав нение имеет два корня : ' ) ;
Wri t eLn ( ' Х1
=
'
Х1 ) ;
Wri t eLn ( ' X2
=
',
Х2 ) ;
end ;
end ;
Begin
C1rScr;
а
:=
ь
:=
а
:=
ь
:=
{ о к о н ч а н и е р а здела о п и с а н и я л о ги к и п р о ц е дуры }
{ н а ч а л о р а з д е л а о п и с а н и я л о ги к и п р о г р аммы }
2;
12 ;
с : = 11;
Wri t eRoot s ;
{ заполнение коэ ффициентов дл я пер в о г о ура в н е ния }
{ в ыз о в проце дуры п о име н и }
1;
5;
с := 200;
Wr i t eRoot s ;
ReadKey ;
End .
{ з а п ол н е ние коэффици е н т о в для
{ выз о в проце дуры п о име н и }
{ о кончание
р а здела
описания
в т ор о г о ур а в н е ни я }
л о ги к и
п р о граммы }
Как видно , программа п олучается значительно короче, а в силу того , что
в ней нет фрагментов, повторяющихся несколько раз, при увеличении
количества анализируем ых уравнений вряд ли может произойти ошибка.
А теперь посмотрим , как выглядит описание локальных констант и пе
ременных в процедуре. Перенесем описание перемен ных X l , Х 2 и D из
раздела описания переменных програм м ы в раздел описани я переменных
процедуры . Такое изменение программы вполне логи ч н о , так как пере
менные X l , х 2 и D используются только в процедуре и в доступе к н и м
и з раздела описания логики программы нет необходимости . Более того ,
доступ из программ ы и других процедур к этим перемен н ы м нежелате
ле н , так как изменен ия в н их должна производить только п роцедура
Wri teRoo t s . Также оформим строки текста с сообщениями о количестве
корней в виде локальных констант (см . листи нг 1 37 ) .
Program Root s З ;
Uses
CRT ;
Va r
а , Ь , с : Rea 1 ;
{ п е р еме н ные
для
хранения
к о э ффици е н т о в }
Procedure Wri t eRoot s ;
{ заголовок процедуры , имя процедуры - WriteRoots }
Con s t
{ н а ч а л о р а з д е л а описания л о к а л ь ных к о н с т а н т
п р о ц е дуры W r i t eRo o t s }
NoRoot s = ' Уравнение корней не имеет ' ;
274
Глава 9 . Ис п ол ьзование п одпр ограм м
OneRoo t
ТWoRoot s
1 Ура:внение имеет один корень : 1 ;
1 Ура:внение имеет д:ва корня : 1 ;
{ о п и с а н и е л о ка л ь ных к о н с т а н т }
{ н а ч а л о р а з д е л а о п и с а н и я л о к а л ь ных
va r
п е р еме н ных п р о ц е дуры Wr i t eRo o t s }
D1 Х11 Х2 : Real ; { о п и с а н и е л о к а л ь ных п е р еме н ных }
{ н а ч а л о р а зд е л а о п и с а н и я л о ги к и п р о ц е дуры }
Begin
D : = Ь*Ь - 4*а* с ; { р а з дел о п и с а ни я л о гики п р о ц е дуры вычи с л е н и е дис крими н а н т а и е г о а н али з }
I f D < О Then Wri t eLn ( NoRoot s )
E l s e I f D = О Then
begin
Х1 : = - Ь / ( 2 * а ) ;
Wri t eLn ( OneRoot ) ;
Wri t eLn ( 1 Х = 1 1 Х1 ) ;
end
E l s e begin
Х1 : = ( -Ь + sqrt ( D ) } / ( 2 * а ) ;
Х2 : = ( -Ь - s qrt ( D ) } / ( 2 * а ) ;
Wri t eLn ( ТWoRoot s ) ;
Wri t eLn ( 1 Х1 = 1 1 Х1 ) ;
Writ eLn ( 1 X2 = 1 1 Х2 ) ;
end ;
{ о к о н ч а н и е р а здела о п и с а н и я л о ги к и п р о ц е дуры }
end ;
{ н а ч а л о р а здела о п и с а н и я л о ги к и п р о г р аммы }
Begin
C l rS c r ;
а := 2;
ь : = 12 ;
{ за п олнение коэффициентов для перв о г о ура в н е ния }
с : = 11 ;
{ в ыз о в проце дуры по име ни }
Wr i t eRoo t s ;
а : = 1;
ь := 5;
{ з а п ол н е ни е коэ ффици е н т о в для в т ор о г о ур а в н е ни я }
с := 200;
{ выз о в процедуры п о име ни }
Wri t eRoo t s ;
ReadKey ;
{ о к о н ч а ни е р а здела о п и с а н и я л о ги к и п р о г р аммы }
End .
=
=
9 . 2 . Ф у нкци и
Функции
это процедуры , которые возвращают значения, что позволя
ет использовать их в арифметических или логических в ыражениях, так
же как переменные или константы.
-
Структура функции аналогична структуре процедуры , за исключением
заголовка, в котором указывается , значение какого тип а возвращает фун
кция. Вместо ключевого слова Proc edure используется ключевое слово
Func t i on :
Func t i on
<Имя функции> : <Тип в о з в раща емо г о з н а ч е ни я > ;
275
Turbo Pascal 7 . 0
Для указания компилятору, какое именно значение должна возвратить
функция, в разделе описания логики функции должно использоваться при
своение следующего вида:
: = < З начени е > ;
Таким образом , описание функци и , возвращающей значение дис крими
нанта, для нашей программы может выглядеть следующим образом :
< Имя ф у нкции >
Funct ion
D i s c r iminant : Real ;
{ з аголовок фун кции , имя функции - Di s crirninant ,
т и п в о з в р а ща емог о з н а ч е н и я - Rea l }
Var
D:
{ н а ч а л о р а з д е л а о пи с а ни я л о к а л ь ных
п е р еме н ных фун кции D i s c r irninant }
Real ;
{ начало
begin
D
раздела
о п и с а н и я л о г и ки
функции }
Ь*Ь - 4 * а * с ; { вычи с л е н и е
:=
Discriminant
:=
end;
ди с крими н а н т а }
D; { ук а з а ние , к а к о е з н а ч е н и е с л е дуе т в о з в р а ти т ь
в к а ч е с т в е з н ач е н и я функции }
{ о к о н ч а н и е р а з д е л а о п и с а н и я л о г и ки функции }
Так как переменная D используется только для хранения промежуточного
результата, можно обойтись без нее , указав в качестве возвращаемого зна
чения выражение Ь * Ь - 4 * а * с , которое присваивалось переменной D до
этого:
Func t i on
Di s c r iminant : Real ;
{ з аголовок функции , имя функции - Dis crirninant ,
тип в о з в р ащаемо г о з н а ч е ни я - Rea l }
{ начало
begin
Discriminant
: =
ра здела
{ о ко н ч а ни е
end;
о п и с а ни я л о г ик и
функции }
Ь*Ь - 4 * а * с ;
{ ук а з а ни е , к а к о е з н а ч е н и е с л е дуе т
в к а ч е с т в е з н ач е н и я функции }
ра здела
описания
л о ги ки
в о з вратить
функции }
Приведем пример использования функции в программе (см. листинг 1 3 8).
�- �;:, ,,,., ., �;��:\����<�����гit:t���r:;����f���;����.J�.:��гt1�·t::i .; . ·\;,>.·'" •..·. · .
.,
Program Root s 4 ;
Uses
CRT ;
Var
а,
Ь,
с:
Funct i on
276
Real ;
{ пе р еме н ные
D i s c r iminant :
Real ;
для
хранения
к о э ффици е н т о в }
{ з аголовок
функции }
Глава 9 . И с польз ование подпрограмм
begin
Discriminant
{ н а ч а л о р а здела
4*а*с;
Ь*Ь
: =
end;
-
{ окончание
о n и с а н и я л о ги к и функции }
{ в о з в р а щ а е мо е з н а ч е ни е }
раздела
Procedure Wri t eRoot s ;
{ заголовок nроцедуры ,
Con s t
N'oRoot s
=
OneRoot
=
ТWoRoot s
оnи с а н и я
л о г и ки
функции }
имя nроцедуры - Wri teRoots }
' Уравнение корней н е имеет ' ;
' Уравнение имеет
один корень : ' ;
' Уравнение имеет
=
два
корня : ' ;
р а здела
оnисания
Var
D,
Х1 ,
Х2 :
Rea l ;
{ начало
Begin
D
л о ги к и
n р о ц е дуры }
D i s c r iminant ;
:=
If D <
О
Then Wri t eLn ( N'oRoot s )
Else I f D
Х1
: =
=
О Then begin
-Ь/ ( 2
* а) ;
Wri t eLn ( OneRoot ) ;
Wri t eLn ( ' Х
',
=
Х1 ) ;
end
E l s e begin
Х1
: =
( -Ь
sqrt ( D ) ) / ( 2
*
а) ;
Х2
: =
( -Ь - sqrt ( D ) ) / ( 2
*
а) ;
+
Wri t eLn ( ТWoRoot s ) ;
Wri t eLn ( ' Х1
=
',
Х1 ) ;
Wri t eLn ( ' Х2
=
',
Х2 ) ;
end;
end;
{ р а здел о n и с а н и я л о гики n р о ц е дуры nо луч е н и е дис крими н а н т а о т функции
D i s c r iminant и его а н а ли з }
{ о к о н ч а н и е р а з д е л а о n и с а н и я л о г ик и n р о ц е дуры }
Begin
{ начало
р а зд ела
оnисания
л о гики
n р о г р аммы }
ClrScr ;
а
: =
2;
ь
: =
12 ;
: =
11;
с
Wri t eRoot s ;
а
: =
1;
ь
:=
5;
: =
200;
с
Wri t eRoot s ;
{ за n олнение
{ выз о в
{ за nолнение
{ выз о в
коэффициентов для первого ура в н е ния }
nроце дуры n o
име н и }
коэффициентов
nроце дуры n o
для
в торого ура в н е ния }
име ни }
ReadKey ;
End .
{ окончание
р а зд е л а
оnисания
л о г и ки
n р о г р а ммы }
277
Turbo Pascal 7 . 0
9 . 3 . П р оцедур ы и ф у нкци и с па р а метр а м и
Для передач и параметров уравнения а, Ь и с в процедуру в нашей про
грам ме используются соответствующие переменн ые, которым перед вызо
вом процедуры присваиваются некоторые значения , а процедура, обраща
ясь к ним как к глобальным переменным , уже может использовать их в
вычислениях и анализе. Однако в больших программах могут использоваться
сотн и процедур, и описание вспомогательн ых переменных для передачи в
каждую процедуру и функцию - довольно утомительное занятие. К тому
же для хранения этих переменных потребуется большой объем оператив
ной памяти .
Во всех языках программирования для передачи какой-либо информации в
процедуры и функции используется механизм параметров - оп и сание струк
туры дан ных, необходимой процедуре или функции для работы, заполняемое
при вызове подпрограммы. Описание такой структуры данных происходит в
заголовках процедур и функций после имени и имеет следующий вид:
P r o c e du re <Имя >
( < П а р аме т р 1 > : < Т и п п а р а м е т р а 1 > ;
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
1.
< П а р а ме т р N> : < Т и п п а р а м е т р а N> ) ;
ИЛИ ДЛЯ фуНКЦИ Й :
Func t i on <Имя >
( < П а р а ме т р 1 > : < Т и п п а р аме т р а 1 > ;
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
.
1
<Параметр N> : <Тип параме т р а N> ) : <Тип з н а ч е ни я > ;
Процедуры и функции обращаются к описанным в их заголовке пара
метрам так же , как и к локальным переменным , но только для чтения .
Таки м образом , парам етру нельзя присвоить новое значение, а можно
только прочитать текущее. При вызове параметры могут задаваться пе
ремен ными или константами соответствующих типов , перечисленными в
последовательности , заданной при описании подпрограмм ы .
В качестве примера приведем функцию , которая делит друг на друга два
вещественных (типа Real) числа, переданных ей в качестве п араметров.
Возвращаемым функцией значением будет результат деления, если дели
тель не равен нулю, и ноль, если делитель равен нулю (см . листин г 1 39).
· : :· ли���Щ:' 1 з� :Н.�������J�':rу�:;;ц�$:ур:�;::Фv��ц��;� � ·Q��·�·��-f'��:����1�rй'( ;:Jtl�i:
.. .
Program Divi s i o n ;
Function
SafeDiv ( a : Real ; Ь : Real ) : Real ;
{ з аголов ок функции , имя
S af eDiv , возвраща емое
з н а ч е ни е име е т тип Rea l , с трук тура п а р аме т р о в
с о с т о и т и з д вух чисел т ип а Rea l , к к о т орым
фун кция буд е т о браща т ь с я по име нам а и Ь }
-
278
Глава 9 . Ис пол ьз ова н и е п од п рограмм
begin
If Ь <> О
Then SafeDiv
: =
а/Ь
E l s e S a f e D iv
:=
О;
{ условный оператор , определяющий , какое з начение
в о з вр а т и т ь в к а ч е с т в е з н а ч е н и я функции .
П а р аметры , п е р е д а н ные функции , и с п о л ь з ую т с я
п о име нам , о п и с а н ным в з а г о л о в к е ( а и Ь ) }
end;
Begin
Wri t eLn ;
Wri t eLn ( Sa f eDiv ( l ,
2) );
{ вы з о в фун кции S a f eDiv с п а раметр ами 1 и 2 и
о д н о в р еме н ный вывод н а э кр а н з н а че н и я , к о т о р о е
о н а в о з в р а ща е т ( О . 5 ) }
Wri teLn ( Sa f eDiv ( l O O , О ) ) ;
{ вы з о в фун кции S a f eDiv с п а р аме т р а ми 1 0 0
и о д н о в р еме нный вывод н а э кр а н з н ач е ни я ,
к о т о р о е о н а в о з в р а ща е т ( О ) }
и
О
End .
Итак, использование параметров в подпрограммах аналогично использо
ванию локальных переменных, за исключением невозможности измен ить
их значения . В остальном же с ними можно делать все то же самое, что
и с переменными , например передавать в качестве параметров другим про
цедурам и фун кци я м .
Изменим программу вычисления корней квадратного уравнения так, что
бы п роцедура wri teRo o t s получала параметры анализируемого уравне
ния не через глобальные переменные, а через параметр ы , о писанные в
своем заголовке . Далее эти параметры будут передаваться еще и функ
ци и Di s c riminan t , вычисляющей дискриминант (см . листинг 1 40) .
'И,'·:J�i �*���.;i4fi ;>��.���if��·��,;�i)��t��:���a,�#I).�Ы;>·r-�кxl'#.���н��,: ;:�:'· : ;,;;::�:7�'J:'мt��;�
Program Root s 5 ;
Uses
CRT ;
Funct ion Di s c riminant ( a : Rea l ; Ь : Real ; с : Real ) : Real ;
{ з а г ол о в о к функции }
Begin
{ н а ч а л о р а здела о п и с а н и я л о ги к и функции }
Discriminant : = Ь*Ь - 4 * а * с ; { в о з в р а ща емо е з н а ч е н и е }
end ;
{ о к о н ч а н и е ра з д е л а о п и с а н и я л о г ик и функции }
Procedure Wri t eRoot s ( a : Real ; Ь : Rea l ; с : Real ) ;
{ заголовок процедуры , имя процедуры - Wri t eRoots }
Con s t
NoRoot s
=
1
Уравнение корней не имеет 1 ;
279
Turbo Pascal 7 . 0
OneRoot
ТwoRoo t s
=
=
' Уравнение имеет один корень : ' ;
' Уравнение имеет два корня : ' ;
Var
D,
Х1 ,
Х2 :
Rea l ;
Begin
{ н а ч а л о р а здела о п и с а ни я л о гики п р о ц е дуры }
D : = Di scriminant ( a , Ь , с ) ;
{ выз о в функции и п е р е д а ч а ей п а р аме тр о в ,
п олуч е н ных , в с в ою о ч е р е д ь , к а к п а р аме тры
п р о ц е дуры Wr i t eRo o t s }
I f D < О Then Wri t eLn ( NoRoot s )
Else I f D
Х1
: =
=
О Тhen begin
-Ь/ ( 2
* а) ;
Wri t eLn ( OneRoot ) ;
Wri t eLn ( ' X
',
=
Х1 ) ;
end
E l s e begin
Х1
Х2
: =
:=
( -Ь + sqrt ( D ) ) / ( 2
( -Ь - sqrt ( D ) ) / ( 2
* а) ;
* а) ;
Wri t eLn ( ТwoRoot s ) ;
Wri t eLn ( ' X1 = '
Х1 ) ;
Writ eLn ( ' X2
=
',
Х2 ) ;
end ;
end ;
{ о ко н ч а н и е
Begin
{ начало
раздела
р а здела
описания
описания
л о гики
л о ги к и
п р о ц е дуры }
п р о г р аммы }
ClrScr;
Wri t eRoot s ( 2 ,
Writ eRoot s ( 1 ,
12 ,
5,
11) ;
{ вы з о в процедуры п о име ни
п ар а ме тр о в 2 , 1 2 , 1 1 }
200 ) ;
{ выз о в процедуры по име ни
п араме т р о в 1 , 5 , 2 0 0 }
с
передачей
с
передачей
ReadKey ;
End .
{ окончание
раздела
описания
л о ги к и
п р о г р аммы }
9 . 4 . П роцедур ы и ф у н кци и
с па р а метр а м и - п е р емен н ым и
Функции очень удобны в использов а н и и , однако и меют довольно суще
ственное огран ичение - функция может возвращать только одно значе
ние . Тем не менее м ожно привести множество примеров, когда на осно
ве н ескольких параметров необходимо рассч итать н е с колько других.
Соответственно, появляется проблема: как вернуть несколько каких-либо
значений вызывающей программе (или подпрограмме) .
280
Глава 9 . И с пол ьз ование подпрограмм
Для решен ия проблемы механизм параметров подпрограмм дополнен так
называемыми параметрами-переменны м и . Перед описанием таких пара
метров в заголовках подпрограмм указывается ключевое слово Var . При
вызове подпрограм м , в которых параметры описаны таким образом , в
качестве этих параметров должны использоваться переменные, а и споль
зован ие констант недопустим о . Это связано с тем , что подпрограмма,
имеющая параметр- переменную , может изменять ее значение. Причем на
этапе разработки программы может быть неизвестно , какая именно п е
ременная будет использоваться в качестве параметра, но значение, при
своеиное п араметру- переменной, в качестве которого она задана, попа
дет именно в нее.
На низком уровне такая возможность реализована р аз н ы м и м етодами
передачи параметров в подпрограмм ы . Простые параметр ы , рассмотрен
ные нами выше, передаются по значению . Поэтому все , что м ожет знать
подпрограм ма о переданном ей параметре - это его значение. Что каса
ется параметров- переменных, то они передаются по ссылке, то есть под
программе передается не значение параметра, а адрес перемен н о й , кото
рая задана в качестве п араметра. Соответственно, подпрограмм а может
занести в переданный ей адрес любую информацию допустимого типа.
Несмотря на такие серьезные внутренние отличия, на уровне языка Turbo
Pascal нет ни какой разницы в работе с просты м и параметрами и пара
метрами - переменн ы м и . Исключение составляет лишь то , что параметры
переменные могут использоваться в левых частях операторов присваива
ния , то есть их значения могут быть изменен ы .
В качестве примера рассмотрим процедуру, получающую д в а простых
параметра
а и Ь
и два параметра- переменных, в которые заносятся
сумма и разность первых двух параметров (см . листинг 1 4 1 ) .
-
.·
-
:�·�g!�·� r' !�1·;r • ; �·&�·����«>.��.. ��\������*·�:�.��я����.�·;���!·:·.:
·
·
Program VarParams ;
Var
m,
n:
Intege r ;
Proc edure
SubSum ( а :
Var
Sub :
Intege r ;
Intege r ;
Ь:
Intege r ;
Var Sum :
Integer ) ;
{ з аголовок процедуры , н а з в а ние процедуры
SubSum , параме тры
а и Ь,
пар аме тры- п еремен ные
Sub и Sum }
{ н ачало ра здела описания л о гики процедуры }
{ и зме не ние параметра- переменной Sub }
{ и зме нени е параме т р а - переме н н о й Sum }
{ о кончание раздела описания логики процедуры }
-
-
-
begin
Sub
: =
а
-
Ь;
Sum
:=
а
+
Ь;
end;
281
Turbo Pascal 7 . 0
Begin
SubSwn ( 1 0 ,
{ н ачало раздела описания л о гики про гр аммы }
8,
m,
n) ;
{ выз ов процедуры SubSum , в каче с т в е параме тров
и Ь задается 1 0 и 8 , а в каче стве параме тров
Sub и Sum - пер еменные m и n }
а
Wri t eLn ;
Wri t eLn ( 1 Сумма :
End .
1,
n,
1 ,
Разность :
1 ,
m) ;
{ вывод сроки ' Сумма : 1 8 , Р а з н о с т ь : 2 '
с и с п ол ь з о в анием значений , з а н е с е нных
в переменные m и n процедурой SubSum
{ о кончание ра здела описания л о гики про граммы }
Приведем еще один пример использования параметров-переменных. Вспом
ним понятия «картинки>> и «маски» при создании спрайта с прозрачным
фоном. Процесс создания картинки вряд ли можно упростить, так как это
на самом деле и есть изображение спрайта, а вот маска создается на осно
ве картинки по совершен но определенным правилам - там , где на кар
тинке находится черный цвет, в маске должен быть белы й , а все осталь
ные цвета картин ки нужно заменить на черный.
Для перевода картинки в маску создадим процедуру, которая с помощью
вложенных операторов цикла For сканирует изображение по строкам и стол
бцам и осуществляет для каждой точки следующее преобразование: если цвет
точки является черным , то вместо нее нужно вывести белую точку. Опреде
лить, какой цвет имеет точка, можно, воспользовавшись функцией GetPixel
модуля Graph, вызываемой с двумя параметрами - координатами анализи
руемой точки - и возвращающей номер цвета в этой точке:
GеtРiхеl ( <Горизонтальная координата>, <Вертикальная координата> ) ;
Итак, наша процедура может выглядеть следующим образом :
Procedure MakeMask ( X1 , У 1 , Х2 , У 2 : Integer ) ;
{ з а г оловок процедуры , исполь зуе т с я ч е тыре
параме т р а , определ яющих пр ямоуг ол ь ник ,
в кот ором н а х о ди т с я с п р а й т }
Var
х , у : Integer; { п е р еменные дл я ис поль з о в а ни я
в к а ч е с т в е с ч е тчико в цикл а }
begin
{ н а ч ал о р а з дел а о п и с а н и я л о г и ки процедуры }
For у : = У 1 То У 2 Do
{ в н ешний ци кл , и зме няющий с ка нируемую с т р о ку }
For х : =Х1 То Х 2 Do
{ вложенный цикл , изменяющий сканируемый столбец}
If GetPixel ( x , у) = О
Then PutPixel ( x , у, 1 5 )
{ е сли точка ( х , у ) черна я , т о сделать е е белой }
282
Глава 9 . И с пол ьз ова н и е подпрограм м
Else Put Pixel ( x , у , О ) ;
{ и н а ч е , сдела т ь е е ч е рной }
{ о кончание раздела описания логики процедуры }
end;
Теперь заметим, что при создании спрайта вообще и спрайта с прозрачным
фоном в частности производятся одни и те же действия: определение объе
ма необходимой для спрайта памяти, выделение памяти, создани е спрайта,
вывод спрайта и, наконец, освобождение выделенной ранее памяти . Вне за
висимости от конфигурации спрайта для его создания , вывода и уничтоже
ния используются вызовы одних и тех же подпрограмм , отличающихся только
параметрами . Соответственно, можно упростить программу и создать для
каждого из этих действи й собственную подпрограмму, локализующую слож
ные процессы. Особенно это касается создания спрайта.
Для создания сп райта можно написать функцию , которая в качестве па
раметров п олучает координаты прямоугольника, охватывающего изобра
жение спрайта, и переменные типа Point e r , в которые следует занести
карт и нку и маску. Возвращаемым значением будет размер п амяти , выде
ленный фун кцией под с прайт-картин ку и спрайт- маску. При этом воз
вращаемое значение следует сохранить в какой-нибудь переменной , что
бы затем испол ьзовать для освобождения п амяти .
Function MakeTransSpri te (Xl , Yl : Integer ;
Х2 , У2 : Int eger ;
Var Pict : Pointer;
Var Mask : Pointer ) : Word ;
{ з а голо в о к функции , и с п ол ь зу е т с я ше с т ь
п а раме т р о в - ч е тыре дл я ука з а ни я пр ямоугол ь ни к а ,
и з к о т о р о г о следует с о з д а т ь с п р а й т , и д в а дл я
ука з а ни я п е реме нных , в кот орые следуе т з а н е с т и
спрайт - картинку и спр а й т - ма с к у }
Var
Spri t eS i z e : Word ;
{ п ер еме н н а я для пр омежут о ч н о г о х р а н е н и я
р а зме р а спрай т а }
begin
{ н а ч ало р а здела о п и с а н и я л о г и к и функции }
SpriteSi z e : = ImageSi z e ( Xl , Yl , Х2 , У2 ) ;
{ о пр е д ел е ни е р а змера спрай т а }
GetMem ( Pict , SpriteSi z e ) ;
{ выдел е н и е п амяти под спрайт - ка р т и н к у , в
к а ч е с т в е переме н н о й , под к о т о рую выдел я е т с я п а
мя т ь , и с п оль зуе т с я т а , к о т ор а я з а д а н а в к а ч е с т в е
п а р а ме т р а P i c t при выз о в е д а н н о й функции }
Get image ( Xl , Yl , Х2 , У2 , Pict A ) ;
{ с о з д а н и е спрайт а - картинки в п амяти , н а к о т орую
ука зыв а е т п е р еме н н а я , з а д а н н а я в к ач е с т в е
п а раме т р а P i c t при выз о в е д а нной функции }
MakeMask ( Xl , Yl , Х2 , У2 ) ; { с о з да н и е ма с ки и з к а р т и н ки }
283
Turbo Pascal 7.0
GetMem ( Mask, Spri teSi z e } ;
{ выд е л е н и е памяти под с п р ай т - ма с ку , в ка ч е с т в е
п е р еме нной , n о д кот орую выдел я е т с я п ам я т ь ,
и с п ол ь зуе т с я т а , к о т о р а я з а д а н а в к а ч е с т в е
п а раметра Mas k при выз о в е д а н н о й фун к ции }
Getimage ( Xl , Yl , Х2 , У2 , MaskA ) ;
{ с о з д а н и е с п р а й т а - ма с ки в памяти , на к о т орую
ука зыв а е т п ереме н н а я , з а д а н н а я в к а ч е с т в е
п а р аме т р а Mask при выз о в е д а н н о й фун кции }
end;
{ о кончание раздела опис ания логики функции )
Также можно упростить процесс последовательного вы вода м аски и кар
тинки на экран , чтобы н е вспоми нать каждый раз, какие м етоды вывода
для этого следует использовать, и избежать ошибок из-за отличия коор
динат маски и картинки .
Procedure PutTransSpri te ( X , У : Integer ;
Mask, Pict : Pointer } ;
{ з а г оло в о к процедуры , п а р аметры Х и У
о п р е деляют опорную точку вывода с пр а й т а
и ма с ки , и картинки }
begin
{ н а ч ало р а здела о п и с а н и я л о г и ки п р о ц е дуры }
Put image ( X , У, Mask A , ANDPut } ;
{ вы в о д с пр а й т а - картинки в координ а т ы , з а д а нные
п а р аме тр ами Х и У , ме с т о в п амя ти о п р е д ел я е т с я
п е р еме нной , з а д а н н о й в к а ч е с т в е п а р аметра Ma s k
п р и выз о в е процедуры }
Put image ( X , У , P i ct A , ORPut } ;
{ вывод с п р а й т а -ма с ки в коорди н а ты , з а да н ные
п а р а ме т р ами Х и У , ме с т о в п амяти о п р е д ел я е т с я
п е р еме нной , з а да н н о й в к ач е с т в е п а р а м е т р а Ma s k
п р и выз о в е проце дуры }
end;
{ о кончание раздела опи сания логики процедуры)
И, наконец, можно вынести фрагмент, освобождающий п амять, задан
ную под спрайты .
Procedure FreeSpriteМem(Var мask, Pict : Pointer; SpriteSize : Word} ;
{ з а голо в о к процедуры , три п а р а ме т р а о п р е д еляют
п е р еменные , и з - nод кот орых сл едует о с в о б о ди т ь
п а мя т ь и е е р а з ме р }
begin
{ н а ч ало р а здела о п и с а н и я л о г и ки п р о ц е дуры }
FreeMem ( Pict , SpriteSi z e } ;
{ о с в о божд е н и е памя т и и з - п од п е р е ме нной , з а да н ной
в к а ч е с т в е п а р аме т р а Pict при выз о в е п р о ц е дуры }
FreeMem ( Mask, SpriteSi z e } ;
{ о с в о божд е н и е памя т и и з - nод п е р еме н н о й , з а д а н н о й
в к а ч е с т в е п а р аме т р а Mas k п р и выз о в е п р о ц е дуры }
end;
{ о кончание раздела описания логики nроцедуры )
284
Глава 9 . И с пол ьз ование подпрограмм
Таким образом , программа TransparentSpri t e (см . листин г 0 8 3 ) с ис
п ол ьзован и е м таких про цедур будет в ы глядеть следующ и м образом
(см . листинг 1 42) .
,:', ;•� истй·�·�·. ·1:·4� ::�.��о���·Q ��it,ие, · ·[�§Цe4m;:�;::::)':;: : if�J� '�:1r��.::�i:;�r::i;:f:. :J�(J';;ю:;:;;·�;z�rii�:!�(;f:
..
P rogram Transparent Spr i t e 2 ;
Uses
Graph ,
CRT ;
Var
GraphDrive r ,
GraphМode :
Integer ;
SprS i z e :
Word ;
P i c ture ,
Mask : Point e r ;
{ с сыл очные п е ременные
Procedure MakeMask ( X 1 ,
{ описание
Va r
х,
У1 ,
Х2 ,
д л я хр а н е н и я м а с к и
Integer ) ;
и
к а р т и н ки }
У2 :
п р о ц е дуры п р е о бр а з о в а н и я
к а р т и н ки
в
ма ску }
у : Int eger ;
begin
For у : =У1 То У2 Do
For х : =Х1 То Х2 Do
у)
I f Get P i xe l ( x ,
E l s e Put Pixel ( x ,
end;
=
у,
О
у,
Then PutPixe l ( x ,
0) ;
Function MakeTrans Spri t e ( Х1 ,
Var P i c t :
Var Mask :
У1 :
Pointer ;
Point er ) :
Intege r ;
15 )
Х2 ,
У2 :
Intege r ;
Word;
{ о п и с а н и е фун кции с о з д а н и я с п р а й т а с п р о з р а ч ным
ф о н ом на о с н о в е карт и н ки , ма с к а с о з д а е т с я
в нутри фун кции }
Var
Sprit e s i z e :
Word ;
begin
Spri t e S i z e
:=
Image Si z e ( X1 ,
GetMem ( P i c t ,
Spr i t e S i z e ) ;
Get image ( X1 ,
У1 ,
Х2 ,
У2 ,
MakeMask ( X1 ,
У1 ,
Х2 ,
У2 ) ;
GetMem ( Ma s k ,
Spri t e S i z e ) ;
Get image ( Xl ,
У1 ,
Х2 ,
У2 ,
У1 ,
Х2 ,
У2 ) ;
P i ct " ) ;
Mask " ) ;
end;
Procedure
Putтrans Spri t e ( X ,
У:
Intege r ;
Mask ,
Pict :
Pointer ) ;
{ о п и с а н и е проце дуры выв о д а сп р а й т а
с п р о з р а ч ным ф о н ом н а э к р а н }
begin
Put image ( X ,
У,
Mask " ,
ANDPut ) ;
285
Turbo Pascal 7 . 0
Put image ( X ,
У,
P i ct " ,
ORPut ) ;
end;
Procedure
Word ) ;
FreeSprit eMem ( Var Mask ,
Pict :
Point e r ;
Spri t e S i z e :
{ о п и с а н и е процедуры очи с т ки памяти ,
з а н я т о й п о д к а р т и н ку и ма с ку }
begin
FreeMem ( P i c t ,
Spr i t e S i z e ) ;
Fre eMem ( Mask ,
Spri t e S i z e ) ;
end;
{ начало
Begin
GraphDri ver
GraphМode
:=
: =
п р о гр аммы }
Detect ;
О;
Init Graph ( GraphDr iver ,
SetLineStyle ( S o l i dLn ,
GraphМode ,
О,
1 1
)
;
ThickWidth ) ;
SetColor ( Wh i t e ) ;
SetFi l l Style ( S o l i dF i l l , Red ) 1 { у с т а н о в к а
т е кущи х х а р а к т е р и с ти к }
F i l 1El l ip s e ( 1 0 0 ,
100,
90,
SetFi l l Styl e ( S o l idFi l l ,
F i l 1E l l ip s e ( 1 0 0 ,
SprSi z e
100,
г р а фич е с к о г о
р е жима
и з о бр а ж е н и я
к о л ь ца }
и
90) ;
B lack ) ;
70,
{ выв од
70) ;
MakeTransSprite ( 9 , 9 , 1 9 1 , 1 9 1 , P i cture , Mask ) ;
{ с о з д а н и е спрай т о в для картинки и ма с ки
в п е р еме н ны х P i c ture и Mask , а т а кже с о х р а н е ни е
р а змера ма с ки и картинки в п е р еме н н ой SprS i z e }
: =
C l earDevi c e ;
SetFi l l Style ( So l i dFi l l ,
Bar ( O ,
О,
63 9 ,
Blue ) ;
479 ) ;
SetRGBPalet t e ( B lue , О , О , 1 0 ) ;
{ оч и с т к а э кр а н а
PutTran s Spri t e ( 5 0 ,
50,
Mask ,
и
вывод
син е г о
фона }
P i cture ) ;
Putтrans Spri t e ( 1 5 0 , 5 0 , Mas k , P i cture ) ;
{ вы во д дву х о ди н а ко вы х с п р ай т о в с п р о з р а ч ным
ф о н ом н а э к р а н в р а з ные коорди н а ты }
Free Spri t eMem ( P i c ture , Mask , SprS i z e ) ;
{ освобождение памяти , занятой под ма ску и
картинку }
ReadKey ;
C l o s eGraph ;
End .
286
{ о жид а н и е н а ж а т и я н а кл а в ишу , з а крыти е
графич е с к о г о р е жима и о к о н ч а н и е п р о г р аммы }
Глава 9 . И с пол ьз ование под п рограмм
9 . 5 . П он я т ие п роцедурно г о ( м одул ьно г о )
п рогр а м м и ров а н ия
Еще одним достоинством подпрограмм (процедур и функций) , помимо сокра
щения объема исходных текстов программ, является их логическая закончен
ность, то есть выполнение ими какой-либо определенной, обычно небольшой,
задачи полностью. Во всяком случае, процедуры и функции должны создаваться,
исходя именно из такой предпосьшки.
П р и м еч а н и е .
Р е ко м ендует с я ра сс ч и ты вать объе м те к ста п ро цедуры ил и функци и таки м
о б разо м , что б ы он п о м ещал с я п о л н о ст ь ю н е б олее ч ем на одну -две с тран и цы
тек с то в о г о редакто ра, в которо м разра б аты вает с я п рогра м м а . То гда разра
б отч и к с м ожет охватить вз г лядо м ве сь те к ст п од п р о г ра м м ы .
И спользование подпрограмм упрощает структуру программ и повышает их
читабельность. Например, раздел описания логики первоначального вари
анта программы расчета корней квадратного уравнения (листин г 1 3 5) был
перепалиен излишними подробностями довольно сложного алгоритма оп
ределения корней и их количества, в то время как основная часть конечно
го варианта программы (листинг 1 40) содержит только вызовы процедуры
Wri teRoo t s , которая прячет в себе всю эту сложную логику, требуя только
передать ей параметры, необходимые для вычислений . А работать с пара
метрами очень просто, так как они отражают не логику программы, зало
женную программистом, а логику части автоматизируемого процесса (в дан
ном случае - процесса вычисления) .
Эrо особенно важно, когда разработчику приходится использовать фрагменты
программы, разработанные другими программистами . В данном случае раз
работчика не интересуют подробности реализации алгоритма, его интересу
ет только список параметров, который необходимо передать подпрограмме,
и формат возвращаемых подпрограммой результатов. Заголовок подпрограм
мы является интерфейсом , предоставляемым данной процедурой или функ
цией вызывающей программе.
Таким образом , програм мирование переходит на новый, более абстракт
ный уровень
процедурное программирование, называемое также модуль
ным , то есть основанным на строении программ ы из логически зако н
ченных модулей .
-
С появлением процедурного программирования появляется возможность
более простого поддержания крупных проектов по разработке програм м
нога обеспечения как в смысле объема исходных текстов программ , так
и в см ысле увеличения числа разработч иков одного програм мнаго про
дукта. При этом разработчики могут обмениваться между собой не про
сто фрагментам и програм м , а процедурами и функци я м и , имеющими
сложн ые внутренние структуры данных, и о которых ничего или практи
чески ничего не нужно знать тому, кто их использует.
287
Turbo Pascal 7 . 0
9 . 6 . Библ иотеки п ро цедур и ф у н кци й
Для более удобного использован ия н акопленного объема п одпрограмм
возможно объединение их в библиотеки (модули) - отдельные файлы с
промежуточным программ н ы м кодом (объектные файлы ) . Эти модули в
случае необходимости подключаются в разделе подключения модулей Uses
(не путать с понятием модуля как логической единицы програм м ы ) .
Обычно процедуры и функции, включаемые в библиотеки, обладают общей
функциональной направленностью, то есть близки друг другу по выполняе
мым задачам . В качестве примера можно привести стандартный модуль CRT,
в который включены процедуры и функции, осуществляющие какие-либо дей
ствия с клавиатурой и экраном в текстовом режиме ( CRT - сокр. от англ.
Cathode-Ray ТUЬе - электронно-лучевая трубка) , то есть с тем , что принято
называть консолью. Еще один пример модуля - стандартный модуль Graph,
содержащий процедуры и функции работы с экраном в графическом режиме.
Исходн ы й текст м одуля располагается в отдельном файле н а диске и
содержит три основные секции:
•
•
•
Интерфейсная секция , в которой располагаются заголовки проце
дур и функци й , составляющих модул ь.
Описательная секция, в которой располагаются описания процедур и
функций , заголовки которых указаны в интерфейсной секции , а также
другие процедуры и функции , используемые подпрограммами данно
го модуля, но недоступные программам , подключающим модуль.
Секция и н ициал изации (не обязательна) , содержащая команды, ко
торые н еобходимо в ы п олнить при подключе н и и м одуля к програм
ме. Благодаря этому п еред выпол нением како й -либо программ ы , к
которой подкл ючаются внешние модул и , сначала в ы п олняются и н и
циализационные ч асти модулей ( в порядке п одключения) .
М одул ь имеет следующую структуру:
unit <Название> ; З а голо в о к модул я
Interface
У к а з а ние на н а ч а л о и н т ер ф е й с н о й с е кции
Uses
Р а здел подключ е н и я мо дул ей
Const
Р а здел описания к он с т а н т
Туре
Р а з дел о п и с а ни я т и п о в д а н ных
Var
Procedure
Funct ion
288
Р а здел описания п е р еме н ных
Р а здел о п и с а ни я з а г ол о в к о в п р о ц е дур и функций
Глава 9 . И с пол ьз ова н ие подпрограмм
Implementat ion Ука з а ни е н а н а ч ал о опис а т ел ь н о й с е кции
Uses
Р а здел по дключ ения модул е й
Label
Р а з дел о п и с а н и я ме т о к бе зусл о в н о г о п е р ехода
Const
Р а з дел о п и с а ни я конст а н т
Туре
Р а здел опис а ни я т и п о в д а н ных
Var
Р а здел описания п е р емен ных
Procedure
Function
Р а здел о п и с а н и я процедур и функций
Н а ч ал о р а здела и нициали з а ции ( н е о б я з а т ел ь но )
Р а здел описания логики и нициали з а ции
Окончание р а з дела иници ализ ации
begin
end;
Заголовок модуля в отличие от заголовка программы должен указываться
обязательно, так как название модуля используется программой, которая его
подключает для получения доступа к описанным в нем процедурам и фун
кциям . Имя файла с исходным текстом модуля должно быгь таким же , как
название модуля, поэтому название модуля не должно превышать восьми сим
волов
системного ограничения MS- DOS на длину имен файлов.
-
Создадим модуль для работы со спрайтами с прозрачн ы м фоном , содер
жащ и й фун к ц и и , о п и с а н н ы е в п редыду щ е м р аздел е : M a k e M a s k ,
МakeTransSpri te, PutTransSpri te, FreeSpri teМem (cм. лиcтинг l 43 ) . По
скол ьку п р о ц едура MakeMa s k и с пол ьзуется только в нутри фун к ц и и
MakeTrans Spri t e , т о е е заголовок н е следует размещать в интерфейсной
секции модуля . Таким образом , данная процедура не будет доступна в про
грамме, которая подключает разрабатываемый модуль.
Секция инициализации в нашем модуле будет отсутствовать, так как нет необ
ходимости в выполнении каких-либо действий в начале программы. Хотя там
можно было бы разместить команды инициализации графического режима.
Uni t
Tran s Spr ;
{ з а г ол о в о к модул я , ф айл , в к о т ор ом н а х о ди т с я
модул ь , д о л же н име т ь и мя Tran s Spr . pa s }
{ н а ч а л о и н т е р ф е й с н о й с е кции }
Interface
Uses
Graph ;
Function MakeTrans Spri t e ( X l , Yl : Intege r ; Х2 , У2 :
Var P i c t : Point e r ;
Var мask : Point er ) : Word;
10
Зах. 702
Intege r ;
289
Turbo Pasca/ 7 . 0
Proc edure
Putтran s Spri t e ( X ,
У:
Int ege r ;
Mask ,
Pict :
Point er ) ;
Procedure FreeSpriteМem (Var мask , Pict : Pointer; SpriteSize :
{ опи сани е заголов ков проц е дур и функций }
{ начало
Impl ement a t i on
Procedure MakeMa sk ( X l ,
Va r
у:
х,
описа тель ной
Yl ,
Х2 ,
У2 :
Word) ;
с е кции }
Integer ) ;
Intege r ;
begin
For y : =Yl То У2 Do
For x : =Xl То Х2 Do
If
Get P ixel ( х ,
у)
= О
у,
E l s e PutP ixel ( x , у ,
Then PutP ixel ( x ,
end ;
15)
0) ;
Funct ion MakeTrans Sprite ( X l ,
Х2 ,
У2 :
Yl :
Integer ;
Int ege r ;
Var Р ict :
Point e r ;
Var Mask :
Point e r ) :
Word ;
Va r
SpriteS i z e :
Word ;
begin
Spri t e S i z e
:=
Image S i z e ( Xl ,
GetMem ( P i c t ,
Spr i t e S i z e ) ;
Get image ( Xl ,
Yl ,
Х2 ,
У2 ,
MakeMask ( X l ,
Yl ,
Х2 ,
У2 ) ;
GetMem ( Mask ,
Spri t e S i z e ) ;
Get image ( Xl ,
Yl ,
Х2 ,
У2 ,
Yl ,
Х2 ,
У2 ) ;
P i ct " ) ;
Mask" ) ;
end;
Proc edure
PutTrans Spri t e ( X ,
Ma sk ,
Pict :
У:
Int eger ;
Pointer ) ;
begin
Put image ( X ,
У,
Mask " ,
ANDPut ) ;
Put image ( X ,
У,
P i ct " ,
ORPut ) ;
end;
Procedure FreeSpriteMem (Var мask,
Pict :
Pointer;
SpriteSize :
Word) ;
begin
Fre eмem ( P i c t ,
Spr i t e S i z e ) ;
Fre eмem ( Mask ,
Spri t e S i z e ) ;
end;
{ о пи с а н и е в с е х п р оц е дур и фун кций , ук а з а н ных
в и н т е р ф е й с н о й с е кции , и пр о ц е дуры MakeMa s k ,
н е ук а з а н н ой в и н т е р ф е й с н ой с е кции , и п о э т ому
д о ступн о й т ол ь к о внутри д а н н о г о мо дул я }
end .
{ о к о н ч а ни е м о д у л я , и ници а ли з а ци о н н ый р а з д е л о т су т с т в у е т }
290
Глава 9 . Ис пол ьз ование подп р о гр а м м
теперь испол ьзуем модуль в программе (см . листинг 1 44) . Перед ком
п иляцией програм м ы необходи мо снач ала отко м п илировать м одуль с
помощью выбора пункта Compile 1 вui ld главн ого меню и нтегрирован
н о й среды разработч и к а . Пе ред этим следует уста н о в ить п а р а м етр
Compi l e 1 Dest inat ion в положение D i s k. После успешной ком п иляции
модуля файл с именем данного модуля и расширением tpu должен на
ходиться в одн о м каталоге с программой, которая его использует.
А
:;;:; :П'� «ir'� �t:·· 1 :�'4Ч<rr��rP�.м ��� ;.й �·бБ���\i.6Щ��;;��дy.n:�·���rii�-��::. ·.::, , ;.,.: "' ;;:: �::: · ..
Program Tran sparent Sprit e2 ;
Uses
Graph ,
CRT ,
Va r
GraphDrive r ,
TransSpr ;
GraphМode :
Integer ;
SprS i z e : Word;
{ п е р еме нные для хр а н е ни я
P i cture , Mask : Point e r ;
Begin
{ н а ч а л о пр о гр аммы }
GraphDri ver : = Detect ;
GraphМode : = О ;
Init Graph ( GraphDrive r ,
SetLineStyle ( S o l i dLn ,
SetColor ( Wh i t e ) ;
GraphМode ,
О,
ма с ки
и
к а р ти н ки }
' ' );
Thi ckWidth ) ;
SetFi l l S tyle ( So l i dF i l l ,
Red ) ; { у с т а н о в к а г р а ф ич е с к о г о р ежима и
т е к ущи х х а р а к т е р и с ти к }
F i l lE l l ip s e ( l O O , 1 0 0 , 9 0 , 9 0 ) ;
SetFi l l Styl e ( So l idFi l l , Black ) ;
{ выв од и з о бр а же ни я к о л ь ц а }
F i l 1E l l ipse ( 1 0 0 , 1 0 0 , 7 0 , 7 0 ) ;
SprS i z e : = MakeTransSpri te ( 9 , 9 , 1 9 1 , 1 9 1 , P i c ture , Ma sk ) ;
{ с о з д а ни е с п р ай т о в для к ар ти н ки и ма с ки
в пер еме нных P i c ture и Mas k , а т а кже с охр ан ени е
р а змера ма ски и к ар тин ки в п ереме нн ой SprS i z e }
C l earDevi c e ;
S e t F i l lStyle ( So l i dF i l l , B lue ) ;
Bar ( O , О , 6 3 9 , 4 7 9 ) ;
SetRGBPalet t e ( Blue , О , О , 1 0 ) ;
{ о чи с т к а э кр а н а и выв од си н е г о ф о н а }
PutTransSpri t e ( 5 0 , 5 0 , Mask , P i c ture ) ;
PutTransSpri t e ( 1 5 0 , 5 0 , Ma sk , P i cture ) ;
{ выв о д д вух оди н а к о вых спр а й т о в с п р о зр а ч ным
ф о н ом н а э кр а н в р а з ные к о ор ди н а ты }
FreeSprit eMem ( P i c ture , Mask , SprS i z e ) ;
{ освобождение памяти , занятой п од маску и картинку }
ReadKey;
C l o s eGraph ;
End .
{ о жид а ни е н ажа ти я н а кл а в ишу , з а кры т и е
г р а фич е с к о г о р е жима и о к о н ч а ни е п р о гр аммы }
291
Turbo Pascal 7 . 0
П роцедура 4
Процедура 5 -. гПроцедура 6
Функция 4
Функция 5
Фу нкция б - 1-
П роцедура 1
П роцедура 2
г' П роцедура 3 ...,.
Функция 1 -+- Функция 2
Функция 3
Модуль 1
• 1:-
L\_j
;;;
=
-
=
=
Модуль 2
• - -[Ш]
=
-
-
П рограмма
1
П1
;;;
П1
-[Ш]
�
-
�-�
L=\= J�
-
г-
-
=
=
=
-
П рограмма 2
1 1 5. Иерархическая
структура программ
Рис.
Таким образом , библиотеки проце
дур и функций позволяют выносить
оп исан ия процедур и функций , ко
торые редко изменяются , и остав
лять в основной ч асти програм мы
только логику работы , что положи
тел ь н ы м образом с казы вается на
удобстве реализации крупных про
граммных продуктов. Еще одним до
стоинством библиотек является воз
м о ж н о с т ь их и с п о л ь з о в а н и я в
нескольких програм м ах. Структура
разрабатываемого проекта (или не
скольких) при использован и и биб
лиотек функций приобретает иерар
хическую структуру, аналогич ную
показаиной на рис. 1 1 5 . На дан ном
рисунке отображены следующие воз
можност и работы с п р о цедурами ,
функция ми и модуля м и :
1 . Програм м ы и с п ол ьзуют процедуры и фун кци и , о п исанные в м о
дул ях ил и о п и санные в своих разделах оп исания п одпрограмм .
2 . Процедуры и функци и , о п и с ы ваем ы е в модулях, м о гут испол ьзо
вать п одпрограмм ы , оп исан н ы е в других модулях.
3. На один и тот же модул ь могут ссылаться нескол ько программ ил и
м одулей .
К онтрол ь н ы е вопрос ы и от в ет ы
В ч е м з а кл ю ч а ется принцип процедурного п рогра м м и рования?
Для сокраще н и я кол ич ества п о вторя ющихся несколько раз фрагментов
программ ы {если этого н евозможно достичь, испол ьзуя зацикл и вание) воз
можно использование подпрогра м м . П рограм м и рован и е с использован и
ем п одп рограмм назы вают про цедур н ы м или модул ьн ы м , основан н ы м
н а постро е н и и п рограм м ы из отдел ьных л о гически зако н ч е н н ых м одул е й ,
которые м огут п олучать н а входе н екото рые дан н ы е и возвращать резул ь
тат своей работы также в виде дан н ых.
Какие виды подпрогр а м м предусмотрены в Turbo Pascal?
В Turbo P a s c a l п редусмотрено два в ида подп рограм м : п р оцедур ы и фун к
ци и . П роцедуры - логически закончен н ы е части п рограм м ы , о п и с ы вае
м ы е отдел ьно от раздел а оп исан и я логики п рограм м ы и вызы вае м ы е по
и м е н и , ун и кал ьному в п ределах п рограм м ы , а также функции - п р о цеду
р ы , возвращающие резул ьтат своей работы в виде н е кото р о го з н а ч е н и я ,
тип которого указывается при о п исан и и фун кци и .
292
Глава 9 . Испол ьзование подпрограмм
Посредством каких механизмов производится
передача д анных подпрогра м м а м и фун кци я м ?
Дл я управл е н и я процессом в ы пол н е н и я процедур и фун кций испол ьзуют
ся параметр ы , пе редаваемые им при вызове. П одпрограм м ы о б ращаются
к параметрам как к локальн ы м переме н н ы м . П р и этом воз м ожн о исполь
зован и е двух механ измов передач и параметро в :
•
по з н а ч е н и ю , ко гда п одп рограмма н е м ожет и з м е н ить значение пара
метр а ;
•
по ссылке, когда п одп рограм м е передается адрес переме н н о й , зада н
н о й в качестве параметра, и о н а может измен ить з н аче н и е в н е ш н е й пе
ремен н о й , заданной в качестве параметра . Испол ьзован и е пе редач и па
р а м ет р о в по с с ы л к е т р е б уется , что б ы о р г а н и з о в ат ь п ол уч е н и е от
п одп рогра м м ы более одн ого результирующего з н ач е н и я .
Возможно л и в Tu rbo Pascal объеди нять п ро цедуры
и функци и в отдел ьные модул и?
Дл я п о в ы ш е н и я удобства процедуры и функции м ож н о объеди н ить в б и б
л и отеки ( м одул и ) , п одключаемые к программам в раздел е п одкл ю ч е н и я
модул е й Uses .
Из каких секци й состоит и сходный текст м одул я ?
Исходн ы й текст м одуля располагается в отдел ь н о м ф а й л е н а диске и со
де ржит три основные секци и :
•
И нтерфейсная секци я , в которой располагаются загол о в к и про цедур и
фун кци й , составл я ющих м одул ь.
•
О п и сател ьная секци я , в которой располагаются о п и сан и я п р оцедур и
фун кци й , заголовки которых указаны в и нтерфей с н о й секци и , а также
другие п р о цедуры и фун кци и , испол ьзуе м ы е п одп рогра м м а м и дан н о го
м одул я , но н едоступ ные п рограм м а м , п одкл ючающим м одул ь.
•
Секция и н и циализации ( н е обязател ьна) , соде ржащая ком анды , кото
р ы е необходи мо в ы п ол н ить п р и подкл ю ч е н и и м одуля к п рограм м е . Та
ким образ ом , п е ред в ы п ол н е н ием како й - л и б о програ м м ы , к кото р о й
п одкл ючаются внеш н и е м одул и , снач ала в ы п ол н я ются и н и циал изаци
о н н ые части модулей ( в п о рядке п одкл юч е н и я ) .
В ч е м з а ключ ается преи мущества использ о в а н и я
процедур ного п рограммирования?
П р о цедурное п рограм м и рован и е , п ростое на п е р в ы й взгляд, п редоста в
ляет о ч е н ь м о щ н ы е средства для разработки слож н ых п рограм м н ы х п р о
дукто в , п озволяя использо вать фрагменты програм м , нап исан н ы е друг и
м и программистам и , б е з углубле н и я в логику сам о й п одп рограм м ы . Для
использован ия процедуры или фун кции необходи мо тол ько пон имание того
п ро цесса, с кото р ы м подп рогра м м а связан а .
293
С л о жн ы е т и п ы дан н ых
М ы уже указы вал и на то, что практически все программы работают с
какой-либо информацией . Для представления информац и и в програм ме
используются перемен ные, находящиеся в оперативной п амяти и имею
щие определенный тип данных. С помощью переменных можно оп исать
характеристики любого объекта или процесса, однако такие описания не
всегда удобны, так как рассмотренные нам и тип ы данных я вляются п ри
митивными и не подходят для описания крупных явле н и й .
Для целостного представления и нформации примитивные данные объе
диняются в более крупные структуры . Такое объединение может проис
ходить по двум направлениям (см . рис. 1 1 6) :
-•
..
�
+
Масси в ы
Разно родные
еди н и цы
и нфо рмации
\
Зап иси
Рис. 1 1 б. Фор мир ование
ма ссивов и записей
из разнородных единиц
информации
294
Объединение однородны х пере м е н н ых
для представления п о следовательносте й .
Структуры , получае м ы е в резул ьтате
объединения однородн ых п ереме н н ых,
называются массивами.
• Объеди нение разнородн ых п ереме н н ых
для полного представления одной еди
н и цы некоторой сущности . Структуры ,
п олучаемые в результате объеди н е н ия
разнородных переме н н ы х , назы ваются
записями.
Заметим , что записи, представляющие одну и
ту же сущность, я вляются одн ородным и , по
этому записи могут объединяться в м асси вы,
в результате чего получаются структуры , на
зываемые массивы записей .
•
Глава 1 0 . Сл ожные ти п ы дан н ы х
1 о. 1 . М ассив ы
Рассмотрим программу (см. листинг 1 45) , вычисляющую среднюю темпера
туру за пять месяцев на основе средних температур по месяцам, вводимых
пользователем . Таким образом, нам необходимо орган изовать ввод пяти
чисел, затем сложить их и разделить на 5, получив среднюю температуру.
H:;i!�,qj�}t_r_;�-��-� :;���:it�SП��.��i-c J>e;4���-j��I"J.�H-�����I.>:�i ::,;;;:·;;;�_-·::-� :•- :;·:�:i};._ � ::,:�::l:
Program Temperature 1 ;
Uв е в
CRT ;
Va r
t1,
t2 ,
tЗ ,
t4 ,
Тв : Real ;
Begin
t S : Real ;
{ п е р е м е нны е для ср е дн е м е с я ч н ых
{ с р е д н я я т е мп е р а т ур а }
т е мп е р а тур }
ClrScr;
Wri te ( ' Введите
темnературу
за
месяц 1 :
');
темnературу
за
месяц 2 :
');
темnературу
за
месяц 3 :
•);
темnературу
за
месяц 4 :
');
темnературу
за
месяц 5 :
');
ReadLn ( t 1 ) ;
Wri t eLn ;
Wri t e ( ' Введите
ReadLn ( t 2 ) ;
Wri t eLn ;
Writ e ( ' Введите
ReadLn ( t З ) ;
Wri t eLn ;
Wri te ( ' Введите
ReadLn ( t 4 ) ;
Wri t eLn ;
Writ e ( ' Введите
ReadLn ( t S ) ;
Wri t eLn ;
Тв
:=
tl
Тв
:=
Тв / 5 ;
+
t2
+
Wri t eLn ( ' Средняя
t З + t4 + t S ;
{ в ычи сл е ни е суммы в в е д е нных т е мп е р а тур }
{ д е л е ни е суммы т е мп е р а тур н а 5 для п олуч е ни я
с р е дн е г о з н а ч е ни я }
темnератур а :
{ в ыв о д ср е дн е й
Тв ) ;
т е мп е р а туры н а
э кр а н }
ReadKey ;
End .
В приведеиной программе есть пять похожих друг н а друга фрагментов,
испол ьзуемых для ввода среднемесячных температур :
295
Turbo Pascal 7 . 0
Wri t е ( ' Введит е т емnературу за ме сяц 1 :
' ) ;
{ п одска з к а поль з о в а т елю в в е с т и т емп е р а туру
за п е р в ый ме с я ц }
{ в в о д з н а ч е н и я с кл а в и а туры и з а н е с е н и е
е г о в п е р емен ную t 1 }
{ п е р е в од строки }
ReadLn ( t 1 ) ;
Wri t eLn ;
Фрагменты отличаются друг от друга номером месяца в подсказке ( 1 , 2 ,
3 , 4, 5) и цифрой , используемой в названиях переменных ( t 1 , t 2 , t З ,
t 4 , t 5 ) . Таким образом , напрашивается использован ие оператора цикла
For для замены всех таких фрагментов одн и м циклом :
For
:=
i
1
То 5 Do
{ о п е р а т о р цикла с о сче тчиком i ,
изме н я емым о т 1 до 5 }
Begin
• , i, ' : ' ) ;
{ п одска з к а пол ь з о в а т елю в в е с т и
т емп е р а туру з а ме с я ц н о м е р i }
{ в в о д з н а ч е н и я с кл а в и а туры и з а н е с е н и е
е г о в п е реме нную t )
{ п е р е в од с троки }
Wri t е ( ' Вв едит е т емпературу з а месяц
ReadLn ( t i ) ;
Wri t eLn ;
end ;
А
сумм ирование переменных можно было бы реализовать так:
Т := О;
For i
:=
1
То 5 Do
{ о б нул ение п е р еме нной Ts }
{ о п е р а т о р ци кла с о с ч е тчиком i ,
и зме н я емым о т 1 до 5 }
{ н а каждом шаге цикла происходит добавление
з н а ч е ни я о ч е р е дной п е р еме н н о й к з н а ч е нию
п е реме нно й Ts , в р е зул ь т а т е ч е г о после
о к о нч а ни я цикла в п е р еме нной Ts буд е т
н а ходит ь с я сумма в с е х п я т и п е р еме нных }
Однако переменные не допускают использования в своих именах таких
индексов - переменная должна быть указан а именно так, как описана в
разделе var . Соответственно, зацикливание такого рода невозможн о , и
при увеличении количества анализируемых месяцев объем программ ы
будет возрастать как м и н и мум н а три строки для каждого месяца. М ож
но посчитать, напри мер, сколько строк будет занимать программа, вы
числяющая среднюю температуру за 1 00 лет, то есть за 1 200 месяцев.
Примечание .
И с п о л ьз о в а н и е и ндексов в и м е нах п е р е м е н н ы х до пусти м о в б о л ь ш и н ст в е
и нт е р п рети руе м ых я з ы к о в п ро грам м и р о ван и я . П р о гр а м м ы , н а п и са н н ы е н а
Tu rbo Pascal , я вл я ются ко м п ил и руе м ы м и , соответст в ен н о , п е р е м е н н ы е дол ж
н ы и с п ол ь з о в ать ся п о те м и м ен а м , с кото р ы м и о н и о п и са н ы уж е на этап е
н а п и с а н и я те к ста п ро грам м ы .
296
Глава 1 0 . Сложные тип ы дан н ы х
Для реализации индексированного доступа к переменным одного типа
предусмотрены сложн ые типы данных, называемые массивом .
1 о. 1 . 1 .
Описание массивов
Массив - поименованная область памяти , доступ к отдельным частям кото
рой осуществляется по общему имени и индексу соответствующей части.
Можно дать еще одно определение массива, более точно отражающее
механ изм работы с н и м : массив - группа переменных одного типа (эле
ментов массива) , названная одни м именем и им еющая индексный меха
низм доступа к каждой переменной этой групп ы .
Оп исание массивов включает в себя указание, и з перемен ных какого типа
должен состоять массив, сколько в нем должно быть элементов и какие
индексы должны быть использован ы для доступа к его элементам:
Var
<Имя ма с си в а > : Array [ < Нижний инде к с >
<Ти п элеме н то в > ;
•
•
< В ерхни й и н д е к с > ] Of
Для Имени массив а применяются идентификаторы, отвечающие тем же
правилам , что и имена переменных и других элементов програм м ы .
Параметры массива Нижний индекс и Верхний индекс должны являться
константами и определяют пределы изменения индекса и, соответствен
но, количество элементов, которые содержатся в массиве. Например, если
в качестве Нижнего индекса использовано значение 5, а в качестве Верх
7 , то массив будет включать в себя три элемента, доступ
него индекса
к которым может быть осуществлен по индексам 5 , 6 и 7 .
-
В качестве Тиnа элемента может быть использован любой необходи
мый для решения поставленной задачи тип дан ных, например :J:nteger
или String. Также в качестве типа элемента может быть указан и дру
гой масси в (такие структуры дан ных будут рассмотрены ниже) .
Напом н и м , что объем оперативной памяти , занимаемой переменными ,
описываемыми в разделе о писания переменных var , не должен превы
шать 64-х килобайт. Таки м образом , существует ограничение на макси
мальное кол ичество элементов некоторого тип а в м ассиве. Для массива
элементов тип а :tnteger, например, такое ограничение - 3 240 8 .
В листи нге 1 46 приведено несколько примеров описания массивов.
· ·'·.:·�щ���·� r,:. f4�.;�·}�����:;i�:�:�����!�:�·;;;:))·;:1;},bl1�:;t1:�!:1::�;·j: •: :\J::�,:�·'1Д�;:/;:J:'S''�::;{;;:; · :··;?;;;.::::::::·: · ...
...
Program ArraysDe f ;
Con st
Start = 1 0 0 ;
Finish = 1 0 5 ;
297
Turbo Pascal 7 . 0
Var
S : Iliteger ;
А1 : Array [ 1
1 0 ] Of Int ege r ;
{ ма с сив д е с я ти п е р емен ных т и п а I n t eger ,
для д о с тупа будут и с п ол ь з о в а т ь с я и н д е к сы 1 , 2 ,
3 , 4 , 5 , 6 , 7 , 8 , 9 и 1 0 . Имя ма с с и в а - А1 }
А2 : Array [ 5 1 0 ] Of Int ege r ;
{ ма с сив ш е с т и п е р еме н ных типа I nt eger , для
д о с т упа будут и с п о л ь з о в а т ь ся и н д е к с ы 5 , 6 , 7 , 8 ,
9 и 1 0 . Имя ма с с и в а - А2 }
Name s : Array [ 5 1 0 ] Of St ring ;
{ ма с с и в ш е с т и п е р еме н ных т ип а S t r ing ,
для д о с тупа будут и с п о л ь з о в а т ь с я ин д е к сы 5 , 6 ,
7 , 8 , 9 и 1 0 . Имя ма с с и в а - Narne s }
Sprite s : Array [ 0
9 9 ] Of Pointer;
{ ма с с и в с т а п е р еменных типа Pointer , ди а п а з о н
инде к с о в - о т О до 9 9 . Имя ма с с и в а - Spri t e s }
В : Array [ St art Finish] Of Byt e ;
{ ма с сив ш е с ти п е р еме н ных типа Byt e , ди а п а з о н
и н д е к с о в з а д а е т с я к о н с т а н т ами S t art и F i n i s h
о т 1 0 0 до 1 0 5 - ти . Имя ма с с и в а - В }
В1 : Array [ Start 1 1 0 ] Of Byt e ;
{ м а с с и в одиннадцати п е реме н ных т и п а Byt e ,
ди а п а з о н инде к с о в з а д а е т с я к о н с т а н тами S t art и
1 1 0 - о т 1 0 0 до 1 1 0 - ти . Имя ма с с и в а - В1 }
IC1 : Array [ St art 9 0 ] Of Byt e ;
{ н е к орр е к т н о е о п и с а н и е ма с с и в а - Нижний инде к с
( з а д а н к о н с т а н т о й S t art = 1 0 0 ) пре выша е т В е рхний
индекс ( з адан к о н с т а н т о й 9 О ) }
IC2 : Array [ S 8 0 0 ] Of Byt e ;
{ н е корр е к т н о е о п и с а ни е ма с с и в а - Нижний инде к с
з а д а н п е р еме н н о й , а н е к о н с т а н т о й }
IСЗ : Array [ 1 8 0 0 0 0 ] Of Integer ;
{ н е к орр е к т н о е о п и с а н и е ма с си в а - о б ъ е м
о п е р а т и в н о й п амяти , н е о бх о димый для х р а н е н и я
т а к о г о ма с с и в а - 1 6 0 0 0 0 б а й т ( один э л е ме н т
т и п а I n t eger з а нима е т 2 б а й т а ) , ч т о п р е выша е т
ма к симал ь н о д о п у с ти мый о б ъ е м }
Begin
End .
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
10.1 .2.
•
Использова н и е м ассивов
Использование массивов заключается в основном в операциях с его эле
ментами . При этом элементы рассматриваются как отдельные переменные.
Для обращения к конкретному элементу в составе массива указывается имя
массива и индекс необходимого элемента в квадратных скобках :
<Имя ма с с и в а > [ <И н д е к с э л е ме н т а > ]
298
Глава 1 О. Сл ожные тип ы да н н ых
Рассмотрим пример использования элементов массива (см . листинг 1 47 ) .
Program Arrays 1 ;
Va r
А:
Array
[ 1 . , 3 ] Of Intege r ;
{ о п и с а н и е ма с с и в а А ,
т и п а I n t eger }
с о д ержаще г о
3
э л е ме н т а
Begin
А[1)
:=
{ и зме н е ни е
и нде к с ом 1
{ и зме н е ни е
и н д е к сом 2
8;
А[2]
:=
12 ;
А[З]
: = А [1]
з н а ч е н и я эл еме н т а
Н о в о е з н а ч е ние з н а ч ения элеме н т а
. Н о в о е з н а ч е ни е -
.
ма с с и в а
8}
ма с с и в а
12 }
с
с
А[2] ;
{ и зме н е ние з н а ч е ния элеме н т а ма с с и в а с инде к с ом 3 .
Н о в о е з н а ч е н и е я в л я е т с я суммой э л еме н т о в э т о г о
20) }
же ма с с и в а с и н д е к с ами 1 и 2 ( 8 + 1 2
+
=
А [ 1) ) ;
Wri t eLn ( ' Пepвый :
{ выв од значения элеме н т а ма ссива
с инде к с ом 1
(8 ) }
А[З] ) ;
Wri t eLn ( ' Tpeтий :
{ выв од значения элемент а ма ссива
с инде к сом 3
(20) }
А[2] ) ;
Wri t eLn ( ' Вт орой :
{ выв од значения элемента ма ссива
с инде ксом 2
( 12 ) }
End .
В качестве индексов массивов могут использоваться не только констан
ты , но и переменные, в том числе и счетчики оператора цикла For . При
ведем пример програм м ы , заполняющей элементы массива квадратами их
индексо в (см . листинг 1 48 ) .
�:i:.:l1,1,1;1�,т�'� г�:1f\�.i�,����,���,�;�i1.,�?�iE��,�9'��:P!;;Iь:;; ;:t:;�Y:e:,,;::;:;',;f\'�:,:'Д':;: :;:::k;&i,,�,fS:'?:,"
Program Arrays 1 ;
Va r
А:
i:
Array
[1
Integer ;
•
•
10]
Of Integer ;
{ о п и с а н и е ма с с и в а А , с о д ержаще г о
элеме н т о в т и п а Int eger }
{ п е р е ме н н а я дл я с ч е тчика цикл а }
10
Begin
For i : = 1 То 1 0 Do { цикл с и зме н е нием счетчика i п о сл е д о в а т е л ь н о
о т 1 до 1 0 }
A[i] : = i*i;
{ н а каждом ш аге цикла элеме н т у ма с си в а с
н омером i при с в а и в а е т с я з н а ч е н и е i * i , то е с т ь
к в а др а т е г о инд е к с а }
Wri t eLn ;
299
Tu rbo Pascal 7 . 0
For i : = 1 Т о 1 0 D o { цикл с изме н е нием
О Т 1 ДО 1 0 }
WriteLn ( A [ i ] ) ;
с ч е т чи к а
i
п о сл е д о в а т е л ь н о
{ н а к аждом ш а г е цикла прои з в о ди т с я в ы в о д
з н а ч е ни я элеме н т а ма с с и в а с и н д е к с о м i }
End .
Резул ьтатом работы программ ы будет столбик чисел , представляющих
собой квадраты чисел от 1 до 1 0 , то есть: 1 , 4, 9 , 1 6 , . . . , 1 00 .
Возвращаясь к примеру расчета средней температуры, видно, что его мож
но значительно упростить, применив массив для хранения последователь
ности введенных тем ператур до момента их сложения (см. листинг 1 49 ) .
· ·ли�т.1�г' 1 �g�·.вь,i����е�t.t& · riр(Щ�е� -т�мri�Р8ЫР.�•,с,·�с.1оn�с)8ан���:· �ti.�����,:
P rogram Temperature 2 ;
Uses
CRT ;
Var
t:
Array
i:
Integer ;
Ts :
[1
•
•
5]
Real ;
O f Real ;
{ ма с си в дл я х р а н е н и я
{ ср е д н я я
среднеме с я ч ных
т емп е р а тур }
т е мп е р а тура
Begin
ClrScr;
For i : = 1 То 5 Do { цикл с и зме н е нием
О Т 1 ДО 5 }
счетчика
i
п о сл е д о в а т е л ь н о
begin
i
Wri t e ( 1 Введите температуру з а месяц 1
{ подсказка поль з о в а телю }
1
ReadLn ( t [ i ] ) ;
{ ввод
очередной
1
1 ) ;
1 :
с ре дн е ме с я ч н о й
темп е р а туры }
end ;
Ts
:=
For
Ts
О;
{ о б нул е н и е
п е р е ме н н о й
Ts }
i : = 1 То 5 Do Т : = Т + t [ i ] ;
{ цикл с и зме н е нием сче тчика i п о сл е д о в а т е л ь н о
о т 1 до 5 , н а к аждом ш а г е ци кла з н а ч е ни е
п ереме н н о й Ts у в е личив а е т с я н а з н а ч е н и е
о ч е р е д н о г о элеме н т а ма с с и в а t }
: = Ts / 5 ;
{ де л е н и е суммы т емп е р а тур н а
средн е г о з н а ч е ни я }
5
для
п олуч е н и я
Wri t eLn ;
Wri t eLn ( 1 Средняя
ReadKey ;
End .
300
т емпература :
{ выв о д средней
Ts ) ;
темп е р а туры н а
э кр а н }
Глава 1 О. Сложные тИп ы дан н ых
1 о. 1 з
.
.
Ста ндартны е операции с м асси в а м и
Массивы предусмотрены в подавляющем большинстве языков програм
мирования и используются в широком круге задач . При этом все-таки
имеются некоторые стандартные операции с массивам и , которые ч асто
применяются вне зави симости от функциональной направленности ре
шаемой задач и . Это операции поиска в массиве или его части м и н и маль
ного и (или) максимального значения , а также упорядочивание массива
ил и его части - выстраи ван ие элементов некоторым образом , обычно
просто по возрастанию или убы ванию.
П о и с к элемента массива по крите р и ю
Поиск элемента в массиве по некоторому критерию - это определение
номера элемента массива или его значения , отвечающего задан ному кри
терию . Такой поиск может применяться в базе данных для поиска запи
си , содержащей информацию, подходящую по запросу пользователя , или
в каких-либо аналитических программах, например, для п о иска уч еника,
которы й имеет самы й высокий средний балл в классе , и так далее.
Поиск максимального и м и н имального значени й в массиве или в задан
ной его части осуществляется перебором всех элементов, среди которых
производится поиск и определение для каждого из них, подходит ли он
по критериям поиска. Аналогич ным образом осуществляется поиск по
другим условия м .
Рассмотрим методы поиска элементов в массиве н а примерах. В первом
примере (см . листинг 1 50) предложим пользователю ввести десять чисел ,
а затем определим номер элемента, значение которого равняется трем .
Если такого элемента нет, то выведем в качестве номера найденного эле
мента ноль.
· � '· ·• ·J1,и·cт�.,t::·:1 :.5 Q;i·:f1o�?.���fi����t:'��������.���'ijq·.·:�P�Т:���-���Jh:.·,�Y,[::!:�j·,1!;,: ::::··;;�?� ·
Program FindElement ;
Uses
CRT ;
Var
[1
N:
Array
i:
Intege r ;
NumЬer :
•
•
10]
Of Int eger ;
{ ма с си в для хр а н е ни я
Intege r ; { и н д е к с
элеме н т а ,
чисел }
в в е д е н ных
о т в е ч а юще г о
кри т е рию }
Begin
ClrScr;
For i : = 1 То 1 0 D o { ци кл
от
1 до
10
-
i,
1 :
1 ) ; { п о д с к а з ка
begin
Write ( 1 ВВеди'l'е число номер
1,
п е р е би р а е м в с е
э л е ме н ты }
п о л ь з о в а т е лю }
301
Turbo Pascal 7 . 0
ReadLn ( N [ i ] ) ;
{ ввод
очередного
числа }
end;
NumЬer
:=
О;
{ о б нул е н и е переме н н о й NurnЬer
п о умо л ч а нию
счи т а е м , что числ о 3 н е найде н о среди в в еде нных
ч и с е л , е сли з н а ч е ни е п е р еме н н о й не и з ме ни т с я ,
т о на э к р а н и буд е т в ыв е д е н О }
For i : = 1 То 1 0 Do
{ цикл от 1 до 1 0 }
I f N [ i ] = Э Then NumЬer : = i ;
{ пр о в е р к а очередно г о элеме н т а ма с с и в а в в е д е нных
чисел на р а в е н с т в о 3 -м , е сли усл о в и е выпол н я
е т с я , т о з а п оми н а ем и н д е к с д а н н о г о ч и с л а в
п е р еме н н о й NurnЬer . Е сли п о сл е э т о г о буд е т
найдено еще одно число , равное трем , т о значение
п е реме н н о й Number и зме н и т с я еще р а з }
-
Wri teLn { • значение
Э
имеет
элемент
номер
'
,
NumЬe r ) ;
ReadKey ;
End .
Теперь попробуем найти среди введенных элементов мини мальный (см .
рис. 1 1 7 ) . Для этого оп ишем переменную , хранящую число , которое на
зывается те кущи м м и н и мальным значением . Перед начал о м п еребора
элементов присвои м ему значение первого
массив
элем ентов
элемента массива. Затем, перебирая элемен
ты , начиная со второго , для каждого элемен
та проверим , не я вляется ли он меньши м ,
чем текущее м и н имальное значен и е . Если
� П ром ежуточный
это
так, то в перемен ную , храня щую теку
мини мум
щее мини мальное значение, занесем значе
ние этого элемента. Таким образом , после
Минимальный
окончания перебора всех элементов текущее
элемеtп
минимальное значение будет являться мини
Рис. 1 1 7. Определение
мальным для всего рассмотренн о го набора
минимального элемента
массива
эл ементов (см. листинг 1 5 1 ) .
11.111.1.1.11
\\\\\\UI/111
i-J,. �9.:r·��f:',l'i�,j·i:' n_9��!'�:�q��-��,��4$»t�Ч��j�,���:r�:!i:,����ц,��, ,-;\\;r:�wfir:;�:a �:�';�f'itй;�t
Program F i ndМinimum ;
Uses
CRT ;
Va r
N:
Array
i:
Integer ;
Minimum :
Begin
ClrScr;
302
[1
•
•
10]
Of Int eger ;
{ ма с си в для хр а н е ни я
Integer; { з н а ч е н и е
в в е де н ных
т е куще г о ми нимал ь н о г о
чисел }
э л е ме н т а }
Глава 1 О. Сл ожные ти пы дан н ых
For i : = 1 то 1 0 Do
begin
Wri t e ( ' Вв едите число номер
'
i
1
1
'
:
'
);
ReadLn ( N [ i ] ) ;
end ;
Minimwn
: = N[1] ;
{ в в о д с кл а в и а туры д е с я т и ч и с е л }
{ сч и т а е м , ч т о п е р вый э л е ме н т - ми нимал ь ный ,
е сли э т о не т а к , то з н а ч е н и е п е р еме н н о й
Minimum и зме н и т с я при п е р е б о р е }
For i : =2 То 10 Do { ци кл о т 2 до 1 0 - п е р е би р а ем в с е
ма с с и в а , н а ч и н а я со в т о р о г о }
If N [ i ]
э л е ме н ты
<
Minimwn Then Minimwn : = N [ i ] ;
{ пр о в е р к а очередного элеме н т а ма с с и в а в в е д е н ных
ч и с е л - если т е кущий э л еме н т ме н ь ше , ч е м
т е кущий ми нимум , изме н я ем т е кущий ми н имум }
Wri t eLn ( ' Минимальный элемент
Minimwn ) ;
'
1
ReadKey;
End .
Для нахождения максимального элемента массива следует произвести те
же самые действия , только проверка, выполняемая для каждого переби
раемого элемента, будет производиться наоборот - если текущий мак
симум меньше, чем очередной элемент, то текущий максимум следует
обновить. Добавим в предыдущий при мер еще и определение макси маль
ного элемента (см . листинг 1 52) .
Program F i ndМinMax ;
Uses
CRT ;
Va r
N:
Array
[1
i:
Integer ;
•
•
10]
Of Integer ;
{ ма с с и в для хр а н е ни я
в в ед е н ных
Minimwn :
Integer; { з н а ч е н и е
ми н имал ь н о г о
мaximum :
Integer; { з н а ч е ни е
ма к симал ь н о г о
чисел }
э л е ме н т а }
э л е ме н т а }
Begin
ClrScr ;
For
i : = 1 То 1 0 Do
begin
Wri t e ( ' Вв едите число
ReadLn ( N [ i ] ) ;
end;
Minimwn
номер
'
1
i1
1 :
1
)
;
{ ввод
: = N [1] ;
с кл а в и а туры д е с яти ч и с е л }
{ сч и т а ем , ч т о п е р вый э л е ме н т - ми нимал ь ный ,
е сли э т о не так , то значение переме нной Minimum
и зме н и т с я при п е р е б о р е }
303
Turbo Pascal 7 . 0
{ счи т а е м , ч т о п е р вый элеме н т - ма к с имал ь ный ,
е сли э т о не так , то значение переменной Maximum
изме н и т с я при п е р е б о р е }
For i : =2 То 10 Do { ци кл о т 2 до 1 0
п е р е бир а е м в с е э л ементы
ма с с и в а , начиная со в т о р о г о }
begin
Maximum
: = N[l] ;
-
If N [ i ]
<
Minimum Тhen Minimum : = N [ i ] ;
{ пр о в е р к а очередного элеме н т а ма с си в а в в е д е н ных
ч и с е л - е сли т е кущий э л е ме н т ме н ь ше , чем
т е кущий ми нимум , изме н я ем т е кущий ми нимум }
If N[i]
>
Maximum Then мaximum : = N [ i ) ;
{ пр о в е р к а очередн о г о элеме н т а ма с с и в а в в е д е н ных
чисел - е сли те кущий элеме н т б ол ь ше , чем те кущий
ма ксимум , изме н яем т е кущий м а к симум }
end ;
Wri t eLn ( ' Минимальный элемент
Wri t eLn ( ' Максималь ный элемент
' ,
',
Minimum ) ;
Maximum ) ;
ReadKey ;
End .
Упорядоч и вание массивов . М етод (( пуз ы р ька»
Упорядочивание массива - это изменение последовательности его эле
ментов таким образом , чтобы последовательность удовлетворяла некото
рому правилу (правилам ) . Напр и мер, когда имеется список абитуриен
тов, сдавш их вступ ител ьные экзамены на разные оценки , необходимо
упорядочить его по убыванию оценок для того , чтобы определить, кто
из абитуриентов должен быть зач ислен в учебное заведе н и е . Этот же
сп исок можно упорядоч ить по фамилиям и именам (по алфавиту) , что
бы можно было быстро найти абитуриента по его имен и .
Рассмотрим алгоритм упорядочивания массива по возрастан и ю .
Допустим , и меется массив, которы й необходимо упорядочить по возрас
танию значений элементов. Будем фиксировать по очереди (сначала 1 - й ,
потом 2 - й и так далее д о предпоследнего) элементы массива и рассматри
вать остатки массива для каждого из этих элементов (соответственно, от
2-го до последнего , от 3-го до последнего и так далее, от предпоследнего
до последнего) .
Перебирая п о очереди все элементы остатка массива для дан ного фикси
рованного элемента , будем искать элемент, который меньше данного фик
сированного . Если такой элемент будет найден, то его значение нужно об
м е н я т ь со з н а ч е н и е м ф и к с и р о в а н н о г о э л е м е н т а и п р од о л ж и т ь
рассмотрение остатка массива. Таким образом , н а месте фи ксированно
го элемента номер i на каждом шаге окажется наименьший элемент из
части массива, заключенной между i-м и п оследни м элементо м .
304
Глава 1 О. Сложные ти п ы дан н ы х
То есть , зафиксировав 1 - й эле м е нт и рассмотрев остаток массива от
2-го элемента до последнего , в 1 -м элементе окажется значени е , м и н и
мальное для массива.
Зафиксировав 2-й элемент и рассмотрев остаток массива от 3 - го элемен
та до последнего , во 2-м элементе окажется значение, м и н имальное для
части м ассива от 2-го элемента до последнего . При этом дан ное мини
мальное значение для рассмотренного остатка массива не может оказаться
меньше значения 1 - го элемента, так как тогда оно было бы поставлено
на 1 -е место во время предыдущего шага.
Таким образо м , зафиксировав по очереди все элементы от 1 -го до пред
последнего и вы полнив для каждого из них такую процедуру, мы полу
ч и м масси в , в котором 1 - й эле м ент не больше 2 - го , 2 - й не больше
3 - го и так далее, предпоследний не больше последнего . То есть м ассив
будет упорядочен по возрастани ю .
Сортировка массива по убыванию происходит аналоги ч н о , но элементы
обмениваются значениями в том случае, если фиксирован н ы й элемент
меньше рассматри ваемого элемента из остатка массива.
Упорядочивание по возрастанию или убыванию реализуется вложенными
циклами - внешний цикл фиксирует элементы массива от первого до
предпоследнего , а вложенный рассматривает остатки массива от следую
щего за зафиксированным до последнего, осуществляя перебор элементов
остатков массива и производя обмен элементов, если это необходимо.
Обрати м внимание на п роцедуру обмена эле
ментов значениям и . Для ее реализации суще
ствует следующ и й простой метод, использую
щий некоторую вспомогательную переменную
(см . рис. 1 1 8 ) :
1 . З н ачение перво го элемента массива за
Рис. 1 1 8 . Обмен
носится во вспомогательную переменную.
зна чениями
2. З н ач е н и е второго элемента массива заносится в первый .
3 . З н ачение вспомогательной переменной (в которой н а самом деле
хранится начальное значение п ервого элемента массива) заносится
во второй элемент ( начальное значение которого уже занесено в
первый эл емент) .
Таким образом , два элемента массива обмениваются значениями п о кругу
через переменную . Замети м , что с помощью такого алгоритма можно об
менивать значения не только элементов массива, но и обычных п еремен
ных. Покаже м , как это делается , на примере (см. листин г 1 5 3 ) .
305
Turbo Pascal 7 . 0
Program ChangeVars ;
Uses
CRT ;
Va r
а,
Ь:
с:
Integer ;
{ в в о димые п ол ь з о в а т е л е м п е р еме нные }
{ в с п омо г а т е л ь н а я п е р еме н н а я }
Intege r ;
Begin
ClrScr;
Wri t eLn ( ' Вв едите
nервое
ReadLn ( a ) ;
число :
');
{ ввод nервого числ а }
Wri t eLn ;
Wri t eLn ( ' Введите
в торое
число :
{ ввод второго
ReadLn ( b ) ;
');
числ а }
Wr i t eLn ;
с
:=
а;
а
:=
Ь;
Ь
:=
с;
{ с о х р а н е н и е з н а ч е н и я п е р еме н н о й а в о
в с п омо г а т е л ь ной п е р еме н н о й с }
{ з ане се ние в переме нную а значения переме нной Ь }
{ з а н е с е н и е в п е р еме н ную Ь
з н а ч е ни я п е р еме н н о й а }
Wr i t eLn ( • значения
nосле
Wri t eLn ( ' Первое
число :
Wri t eLn ( ' Второе
число :
первоначаль ного
обмена : ' ) ;
а) ;
',
Ь) ;
{ вы в о д р е зул ь т а т о в
и з ме н е н и я }
ReadKey ;
End .
А теперь подробно рассмотрим пример упорядочивания м ассива из шес
ти элементов, введенных пользователем (см . листинг 1 54) .
:'?1i�,�+�Hi-':_,1's4::.,:��g,fi�д,�4й.��.�·q�!;t1i\���·�!j���l�g#i?e,�!�W���-�;,�.�;;��1;t;�N:�t:;�;f:•t·
Program Orde rMinToMax ;
Uses
CRT ;
Va r
А:
Array
[1
i,
j:
с:
Integer ;
•
•
б]
Intege r ;
Begin
ClrScr ;
For
i : = l То б Do
begin
306
Of Integer ;
{ ма с сив для хр а н е ни я в в ед е н ных ч и с е л }
{ п е р еме н ные дл я с ч е тчи к о в ци кла
в н е ш н е г о и вложе н н о г о }
{ в с п омо г а т е л ь н а я
п е р еме н н а я }
Глава 1 0 . Сложн ые ти п ы да н н ых
Wri t e ( ' Введите число
номер
',
i,
' :
');
ReadLn ( A [ i ] ) ;
end ;
For i : = l То 5 Do { в н е шний цикл , переме н н а я - с ч е т чи к i
о ч е р е дн о й з а фи к сир о в а н ный э л е ме н т }
определ я е т
For j : = i + l То б Do
{ в н у т р е н ний цикл , переме н н а я-сч е т ч и к j
о п р е д е л я е т о ч е р е д н ой р а с сма три в а емый эл еме н т
о с т а т к а ма с с и в а ( о т i + l до п о с л е дн е г о ) }
I f A [ i ] >A [ j ]
Then
{ е сли з а фи к сиро в а н ный элеме н т б о л ь ш е , чем
о ч е р едной р а с сматри в а емый э л е ме н т о с т а т к а
ма с си в а , т о их нужн о о бме н я т ь ме с т ами }
begin
с
:= A[i] ;
A[i]
: = A[j ] ;
A[j ]
:= с;
{ о бме н
элеме н т о в ма с с и в а
ме с т ами }
end ;
Wri t eLn ;
Writ eLn ( ' Массив
For
i : = l То 7
nосле
уnорядочив ания : ' ) ;
Do WriteLn ( A [ i ] ) ;
ReadKey ;
End .
Рассмотр и м подробно механ изм работы при веде и н о й
програм мы ( с м . р и с . 1 1 9 ) :
1 . Ввод п ол ьзователе м восьми значений . Допустим ,
введены значения б , s , 1 3 , 1 4 , 8 и з .
2. Фи кс и руем первый эле мент (выделен темно-серым
фоном н а рис. 1 1 9) и рассматриваем остаток мас
си ва со второго элемента до шестого. Для каждого
эл е м е нта ( в ыдел е н ы с в етл о - с е р ы м ф о н о м н а
рис. 1 1 9) вы полняем следуюшее действие : есл и эле
мент меньше первого (то есть зафиксированного ) ,
т о обмениваем его значением с первы м .
2. 1 . Первый элемент остатка масси ва ( 5 ) меньше,
чем зафи ксирован н ы й , п оэтому меняем их ме
стами , в результате чего массив приобретает
следующий вид: 5 , 6, 1 3 , 1 4, 8 , 3 .
2 . 2 . Продолжаем рассматривать остаток массива.
Второй элемент остатка ( 1 3) больше, чем за
фиксированн ы й (5) , поэтому обмен не произ
водится . Анал о гичным образом н е п роизво
дится обмен значениями и для следующих двух
элементов ( 1 4 и 8 ) .
l в l s l13l 14l a l 3 1
! 13114l a l 3 1
f155
8 в liiзl14l s l 3 1
8 6 I13Pi41 s l з l
8 в i 1 3I 14P8*I 3 1
1[6 11зl14l sjЗGI
1 3 81ЗI141 s l s l
l з 81311!\l a l s l
ГЗI1ЗТ14]?8[5]
lз
�s'l
з 1 s 814l a l Б l
зls
8l в l
Jtt3
з l s �6;J
3 1 s l reзl 6 1
l з l s l a "t36il
8
l з l s l a i Б I!I1:ЗI
v
l з l s l a l б l131 1 41
Рис.
1 1 9.
Упорядо чивание
массива по
возра станию
307
Turbo Pascal 7 . 0
2 . 3 . Последний элемент остатка массива ( 3 ) имеет значени е , мень
шее, чем у зафиксированного , п оэтому производится обмен
значения м и , в результате чего м ассив п ри обретает вид : 3, 6,
1 3 , 14, 8, 5. Н а этом заканчивается рассмотрение остатка мас
сива для первого зафиксированного элемента. Резул ьтат - в
первом элементе массива находится наимен ьшее значение из
всех введенных п ол ьзователем.
3 . (Dиксируем второй элемент массива и рассм атриваем о статок мас
сива с третьего элемента до шестого .
3 . 1 . Первый элемент остатка массива ( 1 3) не я вляется меньши м ,
ч е м зафиксированны й , п оэтому обмен значениями не произ
водится . Аналогич н ы м образом не производится обмен для
элементов со значениями 1 4 и 8 .
3 . 2. Следующий элемент остатка массива ( 5 ) меньше , ч е м зафик
сированный , п оэтому производится обмен значен иям и , п осле
чего массив принимает вид: 3 , 5 , 1 3 , 1 4, 8 , 6 . Н а этом закан
чи вается рассмотрение остатка массива для второго зафи кси
рованного элемента. Резул ьтат - во втором элементе м ассива
находится н аи меньшее значение из всех введенных п ол ьзова
телем, за искл ючением того значения , которое находится в
первом элементе. Таки м образо м , первые два элемента я вля
ются упорядоченными п о возрастанию.
4. Аналогичным образом фиксируются п о очереди трети й , четвертый
и пятый элементы , в резул ьтате чего весь массив становится упоря
доченн ы м п о возрастанию.
5 . Вывод значений элементов на экран в столбик.
М ы еще вернемся к методам упорядочивания массивов при обсуждении
построения систем управления базами дан ных ( СУБД) . А пока замети м ,
что алгоритмов сортировки существуют десятки , каждый и з н и х подхо
дит для разных критериев упорядочивания и объемов массив о в . Н ами
рассмотрен один из самых простейших, не оптимизированных п о скоро
сти алгоритмов, показывающи й , однако , неплохие результаты для боль
шинства решаемых задач .
1 о. 1 4
.
.
М ногомерные массивы
М ассив можно представить в виде строки (последовательности) элемен
тов (см . рис . 1 20) .
l в l s l1 зl1 4l в l з 1
Рис. 1 20 . Одномерный
массив
308
Как указывалось выше, в качестве Тиnа элеме н п р и оп исан ии массива могут и спользоваться
любые типы данных, в том числе и массивы.
тов
Глава 1 О. Сложные ти п ы дан н ых
Двухмерный массив (матрица)
которого я вляется массив.
это такой м ассив, каждым элементом
-
Описание двухмерного массива имеет следующий вид:
< Имя мас сив а > : Array
Array
[ < Нижний инде к с >
[ < Нижний инде к с >
O f <Тип элеме н т о в > ;
•
•
•
•
< В е р х ни й и н д е кс > ] Of
< В е рхний и н д е кс > ]
Таким образо м , каждым элементом массива с
именем Имя мас сив а будет также я вляться мас
сив. Такую структуру можно представить в виде
таблицы (см. рис. 1 2 1 ) . Доступ к элементу двух
мерного массива осуществляется указанием двух
индексов - индекса строки и индекса элемента
в данной строке :
Jj
6
5
4
1
5
8
4
-3
2
8
3
8
14 -1
о
9
3
7
_:::Вт:..::о",РО::.:;й,_,и::"нд",е""кс::....__.
�
121.
Рис.
Двухмерный ма ссив
<Имя ма сси в а > [ <Пер вый инде к с > ,
<Второй инде к с > ]
Аналогично можно описать массив любой
размерности , например трехмерный или
четырехмерный (на рис. 1 22 показан трех
мерный м ассив) , в зависимости от требо
ваний решаемой задачи . Для упрощен ия
оп исан ия м ногомерных массивов можно
использовать следующую форму описания :
массив
<Имя ма с с и в а > : Array [ < Нижний индекс>
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
1 22. Трехмерный
Рис.
•
•
•
•
•
•
< В ерхний и н д е к с > ,
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
1
<Нижний и н д е к с > < В е рхний и н д е кс > ]
O f < Т и п элеме н т о в > ;
•
•
В случае такого описания массива его размерность определяется количе
ством пар индексов. Приведем при меры описания многомерных масси
вов (см. листинг 1 5 5) .
.1ffh'��:r:��г:::!:��\;••�J;:�����-� ������.:;:�����м����Y��;��9.���:tr(w!�;;,','�i2�'t��i:�jШi!�J11�1��:;
Program SDArrays ;
Va r
А : Array [ 1 1 0 ,
В:
Array
[1
•
•
•
•
1 2 0 ] Of Integer ;
{ дв ухме рный массив из 1 0 - ти с т р о к п о 2 О
элеме н т о в в каждой . Н а з в а ни е ма с с и в а - А ,
и н д е к сы с т р о к - о т 1 д о 1 0 - ти , и н д е к сы
элеме н т о в в каждой с т р о к е - о т 1 до 2 0 - ти }
10 , 5
15 ] Of Intege r ;
{ дв ухмер ный массив и з 1 0 - ти с т р о к п о 1 1
элеме н т о в в каждой . Н а з в а ни е ма с с и в а
А,
и н д е к сы с т р о к - о т 1 д о 1 0 - ти , и н д е ксы
элеме н т о в в к аждой строке - о т 5 д о 1 5 - ти }
•
•
•
•
-
309
Turbo Pascal 7 . 0
С:
Array
Begin
A [ S , 3]
В [3,
С [1,
:=
[1 . . 10 ,
5 . . 1 5 , 1 . . 5 ] Of Int eger ;
{ трехмерный ма ссив из 1 0 - ти строк по 1 1 элементов
в каждой . Н а з в а ние ма ссива - А, инде к сы строк от 1 до 1 0 - ти . Каждый элемент представляет собой
ма с с и в п я ти элеме н т о в типа I n t eger }
14 ;
{ и зме н е ни е з н а ч е н и я тре т ь е г о э л е ме н т а в о с ь мой
с тр о к и ма с с и в а А }
{ и зме н е ни е з н а ч е н и я э л е ме н т а с и н д е к с ом
14 ] : = б ;
1 4 т р е т ь ей строки ма с с и в а В }
1 , 1 ] : = А [ 8 , 3 ] + В [ 3 , 14 ] ;
End .
М н огом ерные массивы обычно применяются для хранения и анал иза
дан ных, которые м ожно структурировать по нескольким направления м .
Например , для хранения совокупности имен ш кольников какого-либо
города можно использовать одномерный массив элементов типа S t r i ng:
FIOs : Array [ 1 . . 1 0 0 0 0 ] Of String ;
Н о в большинстве задач для более удобного и быстрого доступа к и н
формации удобнее структурировать список и м е н по школам (допустим ,
их в городе 20) и классам (в каждой ш коле по l l классов) . Тогда список
имен можно хранить в структуре следующего вида (с учетом того , что в
каждом классе не м ожет учиться более 30-ти человек) :
FIOs : Array [ 1 . . 2 0 , 1 . . 1 0 , 1 . . 3 0 ] Of String ;
Приведем пример использования двухмерного массива для хранения пря
моугольной области экрана. Выведем на экран в строку <<Array E f f ec t ! »
в графическом режим е 640х480х256 (см. рис. 1 23 ) . Фон для н адписи соз
дадим градиентный - плавно перели вающийся от черного к красному
сверху вниз. Н адпись будем вы водить постепенно, сверху вниз, создавая
эффект развертыван ия изображения. Для этого перед начал о м основной
части программ ы вы ведем ее на экран процедурой OutTextXY и сохра
ним в двухмерны й массив цвета точек для всего прямоугольника, охватывающего надпись. Напомним, что
цвет точки можно узнать с помощью
функции Get P i xe l .
Рис. 1 23. Результат работы программы
Splash 1
31 0
Рассмотрим м етод создания гради
ентного фона. На экране одновре
менно может н аходиться 256 цветов .
П р и этом используемые цвета дол
жны иметь такие цветовые характе
ристики , чтобы обеспечить плавное
п ер ел и в а н и е ц в ет а из ч ер н о го в
к р ас н ы й . Для у к аз ан и я я р к о с т и
красного цвета можно использовать
Глава 1 0 . Сложные ти п ы да н н ы х
значение от О до 63 -х, поэтому для создания фона достаточно использо
вать всего 63 цвета, предварительно подготовив их с помощью процеду
ры SetRGBPalett e :
For Colour : = О То 6 3 Do
SetRGBPa l e t t e ( Colour ,
{ ци кл о т О д о 6 3 ,
с ч е т чи к ци кл а }
C o l our
-
п е р еме н н а я
Colour , О , О ) ;
{ н а каждом ш а г е цикла о ч е р е д н ой ц в е т
( определя емый номером Col our ) при о бр е т а е т
н е о бх одимые ц в е т о вые х а р а к т е р и с т и к и }
Высота экрана в точках равна 480. Соответственно, наша задача - распре
делить 63 цвета равномерно по 480 точкам . Соответственно, каждая гори
зонтальная линия экрана с номером у должна иметь цвет с номером , рас
считываемым по формуле Номер цвета = у 14 7 9 * б 3 . Так как результат
деления имеет тип Real , а для указания цвета точки необходимо использо
вать тип Integer, то необходимо округлить номер цвета, получаемый при
расчете по этой формуле: Номер цвета = Целая част ь ( у 1 4 7 9 * б 3 ) .
Для округления вещественного числа в Turbo Pascal используется функ
ция Round, вызываемая с параметром , содержащим число, которое нуж
но округлить, и возвращающая результат округления:
Rоund ( < О к р у г л я е мо е з н а ч е н и е > ) ;
Таки м образом , для вывода градиентного фона следует организовать цикл ,
на каждом шаге которого рассматри вается одна горизонтальная строка
экрана , для нее подбирается цвет по вышеприведенной формуле, затем в
эту строку экрана вы водится ли ния данного цвета.
For у : = О то 4 7 9 Do
{ ци кл от О до 4 7 9 - ти , переме н н а я - с ч е тч и к цикла - у }
begin
Colour : = Round ( y / 4 7 9 * 6 3 ) ;
{ о пр е д е л е н и е н омера ц в е т а п о ф ормул е }
S e t Color ( Colour ) ;
{ ус т а н о в к а о п р е д е л е н н о г о ц в е т а в к а ч е с т в е т е куще г о }
Line ( O , у , 6 3 9 , у ) ;
{ вы в о д линии для з а п олн е ния о ч е р е д н о й с т р о к и
э кр а н а ц в е т о м }
end ;
Теперь рассмотрим , к а к производится сохранение информации об изоб
ражении в м ассив. Аналогичная задача уже была приведен а выше - это
преобразование картинки в маску при выводе спрайта с прозрачным фо
ном . В данном случ ае задача та же - сканирование прямоугольной об
ласти экрана и получение информации о цвете для каждой точки облас
ти . И н ф о р м а ц и ю о ц в ете н е о бходи м о з а н е с т и в п р ед в а р и т ел ь н о
подготовленный массив.
31 1
Turbo Pascal 7 . 0
F o r у : = 2 3 0 'l'o
3 2 0 Do
{ в н е шний цикл , о р г а н и з ующий п е р е б о р с т р о к
прямоуг оль н о й о б л а с т и , переме н н а я - с ч е тчик цикла
у и зме н я е т с я о т 2 3 0 до 3 2 0 }
For x : = S O 'l'o 5 9 0 Do
{ вл о ж е н ный цикл , о р г а н и зующий п е р е б о р с т ол б ц о в
пр ямоуг ол ь н ой о бла с ти , п е р е ме н н а я - с ч е т ч и к цикла
х изме н я е т с я о т 50 до 5 9 О }
E f fectBar [ х ,
у ] : = Get P ixel ( х , у ) ;
{ з а н е се ни е н оме р а ц в е т а т оч ки с к о ордин а т ами
( х , у ) в элеме н т ма с си в а E f f ec t Bar }
Пределы изменения счетчиков циклов и индексов массива выбраны исходя
из размеров надписи, выводимой на экран в разрабатываемой программе.
После вывода на экран надписи, сохранения ее в м ассиве и заполнения
экрана градиентн ы м фоном можно перейти непосредственно к вы воду
надписи на экран из массива. Для этого используется цикл , который для
каждой строки м ассива, в котором хранится цветовая информация о над
писи, вызывает вложенный цикл поточеч ного вывода этой строки.
For у : = 2 3 0 'l' o 3 2 0 Do
{ в н ешний ци кл с п е реме н н о й - с ч е тчи к ом у ,
о п р е д е л яюще й н омер выв одимой с т р о ки н а д п и си }
For х : = 5 0 'l'o 5 9 0 Do
{ вл о ж е н ный цикл с п ер еме н н о й - с ч е т чи к ом х ,
о п р е д е л яюще й н омер в ы в о димо г о с т о л б ц а т е кущей
с т р о ки н а д п и с и }
I f E f f ectBar [ х , у ] > 0
'l'hen Put P ixel ( х , у , E f fectBar [ х , у ] ) ;
{ выв о д точки на э кр а н , е сли е е цв е т н е ч е р ный }
Итак, рассмотрим программу п олностью (см . листинг 1 56) .
������5�?J*�:�I:"�:ifи�пef��:.:��'�J�;;��;::,�, �:��!Y�i":,�,\���j
Program Spl a sh l ;
Uses
Graph , CR'l' ;
Var
GraphDrive r : Integer ;
GraphМode : Intege r ;
E f fectBar : Array [ S O . . 5 9 0 ,
х , у : Intege r ;
Bright : Intege r ;
Proc edure DrawGradi ent ;
Var
у : Intege r ;
Colour :
31 2
Int ege r ;
230 . . 3 2 0 ]
Of
Byt e ;
Глава 1 О. Сложн ые тип ы дан н ых
{ п р о ц е дур а
Do
begin
For Colour : = О То
выв ода
градие н т н о г о
фона }
63
SetRGBPal e t t e ( Colour , Colour , О , О ) ;
{ п одг о т о в к а ц в е т о в дл я
фона }
For у : = О То 4 7 9 Do
begin
Colour
:=
Round ( y / 4 7 9
*
63 ) ;
SetColo r ( Colour ) ;
Line ( O ,
у,
у) ;
639 ,
end ;
{ в ыв о д
end ;
фона }
Begin
GraphDriver
GraphМode
:=
:=
Instal lUserDrive r ( 1 BGI 2 5 6 1 ,
ni l ) ;
2;
Init Graph ( GraphDrive r , GraphМode , 1 1 ) ;
{ ус т а н о в к а г р а фич е с к о г о
SetRGBPalet t e ( 2 5 5 ,
О,
О,
р е жима
6 4 0х 4 8 0х2 5 6 }
О) ;
SetColor ( 2 5 5 ) ;
Setтext Style ( GothicFont , Hori z D i r , 9 ) ;
2 0 0 , 1 Array E f fect ! 1 ) ;
{ ус т а н о в ка ц в е т а с н омером 2 5 5 т е кущим и
прид а н и е ему ч е р н о г о ц в е т а , ч т о бы и н ф орма ци я ,
выв одима я с е г о п омощь ю , н е был а в и д н а .
З а т е м выводи т с я н а д п и с ь }
OutTextXY ( 5 0 ,
For у : = 2 3 0 То 3 2 0 Do
For х : = 5 0 То 5 9 0 Do
E f fectвar [ х ,
у ] : = GetP ixel ( х , у ) ;
{ п е р е н о с информации в
{ вы з о в
For у : = 2 3 0 То 3 2 0 Do
For х : = 5 0 То 5 9 0 Do
begin
DrawGradient ;
If
E f f ec tBar [ х ,
ма с си в }
п р о ц е дуры р и с о в а ни я г р а д и е н т а }
у] > 0
Then PutPixel ( х ,
у,
E f f ectвar [ х ,
у] ) ;
De l ay ( 1 0 ) ;
{ выв о д надписи
end ;
For х : = О То 6 3
на
э кр а н }
do
begin
SetRGBPalet t e ( 2 5 5 ,
х,
х,
х) ;
De l ay ( 3 0 0 ) ;
end ;
{ пл а в н о е и змен е ни е ц в е т а выв е д е н н о й
н а д п и си о т ч е р н о г о к б е л ому }
и з ма с с и в а
ReadKey ;
C l o s eGraph ;
End .
{ з а в ерше н и е
n р о гр аммы }
313
Turbo Pascal 7 . 0
1 0. 1 .5.
Особе н ности р аботы
с перем е н н ы м и ти п а Stri ng
М ы уже довольно активно используем тип данных S t r i ng, а в этом раз
деле изуч и м его нем ного глубже. На самом деле строкавые переменные
являются массивами следующего вида:
Array [ 0
. . 2 5 5 ] Of Cha r ;
Если строковая переменная описывается с указанием дли н ы , например,
String [ 5 0 ] , то внутренняя структура переменной будет эквивалентна мас
сиву Array [ о . . 5 о ] Of Char, то есть содержать сим волов на один боль
ше. Один символ , добавляемый к строке , является служебн ы м и содер
жит длину строки . Работа с ним описана ниже.
Таким образом , к любому сим волу строки можно обратиться так же , как
к элементу одномерного массива. В качестве примера приведем програм
му, выводящую третий сим вол стро ки , введенной п ол ьзователем (см .
листинг 1 57 ) .
:,;c[��c��7�t; ·! ��j�:���:�:-=;��E��������;;���;J���;��r:;��·; ,.:�·:�t�tT�������',��{·�'{,�
Program
St ring l ;
Uses
CRT ;
Va r
S:
St ring ;
Begin
C l rS c r ;
Wri t e ( 1 В:ведите
строку :
1 );
ReadLn ( S ) ;
Wri t eLn ( 1 Третий сим:вол :в:веденной строки :
{ о бр а ща емся к симв олу с т р о ки S
S [3 ] ) ;
с ин де к с ом 3 }
ReadKey;
End .
В связи с частой употребляемостью п еременных типа S t r i ng необходи
мо уметь выполнять некоторые стандартные действия со строками . Рас
смотрим их.
Операции с длиной строк
Все стандартные процедуры ввода/вы вода самостоятельно определяют
длину строки , поэтому обычно нет необходимости каки м -либо образом
влиять на нее. Однако для реал изации дополнительных возможносте й , не
включенных в стандартную поставку Turbo Pascal , изменение размера стро
ки - часто используемая операция. Например, при написани и процеду314
Глава 1 0 . Сложные ти п ы дан н ых
ры, аналогичной процедуре Read, но осуществляющей ввод текстовой ин
формации в графическом режиме, при нажатии пользователем клавиши
Backspace (стирание последнего введенного символа) необходимо умень
шить введен ную строку н а один символ .
<<Полезная>> дл ина строки , то есть та ее часть, которая реально использу
ется, например, в операциях вы вода, хранится в нулевом элементе мас
сива, представляющего строконую переменную. К этому элементу допу
стимо обращаться, как и ко всем остальным элементам массива, одн ако
тип этого элемента - Char, поэтому в него нельзя занести какое-либо
числовое значение.
Полезная длина строки определяется кодом нулевого символа, соответ
ственно , для изменения длины строки необходимо занести в данный эле
мент массива си мвол , код которого равен новой дл и не стро ки . Для по
лучения с и м в ола из е го кода и с пользуется уже рассмотрен н ая н а м и
функция Chr :
Chr ( < Koд симв ол а > )
Для того чтобы проанализировать длину строки , используется обратная
по действию функция Ord, которая возвращает код символа:
Оrd ( < Симв ол > )
При ведем программу, запраши вающую у пользователя строку текста и
выводящую на экран ее длину (см. листинг 1 5 8 ) .
�:�J;t��f,·��r..�:Ei�f::В�Я�8!�i�����!�f�9tP'�t��'�l\i{11!i�}:if�r�:,�'f!:�;t;н;��,1r1;)И�'��;tr,��f]:,:··
Program S t r ing2 ;
Uses
CRT ;
Var
S : S t ring ;
Begin
C l rS c r ;
Wri t e ( 1 Введите строку : 1 ) ;
ReadLn ( S ) ;
Wri teLn ( 1 Размер строки = 1
Ord ( s [ О ] ) ) ;
{ обраща емся к симв олу с т р о ки S с и н д е к с о м
и выв одим н а э к р а н код нул е в о г о симв о л а
с п омощь ю функции Ord }
ReadKe y ;
End .
О
Теперь измен и м программу так, чтобы введенная строка уменьшалась на
один символ. Укороченную строку также выведем на экран . Для умень
шения строки н а оди н символ необходимо:
315
Turbo Pascal 7 . 0
1. Определить дли ну строки и поместить ее в предварительно о п и сан
ную целочисленную переменную.
Var
S:
S t ring ;
Byt e ; { о п и с а н и е переме н н о й для х р а н е н и я
пр омежут о ч н о г о з н а ч е н и я длины с т р о ки
SLength :
S}
Begin
SLength
:=
Ord ( S [О ] ) ;
{ з а н е се ни е
в
п е р емен ную S L ength длины с тр о ки
S}
2 . Уменьшить значение переменной , хранящей длину строки , н а еди
н и цу, если это возможно (то есть если е е значение - положитель
но ) .
Begin
If
SLength >
О Then SLength : = SLength - 1 ;
{ уме н ь ш е н и е з н а ч е ни я п е р еме н н о й SLeпgth , е сли
т е куще е значение б о л ь ше нул я ; е сли т е куще е
значение равно нулю , то уме н ь шение не прои з в о дит с я }
З . Занести в нулевой элемент строки символ , код которого соответ
ствует новой дли н е строки .
Begin
S [ O ] : = Chr ( SLength ) ; { yc т a н o в кa строке S н о в ой дли н ы }
Измененный текст программы приведен в листин ге 1 59 .
�';,]r �H���Ht.·;],��ErJ:� #��'fi���,#�-4!#:� ..,ь.>iHpo.�ь:.-c<(�:::·,,
Program S t ringЗ ;
Uses
CRT ;
Va r
S:
St ring ;
SLength :
Byt e ;
Begin
C l rS c r ;
Wri t e ( ' Вв едит е
строку :
ReadLn ( S ) ;
WriteLn ( ' Размер
SLength
316
:=
строки
Ord ( S [ О ] ) ;
');
=
Ord ( S [ O ] ) ) ;
__
. :: . -;;: ;�5:';- · • . .
Глава 1 0 . Сложные тип ы данных
I f SLength >
S[O]
: = SLength - 1 ;
{ и зме н е н и е длины с т р о ки }
О Then SLength
: = Chr ( SLength ) ;
Wri t eLn ;
Wri t e ( ' YICopoчeннaя
строiСа : • , S ) ;
{ вы в о д укор о ч е н н о й
строки
на
э кр а н }
ReadKey ;
End .
Однако все действия по уменьшению размера строки м ожно выполнить
в одну строку и без использования дополнительной переменной :
1) ;
S [ O ] : = Chr ( Ord ( S [ O ] )
Таким образом , програм м а изменения дли н ы строки п р и н и м ает вид,
представлен н ы й в листи нге 1 60.
-
Program St ring3 ;
Uses
CRT ;
Var
S : S t ring ;
Begin
ClrSc r ;
Wri t e ( ' Введите строiСу :
');
ReadLn ( S ) ;
Ord ( S [ O ] ) ) ;
Wri teLn ( ' Размер строiСи = '
I f Ord ( S [ O ] ) > О Then S [ O ] : = Chr ( Ord ( S [ O ] ) - 1 ) ;
{ и зме н е н и е длины с тр о ки с про в е р ко й
н а в о зможн о с т ь и зме н е ни я }
Wri t eLn ;
Wri te ( ' УIСороченная строiСа : ' , S ) ;
{ выв од укор о ч е н н о й с тр о ки н а э кр а н }
ReadKey ;
End .
Для определения дли н ы строки можно также и с пол ьзовать функцию
Length (см. листи нг 1 6 1 ) , однако возможность установки дли н ы строки
не предусмотрена.
:•·'·
·.!J и·��.�.�г·.· :1· s 1..:i: •.�·������и·�;:4:JI6"�:4!r;gy���-�i::it;i;;·�!·.:A·1;;:hf�?1��:����f����t����111;1;���
..
Program St ring4 ;
Uses
CRT ;
Va r
S:
S t ring ;
317
Turbo Pascal 7 . 0
Begin
ClrScr;
Wri t e ( ' Вв едите строiСу : ' ) ;
ReadLn ( S ) ;
Wri t eLn ( ' Размер строiСи = '
Length ( S ) ) ;
I f Length ( S ) > О Then S [ O ] : = Chr ( Length ( S ) - 1 ) ;
{ и зме н е н и е длины с т р о к и с п р о в е р кой
н а в о зможн о с т ь и зме н е ни я }
Wri t eLn ;
Wri te ( ' УIСороченная строiСа : ' , S ) ;
{ вывод укор о ч е н н ой строки н а э кр а н }
ReadKey ;
End .
Ко н катен ация
Для перемен н ых типа St ring и Char определена о перация сложения ,
называемая конкатенацией. Результат конкатенации - добавление сим
волов одной строки в конец другой .
Рассмотрим пример: попросим пользователя ввести его имя и фамилию
по отдельности , а затем будем хранить имя с фамилией в одно й строко
вой переменной (см . листинг 1 62) .
{\)1"�6тйи�·.·1 в2:�:;и��6ri��o'& aи�; ·��.���i���ц����j::Iтjjz;;;�·•2r;.:ш,.·:· :i���\�l;�;'�·;;�s��"i:·(@:� ;;:;'.
..
Program S t r i ng S ;
Uses
CRT ;
Va r
Name ,
FIO :
Pat ronymi c , Surname : String ;
{ п е р еме н ные для промежу т о ч н о г о хр а н е н и я име ни ,
о т ч е с т в а и ф амилии }
String ; { п еременная дл я хр а н е ни я име ни , отче с т в а и фамилии
одновременно , в порядке , необходимом для целей про граммы }
Begin
C l rS c r ;
Wri t e ( ' Введите имя : ' ) ;
ReadLn ( Nam.e ) ;
{ в в о д име ни }
Wr i t eLn ;
Wri te ( ' Вв едите отчество : ' ) ;
ReadLn ( Patronymic ) ; { в в о д о т ч е с т в а }
Wri t eLn ;
Wri t e ( ' Вв е дите ф амилию : ' ) ;
ReadLn ( SurNam.e ) ;
{ в в о д фамилии }
FIO : = SurName + ' ' + Name + ' ' + Pat ronymi c ;
{ о бъеди н е ни е трех с т р о к и п омеще н и е
р е зул ь т а т а в п е р емен ную F I O }
31 8
Глава 1 О. Слож н ы е ти пы дан н ы х
ClrScr;
Wri t е Ln ( ' Здрав ствуйте ,
ReadKey ;
{ и с п ол ь з о в а н и е
FIO ) ;
с т р о ки }
End .
Также конкате нацию нескол ьких строк можно выполнить с помощью
функции Concat, получающей в качестве параметров строки , которые не
обходимо сложить, и возвращающей результат сложения (конкатенации ) :
Соnсаt ( < С т р о к а 1 > , < С т р о к а 1 > ,
.
.
•
,
< С т р о к а N> )
П р имеча н и е .
Н ет н и какой раз н и цы между испол ьзованием функци и Concat и об ыч ного сложе
ния строк оператором + . Какой м етод конкатенаци и исп ользовать - дело л и ч н ы х
п редпочтени й . Однако необходимо заметить , ч т о тип дан ных Stri n g в таком
виде реал изован п рактически только в Tu rbo Pascal , в боль ш и нстве других я з ы
к о в п рограм м и рован и я работа с н и м п роисходит значител ьно сложнее, и для
кон катенации п ридется испол ьзовать соответствующие функци и .
Изменим предыдущий пример, использовав функцию Concat (см . лис
тинг 1 6 3 ) .
Program S t ring б ;
Uses
CRT ;
Var
Name , Pat ronymi c , Surname :
FIO : S t r ing ;
Begin
ClrScr ;
Writ е ( ' Введите имя : ' ) ;
ReadLn ( Name ) ;
Wri t eLn ;
St ring ;
Wri te ( ' Вв едите отчество : ' ) ;
ReadLn ( Pa t ronymi c ) ;
Wri t eLn ;
Writ e ( ' Вв е дите ф амилию : ' ) ;
ReadLn ( SurName ) ;
FIO : = Concat ( SurName ,
Name ,
Pat ronymi c ) ;
{ о бъ е д и н е н и е трех с т р о к и п омеще н и е р е з ул ь т а т а
в переменную F I O с использов анием функции Concat }
ClrScr ;
Wr it eLn ( ' Здравствуйте , ' , FIO ) ;
ReadKey;
End .
319
Turbo Pascal 7 . 0
Сравнение строк
Для переменн ых типа String реализована операция сравнени я , то есть
для двух строк можно определить, какая из них <<больше>> или « меньше>>
другой . Сравнение строк основано на сравнении дли н строк и на срав
нении кодов символов, из которых состоят строки . Например, строка <<А»
мен ьше строки «Z» , так как сим вол <<А>> и меет код, меньш и й , чем у сим вола «Z». Вообще все символы
буквы
латиницы и кириллицы Таблица 6
Кодьt некоторых видимых символов таблицы ASC/1
расположены в табли це симво
лов ASC I I по алфавиту. Это по
Символ
Код
зволяет п р и м е н я т ь с р а в н е н и е
33 . . .47
!"#$%&'( )*+,-.;
строк, например, п р и упорядо
0 - 9
48 . . . 57
чивании
массива: если упорядо
: ; < = >?@
58 . . . 64
ч и вать масс и в элем ентов ти па
д. . . z
65 . . . 90
String по возрастани ю , то эле
91 . . . 96
[\] А
97 . . . 1 22
a. . .z
менты (строки) расположатся в
1 23 . . . 1 26
{ 1 ) алфавитном порядке . Что каса
д. . я
1 28 . . . 1 59
ется всех остальных си мволов,
а. . .п
1 60 . . . 1 75
которые можно в ыводить на эк
р. . .я
224 . . . 239
ран , то они разбросан ы по таблице символов (см . табл . 6 ) .
.
Если какие-либо две строки идентичны по набору символов , но одна и з
них имеет длину, большую, ч е м другая , т о о н а сч итается большей. На
пример, строка <<ABCD>> больше, чем строка <<АВ С» . Замети м , что длина
строки - всего лишь дополнител ьн ы й критери й и, напри мер, строка
<<МАА>> будет меньше строки <<ВВВ>> , хотя и имеет большую дли ну.
Напишем программу, вводящую пять имен и вы водя щую их в упорядо
ченном виде (см . листин г 1 64) .
�t�.d�:9f���- 1.64>����·P,�'д���-;i��;,:�;��Ц�&'{�i!;��·J,;::':\?·i;�:.·�f:·;;;�-::·.·:�; ·. :·.�jf;�.�:�:;�
...
Program SortName s ;
Uses
CRT ;
Con s t
NameNwn =
5;
{ о пи с а н и е к о н с т а н ты , с о д е ржащей
коли ч е с т в о в в одимых име н }
Va r
Name s : Array [ 1
tmpS : String ;
i,
j:
•
•
NameNum]
Intege r ;
Begin
C l rS c r ;
For i : = 1 т о NameNum Do
320
Of
String ;
..
;t; �tщ;:
Глава 1 0 . Сложн ые тип ы данных
begin
Wri t e ( 1 Введите имя
,
i,
1 :
1 );
ReadLn ( Names [ i ] ) ;
end ; ввод имен
For i : = l То NameNum - 1 Do
For j : = i + l То NameNum Do
I f Name s [ i ]
> Name s [ j ]
Then
begin
tmpS
: = Names [ i ] ;
Name s [ i ]
: = Names [ j ] ;
Names [ j ]
: = tmpS ;
end;
{ уп о р яд о ч и в а ни е име н по в о з р а с т а нию ,
т о е с т ь в алфа в и т ном п о р я д к е }
Wri t eLn ;
Wri t eLn ( 1 От с ортиров анный cnиcol( : 1 ) ;
For i : = l То NameNum Do Writ eLn ( Names [ i ] ) ;
{ в ы в о д у п о р я д оч е н н о г о с пи с к а }
ReadKey ;
end .
Результат работы программы представ
лен на рис. 1 24. Пользователь последо
вательно ввел имена «Миш а», «Маша»,
«Пе т я » , «Дима» и «Аня». В результате
упорядо ч и ва н и я массива, в котором
были сохранены введенные имена, на
экран вы веден ы строки в следующей
последовательности : «Ан я » , «Дима » ,
«Маш а » , «Миш а » , « П е т я » .
Введите имя
Введите имя
Введите имя
Введите имя
Введите имя
1 : Миwа
2:
3:
4:
Маша
Петя
Дима
5: Ан я
Отсо рти рованн ый список:
Аня
Дима
Mawa
Миwа
Петя
Рис.
1 24 . Результат работы
программы SortNames
В ы вод ч и словых д а н н ых в графичес ком р ежи м е .
П реобразование ч исел в стро ку
Единствен н ы м методом вывода информации в графическом режиме яв
ляется процедура Outтext или ее модификация OutтextXY. Обе проце
дуры выводят только строки текста и не могут получать в своих пара
м етрах, н а п р и м е р , цело ч и сл е н н ы е дан н ы е . С о ответстве н н о , е с л и
необходимо осуществить вывод нетекетовой информаци и , нужно преоб
разовать ее в текстовую . Для этого предназначена процедура Str, имею
щая следующий вид:
Str ( <Ч и сло > , < С т р о ка > ) ;
В качестве параметра Число используется переменная или константа ,
значение которой необходимо занести в переменную типа Stri:ng, задан
ную в качестве параметра Стро к а .
11
Зав:. 702
321
Turbo Pascal 7 . 0
Приведеиная ниже программа (см . листинг 1 65) в текстовом режиме запра
шивает у пользователя его вес, а затем выводит его в графическом режиме.
���:�E3:���;{·!:���1].Ef��iвliБ��:�!'Ji�':�в�������1?��ie���,��:11·::;�'�:;'�:f;;�:�;�·r��,!��:' :r;�,\;.
Program St ring7 ;
Uses
Graph , CRT ;
Var
GraphDrive r , GraphМode : Intege r ;
rUserWei ght : Real ;
{ п е реме н н а я для х р а н е н и я в е с а п о л ь з о в а т е л я
в числ о в ом виде ( в еще с т в е н н о е числ о ) }
sUserWe ight : St ring ;
{ п е реме н н а я дл я х р а н е н и я в е с а п о л ь з о в а т е л я
в т е к с т о в ом виде ( с т р о к а ) }
Begin
ClrScr;
Wri t e ( ' Вв едите в а ш вес : ' ) ;
ReadLn ( rUserWeight ) ;
{ п олучение число вых данных о т п ол ь з о в а т еля }
GraphDri ver : = Det ect ;
GraphМode : = О ;
Init Graph ( GraphDrive r , GraphМode , ' 1 ) ;
{ и ници а л и з ация г р а ф ич е с к о г о р е жима }
S t r ( rUserWei ght , suserwe i ght ) ;
{ п е р е в о д число вых д а н ных в с тр о к а вые }
OutTextXY ( 2 0 , 2 0 , ' Ваш вес = 1 + sUserWei ght ) ;
{ в ы во д и н ф орма ции }
ReadKey ;
C l o s eGraph ;
End .
Результат работы программы немного отличается от ожидаемого. Дело в том ,
что при вводе , например, значения <<72 . 5>> на экране отображается строка
<<Ваш вес = 7 . 2500000000Е+0 1 » , то есть значение переменной rUs erWeight
при переводе из числовой формы в строковую записывается в так называе
мой научной форме. Запись 7 . 2500000000E+O l означает 7 . 25* 1 0 1 •
Для того чтобы выводить число в более привычной для нас форме, необ
ходимо указать при переводе ч исла в строку, сколько символов должно за
нимать число и сколько цифр в нем должно содержаться после запятой:
Str ( <Число> :
<Общее количество символов> : <Количество цифр> , <Строка > ) ;
Механ изм работы расш иренного варианта процедуры S t r следующи й :
•
•
322
ч и сло п редставляется в обычной форме ;
кол ичество символов, находящихся п осле десятичной запято й , п р и
водится в соответстви и с параметром Колич е с т в о циф р ;
Глава 1 0 . Сложные типы данных
•
вычисляется общая дли н а полученной строки и , в случае есл и ее
дли н а меньше, чем задано параметром Обще е колич е с т в о симв о
л о в , слева о т числа вставляются пробел ы .
При удалении л и ш н и х десятичных цифр значение округляется п о обыч
ным математическим правилам .
Измен и м предыдущую про грамму таким образом , чтобы на экран выво
дилось ч исло в обы чной форме (см. листи нг 1 66) . Поскольку вес челове
ка обычно измеряется с точностью до десятых долей килограмма (то есть
до сотен грам мов) , укажем в качестве параметра Количество цифр зна
чение 2. В качестве параметра Общее количество символов стоит ука
зать значение О, чтобы вне зависимости от дли н ы строки с числом про
бел ы слева от нее не добавлялись.
: 11�стинг 166.
чис�л · в l"р�фи�еск�м 6е��м�У
· сВ ывод
доп олнительныf111 .форматr.1р ован и е.м
·
·
··
·
··.·.·:.·.··: · ·. .·· ·· . >�·�:· �
·
. ... .• .... ·:..
.
..
. .
.·
. ...
.
/ц . : •
. .
·
Program S t ring7 ;
Us e s
Graph , CRT ;
Var
GraphDrive r , GraphMode : Integer ;
rUserWe ight : Real ;
sUserWe i ght : St ring ;
Begin
ClrScr ;
Writ е ( ' Введите ваш вес : ' ) ;
ReadLn ( rUserWe ight ) ;
GraphDri ver : = Detect ;
GraphМode : = О ;
Init Graph ( GraphDriver , GraphМode , ' ' ) ;
Str ( rUserWe ight : О : 2 , sUs erWe ight ) ;
{ п е р е в о д число вых да н ных в с т р о к а вые с з ад а нием
о б ще г о колич е с т в а симв о л о в и колич е с т в а
де с я тич ных цифр }
OutTextXY ( 2 0 , 2 0 , ' Ваш вес = ' + sUserWeight ) ;
ReadKey ;
C l o s e Graph ;
End .
Аналоги чна ситуация с процедурой вы вода Wr i t e (wri teLn)
она так
же вы водит вещественные числа в научной форме и при вызове может
принимать параметры форматирования:
-
Wr i t e ( < П a p aмe тp
т и п а Rea l > : <Общ е е колич е с т в о с имв оло в > :
< Колич е с т в о цифр> ) ;
323
Turbo Pascal 7 . 0
Ввод текстовой и нформации в графическом р ежи ме
Если стандартный н абор процедур п озволяет выводить в графическом
режиме хотя бы текстовую информацию, то вводить информацию с кла
виатуры невозможно вообще . Однако, используя функцию ReadКey, мож
но самостоятельно реализовать процедуру ввода строки.
Напишем такую процедуру, включив в нее следующие возможности:
•
•
•
Ввод и нформации производится с «эхом» , то есть п ол ьзовател ь
и м еет возможность видеть набираемые им на экране с и м вол ы . Для
вы вода вводимой строки в качестве эха будем использовать теку
щие настройки шрифта и п оложение текущего указателя .
Для стирания послещ-{его символа используется клавиша <<Backspace>> .
Для удаления п оследнего символа вводимой строки с э крана будем
выводить на место всей строки прямоугольник, заполнен н ы й сплош
ной зали вко й , при этом заливка будет определяться в вызывающей
п одпрограмме.
В вод строки заканчи вается по н ажатию п ол ьзователем клави ши
<<Enter>> .
Рассмотрим ал горитм , используемый в процедуре:
l . О п исан ие переменных для хранения вводимой строки (s), нажатой
клави ш и (Ch) и п оложения текущего указателя на момент начала
работы процедуры (Startx и StartY) .
2 . И н и ц и ал изация переменных, испол ьзуемых в процедуре :
• сохранение текущего указателя с п омощь ю фун кци й Getx и
GetY м одуля Graph : S t artX :
GetX И S t a r tY :
GetY;
:
;
• занесение в п еременную s пустой строки : s
• переменную Ch и н и циал изировать необязательно , так как до
обращения к ней она уже будет использована для хранения
нажатой клав и ш и .
3 . С помощью условного оператора цикла Repeat . . . Unt i l п роизво
дится заци кл и ван ие следующего фрагмента программ ы :
3 . 1 ) ожидание нажатия на клавишу и занесение с и м вола, соответ
ствующего нажатой клавише , в переменную ch;
3 . 2) анал из значения переменной Ch с помощь ю условного опера
тора м н ожественного выбора Case:
•
есл и n еременная Ch и меет значение # О , то производится
повторное считывание нажатой клавиш и . Больше н и ч его не
происходит, а повторное считывание п росто позволяет от
фильтровать символ ы , соответствующие управляющим кл а
вишам, от общего п отока ввода;
•
есл и переменная Ch имеет значение # 1 3 , то н ичего не про
исходит (испол ьзован так называе м ы й пустой оператор =
=
=
324
1
1
Глава 1 0 . Сложн ые типы данных
•
•
точка с запято й ) . Такая проверка п озволяет не добавлять
си мвол перевода строки к вводимой пользователем строке;
если п еременная Ch и меет значение # 8 , то строка, уже вве
денная пользователем , стирается с экрана закрашенным пря
моугольником , затем размер строки уменьшается на еди н и
ц у и она выводится на экран заново. В с е эти действия
производятся , только если дли н а строки п оложительна;
для всех остальных значени й переменной C h производится
добавление их в конец строки s и перевывод строки s на
экран без ее стирани я .
4. Посл е заверш е н и я заци кленного фрагмента вследстви е н ажатия
пользователем кл авиш и «Enter>> значение строки s выдается в каче
стве значения функци и .
Процедуру помести м в модуль, имеющи й и м я ExtGraph, чтобы о н а мог
ла быть доступна из нескольких программ без дополн ительного переноса
в эти программ ы ее текста (см. листинг 1 67 ) .
Uni t Ext Graph ;
{ з а г о л о в о к модул я }
Int e r f a c e
{ начало интерфейсной ча сти }
Funct ion ReadS t ring : St ring ; { з а г ол о в о к функци и }
Imp l ement a t i on
{ н а ч а л о о п и с а т ел ь н о й ч а с ти }
Uses
CRT , Graph ;
Funct i on ReadSt r ing : St ring ; { о п и с а н и е п р о ц е дуры }
Var
S : S t ring ;
Ch : Cha r ;
Start X , S t artY : Int eger ;
begin
s
:=
1 1 ;
StartX : = Get X ;
StartY : = GetY ;
Repeat
Ch : = ReadКey ;
Case Ch Of
# 0 : begin
Ch : = ReadКey ;
end;
#13 : ;
# 8 : I f Length ( S )
Then
{ и нициали з а ц и я п е р еме н ных }
{ н а ч а л о цикл а }
{ счи тыв а н и е н а ж а т о й кл а в иши }
{ а н ализ п е р еме н н о й Ch }
{ е сли # О , то дочи тыв а е м в т ор о й
>
{ е сли
О
#13 ,
то
нич е г о н е
{ е сли # 8 и с т р о к а уже
т о с ти р а е м п о следний }
симв о л }
дел а е м }
с о держит
симв олы ,
325
Turbo Pascal 7 . 0
begin
Bar ( Start X , StartY, StartX + TextWidth ( S ) ,
S t art У + TextHei ght ( S ) ) ;
S [ 0 ] : = Chr ( Length ( S )
1) ;
OutTextXY ( StartX , StartY , S ) ;
end;
else
begin
{ в о в с ех о с т а л ь ных случ а ях д о б а в л я е м
введенный символ к строке и выводим ее н а экран }
S : = S + Ch ;
OutTextXY ( StartX , St artY , S ) ;
end;
end ;
Unt i l Ch = # 1 3 ;
{ о к о н ч а н и е з а цикл е н н о г о фрагме н т а , усл о в и е
выхода - н ажа т а кл а в иша Enter }
ReadString : = S ;
{ ук а з а ни е функции , ч т о н е о б х одимо в е рнуть
в к а ч е с т в е з н а ч е ни я }
end;
{ о к о н ч а ние функции }
end .
{ о к о н ч а н и е модул я }
-
И п р и вед е м п р и м е р п р о гр а м м ы , и с п ол ь з у ю щ е й д а н н ы й м од ул ь
(см. листинг 1 68 ) .
�Jii�:���,�r:�-j-�@:!���&���!t�,9��!���t-;��:r�,��Ф�,;�����:::P�,����:';;�;,,;.;.:x�i<J}Ыl;t;�;1�:�:w�
Program GraphRead;
Uses
CRT , Graph , ExtGraph ;
Var
Gd , Gm: Int ege r ;
S : St ring ;
Begin
Gd : = Detect ;
Gm : = О ;
Init Graph ( Gd , Gm , 1 1 } ;
S e t C o l o r ( Wh i t e ) ;
SetFi 1 1 Style ( So l i dFi l l , B lue ) ;
SetText Styl e ( Tripl exFont , Hori z D i r , 2 ) ;
{ ус т а н о в к а х а р а к т е р и с т и к выв одимой и н ф о рмации ,
ко тора я , в ч а с т н о сти , буд е т и с п о л ь з о в а т ь с я дл я
э х о в о г о выв ода при в в оде с т р о ки }
Оut т е хt ( 1 Введите строку : 1 ) ;
S : = ReadString ; { в в о д с т р о ки }
OutTextXY ( O , 1 0 0 , 1 В:ы ввели строку : 1 + S ) ;
{ вы в о д в в е д е н н ой с т р о к и }
ReadKey ;
C l o s e Graph ;
End .
326
Глава 1 0 . Сложн ые ти п ы да нных
Синта ксический разбор строк
Для осуществления си нтаксического разбора строковых переменных с
целью выделения из них каких-либо ключевых слов предусмотрена функ
ция Р о в , осуществляющая поиск заданной подстроки в заданной строке
и возвращающая номер символа, в котором находится начало найденной
подстроки :
Р о s ( <Подс�ро�а > ,
< С �ро � а > )
В качестве параметров Подс�ро�а и с�ро�а используются переменные
или константы типа S t ring. Если заданная с � р о � а не содержит nод
с�ро �у, то функция возвращает нулевое значение.
В к а ч е ст в е п р и м е р а работы ф у н к ц и и Р о s п р и в ед е м п р о гр а м м у
(см . листи нг 1 69 } , осуществляющую простейший синтаксический разбор
строки , вводи мой пользователем . Зададим пользователю вопрос : «Ка:к:ие
цвета в ам нр а в я т с я ? » , - на который можно дать произвольный от
вет, например « :к:р а с ный» или «:к:рас ный и з е л е ный» , или « :к:р а сный
з ел е ный и синий» . Далее проанализируем введен ную строку:
1
•
•
•
1
есл и строка содержит слово з е л е н ый , то нарисуем на экране
полоску зеленого цвета;
если стро ка содержит слово :к:р а сн ый , то нарисуем на экране
полоску красного цвета;
если строка содержит слово синий , то нарисуем н а экране полоску си него цвета.
1
1
1
1
1
1
Таким образом , в зависимости от введенной строки на экране могут по
явиться одна, две, три строки либо не поя виться ничего, если пользова
тель в своем ответе не указал одного из трех цвето в , поддерживаемых
нашей програм мой.
Для то го чтобы проверить, содержится ли искомое слово во введенной
строке , будем для каждого цвета сравнивать результат п оиска подстро
ки - н азвания цвета - во введенной строке с нулем . Если значение, воз
вращаемое функцией Po s , больше нуля , значит, искомое название цвета
содержится в анализируемой строке.
:i��;p�.•�:rи�e.·1 ���"�·.�·�f!�·�·�ц·��\�:ii�#��;!��w!:�����т��'S·���;9�Я'f.#jA:���W�f����
..
Program Color s ;
Uses
CRT ;
Va r
S : S t ring ;
i : Integer ;
Begin
ClrScr;
327
Turbo Pascal 7 . 0
Wri t e ( ' Какие цвета в ам нравятся ? : ' } ;
ReadLn ( S } ;
( ввод строки }
I f P o s ( ' красный • , S } > О Then
begin
Text Color ( Re d } ;
Got oXY ( l , 5 } ;
For i : = l То 8 0 Do Wri t e ( • * • } ;
end ;
{ е сли в с т р о к е содержи т с я сло в о
т о р и с о в а н и е к р а с н о й линии }
I f P o s ( • зеленый • , S } > О Then
begin
Text Col or ( Green } ;
Got oXY ( l , б } ;
For i : = l То 8 0 Do Write ( ' * ' } ;
end ;
{ е сли в с т р о к е содержи т с я сло в о
т о ри с о в а ни е з е л е н о й линии }
I f Ро s ( ' синий • , S } > О Then
begin
Text Color ( B lue } ;
Got oXY ( l , 7 } ;
For i : = l то 8 0 Do Wri t e ( ' * ' } ;
{ е сли в с т р о к е содержи т с я сл о в о
end ;
т о рисо в а ни е с и н е й линии }
ReadKey ;
1
1
1
к р а с ный
1
,
з е л е ный ' ,
си н и й ' ,
End .
Удален и е , вста вка и выделение подстрок из стр о ки
Для удаления части строки и вставки подстроки в задан ную строку ис
пользуются соответственно процедуры Delete и I:nsert , и меющие сле
дующий вид:
Delete ( < C т p o к a > , <Инде кс> , < Колич е с т в о символо в > ) ;
Данная процедура удаляет часть строки , заданной параметром С т р о к а ,
нач иная с с и мвола, номер которого задан параметром Инде к с и длиной ,
заданной параметром Колич е с т в о симв оло в .
Insert ( < Пoдcтpo кa > , < С т р о к а > , <Индекс> ) ;
Данная процедура вставляет строку, задан ную параметром Подстрок а ,
начи ная с символа, номер которого задан параметром Инде к с , в строку,
заданную параметром Стро к а .
Напишем программу, которая будет анализировать строку, введенную
пользователем, искать в ней подстроку «Си» и , в случ ае если такая под
строка содержится во введенной строке, изменять слово «Си» на «Turbo
P a s c a l » (с м . листи н г 1 70) .
328
Глава 1 0 . Сложн ые ти п ы данных
��
�@i·ьpJ�'r��w·�,:�т�:��t����;;��.��.f�·;k��б � ��· -{i}�\ ::1;�:: · •
· · · ; .·���·c i · i-; :'1: ?o:: ; � .;� � ·� ��
Program Ki l l C ;
Uses
CRT ;
Va r
S : S t ring ;
i : Intege r ;
Begin
C l rS c r ;
Wri t e ( ' Введите строку : ' ) ;
ReadLn ( S ) ;
{ в в о д с т р о ки }
CPos : = Pos ( ' Си ' , S ) ;
{ о п р е д е л е н и е н оме р а симв о л а , с к о т о р о г о
н а ч и н а е т с я п о д с т р о к а ' Си 1 }
{ е сли н омер симв ола б о л ь ш е нуля , то е с т ь
If CPos > О Then
в в е д е н н а я с т р о к а с о де р жи т п о д с т р о ку 1 Си 1 }
begin
De l e t e ( S , CPos , 2 ) ;
{ уд а л я ем п о д с тр о ку
Си 1 }
Insert ( ' тurЬо Pascal ' , S , CPos ) ;
{ в ставл яем на ее ме сто п одстроку 1 ТUrbo Pascal 1 }
end ;
Wri t eLn ;
Wri te ( ' Вы ввели строку :
S) ;
{ выв одим р е зул ь т а т изме н е н и я с т р о ки н а э кр а н }
ReadKey ;
1
End .
Таким образом , если пользователь введет, например, строку «Язык: Си с амый лучший язык: прогр аммир о в ания», то на экран будет выведена
строка «Вы в в ели строку : Я зык: Turbo Pa s c a l - с амый лучший язык:
пр огр аммир о в ания» .
Еще одна функци я , п редназначенная для работы с переменн ы м и ти па
String, возвращает для задан ной строки подстроку заданного размера,
начиная с некоторого си мвола:
Сору ( < Стро к:а > , <Инде к с > , < Р а змер> )
Данную фун кцию можно использовать, например, для уменьшения дли
ны стро ки без применения функции Chr :
S : = Copy ( S , 1 , Length ( S ) - 1 ) ;
{ к опир о в а ние в п е р еме н ную S э т о й же с т ро ки
о т п ер в о г о симв ола до п р е д п о с л е дн е г о }
Также для этой цел и м ожно использовать и процедуру D e l e t e :
Delete ( S , Length ( S ) , 1 ) ;
{ удаление из строки S подстроки , начало которой
н а х о ди т с я в последнем симв оле с т р о ки S , а
дли н а р а в н я е т с я одному симв олу}
329
Tu rbo Pascal 7 . 0
Си нтаксически й разбор текста - интересная и обши рная область дея
тельности . Без решения задач такого рода невозможно создание тексто
вых редакторов с возможностью проверки правописания , систем элект
р о н н о го перевода и м ножества других програм м , к кото р ы м мы так
привыкл и . Непосредствен ная работа со строкам и для выделения , удале
ния и вставки отдельных буквосочетани й , рассмотренная в настоящем
разделе, я вляется лишь небольшой частью синтаксического анализа, ос
новная же его часть лежит в области лингвисти ки . Однако без умелого
применения рассмотрен н ых простых методов невозможно создание слож
ных и полезных программ .
В ыдел е н и е ч и словой и нформации и з строки
Если переменная или константа типа String содержит сим вольное пред
ставление вещественного или целого числа, например 1 2 . 8 ил и 1 24 ,
то с помощью процедуры Val можно преобразовать это число в значе
ние переменной типа Real :
1
1
1
1
Vаl ( < Ст ро к а > , < П ер еме н н а я - п риемни к > , < Код з а в ершени я > ) ;
В качестве параметра Переманная- приемник должна использоваться пе
ременная типа Real , а в качестве параметра Код з ав ершения
пере
менная ти па I:nteger. М ехан изм работы процедуры Val заключается в
выделении символьного представления числа из Строки, преобразован ие
его в числовую форму и занесение в переменную, указанную в качестве
параметра Переменная- приемник . В случае если преобразование в чис
ловую форму невозможно, в переменную, указан ную в качестве параметра
Код завершения , помещается иенулевой код ошибки , в остальных слу
чаях в дан ную перемен ную помещается нулевое значение.
-
Реализуем функцию чтения вещественного числа в графическом режиме,
отсутствующую в стандартных возможностях Turbo Pascal , на основе уже
написанной нами функции ReadS tring модуля ExtGraph (см . листинг 1 7 1 ) .
Uni t
ExtGraph ;
{ начало
Interface
Funct ion
{ з а г о л о в о к модул я }
ReadSt ring :
Funct ion ReadReal :
Imp l ement a t i on
и н т ерф е й с н ой
String ;
Rea l ;
{ начало
CRT ,
Graph ;
Funct ion
330
ReadS t ring :
{ з а г оло в о к
функции
ReadS t r i ng }
{ з а г оло в о к
функции
ReadRe a l }
о п и с а т е л ь н ой
Uses
St ring ;
ча с т и }
ч а с ти }
Глава 1 О. Сложн ые типы дан н ых
Va r
S : String ;
Ch : Char ;
StartX ,
Start Y :
Intege r ;
begin
1 .;
:=
s
StartX
:=
Get X ;
StartY
:=
Get Y ;
Repeat
Ch
Read.Кey ;
:=
Case Ch O f
#0 :
begin
Ch : = Read.Кey ;
end;
#13 :
#8 :
;
I f Length ( S )
>
О Then
begin
Bar ( Start X , Start Y , StartX +
StartY + TextHeight ( S ) ) ;
TextWidth ( s ) ,
S [ O ) : = Chr ( Length ( S ) - 1 ) ;
OutTextXY ( St artX , StartY, S ) ;
end ;
e l s e begin
S
:=
S
+ Ch ;
OutTextXY ( StartX ,
StartY,
S) ;
end ;
end ;
Unt i l Ch
=
ReadString
end ;
Funct ion
Var
S:
#13 ;
:=
S;
ReadReal :
Real ;
{ описание
функции
ReadRea l }
String ;
Code :
Intege r ;
rValue :
Real ;
Ьegin
{ в ыз о в функции ReadS t r i ng , в в одящей с т р о ку
с :к л а в и а туры , и з а н е с е н и е в в е д е н н о й с т р о ки
в п е р еме н ную S }
Va l ( S , rValue , Code ) ;
{ выделение число вого значения из переменной S и
занесение его в в еще стве нную переменную rValue }
Read.NumЬer : = rValue ; { ук а з а н и е в о з вращаемо г о фун кцией з н а ч е н и я }
S
:=
ReadSt ring ;
end ;
end .
{ о к о н ч а н и е модул я }
33 1
Turbo Pascal 7 . 0
И п р и в ед е м п р и м е р п р о г р а м м ы , и с п ол ьз ую щ е й д а н н ы й м од ул ь
(см . листинг 1 7 2) .
i.fii!Щ����·t�i�!*Ч���9��)E��л#���5�;'Ф'�ii�ii���:�li;',fJ>i$Ч�'�t:��ii��,��:�:М�1��'-' i;�'
P rogram GraphReadNumЬer ;
Uses
CRT , Graph , ExtGraph ;
Va r
Gd , Gm : Intege r ;
R : Rea l ;
S : St ring ;
Begin
Gd : = Detect ;
Gm : = О ;
Ini t Graph ( Gd, Gm , • • ) ;
SetColor ( Whi t e ) ;
SetFi l l Style ( So l i dFi l l , B lue ) ;
SetText St yl e ( Tripl exFont , Hori zDi r , 2 ) ;
{ у с т а н о в к а х а р а к т е р и с т и к выв одимой и н ф о рмации ,
к о т о р а я буде т , в ч а с т н о с ти , и с п оль з о в а т ь с я для
э х о в о г о выв о д а при в в оде с т р о ки }
Оutт е хt ( ' Введите число : 1 ) ;
R : = ReadReal ;
{ в в о д ч и сл а }
Str ( R : 0 : 2 , S ) ;
{ пе р е в о д чи сла в строку , дл я т о г о ч т о бы
о т о б р а з и т ь е г о на э кр а н е ; и с п ол ь зуе т с я
ф о рма тир о в ание выв одимо г о числа - д в а симв о л а
п о сл е з а п я т ой }
OutTextXY ( O , 1 0 0 , ' Вы ввели число : ' + S ) ;
{ выв од в в е д е н н ой с тр о к и }
ReadKey ;
C l o s eGraph ;
End .
1 0. 2 . Записи
Одной из сам ых распространенных задач программ и рования я вляется
структурирование информаци и , то есть выделение из совокупности еди
ниц беспорядочной и нформации более
Це на , у. е .
М арка монитора
крупных логических структур. Рассмот
420
СТХ PV505
ри
м , например, список жидкокристал
1 295
Bliss 1 940
лических
мониторов и цены на них в
RoverScan Slim Рго
589
некотором магази не.
FineView LM 1 770A
677
ViewSonic VG 1 9 1 Black
1 485
Асег F P - 5 8 1
499
332
Глава 1 О. Сложн ые типы данных
Для автом атизации работы с приведе и ным списком м ожно создать два
массива - оди н для хранения назван и й , второй для хранения цен . Допу
стим , в ассорти менте м агазина не может б ы ть более пятидесяти мон ито
ров одновременно. Тогда программа, осущест вляющая работу со списком ,
должна иметь следующую структуру данных:
Program Moni t o rs 1 ;
Con s t
MaxNumЬer =
50;
{ к о н с т а н т а , о п р е д е л яюща я ма к симал ь н о в о змо ж н о е
колич е с т в о мони т о р о в в а с с о р тиме н т е }
Va r
CodeNames :
Pric e s :
Array [ 1 . . MaxNumЬer ] Of St ring ;
{ о п и с а н и е ма с си в а дл я хр а н е ни я н а з в а н и й
мо н и т о р о в , имеющи х с я в а с с о р тиме н т е }
Array [ 1 . . MaxNu:mЬer ] Of Real ;
{ о пи сание ма ссива для хранения
имеющи е с я в а с с ор тиме н т е ]
CurrentNumЬer :
Byt e ;
{ т е куще е
колич е с т в о мо н и т о р о в
цен
в
на
мо нит оры ,
а с с ор тиме н т е }
Begin
{ ор г а ни з а ци я
р а б о ты с о
с трук турами
д а н ных }
End .
Применение массивов для хранения информации в данном при мере в зна
чительной степени упрощает реализацию программ ы и позволяет приме
нять стандартные операции с массивами для поиска цены монитора по
назван и ю , выяснения марок мониторов , имеющих максимальную и ми
н и мальную цен ы , а также упорядочивать список по названиям м оделей
мониторов или по цене.
Основное требование к информац и и - это ее целостн ость, то есть в
дан ном случае соответствие цен моделям мониторов . Если поменять ме
стам и две м одел и мон иторо в , например , при упорядоч иван ии списка
по названиям мониторов , необходимо обменять местами и их цены , иначе
наруш ится изначальное соответствие цен модел я м м о н иторо в . Таки м
образом , сортировка сп иска по алфавиту (в порядке возрастания) долж
на выгл ядеть следующим образо м :
Procedure
Sort ByMon i t o rAscending ;
Var
i,
j:
Int ege r ;
tmpS :
String ;
tmpR :
Real ;
begin
For i : = 1 То MaxNumЬer- 1 Do
333
Tu rbo Pascal 7 . 0
j : = i + 1 То МaxNumЬer Do
if CodeName s [ i ] > CodeNames [ j ] Then
For
begin
tmpS
: = CodeName s [ i ] ;
CodeName s [ i ]
CodeName s [ j ]
tmpR
: = CodeName s [ j ] ;
: = tmpS ;
{ о бме н з н а ч е ни ями э л е ме н т о в ма с с и в а
CodeName s с н а з в а ни ями мо н и т ор о в }
: = Prices [ i ] ;
Prices [ i )
: = Prices [ j ] ;
Prices [ j ]
: = tmpR ;
{ о бме н з н а ч е н и ями эл е ме н т о в ма с с и в а Pr i c e s с
ц е н ами мо нитор о в ; н оме ра о бме н и в а емых э л е ме н т о в
с о о т в е т с т в уют номерам о бме н и в а емых э л е ме н т о в
ма с с и в а Co deNames дл я п оддержа н и я с о о т в е т с т в и я
цен названиям}
end;
end ;
Аналогичным образом должна производиться и сортировка по цене - при
обмене местами двух цен одноврем енно должен производиться обмен
местам и соответствующих названий. При добавлении еще одной харак
теристики мон итора, например размера диагонал и , во всех процедурах
сортировки будет необходимо добавить обмен значений и этой характе
ристики .
М арка монитора
СТХ
PV505
Bliss 1 940
RoverScan Slim Pro
Це на , у. е .
Диа г она ль
420
15
1 295
19
589
1 5 .7
FineView LM 1 770A
677
17
ViewSonic V G 1 9 1 Black
1 485
19
Acer FP-5 8 1
499
15
Итак, допустим , что для каждой характеристики монитора реализуется
по две процедуры сортировки - по возрастанию и убыван ию. Таким об
разо м , при добавлении характеристи ки с номером n + l необходи м о вне
сти изменения в 2 * n процедур. Для продажи мониторов нужно знать около
десяти характеристи к, п оэтому для добавления десятой из них в уже на
писанную и отлаженную программу необходи мо внести восемнадцать из
менен и й , каждое из которых нуждается в обязательной проверке . Если
же программ а работает с объектами , и меющим и около ста характерис
тик, что вполне возможно, внесение изменений в нее - крайне трудо
емкая операци я .
Описанная проблема заставляет искать альтернативные подходы к струк
турированию информаци и . Одн им из таких подходов является структу334
Глава 1 0 . Сложн ые типы данных
рирован ие не по вертикали, когда укруп ненные структуры данных созда
ются в виде последовательности значен ий одной характеристики для не
скольких описываемых объектов, а по горизонтали - путем создан ия
сложной структуры данных, о п исы вающей все характеристики одного
объекта, то есть представление объекта целико м .
Для горизонтального структурирования дан ных предназначены записи структуры дан ных, состоящие из нескольких переменных разных типов.
1 0.2.1 .
Описание зап и сей
Зап ись является типом данных и описы вается в разделе описания ти пов
данных Тур е . После описания типа данн ых его можно использовать для
создания переменных этого типа в обычном порядке . Оп исание записей
как типов данн ых имеет следующий вид:
Туре
{ н а ч ало р а з д е л а о п и с а ни я т и п о в д а н ных }
< Имя т и п а > = Record
{ з а г ол о в о к о п и с а н и я з а пи с и }
{ о п и с а н и е « п о л я » з а пи с и }
<Имя п е р еме н н о й 1 > : < Т и п > ;
<Имя п е р ем е н н о й n> : < Т ип > ;
end;
{ о п и с а н и е « п о л я » з а пи с и }
{ о к о н ч а н и е о п и с а ни я т и п а }
Таким образом , зап ись как тип данных состоит из набора разнороднЬiх
переменных, называемых полями зап иси , каждая из которых имеет свое
ун икальное имя в пределах записи. В качестве Тиnов nеременных , опи
сываемых внутри зап и с и , могут использоваться любые типы дан н ых ,
встроенные в Turbo Pascal или описанные в программе д о описания дан
ной записи, в том числе масси вы и другие записи.
Рассмотрим при мер описания нового типа дан н ых - записи , содержа
щей информацию о мониторе.
Program Moni to rs 2 ;
Туре
TOneMonitor = Record
CodeName : St ring ;
Price : Real ;
Di agona l : Real ;
end ;
Begin
{ н а ч а л о р а з д е л а о п и с а ни я т и п о в д а нных }
{ з а г о л о в о к з а пи с и }
{поле , представляющее название модели монитора }
{ п о л е , п р е д с т а в л яюще е ц е н у мони т ор а }
{ поле , представляющее размер диагонали монитора }
{ о ко н ч а н и е о п и с а н и я з а пи с и }
{ ор г а ни з ация
р а б о ты
со
струк турами
д а н ных }
End .
Описанная таким образом запись с именем TOneMonitor является ти
пом дан ных, а не перемен ной, то есть не существует на сам о м деле, п о
этому к ней нельзя обращаться для занесения и получения информац и и .
335
Turbo Pascal 7 . 0
Использовать запись можно только для описан ия переменной этого типа.
Аналоги ч н ы м свойством обладают все типы данных, которые мы исполь
зуе м . Н апример , I n t eger - является типом данных и не м ожет быть
использован в строке вида I n t eger := LO .
Оп исание переменных-записей, или , как их принято назы вать, экземп
ляров записей, осуществляется по обыч н ым правилам в разделе о писания
переменных var :
Program Monit o rs 2 ;
Туре
TOneMoni tor
CodeName :
Price :
Record
String ;
Real ;
Di agonal :
end ;
=
Real ;
{ о п и с а ние з а пи си к а к
н о в о г о т и п а д а н ных
-
т ип а д а н ных ,
TOneMon i t o r }
н а з в а ни е
Var
Monitor :
TOneMon i t o r ;
{ о п и с а н и е э к з емпл яра
с име нем Moni tor }
записи
типа
TOneMo n i t o r
Begin
{ ор г а ни з а ци я
р а б о ты
со
с труктурами
д а н ных }
End .
1 0.2.2.
Испол ьзование записей
Обращаться к экземплярам записей в программе можно двумя способа
м и - как к совокупностям полей (то есть к зап исям в целом ) , так и к
отдельным полям конкретной записи.
Ра бота с пол я м и экземпляров з а п и с е й
Для обращения к какому-либо полю некоторой записи указываются имя
экземпляра этой записи и имя поля в его составе , разделенные точко й :
<Имя э к з емпляр а з а писи> . <Имя пол я >
С полям и экземпляров зап исей можно производить любые о перации ,
допустим ые для типа данных этого поля , то есть указывать в качестве
параметров процедур и фун кци й , использовать как операнды для ариф
метических и логических операторов и так далее.
Организуем для примера ввод и нформации в зап ись об одном мониторе
(см . листинг 1 7 3 ) .
336
Глава 1 0 . Сложные ти пы дан н ых
Program Moni t o rs 2 ;
Uses
CRT ;
Туре
TOneMonitor
Price :
Record
=
CodeName :
String ;
Rea l ;
Di agona l :
Real ;
{ о п и с а н и е з а пи с и к а к
н о в о г о т и п а д а н ных
end ;
-
т и п а д а нных
TOneMon i t o r }
н а з в а ни е
1
Va r
Moni tor :
TOneMonitor ;
{ о пи с а н и е э к з емпл яра
с име нем Moni tor }
з а пи с и
типа
TOneMoni t o r
Begin
C l rS c r ;
Wri t e ( ' Введите
');
назв ание монитор а :
ReadLn ( Moni t o r . CodeName ) ;
{ в в о д с кл а в и а туры п о л я Co deName п е р еме н н о й
M o n i t o r . Переме н н а я Moni t o r я в л я е т с я
э к з емпляром з а п и си т и п а TOneMon i t o r }
Wri t eLn ;
Wri t e ( ' Введите
цену монитора :
');
ReadLn ( Monitor . P r i c e ) ;
{ ввод с клавиа туры поля Price переменной Monitor .
Переме н н а я Moni t o r явл я е т с я э к з емпл я р о м з а пи с и
т и п а TOneMoni t o r }
Wri t eLn ;
Wri te ( ' Вв едите размер диагонали :
'
);
ReadLn ( Moni t o r . Di agonal ) ;
{ в в о д с к л а в и а туры п о л я Di agona l п е р еме н н о й
M o n i tor . Переме н н а я Moni t o r я в л я е т с я
э к з емпл яром з а пи с и т и п а TOneMoni t o r }
Wri t eLn ;
Wr i t eLn ( ' Введенные
Wri t eLn ( ' Назв ание
характеристики :
'
);
'
Moni tor . CodeName ) ;
{ вывод н а э кр а н н а з в а ни я мо н и т о р а
х р а нимо г о
в п о л е CodeName переме н н о й Moni t o r }
Monitor . Price ) ;
Wri t eLn ( ' Цeнa
{ вывод н а э кр а н ц е ны мо нитора
хранимой в п о л е
P r i c e п е реме н н о й Moni t o r }
Wri t eLn ( ' Диагональ '
Moni tor . Diagonal ) ;
{ вы в о д н а э кр а н р а змера ди а г о н али мо н и т о р а
х р а н имо г о в п о л е Di agonal п е р е м е н н о й Moni tor }
End .
,
1
1
,
1
337
Turbo Pascal 7 . 0
Таким образом , поля экзем пляров записей используются точн о так же,
как и обычные переменные, только с указанием того , какому конкретно
экземпляру зап иси они принадлежат.
Работа с записями в целом
Для экземпляров записей в целом предусмотрена только одна возмож
ность применения - использование их в операторе присваивани я . Од
нако эта еди нственная возможность как раз и определяет фун кциональ
ность это го типа дан ных, разрешая проблему перемещения круп ных
единиц и нформации из одних переменных в другие .
Напишем программу для ввода информации о двух организациях - на
звания и годовые обороты (см . листин г 1 74) . Характеристики каждой
орган изации будем хранить в зап исях. После ввода информаци и об обе
их организациях обменяем значениями обе записи, если годовой оборот
у первой фирмы меньше, чем у второй .
Program F i rms ;
Uses
CRT ;
Тур е
TFi rminfo
Name :
=
Record
St ring ;
YearlySal e s :
Real ;
{ о п и с а ни е з а писи к а к
н о в о г о т и п а д а н ных
end ;
-
т и п а д а н ных ,
TFirmi n f o }
назв ание
Var
Firm1 ,
Firm2 ,
tmpF i rm : TFi rminfo ;
{ о п и с а н и е э к з емп л я р а
с име нем Moni tor }
з а п и си
типа
TOneMo n i t o r
Begin
ClrScr;
Wri te ( 1 Бв еди'l'е назв ание фирмы 1 : 1 ) ;
ReadLn ( Firm1 . Name ) ; { в в о д с кл авиатуры поля Name переме н н ой F i rml .
П е р е ме н н а я F i rml я в л я е т с я э к з емпл я р ом з а пи с и
т и п а TFirm}
Wr i t eLn ;
Wri t e ( 1 Бведи'l'е оборо'l' фирмы 1 : 1 ) ;
ReadLn ( F i rm1 . YearlySa l e s ) ;
{ в в о д с кл а в и а туры п о л я Year lyS a l e s п е р еменной
F i rml . П е р е ме н н а я F i rml я в л я е т с я э к з емпл яром
з а пи с и т и п а TFirm }
Wri t eLn ;
Wri t e ( 1 Бведи'l'е
338
назв ание
фирмы 2 :
1
);
Глава 1 0 . Сложн ые тип ы данных
Rea(U.n ( Firm2 . Name ) ; { в в о д с кл авиа туры поля Name переме нной F i rm2 .
Переме н н а я F i rm2 я в л я е т с я э к з емпл яром з а пи си
т и п а T F i rm }
Wri t eLn ;
Wri t e ( 1 Вв едите о б орот фирмы 2 : 1 ) ;
ReadLn ( F i rm2 . Ye arlySal e s ) ;
{ в в о д с к л а в и а туры п о л я YearlyS a l e s п ер еменной
F i rm2 . П е р е ме н н а я F i rm2 я в л я е т с я э к з е мпл яром
з а пи с и типа TFirm}
Wri t eLn ;
I f F i rml . YearlyS a l e s < F i rm2 . YearlySales Then
{ е сли г о до в ой о б о р о т п е р в о й фирмы ме н ь ше
г о д о в о г о о б о р о т а в т орой ; с р а в н и в а ю т с я п о л я
р а з ных э к з емпл я р о в з а п и с е й о д н о г о ти п а }
begin
tmpFirm : = F i rml ;
Firml : = F i rm2 ;
F i rm2 : = tmpFi rm ;
W r i t eLn ( 1 Изменен nорядок следования ! 1 ) ;
{ о бмен двух э к з е мпл яр о в з а п и с е й з н а ч е н и ями ;
при э т ом з а пи си и с п о л ь зуют с я к а к ц е л о с т ные
с трук туры и обращение к ним п р ои з в о ди т с я
п о име н и , б е з ука з а н и я к о н кр е т ных п о л е й }
end ;
End .
1 0.2.з.
Массивы записей
С момента описан ия в разделе описания типов Туре запись становится
полноправным типом данных и может использоваться наравне с други
ми ти пами данных для орган изации структуры и нформации в програм
ме. В частности, допустимо описание массива записей. Это позволяет опи
сать м н ожество объе ктов , и м еющих н е которы й н а б о р разн оти п н ых
характеристик, и обеспечить удобную работу с такой структуро й .
Для де монстрации дан ной возможности вернемся к организации работы
со списком мон иторов в некотором магазине и напишем программу (см .
листин г 1 7 5 ) , выполняющую следующие действия :
•
•
•
•
запрос количества разных м оделей мониторов, имеющихся в ассор
тим е нте;
ввод и н формации о мониторах в кол ичестве , введен н о м пол ьзова
телем на предыдущем шаге ;
упорядочи вание с писка мониторов п о возрастанию цены ;
вывод упорядоченного списка на экран.
339
Turbo Pascal 7 . 0
;\.:j)�'6rlf��Pi7§·�;·�����.��rй���й.� .:����!�·�l��;F�·���w�;;�9W�+�:P���-- �··'�jf�it�fi�.
Program Mon i t o rs 2 ;
Uses
CRT ;
Con s t
MaxNumЬer = 5 0 ; { о пи с а ни е к о н с т а н т ы , пред с т а в л яющей мак сима л ь н о
в о змож н о е колич е с т в о мо н и т о р о в }
Туре
ТМonitor = record
CodeName : String ;
Diagona l : Real ;
Price : Real ;
end;
{ о п и с а н и е н о в о г о т и п а д а н ных - з а п и с и ,
п р е д с т а вл яющей х а р а к т е р и с т и ки о д н о г о м о н и т о р а }
Var
Monitors : Array [ 1 . . MaxNwnЬer ] Of TMonitor ;
{ о п и с а н и е ма ссив а , к аждый э л е ме н т к о т о р о г о
име е т т и п TMoni t o r , т о е с т ь я в л я е т с я
э к з емпл яром з а п и с и }
CurrentNwnЬer : Byt e ;
{ п е реме н н а я дл я х р а н е н и я р е а л ь н о учитыв а емо го
к о л и ч е с т в а мони т ор о в }
i : Intege r ;
Procedure SortByP r i c eAscending ;
{ процедур а сортир о в ки ма с с и в а з а пи с е й п о
в о зр а с т анию п о л я Pri c e }
Var
i , j : Intege r ;
tmpMonitor : TMonitor ;
hegin
For i : = 1 То CurrentNwnЬer- 1 Do
For j : = i + 1 То CurrentNwnЬer Do
{ В про ц е с с е упорядочи в а н и я уч а с т в уют т о л ь к о
CurrentNumЬer первых элеме н т о в ма с си в а , т о е с т ь
т о л ь ко р е а л ь н о учи тыва емые мо н и т оры , а н е в с е
эл еме нты ма с сива , которых , скорее в с е г о , больше }
I f Monitors [ i ] . Price > Monitors [ j ] . Price Then
{ е сли поле Pri c e i - г о элеме н т а ма с си в а б о л ь ш е ,
ч ем п о л е P r i c e j - г о э л е ме н т а ма с си в а }
hegin
tmpMonitor : = Monitors [ i ) ;
Monitors [ i ] : = Monitors [ j ] ;
Moni tors [ j ) : = tmpMoni t o r ;
{ о бме н з н а ч е ни ями двух э л е ме н т о в ма с с и в а
к а к цел о с т ных п ереме н ных , б е з у к а з а н и я
к о н кр е т ных п о л е й }
end ;
end;
340
Глава 1 О. Сложн ые тип ы данных
Begin
C l rS c r ;
Wri t e ( ' Введите
количество мониторов :
ReadLn ( CurrentNumber ) ;
{ определение
');
к олич е с т в а
учи тыв а емых мо н и т ор о в }
Wr i t eLn ;
For
i : = 1 То CurrentNumЬer Do
{ ввод инф ормации о монит орах в количе ств е ,
оnределяемом nеременной
CurrentNUmЬer ,
введенной nольз ователем }
begin
Wri t eLn ( ' Введите назв ание монитора
',
i,
' :
');
ReadLn ( Moni t o r s [ i ] . CodeName ) ;
Writ eLn ( ' Введите размер
диагонали :
');
ReadLn ( Moni tors [ i ] . Di agonal ) ;
Wri t eLn ( ' Вв едите
цену :
');
ReadLn ( Monitors [ i ] . Pric e ) ;
end ;
Sort ByP r i c eAsc ending ;
{ вы з о в
п р о ц е дуры упорядочи в а н и я
ма с с и в а }
ClrS c r ;
For
i : = 1 То CurrentNumЬer Do
begin
Wri t eLn ( ' Монитор
',
i,
' :
Wri t eLn ( ' Haзв aниe монит ора :
Wri t eLn ( ' Размер
диагонали :
• );
',
Monitors [ i ] . CodeName ) ;
Moni t ors [ i ] Diagona l ) ;
•
Wri t eLn ( ' Цeнa :
Monitors [ i ] . Price ) ;
Writ eLn ( '
ReadКey ;
любую
end ;
Нажмите
клавишу
•
•
•
');
{ выв од упорядоченного спис к а монИ торов на э к ран ,
причем при выводе у к а зыв ают с я к о н к р е т ные п о л я
з а пи с е й - э л еме н т о в ма с си в а }
End .
1 о . з . С о зд а ние новы х т и пов д а н н ы х .
Раздел описани я типо в Ту р е
Раздел оп исания типов Тур е предназначен для концентраци и о п исаний
типов данных в одном месте программы или модуля. Еди нственн ы й тип
данных, который обязательно должен описываться в данном разделе , это зап иси. Все остальные тип ы , как, например, массивы, могут вводиться
по мере их использования для описания переменных. Однако , если в про
грамме используются две такие переменные, которые должны иметь один
34 1
Turbo Pascal 7 . 0
нестандартны й ти п , и эти переменные о писаны в разделе оп исания пе
рем енных V a r не в одну строку, рекомендуется присвоить такому ти пу
дан ных наименование в разделе описания типов Туре . То же самое от
носится и к локальны м переменным, которые должн ы иметь некоторый
тип дан ных, такой же, как у какой-либо глобальной перем е н н о й .
При ведем примеры оп исанных случаев.
1 . Оп исание двух перемен ных одинакового типа:
Var
А:
В:
Array [ 1 , . 1 0 0 ] Of
{ описание
элеме н т о в
Array [ 1 . . 1 0 0 ] Of
{ описание
элеме н т о в
Intege r ;
ма с с и в а с име н ем А и з
т и п а Int eger }
Intege r ;
ма с с и в а с име н ем В и з
т и п а Int eger }
ста
ста
2 . Описани е локальной переменной такого же типа, как некоторая
глобальная :
Va r
А : Array [ 1 . . 1 0 0 ] Of Intege r ;
{ о п и с а н и е г л о б ал ь н о г о ма с с и в а с
и з с т а элеме н т о в т и п а Int eger }
име н е м А
Procedure Test 1 ;
Va r
В : Array [ 1 . . 1 0 0 ] Of Intege r ;
{ оп и с а н и е л о к ал ь н о г о ма с си в а с име н е м В
и з с т а элеме н т о в т и п а Int eger }
В обоих при ведеи н ых случаях можно присвоИть и мя используемому при
оп исан и и переменных типу данных Array [ 1 1 О О ] Of I n tege r . Описа
ние ти па в разделе Т ур е имеет следующи й вид:
•
•
Тур е
<Имя т и п а > = < О п и с а н и е т и п а > ;
Для приведеиных выше примеров описание типа данных и его исполь
зован ие может выглядеть следующим образом :
Туре
HundredArray = Array [ 1 . . 1 0 0 ] Of Intege r ;
{ о п и с а н и е типа д а н ных с име нем Hundr edAr ray , п р е д с та в
л яюще г о с о б о й м а с с и в и з с т а элеме н т о в т и п а I n t eger }
342
Глава 1 0 . Сложн ые ти п ы да нных
Va r
А:
HundredArray ;
{ о п и с а н и е глобал ь н о г о ма с с и в а с име н е м А
и з с т а элеме н т о в т и п а Int eger }
В:
HundredArray ;
{ о п и с а н и е г л о б а л ь н о г о ма с с и в а с име н ем В
и з с т а элеме н т о в т и п а Int eger }
Procedure
Test 1 ;
va r
С:
HundredArray ;
{ о п и с а н и е л о к а л ь н о г о ма с с и в а с име н е м С
из с т а элеме н т о в т и п а Int eger }
Положительный эффект от такого рода преобразован ия о писан и й струк
туры информации - это повышение гибкости программ ы для возмож
н ых дальнейших изменений . Например, чтобы изменить размер массива
и пределы изменения его индексов, в предыдущем варианте необходимо
исправить о п и сания всех перем е н н ых , которые имеют такой тип , а в
новом варианте достаточно исправить только описан ие самого типа. Та
ким образо м , работа с нестандартными типами дан н ых в некоторой сте
пени аналогична работе с константами .
Второй интересный момент именования типов дан ных вытекает из жес
ткой типизированности язы ка Turbo Pascal . На этапе компиляции про
грамм ы все тип ы данных получают временные назван ия . Таким образо м ,
переменные А и в , описанные в разных строках п рограм м ы , казалось б ы ,
с одинаковым типом данных Array [ 1 1 о о ] Of :I:nteger, на самом деле
с точ ки зрения Turbo Pascal имеют разные типы данных, поэтому дЛЯ них
не будет возможным использован ие оператора п рисваи вани я . Особенно
остро встает эта проблема при передаче данных сложных типов в каче
стве параметров в процедуры и функции . Рассмотрим пример некоррек
тной п ередач и параметра в процедуру:
•
•
Var
А:
Array [ 1 . . 1 0 0 ] Of Int eger ;
{ о пи с а н и е г л о б ал ь н о г о ма с с и в а и з с т а э л е ме н т о в
т и п а Int eger с име н ем А }
Procedure T e s t 1 ( P : Array [ 1 . 1 0 0 ] Of Integer ) ;
{ о п и с а н и е п р о ц е дуры с п а р аме тром , имеющим
сложный тип д а н ных }
begin
end ;
Begin
Te s t 1 ( А ) ;
{ н е к о рр е к т н а я п о пыт к а выз о в а п р о ц е дуры T e s t 1 - п е р е
ме н н а я А име е т тип д а н ных , о тл и ч ный о т т и п а д а н ных
п а р аме тра Р , у к а з а н н о г о в з а г ол о в к е п р о ц е дуры }
End .
.
343
Tu rbo Pascal 7 . 0
При попытке компиляции такой программ ы будет в ыдана ошибка <<O f
exp e c t e d>> . Оп исание параметра с таким типом данн ых н е возможно, так
как в данном случае его нельзя будет передать в процедуру. А есл и про
цедура должна получать параметр и м е н н о такого типа, то програм ма
должна выглядеть следующим образом :
Туре
HundredArray = Array [ l . . 1 0 0 ] Of Int eger ;
{ о пи с а н и е т и п а д а н ных с име н ем Hundr edArray
п р е д с т а в л яюще г о с о бой ма с с и в и з с т а э л е ме н т о в
т и п а I n t eger }
1
Var
А:
HundredArray ;
Procedure
{ о писание глобаль ного мас си в а
т и п а Int eger с име н ем А }
Te s t l ( P : HundredArray ) ;
{ о п и с а ни е п р о ц е дуры с параме тром l
сложный тип д а нных }
из
ста элементов
имеющим
begin
end ;
Begin
Te s t l ( А ) ; { корре к тный выз о в проц едуры Tes t l - п е р е ме н н а я
А име е т т и п дан ных
э к в и в а л е н т ный типу д а н ных
п араме т р а Р , ука з а н н о г о в з а г ол о в к е п р о ц е дуры }
1
End .
1 0. 4 . И сп ол ь з ов ание сл ож ны х т и пов дан н ы х
для о б мен а инфо рм а цие й
Сложные ти пы данных - массивы и записи - находят Ш I-Jрокое приме
нение в обмене информацией между частям и программ ы . Так, в програм
ме Moni t or s 2 процедура S ortByPri c eAscending предназначена для упо
рядо ч и ван ия гл обал ь н о го м ассива Mo n i t o r s . Но более и нтере с н ы м
вариантом обмена сложными данными является использование их как па
раметров процедур и фун кци й . В качестве примеров мы рассмотрим стан
дартные процедуры DrawPoly, Fil lPoly, и GetArcCoords модуля Graph.
1 0.4. 1 .
Рисова н и е м ногоуголь н и ко в
Процедура DrawPoly предназначена для вы вода на экран в графическом
режи ме многоугольн ика и и меет следующий вид:
DrаwРоlу ( < Колич е с т в о т о ч е к > , <М а с с и в т о ч е к > ) ;
344
Глава 1 0 . Сложные ти п ы дан н ых
В качестве параметра Массив оrочек при вызове процедуры должен указы
ваться массив элементов типа Integer, содержащий координаты опорных
точек (вершин) многоугольника. Н ечетные элементы массива содержат го
ризонтальные координаты вершин, четные элементы - вертикальные. Па
раметр Количесоrво оrочек определяет, сколько пар элементов М а с с и в а
т оч е к необходимо использовать п р и выводе многоугольника.
Цвет и стиль л и н и и , которой выводится многоугольник, определяются
текущими характеристиками обводки , установлен н ы м и соответственно
процедурами S e t C o l o r и S e t L i ne S tyl e .
Приведем программу (см . листинг 1 76 ) , выводя щую на экран треуголь
ник с верш инами в точках ( 1 0, 1 0) , ( 1 00, 1 00) , (2 1 0, 1 0) . Замети м , что о
замкнутости многоугольника должен позаботиться разработч ик, то есть
есл и многоугольник должен быть зам кнут, то координаты последней его
верши н ы должны совпадать с первой . Таким образом , для вывода треу
гольника необходимо построить многоугольник с четырьмя верш инам и :
( 1 0 , 1 0) , ( 1 00, 1 00 ) , (2 1 0 , 1 0) и ( 1 0, 1 0) .
.
;.•· 11iitc:.f Инr. ;(76�.1iepeдa-i�··:.� �paiiii.eтpa>J::лoЖ.-!>t();,,-Иna.•д aннl.i�'\) �·�· ··•· · • ·'JB '\':H:;:·�··
• "· ···· · · ':J·::
·
<
'·· · '
"
.:
.n poцёp.yp�;p;.:�wP\)IY:' .
•"
::
· ·' "
P rogram. Po lygon ;
·
·
··· ·· · ·• ' , ''>:
,,:".:'' ' )·•:i '•Uг<Щ;, .:
,,,
Uses
CRT ,
Graph ;
Var
Gd ,
Gm. :
Point s :
Int ege r ;
Array [ 1
•
8 ] Of Integer ;
{ о п и с а ни е ма с с и в а и з в о с ь ми э л е ме н т о в дл я
п е р е д а ч и процедуре DrawPoly к о о рди н а т ч е тыр е х
т о ч е к ( по д в а элеме н т а ма ссива н а одну точку ) }
•
Begin
Gd
: = Detect ;
Gm.
:=
О;
Init Graph { Gd ,
Gm. ,
•
'
);
S e t C o l o r { Wh i t e ) ;
S e t L ineStyle { Dott edLn , О , Thi ckWidth ) ;
{ ин и ци а л и з а ц и я графич е с к о г о
х а р а к т е р и с т и к о б в одки }
Point s [ 1 ] : = 1 0 ;
р е жима
и
установка
P o int s [ 2 ] : = 1 0 ;
P o i nt s [ 3 ] : = 1 0 0 ;
P o i nt s [ 4 ] : = 1 0 0 ;
P o int s [ 5 ] : = 2 1 0 ;
P o int s [ б ] : = l O ;
P o i nt s [ 7 ] : = 1 0 ;
Point s [ 8 ] : = 1 0 ;
{ з а п ол н е н и е
ма с си в а
к о о р ди н а т ами
в е р ши н }
345
Turbo Pascal 7 . 0
DrawPoly ( 4 ,
Point s ) ;
{ выв од мн о г оугол ь н и к а ,
ч е тыр е х т о ч е к }
с о с т о яще г о
из
ReadKey ;
C l o s e Graph ;
End .
Об р ати м внимание н а одну особенность и н ициал изац и и граф и ч еского
р ежи м а . Этот процесс зани м ает некоторое вр емя на всех компьютерах
без исключен ия , особе нно на тех, кото р ы е р аботают под управлением
опе р аци о н н ы х с и сте м , и м еющих граф и ч е с к и е об оло ч к и ( н ап р и м е р ,
Windows) . Однако в о в р емя с м е н ы р ежима программа продолжает вы
полняться . В нашем приме р е в этот момент происход ит устано вка те
кущих ха р актеристик об водки и заполнение значе н и я м и элементов мас
с и в а P o i n t s . Е с л и б ы з а п ол н е н и е з н а ч е н и я м и п р о и с х од и л о до
и н и циализаци и графического р ежима, то это просто увели чило бы ви
димое п ол ьзо в ателю в р емя работы программ ы . Поскольку и н и ц и ализа
ци я графического режима может занимать несколько секунд, рекомен
дуется п о сл е в ы з о в а п р о цедур ы :I n i t Gr aph п о м е щ ать к а к и е - л и б о
расчетные фрагме нты програм м ы .
1 0.4.2.
Рисова н и е закрашен н ого м н о гоугол ь н и ка
Процеду р а Fil lPoly аналогична п р оцедур е DrawP o ly, но вы водит зак
рашенны й м ногоугольник:
Fi l l Роlу ( < Колич е с т в о т о ч е к > , <Ма ссив т оч е к> ) ;
В отличие от процедуры DrawPoly данная процедура вы водит зам кну
ты й многоугольник, соединяя его конечную верш ину с начальной . Для
заполнения внутренней области многоугольника используется текущая за
ли вка, установленная процедурой SetFi ll Styl e .
';:т:j.�����r��··. '"·���:�ff!���!�к:�����::· c "<"··"'·d · "·�: ·�.�·��;:�:. . . . .
,
Program Polygon2 ;
Uses
CRT ,
Va r
Gd ,
Graph ;
Gm :
Point s :
Intege r ;
Array [ 1
б ] O f Integer ;
{ о п и с а н и е ма с с и в а и з ше с т и э л е ме н т о в дл я
п е р е д а ч и п р о ц е дуре DrawP o ly к о орди н а т т р е х
т о ч е к ( п о д в а элеме н т а ма с с и в а н а о д н у т о ч к у } }
Begin
Gd
346
: =
Detect ;
•
.
Глава 1 0 . Сложные ти п ы дан н ых
Gm
:=
О;
Init Graph ( Gd ,
Gm ,
' ');
SetColor ( Wh i t e ) ;
SetLineStyl e ( Dott edLn ,
О,
ThickWidth ) ;
SetFi l l Style ( So l idFi l l , Green ) ;
{ и нициали з а ци я г р а фич е с к о г о
х а р а к т ер и с т и к о б в о д ки }
р ежима
и
установка
Point s [ 1 ] : = 1 0 ;
Point s [ 2 ] : = 1 0 ;
Point s [ 3 ] : = 1 0 0 ;
Point s [ 4 ] : = 1 0 0 ;
Point s [ S ] : = 2 1 0 ;
{ з а п ол н е н и е
Point s [ б ] : = 1 0 ;
F i l l P o ly ( 4 ,
ма с си в а
к о о р ди н а т ами
Point s ) ;
{ вы во д мн о г о у г ол ь н и к а ,
с о с т о яше г о
в е р ши н }
из
трех
точе к }
ReadKey;
C l o s e Graph ;
End .
1 0.4.3.
П р оцедура GetArcCoords
Процедура GetArcCoords использует параметр сложного типа данных не
для приема информаци и , а для ее выдачи и заполняет переданную ей
запись координатами центра, а также начальной и конечной точек дуги
или сектора, которые последними вы водились на экран .
GetArcCoords ( < Зaпиc ь > ) ;
В качестве параметра Заnись должна использоваться переменная типа
ArcCoordsTyp e , описанная в модуле Graph следующим образом :
ArcCoordsType
Х,
=
Record
У,
{ к о о р ди н а т ы ц е н тр а }
Xst art ,
Xend,
Yst art ,
Yend :
Integer ;
{ к о орди н а ты н а ч а л ь н ой
{ к о орди н а т ы
конечной
точки }
т о ч ки }
end ;
Рассмотрим программу (см . листинг 1 7 8 ) , вы
водящую на экран изображение, показанное
на рис. 1 25 . Изображение состоит из сектора
круга с начальным углом 45• и конечным
1 3 5 " . Для определения координат точек, из
которых проводятся дополнительные линии,
используется процедура GetArcCoords .
-
1 25. Результа т ра боты
программы FilledPolygon
Рис.
347
Turbo Pascal 7 . 0
",.,�:fff����:'i ������r����t�,t���*·����m��·�i�:·:�,;
.
Prograш Get t ingCoords ;
Uses
CR'l' , Graph ;
Var
Gd, GDI : Intege r ;
Point s : ArcCoords'l'ype ;
{ о п и с а ние п е р еме н н о й - э к з емпл я р а з а пи с и
для п ер е д а чи в п р о ц е дуру GetArcCoords
в к а ч е с т в е п араме т р а }
Begin
Gd : = Detect ;
GJII : = О ;
InitGraph ( Gd , GJII , • ' ) ;
SetColor ( Wh i t e ) ;
SetLineStyl e ( Dott edLn , О , 'l'hi ckWidth ) ;
SetF i l l Style ( 9 , Green ) ;
{ и нициали з а ци я графиче с к о г о р е жима и у с т а н о в ка
х а р а к т е р и с т и к о б в одки и з а л и в ки }
Sector ( 3 2 0 , 3 8 0 , 4 5 , 1 3 5 , 2 0 0 , 2 0 0 ) ;
{ вывод сектор а }
GetArcCoords ( Point s ) ;
{ о п р е д е л е н и е ко орди н а т це н тр ал ь н ой т о ч к и ,
н а ч а л ь н о й т о чки и к о н е ч н о й т о ч ки , р е зуль т а т
в п е р еме н н о й Point s }
Line ( Po i nt s . X s t a rt , Point s . Ystart , 3 2 0 , 1 0 0 ) ;
{ выв од линии , с о единяющей н а ч а л ь ную т о ч ку
с е к т ора и т о ч ку с ко орди н а т ами ( 3 2 О , 1 О О ) ;
и с п о л ь зуют с я поля з а пи с и P o i nt s }
Line ( Po i nt s . Xend, Point s . Yend, 3 2 0 , 1 0 0 ) ;
{ вы во д линии , с о е ди н яющей к о н е ч ную т о ч ку
с е к т ора и т о ч ку с коорди н а т ами ( 3 2 0 , 1 0 0 ) ;
и с п о л ь зую т с я поля з а п ис и P o i nt s }
ReadKey ;
C l o s e Graph ;
End .
1 o.s.
П е р е м енные - указа т ел и
Механизм работы переменных-указателей довольно полно описан в раз
деле, посвященном спрайтам , а сейчас мы остановимся на некоторых под
робностях их использования.
Основной задачей использования переменных-указателей является пере
нос данных из сегмента данных в Неар-память, и меющую возможность
348
Глава 1 0 . Сложн ы е ти п ы дан ных
вместить больши й объем информации. Также с помощью н их осуществ
ляется более развитое управление объемами памяти, занятой программой ,
через механизмы ее выделения и освобождения . Так как выделение и ос
вобождение памяти происходит во время выполнения программ ы и раз
меры необходим о й памяти определяются не на этапе разработки , Неар
память также назы вают динамической .
Переменные-указател и делятся на два вида : типизированные и нетипизи
рованные. Н етип изированные указатели ссылаются на произвольную об
ласть памяти, использовать которую стандартными средствами Turbo Pascal
невозможно . Все о перации с нети пизированными указателям и произво
дятся специальными процедурами тип а Ge tMem, F r e eMem, Get image и
Put image . Данный вид указателей представлен типом данных P o i n t e r ,
оп исанным при обсуждении спрайтов. Тип изированные указатели ссы
лаются · на область памяти , в которой находятся переменные определен
ного ти па, и позволяют выделить место в памяти для размещения пере
менной , определить и изменить ее значен ие, а также освободить память,
занятую п од переменную, в случае если она больше не будет использо
ваться в програм ме.
1 0.5. 1 .
Описание и и н и ци ал изация
тип изирова н н ых указателей
Описание переменных, ссылающихся н а другую переменную, расположен
ную в неар - п амяти , производится в разделе описания переменных var
следующим образом :
Var
<Имя п е р еме н н о й -ука з а т ел я > : А < Т и п п ер еме н н о й > ;
или . в разделе описания типов дан ных Тур е :
Туре
< Т и п у к а з а т е л я > = А < Т и п п ер еме н н ой> ;
В качестве Типа переменной до
пускается и с п ользоват ь любой
тип дан ных, в том ч и сле и ука
затель.
Посл е о п и с а н и я п е р е м е н н о й
указателя память под п еремен
ную в Неар - п амяти не выделяет
ся ( с м . р и с . 1 2 6 ) , т о е с т ь е е
использование невозможно . Для
выделения п амяти (инициализа-
Се г мен т дан н ых
не сс ылается
на область памяти
?
Рис.
12
о
7 8 9
Неар- nамять
1 26. Под переменную -указа тель
не выделена память
349
Turbo Pascal 7 . 0
ции переменной-указателя) необходимо воспользоваться процедурой New.
Эта процедура выделяет память под задан ную переменную-указатель и
заносит в этот указатель ссылку на выделенную п амять:
Nеw ( < Пер еме н н а я -у к а з а т ел ь > ) ;
Заметим , что в отличие от аналогичной процедуры GetMem для нетип и
зированных указателей процедура New не требует указания размера в ы
деляемой памяти , так как он может быть вычислен автоматически на
основе информаци и о типе переменной , на которую должна ссылаться
переменная-указатель.
Освобожден ие памяти
Для освобожден ия памяти , выделенной под переменную-указатель, не
обходимо вызвать процедуру Di spo s e :
Di sроsе ( < Переме н н а я -ука з а тел ь > ) ;
Таким образом , выделение и освобождение памяти для типизированных и
нетипизированных указателей практически одинаково. Однако непосредствен
ная работа с разными видами указателей имеет существенные отличия .
1 0.5.2.
И с п ол ьзован и е типизи рован н ых указателе й
Ти пизирован ная переменная-указател ь имеет двойственную сущность
(см. рис. 1 27 ) . С одной сторон ы , это переменная , описанная в разделе
описания переменных var и , соот
ветствен н о , физически находящая
ся в сегменте дан ных. С другой сто
Се гме нт данн ых
ро н ы , тип изирован н ы й указатель
динамическо й памяти
подразумевает под собой существо
вание еще одной переменной - на
ходящейся в динамической (Неар)
памяти . Соответствен н о , операци и ,
до пусти м ы е для т и п и з и р о в а н н ы х
Рис. 1 2 7. Двойственная сущность
указателей , можно раздел ить на две
переменной-указателя
групп ы :
1 . Операции с указателями как с переменными - действия выполняют
ся над указателями , а не над переменными , на которые они ссылают
ся. В число таких операций входят и нициализация (вьщеление памяти
п од указатель) , деи нициализация (освобождение памяти , занятой п од
указатель) и использование указателей в операторах присваивания .
2 . Операции с перемен н ы м и , на которые ссыл аются указатели - л ю
б ы е дей ствия , допусти мые для типа п еременных, н а которые ссы
лаются указатели .
350
Глава 1 0 . Сложные типы дан ных
О п е р а ци и с указателями как с перемен н ы м и
Рассмотрим возможн ые операции
с
перемен н ы м и -указателям и :
1 . И н и циал изация и деинициал изация переменных (тип изированн ых
указателей) осуществляется , соответствен н о , п роцедурам и New и
Di spo s e , рассмотрен н ы м и выше (см. л и стин г 1 79 ) .
Prograш
TypedPo i n t er s l ;
Va r
tpl :
" Intege r ;
{ о п и с а н и е переме н н о й - ук а з а т е л я с име н е м tp1 1
с сылающе й с я на п е р еме н н ую т и п а I n t eger }
tp2 :
"Real ;
{ о п и с а н и е п е реме н н о й - ук а з а т ел я с име н е м
с сыл ающе й с я на п е р еме н н ую т и п а Real }
tp2 1
Begin
New ( tp l ) ;
{ выдел е н и е динамич е с кой п амя ти
п е р еме н ную - ук а з а т е л ь tpl }
под
New ( tp 2 ) ;
{ выд е л е н и е дин ами ч е с к о й п амяти
п е р ем е н ную - ук а з а т е л ь tp2 }
под
Di spo s e ( tp l ) ;
{ о с в о б о ж д е н и е д и н ами ч е с к о й
п о д п е р еме н ную tpl }
{ о с в о б о JJ< д е н и е дин амич е с к о й
п о д п е р еме н ную tp2 }
D i s p o s e ( tp2 ) ;
п амяти 1
выд е л е н н о й
памяти
выд е л е н н о й
1
End .
2 . Для переменных-указателей определена о п ерация присваивани я , то
есть знач е н ие одной переменной-указателя можно присвоить дру
гой . В результате такого присвоеимя оба указателя будут ссылаться
на одну и ту же переменную (см . рис. 1 28 ) .
Необходи мо заметить, что з а возвращение памяти , выделенной про
грамме, отвечает сама программа. То есть вся память, которая была
ей выделена, должна быть освобождена с помощью вызова процеду
ры Dispo s e . Если под переменную, которой присваивается новое
значение и з другого ука
зателя , уже выделена па Сегмент да н н ых
мять, то ссылка на нее
будет утеряна и возвра
тить п амять системе бу
ссылается на область
дет уже невозможно. По динам
ическо й памяти
этому перед изменением
Неар· nамять
значения перемен н о й
у к а з ател я н е о бх од и м о
Рис. 1 28 . Два указа теля ссылаются
л ибо освободить п амять,
на одну и ту же о бласть памяти
35 1
Turbo Pascal 7 . 0
выделенную п од нее, либо сохранить значен и е указателя в другой
переменной (см . листин г 1 80).
·
·�p:��f�{�;���tW��q:;�it�����f�������7:2:��r�,���t�:: · ,i:1,; :iк
Program TypedPoint ers 2 ;
Va r
tpl :
" Intege r ; { о п и с а н и е п ереме н н о й - ук а з а т е л я с име н е м
с сыл ающе й с я на п е р еме н н ую тип а I n t eger }
tpl ,
tp2 :
" Intege r ; { о п и с а н и е п е р еме н н ой - ук а з а т е л я с име н е м
с сыл ающе й с я на п е р еме нную т ип а I n t eger }
tp2 ,
Begin
{ выдел е н и е динамич е с кой памяти под
п е р еме н ную- у к а з а т е л ь tpl }
tp2 : = tpl ;
{ при с в о е ни е з н а ч е ни я п е р е ме н н о й - ук а з а т е л я tpl
п е р еме н н о й - у к а з а т е лю tp2 ; т е п е р ь о ни с с ыл а ют с я
н а одну и ту же п е р еме н ную в Неар - п амяти }
Di spo s e ( tp l ) ;
{ о с в о б ожде н и е ди н ами ч е с к о й памяти , выд е л е н н ой
п о д п ер еме н ную tpl ; о с в о б ожда т ь п е р еме н ную
tp2 н е л ь з я , т а к к а к п о д н е е р е ал ь н о н е
выдел е н о п амяти }
New ( tp l ) ;
End .
3 . И з операций сравнения указателей допустим ы только операции <<рав
но» (=) и <<н е равно>> ( < > ) . При этом сравниваются не переменн ы е ,
на которые ссылаются указатели , а с а м и указатели , т о есть два
указателя равны , если они ссылаются на одну и ту же переменную.
Указатели , п оказанные на рис. 1 28 , равны , так как ссылаются на
одну и ту же обл асть п амяти вне зависимости от того , какие данные
в ней н аходятся.
Если два указателя ссылают
ся
на разные переме н н ые в
Се гмент да н н ых
д и н а м и ч ес к о й п а м яти , то
они н е равны даже в том слу
чае, если равны сами дина
ссылается на область
мические п е р е ме н н ы е ( с м .
ди нам ич еско й п амят и
р и с . 1 2 9 ) . И с п ол ьз о в ан и е
Неа р-память
операторо в сравн е н и я п р и
работе с переменн ы м и -ука
Рис. 1 2 9 . Переменныв-указатели ссылаются
зателями продемонстрирова
на разные о бла сти памяти
но в листи н ге 1 8 1 .
352
Глава 1 О. Сложн ые ти п ы данных
Program TypedPoint e r s З ;
Va r
tpl :
" Intege r ;
tp2 :
tp3 :
" Intege r ;
" Intege r ;
Begin
New ( tp l ) ;
New ( tp 2 ) ;
tрЗ
:=
tpl ;
{ о пи с а ни е т р е х п е р еме нных - ук а з а т е л е й
с име нами tpl , t p 2 и tрЗ , с сыл ающи х с я
н а п е р еме н вые т и п а Int eger }
{ выде л е н и е дин амич е с кой п амяти п о д
п е р еме нкую- ук а з а т е л ь tpl }
{ выд е л е н и е дин амич е с кой п амяти п о д
п е р емен кую- ук а з а т е л ь tp2 }
{ пр и с в о е ни е з н а ч е н и я п е р е ме н н о й - у к а з а т ел я tpl
п е р еме н н о й - у к а з а т елю tрЗ ; т е п е р ь о н и с сыл ают с я
н а одну и ту ж е п е р еме н кую в Н е ар - п амяти }
Wr i t eLn ;
I f tpl = tp2
then Wri t eLn ( ' Первый и воrорой равны ! ' ) ;
{ вы в о д с т р о к и , е сли ука з а т ели tpl и tp2
с сыл ают с я н а одну и ту же п е р еме н кую
в дин ами ч е с кой п амяти ( с т р о к а не в ы в о ди т с я ,
т а к к а к усл о в и е ложно ) }
I f tpl = t р З
then Writ eLn ( ' Первый и воrорой равны ! ' ) ;
{ выв о д с т р о к и , е сли ук а з а т ел и tpl и tрЗ
с сыл ают с я н а одну и ту же п е ремен кую в
дин амич е с кой п амяти ( с т р о к а в ы в о ди т с я , т а к
к а к усл о в и е и с т и н н о ) }
Di spo s e ( tp2 ) ;
{ о с в о б о жд е н и е ди нами ч е с к о й п а мя т и , в ыд е л е н н о й
п о д п е р еме н кую tp2 }
Di spo s e ( tp3 ) ;
{ о с в о б ожд е н и е дин амич е с к о й п амяти , выд е л е н н о й
п о д п е р еме н кую tрЗ ; о с в о б о жд а т ь п е р еме н кую
tpl н е л ь з я , т а к к а к п о д н е е р е ал ь н о н е
выд е л е н о п амя т и }
End .
Заметим , что в приведеином примере п ам ять , выделенная п од пе
ременную tp l , освобождалась так, как будто она была выделена
под переменную tр З . Это впол н е допустим о , так как дан н ы е п ере
менные ссыл аются на одну и ту же область памяти , что обусло вле
н о о п ератором tрЗ : = tp l .
4 . Ари ф м етические о п ерац и и с переменн ы м и -указателя м и недопусти
мы, так как о н и не и меют смысла. Нап р и м е р , н ел ьзя заранее ска
зать , куда будет ссылаться переменная -указатель , если п р и бавить к
ней еди н и цу или другой указатель. Память в ыделяется операц и о н 12
Зав:. 702
353
Turbo Pascal 7 . 0
ной системой случай н ы м с точки зре н и я программ ы образом. По
этому взаимное расположение переменных в динам и ч еской памяти
не определено н а этапе разработки п рограмм ы .
Следует заметить, что распределение переменных в сегменте дан ных про
исходит по -другому. А именно: переменные содержатся в памяти в том
порядке , в каком они описаны в разделе описания переменных va r .
Замети м , что все оп исанные операции приме н и м ы и к нетип изирован
ным указателям - переменным типа P o i n t e r .
Операции с переме н н ы м и , н а которые ссыл а ются указатели
Для обращения к переменн о й , на которую ссылается ти п изированн ы й
указатель, используется оператор разыменовывания л :
< П е р еме н н а я - т и п и з и р о в а н ный у к а з а т ел ь > А
После получения доступа к переменной с помощью оператора разыме
новывания с ней можно выполнять любые действия, допустимые для пе
ремен н ых данного типа: использовать в операторах присnаивания и раз
л и ч н ых выражен иях, п ередавать в качестве параметров процедурам и
функциям , и так далее.
Рассмотрим пример работы с тип изирован ным указателем , ссылающим
с я на переменную ти па :Integer (см . листинг 1 82) .
��1;�;�]����:·���2-,�tl�;�����i���i���:m:'i��;�y, ,
Program ТypedP oint e r s 4 ;
Var
tpl : A int ege r ;
{ о п и с а н и е переме н н о й - ук а з а т е л я с име н е м tpl
с сыл ающе й с я н а п ер еме н ную т и п а I n t eger }
Begin
New ( tp l ) ;
{ выд е л е н и е дин амич е с к о й п амя ти п о д
п е р емен ную- у к а з а т е л ь tpl }
{ при с в о е ни е п ереме н н о й
на к о т о рую с с ыл а е т с я
tpl A : = 1 0 ;
п е ременн а я - ук а з а т ел ь t p l з н а ч е ни я 1 0 ( дл я
ука з а ни я п е реме н н ой и с п о л ь з о в а н о п е р а т о р
р а зыме н о выв а н и я " : tp l " ) }
Wri t eLn ;
Writ eLn ( 1 NwnЬer = 1 , tpl A ) ;
{ и с п о л ь з о в а н и е з н а ч е н и я п е р еме н н о й l на к о т о рую
с сыл а е т с я ука з а т е л ь в к а ч е с т в е п а р аме т р а
п р о ц е дуры ( дл я ука з а н и я п е р еме н н о й и с п ол ь з о в а н
о п е р а т о р ра зыме н о в ыв а н и я " : tpl " ) }
Di spo s e ( tp l ) ;
{ о с в о б о жд е н и е дин амич е с к о й п амяти
выд е л е н н о й
п о д п е р еме н ную tpl }
End .
1
1
1
354
Глава 1 0 . Сложн ые ти п ы дан н ых
Использован и е переменной -указателя для ссылки н а переменную типа
Integer нецелесообразно, так как переменные типа Integer зани м ают
в п ам яти два байта, а указатели - четыре. Таким образом , вместо эко
ном и и памяти п олучается ее ненужный перерасход: если описать пере
менную ти па Integer в разделе описания переменных var , то она будет
зан имать в сегменте дан ных два байта, а структура из переменной указа
теля и переменной типа Int eger в Неар- памяти зани м ает ш есть байт,
причем четыре из них в сегменте данн ых и два - в Неар - п амяти .
Таким образом , использование указателей рекомендуется для объемных
структур данных, как м и н и мум занимающих более ч етырех байтов. Рас
смотрим програм му, в которой переменная-указатель ссылается на запись,
состоящую из строки ти па St ring (зан имает 256 байтов) и веществен
ного числа типа Real (зан имает 6 байт) . Запись будет содержать дан н ы е
о б одн ой обезьян ке в зоопарке - е е и м я и в е с (см . листи н г 1 83 ) .
с":f:�с���н.� ,'�:�:3 . �!�i�e;y�,���;���7f�t����]J���;���-�������i;,;; ,
P rogram Monkeyl ;
Us e s
CRT ;
Туре
TMonkey
Name :
record
String ;
=
We ight :
end ;
Var
Мonkey :
Real ;
"'I'Мonkey; { о п и с а н и е п е реме н н ой - у к а з а т е л я с име н е м
Monkey , ссылающейся на п ереме н ную т и п а TMonkey }
Begin
ClrScr;
New ( Monkey ) ;
Wri t e ( ' Введите
{ выд е л е н и е дин амич е с к о й п амяти п о д
п е р е м е н н ую - ук а з а т е л ь Monkey }
имя обез ьянки : ' ) ;
. Name ) ;
{ в в о д име ни о б е з ь я н ки }
в е с обезьянки : ' ) ;
. We i ght ) ;
{ в вод в е с а о б е з ь янки }
ReadLn ( Monkey"
Wr i t e ( ' Вв едите
ReadLn ( Monkey "
Wr i t eLn ;
Wri t eLn ( ' Параметры обезьянки : ) ;
Wri t eLn ( ' Имя : ' , Monkey " . Name ) ;
Wri teLn ( ' Ве с : ' , Monkey" We i ght ) ;
'
•
D i spose ( Monkey ) ;
{ выв од п олей з а писи , н а к о т орую с сыл а е т с я
п е р еме н н а я - ук а з а т е л ь Monkey }
{ о с в о б о ж д е н и е динами ч е с кой п амяти ,
в ыд е л е н н о й п о д п е р еме н ную Monkey }
End .
355
Turbo Pascal 7 . 0
Поясним порядок и спользования оператора разыменовывания при рабо
те с запися м и . В предыдущем примере используется переменная -указа
тель Monkey для ссылки на запись типа тмоnkеу. Для доступа к пере
менной -зап и с и , на которую ссылается указатель Monkey, испол ьзуется
оператор разыменовывания л , таким образом выражение Monkeyл опре
деляет эту зап ись. Далее для доступа к какому-либо полю зап иси исполь
зуется точка и имя этого п оля: Monkeyл.Name и Monkeyл .We i gh t .
1 о.s.з.
М ассивы указателей
Указатели являются полноправ н ы м и типами данн ых, и из них, как и из
любых других переменных, м ожно создавать масси вы . Измен и м преды
дущи й пример таким образом , чтобы можно б ыло вводить и н формацию
о трех обезьян ках. Для этого создадим масси в указателей на зап и с и типа
тмоnkеу из трех элементов (см . листин г 1 84) .
•..
·.·
· .П ИcтИ�/ 71 B4. :�#f!�{IЬ�:c>·��·�!'i�;f��C.:����)�::ri�������·.�i��y·�a#�t�л���,::. :
Program Monkey2 ;
Uses
CRT ;
Тур е
TMonkey = record
Name :
String ;
We ight :
Real ;
end ;
Va r
Monkeys :
i:
Array
[1
3 ] Of "'TMonkey ;
{ о п и с а н и е ма с с и в а и з т р е х э л е ме н т о в , к а ждый
и з к о т орых я в л я е т с я п е р е ме н н о й - ук а з а т е л ем ,
с сыл ающе й с я н а п е р еме н н ую т и п а TMonkey }
•
•
Intege r ;
Begin
ClrScr;
For
For
i : = 1 То
3
Do New ( Monkey [ i ] ) ;
{ в ыд е л е н и е дин амич е с кой памяти
э л е ме н т ма с с и в а Monkeys }
i : = l То 3 Do { в в о д име ни и в е с а для
ма с с и в а Monkeys }
begin
Wri t e ( ' Введите имя: обезьянки : ' ) ;
ReadLn ( Monkey [ i ] "' . Name ) ;
Wri te ( 1 Введите
вес
обезья:юси : 1 ) ;
ReadLn ( Monkey [ i ] "' . We i ght ) ;
356
кажд о г о
под
к а ждый
э л е ме н т а
Глава 1 0 . Сложн ы е ти пы данных
end;
Wri t eLn ;
For
i : = l То 3
Do
hegin
Wri t eLn ( ' Пapaмeтpы
Wri t eLn ( ' Имя : ' ,
Wri t eLn ( ' Be c : • ,
{ вывод
end;
For
i : =l
то
3
обезьянки : ' ) ;
Monkey [ i ] " . Name ) ;
Monkey [ i ] " . We i ght ) ;
ин формации о б о в с е х
обезь янках }
Do Di spose ( Monkey [ i ] ) ;
{ о с в о б о жд е н и е ди нами ч е с к о й памяти , в ыд е л е н н ой
п о д каждый эл еме н т ма с с и в а Monkeys }
End .
Поясним порядок использован ия оператора разыменовывания при рабо
те с масс и вам и указателей на записи . В при ведеином при мере использу
ется масс и в указателей на записи типа тмоnkеу. Для доступа к переме н
ной-указателю с целью выделения под него памяти и л и ее освобождения
и с п о л ьз у е т с я у к а з а н и е и н д е к с а д а н н о й п е р е м е н н о й в м а с с и в е :
Monkey s [ i ] . Для доступа к переменной -записи , н а которую ссылается
указатель, используется оператор разыменовывания "' , таки м образо м ,
выражение Monkeys [ i ] "' определяет эту запись. Далее для доступа к ка
ко м у - л и б о п о л ю з а п и с и и с п ол ьз у е т с я т о ч к а и и м я э т о г о п ол я :
Monkeys [ i ] "' . Name и Monkeys [ i ] " . We i gh t .
Преи мущества использования массивов указателей очевидны . Они вклю
чают в себя достои нства как массивов, позволяющих обеспечить и ндекс
ный доступ к нескольким переменным, так и достоинства переменных-ука
зателей , п озволяющих перенести объе м н ы е дан н ы е в Н е а р - память и
сократить тем сам ым нагрузку на сегмент данн ых. Более совершенная
структура для хранения информаци и , аналогичная масси вам зап исе й , на
зывается списком и рассмотрена нами ниже в соответствующем разделе.
1 0.6.
И нтервал ьные ти п ы д а н н ы х
И нтервальные ти пы данных (типы-диапазоны) представляют собой подмно
жества возможных значений стандартных ти пов данных :tnteger и Char и
применяются для более удобного представления и нформации в програм
ме. Описание интервального типа данных вы глядит следующим образом :
<Переме н н а я > : <На�аль н о е з н а ч ение и н т е рв а л а >
< Ко н е ч н о е з н а ч е ние и н т ер в а л а > ;
•
•
Использован ие и нтервального типа дан н ых аналогичн о использован ию
любого другого типа дан ных. Рассмотри м пример (см . листи нг 1 8 5 ) , в
котором описы вается перемен м ая интервального типа, знач е н и я м и кото
рой могут быть строч ные латинские символ ы , от с до у
1
1
1
1
•
357
Turbo Pascal 7 . 0
Program cyChars ;
Uses
CRT ;
Va r
Interval :
1С1
•
•
1у1 ;
{ о п и с а н и е и н т е р в а л ь н о г о т и п а - п о дмноже с т в а
т и п а Char ; допустимые з н а ч е ни я п е р е ме н н о й
Int erval н а х о д я т с я в ди а п а з о н е о т симв о л а ' с '
до симв о л а
у }
'
'
Begin
Interval
:=
1
е
1 ;
{ при с в о е ни е
п е р еме н н о й
I n t erva l
значения
'е' }
End .
Если переменной интервального типа данных присваивается значение, не
соответствующее диапазону данного типа, то программа прерывается и вы
дается ошибка Error 2 0 1 : Range check error - Ошибка пр о в ерки ди
апа з она в о зможных значений. Данное свойство интервального типа ис
пользуется для ограничения возможных значен ий переменной , так как в
некоторых случаях удобнее прекратить программу с ошибкой, чем продол
жать ее выполнение с некорректным значением некоторой переменной .
В качестве примера можно привести програм му, осуществляющую расчет
каких-либо параметров на основе номера дня недели: если номер превы
шает число 7, то расчет п роизойдет неверно и пользователь будет введен в
заблуждение. Если же огранич ить множество возможных значений пере
менной , в которую пользователь осуществляет ввод и нтервальным типом
1 . . 7 , то будет выведено сообщение об ошибке и пользователь сможет, вы
полнив программу еще раз, ввести корректный день недели .
Вторы м , более и нтересн ы м , вариантом применения и нтервальных ти пов
является их использован ие в условных операторах м н ожественного вы
бора Case в качестве значени й , с которыми сравнивается значение ана
лизируемой переме н н о й . Напишем программу ( см . листин г 1 86) , кото
рая вы водит строку « в в е д е н а бук в а » для всех латин с ких с и м воло в ,
набираемых пользователем , и « в в е д е н о ч и с л о » для всех цифр. Если
пользователем введена не латинская буква и не цифра, то будем выда
вать сообщение « н е и з в е с т ный симв ол».
�-;!�И:��-��Iis��,::-�������ia�{�;:��i�����fi�ii('��H���A����i� ��:ь6�t>��9B;:�q���
Program IntCa s e ;
Uses
CRT ;
Va r
Ch :
358
Char ;
Глава 1 0 . Сложн ые ти п ы данных
Begin
C l rS c r ;
Wri t eLn ( ' Haжмитe
Ch
:=
11:лавишу ! ' ) ;
{ определение
ReadКey ;
{ анализ
case Ch Of
нажа т ой
н а ж а т ой
Wri t eLn ( ' Нажата бу11:в а ' ) ;
{ ср а в н е ни е з н а ч е н и я
з н а ч е ний от
а 1 до
п е р е ме н н о й
z1 }
1
'0'
.
else
•
19' :
к л а в иши }
к л а в иши }
Ch
с множе с т в ом
Ch
с множе с т в ом
1
Wri t eLn ( ' Haжaтa цифра ' ) ;
{ ср а в н е ни е з н а ч е ни я п е р е м е н н о й
з н а ч е ний о т 1 О 1 до 1 g 1 }
Wri t eLn ( ' Неизве стный симв ол ' ) ;
{ е сли з н а ч е ние переме н н о й
в о б а множе с т в а }
Ch
не
попадает
end ;
ReadKey ;
End .
1 о . 7 . П ере ч исл и мые ти п ы д а н н ы х
Перечислимый тип дан ных представляет собой некоторый набор констант,
представляющий собой перечень значений переменной данного типа. Кон
станты задаются именам и , их значения неизвестны и определяются ком
пилятором во время построения программ ы . О писани е переменных пе
речислимых типов и меет следующий вид:
<Пер еме нн а я > :
( <Имя к о н с т а н т ы 1 > ,
•
•
•
<Имя к о н с т а н т ы n> ) ;
Переч и сл и м ы е ти п ы используются для о писания мн ожества з н ачений
какого-либо свойства, например цвета некоторого объекта. Оп исание та
кого свойства может выглядеть так, как это по казан о в листин ге 1 87 .
, ::.�·и с*�:��:)··�:.,,: :;цьЩi���с?����е:,н��·�����Щ•Ь,•�)��Н�\fь·�;:�Н'�l�,����iti!Ш1iQ!
Program Enumerat ion;
Uses
CRT ;
Va r
Color :
( Black ,
Whi t e , Red ) ;
{ о писание перечислимо г о т и п а д а нных
ди а п а з о н ом
з н а ч е ни я к о т о р о г о я в л яют с я три к о н с т а н ты
B l a c k , Wh i t e , Red ; з н а ч е н и я э тих к о н с т а н т
н е и з в е стны , но и х можно исполь з о в а т ь по именам}
1
-
Begin
Color
:=
Whit e ;
{ присвоение
переменной Color
з н а ч е ния Whi t e }
359
Turbo Pascal
7.0
I f Color
= Wh i t e Then
Wri t eLn ( 1 Все белое ! 1 ) ;
{ ср а в н е ни е з н а ч е н и я п е р еме н н ой
с о з н а ч е ни е м Whi t e }
Color
End .
Перечислимые типы дан ных используются в основном для повышения
ч итабельности программы и привлечения вн имания к возможным значе
ниям какого-либо парам етра программы. Н апример, имеется процедура,
которая рисует рамку вокруг объекта и может сделать ее толсто й или
тонко й , а также выпуклой или вдавлен н о й . Все возможн ые состояния
рамки можно было бы п ередавать процедуре целочисле н н ы м значением ,
напри мер, так:
1 . . . . . . . . . Тонкая вы пуклая
2 . . . . . . . . . Толстая в ыпуклая
3 . . . . . . . . . Тонкая вдавленная
4 . . . . . . . . . Толстая вдавленная
Однако с таким множеством значений не очень удобно работать. В место
это го м ож н о о п и с а т ь д а н н ы й п ар а м е т р к а к п е р е ч и сл и м ы й т и п
(Thi nRa i s ed, Thi c kRa i s ed, Thi nLowered, Thi c kL owered) . Если пара
метр оп исан таким образом , то м ножество его знач е н и й легко запо м ина
ется , в програм ме намного проще искать ошибки, она становится более
понятной даже тому, кто ее написал , не говоря уже о тех, кто п ытается
разобраться в алгоритме .
Поясни м , как устроен перечислимый т и п данных внутри Turbo Pascal . При
описан ии такого типа константам , заданным в качестве множества значе
ний, присваиваются последовательные значения от О и выше. Соответствен
но, внутренняя структура переменной перечислимого типа экви валентна
внутренней структуре целочислен ной переменной. Но вместо числового
значения мы имеем возможность использования некоторого текстового
представления , что знач ительно упрощает процесс программирования.
1 0 . s. М ножеств а
1 0 . 8. 1 .
О п и с а н и е и использова н и е м н ожеств
Типы данных множества аналогичны перечислимым и и нтервальны м ти
пам данных, однако переменные множественных типов могут иметь не
сколько значений из описанного перечисления , причем каждое значение
не может присутствовать в м ножестве дважды в одно и то же время . Опи
сание переменной множественного типа выглядит следующим образом:
<Пе р еме н н а я > : Set Of <Перечи слимый ти п > ;
360
Глава 1 0 . Сложн ые ти п ы дан н ых
Аналогич н о можно описать м ножество на основе и нтервального типа:
<Пе р еме н н а я > : S e t Of <Ин т е р в а л ь ный тип > ;
Для присвоения значения переменной множествен н о го ти па испол ьзует
ся оператор - конструктор м ножества [ ] :
<Пе р еме н н а я > : = [ < Зн а ч е ни е 1 > ,
<Значение n>] ;
В качестве Значений может быть использовано любое значен ие из мно
жества, на основе которого создан дан н ы й тип .
•
•
•
Рассмотрим пример описания и использован ия перемен н о й - м н ожества,
основанной на персч ислимом типе дан ных (см . листинг 1 8 8) .
... . J1истйнГ. · 1аs·:: ,иъh <>�ь·з с;:�а-�и�:�:�'н.д��сi,·t;];.;'.�::.J: _•:
Program Mul t i tude l ;
Uses
CRT ;
Var
Colors : Set Of ( Black, Whi t e , Red ) ;
{ описание переменной множе с т в е нного типа данных
з н а ч е нием к о торой в люб ой моме н т в р емени
выполнения программы может быт ь любо е сочетание
к о н с т а н т B l a c k 1 Whi t e и Red }
Begin
Colors : = [ Black , Red] ;
{ лри с в о е н и е л ереме н н о й C o l o r s мн о ж е с т в а
с о с т о яще г о и з двух элеме н т о в
B l a c k и Red }
Colors : = [ ] ;
{ при с в о ение лереме нной Colors пус т о г о множе с т в а }
Colors : = [White ] ; { при с в о е ни е п е р е ме н н о й C o l o r s мн о ж е с т в а
с о с т о яще г о и з о д н о г о элеме н т а - Whi t e }
1
1
-
1
End .
При работе с м н ожествами используются следующие поняти я :
Объединением двух м ножеств называется м ножество, содержащее эле
менты как одного , так и второго множеств.
Пересечением двух м ножеств назы вается м н ожество, содержащее эле
менты , включенные в оба м ножества.
Разностью двух м ножеств называется м ножество , содержащее элемен
ты п ервого м ножества (уменьшаемого) , н е содержащи еся во втором
множестве .
Пустым м ножеством называется множество , не содержащее элементов.
На рис. 1 30 наглядно представлены объединени е , пересечение и разность
двух м ножеств (закрашены серым цвето м ) . В п равой части рисунка по
казана, как при операциях объединен и я , пересечения и разности могут
36 1
Turbo Pascal
7.0
Объединение________.
�, _9D
___
�
Разность ______.,.- .
Рис.
1 30. Объединение, пересечение
и разность двух множеств
получаться пустые множества (сто
ит знак вопроса) . Замети м , что при
объединении двух непустых мно
жеств не может получ иться пустое
множество.
Примечание.
Об ратите в н и м а н и е , что в кач естве
разности расс м атри ваетсR случай ,
ко гда и з м ножеств а 1 в ы ч итаетсR
м ножество 2 . Е сл и б ы б ыло н аобо
рот ( и з м н ожества 2 в ы ч италос ь
м н ожество 1 ) , то карт и н ка, де м о н
ст р и рующая раз ность , в ы гл ядела
б ы п о -другому , а с п рава пустого
м ножества не б ы л о б ы .
Для осуществления операций объединения, пересечения и разности множеств
в Turbo Pascal используются , соответственно, операторы + , * и - . Рассмот
рим примеры использования описанных операций (см . листинг 1 89) .
:(1Ji'1��I�Rre.�· ��:�t9���P.и��·����>;· ·�.�p�����·� и·�·� и-· p��ь()t:,.�··.p.·�y'x:•· � ��>l<�§т�:;;e,· :·
Program Mul t itude 2 ;
Uses
CRT ;
Va r
Colors l , Colors 2 , ColorsЗ : Set Of ( Black , Whit e , Red) ;
{ описание переменной множе с т в е нного типа данных ,
з н а ч е нием к о т орой в любой моме н т в р емени
выполнения программы может быть любо е соче т а ние
к о н с т а н т B l a c k , Whi t e и Red }
Begin
Colorsl : = [ Black , Red] ;
{ пр и с в о е ние п е р е ме н н о й C o l o r s l м н о же с т в а ,
с о с т о яще г о и з двух элеме н т о в - B l a c k и Red }
Colors2 : = [ Red] ; { при с в о е ни е переме н н о й C o l o r s мн о ж е с т в а ,
с о с т о яще г о из о д н о г о элеме н т а - Red }
ColorsЗ : = Colorsl + Colors2 ;
{ пр и с в о е ни е п е р е ме н н о й C o l o r s З з н а ч е ни я ,
пр е д с т а в л яюще г о с о б ой о б ъ е ди н е ни е мн оже с т в
Colorsl и Colors 2 , то е с т ь множе с т в а , состояще го
и з д в ух элеме н т о в - B l a ck и Red ( н е смотря на
т о , что эл еме н т Red присут с т в у е т в о б оих мн о
жествах , в объединении такой элемент толь ко один ) }
ColorsЗ : = Colors l * Colors2 ;
{ при с в о е н и е п е р еме н н о й C o l o r s З з н а ч е ни я ,
пре д с т а в л яюще г о с о б о й п е р е с е ч е ни е множе с т в
Co lorsl и Colors 2 , то е с т ь мн оже с т в а , состояще г о
и з о д н о г о элеме н т а - Red }
362
Глава 1 О. Сложн ые тип ы дан ных
Colo r s З
: =
Colors3
: =
Colors l - Colors2 ;
{ присвоение переменной ColorsЗ значения , представ
л яюще г о собой р а з н о с т ь мн о же с т в C o l o r s l и
C o l o r s 2 , то е с т ь мн оже с т в а , с о с т о яще г о
и з о д н о г о элеме н т а - B l a ck }
Colors 2 - Colors l ;
{ при с в о е н и е переме н н о й C o l o r s З з н а ч е ни я ,
представляюще го собой разность множе ств Colors2
и C o l o r s l , т о есть пус т о г о мн о же с т в а }
End .
1 0.8.2.
Операции над мн ожества м и
Для определения наличия элемента в переменной множествен ного типа
испол ьзуется оператор in, возвращающий истинное значение, есл и эле
мент присутствует в м н ожестве , и ложное, если элемент в м ножестве не
присутствует:
< Эл еме н т > in <Пер еме н н а я множе с т в е н н о г о т и п а >
В качестве Элемента используется одна и з констант, на основе которых
описан множественный тип данных. Напишем процедуру (см. листинг 1 90) ,
определяющую, есть ли в заданном ей в качестве параметра множестве эле
мент Pascal . Множество может содержать элементы Pascal, С , Java и Bas ic.
p:{ti·��]��w::�:�,9жi��!i�!�������i;'���������-:��������,;:�;������������c��1
Program Mul t i tude 4 ;
Uses
CRT ;
Туре
TProgrLang
Procedure
=
Set
{ н а чало р а здела о п и с а н и я т и п о в }
Of ( Pascal , С , Java , Ba s ic ) ;
{ о п и с а н и е мн оже с т в е н н о г о т и п а д а н ных ( н е
п е р е ме нной ! ) , множе с т в о значе ний к о т о р о г о может
в ключ а т ь элеме н ты Pas c a l , С, Java и Ba s i c
Che ckPa scal ( PrLangs : TP rogrLang ) ;
{ з а г о л о в о к проце дуры с име н ем CheckPa s c a l
одним п а р аме тром PrLangs мн оже с т в е н н о г о
т и п а TProgrLang }
и
begin
If
Pascal
in
PrLangs
Then Wri t eLn ( • nаскаль
есть ! ! ! • )
E l s e Wri t eLn ( ' А где nаскаль ? ! ! • ) ;
{ пр о в е р к а наличия элеме н т а Pa s c a l в множе с т в е ,
з ад а н ном в к а ч е с т в е п а р аме тр а , и выв о д с т р о ки
в з а в и симо сти от наличия элеме н т а }
end;
363
Turbo Pascal
7.0
Begin
ClrSc r ;
CheckP a s c a l ( [ С ,
Basic ] ) ;
{ вы з о в проце дуры CheckPas c a l с п а р аме т р ом
мн оже с т в ом из двух элеме н т о в
С и Bas i c , на
экран будет выв едена строка 1 А г д е Па скаль ? ! ! 1 }
-
CheckP a s c a l ( [ С ,
Pascal ] ) ;
{ вы з о в проце дуры CheckP a s c a l с п а р аме тр ом
множе с т в ом из двух элеме н т о в
С и Pa s ca l , н а
э кр а н буд е т выв е д е н а с т р о к а 1 П а с к а л ь е с т ь ! ! ! 1 }
-
End .
Специальных операторов или процедур для добавления эле ментов в мно
жество и удаления их из м н ожества не существует. Дан н ы е операци и
вы полняются с помощью объединения и разности м н ожеств.
Для того чтобы добавить элемент в множество, следует объедин ить ис
ходное м н ожество с множеством , содержащим дан н ы й элемент (только
дан н ы й элемент) . Если добавляемый элемент уже содержится в и сходном
множестве, то никаких изменений с ним не произойдет - каждый эле
мент может включ аться в множество только один раз . Если добавляемый
элемент не присутствует в исходном множестве, то он будет туда добав
лен в результате выполнения операции объеди нения.
Для того чтобы удалить элемент из м ножества, следует вычесть из ис
ходного м ножества м н ожество , содержащее данн ы й элемент (только дан
н ы й элемент) . Если удаляемый элемент содержался в и сходном множе
стве , то он будет из него удален . Если же удаляемый элемент в м ножестве
не содержался , то с исходн ым множеством не будет произведено н и ка
ких измене н и й .
Рассмотрим при меры добавления и удаления элементов из м ножества (см.
листи н г 1 9 1 ) .
Program Мul t itude S ;
Uses
CRT ;
Туре
TProgrLang
=
Set
{ н а ч а л о р а з д ела о п и с а н и я тип о в }
Of ( Pascal , с , Java , Basi c ) ;
{ о п и с а н и е множе с т в е н н о г о т и п а д а н ных ( н е
переме нной ! ) , множе с т в о значе ний к о т о р о г о мож е т
в ключ а т ь элеме н ты Pa s c a l , С , Java и Ba s i c }
Va r
Langs :
364
TprogrLang ;
{ о п и с а н и е п е р еме н н ой
т и п а T ProgrLang }
Langs
множе с т в е н н о г о
Глава 1 0 . Сложн ые типы данных
Begin
C l rS c r ;
{ пр и с в о е ни е п е р е ме н н ой
п у с т о г о мн оже с т в а }
Langs
:=
[] ;
Langs
:=
Langs
Langs
:=
Langs +
Langs
:=
Langs
-
Langs
:=
Langs
+
Langs
:=
Langs -
+
Langs
значения
[ Pascal ] ;
{ при с в о е ни е переме н н о й Langs р е з ул ь т а т а
е г о объеди н е н и я с множе с т в ом , с о с т о ящим и з
о д н о г о элеме н т а P a s c a l ; т а ким о бр а з ом ,
в мн оже с т в о Langs д о б а вл я е т с я э л еме н т P a s c a l }
[С] ;
{ до б а в л е ние в мн оже с т в о Langs э л е ме н т а С }
[ Ba s i c ] ;
{ при с в о е н и е пер еме н н о й Langs р а з н о с т и
множе ства Langs с множеством, состоящим из одного
э л еме н т а Ba s i c ; множе с т в о Langs н е и зме н я е т с я ,
т а к к а к о н о н е содержало элеме н т а B a s i c }
[ Pascal ] ;
{ до б а в л е ни е в мн оже с т в о Langs э л еме н т а P a s c a l ;
множе с т в о н е и зменяе т с я , т а к к а к уже с одержит
э л е ме н т P a s c a l }
[С] ;
{ уд а л е н и е
и з множе с т в а
Langs
э л е ме н т а
С}
End .
М ножества я вляются удобны м инструментом для передачи в процедуры
и функции нескольких параметров, некоторые из которых могут быть нео
бязательны. Еди нственное ограничение в использовани и множеств состоит
в том , что коли чество элементов не может превышать 2 5 5 . Однако дан
ное о граничение н а практике обычно не достигается .
К онтрол ьные вопросы и ответы
Каки м о б р а з о м может п роизводиться о бъеди н е н и е и н ф о р м а ц и и
п росте й w их т и п о в в более круп н ы е структур ы?
Для целостн ого представления и н формаци и дан н ы е просте й ш их типов мо
гут о бъеди н яться в более круп н ы е структуры . Такое обьеди н е н и е м ожет
п роисходить по двум н аправле н ия м : обьеди н е н и е одн о родн ых п е ре м е н
н ых для получения массивов и обьединение разнородн ых переме н н ых для
получения з а п исей .
Что такое м а с с и в и в каком виде осуществляется его о п и са н и е ?
Массивом н аз ы вают п о и менован ную область памяти , содержащую пере
менные одного типа, доступ к кото р ы м осуществляется п о общему и м е н и
365
Tu rbo Pascal 7 . 0
масс и ва и и нде ксу соответствую щ е й п е р е м е н н о й . О п и са н и е м ас с и в о в
включ ает в с е б я указ а н и е , из переме н н ых какого типа долже н состоять
масс и в , сколько в нем должно б ыть эл ементов и какие индексы должн ы
быть использова н ы для доступа к е г о эл ементам . До пускается создание
м н о гомерных (двухмерных, трехмерн ых и так далее) масс и в о в , когда эл е
ме нто м массива м ожет я вляться друго й масс и в .
Назо вите н а и более распространенные операции с м а сс и в а м и .
Одн и м и и з самых расп ространен н ых операци й с масси вами являютс я :
• поиск элеме нта в массиве по критерию ( о п редел е н и е н о м е р а эл еме нта
массива или его значен и я , отвечающего заданному крите р и ю , например
максимал ь н ы й или м и н и м альн ы й элемент) ;
• уп о рядоч и в а н и е массивов ( изменение последовател ьн ости его эл е м е н
тов таким об разом , чтобы последовател ьн ость удовлетворяла некото рому
прав илу) .
Дайте краткое описание строковых переменных и т и п а Stri n g .
Т и п Stri ng по своей внутренней структуре я вляется м ассиво м , поэтому со
строко в ы м и перемен н ы м и допусти м ы операци и , а н алоги ч н ы е операци я м
с массивам и . К осн о в н ы м операциям со строка м и , п р и м е н я е м ы м в боль
ш и н стве п рограм м , отн осятся :
• операции с размером строк и ,
• кон катен ация ( сложе н и е строк) ,
• срав н е н и е стр о к ,
• выдел е н и е ч и словых значе н и й из стро к ;
• зан есе н и е сим вол ьного п редставле н и я ч исл овых з н аче н и й в строки ;
• си нтаксический р азбор строк - выдел е н и е отдел ьных последовател ь
ностей с и м волов с цел ью их анализа.
Что т а кое з а п и сь?
Записью н азы вают поименован ную область памяти , соде ржащую перемен
ные разного ти па, доступ к которым осуществляется по общему имени эк
земпляра записи и имени соответствующей переменной - полю записи .
Что такое указатели и какими о н и быв ают?
Для более гибкого управления памятью , выделяемой п рограмме в п роцессе
ее в ы п ол н е н и я , п редн азначе н ы перемен н ы е -указател и . Эти п е ремен н ы е
делятся н а д в е груп п ы - ти п изирован ные и н ети пизи рован н ы е . Указате
ли позвол я ют перен ести часть и н форм аци и из сегме нта дан н ых , в кото
ром располагаются пере м е н н ы е , описанные в раздел е описа н и я переме н
н ых Va r , в динамическую Неар-п амять, имеющую больш и й объе м .
Дайте о п и с а н и е перечисл и м ых типов д а н н ы х .
Перечисл и м ы й ти п дан н ых представляет собой некото р ы й набор констант,
представл я ю щ и й собой перечень значен ий переме н н о й дан н о го ти п а . Кон
станты задаются именам и , их значе н и я неизвестн ы и о п р едел я ются к о м
п илятором во время построе ния програ м м ы . П е реч и сл и м ы е т и п ы исполь
зуются для описания м н ожества значе н и й какого -либо свойства, например
м н ожества воз можных цвето в некоторого объекта .
366
Глава 1 0 . Сложн ые типы данных
Что т а кое и нтервальные типы?
Дл я огран и ч е н и я возм ожн ых значе н и й используе м ых в программе пере
м е н н ы х п ростых типов используются и нтервальные типы, являющиеся
подмн ожества м и п ростых типов. Их использован и е позволяет б олее жес
тко отслежи вать корректн ость значен и й переме н н ых , когда это н еобход и
м о . Аналогом и нтервальных ти пов дан н ых я вляются перечисл и мые ти п ы ,
еще более уси л и вающие ко нтрол ь з а знач е н и я м и в перем е н н ых дан н о го
ти па и п о в ы ш ающие ч итабельнесть п рограм м ы .
Расскажите о множестве.
Еще оди н сложн ы й тип дан н ых Turbo Pascal - м н ожество , позвол я ю щее
хран ить в перемен н ых и кон стантах несколько з н ач е н и й одновремен н о ,
п р и ч е м возможные значения определяются во время разработки програм
мы на основе перечисл и мого или и нтервал ьного типа. Для м н ожеств п р е
дусмотрен ы о перации объеди н е н и я , пе ресеч ения и в ы ч итан и я .
Ка ко й раздел програ м м ы п редназначен для о п и с а н и я ти п о в?
Для орган изаци и работы с типами дан н ых в программе предн азначен раз
дел описания типов Тур е , в котором производится о п исан и е т и п о в , ис
пользуемых в п р о гра м м е . На основе л юбого о п и са н н ого ти п а дан н ых, в
том ч и сле и сложн ого , м ожно о п исать масс и в с цел ью хран е н и я последо
вател ьностей сложных дан н ых, например массив записей или массив м н о
жеств.
367
Turbo P a s c a l 7 . 0
_1
�..г л а в а
И с п о л ь зо в ан и е ф а йл о в
До сих пор все методы хранения и нформации , рассматриваемые нам и ,
касались только оперативной п амяти , а методы ввода и вывода инфор
мации - ввода значений переменных с клавиатуры и вы вода текста и гра
фических объектов на экран . Конеч н о , без таких операций с и нформа
ц и е й не м ожет о б о й т и с ь п ракти ч е с к и ни од н а п р о грам м а , од н а ко
и нформаци я , хран и м ая в оперативной памяти , имеет смысл только во
время работы программ ы , что подходит не для всех задач , решаемых
программированием . Еще одн им недостатком хран ения и нформации в
ОЗУ я вляются затруднения в ее передаче от одной Э В М к другой .
Можно н азвать еще м ножество задач , не решаемых в п ределах оператив
ной памяти , например отсутствие возможности архиваци и дан ных, исполь
зуем ых програм мой. Решением больш инства таких проблем я вляется ис
пользование файлов - специальных структур, расположенных на дисковых
накоп ителях (дискетах или жестких дисках) , либо других постоянных но
сителях информации (например, устройствах Flаsh- п амяти ) .
1 1 .1.
С тр укту р а ди сковы х н ако п ител е й
Простейшим дисковым накопителем информации является дискета (Floppy
di sk - гибкий диск) - поверхность в виде кольца из гибкого материала,
имеющая магнитное напыление (см. рис. 1 3 1 ) . Кольцо
заключено в пластмассовый корпус для предохранения
от загрязнений и других воздействий окружающей сре
ды, которые могут нанести вред магнитному покрытию.
Рис.
131.
Дискета
368
М агнитное покрытие обладает свойством сохранения
единицы и нформации на некотором участке (напри
мер, намагниченный участок - 1 , ненамагниченный
участок - 0 ) . Для изменения намагниченности уча
стка п о крытия и с пользуется с п е ц и ал ь н о е устрой -
Глава 1 1 . И спол ьзова н и е файлов
ство - дисковод, которое обладает магн ит
ной головкой . Магн итная головка переме
щается по поверхности дискеты, намагни
ч и в а я и р аз м а г н и ч и в а я отдел ь н ы е ее
участки .
Чтобы читающее устройство могло ориен
тироваться в пределах кольца, например оп
ределять начало области зап иси информа
ц и и , п е р ед и с п ол ь з о в а н и е м д и с к ета
проходит процедуру форматирования - на
несения на магнитную поверхность специ
альных меток, разби вающих ее на дорожки
и сектора (см . рис. 1 3 2). Дорожки нумеру
ются от нулевой (ближней к центру коль
ца) по возрастан ию. Сектора нумеруются
также от нулевого (за нулевой сектор при
н и м ается какой-либо из секторов и при
форматировании на нем ставится специаль
ная метка) .
Рис .
1 32. Дискета
с разметкой форма тированием
Количество дорожек и секторов определя
ется форматирующей программой, для дис
кет объемом 1 .44 мегабайт стандартная раз
метка включает в себя 1 8 секторов и 80
Рис. 1 33 . Возможное
дорожек на одной стороне диска и столько
же на другой . Стандартный размер части ра сположение ча стей одного
массива информации
одного сектора, приходящейся на одну до
рожку,
5 1 2 байт, поэтому большие объем ы информации занимают на
дискетах несколько таких частей (см . рис. 1 33 ) . Такие совокуп ности обла
стей диска называют файлами (англ. File - п апка) .
-
Для хранения информации о том, какие области диска каким файлам при
надлежат, используется так назы ваемая таблица FAT (FAT - File Allpcation
ТаЬlе - таблица размещения файлов) . Это необходимо, чтобы различные
части файлов не терялись и не пересекались с другим и файлами . Таким
образом, чтобы получить информацию, записанную на дискету, необходи
мо просмотреть таблицу FAT, найти в ней нужн ый файл (файлы отл ича
ются друг от друга именами), а затем прочитать все ч асти этого файла с
дискеты, устанавливая головку дисковода в положение соответствующей
части . Этот процесс напоминает вытаскивание листков бумаги , соответ
ствующих одному предмету, из большой пачки.
Жесткие диски (англ . Hard drive - жесткий диск) по своей структуре ана
логичн ы дискетам , однако содержат множество таких кольцевидных по
верхносте й , причем количество дорожек, секторов и самих дисков мо
жет существенн о отличаться для разных дисков (см. рис. 1 34) . Каждая
369
Turbo Pascal 7 . 0
поверхность из состава жесткого диска и м еет
свою считывающую магнитную головку. Таким
образом , для каждой области , принадлежащей
какому-либо файлу на жестком диске , сопостав
ляется еще один параметр - номер головки .
Естественно, что работа с такой структуро й дан
н ых очень сложна. Поэтому операционн ая сис
тема полностью берет на себя управление разм е щ е н и е м ф а йл о в н а д и с ке , п р едл а га я
Рис. 1 34 . структура
програм мам и нтерфейс доступ а к файлу как к
жесткого диска
единому массиву байтов. Такая структура файла
более удобна для работы, однако так же несовершенна, так как не под
разумевает под собой какую-либо логическую структуру. Поэтому языки
программирован ия высокого уровня имеют более развитые средства для
доступа к файлам , позволяющие, в частности , рассматривать файлы не
как массивы байтов, а как массивы элементов некоторого типа данных,
и меющегося в языке программирован ия , или даже как массивы записе й .
1 1 . 2 . И менов ан ие файл ов
1 1 .2. 1 .
Основы именова н и я файлов
Для того чтобы структурировать список файлов с целью повышения удоб
ства работы с ним, файлы хранятся на дисковых носителях в иерархичес
ком виде , что достигается использованием специального вида файлов каталогов. Каталоги могут содержать другие файлы, а также и другие ката
логи . Еще оди н прием структурирования беспорядочной совокупности фай
лов - создание нескольких <<логических>> дисков в пределах одного физичес
кого диска.
Во всех операционных системах принято именование файлов (формирование
их имен) на основе последовательности каталогов, определяющей расположе
ние файла, и имени самого файла. В операционных системах, поддерживаю
щих разбиение жесткого диска на логические, в полное имя файла включается
также наименование логического диска, на котором он находится.
Мы рассмотрим правила именования файлов в операционной системе M S
D O S . Такие ж е п равила, но содержащие намного меньше ограничен и й ,
при няты для именования файлов в ОС Windows .
Первая ч асть и м ен и файла представляет собой назван и е логического
диска, состоящее из одной буквы (для дисковода приняты буквы А и в,
для всех остальных дисков - с, D, Е и так далее по порядку) . Для отде
ления имени логического диска от остальной части и м е н и файла исполь
зуется двоеточие и символ <<обратный слэш>> (Back Sl ash) :
<Имя логич е с ко г о ди с к а > : \
370
Глава 1 1 . Испол ьзован и е файлов
Например:
С: \
А: \
Х: \
Файл н а х одит с я н а диске
Ф а йл н а ходит с я н а ди с к е
Файл н а х о ди т с я н а диске
С
А
( н а ди с к е т е )
Х
Вторая часть и мени файла п редставляет собой последовательность ката
логов, нач и н ая от самого первого, н аходящегося на логическом диске и
не принадлежаще го какому-либо другому каталогу, и до того каталога,
который содержит файл . Каталоги в последовательности разделя ются
символами <<обратны й слэш>> . Данная последовательность называется путь
к файлу:
<Каталог 1 > \
•
•
•
\ < К а т а л о г n>\
Третья, последняя , часть полного имени файла содержит собственно имя
файла, состоящее из восьми или менее латинских символов или цифр ( и мя
файла должно содержать хотя бы один символ или цифру) . Также непос
редственное имя файла может содержать так называемое расширение, со
стоящее из трех латинских сим волов или цифр. Однако рас ширение мо
жет и отсутствовать.
В случае если расширение присутствует в имени файла, оно указывается
через точку:
<Имя ф а йл а > . < Р а сшир е н и е >
П р и м еч а н и е .
О гран и ч е н и е дл и н ы и м е н и фай ла восе м ь ю с и м волам и н аклады вается оп ера
ци о н н ой с и стемо й DOS. Со в р е м е н н ы е О С ( W i n d ows , Linux и т .д ) из бавлены
от этого и п оз вол я ют и с п ользовать дл и н н ы е имена ф а йл о в .
Таким образо м , полное имя файла имеет следующий вид:
<Имя логического диска> : \<Каталог 1>\
ние>
• • •
\<Каталог n>\<Имя файла> . <Расшире
Приведем несколько при меров.
Файл н аход ится н а д и ск� с в катал оге
MYPROGS , имеет имя ех1 и расширение pa s .
A:\SAVES\PROGS\snow. exe Файл находится н а диске А ( н а дискете) в
каталоге PROGS , которы й , в свою очередь,
находится в каталоге SAVE S . Имя файла snow, расширение - ехе .
x:\s tart .ba t
Файл н аходится на д и ске х , и м еет и м я
s tart и расширение b a t .
с : \ MYPROGS\ex l .pas
Когда файл не принадлежит никакому каталогу, а находится п р я м о н а
логическом диске, говорят, что он находится в корневом каталоге данного
логического диска. Например, про файл с полным именем с : \ s tart .bat
можно сказать, что он находится в корневом каталоге диска х.
37 1
Turbo Pascal
7.0
1 1 .2.2.
И сп ользова н и е расш и рен и й
Остановимся подробнее н а расширении файла. Как было указано выше, оно
не является обязательной частью имен и , однако несет на себе достаточно
важную функцию идентификаци и типа файла для пользователя или для
каких-либо программ . Например, в файлах с расширением txt принято хра
нить текстовые документы , а файлы с расширением ехе содержат в себе
программы, выполняемые операционной системой .
В файлах с расширением pas хранятся исходные тексты программ на Turbo
Pascal , а в файлах с расширением bak интегрированная среда Turbo Pascal
сохраняет резервные копии редактируемых программ . Существует еще мно
жество расширений файлов, которые могут указать пользователю на тип
информации, хранимой в файле. И хотя имя файла назначается произволь
ным образом и обычному файлу с текстом можно присвоить любое расши
рение, например ехе , все же рекомендуется следовать установленным со
глашениям о назначении файлам расширений.
1 1 .2.з.
И с п ол ьзова н и е неп ол н ых имен файлов
Имя файла, сформированное по описанным в ы ш е правилам, назы вается
полным именем файла. Однако существуют другие фор м ы , основанные
на строении имени файла относительно другого файла ил и каталога. При
этом обычно за точку отсчета расположения файла выбирается так назы
каталог, в котором н аходится выполняемая
вае м ы й текущий каталог
программа, и и м я файла строятся , начиная от него .
-
Такой подход удобен для обращения к файлам , принадлежащим кон к
ретной программ е . Таким образом , чтобы обратиться, например, к фай
лу настроек, н еобходимому для корректной работы программ ы , если он
находится в том же каталоге , что и сама програм ма, достаточно указать
только его имя и расширение. Например:
С:
PRO G S
exl . ex e
exl . i n i
ТР7 0
BIN
BGI
При таком расположении файлов программа exl ехе может обращаться к
файлу exl . ini не по его полному имени С : \ PROGS \ exl . ini , а по корот
кому ех1 ini .
.
.
Если теперь программу и инициализационный файл скопировать в другой
каталог, не изменяя их взаимного расположения (то есть чтобы после ко
пирования они остались в одном каталоге) , то работоспособность програм372
Глава 1 1 . И спол ьзование файлов
мы не нарушится и программа все так же сможет обращаться к своему ини
циализационному файлу по короткому относительному имени exl . ini:
D:
T PEXMPL
exl . exe
exl . i n i
Точно такой же подход используется , если файл , к которому обращается
програм ма, находится в каталоге , принадлежащем тому каталогу, в кото
ром находится сама программа. Например:
D:
-
T PEXMPL
exl . exe
INIT
P I CTURES
BIN
P I CTURES
1
exl . ini
1
l wo rds . exe
l p i c t l . pcx
Для обращения к файлу p i c t l . р сх программа words . exe может исполь
зовать полное имя файла D : \ GWORDS \ P I CTURE S \ p i c t l . pcx либо отно
сительное и м я . . \ P I CTURE S \ p i c t l . pcx, что намного удобнее.
1 1 з П он я т ие файла в
.
.
Tu rbo Pascal
Итак, файл - это поименованная о бласть диска , доступ к которой осуществ
ляется по имени. Можно также дать определение, более близкое к програм
мированию: файл - это группа элементов на диске , названная одним именем.
373
Turbo Pascal 7 . 0
Файлы аналогич ны массивам , только и нформация хранится не в опера
тивной памяти , а на постоянном носителе. Однако имеется существенное
отличие файлов от масси вов, связанное с прирадой этих структур данных.
Оп исан ие м ассива задается в программе, причем обычно уже на этапе
написания программ ы . Соответственно, программе заранее известны тип ы
элементов м ассива и их количество. С файлами дело обстоит совершен
но по-другому - для программы файл, расположе н н ы й н а како м -либо
носителе, я вля ется всего лишь набором байтов, а его логическая струк
тура определяется подпрограммой чтения файла. В качестве иллюстра
ции такого подхода можно привести диалог выбора формата файла в
програм ме MS Word , когда она не может самостоятельно его определить.
После выбора пол ьзователем формата и нформация будет прочитана из
файла методом , соответствующим выбран ному формату. Соответственн о ,
оди н и тот ж е файл можно проч итать по-разному.
Информация , находящаяся в файле, может быть использована тогда, коtда
програм ма п олуч ает к нему доступ . Соответственно, на этапе разработки
програм мы размер файла неизвестен , вследстви е чего для файлов в от
личие от масси вов, реализован не индексный метод доступа, а последовательн ы й , то есть получить доступ к како
му-либо элементу можн о , только считав все
предыдущие.
�
DDDDDODDDDDD
.А
'-
Указ атель текущего злемента
Рис.
1 35. Логическая
стр уктура файла
В общем виде файл можно представить пос
ледовательностью элементов, имеющей нача
ло и конец (см. рис. 1 35 ) . Для определения
элемента, который может быть прочитан в
данный момент или в который может быть
записана информация , существует так назы
ваемый указатель текущего элемента.
1 1 . 4. Кл ассифи ка ция файл о в
Файлы разделяются на группы (см . рис. 1 3 6) в соответстви и с типом эле
ментов, которые они содержат. Классификация файлов необходи ма для
правильного выбора средств работы с ним и .
Файл ы
Те ксто вые
�
I Ш !f 0 1Ы [Q] D [f] �
..
.
l
Двоич ные
�
Нетиnизи рован н ые
1 [!] [!] [!] [!]
Рис.
374
� [!] [!]
...
1
1 1::1 1::1 1:: 1 · 1
Тип изирован н ые
.
А
1 36. Классификация файлов
.
По логической структуре файлы делятся на текстовые и дво
ичные. Тексто в ы м и файлам и
назы ваются файл ы , и нформа
ция в которых представлена в
виде , попятном пользователю.
Все остальные файлы являются
д в о и ч н ы м и . Т а к о е дел е н и е
очень условно, так как выраже-
Глава 1 1 . Использование файлов
ние <<понятное пользователю>> субъективно. Например, файл, содержащий
исходный текст програм м ы , может быть понятен программисту, знач ит,
данный файл является текстовым .
С другой стороны, человек, незнакомый с программированием , н е может
понять, что представляет собой текст, находящийся в файле, значит, для него
такой файл является двоичным. Точно так же для подавляющего большин
ства пользователей файл, содержащий откомпилированную программу (см. рис.
6) , будет являться двоичным, однако для некоторого количества пользовате
лей такой файл будет достаточно информативен.
Так или и н аче деление файлов на текстовые и дво и ч н ы е все же суще
ствует, и Turbo Pascal содержит различные методы доступа для разных
файлов. Запись информаци и в текстовые файлы аналогич н а выводу ее на
экран - вне зависимости от типов данных выводимых еди н и ц информа
ции она записывается в файл в текстовом виде . Вы вод и нформации в
двоич н ы й файл происходит в формате , принятом для хранения инфор
мации в операти вной п амяти .
Двоичные файлы подразделяются на нетипизированные и типизированные .
Нети пизирован ные файлы представляются в виде совокупн ости байтов,
то есть каждый элемент нети пизированного файла и меет тип Byt e . Ти
пизированн ы е файл ы рассматриваются программой как более сложные
структуры , хотя на самом деле они также я вляются совокупностя м и бай
тов. Элементы типизированн ых файлов могут иметь сложные тип ы дан
ных, в том ч исле они могут я вляться и запися м и .
1 1 . 5 . М ехани з м р аб оты с файл а м и
1 1 .5. 1 .
О п исание файловой перем е н но й
В момент запуска программ ы на диске могут находиться тыся ч и файлов
и программа не имеет возможности получить и н формацию обо всех н их.
Более того , такая информация в программе не нужна. Когда программе
требуется получить доступ к какому-либо файлу, она делает это посред
ством специальной файловой переменной, определяющей имя файла на
диске и его состояние в контексте данной программ ы (возможные со
стоя ния файлов обсуждаются ниже) . Через эту переменную и ведется в
дальнейшем вся работа с файлом в программе.
Оп исан ие файловой переменной зависит от типа используемого файла.
Для текстовых файлов применяются переменные типа техt :
Var
<Имя п ереме н н о й > : Text ;
375
Turbo Pascal 7 . 0
Для двоичных нети пизированн ых файлов применяются файловые пере
менные типа F i l e :
Var
<Имя переме н н ой > : Fi l e ;
Для двоичных типизирован ных файлов применяются переменные типа F i l e
с указанием типа элементов в файле после ключевого слова O f :
Var
<Имя переме н н ой > : File
Of < Т и п
элеме н т о в > ;
Приведем пример о п и сания файловых переменных для файлов разных
типов (см . листин г 1 92) .
�j1Л��t�Hf.' c1.�2·:;:;o��ь.�.���-·���;;c;fi��*:;����-�.��E�i,� 'W!�:'Ф�й�·��'>IJ'����:·�:f.,nc>� ;t
Program F i l e s l ;
Туре
TName = Record
Name : St ring ;
Pat ronymi c : String ;
SurName : S t ring ;
{ о п и с а ни е т и п а д а н ных з а п и с ь и з т р е х п ол е й
end ;
с т р о к о в о г о ти п а }
Var
{ о п и с а н и е файл о в ой п е р е ме н н о й с име н е м T l
Tl : Text ;
д л я р а б о ты с т е к с т о выми файл ами }
{ о п и с а ни е файло в ой п е р еме н н ой с име н е м B l дл я
Bl : File ;
р а б о ты с дв оич ными н е ти п и з ир о в а н ными ф а й л ами }
В2 : F i l e .o f Int eger ;
{ о п и с а н и е файл о в ой п ереме н н о й с име н е м В 2 дл я
р а б о ты с д в о и ч ными типизир о в а н ными ф а й л ами ,
э леме н ты к о т орых имеют тип Int eger }
В З : F i l e Of TName ;
{ о п и с а н и е файл о в ой п е р еме н н о й с име н е м ВЗ дл я
р а б о ты с дв оич ными типизир о в а н ными ф а й л ами ,
э л еме нты к о т орых имеют т и п TName }
Begin
End .
1 1 .5.2.
Сопоставлен и е файловой перем е н н о й
файлу на диске
На дан ном этапе происходит связыван ие файловой переменной с реаль
н ы м файло м , находя щимся н а диске. Связывание осуществляется проце
дурой Assign (от англ . Assign - назнач ить) , и меющей следующий вид:
Аs sign ( <Ф айло в а я переме н н а я > , <Имя файл а > ) ;
376
Глава 1 1 . И спол ьзован и е файлов
В качестве параметра Ф айлов ая переменная может исп ользоваться пе
ременная или константа типа S tring, содержащая п олное или относи
тельное имя файла на диске. Сопоставление файловых п еременных фай
л а м п р о и з в од и тс я н е з ав и с и м о от т и п а ф а й л а . П р и веде м п р и м ер
сопоставления файловой переменной текстовому файлу (см. листин г 1 9 3 ) .
-::i!J�,�r�,� r:: 1 9;i•��·,�:9:!19:?т�-�лв'Ji,� �;��,t;�����,�����;ж�-н �o#')�:a��x, H�,. ,��,Я��';i1'�;
Program F i l e s 2 ;
Va r
{ о п и с а ни е файл о в о й п е р е ме н н о й с име н ем Т
Т : Text ;
для р а б о ты с т е к с т о выми файл ами }
Begin
As s i gn ( T , • game . in i ' ) ;
{ с о п о с т а в л е ни е файл о в ой п е р е ме н н о й Т файлу с
име нем game . ini , находящемуся в т е кущем к а т ало г е }
End .
11 5 3
.
.
.
Открытие файла
Каждый файл , которому сопоставлена файловая пере м е н н ая , в любой
момент времени выпол нения програм мы может н аходиться в одном из
трех состоян и й :
•
Файл закрыт: с н и м нел ьзя выполнять н и каких дей стви й . Дан н ы й
режим устанавл ивается для файла п р и сопоставл е н и и е м у файловой
переменной .
•
Файл открыт для чтения: для файла допусти ма о п ерация п олуч е н ия
эл емента, н а который указы вает указатель текущего элемента.
•
Файл открыт для записи: для файла допустим а операция добавления
ил и изменения текущего элемента, на который указывает указатель
текущего эл емента.
Открытие файла для чте н и я производится п р о цедур о й Re s e t (англ .
Reset - сбросить) с одн и м параметром - файловой переменн о й , опре
деляющей , какой именно файл следует открыть для чте н и я :
Rеsеt ( <Файло в а я п е р ем е н н а я > ) ;
Открытие файла для записи производится процедурой Rewr i t e (англ .
Rewrite - п ерезаписать) с одни м параметром - файловой п еременной,
определяюще й , какой именно файл следует открыть для зап и с и :
Rеwritе ( < Ф айло в а я п е р е ме н н а я > ) ;
377
Turbo Pascal 7 . 0
Процедуры Re set и Rewrite требуют некоторого пояснения . Есл и файл
открывается программой для чтения, то он должен существовать на дис
ке , то есть файловая п еременная должна содержать имя реально суще
ствующего файла. Если данное условие не выполняется , то при попытке
открытия несуществующего файла будет выдана о шибка Error 2 : F i l e
not f ound
Оши б к а 2 : Ф айл н е н айден .
-
Процедура Rewrite не требует наличия файла, которому сопоставлена
файловая перемен ная : если файл с таки м именем не существует, то он
будет автоматически создан. Если файловая переменная ссылается на файл
с недопустимым и менем, например, содержащим пробел ы , то при попытке
открытия его для записи будет выдана та же самая ошибка, что и при
открытии несуществующего файла для чтения. Если файловая перемен
ная ссылается на существующий файл , т о п р и открытии для записи все
его -еодержимое будет удалено.
В Н И МАН И Е !
Самая расп ространен ная о ш и б ка нач и наю щ их п рограм м и стов - это эксп е р и
м е нты с фай лам и , содержа щ и м и тексты исходных п рограм м , в резул ьтате
ч е го сти раются и сходн ые тексты п рог р а м м . Н и ко гда не и спол ьзу йте для от
ладки п рограм м п олезные файл ы . Есл и п рограм м а де й ств ител ь н о должн а
ра б отать с таки м и файлам и , обязател ь но создавайте их рез е р в н ы е ко п и и .
Приведем пример открытия для чтения двоичного типизированного файла
с элементами ти п а Int eger (см . листинг 1 94) .
:;'�и.c��H<J.�4.�· ·C?:т.�R�•i·��,���.�·.n,;#.AWi.�:'�r���(�· �•::·��:":�:·····: ·::'·:;.'· · ·:.;;:�··.::·:�< .
Program F i l e s З ;
Va r
Т:
F i l e Of
Intege r ;
{ о п и с а н и е файл о в ой переме н н о й с име н е м Т дл я
р а б о ты с двоич ными типизир о в а н ными ф а йл ами
с эл еме н т ами типа Int eger }
Begin
As s i gn ( T ,
• game . bin • ) ;
{ с о п о с т а в л е ни е файл о в ой п е р еме н н о й Т файлу с
именем game . bin, находящемуел в те кущем каталоге }
Re s e t ( T ) ;
{ о т крыт и е файла , к о т ор ому с о п о с т а в л е н а
п ереме н н а я Т ( garne . bin ) дл я ч т е н и я }
End .
1 1 .5.4.
Чтение или запись файла
Чтение информации из файла и л и зап ись информации в файл произво
дится после его открытия соответствующим образом (для чтения или для
записи) . Чтение и запись файлов очень сильно зависит от их типа, по
этому дан ному вопросу посвящен отдельн ы й раздел (см . п . 1 0 . 6 ) .
378
Глава 1 1 . Испол ьзовани е фа йлов
1 1 .5.5.
Закрытие файла
Для подтвержден и я записанной информации в файл и для сокращения
ресурсов, занятых системой для поддержания файлов в открытом состо
я н и и , после окончания работы с файлом необходимо его закрыть - пе
ревести в неактивное состояние, когда файл недоступен для чтен ия и
зап и с и . Независимо от типа файла его закрытие производится п роцеду
рой Close (англ . Close
закрывать) :
-
Сlоsе ( < Ф а йло в а я п е р еме н н а я > ) ;
При открыти и файла для зап иси информаци я , содержащаяся в нем , уда
ляется , затем программа заново формирует файл . После выполнения про
цедуры Close файл закрывается и вся информация , записанн ая в него ,
подтверждается (остается н а диске) . Есл и программа заканч и вается , а
файл, в который п роизводился вывод, не закрыт, то его дли н а остается
нулевой , то есть информация реально не записывается в файл .
При открытии файла для чтения не может возникнуть такого рода ошиб
ки , однако существует другая проблема. Дело в том , что коли чество фай
лов, которое может быть открыто всеми программ а м и одновремен н о ,
ограниченно. Таким образом , если , например , какая -либо процедура от
крывает файл, используя для этого локальную переменную , и не закры
вает его после чтения и нформации , то такой файл считается открытым и
при некотором количестве вызовов данной процедуры программа аварий
но завершается с ошибкой Error 4 : Т о о many open f i l e s
Оши б к а
4 : Слишком мн о г о о т крытых файл о в .
-
Таким образом , необходи мо внимательно следить за состоян ием файлов,
и , если какой -либо из н их более не нужен для работы, его следует зак
рыть. Приведем п р имер открытия для чтения и закрытия двоичного не
типизированного файла (см . листинг 1 95 ) .
:�ii7J:q;95�bi\��:��;'�€��rt�il$��дз���!1��t����;:�jti�,j§�P-�п:��,;=�; �- - .- :�;:::;:. _ , ·.;i�·-.:1::;
Pro gram F i l e s 4 ;
Va r
В : File ;
{ о п и с а н и е файл о в ой п е р е ме н ной с име н ем В дл я
р а б о ты с двоич ными н е ти п и з ир о в а н ными ф а йл ами }
Begin
As s i gn ( B , • t e s t . bin • ) ;
{ с о п о с т а в л е н и е файл о в ой п ереме н н о й В файлу с
име нем te s t . bin , находящемуел в т е кутем каталог е }
Reset ( В ) ;
{ о т крытие файл а , к о т о р ому с о п о с т а в л е н а
п ереме н н а я В ( t e s t . bin ) дл я ч т е ни я }
Close ( B ) ;
{ з а крыти е файл а , к о т о р ому с о п о с т а в л е н а
п е р е ме н н а я В ( t e s t . bin ) }
End .
379
Turbo Pascal
7.0
После закрытия файла процедурой Close файловая переменная остается
сопоставленной файлу, с которы м производилась работа. Следовательно,
файл может быть открыт снова для чтения или записи без допол нитель
н о го вызова п р о цедуры сопоставления файловой п е ре м е н н о й ф айлу
Assign. Если же файловую переменную необходи мо сопоставить друго
му файлу, то следует воспользоваться процедурой Assign еще раз.
1 1 .6.
Ч тен и е и за п ись файл ов р аз но г о т и па
Операции сопоставления файловых переменных файлам , открытие фай
лов для чтения и зап и с и , а также закрытие файлов осуществляется оди
наково вне зависимости о т их т и п а . Существенные различия наблюдают
ся лишь при чте н и и и записи файлов.
1 1 .6. 1 .
Текстовые файлы
Работа с текстовыми файлами аналогична работе с экраном в текстовом
режим е . Чтение и запись в них производится операторами Read, ReadLn,
wri t e , Writ eLn. При этом в качестве первого параметра этих процедур
указывается файловая п еременная , сопоставленная файлу, в который не
обходи мо вывести и нформацию или из которого ее необходимо считать.
< При емни к информации 1 > ,
<Приемник информации n> ) ;
RеаdLn ( <Ф а йл о в а я п ер еме нн а я > , <При емник информации 1 > ,
<При емни к инфо рма ции n> ) ;
Writе ( < Фа йл о в а я пер еме н на я > , <Выводима я и нформаци я > ,
<Выв одима я информа ц и я > ) ;
Writ eLn ( <Фaйл o в a я переменная> , <Выводима я и нформаци я > ,
< Выв одима я информаци я > ) ;
Rеаd ( < Ф а йло в а я п ер еме н на я > ,
•
•
•
•
•
•
•
•
,
,
,
•
•
•
•
,
Приведем пример создания текстового файла, содержащего строку «Мой
п е р вый т е к с т о в ый ф айл» (см . листин г 1 96) . Файл будет и меть имя
t ext l . txt и н аходиться в текущем каталоге (вместе с вы полняемой про
граммой ) .
:�;�;j1'� С:f��г;;:� ��7���·�����:.:����!:� в.о f�:��й�а · ..
Program Wr i t eTextFi l e ;
Var
t:
Text ;
Begin
380
{ о п и с а ни е файловой п е р е ме н н о й с име н е м t
для р а б о ты с т е к с т о выми файл ами }
Глава 1 1 . Ис пол ьзование файлов
As s i gn ( t ,
1 t ext l . txt 1 ) ;
{ с о п о с т а в л е н и е файл о в ой п е р е ме н н о й t файлу
име н ем t e x t l . txt , н а х о дящему с я в т е кущем
каталоге }
с
{ о ткрытие файл а , к о т о р ому с о п о с т а в л е н а
п ереме н н а я t ( t ex t l . txt ) д л я з а пи с и }
1 Мой nервый текстовый файл 1 ) ;
{ выв о д с троки в файл , к о т о р ому с о п о с т а вл е н а
ф а йл о в а я переме н н а я t ( t ex t l . tx t ) }
Rewri t e ( t ) ;
Wri t e ( t ,
Close ( t ) ;
{ з а крытие файл а , к о т о р ому
п е р е ме н н а я t ( textl . txt ) }
с о п о с т а вл е н а
End .
Убедиться , что файл создан , можно с помощью любого текстового ре
дактора, откр ы в в нем данн ы й файл .
П римечан и е .
Фай л ы , созда н н ы е п рограм м а м и M S - DO S , а и м е н н о таки м и п рограм м а м и
я вл я ютс я в с е п рограм м ы , н ап и сан н ы е в T u r b o Pascal , содержат с и м волы в
коди ровке 8 6 6 , следовател ь н о , для их п ро с м отра в W i n d ows следует указ ы
вать ти п фай л ов «Текст M S - D O S » .
Приведем пример чтения информации из файла, созданного предыдущим
примерам (см . листин г 1 97 ) . Считав строку из файла, выведем ее на экран .
, -· . ,)1 иc+я·��: '1_�ii': ·'Yт���� ,т-� ��-r�·��f�'·: ��·��'� ;�г,: .;;:1,n; · ·· " Y�.·-· ,:>!�;··�'\T;�:?1;%t�;���,�j�ш·:·-:;;:
Progra.m. ReadText F i l e ;
Uses
CRT ;
Var
t : Text ;
{ о п и с а н и е файл о в ой п е р еме н н о й с име н е м t
для р а б о ты с т е к с т о в ыми файл ами }
S : S t ring ;
{ о п и с а н и е с т р о к а в о й п е р еме н н о й , в к о т орую
буд е т прои з в о ди т ь с я ч т е н и е и з ф а й л а }
Begin
ClrScr ;
As s i gn ( t , 1 t ext l . txt 1 ) ;
{ с о п о с т а вл е н и е файл о в ой п е р е ме н н о й t файлу с
именем textl . txt , находящемуся в текущем каталоге }
Re s e t ( t ) ;
{ о т крытие файл а , к о т о р ому с о п о с т а в л е н а
п е р еме н н а я t ( t ex t l . txt ) д л я ч т е ни я }
ReadLn ( t , S ) ;
{ ч т е ни е с тр о ки из файла в п е р е ме н ную S }
Wri t e Ln ( S ) ;
{ вы в о д п ро чи т а н н ой с т р о к и н а э к р а н }
Close ( t ) ;
{ з а крыти е файл а , к о т о р ому с о п о с т а вл е н а
п е р еме н н а я t ( t ex t l . txt ) }
ReadKey ;
End .
381
Turbo Pascal 7 . 0
1 1 .6.2.
Дво и ч н ы е типизирован н ы е файлы
Двоичные файлы содержат и н формацию, аналогичную по строению и н
формации в операти вной памяти . Чтение и запись двоичных тип изиро
ванных файлов осуществляется соответственно процедурами Read и Write
(формы ReadLn и WriteLn не используются , так как файлы я вляются дво
и ч н ы м и , следовательно, не содержат в себе каких-либо строк) . Тип дан
ных, зап исываемых в файл , должен строго соответствовать типу, заявлен
ному в описан и и файловой переменной.
Rеаd ( < Ф а й л о в а я п е р е ме н н а я > ,
Wri t е ( < Ф а й л о в а я п е р еме н н а я > ,
<Приемник
<Приемник
<Ис т о ч н и к
<Источник
и н ф о рма ции
и н ф ормации
и н ф ормации
и нформации
1>,
n> ) ;
1>,
n> ) ;
•
•
•
,
•
•
•
,
В отличие от работы с экраном и текстовым и файлами в качестве п ара
метров Ис'l'очник информации должны использоваться перемен н ы е . Ис
пользование констант недопустимо.
Рассмотрим пример записи в двоичный файл с элементами типа Integer
десяти целых чисел, вводимых пользователем с клавиатуры (см. листинг 1 98).
:t:;,:��9t:� �г:� ��:. · · g9�д�нЩk"���я���r�Ei:�Э��:�P'�!���ь·г� P��:л:�··�,. ,;!> .'!i;;,;s::;i!di(
Program Wri t eTB inF i l e ;
Uses
CRT ;
Var
f : F i l e Of Int ege r ; { о пи с а н и е файл о в о й п е реме н н ой с име н ем
f для р а б о ты с д в о и ч ными типизир о в а н ными
файлами , элементы которых имеют тип Int eger }
i : Intege r ;
А : Int eger ;
Begin
ClrScr;
A s s i gn ( f , 1 numbers . bin 1 ) ; { с о п о с т а в л е н и е ф а й л о в о й п е реме н н о й
f файлу с име н ем numbers . bin ,
н а ходящемуся в т е кущем к а т а л о г е }
{ о т крытие ф а й л а , к о т о р ому с о п о с т а в л е н а
Rewr i t e ( f ) ;
п е р еме н н а я f ( numbers . bi n ) дл я з а пи си }
For i : = l То 1 0 Do
Begin
Wri t e ( 1 Введите число : 1 ) ;
ReadLn ( A ) ;
{ в в од п ол ь з о в а т ел е м ц е л о г о ч и с л а }
Wri t e ( f ,
end;
Close ( f ) ;
End .
382
А) ;
{ запись
введенного
числа
в
файл }
{ з а крытие ф а йл а , к о т о р ому с о п о с т а в л е н а
переме н н а я f ( number s . b i n ) }
Глава 1 1 . И спользование файлов
Теперь прочитаем все десять ч исел из файла, созданн о го программ о й , и
выведем их н а экран (см . листинг 1 99 ) .
�;�iJ;�;�]��rЯ'!���;r;�I������j9i��'�9tt��:r��E��b��,�м;�;����;::'��!!!'�"%l�Ш�1�ц;�;��(R'';�!i:i:;:?�:•
Program ReadTBi nF i l e ;
t1s e s
CRT ;
Va r
f:
F i l e Of
i:
Intege r ;
А:
Intege r ;
{ о п и с а н и е файл о в о й переме н н о й с име н ем f
для работы с дв оичными типизиро в а н ными
файл ами , эл еме нты к о т орых имеют тип Integer }
Integer ;
Begin
ClrScr;
A s s i gn ( f ,
1 nwnbe rs . bin 1 ) ; { с о п о с т а в л е н и е ф а йл о в ой п е р ем е н н о й
f файлу с име н ем numЬers . b i n ,
н а х о д ящимся в т е кущем к а т а л о г е }
{ о т крыти е файл а , к о т о р ому с о п о с т а в л е н а
п ереме н н а я f ( number s . bin ) , дл я ч т е ни я }
Re s e t ( f ) ;
Wr i t eLn ;
For
i : = l То 1 0 Do
Begin
Read ( f ,
А) ;
Wri t eLn ( 1 Пpoчитaиo
{ ч т е ние числа и з файла }
число : 1 , А ) ;
{ выв од числа , прочи т а н н о г о
из
файла }
end;
Close ( f ) ;
{ з а крытие файла , к о т о р ому с о п о с т а в л е н а
п е р еме н н а я f ( number s . b i n ) }
ReadKey ;
End .
Таким же образом зап исываются в файл сложные типы данных. Напри
мер, создадим файл, каждый элемент которого будет иметь ти п данных
<<запись>> , состоящ и й из трех строковых полей (см. листинг 200) .
Program Wri t eRecords ;
t1 s e s
CRT ;
Туре
TName = Record
Name : String ;
383
Turbo Pascal 7 . 0
Pat ronymi c : S t r ing ;
SurName : S t ring ;
end;
{ о п и с а н и е типа д а н ных з а п и с ь
и з т р е х п о л е й с т р о к о в о г о тип а }
Va r
NameFi le : File Of TName ;
{ описание файло вой переменной с име н ем NameF i l e
д л я работы с дв оичными типизир о в а н ными файлами ,
элементы к о т орых имеют тип TNarne }
Name : 'l'name ;
{ о п и с а н и е п е реме н н о й т и п а TNarne }
Begin
C l rS c r ;
Wri t eLn ( 1 Вв еди'I'е ф амилию : 1 ) ;
{ выв од с т р о к и н а э кр а н }
Read ( Name . SurName ) ;
{ ч т е н и е с т р о к и с кла в и а туры }
Wri t eLn ( 1 Введи'I'е имя : 1 ) ;
{ выв о д с т р о ки н а э к р а н }
{ ч т е н и е с т р о к и с кла в и а туры }
Read ( Name . Name ) ;
Wri t eLn ( 1 Введи'I'е о'I'чес'I'в о : 1 ) ;
{ выв од с т р о ки н а э кр а н }
Read ( Name . Pat ronymi c ) ;
{ ч т е н и е с т р о ки с кла в и а туры }
Ass ign ( NameF i l e , 1 name s . bin 1 ) ;
{ с о п о с т а в л е н и е файл о в ой п е р еме н н о й NarneFi l e
файлу с име н е м narnes . bin }
Rewri t e ( NameF i l e ) ;
{ о ткрытие файла дл я ч т е ни я }
Writ e ( NameF i l e , Name ) ; { з а п и с ь переме н н о й Narne в файл , к о т о р ому
с о п о с т а в л е н а п е р еме н н а я NarneF i l e }
{ з а крытие файл а }
C l o s e ( Name F i l e ) ;
End .
Напомн и м , что тип файла - это условность, и меющая смысл только в
подпрограмме его чтения или зап иси . Записав файл с элементами типа
Integer, можно открыть его как файл с элементами , например, типа Byte.
Приведем такой пример (см . листинг 20 1 ) .
'СХ�ЩстИн� �9:Е,;�.��йс'4<�\�-i�l:'и�-. �8о�·ч ноrо :т�пИЭ�ро_��·а нноrо' · 'Фа�ii� :� : : ;;;:,·;· ·
Program ReadWri t e B i n ;
Us e s
CR'l' ;
Var
Bl :
F i l e Of
Integer ;
{ о п и с а н и е файло в ой п е р е ме н н о й с име н е м B l
д л я работы с двоичными типизиро в а н ными файлами ,
э л еме н ты к о т орых имеют тип I n t eger }
В2 :
F i l e Of
Byt e ;
{ о п и с а н и е файл о в ой п е р еме н н ой с име н е м В 2
д л я работы с двоичными типизиро в а нными файлами ,
э л еме н ты к о т орых имеют т и п Byt e }
V:
Byt e ;
I:
Int ege r ;
384
Глава 1 1 . Испол ьз ование файлов
Begin
1 names . bin 1 ) ;
{ с о п о с т а в л е ни е ф а й л о в о й п е р е ме н н ой Bl файлу
с име нем names . bin ; э л еме н ты файла р а с см а т р и
в аю т с я к а к элеме нты т и п а I n t eger }
A s s i gn ( B 1 ,
{ о ткрытие
Rewri t e ( B 1 ) ;
I
: =
файла
для
ч т е ни я }
12 0 0 0 ;
Writ e ( B 1 ,
I) ;
Close ( B 1 ) ;
{ з а п и с ь в файл , к о т о р ому с о п о с т а в л е н а
п е р е ме н н а я NameFi l e , з н а ч е н и я 1 2 0 0 0 }
{ з а крытие файл а }
ClrScr;
As s ign ( B 2 ,
1 name s . bin 1 ) ;
{ с о п о с т а вл е н и е ф а й л о в о й п е р е ме н н о й В2 файлу
с име нем names . bin ; эл еме н т ы файла р а с сма три
в аю т с я к а к элеме н ты т и п а Byt e }
Re s e t ( B2 ) ;
{ о т крыти е
Read ( B 2 ,
Wri t e ( V ) ;
{ ч т е н и е з н а ч е н и я пер еме н н о й V и з ф а й л а }
{ выв од з н а ч е н и я переме н н о й V н а э кр а н }
Close ( B2 ) ;
{ з а крыти е
V) ;
файл а для ч т е ни я }
файл а }
ReadKey ;
End .
Приведен ный пример вполне корректен с точки зрения языка программи
рования. В первой его части создается файл, содержащий целочисленное зна
чение 1 2000, занимающее два байта. Далее производится сч итыван ие пер
вого байта в переменную v , имеющую тип Byte . Никакого прикладиого
значен ия такая программа не имеет, так как основное правило работы с ин
формацией - информация, записанная в какой-либо форме, должна быть
прочитана в той же самой форме. А число, выдаваемое на экран , - 224.
1 1 .6.3.
Дво и ч н ы е н ети п изирован н ы е файлы
М етоды работы с двоичными нетипизированн ы м и файлами существен н о
отличаются о т методов работы с текстовыми и дво и ч н ы м и ти пизирован
ными файлами . Эти методы являются более сложны м и , однако и предо
ставляют более развитые возможности . Рассмотрим особенности исполь
зован ия файлов дан ного типа.
1 . О п исани е файловой переменной и сопоставл е н и е ее файлу уже
рассмотрен о нам и .
2 . Открытие файла для чтения или записи содержит допол нительн ы й
параметр, определяющий размер единицы информации (в байтах) , ис
пользуемой для обмена данными программы и операционной системы:
Rеsеt ( < Файлов а я п еременна я > , < Р а змер е диницы информации> ) ;
Rеwritе ( <Файл о в а я п ереме нна я> , < Р а змер единицы информации> ) ;
13
Зах. 702
385
Turbo Pascal
7.0
3 . Чтение и нформации из файла и запись информации в файл осуще
ствля .тся соответственно процедурами BlockRead (англ . Read Block
прочитать бл ок и нформации) и BlockWrite (англ . Write Block
зап исать блок и н формации ) , имеющим и следующие параметр ы :
ВlосkRеаd ( < Ф айло в а я п е р еме н н а я > , <При емни к и нформации > ,
< К олич е с т в о е диниц и н формации> ) ;
BlockWri t e ( < Ф a йл o в a я п е р е ме н н а я > , < И с т о ч н и к и н ф ормации > ,
< Колич е с т в о е ди н и ц и н ф о рмации > ) ;
В качестве параметров Приемник инф ормации и Источник инф ор
могут использоваться переменные любого типа, в том числе и
области дан ных, на которые ссылаются нети пизирован н ы е указате
ли , что позволяет сохранять в файлах спрайты . Параметр Колич е
с т в о единиц информации указы вает размер читаемых и записывае
мых дан н ых в еди н ицах информации , размер которых указан при
открытии файла процедурой Re set или Rewri t e .
мации
Рекомендуется при открытии файлов указывать в качестве Размера еди
информации число 1 , тогда при вызове процедур BlockRead и
BlockWrite параметр Количество единиц информации будет равен
размеру переменной, заданной в качестве параметра Приемник инфор
мации для процедуры BlockRead или Источник информации для про
цедуры BlockWrite. Размер переменной можно определить с помощью
функции Si zeOf (англ . Size Of - размер чего-либо) , возвращающей
размер в байтах переменной , заданной в качестве параметра:
ницъi
...
S i z еОf ( < П е р е ме н н а я > )
4. Закрытие файла п р о изводится обыч н ы м образом - вызовом п роце
дуры C l o s e .
При ведем примеры записи информации в двоичный нети п изирован ный
файл и чтения ее обратно (см . листи н г 202) .
t;'1!1Цc�;;r·���9·2·:;:·����!a�·:��Ф:9·�·��ц�·�·., �,Aiь��:��;:�,·��f�'��З'�'pri·� ����·�:::Фa:�;t;t\
Program Writ eUTB i n ;
Va r
I:
Intege r ;
S:
St ring ;
F:
File;
Begin
Ass i gn ( F ,
Rewri t e ( F ,
• untyped . bin ' ) ;
{ с о п о с т а в л е ние файл о в о й
файлу un typed . bi n }
1) ;
п е р еме н н о й
{ о т крытие файла untyped . b i n дл я
е диницы информации для о бме н а
-
386
F
з а писи , р а змер
1 байт }
Глава 1 1 . Испол ьзован ие файлов
S
1 Ветер жиз нь в
:=
BlockWri t e ( F ,
I
nрироду вдохнул 1 ;
S,
S i zeOf ( S ) ) ;
{ з а n и с ь в файл с т р о к и , д л я о n р е д е л е н и я
р а зме р а с тр о ки и с n о л ь з о в а н а функци я S i z eO f
с n а р аметром
име н е м n е р е ме н н о й S ,
з а n и сыв а емой в файл }
I,
S i z eO f ( I ) ) ;
{ з а n и с ь в файл числа , для о n р е де л е н и я
р а зме р а ч и с л а и с n ол ь з о в а н а фун кция S i z eO f
с n а р аметром - име н ем n е р е ме н н о й I ,
з а nи сыв а емой в файл }
15 ;
: =
BlockWri t e ( F ,
Close ( F ) ;
{ з а крытие
ф а йл а }
End .
Т е п е р ь н ап и ш е м п р о гр а м м у , ч итающую з а п и с а н н у ю и н ф о р м ац и ю
(см . листи н г 203) .
,·]1_и.стиi;IГ�2о з. ч:tенИ_е
�: :,:.\
·
..
·: '·
. · . · ..
·и·и·ф-о р���йи ;�· ' "'· :��.q�
:, ��t�.n�эи��!l��,��r�:�.
�,;,/�1;�;i;it{:;;:c�;'f,.,::
·
''-' i'''"
Program ReadUTBi n ;
Uses
CRT ;
Var
I : Intege r ;
S : S t ring ;
F : File ;
Begin
C l rS c r ;
Ass ign ( F , 1 Untyped . bin 1 ) ;
{ с о n о с т а в л е ни е ф а йл о в ой n е р еме н н ой
F файлу untyped . bi n }
Re set ( F , 1 ) ;
{ о т крытие файла untyped . Ьi n для ч т е н и я ,
р а змер единицы информации для о бме н а - 1 б ай т }
BlockRead ( F , S , Si zeOf ( S ) ) ; { ч т е н и е и з файла с т р о ки , для о n р е
д е л е н и я р а зме р а с тр о ки и с n ол ь з о в а н а
фун кция S i z eOf с n араме тром - име н ем
nереме н н ой S , чи т а емой и з ф а й л а }
BlockRead ( F , I , Si zeOf ( I ) ) ;
{ чт е ние из файла чи сл а , дл я оnределе
ния размера числа исnоль зована функция
Si zeOf с nараме тром - име н е м
n е р е ме нн о й I ,
ч и т а емой и з ф а й л а }
Close ( F ) ;
{ з а крытие файл а }
S) ;
Wri t eLn ( 1 S t r ing :
Wri t eLn ( 1 Number :
I) ;
{ вывод н а э к р а н д а н ных ,
nрочи т а н ных и з ф а й л а }
ReadKey ;
End .
387
Turbo Pascal
7.0
1 1 .7. В сп о м о га тел ь н ые опер аци и с файл а м и
1 1 .7. 1 .
Определение размера файла
Все приведеин ы е выше программ ы ч итали информацию из файла, осно
вываясь на некотором жестком формате , задаваем ы м методом создания
этого файла. Однако программа не всегда располагает информацией о ко
личестве еди н и ц и н формаци и , которые должны содержаться в файле.
Например, одна програм ма производит измерения температуры и зап и
сывает их в файл . Затем другая программа должна проч итать этот файл
и вычислить среднюю температуру. При разработке второй программы не
известно , сколько измерен ий записано в файле, известен только тип дан
ных, который используется для записи каждого измерения в файл .
О п редел е н и е размера текстового ф а йла
Н а п и ш е м програм му (см . листи н г 204) , которая в н ач але свой р аботы
будет запраши вать у п ользователя коли чество измерен и й . Затем пользо
вателю должно быть предложено ввести заданное коли чество чисел , ко
торые будут зап и с ы ваться в файл . Для хран е н и я ч и сел будем и споль
зовать те кстовы й файл , в каждой строке которого будет рас п олагаться
ОД Н О Ч И СЛ О .
i�<l,J �;��.и.�r_i2 q4;.:·�э�·�i?:�<�·.•:z�g#����1�1fli�·�"�;iP:P.�.����.���<�.f�:��#��.��i��1��c.e�<:
Program Wri t eTemp s ;
Uses
CRT ;
Var
Т : Rea l ;
TNumЬer : Intege r ;
i : Integer ;
F : Text ;
Begin
ClrSc r ;
Writ e { ' Вв едите количество измерений : ' ) ;
ReadLn { TNwnЬe r ) ;
{ в в о д количе с т в а и зме р е ний , к о т орые н е о б х о димо
с о х р а н и т ь в файле }
' t emps . t xt ' ) ;
As s i gn { F
{ с о п о с т а вл е ни е файл о в ой п е р еме н н о й ф айлу
t emp s . txt , файл счи т а е т с я т е к с т о вым }
Rewr i t e { F ) ;
{ о т крытие файла t emp s . txt для з а пи с и }
For i : = 1 То TNUlDЬer Do
begin
{ цикл п о колич е с т в у и змер е ни й , в в е д е н н ому
п о л ь з о в а телем в п е р е ме н ную TNumber }
Wri t е { ' Вв едите измерение номер '
i
: •);
ReadLn { T ) ;
{ в в од о ч е р е д н о г о з н а ч е ни я с кл а в и а туры }
1
1
388
1
'
Глава 1 1 . И спользова н и е файлов
Wri teLn ( F , 'l' ) ;
{ з а п и с ь в в е д е н н о г о з н а ч е ни я
end;
C l o s e ( F) ;
О { з а крыт и е ф а й л а }
');
Wri t eLn ( ' Информация усnешно сохранена
ReadKey ;
End .
•
•
в
файл }
•
Таким образом , после выполне ния программы в файле t emp s . txt кол и
чество строчек будет равняться числу, введен ному п ол ьзователем в ответ
на запрос « В в е ди т е колич е с т в о и зме р е ний».
Теперь напишем программу, которая читает весь файл t emp s . tx t , зара
нее не зная его размера. Для этого используем специал ьную функцию EOF
(англ . End Of File
конец файла) , возвращающую и стин ное знач е н и е ,
если дости гнут конец заданного файла, и л и ложное , если конец файла
не достигнут:
-
ЕОF ( < Файло в а я п ер еме н�а я > )
С помощью функци и EOF можно реализовать условный оператор цикла
Whil e , заци кл и вающи й фрагмент програм м ы , ч итающий очередное ч ис
ло из файла и сч итающий количество прочитан н ых ч исел . Цикл автома
тически закончится при достижении конца файла, после этого м ожно вы
числить среднее значение для прочитанных чисел (см . листинг 205 ) .
"tr;mr,}т�f'�, '�;e��� '�t!��=��=�т:=������r:i :����2,�: ;�1r';�:;r:��1�t�[ijji�,��t��:ti'�"IИt[f!'
Program Read'l'emp s ;
Uses
CRT ;
Va r
т , Suш. : Real ;
'l'RumЬer : Intege r ;
f : Text ;
Begin
ClrScr ;
As s i gn ( f , ' t emp s . t xt ' ) ; { с о п о с т а вл е ни е ф а йл о в ой п е р еме н н о й
файлу t ernp s . txt }
Re s e t ( f ) ;
{ о ткрытие файла для ч т е ни я }
Suш. : = О ;
{ о б нул е ни е переме н ной , в к о т о р о й буд е т }
содержа т ь с я сумма прочи т а н ных и з ф а й л а ч и с е л }
TNum.Ьer : = О ;
{ о б нул е н и е сче тчика п р о чи т а н ных ч и с е л }
While not EX>F ( f ) do { усл о в ный о п е р а т о р цикл а , усл о в и е п р о д о л
ж е н и я - «не д о с т и г нут к о н е ц ф а й л а » }
begin
ReadLn ( F , 'l' ) ;
{ ч т е н и е из файла о д н о г о числа в п е реме н ную Т }
Suш. : = Suш. + 'l' ;
{ ув елич е н и е суммы п р о чи т а н ных ч и с е л }
'l'NumЬer : = 'l'NumЬer + 1 ; { увеличение счетчика прочитанных чисел }
end;
389
Turbo Pascal
7.0
Close ( F ) ;
{ з а крыти е файл а }
Writ eLn ( ' Cpeдняя темnература :
Swn/TNwnЬer : О : 3 ) ;
{ выв од на экран среднего значени я , ра считыва емого
по формуле Sum/ TnumЬer ( сумма дели т с я на коли
ч е с т в о чисел ) ; форма т вывода н а э к р а н - три
цифры после д е с ятичной з а п я т ой }
ReadKey ;
End .
'
1
О п редел е н и е размера двоичн ого файла
Измен и м программы сохранения измерен ий температуры и вычисления
среднего значения таким образом, чтобы и н формация хранилась в дво
ичном типизированном файле (см . листи нг 206) . Элементы файла будут
и меть тип Real .
!�!f?�<
i�J��i����:�,;�j��,: ,�:�=�=�����t��������;:���\��:�·:�-:"Ф-�.�-1o' ·;,_; :y/:'!:':- ,И, '· _;.j
Program Wri t eTempsTB ;
Uses
CRT ;
Var
Т:
Rea l ;
TNumЬer :
Intege r ;
i:
Integer ;
F:
F i l e Of Rea l ;
Begin
ClrSc r ;
Wri t e ( ' Вз едите
количест з о измерений :
' );
{ в в о д количе с т в а и зме р е ний , к о т орые н е о б х о димо
с о х р а н и т ь в файл е }
• t emps . bin ' ) ;
{ с о п о с т а в л е ни е файл о в ой п е р еме н н о й файлу
t emp s . bin , файл счи т а е т с я т е к с т о вым }
ReadLn ( TNwnbe r ) ;
As s i gn ( F I
Rewri t e ( F ) ;
For
i : = 1 То
{ о ткрытие
файла
t emp s . bin дл я
з а пи с и }
TNumЬer Do
{ цикл по колич е с т в у и змерений в в е д е н н ому
п о л ь з о в а т елем в п е р еме н ную TNumber }
: ');
Wri te ( ' Взедите измерение номер ' , i
begin
'
1
ReadLn ( T ) ;
{ в в од
Writ e ( F I
{ запись
Т) ;
очередного
значения
введенного
end ;
Close ( F ) ;
{ з а крытие
Wri t eLn ( ' Информация
ReadKey ;
End .
390
усnешно
с
з н а ч е ни я
файл а }
сохранена
•
•
•
');
к л а в и а туры }
в
файл }
Глава 1 1 . Испол ьзован ие файлов
Программа зап иси в файл практически не отличается от аналогич ной,
использующей текстовый файл. Разница состоит только в описан и и фай
ловой переменной - вместо тип а техt используется тип F i l e Of Real .
Вместо процедуры зап иси в файл WriteLn используется процедура Write.
Программа чтения и нформации также может быть изменена п одобным
образом , чтобы осуществлять чтение из двоичного файла (см . листинг 207) .
�;,;�'�:r�t"r:��,!·��:·;i=���{:ii���:ffq�:�1����t����!���.���;,,
Program ReadTemp s ;
Uses
CRT ;
Va r
т, Sum : Real ;
TNumЬer : Intege r ;
f : F i l e Of Rea l ;
Begin
ClrScr ;
As s i gn ( f , • t emps . bin ' ) ;
{ сопоставление файловой переменной файлу temps . bin }
Reset ( f ) ;
{ о ткрытие файла дл я ч т е ни я }
Sum : = О ;
{ обнуление переменной , в которой будет содержа ть
с я сумма прочи т а н ных из файла ч и с е л }
{ о б нул е н и е сче тчика прочи т а н ных ч и с е л }
TNumЬer : = О ;
Whi l e not EOF ( f ) do { у сл о в ный о п е р а т ор цикл а , у с л о в и е продолже н и я - « н е д о с тигнут к о н е ц файла» }
begin
Read ( f , Т ) ;
{ ч т е н и е из файла о д н о г о ч и с л а в п е ременную Т }
Sum : = Sum + Т ; { ув е л и ч е н и е суммы прочи т а н ных ч и с е л }
TNumЬer : = TNumЬer + 1 ;
{ ув е л и ч е н и е с ч е т ч и к а п р о чи т а н ных ч и с е л }
end ;
Close ( f ) ;
{ з а крыти е файл а }
WriteLn ( ' Cpeдняя 'l'eмnepa'l'ypa : ' , Sum/ TNumЬer : О : 3 ) ;
{ вывод на экран среднего значения , рассчитываемого
п о формуле Sum/ TnumЬer ( сумма дели т с я на коли
ч е с т в о чисел ) ; форма т выв о д а н а э к р а н - три
цифры после д е с я ти ч н о й з а п я т о й }
ReadKey ;
End .
Однако для двоичных файлов предусмотрен еще оди н способ определе
ния длины файла, часто более удобный в использовани и , чем функция EOF.
Процедура Fi l e S i z e (от англ. Size Of File - размер файла) возвраща
ет размер файла, заданн ы й ей в качестве параметра:
FileSize ( < Ф a йлo в a я п е р ем е н н а я > )
391
Turbo Pascal 7 . 0
Для двоичных типизированн ых файлов данная функция возвращает коли
чество элементов в файле, а для двоичных нетипизированных - количество
единиц информации , используемых для обмена программы с операционной
системой. Размер таких единиц задается процедурами Re set и Rewrite
соответственно, при открытии файла для чтения или для записи.
В момент использования функции FileSi z e , файл , соответствующий па
раметру Файловая nеременная, должен быть открыт.
Изменим предыдущую программу чтения и нформации и вычисления сред
него значения (см. листин г 208 ) .
-.:,,:, �:::"' .·· ··
'-'�Jiиc:тИFiг,::zo�� '.:.тitн�е 'и�;д�Qи�'�оi'S;Fi�""��'ро•i��Ы91Ф��л�: ' . . :' ; . ;, · . .
.
. ,/,
, . , . ,< :: <' <: >:: :: .�р()иЗ!Iол�"!�·Г�;�к�iоtч'е�t,�� :ч��е11Ь·, ·'>· :;· ,;' :'е, ' , '.· . ,. · . :: :С:
·,
·
·
·
,
.
Program ReadTemp s ;
Uses
CRT ;
Va r
т , Sum : Real ;
i : Int eger ;
f : F i l e Of Rea l ;
Begin
ClrScr;
As s i gn ( f , ' t emp s . bin ' ) ;
{ с о п о с т а вл е ни е ф а йл о в ой п е р е м е н н о й
ф а йлу t emp s . Ьin }
{ о ткрытие файла для ч т е ни я }
Re s e t ( f ) ;
{ о бнул е н и е п е р е ме н ной , в к о т ор о й буд е т с о д е р
Sum : = О ;
жа т ь с я сумма прочи т а н ных и з ф а й л а ч и с е л }
For i : = l То F i l e S i z e ( f ) Do
{ безусловный цикл по количеству элементов в файле }
begin
Read ( f , Т ) ;
{ ч т е н и е и з файла одн о г о ч и с л а в п е р е м е нную Т }
Sum : = Sum + Т ; { ув елич е н и е суммы прочи т а н ных ч и с е л }
end ;
Wri t eLn ( ' Средняя т емnератур а : ' , Sum/Fi l e S i z e ( f ) : О : 3 ) ;
{ вывод на экран среднего значения , рассчитываемого
п о формул е Sum/ F i l eS i z e ( f ) ( сумма д е ли т с я н а
длину файл а ) ; форма т в ы в о д а н а э к р а н - три
цифры после д е с я ти ч н о й з а п я т о й }
Close ( f ) ;
{ з а крытие файл а }
ReadKey ;
End .
Как видно, программа стала немного короче. Заметим , что строка про
грам м ы , в которой производится расчет средней температуры и вы вод ее
392
Глава 1 1 . Испол ьзование файлов
на экран , п еренесена выше, чтобы находиться перед закрытием файла,
и н аче обращени е к функции FileSize будет недопусти м о .
1 1 .7.2.
Изменение текущего элемента
При открытии файла для чтения или записи текущи м элементом авто
матически становится первый элемент. Для дво и ч н ых файлов в Turbo
Pascal предусмотрена специальная процедура, позволяю щая переместить
указатель текущего элемента в любое место , то есть перейти сразу к нуж
ному элеме нту. При этом не надо последовательно считы вать все преды
дущие элементы с начала файла.
Sееk ( < Ф айлов а я переме н н а я> , <Номер н о в о г о т е куще г о элеме н т а > ) ;
Процедура Seek (англ. Seek
искать) перемещает указатель текущего
элемента файла, заданного параметром Файловая nеременная, в пози
цию, задан ную п араметром Номер 'l'екущеrо элемен'l' а . Н умерация эле
ментов файла ведется от нуля , то есть первый элемент и меет номер О.
-
Приведем пример программы, сч итывающей первый и последний элемен
ты файла без с ч иты в а н и я эл е м ен то в , рас п ол оже н н ы х м е жду- н и м и
(см . листин г 209) .
•·· • Л. и cj·м �.f:.;ip�.:; ���-�@���:;��ltYЩW��;·�;�,��:�:t�::'#»����:· :;i;X�:�;;;;l\�.;'�iб�����:;�;:�\��}i':.
P rogram RandomRead;
Uses
CRT ;
Va r
т , Sum : Real ;
f : F i l e Of Rea l ;
Begin
ClrScr;
As s i gn ( f , 1 t emps . bin 1 ) ;
Reset ( f ) ;
{ о ткрытие файла дл я ч т е ни я }
Seek ( f , О ) ;
{ п о зиционир о в а н и е ук а з а т е л я т е куще г о э л е ме н т а
н а п е р вый эл еме н т н е о б я з а т ел ь н о , т а к к а к при
о т крытии файла т е кущим э л е ме н т ом я в л я е т с я
п е р вый ( с н омером н о л ь ) }
{ ч т е ни е т е куще г о э л еме н т а ( п е р в о г о ) }
Read ( f , Т ) ;
Writ eLn ( 1 Первый элемент : 1 , Т : О : 3 ) ;
Seek ( f , F i l e S i z e ( f )
1) ;
{ п о зиционир о в а н и е ук а з а т е л я т е куще г о э л е ме н т а
н а п о следний элеме н т }
Read ( f , Т ) ;
{ ч т е н и е т е куще г о элеме н т а }
Wri t eLn ( 1 По следний элемент : 1 , Т : О : 3 ) ;
Close ( f ) ;
{ з а крытие файл а ]
ReadKey ;
End .
-
393
Turbo Pascal
7.0
1 1 . 8 . Д о ба влен ие и нфо р м ации в файл ы
1 1 .8. 1 .
Добавл е н и е информации в текстов ы е ф а йлы
Для текстовых файлов предусмотрена возможность добавления и нформа
ции в их конец. Для этого файл следует открывать не процедурой Rewri te,
а процедурой Append (от англ . Append - до бавить) :
Арреnd ( < Файло в а я п е р еме н н а я > ) ;
После вызова данн ой процедуры файл открывается для записи , но ин
формация в нем не стирается , как в случае использования п р оцедуры
Rewr i t e . Указатель текущего элемента автоматически перемешается в
конец файла, куда и будет дописываться выводим ая и нформация .
В к а ч е с т в е п р и м е р а д о п и ш е м к ф а й л у , с озд а н н о м у п р о гр а м м о й
WriteTextFile , еще одну строку: « С о с т ои т и з двух с т р о к» (см. ли
сти нг 2 1 0) .
�����Sf����,1�Q'i�·89���#'�'���;::�!fi���§.�{i���!ci�·a·�v· Ф�·���: ;:.·,�; :i··::;·.:;;:�.}�l�;1'.Б.�!K··;
..
..
Program Writ eтextF i l e 2 ;
Va r
{ о п и с а н и е файл о в ой переме н н о й с име н ем t
t : Text ;
для р а б о ты с т е к с т о в ыми файл ами }
Begin
Ass ign ( t , • t ext l . txt ' ) ;
{ со п о с т а вл е н и е файл о в ой переме н н о й t файлу с
именем textl . txt
находящемуся в текущем каталоге }
{ о т крытие файла для д о б а в л е н и я и н ф ормации }
Append ( t ) ;
Wri t eLn ( t , ' Мой nервый текст овый файл ' ) ;
Wri t e ( t , ' Состоит из двух строк ' ) ;
{ вы во д с т р о ки в к о н е ц файла
к о т о р ому
с о п о с т авлена файл о в а я переме н н а я t ( t extl . txt ) }
Close ( t ) ;
{ з а крытие ф а й л а }
1
1
End .
В результате выполнения такой програм м ы файл text l . txt будет содер
жать две строки : «Мой п е р вый т е кс т овый ф айл» и « С о с т о и т и з д в ух
с т р о к» .
1 1 .8.2.
Добавление и нформ аци и в дво и ч н ы е файлы
Двоичные файлы подде рживают одновременное чтение и зап ись элемен
тов , причем если производится запись элементов за предел ы файла, то
перед записывае м ы м элементом автоматически добавляется соответству
ющее кол ичество нулевых элементов.
394
Глава 1 1 . Испол ьзован и е файлов
Напишем программу, записывающую и нформацию в десятый элемент дво
ичного типизированного файла с элементами типа Real (см. листинг 2 1 1 ) .
з,�r.�:;�t�:2:1;.�'�1{:�gili��������;::�1��:�,т���������l����������
Program RandomWr i t e ;
Uses
CRT ;
Va r
Т : Real ;
i : Intege r ;
F : F i l e Of Real ;
Begin
As s i gn ( F , ' rand . bin ' ) ;
{ с о п о с т а в л е ни е файл о в ой п е р ем е н н о й
файлу r and . b i n }
Rewri t e ( F ) ;
{ о ткрытие файла t emp s . bin для з а пи с и }
Seek ( f , 9 ) ;
{ п е р емеще ние ук а з а т е л я т е куще г о э л е ме н т а
н а д е с ятый }
т : = 20 .5;
Wri t e ( F , Т ) ;
{ з а п и с ь з н а ч е н и я в де с я тый э л е ме н т файла ,
пре дыдущи е д е в я т ь з а п ол н яют с я н ул ями }
Close ( F ) ;
{ з а крытие файл а }
ReadKey ;
End .
Добавление элементов в двоичные файлы происходит аналоги ч н ы м об
разом - открытием фа й ла, изменением текущего элемента и записью в
него и нформаци и . Для того чтобы не удалялась предыдущая ин форма
ция , файл нео бходимо открывать процедурой Re set (см. л истин г 2 1 2) .
·, ·: '·
·
· ;\ : < :.' •·. . · : .: · • <:::::,�::p;.тiii �.���P;:� �·�.�E�i�.·*,� ��::�: A�::::,��·· .� ·"·
·
. .
>J,/�- . .
. ·.
=-·
· �"�·
.- ) , -·J ,_ц.х = . � --�·- = ; � .� :- �:;;·;::· ·��:т:..
..
-��;:'"h;' .· = -·--:'";---:::·:. ' / '/· · : nz. . c:.:',.; ·:",t-·:f: ; >:::· i ·�y;;.,-,· : �' �· - =:.h ;,::; >
,<:;:'l] И CTИH ('., ,2 1 ,2 �.Дoб�BЛEЩI/I�l 111 1:1ФOPI\otlli,\I/IИ; Q�Д�()I/IЧH.�I.И '
:·
У "
• , --
·
, ·-
'>'; � .
:�
..
Program AddB i n ;
'j!t?p.
Uses
CRT ;
Var
Т:
Real ;
i:
Integer ;
F:
F i l e Of Rea l ;
Begin
As s i gn ( F ,
Re s e t ( F ) ;
• rand . bin ' ) ;
{ сопоставление
rand . b i n }
{ о т крытие
файла
ф а йл о в о й
п е р еме н н о й
t emp s . bin дд я
ф айлу
з а п ис и }
395
T u rbo Pascal
Seek { f ,
т
: =
7.0
10 ) ;
{ п е р емеще н и е ука з а т ел я
н а оди н н адца тый }
т е куще г о
э л еме н т а
20 . 5;
Wri t e { F ,
Т) ;
Close { F ) ;
{ з а п и с ь з н а ч е н и я в оди н н а д ц а т ый э л е ме н т
о с т а л ь ные о с тают с я б е з и з ме н е ни я }
{ з а крытие файл а }
файла ,
ReadKey ;
End .
1 1 . 9 . Раб от а с файл ово й сист е м о й
Для эффекти вн ого управления расположением файлов в Turbo Pascal
предусмотрено множество процедур. Т е операци и , которые не входят в
стандартную поставку Turbo Pascal , можно реализовать самостоятельно .
1 1 .9. 1 .
Удаление файлов
Удаление файлов с диска производится процедурой Erase (англ . Erase
стирать) , имеющей следующ и й вид:
-
Еrаsе { < Ф а йло в а я п ер е м е н н а я > ) ;
Перед удале нием файл , определяемый параметром Файловая nереме н
не должен быть открыт для чтения или зап иси. Соответственно, после
удаления файл н е следует закры вать, так как он не б ыл открыт. Правила
сопоставления файловых переменных файлам при использовани и проце
дуры Erase остаются такими же , как и для обычно й работы с файлами ,
то есть в процедуре Assign можно использовать либо полные имена фай
лов, ли бо относительн ые .
ная,
1 1 .9.2.
П ереи менование и перенос файлов
Переи менован ие и перенос файлов на диске производится процедурой
Rename (англ . Rename
переименовать) , имеющей следующий вид:
-
Rеnаmе ( < Ф а йл о в а я п е р е м е н н а я > , < Н о в о е имя ф а йл а > ) ;
В качестве параметра Новое имя файла используется строковал пере
менная или константа, содержащая новое имя файла, пр и этом возмож
на смена каталога, в котором находился файл , в результате чего и осу
ществляется не просто переименование файла, а его перенос . Изменять
положение файла таким образом, чтобы он оказался на другом логичес
ком диске, не допускается .
396
Глава 1 1 . И с пол ь зование файлов
1 1 .9.3.
Коп и рование файлов
Специал ьн ых процедур для коп ирован ия файла не существует, п оэтому
дан ную задачу приходится решать стандартными средствами чтен ия и со
здания файлов . Положительным побочным эффектом нап исания таких
подпрограмм я вляется решение проблемы невозможности переноса фа й
ла на друго й логически й диск.
Н ап и шем процедуру, которая должна:
1 . Получать в качестве п араметров два имени файла - и сходное и
конеч ное, образующееся в результате коп и рован ия ил и перемеще
н ия файла. Еще одни м параметром будет логическое значени е , оп
ределяющее, надо ли удалять и сходны й файл . Таким образо м , про
цедура будет л ибо копировать оди н файл в другой , с новым и менем ,
ли бо переносить файл из одного места в другое. Поскол ьку для
создания резул ьтирующего файла будут испол ьзоваться тол ько стан
дартн ые п роцедуры чтен ия и зап иси файл о в , то резул ьтирующий
файл может н аходиться на любом логическом диске , вне зависи мо
сти от того, где н аходился исходный .
2 . Создавать коп и ю исходно го файла в файле с и ме не м р езул ьтирующего файла и в случае необходимости удалять исходны й файл .
И спользо ван и е про цедуры п родемо нстрируем н а примере програм м ы ,
создающей текстовый файл и перемещающей его в корневой каталог дис
кеты (см . листи нг 2 1 3 ) .
•
- --:��_сf���:-��--�;�· :s#��#:���:с, �;.?·� �:���-�щ�ж�:'ч'��:е,�'#,:·.;�::;;:·.t:::Е�д:).�- 'i:•';:;;�:::йу·:·,:<:г :·;>.·+,;
Program Creat eAndCopy ;
Uses
CRT ;
Va r
t:
Text ;
{ о п и с а н и е г л о б ал ь н о й файл о в ой п е р еме н н о й для
создания текстового файла , который в дал ь н е йшем
буд е т п е р е н е с е н на ди с к е т у }
Procedure MoveFile ( SourceName ,
DestName :
String ;
Move :
Boolean ) ;
{ з а г ол о в о к проце дуры MoveF i l e для п е р е н о с а или
п е р еиме н о в а ния файл а , п а р аме тры S our c eNarne и
Des tNarne указывают имена исходного и ре зуль тирую
щего файлов , параметр Move
необходимость удале
ния исходного файла п о сле с о з д а н и я его к о пии }
-
Va r
Sourc e ,
tmpByte :
De s t :
Byt e ;
File;
{ о п и с а н и е л о к а л ь ных п ер еме н ных S ou r c e и Des t
дл я с о п о с т а в л е н и я и с х о д н ому и р е з ул ь тирующему
397
Turbo Pascal
7.0
файлам и переменной tmpByt e дл я пр омежуточного
х р а н е н и я э л еме н т о в файл о в }
begin
A s s i gn ( Sourc e ,
As s i gn ( De s t ,
SourceName ) ;
{ с о п о с т а в л е н и е л о к ал ь н ой
и с ходн ому файлу }
п е р е ме н н о й
S ou r c e
DestName ) ;
{ с о п о с т а в л е ни е л о к а л ь н о й
р е зул ь тирующему файлу }
переменной
Des t
Re set ( Sourc e ,
1) ;
Rewri t e ( De s t ,
1 ) ; { о т крытие
Whi l e
not
и с х о дн о г о и
р е зул ь тирующе г о
файлов }
EOF ( Source ) Do
{ условный о п ера тор цикла , условие продолжения
н е д о с т и г нут к о н е ц и с х о д н о г о ф а й л а }
begin
B1ockRead ( Sourc e ,
B l ockWri t e ( De s t ,
tmpByt e ,
1) ;
tmpByt e , 1 ) ;
{ ч т е н и е очередн о г о элеме н т а и з и с х о д н о г о файла
в л о к а л ь ную п ереме н ную tmpByt e и з а п и с ь ее
в р е зуль тирующий файл }
end ;
C l o s e ( Source ) ;
{ з а крыт и е
C l o s e ( De s t ) ;
исходного и
р е зуль тирующе г о
файло в }
i f Move Then Erase ( Source ) ;
{ е сли в к а ч е с т в е п араме тра Move п е р е д а н о True ,
т о удал ение исходн о г о файла , в р е зул ь т а т е ч е г о
прои сходит как б ы не копирование файл а , а пере
н о с ( или п е р е име н о в а ние , е сли р е зуль тирующий
файл н а х одится в одном к а т а л о г е с и с х одным ) }
end;
Begin
A s s ign ( t ,
' Fo rMove . txt ' ) ;
{ с о п о с т а в л е н и е гло б а л ь н о й
с име нем formove . txt }
{ создание файла
Rewri t e ( t ) ;
Wri t e ( t ,
Close ( t ) ;
' Этот
formove . txt
ф айл будет nеремещен ' ) ;
{ з а п и с ь с т р о ки в файл
( з акрытие
ф айл а
п е р еме н н о й
398
ф а йлу
в те кущем к а т алоге }
f o rmove . txt ]
formove . t xt }
MoveFi l e ( ' ForMove . t xt ' , ' а : \ Move d . txt ' , True ) ;
{ п е р е н о с файла fo rmove . txt на
End .
t
ди с к е т у }
Глава 1 1 . Испол ьзован ие файлов
1 1 .9.4.
Работа с каталогам и
Для более удобной организации файлов, исп ользуемых програм мо й , ис
пользуются катало ги . Например, если программа работает с м ножеством
изображени й , их можно хранить в каталоге с назван ием P i c ture s , тек
стовые файлы можно хран ить в каталоге Text s , и так далее . Основные
операции с каталогам и состоят в их создан ии с каки м и -либо и м енам и в
каком -либо месте фа й лово й структуры и переименовании . Также и нте
ресна операция изменения текущего каталога, из которого читаются и в
кото р ы й записы ваются файлы с относительными именам и (не включаю
щими название логического диска и полны й путь) .
Создание каталога
Создание каталогов на диске производится оператором МkDir (англ . Make
Directory - создать каталог) , имеющим следующи й вид:
МkDi r ( <Имя к а т ал о г а > ) ;
Параметр Имя ка'I'алоrа является строкавой перемен но й или констан
то й , содержащей н азван ие каталога по правилам , аналоги ч н ым именам
файлов . Если задается пол ное н азван ие каталога, то он появляется на
диске . Возможно задание относительного названия каталога. При попытке
создания уже существующего каталога и нформация в нем не стирается ,
а выдается ош и бка в р емени выполнения програм м ы Error s : F i l e
acce ss denied - Ош и бка 5 : Запрещен доступ к файлу.
Удаление каталога
Удаление катало го в н а диске производится операторо м RmDi r (англ .
Remove Directory - удалить каталог) , и меющим следующи й вид:
RmDir ( <Имя к а т а л о г а > ) ;
Удаление возможно только для каталого в, которые не содержат файлов
или подкаталогов .
П ереименование каталога
Специальной процедуры для переименования каталогов не существует,
однако можно написать свою процедуру для переи менования каталога,
состоящую из двух часте й :
1 . Удален и е каталога .
2 . Создание каталога с н овым им е н е м .
Изменение те кущего каталога
Для изменения текущего каталога - каталога, относительн о которого
рассматриваются относительн ые имена файлов и каталогов - использу
ется процедура ChDir (англ . Change Directory - изменить каталог) :
ChDi r ( <Имя к а т алог а > ) ;
399
Turbo Pascal 7 . 0
1 1 .9.5.
Поиск файлов
Одной и з часто решаемых задач п р и работе с файловой системой является
поиск файлов. В Turbo Pascal для этого предназначена пара функций:
Find.First (от англ . Find First - найти первый) и FindNext (англ . Find
Next - найти следующий) , н аходя щиеся в стандартном модуле WinDo s .
Поиск файлов основывается н а сканировани и каталога с целью поиска
файла, имя которого соответствует так называемой м аске . М аска, поми
мо о быч ных символов, может включать символ *, означающий , что на
дан ном месте и мени файла может присутство вать лю б ое сочетан ие сим
волов, и символ ? , озн ачающи й , что на данной п ози ци и и м е н и файла
может п рисутствовать любой сим вол .
Например, текущим является каталог с : \ MyProgs , содержащий следую
щие файлы : 1 . tx , 2 . tx t , 1 2 . txt , 2 . pa s , З . ра s , 3 4 . pa s .
Тогда маске * . * соответствуют все файлы , так как о н а задает любое со
четание символов в имени и любое сочетан ие символов в расш ирени и .
М аске 1 * . * соответствуют файлы 1 . txt и 1 2 . txt , которые нач и нают
ся с символа 1 , и меют любое сочетание символов после него и любое рас
ш ирение. М аске 1 ? . * соответствует только оди н файл - 1 2 . txt как со
стоящи й из двух с и мволов
1 и любого другого . Соответственно , маске
* . z z z не соответствует н и одного файла, так как файлов с таким рас
ширением в каталоге нет.
-
Сканирование катал ога происходит следующим образом :
1 . Процедура FindFir s t ищет первый файл , и мя которого соответ
ствует маске:
FindFirst ( <M a c кa > , < Фл а ги поиска > ,
< При емник информации о н а йде н ном ф а йл е > ) ;
Параметр Маска является строковой переменной или константой и за
дает маску, которой должны соответствовать имена найденных файлов.
Параметр Флаги поиска определяет ти пы файлов , которые рассмат
ри ваются п р и поиске, и я вляется н абором специаль н ых констант,
объединенн ых бинарным оператором OR:
Таблица 7
Флаги поиска файлов
Флаг
Тип файл а
faReadOnly
Ис кат ь фа йл ы с атр и бутом •То л ь ко для чте н и я •
Ис кат ь фа йл ы с атр и буто м • Скр ыты й•
Ис кат ь фа йл ы с атр и буто м •Сис те мны й•
В озврат и т ь иде нт ифи катор но си тел я
В оз в ращат ь и н формац и ю о на й де н н ы х катал о гах
Ис кат ь фа йл ы с атр и бутом •А рхивны й•
Ис кат ь фа йл ы с атр и буто м
fa H idden
faSysFile
faVo l u m e l d
faDi rectory
faArchive
faAnyFile
400
Глава 1 1 . И спол ьзование файлов
Параметр Приемник информации о найденном ф айле представля
ет собой переме н ную сложного типа TsearchRe c , описанную в мо
дуле WinDos следующим образом :
Туре
TSearchRec = Record
F i l l : Array [ 1
21]
•
•
At t r : Byte ;
Time : Longint ;
S i z e : Longint ;
Name : Array [ 0 , , 1 2 ]
{ з а г ол о в о к о п и с а ни я т и п а д а н ных }
Byt e ; { з а р е з е р в ир о в а н о и
не и с п ол ь з уе т с я }
{ а трибуты найденного файла
( см . т а бл . 5 ) }
{ в р емя с о з д а н и я ф а й л а }
{ р а змер ф а йл а }
Of Cha r ; { имя н а йд е н н о г о ф а й л а }
Of
end ;
2 . В гл обальной целочисленной переменной DosError модуля WinDos
н аходится результат выпол н е н ия операц и и п оиска файла. Если дан
н ая переменная и меет значение О , то поиск п роизведен успешно и
можно производить поиск следующего файла. Если же значение
данной переменной н е нулевое, то файл н е найден и дальнейшее
продолжен и е поиска бесполезно .
3 . Процедура F indNext и щет следующий фай л, соответствующий ус
л о в и я м п о и с ка , з ада н н ы м п р и п оследн е м в ы з о в е п р оцедуры
FindFir s t :
FindNехt ( < При емник инф орма ции о н а й д е н н о м ф а й л е > ) ;
В качестве примера поиска файлов напишем программу, осуществляю
щую поиск файлов в текущем каталоге , имеющих расширение pa s , и вы
ч исление их суммарного размера (см. листин г 2 1 4) .
Program FindP rograms ;
Uses
CRT , WinDo s ;
Var
Found : TSearchRec ;
Al l S i z e : Word ;
Begin
ClrScr;
All S i z e : = О ;
{ о б нул е н и е суммарн о г о о бъема ф а й л о в }
FindF i r s t ( ' * . pas • , faAnyF i l e , Found ) ;
{ п о и с к п е р в о г о файл а , имя к о т о р о г о с о о т в е т с т в у е т
ма с к е * . pas ( любое и м я и р а сшир е н и е pa s ) ,
р а с сма три в аю т с я в с е файлы , р е зул ь т а т п о и с к а
п омеща е т с я в п е р еме нную Found }
40 1
Turbo Pascal 7 . 0
Whi l e DosError
О Do
{ п о к а п е р е ме н н а я DosError , с о д е ржаща я р е з ул ь т а т
п о и с к а , име е т нул е в о е з н а ч е ни е ( т о е с т ь п о с л е д
н я я о п е рация п о и с к а пр о в е д е н а у с п е ш н о ) , п р о д о л
ж а т ь п о и с к о ч е р е дных файл о в , с о о т в е т с т вующих
з а д а н ным у сл о в и ям }
=
begin
Wri t eLn ( Found . Name ) ;
{ вывод име ни файл а , н а й д е н н о г о п о сл е д н е й
п р о ц едур о й п о и с к а }
Al l S i z e : = Al l S i z e + Found . S i z e ;
{ ув е лич е н и е з н а ч е н и я п е реме н н о й , с о д е ржащей
суммарный о бъем н а й д е н ных файл о в , н а р а змер
файла , н а й д е н н о г о в п о сл е дний р а з }
FindNext ( F01Шd) ; { п о и с к сле дующе го файла с теми же
п а р аме т р ами и п омеще ние р е зул ь т а т о в
в п е р еме нную Found }
поиска
end ;
Wr i t eLn ( Al l S i z e ) ;
{ выв о д
сумма р н о г о
о бъема
файлов
на
э кр а н }
End .
Контрол ьные воп ро с ы и ответы
Ч т о п р едста вл яет с о б о й файл?
Для сохра н е н и я и н формации на дисковых н осител ях и с пол ьзуются ф а й
лы
поиме нован ные области диска, доступ к которым осуществляется как
к последовател ьности эл ем ентов н е которого ти па. Доступ к файлам н е я в
ляется и нде ксирова н н ы м , к а к к масси вам , одн ако существует м н ожество
вспомогател ьных операци й , таких как оп редел е н и е разм ера файла и п о
з и цио н и рован ие внутри него .
-
Какие б ы вают файлы?
Файлы делятся н а тексто вые, двоичные типизированные и дво и ч н ы е
нети п и з и рова н н ы е . В зависимости о т ти п а ф а й л а испол ьзуются разл и ч
н ы е методы доступа к и н формаци и , хран и м о й в н е м . Для тексто вых ф а й
лов до пустимы о п ерации чте н и я и л и зап и с и , а также добавл е н и я строк в
конец файла. Для дво и ч н ых файло в до пусти м ы операции одн овремен н ого
чтения и зап и с и , а также изменения те кущего элемента.
Какие п р о цедуры Turbo Pascal используются
для о п е р а ц и й открытия и закрытия файла?
П е ред испол ьзованием файлов дл я чтения и л и записи их нео бходи м о от
крыть с помощью процедур соответстве н н о Reset (Аррепd) или Rewrite .
П осле чте н и я из файла или записи в него файл необходимо з а крыть с
помощью про цедуры Clos e .
402
Глава 1 1 . Испол ьзовани е ф айлов
Ка кие п р о цедур ы испол ьзуются
дл я чте н и я информации из файлов разных типов?
Дл я чте н и я и н формаци и из файлов дл я текстовых файлов испол ьзуются
п р о цедуры Read и ReadLn , для дво и ч н ых т и п и з и рован н ых - процедура
R ea d , а дл я дво и ч н ых нети пизи рован н ых - процедура BlockR e a d .
Какие про цедуры испол ьзуются
дл я з а п и с и и нф о р м а ци и в файлы разных типов?
Дл я записи и н фо р мации в файл для текстовых файлов и с п ол ьзуются п р о
цедуры Write и WriteLn, для двоичных ти пизирован н ых - процедура Write ,
а для дво и ч н ых н ети пизирован н ых - процедура BlockWrite .
Какие процедуры п редусмотрены в Turbo Pascal
для операций с катало гами?
Дл я о р ган изации удо б н о й ие рархической структур ы файлов испол ьзуются
каталоги файловой систе м ы . Операци и , выполняемые с каталогам и , вклю
чают их создание ( п роцедура M kDi r) , удаление ( п роцедура R m D i r) и из
м е н е н и е текущего катало га - каталога, отн осител ьно кото рого указыва
ются пути к файл а м , имя которых задано не полн ость ю .
403
�rп а в а
Turbo P a s c a l 7 . О
О р г ан и з а ц и я
хра н е н и я и н фо р м аци и .
О с н о в ы С УБД
1 2 . 1 . Д и н а м и ч ес к ие с тр укту р ы д а н н ы х
При решении практически любых задач а в томатизаци и и модел ирования
в стает проблема получения, сохранения (накопле н ия) и представления ин
форма ц и и , с в о й ств енно й решаемо й задаче . Н апример, при автом атиза
ци и б ухгалтерского учета информация о п еремещении денежных средст в
и других акти в о в предприятия за некоторы й период в ремени должна хра
нит ьс я каки м-либо о бразом и б ыт ь доступна для просмотра бухгалтеру
или директору предприятия, а также подда в ать ся обработке автоматизи
рующе й программ о й с цел ь ю соста вления отчетн о й документаци и .
Объем информаци и в таких системах заранее неиз в есте н , что в ызы в ает
определенные трудности при оп исан и и структур дан н ых в программе .
Предста в и м себе программу для вв ода, хранения и выдач и списка работ
ников некоторо й организаци и и их телефоно в . Допустим , в этой органи
зации работает д в адцат ь сотрудни ков, кажды й из которых имеет по два
телефона - домашни й и мобил ь ны й . Т огда для работы с д анн ы ми о б
одном чело в еке нео б ходимо описать зап ис ь следующего в ида :
{ р а здел
Туре
THuman
Name :
=
Record
St ring ;
Patronymic :
SurName :
St ring ;
Array [ 1
Mobi leTel :
end ;
404
{ п оле
хр а н е ни я
{ п оле
•
•
типов
типа
String ; { п оле
HomeTel :
описания
{ о п и с а ни е
дл я
д а нных
дл я х р а н е н и я
для х р а н е н и я
7 ] Of Char ;
{ п оле для х р а н е н и я
с о трудни к а }
име ни
с о труд ни к а }
о т ч е с т в а с о труд н и к а }
ф амилии с о трудни к а }
домашн е г о
Array [ 1 7 ] Of Cha r ;
{ п о л е дл я х р а н е ни я мо бил ь н о г о
•
д а н ных }
запись }
телефона
•
{ окончание
о п и с а ни я
типа
т е л е ф о н а с о т р у д ни к а }
д а н ных }
Глава 1 2 . Организация хранен и я информаци и . Основ ы СУБД
Для хранен ия всего списка сотрудни ков необходимо описать следующую
структуру данных:
Var
{ р а здел
Humans :
Array [ 1
•
оnисания
п е р еме н ных }
2 0 ] Of THuman ;
{ о n и с а н и е n е р еме н н о й - ма с си в а
элеме н т о в тиnа THuman }
•
из
д в а дц а т и
Такая структура дан ных впол не удовлетворительна для одной организа
ци и , в которой никогда не будет работать более двадцати человек. Одна
ко заранее не может быть известн о , каким образом организация будет
развиваться и сколько сотрудни ков будет в ней через некоторое время.
В случае разработки программы для нескольких орган изаций вообще не
известно точное кол ичество работников. Для решения появившейся про
блем ы можно описать м аксим ально возможную структуру дан ных:
Va r
Humans :
Array [ 1
•
•
82]
Of ТНuman;
{ р а з д ел о n и с а н и я п е р ем е н ных }
{ оnисание nереме нной - массив а }
Несмотря на то что такой объем массива все равно не подходит для некото
рых организаций , его описание не позволит хранить в программе какие-либо
другие данные, которые также могут требовать большого количества памяти.
Ра бота со списком сотрудников - это не един ственное, что требуется от
системы автом атизации производства. Например, необходимо еще и хра
нение и н формации об и меющихся транспортн ых средствах. Приведем
описание записи, в которой может храниться информация об одном транс
портном средстве.
{ р а з д е л о n и с а н и я т и n о в д а н ных }
{ о n и с а н и е тиnа д а н ных з а nи с ь }
Name : String ;
{ поле для хранения марки трансnортного средств а }
NwDЬer : Array [ 1 12 ] Of Char ;
{ n о л е для х р а н е н и я г о судар с т в е н н о г о }
{ р е ги с тр а ци о н н о г о н о ме р а }
Year : Intege r ;
{ n оле д л я х р а н е н и я г о д а выnус к а }
Тур е
TCar
=
Record
•
•
{ окончание
end ;
о n и с а ни я
тиnа
д а н ных }
И , соответственно, структура памяти для хранения дан н ы х о нескольких
транспортн ых средствах:
Va r
Cars :
Array [ 1
•
•
10]
Of
TCar ;
{ р а зд е л о n и с а н и я n е р еме н ных }
{ о n и с а н и е n е р е ме н н о й - ма с си в а
и з д е с яти э л е ме н т о в т и n а TCar }
При описан и и массива Humans и м ассива Cars одновременно появляет
ся вопрос: в каком соотношении поделить оперативную память м ежду
эти м и двумя м ассива м и , то есть сколько элементов должен содержать
каждый из этих массивов. Для предприятий разного проф иля соотноше
ние кол ичеств элементов будет существенно различ аться .
405
Turbo Pascal 7 . 0
Решение описанной проблем ы состоит в использовани и ди намических,
располагаемых в Н еар-памяти переменных вместо статических, распола
гаемых в сегменте данных програм мы (описы ваемых в разделе оп исания
переменных var) . Подробное описан ие динамических структур выходит
за пределы наш ей книги , однако мы познаком имся с простей шими ди
намически ми структурами, которые, впрочем, нередко используются и для
создания промы шлен ных программ ных продукто в.
1 2. 1 . 1 .
Ди намические массивы
Массивы дина мически расп ределяемых элементов
М ассив ди н а м и ч ески распределяемых эле ме нтов представля ет соб ой
массив, кажды м элементом которого является типизирован н ый указатель
на ка кую - л и б о п е р е м е н ную , н аходя щуюся в д и н а м и ч ес к о й п амяти
(см . р ис. 1 3 7 ) . В сегменте дан ных такая структура зан имает п амять объе
мом , равны м произведению количества элементов массива на 4 (объем
памяти , необходимы й для хранения типизированного указателя ) .
Объем динамической Неар-памяти , занимаемый таки ми структурами дан
ных, в начале работы программ ы равен н улю и далее растет п о мере вы
деления памяти под тип изированные указатели , я вляющиеся элементам и
массива. Использован ие массивов такого рода рассмотрено в разделе Мас
сивы указателей и продемонстрировано программой Monkey2 (см . листин г
1 84) то го же раздел а.
- масси в
Сегмен т дан н ых
Неар · nам я ть
Рис.
1 3 7. Переменная-массив указа телей ссылается
на о бла сти Неар-памяти
Работа с масси вами динамически распределяемых элементов достаточ но
удобна и помогает решит ь проблему недостаточности размера сегмента
данн ых, но не во всех случаях, так как сами массивы также занимают
довольно много места.
Д и н а м ически расп ределяемые м ассивы
Динамически распределяемый массив представляет собой п ерем ен ную
т и п и з и ро ван н ы й указател ь на м ас� и в эл е менто в н е обход и м о го ти п а
(см . рис . 1 3 8 ) . Возвращаясь к при меру со списком сотрудников, описа
ние такой структуры данных может вы глядеть следующи м образо м .
406
Глава 1 2 . Органи з ация хранен и я информаци и . Основы СУБД
Се г мен т да н н ых
Неа р- память
Рис.
1 38. Переменная·типизированный указа тель ссылается на массив,
размещенный в динамической памяти
{ р а здел
Туре
THuman
Name :
о п и с а ни я
типов
д а н ных }
{ о п и с а н и е типа д а н ных з а п и с ь для
с в е де ний о б о д н ом с о трудни к е }
Record
=
хра н е ни я
St ring ;
Pat ronymi c :
String ;
SurName :
S t ring ;
HomeTe l :
Array [ 1
Mob i l eTel :
.
.
Array [ 1
7]
.
.
Of
7]
Char ;
Of
Char ;
end ;
THumans
PHumans
Array [ l
=
=
.
8 0 ] Of THuman ;
{ о п и с а н и е типа д а н ных
т и п а THuman }
.
AТНumans ; { о п и с а н и е
ука з а т е л я
{ р а здел
Va r
Humans :
PHumans ;
э л е ме н т о в
т и п а д а н ных - т и п и з ир о в а н н о г о
н а ма с с и в элеме н т о в т и п а Thuman }
описания
{ описание
ука з а т е л я
ма с си в а
п е ремен ных }
п ереме н н о й - т и п и з ир о в а н н о г о
н а ма с с и в з а п и с е й т и п а THuman }
Далее необходимо выделить место в Н еар - п амяти под перемен ную
ти пизированн ый указатель. Это можно сделать вызовом процедуры New,
рассмотренной нами при изучении тип изированных указателей . Освобож
дение памяти в таком случае следует произвести процедурой Di spo se
(см . листинг 2 1 5 ) .
Туре
THuman
Name :
=
Record
String ;
Pat ronymi c :
String ;
SurName :
St ring ;
HomeTe l :
Array [ 1
Mob i l eTe l :
.
.
Array [ 1
7]
.
.
Of
7]
Char ;
Of
Cha r ;
end ;
407
Turbo Pascal 7 . 0
THumans
=
Array [ 1
PHumans
=
A THumans ;
•
•
82 ]
Of THuman ;
Var
Humans :
PHumans ;
Begin
New ( Humans ) ;
Humans А [ 3 О ] Name
•
: =
{ выде л е н и е динами ч е с к ой памяти п о д т и п и з и
р о в а н ный ук а з а т е л ь Human s ; р а змер выд е л я емой
п амяти р а в е н р а змеру ма с с и в а 8 2 - х э л еме н т о в
т и п а THuman }
' Валентин ' ;
Humans A [ 3 0 ] . Pat ronymic
Humans А [ 3 О ]
•
SurName
Dispose ( Human s ) ;
: =
' Викторович • ;
: = ' Осколков ' ;
{ о бр а ще н и е к з а пи с и ма с с и в а , н а к о т о рый
с сыл а е т с я типизир о в а н ный ука з а т е л ь Humans ;
и с п о л ь зуе т с я з а п и с ь с и н д е к с ом 3 О }
{ о с в о б ожде н и е памяти , выд е л е н н о й п о д п е р еме н ную
Humans ; о с в о б ожда е т с я в с я з а н я т а я памя т ь }
End .
Останови мся подробнее на обращении к элементам динам ически распре
деляемых массивов. Переменная Human s представляет собой тип изиро
ванны й указатель н а массив записей . Указание оператора разы меновы
ван ия п осл е и м е н и дан но й перемен ной указы вает н а н еобходи м ость
обращения к самому массиву: нuman s А . Указан и е и ндекса эле м е нта в
квадратных скобках показы вает необходимость обращен ия к элементу с
данн ы м индексом : Humans A [ 3 0 ] .
Описан ная структура зан имает в сегменте данн ы х всего четыре байта
( од и н т и п и з и р о в ан н ы й указател ь ) , а в ди н а м и ч е с ко й п а м я ти
82*782 = 64 1 24 байтов (размер записи типа тнuman составляет 7 8 2 бай
т а, м а ссив содержит 8 2 таких зап иси) . Т аким образом , при размещении
структуры тнuman s в сегменте дан н ых памяти на другие пере м е н н ы е
практически не остается , что решается размеще н и е м такой ж е структу
ры в динамическо й Н еар- памяти , размер которой знач ительно больш е
(почти в десять раз) .
-
Эффект и сп ол ьзо в ания динам ически распределя е м ых массивов мож
н о знач ительно усилить , выделяя место в динамической п амяти н е под
весь масс и в , а толь ко под его часть. Измен и м предыдущий п р и м е р так,
чтоб ы в Н еар - п амяти в ыделялось место тол ько под 3 0 эле ме нтов мас
сива. Для этого воспользуемся при выделе н и и памяти н е процедурой
New, а процедурой GetMem, рассм отре н ной н ам и п р и изучен и и н ети
пизированных указателей . Соответствен н о , освобожде н и е в ыдел е н н о й
п амяти буде м осуществлять н е про цедурой Di spo s e , а п р о ц едуро й
FreeMem (см . л исти н г 2 1 6) .
408
Глава 1 2 . Организация хранения информаци и . Основы СУБД
.;·�t �с:-rи.�г·· 2 1.�:;··и§�()�ь�р·��[��:·:·'��Н!��А·�я��:;:р·а86'р�]:(���-�,�-ьi*'�.�������:}�
Туре
THwnan = Record
Name : St ring ;
Patronymi c : String ;
SurName : S t ring ;
HomeTe l : Array [ 1 7 ] Of Char ;
Mobi leTel : Array [ 1 7 ] Of Char ;
end ;
THwnans = Array [ l 8 2 ] Of THuman ;
PHumans = A THumans ;
Va r
Hwnans : PHwnans ;
Begin
GetMem ( Hwnans , 30 * S i zeOf ( THuman ) ) ;
{ выде л е ни е дин амич е с к о й п а мя т и п о д типизир о в а н ный ук а з а т ел ь
Humans с п омощь ю п ро ц едуры Ge tMem ; в к а ч е с т в е р а з ме р а
выд е л я емой п амяти и с п ол ь зуе т с я прои з в е д е н и е колич е с т в а
з а п и с е й , к о т орые п р е д п ол а г а е т с я х р а н и т ь в Неар - п амя т и ,
на р а змер о д н о й з а пи с и , о п р е д е л я емой фун кци е й S i z eO f }
Hwnans А [ 3 О ] Name : = ' Валентин ' ;
Humans A [ 3 0 ] . Pat ronymic : = ' Викторович ' ;
Hwnans А [ 3 О ] SurName : = ' Осколков ' ;
{ о бр аще н и е к з а п и с и масси в а , на к о т о рый с сыл а е т с я т и пи з и
р о в а н ный ука з а т е л ь Humans ; и с п ол ь зуе т с я з а п и с ь с и н д е к с ом 3 О }
FreeМem ( Нumans , 3 0 * Si zeOf ( ТНuman ) ) ;
{ о свобожде ние памяти , выделенной под переменную Humans ;
освобожда е т с я п амя ть р а змером , равным ра змеру выдел е н н ой п амяти }
End .
•
•
•
•
•
•
•
•
Таким же образом можно выдел ить память для колич ества элементов ,
введенных пользователем ил и храня щ ихся в файле настроек , то есть п р о
грамма получает гибкость и становится нетребовател ьной к ресурсам ком
п ьютера (точнее , испол ьзует столько ресурсов , сколько е й действительно
необходимо для ра боты) .
За исключением методов выделения и освобождения памяти , а также обраще
ния к элементам динамически распределя ем ых массивов , работа с ними н и
чем не отличается от использования обычн ых статических массивов , описан
ных в разделе описания переменных и располагающихся в сегменте данных.
1 2. 1 .2.
Списки
П онятие списка и его о ргани зация
К ажды й иденти ф икатор в програм ме и меет область видимости
часть
про граммы , в которой допустимо использование дан ного идентификато
ра . Область видимости идентификатора начи н ается с момента оп исания
-
409
Turbo Pascal
7.0
идентификатора и заканчи вается в конце программ ы (для глобальных
идентификаторов) или в конце процедуры или фун кци и , в которых они
оп исаны (для локал ьных идентификаторов) .
Единствен н ы м исключением является возможность использования зап и
сей для определения ссылочного типа н а их основе. То есть оп исание типа
данных, ссылающегося на запись, возможно до описания самого типа дан
ных <<Запись» . Рассмотрим пример.
Ту ре
{ р а здел о п и с а ни я т и п о в д а н ных }
{ описание типа данных - типизированного указателя
н а з а п и с ь т и п а TRe c ; о п и с а н и е т и п а д а н ных TRec
р а с п о л а г а е т с я ниже }
PRec
=
A TRec ;
TRec
=
Record { з а г о л о в о к
. . . . . . . . . . .
{ описание
{ о ко н ч а н и е
end ;
о пи с а ни я
п ол е й
типа
з а писи
о пи с а ни я
д а н ных
TRe c }
TRec }
типа
д а н ных
TRec }
В приведеином примере область видимости идентификатора PRec н ач и
нается с момента его описания и заканч ивается в конце програм м ы . Т а
ким образом , возможно оп исание поля записи TRe c , имеющего тип PRe c ,
т о есть запись может ссылаться одн им или нескольки м и сво и м и поля ми
на зап иси такого ж е тип а, в то м числе и на себя .
{ р а здел о пи с а н и я т и п о в д а н ных }
{ о п и с а н и е типа д а н ных - типизиро в а н н о г о
ука з а т е л я на з а п и с ь т и п а TRe c ; о п и с а н и е т и п а
д а н ных T R e c р а с п о л а г а е т с я ниже }
TRec = Record { з а г о л о в о к о пи с а ни я т и п а д а н ных TRec }
Next : PRec ; { о п и с а н и е п о л я т и п а PRec - типизир о в а н н о г о
ука з а т ел я на з а п и с ь т и п а TRe c }
{ о п и с а н и е информа тив ных п о л е й з а п и с и TRec }
end ;
{ о ко н ч а н и е о пи с а ни я т и п а д а н ных TRec }
Туре
PRec
•
A TRec ;
=
•
•
•
•
•
•
•
•
•
•
Рассмотренная возможность позволяет создавать структуры данн ых, на
зываем ые списками - последовательности записей , расположенных в ди
нам ической памяти и ссылающихся друг на друга (см . рис. 1 3 9 ) . Н а пер-
Сег м е нт дан н ы х
Рис.
1 39. Динамическая структура данных « Сnисок"
ра сполагается в динамической памяти
41 0
Глава 1 2 . Организация хранен и я информаци и . Основы СУБД
вую зап ись списка ссылается типизированный указатель , расположенный
в сегменте данных (описанн ы й в разделе описания переменных var) . Пос
ледняя зап ись н е ссылается н и на какую другую .
П роцесс созда н и я с пис ка
Рассмотри м процесс создания списка.
1 . Опи сание типа данных «Запись» , содержащего и нформативные п оля
для хранен ия и нформации , предназначенно й для хранения в каж
дой записи , и одно поле - типизирован н ый указатель на такую же
запись.
Туре
PRec
=
TRec
=
лтR е с ;
Record
{ описание
указ а т ел я
п о л я типа PRec - типизир о в а н н о г о
на з а п и с ь т и п а TRe c }
Next :
PRec ;
Name :
String ; { описание информационного ( предна значенного для
х р а н е н и я информации ) п ол я }
end ;
В п р и веде и ном описании информ ац ио н н ы м п олем я вляется поле
Name типа S t r i ng, а полем-указателем на следую щую зап и сь - поле
Next типа PRec .
2. Оп и сание п ерем енной ти пизирован ного указателя - в разделе о п и
сани я п ереме н н ых var . При этом память под данн ый указател ь н е
выделяется и о н н е ссыл ается на какую-ли бо запи с ь (см. рис . 1 40) .
Туре
PRec
TRec
лтR е с ;
Record
=
=
Next :
PRec ;
Name :
String ;
С е см е "'
Рис.
end ;
I I III I I J 1 1 1 1
'?
1 40. Под указа тель
не выделена память
Va r
First :
да " " " '
PRec; { о пи с а ние
переме нной
типизир о в а н н о г о ука з а т еля }
3 . В ыделен и е п амяти п од перемен ную-указател ь , находящуюся в сег
менте данных, в результате чего в ди намической п амяти резервиру
ется место п од одну запись типа
TRec . Поле Next данной зап иси
не ссылается на какую-либо за Сегмент дан н ых
пись , и нформационное п оле так
же не и меет какого-л ибо опреде
лен ного значен ия (см . рис. 1 4 1 ) .
Рис.
1 4 1 . Под переменную указатель
выделена динамическая память
41 1
Tu rbo Pascal 7 . 0
Тур е
PRec
=
TRe c
=
л тR е с ;
Record
Next :
PRec ;
Name :
String ;
end ;
Var
PRec ; { о пи сание
First :
переме нной
типизир о в а н н о г о ука з а теля }
Begin
{ выде л е н и е
New ( Fi r s t ) ;
п амяти
под
п е р еме нную-ук а з а т е л ь }
End .
4. Посл е выделения памяти с записью, на которую указы вает пере
менная - указатель , можно выполнять л юбы е де й ствия , например
измен ять значения ее полей (см . рис. 1 42) .
Тур е
PRec
=
TRec
=
лтRе с ;
Record
Сегме нт данных
Next :
PRec ;
Name :
String ;
end;
Var
First :
PRec ;
Рис. 1 42. Изменение зна чения
информационного поля первой записи списка
Begin
New ( Fi r s t ) ;
Firstл ,Nallle
' 795FТ+ ' ; { изменение значе ния информационного поля }
:=
End .
Кроме изменения значений информационных полей , также можно
работать и с полем-ссылко й на следующую запись, например вьще
лять память под дан ный указатель.
Тур е
PRec
=
лтRес ;
TRec
=
Record
Next :
PRec ;
Name :
String ;
end ;
Var
First :
PRec ;
Begin
New ( Fi r s t ) ;
First л . Name
:=
' 7 9 5FT + ' ;
New ( Firstл . Next ) ; { выделение динамической памяти под поле -указатель }
End .
41 2
Глава 1 2 . Орган изация хранения информаци и . Основы СУБД
В результате выделения памяти ПОД ПОЛе-указатеЛЬ В Сегмент данн ых
динамической памяти будет
зарезе р в и р о в а н о м е сто
р а з м е р о м , н е о б х од и м ы м
для хранения одной зап иси
типа TRec . Поле Next этой
записи будет указы вать на
Рис. 1 43. Изменение зна чения инфорвновь расп ределен ную замационного поля первой записи списка
пись (см . рис . 1 43 ) . Данная
зап ись будет являться второй записью списка. При этом поле Next новой записи не будет ука
зывать на какую -либо запись , и нформационное поле Name также не
и меет какого -либо определенного значени я .
5 . Методы работы со второй зап исью списка стандартны - для н е е
до пусти м ы обыч н ы е операци и с запи ся м и , например изменение
значен и й полей , а также в ыделение памяти п од п оле-указатель на
следующую зап ись (см . рис. 1 44) .
Туре
PRec = "TRec ;
Се г мент да н н ых
TRec = Record
Next : PRec ;
Name : String ;
end;
Var
First : PRec ;
Begin
Рис. 1 44 . Выделение памяти
New ( Fi r s t ) ;
под третий элемент списка
First " . Name : = ' 7 9 5FT+ ' ;
New ( F i r s t " . Next ) ;
F i r st " . Next " . Name : = ' CTXPR7 11 ' ;
{ и зме н е н и е з н а ч е н и я и н ф ормаци о н н о г о п о л я
в т о р о й з а пи с и с п и с к а }
New ( Fi r s t " . Next " . Next ) ;
{ выд ел е н и е дин амич е с кой п амяти п о д
п о л е - ук а з а т е ль в т орой з а пи с и с п и с к а }
End .
Таким же о бразом можно добавить в список четвертый элемент, пятый и
так далее, сколько нео бходимо. Однако обращение к элементам списка че
рез последовательность операторов разыменовывания и ссылочных полей
записей списка неудобно. Упростить процесс доступа к конкретной записи
по ее номеру можно с помощью зацикливания оператора присваивания вида:
<Переме н н а я
типа
PRec>
: =
<Переме н н а я
типа
PRec> " . Next ;
413
Turbo Pascal
7.0
Фун кция , возвращающая ссылку н а запись с заданным номеро м , может
выглядеть следующим образом .
Туре
{ о п и с а н и е т и п о в д а н ных ,
для с о з д а н и я с п и с к а }
PRec = ATRec ;
TRec = Record
Next : PRec ;
Name : St ring ;
end ;
va r
First : PRec ;
{ о п и с а н и е переме н н ой ,
н а начало списка }
н е о бх о димых
с сылающе й с я
Funct ion GetRecPoint er ( RecNum : Integer ) : PRec ;
{ з а г ол о в о к функции ; ц е л о чи с л е н ный п а р ам е т р
о п р е д ел я е т н омер з а писи , с сыл ку н а к о т орую
нужно в е рнуть ; тип в о з вращаемо г о з н а ч е ни я PRec ( с сыл к а н а з а пи с ь TRe c ) }
Va r
{ п ер еме н н а я для и с п ол ь з о в а ни я в к а ч е с т в е
i : Intege r ;
с ч е тчика цикла }
{ п ереме н н а я дл я време н н о г о х р а н е н и я с сылки
tmpRec : PRec ;
на запись }
Begin
tmpRec : = F i r s t ; { п о умолча нию счи т а ем , ч т о в о з в р а ща е т с я
первая запись }
For i : = 2 То RecNum Do
{ ци кл от 2 до н оме р а н е о б х одимой з а п и с и ;
выполн я е т с я RecNum- 1 р а з , ч т о о б е с п е чи в а е т
п е р емеще ние п о с п и с ку о т п е р в о й з аписи , с сыл к а
н а к о торую н а х о ди т с я в п е р еме н н о й tmpRe c , д о
н е о б х о димой , з ад а н н о й п араме т р ом RecNum }
tmpRec : = tmpRec A . Next ;
{ в переменную tmpRec помещаем з а п и с ь , следующую
за той , на которую ука зыв а е т п е р еме н н а я tmpRec
до и зме н е ни я ( н а п е р в ом ш а г е цикл а п е р еме н н а я
tmpRec указыв а е т н а п е р в ую з а п и с ь ) }
GetRecPoint e r : = tmpRec ;
{ в о з в ращаем з н а ч е ни е п е р еме н н о й tmpRec
в ка ч е с т в е з н а ч е н и я фун кци и }
end;
Н а основе функции GetRecPointer строится вся работа со списком . Для
изменения полей любого элемента списка следует получить на него ссылку
и далее изменять поля записи , н а которую указывает полученная ссылка.
Например, для добавления элемента в список следует получить ссылку
на последний элемент, а затем выделить память под его поле Nex t . Для
41 4
Глава 1 2 . Орган изация хранения информаци и . Основы СУБД
удаления последнего элемента списка следует получ ить ссылку на пред
последн ий элемент и освободить память, занятую под его поле Nex t .
Основной ошибкой п р и работе со сп иском является удаление элемента,
который не является последни м , так как в этом случае теряются ссылки
на все оставшиеся элементы , и, следовательно , отсутствует возможность
освободить память , выделенную под элементы списка (см . рис. 1 45 ) .
С егмент д - �
--==:.:.�
.:...о
Неа р- па мять
Рис.
11 jjffiJ I I I I IJ 1
1 45. Некорректное удаление элемента списка
Создание модуля для работы со с п иском
Реализуем модуль , содержащий процедуры и функции для работы со
списком . Вызывающая програм ма должна описать для поддержания списка
две переменные - указатель на начало списка и целочисленную пере
менную для хранения текущей длины списка. Эти переменные б удут п е
редаваться процедурам и функциям м одуля в качестве парам етров. Опи
шем структуру м одуля .
l . Для создан ия сп и ска и спользуются зап ис и для хранен ия и н форм а
ции об и м ен и , отчестве и фамили и сотрудника , а также его телефо
не . О п и сани е зап иси им еет следующий вид:
Ту ре
PLi stRec
"TL i s tRec ;
{ о п и с а н и е т и п а д а н ных дл я с сыл о к
н а з а пи с и
и з к о т орых с о с т ои т с п и с о к }
TL i stRec = Record { о п и с а н и е типа д а н ных дл я з а п и с е й
и з к о т орых с о с т о и т с пи с о к }
Name : String ;
{ п оле д л я х р а н е н и я име ни }
Pat ronymi c : St ring ;
{ п оле дл я х р а н е н и я о т ч е с т в а }
SurName : S t ring ;
{ п оле дл я хр а н е н и я ф амилии }
Telephone : St ring [ З O ] ; { п оле для х р а н е н и я т е л е ф о н а }
Next : P L i st Rec ; { п о л е для с сыл ки н а с л е дующую з а п и с ь }
end ;
=
1
1
2 . Процедура C r e a t eL i s t создает сп исок, выделяя п ам ять п од его
первый эл ем ент. Таким образо м , в созданном сп ис ке всегда есть
хотя бы одна зап ись.
Procedure CreateLi st ( var First :
PLi stRec ;
var ListSize :
Integer ) ;
41 5
Turbo Pascal 7 . 0
Параметр F i r s t задает ссылку на начало списка, параметр L i s t si z e
размер списка. Оба параметра являются параметрами-переменными,
так как продедура изменяет их значения - выделяет место под пере
менную F i r s t и заносит единицу в переменную L i s t S i z e .
3 . Функци я GetReoord
возвращает ссылку н а задан н ы й элемент
заданного сп и ска и и меет следующий заголовок:
-
Function GetRecord ( First :
PLi s tRec ;
RecNum :
PLi s tRec ;
Integer) :
Д а н н ая ф у н к ц и я а н ал о г и ч н а р а с с м о т р е н н о й в ы ш е ф у н к ц и и
GetRec Pointer. Параметр F i r s t задает ссылку н а начало списка, па
раметр RecNum - номер запис и , указатель н а которую необходимо
возвратить.
4. Функция AddReoord
добавляет элемент в конец с п иска, п олучая
п оследн ий текущий элемент и в ыделяя память под е го поле Nex t .
-
Procedure AddRecord ( Firs t :
PL i s tRec ;
var L i s t S i z e :
Integer ) ;
П а р а м етр F i r s t задает с с ы л ку н а н ач ал о с п и с к а , п ар а м етр
L i s t S i z e - размер списка. Параметр L i s t S i z e я вляется парамет
ром- переменной , так как его значение изменяется продедурой (уве
личивается на единицу) .
5 . Функция De leteReoord
удаляет последн ий элемент списка, п о
лучая ссылку на предпоследни й текущи й элемент и освобождая
п амять, выделенную п од его поле Nex t .
-
Procedure DeleteRecord ( Firs t :
PLi stRec ; va r ListS i z e :
Integer) ;
П а р а м етр F i r s t задает с с ыл ку н а н а ч а л о с п и с к а , п ар а м етр
L i s t S i z e - размер списка. Параметр L i s t S i z e я вляется парамет
ром -перемен ной , так как его значение изменяется продедурой (уве
личи вается на единицу) .
6 . Продедура De stroyL i s t удаляет список из п амяти , п оследовател ь
но удаляя е го п оследние элементы. После удале н ия всех элементов
с номерами бол ьшими единицы , освобождается память, в ыделе н
ная п од переменную F i r s t .
Procedure DestroyLis t (var First :
PListRec ; var ListSi ze :
Integer) ;
Текст модуля представлен в листинге 2 1 7 .
ж\f�i ;�:r�Нf�·��.l:.���е�х���:±ь:�,Р.� эхщщ:�����:�!У�:��·L9���:�·�:мж;,·�1;;:;;;;,�:� :;,:�;;·;н:;r[[i:
··
Uni t
List ;
{ з а г о л о в о к модул я ,
Interface
{ начало
Туре
{ описа ние типов
с о с п и с к ами }
41 6
н а з в а ни е
интерфейсной
мо дул я
-
List }
с е кции }
дан ных ,
н е о бх одимых
для
работы
Глава 1 2 . Организация хранен и я информаци и . Основы СУБД
PLi s tRec
=
TLi s tRec
=
Name :
лтL i stRec ;
Record
String ;
Patronyшi c :
SurName :
Tel ephone :
Next :
String ;
S t ring ;
String [ З O ] ;
PLi stRec ;
end;
Funct ion
GetRecord ( Fi r s t : PLi stRec ;
RecNum : Integer ) :
PL i s tRec ;
Procedure
Creat eL i s t ( var First : PLi s tRec ;
var L i s t S i z e : Integer ) ;
Procedure
Dest royL i s t ( var First :
var
Procedure AddRecord ( Fi r s t :
var
Procedure
PLi s t Rec ;
Li s t Si z e :
Integer ) ;
PLi s tRec ;
ListSize :
Delet eRecord ( Fi r s t :
Integer ) ;
PLi stRec ;
var Li s t S i z e : Integer ) ;
{ з а г ол о в ки п р о ц е дур и функций , к о т о рые могут
и с п о л ь з о в а т ь с я вызыв ающими п р о г р аммами }
I:ш.p l e:ш.ent at i on
{ начало
о пи с а т ел ь н о й
Procedure CreateList ; { о пи с а ни е
с е кции }
п р о ц е дуры C r e a t eL i s t }
begin
New ( F i r s t ) ;
ListSize
:=
1;
{ выд е л е н и е
п амяти
{ ус т а н о в к а
р а зме р а
п о д п е р в ую з а пи с ь
списка }
списка }
end;
Func t i on GetRecord; { о п и с а н и е
фун кции G e t Re c ord }
Var
i:
Integer ;
t:ш.pRec :
PLi stRec ;
begin
t:ш.pRec
For
F i rst ;
: =
i : =2
{ с сыл к а
на
п е р вую з а п и с ь
списка }
То RecNum Do
t:ш.pRec ;
{ смеще н и е
{ ук а з а н и е
по с п и с ку н а одну з а п и с ь }
в о з в р аща емо г о з н а ч е ни я }
Procedure AddRecord;
{ описание
проце дуры AddRe c o r d }
t:ш.pRec
: =
GetRecord
end ;
t:ш.pRec л . Next ;
: =
Var
t:ш.pRec :
PLi stRec ;
begin
t:ш.pRec
14
Зав:. 702
: =
GetRecord ( Fi r s t , L i s t s i z e ) ;
{ п олуч е н и е с сыл ки н а
п о сл е днюю
запись }
41 7
Turbo Pascal
7.0
new ( tmpRec " . Next ) ;
ListSize
: =
{ выде л е н и е памяти п о д п о л е - с сыл ку п о сл е д н е й
з а п и с и 1 т о е с т ь д о б а в л е н и е к с п и ску еще
о д н о г о элеме н т а }
ListSize + 1 ;
{ ув елич е н и е р а зме р а с п и с к а н а е ди ницу }
end ;
Proc edure
De l e t eRe cord ; { о пи с а ни е
п р о ц е дуры D e l e t eRecord }
Var
tmpRec :
PLi s tRec ;
beg in
tmpRec
: =
GetRecord ( First , L i s t S i z e - 1 ) ;
{ п олуч е н и е с сыл ки н а
п р е д п о с л е днюю з а п и с ь }
Dispo s e ( tmpRec " . Next ) ;
{ о с в о б ожд е н и е п амяти 1 выд е л е н н о й п о д
п о л е - с сыл ку пр е д п о сл е д н е й з а п и с и 1 т о е с т ь
уда л е н и е п о сл е д н е й з а п и с и с п и с к а }
List Size
: =
ListSize
1;
{ уме н ь ше н и е
-
tmpRec " . Next
ра зме р а
ni l ;
{ о б н ул е н и е ука з а т е л я
не выд е л е н а памя т ь }
: =
списка }
1
под
к о т о рый
end ;
Procedure
De s t royL i s t ;
{ описание
п р о ц е дуры De s t r o yL i s t }
Var
tmpRec :
P L i s t Rec ;
begin
Whi l e L i s t S i z e
>
1 Do
{ усл о в ный ци кл ; усл о в и е п р о д о л ж е н и я
в с п и с к е н а х о ди т с я к а к минимум д в е з а пи с и }
De l e t eRecord ( Fi r s t ,
Listsize ) ;
{ удаление п о сл е д н е й з а п и си с п и с к а с п омощь ю
процедуры D e l e t eRecord э т о г о же модул я }
D i spo s e ( F i r s t ) ;
{ о с в о б о жд е н и е памяти 1 выдел е н н ой п о д п е р е
ме н ную 1 ука зыв ающую на первый элеме нт списка }
List S i z e
: =
{ о б н ул е н и е
First
ni l ;
: =
О;
длины
списка }
{ о бнуление ука за теля
на
первый элемент
списка }
end;
end .
Т аким образом , пять процедур небольшага размера позволяют организо
вать удобную ра б оту с такой сложно й структурой данных, как список.
Рас с м от р и м п ри м е р и с п ол ьзован ия п р и веде и н ого м одуля ( с м . л и с
ти н г 2 1 8 ) . Наша программа будет запраш ивать у пользователя количество
41 8
Глава 1 2 . Организация хранен и я информаци и . Основы СУБД
записей , которые он будет вводить, затем осуществлять ввод и нфо р м а
ции . После окончания ввода всех записей на экран будет выведена вся
введен ная пользователем и нформаци я , затем будет удалена последняя
запись и и нформация будет выведена еще раз. В кон це программы спи
сок будет удален вызовом процедуры Des t royL i s t .
,�;:JI��j�'�Ji':-2'1 a:��:fi'P�i'��'�,��·;�,;��-�����y�Щ��·����;Ц}![�E���i�Гi�i!j�:ii!!(!�o:��:�;���;;·',�:t;\;�3�
Program UseLi s t ;
Uses
CR'l' ,
List ;
{ п одключ е н и е модул е й
CRT и
List }
Va r
L i st l :
PLi s tRec ;
{ переме нная для
List1Si z e :
tmpRec :
Intege r ;
{ п ереме н н а я
ссылки
дл я
на
первую запись
хр а н е ни я р а зм е р а
списка }
списка }
P L i s t Rec ;
{ п ереме н н а я дл я време н н о г о х р а н е н и я с сыл ки н а
к а кую - л и б о з а п и с ь дл я е е в в од а и л и вывода }
� =
Int eger ;
{ п ер е ме н н а я
для
сче тчика
N:
Integer ;
{ п ереме н н а я
дл я
запроса
цикл а }
колич е с т в а
записей }
Begin
C l r S cr ;
Wri t e ( ' Введите размер
сnиска :
');
{ в в од желаемо г о р а зме р а с п и с к а }
ReadLn ( N ) ;
Creat eLi s t ( Li s t l , L i s t 1 S i z e ) ;
{ с о з д а ни е с п и с к а и з о д н о г о элеме н т а }
For i : = 2 'l'o N Do
AddRecord ( L i st l ,
List 1Size ) ;
{ д о б а вл е н и е в
э л е ме н т о в }
список
н е о б х одимо г о
к о л ич е с т в а
For i : = l 'l'o N Do
begin
Writ eLn ;
Writ eLn ( ' Ввод nолей
tmpRec
з аnиси
: = GetRecord ( Li s t l ,
Wri te ( ' Фамилия :
'
i) ;
i) ;
');
ReadLn ( tmpRe c A . SurName ) ;
Wri t e ( ' Имя : • ) ;
ReadLn ( tmpRec A . Name ) ;
);
Wri t e ( ' Отчеств о :
ReadLn ( tmpRec A . Pat ronymi c ) ;
'
41 9
Turbo Pascal
7.0
Wri t e ( ' Телефон : ' ) ;
ReadLn ( tmpRec л . т e l ephone ) ;
end ;
{ в в о д и н формации в п о л я з а п и с е й , н а к а ждом
ш-а г е цикл а з ап и с ь , в к о т орую буд е т в в о ди т ь с я
и н ф о рмация о пр е де л я е т с я с п омощь ю функции
GetRecord модуля List и заносится в переме н ную
tmpRec , с к о торой и прои з в оди т с я р а б о т а }
Wri t eLn ;
Wri t eLn ( ' Ввод
з акончен . ' ) ;
Wri t eLn ( ' Нажмите любую клавишу
•
•
');
•
ReadKey ;
Clrscr;
Wri t eLn ( ' Инф ормация: из
списка : ' ) ;
Wri t eLn ( ' Количество з аписей : ' , L i s t 1 S i z e ) ;
{ выв о д н а э кр а н колич е с т в а
For i : = 1 То L i s t 1 S i z e Do
записей
в
списке }
begin
Wri t eLn ;
Wri t eLn ( ' Заnись номер ' , i ) ;
tmpRec : = GetRecord ( Li s t 1 , i ) ;
Wri t eLn ( ' Фамилия: :
' ,
tmpRec л . SurHame ) ;
tmpRec л . Наше ) ;
tmpRec л . Pat ronymi c ) ;
Wri t eLn ( ' Oтчecтвo :
Wri t eLn ( ' Имя: :
',
tmpRec л . тelephone ) ;
{ вы во д информации и з п о л е й з а п и с е й , н а к а ждом
ша г е ци кла з а п и с ь , и з к о т ор о й буд е т в в од и т ь с я
и н ф ормаци я о п р е д е л я е т с я с п омощь ю функции
GetRecord модуля L i s t и з а н о си т с я в п е р еме н ную
tmpRe c , с к о т орой и произ в оди т с я р а б о т а }
');
Wri teLn ( ' Нажмите любую клавишу
Wr i t eLn ( ' Teлeф oн :
end ;
•
•
•
ReadKey ;
De l e t eRecord ( Li s t 1 , L i s t 1 S i z e ) ;
{ уд а л е н и е п о с л е д н е й
з аписи
списка }
Clrscr;
Wri t eLn ( ' Инф ормация: из
Wri t eLn ( ' Количество
сnиска : ' ) ;
з аписей :
',
List1Size ) ;
For i : = 1 то L i s t 1 S i z e Do
{ выв о д с п и с к а ,
з а п и с ь ме н ь ше }
в
к о т ором с одержи т с я
begin
Wri t eLn ;
Wri t eLn ( ' Заnись
tmpRec
:=
номер
Wri t е Ln ( ' Фамилия: :
420
',
i) ;
GetRecord ( Li s t 1 ,
• ,
i) ;
tшpRe c л . surN"ame ) ;
на
одну
Глава 1 2 . Орган изация хранен и я информаци и . Основы СУБД
Wri t eLn ( ' Имя :
•,
tmpRec " . Name ) ;
Wri t eLn ( ' O'l'чec'l'в o :
Wri t eLn ( ' Teлeфoн :
•,
•,
tmpRec " . Pat ronymi c ) ;
tmpRec " . Te l ephone ) ;
end ;
Wri t eLn ( ' Нажми'l'е
любую клавишу •
• • '
);
ReadKey ;
De s t royL i s t ( L i s t l ,
List lSize ) ;
{ удал е н и е
списка }
C l rS c r ;
end .
Возвращаясь к обсуждению различных динамических структур данных, за
метим , что список является наиболее удачной структурой во всех отноше
ниях, так как практич ески не зан имает статической памяти сегмента дан
ных (всего четыре байта для указателя на первый элемент списка) и тре бует
ровно столько динамической памяти , сколько необходимо для хранения
всей информаци и. Как только пропадает необходимость хранения каких
либо записей, из сп иска можно удалить неиспользуемые записи.
1 2 . 2 . Осн овы ор ганиза ц и и сист е м
у п ра влен ия базами д а н н ы х
Базой данных назы вается совокупность каких-л ибо структур для долго
временного хранения информации . Проектирование и поддержание баз
данных я вляется одним из самых частых приложений программирования
в силу ш и рокого их применения в различных областях жизн и .
Системой управления базой данных (СУБД) н азы вается программа или
совокуп ность п рограмм , предназначенн ых для занесения ин формации в
базу дан ных, извлечения ее из базы и представления в некотором виде,
например, при вы воде н а экран для просмотра пользователем. В каче
стве при меров СУБД м ожно привести такие известн ы е систем ы , как
FoxPro , dBase , MS SQL Server, Oracle и множество других.
1 2.2. 1 .
Реал изация п ростей шей СУБД
Структура данных в виде списка, описан ная в программе UseL i s t (см. ли
стинг 2 1 8) , пракгически является базой данных, так как предназначена для
хранения информации. Однако данная струкгура не обладает свойством дол
говременного хранения введенной информаци и - все данные, введенные
пользователем , теряются при завершении проrраммы.
Для долговременного хранения и нформации можно записывать введен ную
пользователем информацию в файл перед о кончанием работы программы,
а в начале работы считывать ее оттуда. В результате этого записи, введен
ные пользователем, будут не теряться меЖду сеансами программы, а накал 42 1
Turbo Pascal
7.0
ливаться в некотором файле. Этот файл и будет являться базой данных, а
сама программа (см . листинг 2 1 9) будет являться системой управления ба
зой данных.
:i�ЛИcf�,J�;,21··��:�tg�,��f�!fw�:Jti;P;!����tf!�;!iд���i7��g:�д����i�il�������<1;
P rogram UseLi st 2 ;
Uses
CRT ,
WinDo s ,
List ;
{ п одключ е ни е модул е й CRT , WinDo s ( дл я п о и с к а
файла ) и L i s t ( дл я р а б о ты с о с п и с к ом ) }
Var
List 1 :
PLi s tRec ;
List1Size :
tmpRec :
� =
Intege r ;
PListRec ;
Intege r ;
N:
Integer ;
F:
File
sr :
Of
TLi s tRec ;
{ о пи с а н и е файл о в ой п е р еме н н ой для р а б о ты
с дв оич ными типизир о в а н ными ф а й л ами , э л еме н ты
ко т о р о г о имеют тип TL i s tRec , а н ал о г и ч ный типу
э л еме н т о в с п и с к а }
TSearchRec ;
{ о п и с а н и е п е р е ме н н о й ,
дл я п о и с к а файл о в }
н е о бх одимой
Begin
FindF i r s t ( ' l i s t . bin ' ,
I f Do sError
>
faAnyF i l e ,
sr) ;
{ nоиск
ф айла
l i s t . bi n }
О Then
begin
As s i gn ( F ,
' l i st . bin ' ) ;
Rewr i t e ( F ) ;
Close ( F ) ;
{ е сли файл не н а й д е н , т о о н с о з д а е т с я и
с р а з у же з а крыв а е т с я , в р е з ул ь т а те ч е г о
п о я в л я е т с я н а д и с к е с нул е в ым р а змером }
end ;
Ass i gn ( F ,
' l i s t . bi n ' ) ;
Re s e t ( F ) ;
{ о т крытие файла для чтения ; о н точно суще с т вуе т
н а ди с к е , т а к к а к е сли е г о не был о до н а ч ал а
п р о г р аммы , т о о н был с о з д а н п р е дыдущим
ф р а г ме н т ом п р о г р а ммы }
Creat eL i s t ( L i s t 1 ,
List1Size ) ;
{ с о з д а н и е с п и с к а из о д н о г о элеме н т а ; т а ким
образом, о бщее колич е с т в о элеме н т о в в списке на
один больше , чем записей с поле зной информацией }
422
Глава 1 2 . Организация хранен и я информаци и . Основы СУБД
For
i : =1
То F i l e S i z e ( F )
Do { цикл
по
количе с т в у э л еме н т о в
ф а йл а }
begin
tmpRec : =
GetRecord ( Li st 1 , L i s t 1 S i z e ) ;
{ получение ссьurки на п о следнюю запись }
tmpRec A ) ; { ч т е н и е и н ф ормации из о ч е р е д н о г о эл еме н т а
файла в п о следний элеме н т с п и с к а }
AddRecord ( L i s t 1 , L i s t 1 S i z e ) ;
{ до б а вление одной з а писи в к о н е ц спи с к а ; та ким
обра зо м , о бще е количе с т в о элеме н т о в в списке на
один больше , чем з аписей с полезной информацией }
end ;
Read ( F ,
ClrScr;
Wri t e ( ' Введите
заnисей для доб авления : ' ) ;
{ в ыя с н е н и е у п о л ь з о в а т е л я к о л и ч е с т в а
к о т орые о н х о ч е т д о б а в и т ь к с п и с ку }
холичество
ReadLn ( N ) ;
з а пи с е й ,
For i : = 1 Т о N Do
begin
Wri t eLn ;
Wri t eLn ( ' Ввод nолей з аnиси ' , i ) ;
tmpRec : = GetRecord ( L i st 1 , L i s t 1 S i z e ) ;
Wri te ( ' Фамилия :
');
ReadLn ( tmpRec ... . SurName ) ;
Wri t e ( ' Имя :
');
ReadLn ( tmpRec ... . Name ) ;
Wri t e ( ' Отчеств о :
');
ReadLn ( tmpRec ... . Pat ronymi c ) ;
Wri t e ( ' Телефон : ' ) ;
ReadLn ( tmpRec ... . Tel ephone ) ;
AddRecord ( Li st 1 , L i s t 1 S i z e ) ;
end ;
{ до б а в л е ни е к с п и ску н е о б х о димо г о к о л ич е с т в а
з а пи се й ; сначала о суще с т в л я е т с я в в од и н формации
в п о сл е д нюю з а п и с ь с п и с к а , т а к к а к о н а еще н е
с о д ержит информации , з а т е м д о б а в л я е т с я пус т а я
з а п и с ь в к о н е ц с п и с к а ; т а ким о б р а з ом , о бще е
колич е с т в о элеме н т о в в с п и с к е н а один б о л ь ше ,
чем з а п и с е й с п о л е з н ой и н ф о рмаци е й }
Wr i t eLn ;
Wri t eLn ( ' Ввод
захончен . ' ) ;
Wri t eLn ( ' Нажмите
любую хлавишу
•
•
•
');
ReadKey ;
Clrscr;
Wri t eLn ( ' Информация и з
сnисха : ' ) ;
Wri t eLn ( ' Koличecтвo заnисей :
For i : =1 то L i s t 1 S i z e - 1 Do
begin
Wri t eLn ;
List1Size- 1 ) ;
423
Turbo Pascal 7 . 0
Wri t eLn ( ' Заnись номер ' 1 i 1 ' из ' 1 L i s t 1 S i z e - 1 ) ;
tmpRec : = GetRecord ( L i s t 1 1 i ) ;
Wri t eLn ( ' Фамилия : ' 1 tmpRec " SurName ) ;
Wri t eLn ( ' Имя : ' 1 tmpRec " . Name ) ;
Wri teLn ( ' Ооrчесоr:во : ' 1 tmpRec " . Pat ronymi c ) ;
Wri teLn ( ' Teлeф oн : ' 1 tmpRec " . Telephone ) ;
•
Wri t eLn ( ' Нажмиоrе любую клавишу
');
ReadКey ;
end ;
{ выв од и н формации из в с е х з ап и с е й с п и с к а ,
кроме п о сл е д н е й , т а к к а к о н а не с о д е ржи т
п о л е з н ой и н ф о рмации }
{ о ткрытие файла для з а писи }
Rewri t e ( F ) ;
For i : = 1 то L i s t 1 S i z e - 1 Do
•
•
•
begin
tmpRec
:=
Writ e ( F I
end;
GetRecord ( Li st 1 1
i) ;
tmpRec " ) ;
{ з а п и с ь в файл в с ех элеме н т о в с п и с к а , кроме
п о сл е дн е г о , так как о н не с о д е ржит п ол е з н ой
информации ; в файл з а пи сыв а е т с я з а п и с ь целиком ,
т а к к а к тип элеме н т а файла с о о т в е т с т в у е т типу
э л е ме н т а с п и с к а }
Close ( F ) ;
Dest royL i s t ( Li s t 1 1
ClrScr;
{ з а крытие файл а }
List1Size ) ;
{ уд а л е н и е
списка
полностью}
end .
Представленная система не является совершенно й , так как н е обладает
многими необходим ы м и функция м и , таким и как:
•
•
•
•
П оис к нео б ходимо й зап иси по запросу, содержа щему значения не
с кольких полей . Н апри мер, в ы вод на экран номера тел ефона по
фамилии , и м е н и и отчеству абонента.
Упорядоч и вани е списка п о полям записей , например п о фам ил ия м .
Удал ени е ненужных записей.
Корре ктировка (редакт ирование) како й -л и б о зап и си .
Структура данн ой п рограм м ы также не соответствует обсужд е нно й выше
правильной орган изации : в н ей отсутствует меню, описание выполня е
мых д ейств и й , а и нтерфейс, выполненный в черно - белом текстовом сти
ле , кра й не н еуд обе н для пользователя . Однако программ а в д анном виде
легко раз вивается и м ожет быть изменена таким о бразо м , чтобы соот
ветствоват ь современным стандартам .
М ы не б удем здесь приводить программу, отвечаю щую вышеперечислен
ным тре б ования м , в связи с ее немал ы м размеро м , а останови мся на н е
которых теоретических аспектах организации самой базы дан ных, кото
рая на сам ом д еле , так же как и интерфе й с, далеко не соверш енна.
424
Глава 1 2 . Органи з ация хранен и я информаци и . Основы СУБД
1 2.2.2.
Основы орга н изаци и баз да н н ых
Отсутствие избыточности как основное требова н и е
Основ н ым требованием , предъявляемым к и нформации , храни мой в базе
дан н ых, я вляется отсутствие избыточности. Поясни м на при мере . Допус
тим , есть сп исок сотрудников орган изации , и меющи й структуру, исполь
зованную в программах U s e L i s t и U s e L i s t 2 .
Фамилия
С ухар ев
Д ра ч
Дивн о в а
Ер охи н
Имя
М и хаил
Петр
М ар и я
Д м ит р и й
Отчество
Викт оро ви ч
Михай л о ви ч
Викт оро вн а
Алекс а ндро ви ч
Тел е фон
32308 1 8
1 1 8 25 1 4
540 1 229
32323 1 6
Такая структура предполагает наличие одного телефон а у одного сотруд
ника. Если же како й -л ибо сотрудник имеет два телефона, то для него
придется добавить е щ е одну запись в список, п родублировав поля Имя ,
Отче с т в о и Ф амили я .
Фамилия
С ухар ев
Д рач
Дивн о в а
Еро хин
С ухарев
Ерох ин
Имя
М ихаил
Пет р
М ар и я
Д м ит р и й
Миха ил
Д м итр и й
Отч е ство
Тел е фон
Викт оро ви ч
М ихай л о ви ч
Викторо вн а
Алекс а н дро ви ч
32308 1 8
Викторо ви ч
Алекс а ндро вич
998 1 8 1 8
1 1 825 1 4
540 1 229
32323 1 6
99623 1 6
Данная операция связана с повторным вводом фамилии, имени и отчества
сотрудника, в результате чего могут появиться расхождения в полях записей,
относящихся к одному и тому же человеку. Такие расхождения могут быть
связаны, например, с ошибками оператора, дополняющего базу данных.
Фамилия
С ухар ев
Д рач
Дивн о в а
Ерохи н
Сухар ев
Е РОХИ Н
Имя
М и ха ил
Петр
М ар ия
Дм ит рий
М иха ил
Д м итр и й
Отч е ство
Викторо ви ч
М ихайл о ви ч
Викт оро вн а
Алекс а ндро ви ч
Викторо ви ч
Алекс а ндро ви ч
Тел е фон
32308 1 8
1 1 8 25 1 4
540 1 229
32323 1 6
998 1 8 1 8
99623 1 6
В приведеи ном при м ере последняя фамилия , н абран ная больш и м и бук
вами , не соответствует той же само й фамилии , набранной с одной б оль
шой буквы . Таки м образом , пользователь систем ы управления базой дан
н ых , введя запрос п о фамили и « Е р о х и н » , н е п олучит и н формации ,
занесенной во вторую зап ись и , соответствен но, не узнает второго номе425
Turbo Pascal 7 . 0
ра телефона, относящегося к данному сотруднику. Ош и бка происходит
из-за избыточ ности и нформации , хранимой в базе , то есть из-за необхо
димости повторного ввода в базу и нформац и и , которая там уже есть.
Для предотвращения таких ситуаций возможно применение двух методов.
Метод 1 . Резервирование в зап и сях с писка нескол ьких п олей п од те
лефоны . В случае вы бора такого метода табли ца будет и меть следу
ющи й вид:
Фамилия
Др ач
Ди ан ав а
Ер о хи н
Суха р е в
И мя
П ет р
М а ри я
Д м и т ри й
М ихаил
Отчество
М ихай л о вич
В и кто р о в на
Ал ек сандр о вич
Ви кто р о вич
Телефон 1
Телефон 2
1 1 825 1 4
5401 229
32323 1 6
99623 1 6
32308 1 8
9981 8 1 8
Аналогичн ы м образом можно добавить поля для хранения третьего , чет
вертого телефона и так далее. Это довольно п ростой м етод , решающи й
оп исанную выше проблему, но при этом возни кают несколько других.
Первая проблема - н еэффективное расходован ие памяти н а яче й ки , не
содержащие телефонов. Обыч но одному человеку сопоставляется два-три
телефона, но могут быть исключени я . Например, оди н сотрудник будет
иметь десять телефо нов, значит, для всех остал ьных сотрудников семь
восемь ячеек, отведенных под телефон ы , будут незаняты , то есть неоправ
данно расходуется п амять.
Вторая проблема появляется при попытке сохран ить в базе некоторы й
признак для каждого телефона (например, домашни й/факс/мобильны й ) ,
в результате чего опять появится избыточность информации , так как при
знаки придется также вводить вручную. Соответственно, рано или поздно
опять появятся расхождения, например «Мобиль ный» и «МОБИЛ Ь НЫЙ» .
Второй метод исключает все эти ситуаци и .
Метод 2. Разбиение табл и ц ы , представляющей базу, на несколько от
дельных табл и ц , представляющих и нформацию об одн о м объекте .
Для н ашего примера из одной табли ц ы получается две: одна для
хранения и нформации о сотрудни ках ( и мя , отчество и фамили я ) , а
вторая - для хранения и нформ ац и и о телефонах (номер) .
Телефон
Фамилия
Др ач
Ди ан ав а
Ер о хи н
Суха р е в
И мя
П ет р
М а ри я
Д м итри й
М иха ил
О тчество
М ихайлович
Ви кто р овна
Ал екс андр о вич
Ви кто р о вич
32308 1 8
1 1 8 25 1 4
540 1 229
32323 1 6
998 1 8 1 8
99623 1 6
426
Глава 1 2 . Организация хранен и я информаци и . Основы СУБД
Далее необходимо присвоить каждой записи в каждо й таблице номер,
уни кальны й для дан ной таблицы:
Те n ефон
Н омер
1
2
3
4
Ф а миnия
Сухарев
Д рач
Ди ан ав а
Е р ахи н
И мя
М иха ил
Петр
М ар и я
Д м итр ий
Отчество
1
Ви кторо ви ч
Миха йл о ви ч
Ви кторо в на
Але к с андро ви ч
32308 1 8
2
1 1 825 1 4
3
540 1 229
4
32323 1 6
5
998 1 8 1 8
6
99623 1 6
Т еперь с таблицами можно работать п о отдельности , в водя новые запи
с и ли бо в одну таблицу, либо в другую , в результате чего н и в одной
таблице не б удет повторен ий . Однако эти две таблицы не связан ы друг с
другом , поэтому такая база данных не отвечает своим задачам . Для того
чтобы организовать связь между таблицами , добавляется еще одно поле
в таблицу телефонов, определяющее, какой зап иси в табли це сотрудни
ков соответствует дан н ы й номер телефона:
Теnефон
Н омер
1
2
3
4
Фамиnия
Сухарев
Д рач
Диан ав а
Ер ахи н
И мя
М иха ил
Петр
М ар ия
Д м итр ий
Н омер
сотрудн ика
Отчество
1
32308 1 8
1
Ви кторо ви ч
М иха йл о ви ч
Ви кторо в на
Але ксан дро ви ч
2
1 1 8 25 1 4
2
3
540 1 229
3
4
32323 1 6
4
5
998 1 8 1 8
1
6
99623 1 6
4
При такой организации базы дан ных в ней б удет храниться ровно столько
и нформ аци и , сколько необходимо для корректно го представления дан
н ых о сотрудниках и их телефонах. Процесс получе н ия телефонов по
фамилии , имени и отчеству сотрудника будет состоять из двух этап ов:
•
•
•
поиск записи , соответствующей задан н ым фамил и и , и м е н и и отче
ству, в табл и це сотруд н и ков;
в ывод на экран име н и , отчества и фамил и и сотруд н и ка;
поиск зап исей в табли це телефонов, Н омер с о т рудни к а в которых
соответствует номеру записи , найденной в табл и це сотрудни ков.
Н апример, по запросу «Ерохин Дми трий Ал е к с ан др о вич» производит
ся поиск такой зап иси в таблице сотрудников. Номер найденной зап иси
4 . Дал ее производится поиск в табл ице телефонов по полю Н омер с о
трудника таким образом , чтобы значение этого поля было равно 4. В
резул ьтате поиска на экран выводятся номера телефонов из записей с
номерами 4 и 6 .
-
427
Turbo Pascal
7.0
Есл и пользователю будет и н те р есна допол нительная и нфо р м ац и я о но
мере телефона (домашнийjфаксjмобильный) , то для различных типов опи
сывается еще одна таблица :
Номер
1
2
3
Тип
телефона
Домашн ий
Ф ак с
М о биль н ый
В табл ицу номеров телефона следует включить еще одно поле , опреде
ляющее тип телефона:
Телефон
Номер
1
2
3
4
Фамилия
Сухарев
Д рач
Ди ано в а
Ерохин
И мя·
М иха ил
Пе тр
М ария
Д м итр и й
Ном ер
сотрудника
Ном ер
типа
Отчество
1
32308 1 8
1
1
Ви кторо ви ч
М их а й л о ви ч
Ви кторо в на
Але к с андро ви ч
2
1 1 825 1 4
2
1
3
540 1 229
3
1
4
32323 1 6
4
1
5
998 1 8 1 8
1
3
6
99623 1 6
4
3
Связи между табл и цами
П р и запросе телефонов , соответствующи х введе н н ы м фам и л и и , имен и
и отчеству , п р и такой структу р е базы данн ы х появится еще оди н этап
в момент вывода телефона необходимо просмотреть табл и цу т и пов те
лефонов для определения ти па телефона по его номеру , соде р жащему
ся в поле Н омер типа таблицы телефонов. Т акого р ода связи м ежду та б
ли цами называются << многие к одному>> , то есть м н о го тел ефонов могут
ссылаться своим п олем Н омер с о тр удни к а н а одну запи с ь та б л и цы со
трудников.
Т акже испол ьзуются связи << один к одному>> , ко гд а одн о й зап и си пер
вой табл и цы сопоставляется одн а зап и с ь второй табл и ц ы . Т акая с вязь
испол ьзуется об ы ч н о для экономии памяти . Н априм е р , табл и цу сотруд
н и ков можно р азбить н а две - в одн ой будут содержаться только фа
м ил и и , в б ольш и н стве небольших орган изаций однознач н о определя
ю щ и е сот р удн и ков , а в д р угой - имена и отч ества , кото р ы е м о гут
использоваться не всегда , а тол ько в н екоторых случ ая х , по допол н и
тельному зап р осу пользо вателя . Т аблицу фамилий следует загружать
всегда , а табл и цу име н тол ько п ри необходимости , в резул ьтате ч е го
эконом ится опе рат и в н ая пам я ть.
И, н ако н е ц , существуют связ и м ежду табл и цами вида << многие ко мно
гим » , когда одн о й зап иси первой табл иц ы сопоставляетс я несколько
зап исе й вто р ой табл и цы , п р и че м зап иси вто р ой табл и ц ы м о гут сопос428
Глава 1 2 . Организация хранен и я и н ф о рм ац и и Осн овы СУБД
.
тавляться н ескольким записям п ер в о й . Такая с итуация возможна, если
н ескол ько сотруд н и ко в им еют оди н и тот же номер телефона ( напри
мер, если о н и работают в одном отделе) . Реал изуются такие с вязи ч е
рез допол нительную та бл и цу , содержащую п ары чи сел Н омер С о т руд
н и к а , Н омер т е л е ф о н а .
Номер
Н омер
сотруд ника телеф она
Н омер
1
2
3
4
Фамилия
Суха рев
Др ач
Ди ан о в а
Е р о хи н
1
1
2
2
3
3
4
4
1
5
4
6
2
6
Номер
Телефон
1
32308 1 8
2
1 1 825 1 4
3
540 1 229
4
32323 1 6
5
998 1 8 1 8
6
99623 1 6
В приведеином при мере сотруднику с номером 4 («Ер о хин») соответству
ют две записи в таблице телефонов - с номерам и 4 и 6 (соответственно ,
пары чисел в промежуточной таблице 4 , 4 и 4 , 6 ) . При этом телефону с
номером 6 также соответствуют две зап иси в табл и це сотрудн и ков «Ер о хин» с номером 4 и «Драч>> с номером 2 (соответствен но , пары ч и
сел в промежуточной табл ице 4 , 6 и 2 , 6 ) .
П рочее
Реальные базы данных могут содержать сотни табли ц и сотн и различных
связей между ними. Н азываются такие базы данных реляционными.
М ы рассмотрели не все правила организации баз данных, а только ос
новные. Однако суть процесса организации БД, вне зависим ости от их
назначения и объема храни мой информации, и менно такая - сначала оп
ределяется набор информации , которую необходимо хранить, а затем по
лученные таблицы разбиваются на несколько более простых для исклю
чения повторяемости дан н ых.
П р и м еч а н и е .
П равила раз б и ен и я и н формации н а логические груп п ы п ри п о строен и и б аз
дан н ых назы ваются п равилам и н ормализации , включ ают в се б я н а м но го
б ол ь ш е м етодов , ч е м рассмотрено н ам и , и изложен ы п ракти чески во всех
издан и я х , п о с вя щен н ых п роекти рован и ю СУБД .
Для реализации баз данных и систем управления и м и необходимо твер
дое знание приемов работы с данными сложн ых типов - масс и вами и
запися м и , а также навыки работы с файлам и . Изменение формата хра
нения информации как в оперативной п амяти , так и на диске вызывает
существен н ые изменения в программ е и в большинстве случ аев требует
429
Turbo Pascal
7.0
написания допол н ительных программ
ного форм ата в друго й.
-
конверторов баз данных из од
Таким образом , время, потраченное на исчерпывающее описание базы
данных и анал из возможных вариантов ее построен и я , не я вляется по
трачен н ы м зря и с лихвой окупится при изме не ниях систем ы управл е
ния базой , которые вс е равно н еизбежны .
К онтрол ьн ы е вопрос ы и ответы
Что п р едставляют собой д и н а м ические структуры да н н ых и ч е м
выз в а н а необходимость их использова ния?
П олуч е н и е , сохранение ( накопление) , а также представление и нформации
является одн ой и з наиболее расп ростран е н н ых задач программи рован и я .
В связи с переме н н ы м и объемами информаци и , с которой работают п р о
грам м ы , необходи мо использовать динамические структуры данных, о с
н о в н ы м и из которых я вля ются массивы динам ически расп ределяемых
элементов ( м ассивов ссылочных перемен н ых) , динам ически расп реде
ляемые массивы ( переме н н ые-указател и на масс и в ы ) , а также списки
посл едо в ател ьн ости записей, и м е ю щ их поля дл я ссыл ки н а сл едующую
запись.
-
Что т а кое база д анных?
Структура дан н ых, характеризующаяся свойством дол говременного хран ения
информаци и , назы вается базой данных. Для работы с базами дан ных пред
назначены программы или их совокупности , называемые системами управ
ления базами данных. Построение баз дан ных регламентируется специаль
ными п равилами , называемыми правилами нормализации баз данных.
Какие основные требования предъя вляются к и н ф о р м а ци и , х р а н и
мой в базе д а н н ых?
Осн о в н ы м и требован и я м и , предъя вляем ы м и к и н фо р м аци и , хран и м о й в
базе дан н ых, являются целостность и отсутствие избыточ ности .
430
а в а
Р е кур с и я
1 з. 1 .
Осн о вн ы е понят ия
Рекурсия
это вызов подпрограммой (процедурой или фун кцией) самой
себя . Основана рекурсия на том , что началом области видимости иден
тификатора (в дан ном случае имени подпрограммы) я вляется строка, в
которой этот идентифи катор описывается . Приведем пример (см . листи нг
220) .
-
Program Recurs l ;
Procedure Wri t e A ; { за г о л о в о к проце дуры Wr i t eA - н а ч а л о
видимо с т и иде н тифик а т о р а Wr i t eA }
begin
{ н ачало
Wr i t e ( ' А ' } ;
{ выв о д
на
Wri t eA ;
{ вы з о в
э т ой ж е процедуры еще
end ;
{ о к о н ч а ние
о бл а с ти
п р о ц е дуры }
экран
симв о л а А }
описания
раз }
п р о ц е дуры Wri t eA }
Begin
Wri t eA ;
{ вы з о в
проце дуры Wr i t eA }
End .
Пр иведеиная программа выполняется следующи м о бразом :
l . Вызывается процедура Wr i t eA.
2 . П роцедура Wr i t eA выводит на э кран сим вол <<А» , затем вызы вает
саму себя . Это м ожно представить как создание н ового э кземпляра
процедуры Wr i t eA в п амяти и его вызов. Для нового э кзем пляра
43 1
Turbo Pascal 7 . 0
п роцедуры создаются собственн ы е локальные
переменные и д ругие необход и мы е структуры .
3 . Второй экземпляр п роцедуры wr i t eA вывод ит
н а экран с и мвол <<А>> , затем вызывает еще оди н
экземпляр п роцедуры Wr i t eA .
4. Трети й экземпляр п роцедуры wr i t eA вывод ит
н а экран символ «А» , затем вызывает еще од и н
экземпляр процедуры Wr i t eA.
Дан н ы й процесс м ожет прои сход ить бескон ечн о
(см . рис . 1 46 ) , заполняя экран символам и . Такой
вариант выполнения рекурсивной программы назы
вается бесконечной рекурсией . Для предотвращен ия
бесконечности рекурсии можно описать глобальную
Рис. 1 46.
Рекурсивное
переменную , в зависимости от которой каждый эквыполнение
земпляр рекурсивной процедуры буд ет определять,
процедуры
нужно ли в ыз в ать еще од и н экземпляр или следует
закончить данны й экземпляр процедуры . Использование конечной рекур
сии прод емонстрировано в листин ге 22 1 .
,•: i!�·?т..,:4�··��,·��?:��Ji()�a;�c)�·��,��'"к�и,�����,'��!##��'� t;��}·�;�i�·-,�'tr��;:�!�,i ����ii�вrr.��
Program Recur s 2 ;
Var
waCount :
Integer; { о п и с а н и е п ер е ме н н о й - с ч е т ч и к а к о л ич е с т в а
з а пуще н ных э к з емпл я р о в п р о ц е дуры Wr i t eA }
Procedure Wri t eA ; { з а г о л о в о к п р о ц е дуры Wr i t eA - н а ч а л о
видимо с т и и д е н т и фи к а т о р а Wr i t eA }
области
{ н а ч а л о проце дуры }
: = waCount + 1 ;
{ ув ели ч ен и е с ч е тчика н а 1 }
Wri t eLn ( ' Начало экземnляра ' 1 wacount ) ;
{ в ыв о д с о о бщ е н и я о н а ч а л е п р о ц е дур ы }
I f wacount < 4 Then Wri t eA ;
{ е сли с ч е тчик з а пуще н ных э к з емпл я р о в ме н е е
ч е тыр е х , то з а пу с т и т ь е щ е один э к з емпляр ,
и н а ч е - не з а пу с к а т ь , то е с т ь п р о ц е дура
з а к о н чи т с я }
Wri t eLn ( ' Окончание экземnляра ' 1 wacount ) ;
{ вывод с о о бще н и я о б о к о н ч а нии п р о ц е дуры }
begin
waCount
WaCount
1;
{ уме н ь ше н и е
{ о ко н ч а ни е о п и с а ни я
с ч е тчика н а 1 }
п р о ц е дуры Wri t eA }
: =
WaCount
: =
О ; { н а ч ал ь н о е з н а ч е ние п е р е ме н ной WaCount р а в н о О
( не з а пуще но ни одного экземпляра процедуры Wri t eA ) }
end;
-
Begin
WaCount
Wri t eA ;
End .
432
{ выз о в
пр о ц е дуры Wr i t eA }
Глава 1 3 . Рекурсия
1 з. 1 . 1 .
Конечная рекурсия
В при ведеиной програм ме используется конечная рекурсия - запуска
ется всего четыре экземпляра процедуры Wri teA, далее программа закан
ч и вается . К о н е ч н ость рекурси и основана н а гл об альной перемен н ой
waCoun t , общей для всех запущенных экзем пляров процедуры Wr i t eA.
В начале программы значение waCount устанавли вается равн ы м нулю,
затем кажды й запущен н ы й экземпляр процедуры Wr i t eA увеличи вает его
на 1 . Таким образом , переменмая waCount содержит количество запущен
н ых экземпляров процедуры Wri t eA. Для определения необходи мости
запуска очередн ого экзем пляра процедуры Wri t eA кажды й п редыдущий
экземпляр сравн ивает переменную waCount со значением 4. Если waCount
< 4, то запускается еще оди н экземпляр про цедуры , который увеличива
ет значение waC oun t н а 1 и опять выполняет проверку wac ount < 4.
Когда запускается четверты й экземпляр процедуры wr i t eA, значение
waCoun t стан овится равным 4 и очередной экземпляр про цедуры не за
пускается . Управление передается предыдущему экземпляру процедуры ,
которы й в ы водит сооб щен и е о
с в о е м за в ер ш е н и и , у м е н ь ш ает
waCount : = 0
1 г- WriteA;
значение счетчика waC ount и за
9
П рогра мм а
� · end; - - - - - - - - - - - - - - - - - -канчивается , передавая управле
· закончена
: Вызы ваю щая програм м а
н и е предыдущему экзем пляру.
�
1
·----------------------------
Рассмотрим процесс выполнения
п р о ц еду р ы п о ш а га м ( с м .
рис. 1 47 ) .
1 . Вы полнение основной части
программы. Обнуление пере
м е н н ой wac o u n t и вызов
первого экземпляра процеду
ры Wri t eA.
2. Выполнение первого экземп
ляра процедуры Wri t eA. Уве
личение значения перемен
н ой w a C o u n t н а ед и н и цу
(теперь waCount
1 ) и вы
вод сообщения о начале оче
редного экземпляра процеду
ры ( « Н а ч а л о э к з емпляр а
1 » ) . Проверка и сти н н ости
в ыражен ия waC oun t < 4
(истинно) и запуск второго
э кз е м п л я р а
п р о ц е д ур ы
Wri t eA.
=
waCount := waCount
2
-
WriteLn ( . . . . . . . . . ) ;
end;
- --------
-
1
:
:
1
lf waCount < 4 Then WriteA;
! _. WoiteLn( . . . . . . . . . );
waCount := waCount
J
!
+1
1
эКзёмriЛЯ р Т -
J
:
8
-�
·-----------------------------
��-------, :
waCount := waCount + 1
J
:
:
WritвLn ( . . . . . . . . . );
3 г-
1
lf waCount < 4 Then WriteA;
! " WrlteLn ( . . • . . • • . . );
waCount := waCount
J
-1
:
end;
-�
:
- - - - - - - - - э Кзё'МГiЛЯii 2- 1
·----------------------------�
1
waCount := waCotont + 1
:
WriteLn( . . . . . . . . . );
4 г- lf waCount < 4 Then WriteA;
� -� -writeLn( . • • . • • • • . );
waCount := waCount - 1
J
!
end;
7
:
:
1
- - - - - - - - -э кзёмnляр з
--
6
:
·
-
•-----------------------------·
waCount := waCotont
WriteLn ( . . . . . . . . . ) ;
+1
1
J
:
J
:
lf waCount < 4 Then WriteA;
WriteLn ( . . . . . . . . . ) ;
f---
:
waCount := waCount
end;
-
1
Экзем пл я р
1
4
:
!
·----------- - - - - - - - - - - - - - - - - - - - -
5
Рис. 1 4 7. Процесс выполнения
программы Recurs2
433
Turbo Pascal 7 . 0
3 . Вып ол нение второго экзем пляра процедуры Wr i t eA. Увел ичение
зн ачения переменной waCount на еди н и цу (теперь waC ount
2) и
вывод сообщен и я о начале очередного экзем пляра п р оцедуры ( «Н а
чало э к з емпл яра 2 » ) . Проверка истинности выражен ия waCount
<
4 (истин но) и запуск третьего экземпляра процедуры Wr i t eA.
4 . Выпол нен и е третьего экземпляра процедуры Wr i t eA. Увеличение
3) и
знач ен и я переменной waC oun t н а еди н и цу (теперь waCoun t
вывод сообщения о нач але очередного экзем пляра процедуры ( «Н а
чало э к з емпл яр а 3 ») . Проверка истинности выражен ия waC ount
<
4 (и стинно) и запуск ч етвертого экзем пляра процедуры Wr i t eA.
5. Выполнение четвертого экземпляра процедуры wri teA. Увеличение зна
4) и вывод
чения переменной waCount на единицу (теперь waCount
сообщения о нач але оч ередного экземпляра процедуры ( «Начало эк
з емпляра 4») . Проверка истинности выражения waCount < 4 (ложно) ,
соответственно, запуск пятого экземпляра процедуры Wri t eA не осуще
ствляется. Вывод сообщения об окончании данного экзем пляра проце
дуры ( «Окончание экземпляра 4» ). Уменьшение значения перемен
ной waCount на единицу (теперь waCount
3 ) , окончание данноГо
экземпляра процедуры (достигнуто кл ючевое слово end) и , соответ
ственно, возврат управления третьему экземпляру процедуры Wri t eA.
6. Вып олнение третьего экземпляра процедуры Wr i t eA. В ы вод сооб
щен и я об окончании дан н ого экзем пляра процедуры ( «Око нч ание
э к з емпл яра 3 » ) . Уменьш ение значения п еременно й waCoun t н а
еди н и цу (теперь waCount
2 ) , окон ча н ие данного э кзем пляра
процедуры (дости гнуто ключевое слово end) и , соответственно , воз
врат управл ения второму экземпляру процедуры Wr i t eA.
7 . В ы пол нение второго экземпляра процедуры Wr i t eA. В ы вод сооб
щения об оконч ан и и дан ного экзем пляра процедуры ( «Око нч а ние
э к з емпл яра 2 » ) . Умен ьшение значен и я переменной waCount на
едини цу (теперь waC ount
1 ) , окончание дан ного э кземпляра
процедуры (достигнуто клю ч евое слово end) и , соответственно , воз
врат управл ения первому экземпляру процедуры wr i t eA.
8. Выполнение п ервого экзем пляра процедуры wri t eA. Вывод сообще
ния об окончан и и данного экземпл яра процедуры ( «Ок о н ч а ние э к
з емпляра 1 » ) . Уменьшение значения переменной waC ount на еди
ницу (теперь waCount
о ) , окончание данного экземпляра процедуры
(дости гнуто ключевое . слово end) и , соотНачало экзе м пляра 1
ветственно, возврат управления в основ
Начало экзем пляра 2
Начало экзе мпляра 3
ную часть программ ы .
Начало экзе мпляра 4
Око нч ан ие экземпляра 4
9 . В ы пол нение основной части програм м ы .
Око нчание экземпляра 3
Око нч а н ие экземnля р а 2
Окон чание программ ы (достигнуто клю
Око нч ан ие экземпляра 1
ч евое слово end ) .
=
=
=
=
=
Рис.
Результат работы програм мы представлен на
рис . 1 4 8 .
434
1 48 .
Результа т ра боты
программы Recurs2
Глава 1 3 . Рекурсия
1 3. 1 .2.
Бесконечная рекурсия . П о н ятие стека
Теперь вернемся к б есконечной рекурсии. Во- пе р вых, заметим , что ее ис
пользование вообще противоречит определению програм м ы , которая дол
жна иметь логическое завершение. При бесконечной рекурси и результат
работы не может быть получен , так как программа не заканчи вается ка
ки м -либо корре ктным образом .
Во- вторых, бесконеч ная рекурсия , строго говоря , не я вляется бесконеч
ной. Дело в том , что при вызове какой-либо подпрограм мы (неважн о ,
рекурсивной или нет) адрес вызы вающе й подпрограммы сохраняется в
специальной области памяти , называемой стеком. Этот адрес назы вается
адресом возврата и используется для п ередачи управления вызы вающей
подп р ограмме после завершения вызванной процедуры .
Стек состоит из ячеек памяти , в кото р ые пос
л едо вател ьно заносятся каки е -л и бо значен ия
(рис. 1 49) , и об ыч но используется для сохран е
ния адресов возврата и передач и параметро в в
процедуры (и м е н н о так передаются парам етры
в процедуры и функции Turbo Pascal . Для обыч
ных параметро в в стек заносятся их значен ия ,
для параметров- переменных - адреса перемен
ных, задан ных в качестве этих параметров при
вызове процедуры) .
Последн и й элемент
6
c::J
5 ....... c::J
Элеме нт 4 .......
c::J
Элемент
Элемент
3 ....... c::J
2 ....... c::J
Эле м е нт 1 .......
c::J
....... c::J
Элеме нт
Элемент
Для стека определено две операци и - добавить
очередной эле м е нт и извлечь последн ий добав
Рис. 1 49.
ленны й элемент. Размер стека огра ниче н и не
Структура стека
может содержать элементов более, чем указано
в н астройках комп илятора (см . описание пункта главного меню и нтег
ри рован н о й среды разработч и ка Op t i on s J Memory S i z e s . . . ) . В лю б ом
случае размер сте ка н е может превыш ать 65520 байт. Пр и это м стек
я вляется обще й структурой для всей програм м ы , соответственно , даже
такое кол ичество элементо в стека недостижимо.
П р и м еча н и е .
Стека в ы е структуры ч асто и спользуются в п рогра м м ах . Существуют структу
ры дан н ы х с п оследовател ь н ы м досту п о м к эле м е нтам , анал о г и ч н ы е стекам ,
но о п е раци и , оп редел е н н ы е для н их - доб авл е н и е эле м е нта и и з вл е ч е н и е
п е р в ого эл е м е нта. Такие структуры дан н ы х наз ы ваются очередя м и . Для сте
ков и с п ол ьзуется об означ е н и е L I FO ( Last lп Fi rst Out - п р и ш ел п о сл едн и м ,
в ы йдет п е р в ы м ) , дл я очередей и с п ол ьзуется об означ е н и е F I FO ( Fi rst l п Fi rst
O u t - п е р в ы м п р и ш е л , п е р в ы м в ы йдет ) .
Когда программа пытается добавить в полностью заполненный стек еще один
элемент, ее выполнение пре р ывается и на экран выдается сообщение о б
Ошибка 2 0 2 : Пер е п олне ошибке Error 2 0 2 : Stack overflow error
-
435
Turbo Pascal
7.0
ние с т е ка . При выполнении программы с бесконечной рекурсией вне за
висимости от размера стека появится такая ошибка, так как при вызове
очередного экземпляра процедуры в стек заносится адрес возврата преды
дущей , при этом экземпляры процедуры не заканчиваются, а значит, не
вынимают из стека адреса возврата. Увеличение размера стека влияет толь
ко на количество возможных экземпляров процедуры - чем больше размер
стека, тем больше экземпляров процедуры можно запустить.
Заметим , что размер стека все-таки является полезным параметр о м ком
пиляци и , но его увеличение используется не для беско н ечной рекурси и ,
а для конечной , им еющей высокую степень вложенности . Если конеч
ная рекурсия вызывает ош ибку переполнения стека, то можно увеличить
его размер. По умолчанию размер стека составляет 1 63 84 байт.
1 3 . 2 . И спол ь з ов а н ие ре ку рс и и
Рекурсия я вляется мощным средством для решен ия задач , ал горитм ре
шения которых и меет п ереборны й иерархический характер .
Рассмотрим задачу. Имеется прямоугольное поле некоторого размера, раз
битое на клетки (см . рис. 1 50) . Начав с левой верхней клетки , будем пос
ледовательно расставлять числа в клетках ходом шахматного кон я , то есть
месторасположение двух соседних чисел отличается на две клетки в одну
сторону и на одну в перпендикулярном направлении. Задача - запол
нить все клетки поля.
Предлагается следующее решение задач и .
1 . Ставим в л евую верхнюю клетку число 1 .
2 . Число 2 можно поставить в одну из двух клеток:
• на две
п равее и одну ниже, чем левая
верхняя ;
• н а две
н иже и одну правее, ч е м левая
верхняя .
В ыбере м первую и п оставим в нее число 2
(рис. 1 50 ) .
3 . Для числа 3 есть четыре возм ожных п оложе
н и я . В ыберем верхнее правое и поставим в эту
клетку ч и сл о 3 (рис . 1 50 ) .
4. Далее будем продолжать таки м ж е образо м .
Как видно на р ис. 1 50 , данн ый процесс м ожет
закончиться н еудачей - поставив очередное
числ о (43 ) , н е возм ожно ходом коня перейти к
другой незапол нен н ой клетке. З н ач ит , ч исло
43 нужно удалить и поставить в следующую
возм ожную клетку.
436
Рис. 1 50. Игра
«ХОД КОНЯ»
Глава 1 3 . Рекурсия
Обобщим процесс решения задач и . Н а каждом шаге (для текущей клет
ки с номером N) выполняются одн и и те же дей ствия :
1 . Если найдено решен и е , то есть заполн ен ы все клетки , т о следует
сообщить об этом п ол ьзователю и закончить п роцесс решен и я
задачи .
2 . Есл и решени е е ще н е найдено (заполнены не все клетки ) , то:
• по п равилу перемеще ния коня определяются клетки , в которых
еще не находятся числа;
• из этих кл еток выби рается одна, в нее ставится очередное ч и сло
( N + l ) и в е с ь п роцесс повторяется для новой клетк и ;
• есл и
свободных клеток нет, т о следует возвратиться на шаг
назад и выбрать другую клетку для установки в нее ч и сла N.
Таки м образом перебираются все возможные варианты расп оложе н ия
чи сел на поле, пока не будет найде н тот, которы й удовлетворяет усло
вию задач и , то есть данная задача я вляется переборной . Решение задачи
и меет иерархический характер, то есть содержит в себе несколько ша
гов , н а каждом из которых производятся одн и и те же действия - опре
деление, не найдено ли решение, или выбор новой клетки . Если н а ка
ком -ли бо шаге определено наличие тупиковой ситуаци и , то происходит
возврат на предыдущи й шаг.
Н есмотря н а то что задача кажется достаточно сложно й , ее решение с
помощью рекурсии таковы м не является.
Допустим , и меется глобальный двухмерны й массив Field, представляю
щи й максимально возможное игровое поле :
Field :
�
tiiiiJ
Array [ 1 . . 2 0 ,
1. .20]
Of
Int eger ;
Примечание .
Поиск одного решения задач и для nоля В х В зани мает на комn ь ютере AM D
Ath l o n 1 400 M Hz более ч аса.
Две глобальные переменные Махх и махУ, вводимые пользователем , оп
ределяют реальные размеры поля , для которого необходимо найти реше
н ие задачи :
МахХ ,
МахУ :
Intege r ;
Глобальная переменная N определяет текущее ч исло (номер ш ага) :
N:
Int ege r ;
Тогда процедура вы вода на экран игрового поля будет выглядеть следу
ющим образом :
Proc edure Wri t e Po s i t i o n ;
Var
х , у : Int ege r ;
{ о пи с а н и е л о к а л ь ных п е р еме н ных для
испол ь з о в а ния в каче с т в е счетчиков цикла }
437
Turbo Pascal 7 . 0
begin
ClrScr ;
for y : = l to МахУ do
for x : = l to махх do
Begin
Got oXY ( x * 4 , у* 2 ) ;
Wri t e ( Fi e l d [ x ,
у] ) ;
{ в н е шний цикл по выс о т е п ол я }
{ вложен ный цикл по шир и н е п о л я }
{ п о зиционир о в а ни е к ар е т ки - р а с с т о я н и е
между кле т ками будет 4 симв ола п о ширине
и 2 симв ола п о выс о т е }
{ вывод числа и з о ч е р е д н о й яч е й ки п о л я
на экран }
end ;
end;
Ре к ур сивна я п р оцеду ра б удет иметь два параметра - к оо рдинаты клетки
на п оле, дл я к ото р ой вызываетс я данны й экземпл я р процедуры .
P roc edure
Move ( x ,
begin
N := N + 1;
Field [ x , у ]
: =
I f N = МахХ *
у : Integer ) ;
{ з а г о л о в о к процедуры , п а р аме тры х и у
о п р е д е л яют к о орди н а т ы к л е т к и н а п о л е }
{ ув еличение т е куще г о чи сла на единицу }
N ; { з а н е с е н и е т е куще го числа в т е кущую кле т ку }
МахУ Then
{ е сли т е куще е число р а в н я е т с я коли ч е с т в у
кле т о к н а п о л е , з н а чи т , в с е кл е т ки з а п ол н е ны
и з а д а ч а реше н а }
Begin
Writ eLn ( ' Е С'l'Ь решение ! ! ! • ) ;
Wr itePo s i t i on ;
ReadКey ;
ha lt ;
{ с о о бщение п о л ь з о в а телю об у с п е ш н о м р е ше нии
end;
з адачи , выв о д н а э кр а н з а п о лн е н н о г о п о л я ,
ожид а н и е н аж ат и я н а к л а в ишу и вых о д и з
п р о г р аммы { и с п ол ь з о в а н а п р о ц е дура H a l t
б е зусл о в н о г о з а в ерше н и я п р о г р а ммы ) }
I f ( х + 2 < =МахХ ) and ( y+ l < =MaxY ) Then
{ е сли клетка , нах одяща я с я на д в е кле т ки пра в е е
и на одну кле тку ниже те кущей кле т ки , не выходит
за пределы рабочего пространства игрового поля ,
ограниченного значе ниями переменных МахХ и МахУ ,
то выпол н я е т с я сле дующа я с т р о к а }
I f F i e l d [ x + 2 , y+ l ] = O Then move ( x+ 2 , y+ l ) ;
{ е сли кл е т к а , н а х одяща я с я н а д в е к л е тки
пр а в е е и н а одну кл е т ку ниже т е кушей кл е т ки ,
содержи т число О , то для н е е следуе т выполнить
п р о ц е дуру Move }
I f ( x+ l < =MaxX ) and ( у+ 2 < =МахУ ) Then
438
Глава 1 3 . Рекурсия
If
F i e l d [ х+ 1 ,
I f ( х - 1 > 0 ) and
If Field [x- 1 ,
I f ( х - 2 > 0 ) and
If Field [ х - 2 ,
I f ( х - 2 > 0 ) and
I f Field [x- 2 ,
I f ( х - 1 > 0 ) and
If F i e l d [ x - 1 ,
I f ( х+ 1 < =М&хХ )
If F i e l d [ x+ 1 ,
I f ( х + 2 < =МахХ )
If Field [ x + 2 ,
N := N
Field [ x ,
end;
-
1;
у] : = 0 ;
у+ 2 ] =О Then move ( х+ 1 , у+ 2 ) ;
{ а н а л о ги ч н а я n р о в е р к а для кл е т ки , н а х о дяще й с я
н а одну кл е т ку nр а в е е и дв е кл е т ки ниже
т е кущей кл е т ки }
( у+ 2 < =МахУ ) Then
у+ 2 ] = 0 Then move ( x- 1 , у+ 2 ) ;
{ а н ал о ги ч н а я n р о в е р к а для кл е т ки , н а х одяще й с я
н а о д н у кл е т ку л е в е е и д в е кл е т ки ниже
т е куще й кл е т ки }
( у+ 1 < =МахУ ) Then
у+ 1 ] = О Then move ( х- 2 , у+ 1 ) ;
{ а н а л о гич н а я nр о в е р к а для кл е т ки , н а х одяще й с я
н а д в е кл е т ки л е в е е и одну к л е тку ниже
т е кущей кл е т ки }
( у- 1 > 0 ) Then
у- 1 ] = О Then move ( x - 2 , у- 1 ) ;
{ а н а л о ги ч н а я n р о в е р к а для кл е т ки , н а ходяще й с я
н а д в е кл е т ки л е в е е и одну кл е т ку выше
т е кущей кл е т ки }
( у- 2 > 0 ) Then
у- 2 ] = О Then move ( x - 1 , у- 2 ) ;
{ а н ал о гичн а я n р о в е р к а дл я кл е т ки , н а х о дяще й с я
н а о д н у кл е т ку л е в е е и д в е кл е т ки выше
т е кущей кл е т ки }
and ( у- 2 > 0 ) Then
у- 2 ] = О Then move ( x+ 1 , у- 2 ) ;
{ а н а л о гичн а я n р о в е р к а дл я кл е т ки , н а х о дяще й с я
н а одну кл е т ку nрав е е и д в е кл е т ки выше
т е кущей кле т ки }
and ( у- 1 > 0 ) Then
у- 1 ] = О Then move ( x + 2 , у- 1 ) ;
{ а н а л о г и ч н а я nр о в е р к а дл я кл е т ки , н а х о дяще й с я
н а д в е кл е т ки nра в е е и о д н у кл е т ку выше
т е кущей кл е т ки }
{ е сли уnра вление nерешло к этой строк е , з н а чит ,
в с е n е р емеще ния о т н о си т ел ь н о т е куще й кл е т ки
з а к о нчили с ь неудач н о , сле д о в а т е л ь н о , т е кущий
н омер нужно удал и т ь , а в т е кущую к л е тку
n о с т а в и т ь nри з н а к н е з а н я т о с ти ( з н а ч е ни е О ) }
{ возврат
к
nредыдущему ш а г у }
Все , что требуется теперь от основно й части п рограмм ы , - это запро
сить у пользо вателя рабочие размеры поля и в ызвать рекурсивную про
цедуру с параметра м и , оп ределяющими координату начал ьной клетки
(левая верхняя клетка имеет координаты 1 , 1 ) . Полн ы й текст програм мы
приведен в листи нге 222.
439
Turbo Pascal 7 . 0
.:�h.d!@�.:�2�?· ��,������;!��д��'�.1��f�����������t1\��1:��,·�!М��:;�;w���������)t�:;J:;;:
Program HorseMoving ;
Uses
CRT ;
va r
F i e l d : Array [ 1 2 0 ] Of Array [ 1 2 0 ] Of Integer;
{ п е р е ме н н а я -ма с с и в дл я х р а н е н и я и г р о в о г о п о л я }
N : Integer ;
{ п е реме н н а я , о пределяюща я н омер т е кущ е й к л е т к и }
махХ , МахУ : Int eger ;
{ п е р еме нные , о п р е д е л яющи е р а змеры р а б о ч е й
ч а с ти и г р о в о г о п о л я }
х , у : Intege r ;
{ в с п о мо г а т е л ь ные п е р е ме н ные для о б н ул е ни я
ма с с и в а с и г р о в ым п о л е м п ер е д выз о в ом
р е кур с и в н о й п р о ц е дуры }
•
•
Procedure Wri t e P o s i t i on ;
Va r
х , у : Intege r ;
begin
ClrSc r ;
f o r у : = 1 t o МахУ do
for х : = 1 to махх do
Begin
Got oXY ( x* 4 , у* 2 ) ;
Writ e ( Fi e l d [ x , у ] ) ;
end ;
end;
•
•
{ описание
п р о ц е дуры Wri t e Po s i t i o n }
Procedure Move ( x , у : Integer ) ;
{ описание
begin
N := N + 1;
Field [х, у] : = N ;
I f N = МаХХ * МахУ Then
Begin
WriteLn ( ' Е сть решение ! ! ! ' ) ;
Wri t ePos i t ion;
ReadКey ;
hal t ;
end ;
I f ( х+ 2 < =махх ) and ( у+ 1 < =МахУ ) Тhen
I f F i e l d [ x + 2 , у+ 1 ] = 0 Then move ( x + 2 , у+ 1 ) ;
I f ( х+ 1 < =махх ) and ( у+ 2 < =МахУ ) Then
I f F i e l d [ x+ l , у+ 2 ] = 0 Then move ( x+ 1 , у+ 2 ) ;
I f ( х - 1 > 0 ) and ( у+ 2 < =махУ ) Тhen
I f F i e l d [ x - 1 , у+ 2 ] = 0 Then move ( x - 1 , у+ 2 ) ;
I f ( х - 2 > 0 ) and ( у+ 1 < =МахУ ) Тhen
I f F i e l d [ x- 2 , у+ 1 ] = 0 Then move ( x - 2 , у+ 1 ) ;
440
п р о ц едуры Move }
Глава 1 3 . Рекурсия
I f ( х - 2 > 0 ) and
If F i e l d [ х - 2 ,
If ( х - 1 > 0 ) and
If F i e l d [ x - 1 ,
I f ( х+ 1 < =МахХ )
If F i e l d [ x+ 1 ,
I f ( х+ 2 < =М&хХ )
If F i e l d [ x + 2 ,
N := N
1;
Field [ х , у ) : = О ;
end;
( у- 1 > 0 ) Then
у- 1 ) = 0 Then шоvе ( х- 2 ,
( у- 2 > 0 ) Then
у - 2 ) = 0 Then шоvе ( х- 1 ,
and ( у- 2 > 0 ) Then
у - 2 ) = О Then шоvе ( х+ 1 ,
and ( у- 1 > 0 ) Then
у - 1 ) = 0 Then шоvе ( х + 2 ,
у- 1 ) ;
у- 2 ) ;
у- 2 ) ;
у- 1 ) ;
-
Begin
ClrSc r ;
{ о б нул ение п еременной , содержащей т е куще е чи сл о }
N := О;
Wri t e ( 1 Введите ширину nоля ( от 1 д о 2 О ) : 1 ) ;
ReadLn ( Махх ) ;
Wri te ( 1 Введите высоту nоля ( от 1 до 2 О ) : 1 ) ;
{ в в о д ширины и высо ты р а б о ч е й ч а с ти
ReadLn ( MaxY ) ;
игрового поля }
For х : = 1 То Махх Do
For у : = 1 То махУ Do Field [ x , у ] : = 0 ;
{ о б нул е н и е э л еме н т о в ма с с и в а р а б о ч е й ч а с т и
и г р о в о г о п о л я в л о ж е н ным цикл о м }
C l r Sc r ;
{ вы з о в р е кур с и в н о й п р о ц е дуры с у к а з а ни е м
Move ( 1 , 1 ) ;
н а ч а л ь н о й кле тки п е р е б о р а - л е в ой в е р х н е й }
1 );
Wri t eLn ( 1 Реше ние не н айден о
{ е сли упр а вл е н и е п е р е д а н о э т ой с т р о к е
п р о г р аммы , з н а чи т , в р е з ул ь т а т е п е р е б о р а
р е ш е н и е н е найде н о }
•
•
•
End .
Задача «Ход коня>> , подробно рассмотренная нам и , будет им еть намного
меньшее время работы , если вызовы очередного э кземпляра рекурсивной
процедуры моvе сначал а осуществлять для тех точек, которые им еют наи
меньшее количество вызовов.
Еще одной классической задачей , решаемой с помощью рекурс и и , явля
ется нахождение кратчайшего пути в графе
совокупности точек, со
единенных между собой в п роизвольном порядке . Точки , из которых со
стоит граф , называются вершинами графа, а ли н и и
ребрами графа
(рис. 1 5 1 ) . Для каждого перехода от одной вершины к другой по ребру
графа (есл и ребро имеется) задается время этого перехода. Задача состо
ит в то м , чтобы н айти кратчайшее время перехода от одно й задан ной
точки к друго й .
-
-
441
Turbo Pascal 7 . 0
Верш и н ы графа
В г р а ф е , п р ед с т а в л е н н о м н а
рис. 1 5 1 , из точки 1 в точку 8 мож
но попасть двумя путя м и :
1 . Через вер ш и н ы 1 - 6 - 3 - 8 .
2. Через верш и н ы 1 - 5 - 2 - 8 .
Рис.
1 5 1 . Гра ф
Ребра графа
Решение задачи сводится к рекур
сивному перебору всех возможных
путей , определению суммарного вре
мени перехода для каждого из них и
выбору пути , имеющего минимальное время перехода.
Данная задача имеет огромное прикладное значен ие для о птим изации ка
кого-либо п еремещения в пространстве и и меет названи е Транспортная
задача в сетевой постановке. Например, для перевозки груза из одной части
страны в другую могут использоваться сотни вариантов различных путей ,
н о только один и з них будет оптимальным. Решен ие такой переборной
задач и человеку не под силу, поэтому программ ы , решающие ее, могут
быть очень полез н ы .
Напоследок хотелось бы заметить, что з а простоту и элегантность рекур
сивных решений задач приходится nлатить быстродействием програм м .
Вызов подnрограм м ы зан имает довольно много време н и , nоэтому рекур
сивные nроцедуры и функци и , постоянно вызывающие свои экземпляры
в большом количестве , и меют дл ительное время работы .
Очень часто вместо рекурси и можно исnользовать обыч н ы е алгоритм ы ,
в резул ьтате чего программ ы работают знач ительно быстрее . Есл и же
рекурсивн ы й алгоритм невозможно заменить каки м-либо более простым ,
то следует искать пути его опти м изаци и п о скорости. Опти мизация ал
горитма зависит от решаемой задачи , поэтому нет каких-либо общих
nравил его нахожден ия . Обычно такие решения разрабаты ваются различ
ными прикладны м и науками математического наnравления . Например,
задача определения кратчайшего nути в графе может решаться вообще
без рекурсии специальным методом , называемым симплекс - метод, рассмат
риваемы м наукой « М атем атические методы в экономике>> .
Еiце одним применением рекурсивных подпрограмм может быть рекур
си вное сканирование каталога вместе с подкаталогами с использованием
пары процедур FindFirst и FindNext . После нахожден ия очередного
файла процедура м ожет nроверять его тип , которы й возвращается в поле
At tr переменн о й -записи , заданной в качестве параметра nриемник ин
ф ормации процедур FindFirst или FindNext . Если н айде н н ы й файл
является каталого м , то следует вызвать еще один экземпляр процедуры
для скан ирования этого каталога. Таким образом, можно искать какой
л и б о файл не только в текущем каталоге, но и в о всех его подкаталогах.
442
Глава 1 3 . Рекурсия
К онтрол ьн ы е воп ро с ы и ответ ы
Что та кое р е курсия?
это вызов подп рограммой ( п роцедурой и фун кци е й ) самой
Рекурсия
се б я . Основана рекурсия н а том , что началом обл асти види м ости иденти
фи като ра ( в дан н о м случае и м е н и подпрограм м ы ) я вляется строка, в ко
то рой этот идентифи катор описы ваетс я .
-
К а к а я бывает рекурсия?
Рекурсия может быть бесконеч ной и конеч н о й , бесконечная рекурсия н е
и м еет п р и кладноге з н ачения и ведет к заве р ш е н и ю програ м м ы с о ш и б
кой , конечная же рекурсия я вл яется м о щ н ы м средством дл я р е ш е н и я з а
дач переборн ого типа.
В ч е м особенность ис пользования рекурсии?
И сп ол ьзовать ре курси ю сл едует крайне осто рож н о , так как п рограм м ы ,
испол ьзующие е е , обладают крайне н и з к и м б ы строде йств ием . В любом
случае при использован ии рекурсивных ал горитмов необходимо искать пути
их опти мизаци и .
443
�а а
в
И с п о л ь зо в ан и е
в строе н н о го ассе м бл е ра
Команда языка программирования высокого уровня , такого как, напри
мер, Turbo Pascal , обычно представляет собой совокупность нескольких ко
манд процессора. При этом в результирующую программу компилятором
добавляются фрагменты , обеспечивающие корректную работу программы
в рамках операционной системы (сообщения об ошибках в ыхода за пре
делы индексного пространства массивов и другие).
В языках программ ирования высокого уровня реализовано множество слож
ных команд для упрощения процесса программирования, таких как поддерж
ка работы со сложными типами дан ных (например, с множествами) или ре
ализация объектно-ориентированного подхода к разработке программ. Все
это позволяет быстро и качественно разрабатывать программные продукты ,
однако имеет и свои отрицательные стороны. Например, если в программе
массив из нескольких элементов используется таким образом , что выход за
пределы индексного пространства невозможен, то нет необходимости до
бавлять в такую программу проверки корректности работы с массивами.
Лишние команды в результирующей программе увеличивают ее объем и
снижают быстродействие. Также в силу универсальности высокоуровневых
команд они не обеспечивают максимально возможной эффективности по
размеру и скорости для конкретного случая их применения.
Второй , более существенный, недостаток языков высокого уровня связан
с необходимостью использовать при разработке программ ы только те ко
манды, которые предусмотрены разработчиком языка, тогда как процес
сор и операционная система могут иметь намного более ш ирокие возмож
ности . В Turbo Pascal , например, не реализована поддержка работы с
мышью, хотя такие функции поддержи ваются операционной системой
MS-DOS . Для решения подобных проблем в Turbo Pascal встроен язык про
грам мирования низкого уровня - Ассемблер, с помощью которого можно .
выполнить любые действия, допустимые в M S-DOS.
444
Глава 1 4 . Испол ьзование встроен н ого ассемблера
Ассемблер - это язык программирования низкого уровня , набор команд ко
торого отвечает набору команд процессора, для программирования которого
он предназначен. Каждая команда ассемблера сопоставляется одной команде
процессора, из которых можно выделить следующие групп ы :
•
•
•
о п ерац и и перемещения и нформации между ячейками оперативной
п амяти и ячейками оперативной п ам яти процессара (регистрами ) ;
выполнение о пераций ( команд процессора) над информацией , на
ходящейся в его регистрах процессара (нап р имер , ари ф м етические
о пераци и ) ;
вызов системных функций операционной систе м ы (прерыван и й ) .
В результате ком п иляц и и и построения программ ы , нап исанной на ас
семблере, получается результирующий исполняемый файл , который н и
ч е м существенно не отличается о т исполняемых программ , разработан
н ых с п о м о щ ь ю я з ы к о в в ы с о к о го уров ня . При этом и с п ол н я е м ы е
программ ы , написанные на ассемблере, отличаются высоким быстродей
ствием и малым объемом зани маемой оперативной памяти , так как в такие
програм мы не добавляется н ичего , кроме того , что задумано разработч и
ком . С другой стороны, исходный текст программ на ассемблере имеет
размер, значительно превосходящий размеры исходн ых текстов аналоги ч
н ы х программ , написанных на любом языке высоко го уровня .
Таким образом, крайне удобно сочетание языка проrраммирования высокого
уровня, с помощью которого можно реализовать удобную структуру программы,
и ассемблера, с помощью которого можно выполнить некоторые операции , от
суrсrвующие в составе высокоуровневого языка или имеющие недостаточные по
казатели по скорости или объему результирующего кода. Обычно с помощью
встроенного ассемблера реализуются резидентные процедуры, которые должны
занимать наименьший размер, и подпрограммы для работы с графическими объек
тами, которые должны иметь максимально возможное быстродействие.
Задача данной главы - общее знакомство с языком ассемблера и изуче
ние основ работы с ним.
Примечание .
П оскол ьку м ы расс м атри ваем я з ы к ассем б лера в конте ксте его и с п ол ьзова
н и я в T u rbo Pasca l , в насто я ще м разделе о п и с ы вается ассем бл е р п ро цессара
8 0 8 6 , кото р ы й и в строен в Turbo Pascal .
1 4. 1 .
И сп ол ь з о вание ко ман д ассем бл ера
в про г р ам ме
Команды ассемблера могут использоваться в любом месте програм м ы ,
наравне с обыч ными командами Turbo Pascal - в разделе описания ло
гики программ ы , в подпрограммах, а также в иници ализационных сек445
Tu rbo Pascal
7.0
циях библиотек. Для указания компилятору, что некоторый фрагмент
программы содержит команды ассемблера, испол ьзуется ключевое слово
a sm (англ . AssemЬler
Ассемблер) . После завершения блока ассемблер
ных команд следует указать ключевое слово end:
-
asm
<Кома нда а с с ембл е ра >
<Кома нда а с с ембл е р а >
end;
Команды ассемблера в отличие от команд Turbo Pascal не отделяются друг
от друга раздел ителями << ;>> . Каждая команда ассемблернога блока долж
на находиться на отдельной строке.
1 4. 2 . Р е г истр ы п ро ц есс а р а
Процессор и меет собственную область памяти , в ячейках которой долж
на находиться информация , необходимая для выполнения некоторых его
команд. Эти ячейки называются регистрами процессора, представляют со
бой двухбайтовые ячейки памяти и делятся на следующие груп п ы :
l . Регистры данных, предназначенные для временного хранения любой
и нформации и обмена с системными функциями MS- DOS. Регистры
и меют названия АХ, вх, сх и DX. Особенностью регистров данных
является возможность раздельного обращения к их старши м и млад
шим байтам. Старшие байты регистров данных имеют названия АН,
ВИ, СИ И DИ, младшие
AL , BL, CL И DL.
2. Регистры - указатели , предназначенные для хранения адресов памяти в
формате < С е гмент > : < Смещени е > при передаче параметров в систем
ные фун кци и MS-DOS. Регистры -указатели и меют назван ия ВР, SP ,
s:r и D:r . Побайтовая адресация регистров-указателей недопусти ма.
3 . Сегментные регистры, определяющие расположение п рограмм ы в сег
ментах памяти . Используется четыре сегментных регистра: регистр
сегмента команд (cs), регистр сегмента данных ( D S) , регистр допол
н ител ьного сегмента данн ых (ES) и регистр сегмента стека (ss) .
4. Указатель команд (:rP) , п редназначенный для указания относитель
ного адреса команды, следующей за в ы п олняемой в дан н ы й мо
мент. Программ ы н е имеют п рямого доступа к дан ному регистру.
5. Регистр флагов (FLAGS) , содержащи й некоторые резул ьтаты п ослед
ней выпол н е н н о й команды, например выход значения , п олученно
го в резул ьтате арифметической операци и , за пределы допустим ых
знач е ни й .
-
446
Глава 1 4 . Ис п ол ьзование встроен ного ассемблера
1 4. 3 . О перац и и переме щ е ния и нформ а ц ии
Операци и перемещения и нформации предназначены для изменения зна
чен и й , находящихся в оперативной памяти или регистрах процессора, и
имеют п о два операнда - первый , значение которого следует изменить,
и второй , значение которого следует присвоить первому. О перанды ука
зываются через запятую , без использования круглых скобок:
< О п е р а ц и я п е р ем еще н и я > < И зме н я емый о п е р а н д > ,
< З н а ч е ни е >
Простейшей операцией пересылки является команда mov (англ . Move
переместить) , позволяющая пом естить значение в регистр дан ных про
цессара или ячейку операти вной памяти (см. л истинг 223 ) .
:.�;;��:Wi'��f:· . 2 ��·;'_:··�ьr�#:��9.��к��f������,P:�i'Шn§�,: ·,т"ц�·:yn; ,:·� :r·i (;7:':;:·(f.· .::. �;;;·:;·::r j._},-:;�':;,' :•
Begin
asm
АХ ,
mov
ВХ
end ;
End .
{ н а ч а л о р а з д е л а о п и с а н и я л о ги к и п р о г р аммы }
{ н а ч а л о бл о к а а с сембл ер ных кома нд }
{ з а н е с е н и е в р е гистр АХ з н а ч е н и я и з р е г и с т р а ВХ }
{ о к о н ч а н и е б л о к а а с с ембл ер ных к ома н д }
{ о к о н ч а н и е р а здела о п и с а н и я л о гики п р о г р аммы }
Размерность операндов при использовании команды mov должна совпадать,
то есть двухбайтовое значение можно занести только в двухбайтовый при
емник, а однобайтовое - только в однобайтовый (см. листинг 224) .
Begin
{ начало
asm
end ;
{ н а ч а л о б л о к а а с с ембл ер ных кома н д }
{ з а н е с е н и е в с т арший б а й т р е г и с тр а АХ
и з мл а дш е г о б а й т а р е г и с тр а ВХ }
{ о к о н ч а ни е бл о к а а с с ембл ер ных к ома н д }
End .
{ о ко н ч а н и е
АН ,
mov
BL
раздела
описания
р а здела
л о г и ки
описания
п р о г р аммы }
л о гики
з н а ч е ни я
п р о граммы }
К операциям перемещения информации относятся также команды рабо
ты со стеком : push (англ. Push - толкать) - положить значение в стек и рор (англ . Рор - извлечь) - достать значение из стека. Эти команды
имеют по одному операнду, определяющему, соответственно, какое имен
но значение следует положить в стек и в какой регистр или ячейку па
мяти следует занести вынутое из стека значение (см. листинг 225 ) .
�i��.,.�t�Ar::2,,?�:� .:�.� g-�;��-��-���ж��tr�9м�:�:ц, ::P��.�::��:�·�.�'.:1.��;,,:f::I�;·;;!·:·;: ··:·'·:i···;:-:·:�1;�,•·;i;; :.� . .
Va r
Z:
Intege r ;
Begin
z
: =
10 ;
{ о п и с а н и е ц е л о чи с л е н н о й п е р е ме н н о й }
{ н а ч а л о р а зд е л а о пи с а н и я л о г и к и п р о г р аммы }
{ при с в о е ни е
з н а ч е ни я
п е р еме н н ой
Z}
447
Turbo Pascal 7 . 0
asm
АХ ,
mov
{ н а ч а л о б л о к а а с с ембл е рных кома н д }
{ з а н е се ни е в р е гистр АХ з н а ч е н и я 5 }
5
push АХ
{ nомеще н и е
р ор Z
end;
Writ eLn ( 1 Z
з н ач е ни я р е ги ст р а АХ
(5)
в
стек }
{ из ъ я т и е двух б а й т о в о г о з н а ч е н и я и з с т е ка
n омеще н и е е г о в n е р еме н ную Z }
{ о к о нч а ни е б л о к а а с с ембл ер ных кома н д }
Z ) ; { выв од з н а ч е н и я n е р еме н н ой Z }
=
{ о к о нч а ни е р а здела
End .
о n и с а н и я л о ги ки
и
nро граммы }
Результатом выполнения данной программы будет вывод на э кран стро
ки « Z
5».
=
Остальные команды перемеще н ия и нформации п редлагают возможности
перемещения байтов из одно й строки в другую, требуют более глубокого
знания ассемблера и нами рассматриваться не будут.
1 4. 4. И спол ь з ов ание ко манд п роцесс а р а
В качестве примера использования команд процессара мы рассмотрим (см .
листинг 226) применение операции арифметического сложения add (англ .
Add - добавлять) , и меющей два операнда:
•
•
регистр или адрес ячейки п амяти , где находится п ервое слагаемое;
регистр или адрес ячейки п ам яти , где находится второе слагаемое.
В качестве второго слагаемого могут использоваться константы. Операция
сложения является целочисленной и не может при меняться к веществен
ным значениям. Результат сложения заносится в область памяти , задан
ную первым операндом .
Va r
Z:
Integer ;
{ оnисание
{ начало
Begin
z
: =
целочи сл е н н о й
р а здела
{ nри с в о е н и е
10 ;
a sm
{ начало
оnисания
значения
блока
л о ги ки
п е р е ме н н о й
а с с ембл е р ных
кома н д }
Z
{ з а н е се ни е
add АХ ,
5
{ ув е л и ч е н и е з н а ч е н и я р е г и с тр а АХ н а 5 }
{ з а н е с е н и е в nереме н ную Z з н ач е ни я р е г и с тр а АХ }
mov
Z,
АХ
end;
Writ eLn ( 1 Z
=
1
р е г и с т р АХ
n р о г р а ммы }
Z}
АХ ,
mov
в
n е р еме н н о й }
значения
n е р е ме н н о й
Z}
{ о к о н ч а н и е б л о к а а с с ембл ер ных к ома н д }
з н а ч е н и я п е р еме н н ой Z }
Z ) ; { вывод
{ окончание раздела описания логики nро граммы }
End .
Резул ьтатом вы полнения данной программы будет вы вод на э кран стро
ки << Z
1 5 >> .
=
448
Глава 1 4 . Испол ьзов ан ие встрое н н ого ассемблера
1 4. 5 .
В ы з ов сист е м н ы х фун кц и й M S - DOS .
И спол ь з ов ание п рерыв а н и й
Одно й и з важней ших частей функционирования ком пьютера являются
прерывания - процессы остановки работающей в дан н ы й момент про
граммы и передач и управления в какие-либо другие подпрограммы. Пре
рывания могут возникать тремя путями :
l . Аппаратные прерывания - возни кающие п р и изменени и состояния
каких-либо устройств: клавиатуры , мыши или тай м ера.
2 . Внутренние прерывания - возни кающие при в ы п олнении некото
рых о п ерац и й п роцессора, например п р и возн и кновени и о ш ибки
деления на нол ь .
3. Программвые прерьmания
вызываемые выполняемы м и програм
мами для обеспечения собственной функциональности : вывод и н
формаци и н а экран , считывани е с клавиатуры ил и м ы ш и , работа с
файловой системой , и др.
-
Начало оперативной памяти (от адреса O O O Oh до адреса O З FFh) отводится
под так называемые векторы прерываний
указатели на адреса памяти , в
которых хранятся специальные подпрограммы
обработчики прерываний.
-
-
Обработчики прерываний используются в программах в двух случаях: ког
да необходимо переопределить поведение системы при вызове какого-либо
прерывания (так п ишутся резидентн ые программ ы , в том числе вирусы)
и когда необходимо воспользоваться подпрограммой-обработчиком пре
рывания. Нас интересует второй вариант использования прерыван и й , ко
торый и является в ызовом системных функций M S - D O S . Подпрограмм ы
B I O S , выполняющие множество полезных задач , распределены по пре
рываниям , и их можно вызвать с помощью команды ассемблера int (англ .
lnterrupt - прерывать) , в качестве параметра которой указывается номер
прерывания , которое нужно вызвать:
int
<Номер пре рыв а ни я >
Прерывания могут объединять в себе несколько подпрограм м . Какую
именно из этих подпрограмм следует вызвать, определяется значением ре
гистров ( данные о номерах конкретных функций и их параметрах содер
жатся в различных справочниках, например в програм ме Tech Help) , па
раметры системным функциям также передаются через регистры .
Например, п реры ван ие с н о мером l б h содержит подпрограм му с н о
м е р о м 0 2 h , котор ы й при вызове фун кции должен б ы т ь занесен в р е
гистр АН . В качестве результата п осле работы функци и в ре гистре AL
возвращается так н азывае м ы й флаг состоя н ия кл ави атуры , кажд ы й бит
которого определяет состоя ние соответствующей клавиши ( 1 - нажато ,
О - не нажато ) . Соответствие каждого б ита конкретной кл ави ше п о
казана в табл . 8 .
15
Зав:. 702
449
Turbo Pascal 7 . 0
Состав флага состояния клавиа туры Таблица В
При ведем пример использован ия
в ы з о в а о п и с а н н о й с и сте м н о й
Соответству ющая кпавиwа
Номер бита
функции . Для проверки значения
П р авый S h ift
1
второго бита будем использовать
Левый S h i ft
2
операцию логического умножения
Ctrl
3
(AND) значения перемен ной , со
4
Alt
Scro l l Lo c k
5
держащей флаг состояния клави
6
N u m Loc k
атуры , на ч и сло , в котором все
7
Caps Loc k
б иты равн ы нулю, а второй бит
равен единице. Результат такой операции будет равен второму операнду,
если второй бит первого операнда равен единице:
Флаг клавиатуры . . . . . . . . . . . . . . . . . 1 1 000 1 1 1
Вспомогательн ы й операнд . 000000 1 О
Результат: . . . . . . . . . . . . . . . . 000000 1 О
.
. .
.
. . .
. .
.
.
. .
.
или нулю, если второй байт первого операнда равен нулю:
Флаг клавиатуры . . . . . . . . . . 1 1 000 1 0 1
Вспомогательный операнд . 000000 1 О
Результат: . . . . . . . . . . . 00000000
.
. . . .
.
. .
. .
.
. .
. . . .
.
.
. . . .
. .
.
:,;;·ij�:9�И�.r: 2,27;-�иc'�6�·��C)�����·.������,9.��ii,��r���;���i9��ц:�'й'Л::�;'�;�(tii!I;�4�itD�t
.
.
Program Int errup t s l ;
Uses
CRT ;
Funct i on LShi f t P r e s sed : Bool ean ;
Va r
Status : Byt e ;
{ о п и с а н и е о д н о б а й т о в ой п е р еме н н о й }
begin
{ н а ч а л о с е кции а с с ембл е р ных кома нд }
a sm
mov АН, 0 2 h
{ з а н е с е ни е в с т а рший б а й т р е г и с т р а АХ н омер а
вызыв а емой функции ( 0 2 h ) }
{ выз о в пр ерыв а н и я с н омером l бh }
int 16h
mov Status , AL
{ п е р е н о с з н а ч е н и я , в о з в р а ще н н о г о фун к ц и е й и з
р е г и с т р а AL , в п е р еме н ную S t a tus }
end;
i f ( Status and 2 ) > 0
then LShi f t Pre s s e d : = True
e l s e LShi ftPressed : = Fal s e ;
{ пр о в е р к а з н а ч е н и я в т о р о г о б и т а п е р еме н н ой
S t a tus ( л о гиче с к о е умн о ж е н и е п е р е ме н н о й S t a t u s
и д в о и ч н о г о з н а ч е н и я 0 0 0 0 0 0 1 0 ) ; е сли б и т
ед и нич ный , то в о з вращаем з н а ч е н и е Tru e ,
т а к к а к э т о з н а чи т , ч т о л е вый Shi f t н а жа т }
end;
450
Глава 1 4 . Испол ьзован ие встроен н ого ассемблера
Begin
ClrS c r ;
{ ци кл
repeat
Got oXY ( l O ,
if
10 ) ;
до
н ажатия
клавиши }
{ п о зици о н ир о в а н и е
к а р е т ки }
LShi f t P re s s ed
1 )
кажимается 1 ) ;
then Wri te ( 1 Нажимается: левый
Shi f t
e l s e Wri t e ( 1 Левый Shi ft не
{ выв о д с о о бщения
unt i l
о
•
•
•
с о с т о я ни и
к л а в иши }
KeyPre s s ed;
End .
1 4. 6 . И спол ь з ов ание м ы ш и
в п р о г р ам мах Tu rbo Pascal
В качестве примера использования встроенного ассемблера мы разработа
ем библиотеку подпрограмм для работы с мышью, не включенную в стан
дартную поставку Turbo Pascal (см. листинг 229) . Использован ие мыши
существенно отличается от использования клавиатуры. Во-первых, для под
держки мыши требуется драйвер, который должен быть запущен перед
началом работы программы, использующей мышь. Драйвер для мыши обыч
но входит в ее комплектацию, но разработано и множество других драй
веров, таких, например, как программа mouse.com и др. Второе существен
ное отличие мыши от клавиатуры заключается в том , что программа не
может ждать перемещения мыши , как ждет нажатия на клавишу функция
ReadKey. Программа должна сама регулярно опрашивать состояние мыши
и выполнять какие-либо действия на основе анализа ее положения.
После запуска драйвера м ы ш и на экране появляется так назы вае м ы й
указатель мыши, имеющий форму прямоугольника в текстовом режиме и
. стрелки в графи ческом режиме. Вывод указателя на экран и его перемещение поддерживаются непосредственно операционной системой , поэтому
програм м а не должна заботиться об это м .
Переч ислим действия , которые может выполнять п рограмма (см. л и с
ти нг 2 2 9 ) над указателем м ы ш и :
1 . Скрытие указателя м ы ш и и его отображен и е с п омощью функций
0 2 h и O lh п рерывания З З h.
2. Установка прямоугольной области экрана, в которой может переме
щаться указатель м ы ш и . Диапазон горизонтал ь н ых координат облас
ти устанавл ивается функцией 07h прерывания З З h и задается регис
т р а м и с х ( м и н и м ал ь н ая го р и з о нтал ь н ая к о о рд и н ат а ) и D X
(минимальная горизонтальная координата) , диапазон вертикальных
координат области устанавливается функцией 0 8h прерывания З З h и
также задается регистрами сх и DX.
45 1
Turbo Pascal
7.0
3 . Установка указателя мыши в какое-либо положение внутри допус
ти мой о бласти производится функцие й 0 4 h п рерывания З З h . Коор
ди наты м ы ш и при этом задаются в регистрах сх и DX.
4. Получение координат мыши и состояния ее кно п о к производится
функцией О З h п рерывания З З h. Координаты м ы ш и возвращаются в
регистрах сх и DX , а состояние кнопок - в регистре вх.
:l;-:nиc1:��-� �'22���f������!�i5��Ji�!1�4���,��m1i����·J:�i��щ��;���ii���::ilii�*w•k/
Uni t
Mouse ;
Int erface
Тур е
TBtnState
=
Set
Of ( Le f tButt on , RightBut ton } ;
{ ти n д а нных - мн оже с т в о и з двух э л е ме н т о в ,
Lef tBut ton у к а з ыв а е т н а т о , ч т о н а ж а т а л е в а я
кноnка мыши , RightButton
нажата nравая кноnка }
-
Procedure
ShowMous e ;
{ з а г ол о в о к n р о ц е дуры о т о бр а ж е н и я
у к а з а т е л я мыши н а э к р а н е }
Proc edure
Hi deMou s e ;
{ з а г о ло в о к n р о ц е дуры скрытия
мыши н а э к р а н е }
Procedure
SetMous e ( X , У : Integer } ;
{ з а г о л о в о к n р о ц е дуры n е р емеще н и я у к а з а т е л я
мыши в т о ч ку , з ад а н ную n а р аме трами Х и У }
Proc edure
S etMouseBounds ( Xl , Yl : Int ege r ; Х2 , У2 : Integer } ;
{ з а г о л о в о к n р о ц е дуры у с т а н о в ки n р ямо у г ол ь н о й
о бл а с ти э кр а н а , в к о т ор о й мож е т n е р емеша т ь с я
ука з а т е л ь мыши , n а р аметры з а дают к о орди н а ты
о бл а с ти }
Procedure
GetMouse ( Var
Var But t on s :
Х,
У:
указ ателя
Intege r ;
TBtnStat e } ;
{ з аголовок nроцедуры nроверки nараме тров мыши
к о ордин а т ука з а т ел я ( ) и с о с т о я н и я к н о n о к }
Impl ement a t i on
Proc edure
SetMou s e ;
begin
asm
mov АХ ,
0 0 04h
mov сх ,
х
mov DX ,
int
end;
end ;
452
33h
у
{ в р е г и с тр АХ
{ в р е г и с тр СХ
н омер функции ( 4 h ) }
гори з о н т а л ь ную к о ордин а ту }
{в
в е р ти ка л ь н ую
р е г и с тр
{ вы з о в
DX
nрерыв а н и я
З Зh}
к о о р ди н а т у }
Глава 1 4 . Испол ьзование встроен ного ассемблера
Procedure
begin
a sm
mov АХ ,
S etMou s eBounds ;
0 0 07h
mov СХ ,
Х1
mov DX ,
Х2
int 3 3 h
mov АХ ,
mov сх ,
O O O Sh
У1
mov DX ,
У2
int
end ;
33h
{ в р е г и с тр АХ - номер функции ( 7 h ) }
{ в р е ги с тр СХ - ми нима л ь ную г о р и з о н т а л ь ную
к о ор ди н а ту о б л а с т и }
{ в р е г и с тр DX - ма к с има л ь ную г ориз о н т а л ь ную
к о ордин а ту о б л а с т и }
{ вы з о в прерыв а н и я 3 З h }
{ в р е г и с тр АХ - номер функции ( Bh ) }
{ в р е г и с тр СХ - ми нимал ь ную в е р т и к а л ь ную
к о орди н а ту о б л а с т и }
{ в р е ги с тр DX - ма к сималь ную в ер т и к а л ь ную
ко ордин а ту о бл а с т и }
{ вы з о в прерыв а н и я З З h }
end ;
Proc edure
Var
GetMous e ;
tmpX , tmpY , ПtmpBut t :
begin
asm
mov АХ,
int
О О ОЗh { в
33h
mov tmpX , сх
mov tmpY , DX
mov tmpВutt , вх
Int eger ; { оnисание
лоiСальных
nеременных }
регистр АХ - номер функции ( З h ) }
{ вы з о в прерыв а н и я З З h , в р е г и с тр а х СХ и DX
п о сл е вып о л н е н и я функции н а х о д я т с я к о орди н а ты
ука з а т ел я , в р е ги с т р е ВХ - с о с т о я ни е к н о п о к }
{ в п е р еменную tmpX - з н а ч е н и е и з р е г и с тр а СХ }
{ в п е р еме нную tmpY - з н а ч е н и е и з р е ги с т р а DX }
{ в переменную tmpButt - значение из р е гистра ВХ }
end;
х
у
:=
tmpX ;
tmpY ;
{ з а полняем значения переме нных - п араме тров Х и У
з н а ч е ни ями , п олуч е н ными в р е ги с т р а х СХ и DX
п о сле в ыз о в а функции }
Buttons : = [ ] ;
{ в параметр- переменную Buttons - пустое множество }
I f ( tmpButt and 1 ) = 1 Then
But t ons : = But tons + [ LeftButton] ;
{ е сли п ервый бит в переменной tmpButt - единица ,
то д о б а вляем в мн оже с т в о Bu t t ons э л е ме н т
L e f t Bu t ton }
I f ( tmpButt and 2 ) = 2 Then
But tons : = But t ons + [RightBut ton ] ;
{ е сли в торой бит в переменной tmpBut t - единица ,
то д о б а вл я ем в мн оже с т в о Bu t t ons э л е ме н т
R i gh t Bu t t o n }
end;
: =
453
Turbo Pascal 7 . 0
Procedure
HideMou s e ;
begin
a sm
mov АХ ,
{ в р е ги с тр АХ
0 0 02h
i n t З Зh
{ вы з о в
-
номер функции
пре рыв а н и я
( 2h) }
ЗЗh}
end;
end;
Proc edure
ShowMous e ;
begin
asm
mov АХ,
int
{ в р е ги с тр АХ
0 0 0 1h
З Зh
{ вы з о в
-
пр ерыв а н и я
номер функции
( 1h ) }
ЗЗh}
end;
end;
end .
li,??;*)�]�;�,c���·;,��;fiil�;�t����:i�д�;:����t��i,,
Program МU s e r ;
Uses
CRT ,
Mouse ;
Var
Х,
У:
{ пе р еме н ные для хр а н е н и я т е куще г о
п о л о ж е н и я у ка з а т ел я }
TBtnStat e ;
{ п ер е ме н н а я -множе с т в о для хр а н е ни я
т е куще г о с о с т о я ни я }
Intege r ;
Butt ons :
Begin
ClrScr ;
{ выз о в проце дуры о т о бр а ж е н и я у к а з а т е л я мыши
п р ямоуг оль ник р а змером с симв о л }
ShowMous e ;
-
Repeat
GetMou s e ( X ,
У,
Buttons ) ;
{ выз о в проце дуры о п р е д е л е н и я п а р аме т р о в мыши ,
в п е р емен ные Х и У з а н о с я т с я к о о р ди н а ты
ук а з а т е л я , в п е р еме н ную Bu t t ons
м н о же с т в о ,
о п р е д е л яюще е с о с т о я ни е к н о п о к }
-
Got oXY ( l O ,
10 ) ;
Wri t e ( ' X =
•,
Got oXY ( 1 0 ,
11) ;
454
Х,
• У = • , У,
');
{ выв од к о ордин а т у к а з а т е л я
в
п о зицию 1 0 ,
10}
Глава 1 4. Использован ие встроен н ого ассемблера
if LeftButton in Butt ons
1 )
Then wri t e ( 1 Нажа'l'а л е в а я кноnка
E l s e wri t e ( 1 Левая кноnка не нажа'l'а 1 ) ;
{ е сли Lef tButton содержится в множе с т в е
то вывод строки Нажата л е в а я кнопка . . . ,
выв од с т р о ки Л е в а я к н о п к а н е н а жа т а }
•
GotoXY ( l O ,
•
•
Buttons ,
иначе -
12 ) ;
i f RightBut t on in But tons
1 )
Then writ e ( 1 Нажа'l' а nравая кноnка
E l s e wri t e ( 1 Правая кноnка не нажа'l'а 1 ) ;
{ е сли RightBut ton содержится в множестве Buttons ,
т о выв од с т р о ки «Нажа т а пра в а я к н о п к а . . . » ,
иначе - вывод строки «Пр а в а я к н о п к а н е нажата» }
•
Unt i l keypressed;
•
•
{ ус л о в и е з а в ершения цикла - н а ж а т и е
кл а виши н а кл а в и а т ур е }
любой
End .
Текст програм м ы , и с п ользующей библи отеку процедур для работы с
мышью в графическом режиме, представлен в л истин ге 230.
:�:��i�;�;��j1tn���":;���l��/#!",�: �::""ж::��1r���ffl��rl�Ji����i!'
Program Muser2 ;
Uses
CRT ,
Va r
Gd ,
Х,
Graph ,
Gm :
Intege r ;
sY :
String ;
У:
sX ,
Mous e ;
Intege r ;
But tons :
{ п е р еме н ные д л я хр а н е ни я с т р о к о в о г о
п р е д с т а в л е ни я к о о р ди н а т ук а з а т е л я }
TBtnStat e ;
Begin
Gd
: =
Detec t ;
Gm
: =
О;
Init Graph ( Gd ,
Gm ,
1 1
)
;
S e t C o l o r ( Wh i t e ) ;
ShowMou s e ;
SetMouseBounds ( O ,
О,
639 ,
47 9 ) ;
Repeat
GetMous e ( X ,
Str ( X ,
У,
But tons ) ;
sX) ;
455
Turbo Pascal
Str ( Y ,
7.0
sY} ;
{ пе р е в од целочи с л е н ных к о орди н а т у к а з а т е л я мыши
в с т р о к а в о е пр е д с т а вл е н и е для вывода н а э кр а н
п р о ц едурой O u tTex t }
C l earDevi c e ;
MoveTo ( l O ,
outтext ( 1 х
MoveTo ( l O ,
10 } ;
1
=
+
20} ;
sx
+
1 У
=
1
+
sY} ;
i f LeftBut t on
in But t ons
1}
Then OutText ( 1 Нажата л е в а я к н о n к а
1
1
E l s e Outтext ( Левая кноnка не нажата } ;
•
MoveTo ( l O ,
if
•
•
30} ;
RightBut ton
in Buttons
1 }
Then OutText ( 1 Нажата nравая кноnка
1
E l s e Outтext ( Правая кноnка не нажата 1 } ;
•
unt i l
•
•
keypre s s e d ;
C l o s eGraph ;
End .
К о н трол ь н ые вопросы и отв еты
Дайте краткую характеристи ку языку Ассембл е р .
Ассемблер
это я з ы к п рограм м и рования н изкого уро в н я , н абор команд
которого отвеч ает набору команд процессо ра, для п р о гра м м и рования ко
торого о н п редн азначен . Каждая команда ассе м блера сопоставляется од
н о й команде п ро цессора.
-
В чем з а кл ю ч а ются особенности и преи мущества
испол ьзования ассемблера?
В последнее время объе м ы ассемблерных блоков в п ро г р а м м ах сокра
щаютс я , так как с п о в ы ш е н ием б ы строде й ствия к о м п ьюте р н о й техн и к и
станов ится н е н уж н ы м о с н о в н ое полезное свойство ассе м б л е р а - с к о
рость п одп рограм м , реализован н ых н а н е м . Увел и ч е н и е объемов п а м я
ти , доступ н ы х п рограммам , ослабл я ет еще оди н а р гум е н т в п ол ьзу а с
с е м б л е р а - м ал ы й р а з м е р ассемблерных п одп рограм м . Так и м об разо м ,
о с н о в н о е п р и м е н е н и е ассемблера заключ ается в в ы з о в е фун к ц и й о п е
рацио н н о й систе м ы , н е реализован н ых разработч и ка м и я з ы к а п рограм
м и р о в а н и я высокого уров н я .
В ч е м з а кл ю ч а ется механизм испол ьзо вани я
регистров и п р е р ы в а н и й ?
П роцессор , п о м и м о командн ой части , имеет область пам яти , я ч е й к и к о
торой н азы ваются регист р а м и . П рограммы и м е ют доступ к н екотор ы м из
н и х для хран е н и я з н ач е н и й или передач и параметров как п одп рограммам
самого п р о цессора, так и подп рограммам о пе рацио н н ой систе м ы .
456
Глава
1 4.
Использование встроенного ассемблера
П роцессор в ы п ол н яет п ростейш ие операци и , такие как арифметические ,
ло гические и перемеще н и я дан н ых между областя м и памяти , в т о м ч исле
и собстве н н ы м и ре гистрам и .
Более сложн ы е и полез н ы е фун кции реализован ы в операци о н н о й систе
м е и объеди н е н ы в груп п ы , называемые п р е р ы ва н и я м и . В каждо м п р е
р ы в а н и и собран ы фун кци и , имеющие одну логическую н а п равл е н ность, на
п р и м е р , п р е р ы в а н и е с н о м ером 33h соде ржит фун к ц и и дл я работы с
м ы ш ью . Дл я в ызова п ре р ы ван ия с каким-либо н о м е р о м испол ьзуется ко
м анда i п t , п р и вызове которой в регистрах п р о цессара необходи мо раз
местить всю н еобходи мую для работы прерывания и н формаци ю , а и м е н
н о н о м е р вызы ваемой фун кции и ее параметр ы . Н а самом деле н о м е р
п рерывания является номером вектор а п р е р ы в а н и я
обл асти п амяти ,
в кото рой хран ится адрес о бработч и ка дан н о го п р е р ы ван и я .
-
Перечисл ите регистры п роцессара и дайте краткое и х о п и с а н и е .
Регистры п роцессара п р едставля ют собой двухбайто вые я ч е й к и памяти и
делятся н а следующие груп п ы :
1 . Регистры д анных, п редназначен н ы е для време н н о го хран е н и я любой
и н фо р м аци и и о б м е н а с систем н ы м и фун к ци я м и MS- DOS. Ре гистры
и меют названия АХ, ВХ, СХ и DX. Особенностью регистров дан н ых яв
л я ется возмож ность раздел ьного обраще н ия к их стар ш и м и младш и м
байтам . Старш ие. байты регистров дан н ых и меют названия АН, В Н , СН
и D H , младш и е
AL, BL, CL и D L .
-
2 . Регистры -указател и , п редн азнач е н н ы е для хран е н и я адресов памяти
в формате < Сегмент> : < Смещен ие> при передаче п араметров в систе м
н ы е фун кции MS- DOS . Регистры-указатели имеют н азвания В Р , 5 Р , 51
и Dl . Побайтовая адресация регистров- указател е й н едопусти м а .
3 . Сегментные регистры , определяющие расположен и е п рограмм ы в сег
ментах памяти . Испол ьзуется четыре сегментн ых регистра: регистр сег
мента команд (С5) , регистр сегмента дан н ых ( D 5 ) , регистр допол н и
тел ьного сегмента дан н ых ( Е5) и регистр сегмента сте ка ( 55) .
4.
Указатель ком а нд ( I P ) , п редназ начен н ы й дл я указания относител ь н о
г о адреса команды , следующей за выполняемой в дан н ы й м о м е н т . П ро
грам м ы не и меют п ря мого доступа к дан ному регистру.
5 . Регистр флагов ( FLAG5), содержащий н екоторые резул ьтаты последней
выполненной команды , например выход значения, получен ного в резуль
тате арифметической операци и , за предел ы допусти м ых з н аче н и й .
Какие б ы в а ют прерывания?
П рерыван и я мо гут воз н и кать т р е м я путя м и :
1 . Ап па ратные п р е р ы в а н и я
воз н и кающие п р и изменен и и состоя н и я
каких- л и б о устройств : клавиатур ы , м ы ш и или тай м е р а .
2 . Внутренние прерывания
возникающие п р и выполнении некоторых опе
раций процессора, например при возникновен и и ош ибки деления на ноль.
3 . П рогра м м н ы в прерывания
вызывае м ы е в ы п ол н я е м ы м и п рогра м
м а м и дл я обеспечен и я собствен н о й фун кциональн ости : вывод и н ф о р
м а ц и и н а экран , считыван ие с кл авиатур ы или м ы ш и , работа с файло
вой системой , и др .
-
-
-
457
О бъе ктн о - о р и е нти р о ва н н о е
п р о гр а м м и р о в ан и е
Объектно-ориентированное программирование (ООП) - передовая тех
нология современного программирования . Она является логическим про
должением структурного и процедурного программировани я . Подавляю
щее бол ь ш и н ство новых проектов разрабатывается с и с п ользован ием
именно ООП . Большинство языков программ ирования, появившихся за
последнее десятилетие , также основано на объектно-ориентиро ванном
подходе. Таким образом , пони мание ООП явля ется обязательным для
любого программиста.
Аргументы в пользу выбора объектно-ориентированного подхода к раз
работке программных продуктов мы рассмотрим в конце дан ной главы ,
а пока наберемся терпения и изучи м его основы .
1 5 . 1 . И нк а псуля ц ия
1 5. 1 . 1 .
П онятия и н капсуляции и объекта
Концепция процедурного програм мирования подразум евает наличие в
программе нескольких логически законченных м одулей (подпрограмм ) ,
которые работают с глобальными дан
ными и образуют между собой связи
через вызовы друг друга с передачей
параметров (см. рис. 1 52) .
Подп рогра м м а f
-"-"па...,р,..,ам.,.ештр,."ы�V#
Рис.
Подп рограмма
N
t
1 52. Организация данных в
процедурном программировании
458
Такая о р г а н и з а ц и я п р о гр а м м ы х о
р о ш о структури рует с а м у п р о грам
м у , н о н е и н фо р м ац и ю , с котор о й
п р о гра м м а работает. Д л я структури
р о в а н и я и н фо р м а ц и и п р ед н азн ач е
н ы слож н ы е ти п ы дан н ы х - масс и вы и зап и с и , но он и н е дают
Глава 1 5 . Объектно-ор иенти рованное п рограм м и рование
желаем о й л о кал из а ц и и (размеще н и я в од н о м м е сте ) л о г и ч е с к и за
кон ч е н н ых фрагм ентов п р о грам м ы и дан н ых , с которы м и о н и ра
ботают. Разл и ч н ы е п од п р о грам м ы должн ы и с п ол ьзо вать гл обал ь н ы е
п е ре м е н н ы е дл я того , чтобы хран ить в н и х и н ф о р маци ю , которая н е
должна б ыть п отеря н а п о сле выхода и з п од п р о гр а м м ы . Э т о н акла
ды вает ответств е н н ость н а п одпрогра м м ы за п одде ржан и е целостн о
сти дан н ы х , отн о с я щ ихся к друг и м п одп рограм м а м . Н а п р и м е р , м о
дул ь L i s t , реал и з о ван н ы й н а м и в раздел е , п о с вя ще н н о м с п и скам ,
я в л я ется о ч е н ь удо б н ы м для п оддерж а н и я работо с п о с о б н ости н е
скол ьких с п и с ков . Одн ако п ере м е н н ы е , кото р ы е н е о бход и м ы для р а
боты со с п и с ко м , должн а создавать подп р о гра м м а , з а интерес о в а н
н а я в хра н е н и и и н фо р м а ц и и . З атем с п и с о к должен б ыт ь
п ро и н и ц и ал и з и ро в а н и деи н и циал и зирован в о п редел е н н о м п оряд
ке. Это н е я вл яется существенн ы м затруд н е н и е м п р и работе со с п и с
кам и (так к а к д л я каждого с п и с ка таких п ерс м е н н ых н е м н о го ) , н о
м ожет стать п р е п ятстви е м п р и работе с более сл ожн ы м и б и бл и о те
кам и , о с о б е н н о если о н и созда н ы н е те м разработч и ко м , котор ы й
с о б и р ается и х и с п ол ьзо вать .
И вообще, хранение всех данных вместе усложняет процесс создания про
граммнога продукта и ведет к появлению динамических ошибок, вызванных
тем, что одни подпрограммы могут изменять информацию, относящуюся к
другим подпрограммам. Возвращаясь к нашему примеру, можно представить
себе ситуацию, когда значение переменной, в которой хранится количество
записей списка, изменяется не процедурами добавления или удаления запи
сей , а каким-нибудь произвольным образом, например, при использовании
ее в качестве счетчика цикла. В результате вмешательства в структуру списка
часть хранимой в нем информации может быть потеряна. Частично решить
проблему помогла бы секция инициализации библиотеки , в которой можно
создать необходимые переменные, но это не избавляет программу, использу
ющую библиотеку, от вызова процедуры деинициализации и не запрещает ей
изменять значения переменных. Еще одним минусом такого подхода будет
создание всего одного списка, так как подключить библиотеку к программе
можно только один раз.
Оп исан ные проблем ы существуют во всех процедурных языках програм
миро вания , что приводит к немалым затратам на разработку и сопровож
дение круп ных программ н ых продуктов. Решением я вляется изменение
п одхода к п рограмм и рованию и использован ие принципиально нового
ти па программ н ых м одулей - объектов.
Инкапсуляция - объеди нение записи с подпрограм мам и , которые рабо
тают с экзем пля рами этой записи , в результате чего получается новый
тип дан ных - объект. Оп исание объекта в программе состоит из двух
частей - и нтерфейсной и описательной. При этом п оля зап иси н азыва
ют свойствами объекта, а подпрограммы - методами объекта. И нтерфей459
Turbo Pascal 7 . 0
сная часть располагается в разделе описания типов данных Тур е и и меет
следующий вид:
Туре
{ за голов о к интерфейсной ч а сти }
<Имя о бъекта> = Obj ect
<Имя п о л я 1 > : <Тип поля 1 > ;
<Имя поля N> : < Т и п поля N> ; { о пис а н и е с в о й с т в объе к т а }
< З а г ол о в о к ме т о д а 1 > ;
< З а г о л о в о к ме т о д а М> ;
{ з а голо в ки ме т о д о в объе кт а }
end ;
О п и с ательная ч асть объекта н аход ится в разделе о п и с а н и я п одпрог
рам м и строи тся п о п равилам , анал о ги ч н ы м о п ис а н и ю п од п р о грам м
в б и бл и оте ках процедур и функци й . Для о п редел е н и я п р и н адлежно
сти м етода какому-либо объекту перед и менем м етода указ ы вается имя
объекта :
<Имя объе кт а > . <Имя ме тода > ( Сп и с о к п а раме т р о в ) ;
Procedure
или
Funct ion
<Имя объе кт а > . <Имя ме тода > ( Сп и с о к п а р аме т р о в ) :
< Т и п в о з в раща емо го знач ения > ;
Так же как и при описан ии процедур и фун кци й в библиотеках, в описа
тельной части объектов разрешается не указы вать списки п араметров и
ти пы возвращаем ых значени й , так как они уже указаны в и нтерфейсной
части объекта:
Procedure <Имя о бъе кт а > . <Имя ме т о д а > ;
Funct i on <Имя о бъе кт а > . <Имя ме т о д а > ;
Обращение к полям и методам объектов осуществляется так же , как и к
поля м зап исей - указанием имени переменной-экземпляра объекта и
имени п оля или метода через точ ку. Приведем пример описания объекта
(см . листи н г 23 1 ) .
Program Obj U s ingl ;
{ н а чало
Туре
ТWriter
А:
=
раздела
описания
Obj ect { з а г о л о в о к и н т е р ф е й с н о й
с име нем TWr i t er }
Intege r ;
{ описание
целочисл е н н о г о
типов д а н ных }
ч а с ти о п и с а н и я
поля
объекта
с име н е м А }
P rocedure Wri t eA ;
{ заголовок ме тода - процедуры с име н ем Wri t eA }
end ;
Procedure
460
{ окончание
интерфейсной
ч а с ти
о п и с а ни я }
Wr i t eA
TWri t e r . Wr i t eA ; { з а г о л о в о к о пи с а ни я ме т о д а
о б ъ е к т а Twr i ter }
Глава 1 5. Объектно-ор иенти рованное програм м и рование
begin
Wri t e ( 1 Строка
выведе на
{ выв од
о бъектом 1 ) ;
с т р о ки « С т р о к а
в ыв е д е н а
о бъе к т ом» }
end;
{ начало
Var
р а здела
описания
п е р ем е н ных }
'lWriter; { о пи с а ни е п е р еме н н ой с име нем Wr i t er
э к з емп л я р а объе к т а TWr i t e r }
Writer :
Begin
Wri t e r . A
:=
1 0 ; { при с в о е н и е
з н а ч е ни я
п олю А п е р еме н н о й Wr i t er }
Wri t e r . Wr i t eA ;
{ вы з о в ме т о д а Wri t eA п ереме н н о й Wr i t er
э к з емпл я р а о бъ е к т а типа TWr i t er }
End .
Результатом выполнения программы будет вывод на экран строки «Стро
ка выв е д е н а о бъе к т ом» .
На первый взгляд в работе с объектами нет н и каких отл и ч и й от обычно
го процедурного программирования. Однако они все-таки есть. Дело в
том , что метод, описанн ы й в объекте, может обращаться к п олям этого
объекта без указания имени переменной , являющейся экземпляром объек
та. Данная возможность связана с тем , что объект является оп исан ием
данных и п равил работы с этими данны м и , а методы конкретных экзем
пляров объекта работают с данными , относящимися именно к этому эк
зем пляру (см. листин г 232) .
Program Obj U s ing2 ;
{ начало
Туре
'l'Writer
А:
р а з д е л а о п и с а ни я т и п о в д а н ных }
и н т ер ф е й с н о й ч а с т и о п и с а н и я
Obj ect { з а г о л о в о к
с име нем TWr i ter }
=
Intege r ;
{ оп и с а н и е ц е л о ч и сл е н н о г о
поля
объекта
с име н ем А }
Procedure WriteA; { заголовок ме тода - процедуры с имен ем Wri teA }
end ;
Proc edure
{ о к о н ч а ни е
и н т ер ф е й с н о й
ч а с ти
о п и с а ни я }
TWr i t er . Wr i t eA ; { з а г о л о в о к о п и с а н и я ме т о д а
о б ъ е к т а TWr i t e r }
Wr i t eA
begin
Wr i t e ( A ) ;
{ вы в о д
з н а ч е ни я
поля А }
end ;
Var
Writer :
{ начало
р а зд е л а
описания
п е р емен ных }
'l'Writer; { о пи с а ни е п е р е ме н н ой с име н е м Wr i t er
э к з емпляра о бъе к т а TWr i t er }
461
Turbo Pascal 7 . 0
Begin
Wri t er . A
: =
10 ;
Wri t e r . Wr i t eA ;
{ при с в о е ние
з н а ч е ни я
п олю А п е р еме н н о й Wr i t er }
{ выз о в ме т о д а Wr i t eA п е р емен н о й Wr i t e r э к з емпл яра о бъе к т а т ип а TWr i t e r ; на э к р а н
в ыв одит с я з н а ч е н и е п о л я А п е р еме н н о й Wr i t er ,
то е сть 1 0 }
End .
В рассмотренном при мере при вызове метода Wri teA н а экран вы водит
ся значение поля А той переменной-экземпляра, для которой вызывает
ся метод Wr i t eA. То есть если создать два разных экзем пляра объекта и
занести в их поля А разные значения , то при вызове метода wr i t eA для
одного объекта и этого же метода для другого объекта на экран будут
выведен ы разные значения (см . листи нг 233) .
��i(��f��t:���;''i�:�n9':�t�:;���;�Щ(;·����,���;:;,;,;:i�·;��:�·t'��:};;�;','fi)·:�:iз::;.:'·C':<'�:��i·)!·: :i(;�:�?)·rR11�K
Program Obj Us ingЭ ;
Туре
'lWriter
А:
=
Obj ect
Intege r ;
{ н а ч а л о р а з д е л а о п и с а н и я т и п о в д а н ных }
{ з а г оло в о к и н т е р ф е й с н о й ч а с т и о п и с а н и я
с име нем TWr i t er }
{ описание
целочисл е н н о г о
поля
с
объекта
име н е м А }
Procedure Wri t eA ;
{ з аголовок ме тода - процедуры с име нем Wri t eA}
{ о ко н ч а н и е
end ;
Procedure
TWri t e r . Wr i t eA;
и н т е р ф е й с н о й ч а с ти о п и с а ни я }
{ з а г ол о в о к о п и с а н и я ме т о д а Wr i t eA
о б ъе к т а TWr i t e r }
begin
{ вы во д
Wri t e ( A ) ;
з н а ч е ни я
поля А }
end;
{ начало
Va r
Writer1 :
р а здела
описания
п е р ем е н ных }
'lWriter; { о п и с а н и е п е реме нной с име нем Wri t er 1
э к з емпл яра о бъе к т а TWr i t er }
Writer2 : 'lWriter; { о п и с а н и е п е реме нной с име нем Wri t e r 2
э к з емпляра о бъе к т а TWr i ter }
Begin
Wri ter1 . A
: =
10 ;
Wri t er2 . А
: =
20;
{ присвоение значения полю А переме нной Wri t er1 }
{ присвоение значения полю А переменной Writer2 }
Wri t e r 1 . Wr i t eA ;
{ вы з о в ме т о д а Wr i t eA п е реме н н о й Wr i t er 1 э к з емпл яра о бъе к т а типа TWr i t e r ; н а э кр а н
выводи т с я з н а ч е ни е п о л я А п е р е м е н н о й Wr i t er 1 ,
то есть 1 0 }
Wri t er2 . Wr i t eA ;
{ вызов ме тода Wri teA переменной Wri ter2 - экземn
ляра объе к т а типа TWr i t er ; н а э кр а н в ы в о ди т с я
значение п оля А переме нной Wri t er2 , т о е ст ь 2 0 }
End .
462
Глава 1 5 . Объектно-ориенти рова н н ое програ м м и рование
Результатом вы полнения такой программы
будет вывод на экран двух чисел : 10 (зна
чение поля А переменной Wri t e r l ) и 20
(значение поля А переменной Wr i ter2 ) .
Итак, для н а ч ал а м о ж н о расс м атр и вать Рис. 1 53• Организация данных
объекты как аналог библиотек подпрограмм , в о бъ е ктн о - ориентированном
но с той раз н и це й , что програм ма может программировании
создать нескол ько экзе м пляров объектов ,
тогда как библиотека подключается только оди н раз. Соответственно, при
использован ии объектов программы могут не иметь глобальных данных,
а вся и нформация будет хран иться внутри объектов, которые будут взаи
модействовать друг с друго м , вызывая методы или изменяя поля других
объектов (см. рис. 1 53 ) .
1 5. 1 .2.
Ди намические объекты .
Кон структор и деструктор
Экземпляр объекта является не просто структуро й данных, а структурой
данных, к которой прилагаются еще и методы работы с этими данными.
Поэтому создание объекта в памяти - довольно сложная процедура, свя
занная с размещением внутренних вспомогательных данных. Всю эту рабо
ту берет на себя компилятор, но есть некоторые правила, которым необхо
димо следовать.
П о м и м о процедур и функций , предусмотре ны еще два в ида методов
объектов - конструктор и деструктор.
Конструктор вызывается в начале работы с экзе м пляром объекта для его
и н и циализаци и . Оп исывается конструктор по обыч н ы м п равилам о писа
ния метода объекта, но вместо ключевых слов Proc edure и Func t i on ис
пол ьзуется ключевое слово Constructor. Таким образом , в и нтерфейс
ной части объекта описание конструктора выглядит так:
Туре
<Имя объе к т а > = Obj ect
Constructor <Имя > ( <Список п а раме т р о в > ) ;
end ;
В описательной части объекта конструктор описывается так:
Constructor <Имя объе кт а > . <Имя > ;
Деструктор вызы вается в конце работы с экземпляром объекта для его
деинициализации . Для описания деструктора используется ключевое слово
463
Turbo Pascal 7 . 0
Destructor. Таки м образом , в и нтерфейсной части объекта описание де
структора выглядит следующим образом :
Тур е
<Имя объе к т а > = Obj ect
De structor <Имя > ( < С п и с о к параметро в > ) ;
end;
В описательной части объекта деструктор описывается как:
De structor <Имя объект а > . <Имя > ;
В конструкторе и деструкторе обычно размещаются ком анд ы , которые
необходимо выполнить, соответственно, до и после работы с экземпля
ром объекта. Н апример, при описании объекта, представляющего спрайт,
в кон структор е , скорее всего , будет находиться о предел е н и е размера
спрайта, выделение места для его хранения и создан ие спрайта в памя
ти , а в деструкторе - освобождение памяти , выделенной для хранения
спрайта, что освобождает программу, использующую такие объекты, от
необходимости следить за корректностью использования памяти . Доста
точно просто вызвать конструктор перед началом работы и деструктор
после окончания работы , все остальные действия будут произведены над
внутренними перемен ными экземпляра объекта сам и м же объектом .
Конструкторы необходимы для корректной работы с объектам и при ис
пользовании некоторых их возможносте й , одна из которых - создание
объектов не в статической области памяти, а в динамическо й . Для дина
мического распределения объекта в Неар-памяти необходимо описать пе
ременную-тип изированный указатель на объект - и проинициализировать
его (выделить память) с помощью расширенного варианта процедуры New:
Nеw ( <Указатель на объект>, <Имя конструктора> ( <Список параметров> ) ) ;
Про цедура New выделяет место под переменную, заданную п араметром
на объек'l' , и вызывает конструктор объекта, заданный па
раметром Имя конс'l'рук'l'ор а . При этом все внутренние структуры , не
обходимые для нормального функционирования объекта, будут размещены
в памяти автоматически.
Указа'l'ель
Обращение к м етодам и полям динамически распределенного объекта
осуществляется с помощью оператора разыменовыван и я :
<Ука з а т е л ь н а о бъ е к т > А . <Имя пол я и л и ме т о д а >
Разрушение динамического объекта и возвращение п амяти о п ерацион
н о й системе выполняет процедура Di spo s e , также и меющая расширен
ный вариант для использован ия с объектами:
Diщроsе (<Указатель на объект>, <Имя деструктора> (<Список параметров>) ) ;
464
Глава 1 5 . Объектно-ориентированное програ м м ирование
Процедура Di spose разрушает экземпляр объекта, заданный параметром
на объект , и все внутренние структуры , связанные с этим эк
земпляром. Перед разрушением объекта вызывается его деструктор, заданный
параметром Имя: деструктора, что позволяет объекту выполнить действия,
необходимые для успешного завершения работы, например освободить ди
намическую память, занятую под внутренние переменные экземпляра.
Указатель
Рассмотрим пример (см . листинг 234) .
Progra.m. Obj Us ing4 ;
Тур е
ТWriter
А:
Obj ect
=
Integer ;
{ н а ч а л о р а з д е л а о п и с а н и я т и п о в д а н ных }
{ з аголовок интерфейсной ча сти описани я объекта
с име нем TWr i ter }
{ описание
целочисл е н н о г о п о л я с име н ем А }
к о н с трукт о р а с име н е м I n i t }
Destructor Done ; { з а г ол о в о к д е с труктора с име н е м Done }
Constructor Init; { з а гол о в о к
Procedure WriteA; { заголово� ме тода - процедуры с именем Wr iteA }
{ окончание
end ;
интерфейсной
ч а с ти
о п и с а ни я }
TWri t e r . Wr i t eA ; { з а г ол о в о к о пи с а н и я ме т о д а
о б ъ е к т а TWr i t er }
Procedure
Wr i t eA
begin
{ вы во д
Wri t e ( A ) ;
з н ач е ни я
поля А }
end ;
TWr i t e r . Init ; { з а г ол о в о к о п и с а н и я к о н с тр у к т о р а
Ini t о б ъ е к т а TWr i t er }
Con s t ructor
begin
end;
{ не
Dest ruc t.o r ТWri t e r . Done ;
выпол н я е т с я
н и к а ких
действий }
{ з а г ол о в о к о п и с а н и я д е с трук т о р а
Done о б ъ е к т а TWr i t er }
begin
end;
{ не
Va r
Writer :
'"'lWriter;
выполн я е т с я
н и к а ких
действий }
{ н а ч а л о р а здела о п и с а н и я п е р еме н ных }
{ о пи с а н и е переме н н ой с име н е м Wr i t er
с сыл о ч н о й п е р еме н н о й н а э к з емп л я р о б ъ е к т а
TWr i t er , р а змеще н ный в дин амич е с к ой п амяти }
Begin
New (Writer,
Writ e r " . А
Init ) ;
: =
10 ;
{ с о з д а н и е э к з емпл яра о б ъ е к т а т и п а TWr i ter
в динами ч е с к о й п амяти с выз о в ом е г о
к о н с трук т о р а I ni t }
{ присв оение значения полю А переменной Wri ter ;
дл я у к а з а н и я о б ъ е к т а и с п ол ь зуе т с я с с ыл о ч н а я
465
Tu rbo Pascal
7.0
п е р емен на я W r i ter и
Wr i t er л }
Wri t e r " . Wri t eA ;
о п е р а тор р а зыме н о в ыв а н и я :
{ вы з о в ме т о д а W r i t eA п ереме н н о й W r i t e r
э к з емпл яра о б ъ е к т а т и п а TWr i t er ; н а э кр а н
выв оди т с я з н а ч е н и е п о л я А п е р еме н н о й Wr i ter
то е с т ь 1 0 ; для ука зания о бъекта и с п ол ь зуе т с я
с сыл о ч н а я п е р е ме н н а я Wr i ter и о п е р а т о р
р а з ыме н о в ыв а н и я : Wr i t e r л }
Done ) ;
{ р а зрушение э к з емпл я р а о бъе к т а т и п а TWr i t e r
в дин амич е с к о й п амяти с выз о в ом е г о
д е с тр у к т о р а Done }
-
1
Di spo s e ( Wr i t e r ,
End .
Для объектов , так же как и для записей , допустимо использование о п и
санных ниже по тексту програм мы объектов п р и форм ировани и ссылоч
ных типов (см. листинг 2 3 5 ) .
Program Obj U s i ng S ;
Ту ре
PWri ter
" TWri t e r ;
{ описание типа на основе еще не описанного объекта }
ТWriter = Obj ect
А: Intege r ;
Constructor Ini t ;
De structor Done ;
Procedure Wri t eA ;
end ;
{ о п и с а н и е о бъе к т а }
=
P rocedure TWri t e r . Wri t eA ;
begin
Wr i t eLn ( A ) ;
end;
Cons t ructor
begin
end;
De s t ructor
begin
end;
Va r
Writer :
TWri t e r , Init ;
TWri t e r . Done ;
PWriter; { о пи с а ни е переме н н о й с име нем Wr i t er
с сыл очной п е р еме н н о й н а э к з емпл яр о б ъ е к т а
TWr i t e r р а змещен ный в ди н ами ч е с к о й п амяти }
-
1
466
Глава 1 5 . Объектно-ориенти рованное п рогр а м м и ровани е
Begin
New ( Wri t e r , Init ) ;
Wri t er A . A : = 1 0 ;
Wri t er A . Wr i t eA ;
Di spos e ( Wr i t e r , Done ) ;
End .
Конструктор и деструктор могут иметь любые имена, однако рекоменду
ется использовать имя :rnit для конструктора и Done для деструктора.
Это сложи вшалея традиция в языке Turbo Pascal , и не стоит нарушать
ее, так как в проти вном случае сторонние разработчи ки не смогут ис
пользовать тако й объект в своих программах.
1 5. 1 .3.
Области видимости свойств и методов
В качестве одного из достоинств объектов мы называл и локал изованность
данных вместе с фрагментом программ ы , который работает с этим и дан
ным и . Этим уменьшается вероятность внесения подпрограммами ошибоч
ных значен и й в п еремен н ы е , предназначенные для работы с другими
подпрограмм ам и . Однако , как м ы види м , к полю объекта и меется пря
мой доступ через имя экземпляра объекта и имя поля . Соответственно,
вероятность ошибок все равно существует.
Для того чтобы разработчик объекта сам мог указать, к каким полям и
методам объекта могут иметь доступ вызывающие подпрограмм ы , а к ка
ким - нет, Turbo Pascal поддержи вает для объектов области видимости
идентификаторов. Всего предусмотрено две области види мости :
•
•
Privat e (англ . Privat e - ч астны й ) - свойства и м етоды , о п и сан
ные в объекте , доступн ы только методам дан н ого объекта;
PuЬl i c (англ . PuЬl i c
общи й ) - свойства и м етоды , описан н ы е
в объекте , доступн ы всем вызывающим подпрограммам.
-
П римеча н и е .
Идентифи каторы с областью види мости private доступ н ы также и в с е м n од
n рограм м а м , раз м е ще н н ы м в одно м модуле с объектом ( в том ч и сле и м ето
дам о n исанных в этом м одуле объекто в ) . П од м одулем в дан н о м случае n одра
зумевается б и бли отека или n рограм м а , в которо й оn и сан объект. Несмотря на
такую возможность , все равно не стоит об ращаться к рrivаtе - сво й ствам объек·
та из в н е ш н его окруже н и я .
Область видимости идентификаторов указывается в и нтерфейсной части
объектов ключевым и словами puЬlic и private . Все идентификаторы, опи
санные после указания ключевого слова private , имеют область видимос
ти Private , а идентификаторы , описанные после ключевого puЬli c , име
ют, соответственно, область видимости PuЬl ic. Если область видимости не
указывается явно, то все свойства и методы объекта считаются PuЬl i c .
467
Turbo Pascal 7 . 0
Рассмотрим пример (см. листинг 236) .
P rogram Vi s ibi l i ty l ;
Тур е
ТЬооk
=
Obj ect
{ в с е и д е н тифи к а т оры п о сл е э т о г о ключ е в о г о
с л о в а имеют о б л а с т ь в идимо с т и Priva t e }
Price : Integer ; { о бл а с т ь видимо с т и Privat e }
Wei ght : Real ;
{ о бл а с т ь в идимо с т и Privat e }
privat e
Page s :
Intege r ;
{ о бл а с т ь
в идимо с т и
Priva t e }
{ в с е и д ен тифи к а т оры п о сл е э т о г о ключ е в о г о
с л о в а имеют о б л а с т ь в идимо с т и PuЬl i c }
Constructor Init ; { о бл а с т ь видимо с т и PuЬl i c }
puЬl i c
Destructor Done ; { о бл а с т ь
видимо с т и
PuЬl i c }
Procedure ReadМe ; { о бла с т ь
видимо с т и PuЬl i c }
private
{ в с е иде н тифи к а т оры п о сл е э т о г о ключ е в о г о
с л о в а имеют о б л а с т ь в идимо с т и P r i va t e }
Funct ion Wri teMe : Bool ean ;
{ о бл а с т ь в и димо с т и P r i va t e }
end ;
Begin
End .
Ключевые слова private и puЬl ic могут использоваться в и нтерфейс
ной части объекта любое количество раз, однако рекомендуется в начале
интерфейсной части описывать Рrivаtе -идентификаторы, а в конце
РuЫ i с - идентификаторы. Это повышает ч итабель м ость программ ы и по
зволяет более ясно понимать структуру объекта. Исправи м предыдущий
пример в соответстви и с этой рекомендацией (см . листинг 237) .
Program Vi s ibi l i ty2 ;
Тур е
ТЬооk
=
Obj ect
private
P r i ce :
Wei ght :
{ в с е иде н тифи к а т оры п о сл е э т о г о ключ е в о г о
с л о в а имеют о б л а с т ь видимо с т и Priva t e }
Int ege r ; { о бл а с т ь видимо с т и Priva t e }
Real ;
{ о бл а с т ь
видимо с т и
Priva t e }
{ о б л а с т ь в и димо с т и Priva t e }
Funct ion Wri t eMe : Bool ean ;
{ о бл а с т ь в и димо с т и
Page s :
468
Int ege r ;
Priva t e }
Глава 1 5 . Объектно-ориенти рованное п рограм м ирование
{ в с е иде н тифи к а т оры п о сл е э т о г о ключ е в о г о
с л о в а имеют о бл а с т ь видимо с т и PuЬl i c }
puЬ l i c
Constructor Init ; { о бла с т ь
в идимо с т и
{ о бл а с т ь
видимо с т и
PuЬl i c }
Procedure ReadМe; { о бла с т ь
видимо с т и
PuЬl i c }
Destructor Done ;
PuЬl i c }
end ;
Begin
End .
Правильным подходом к описанию объектов считается определение облас
ти видимости Private для всех свойств и внутренних методов (предназна
ченных для использования только в объекте) . Если свойство используется
для того, чтобы хранить в нем значение, задаваемое сторонним объектом,
то для него описываются дополнительные процедуры чтения и записи . При
таком подходе объект способен контролировать изменение своих свойств,
так как оно происходит через вызов его методов (см . листинг 238) .
· :·����r�l����i:�;t�t���,я�����·.· ·?· · · · · · +··
P rogram Obj Us ing б ;
Туре
PWriter = "'ТWri t e r ;
{ описание типа на основе
еще н е о п и с а н н о г о объе к т а }
{ описание объект а }
тwriter = Obj ect
privat e
{ в с е сле дующи е и д е н т и фи к а т оры будут име т ь
о б л а с т ь видимо с т и priva t e }
А : Int ege r ;
{ име е т о б л а с т ь видимо с т и priva t e }
puЬl i c
{ в с е сле дующи е и д е н т и фи к а т оры будут име т ь
о бл а с т ь видимо с т и puЬl i c }
Con s t ructor Ini t ;
Destructor Done ; { з а г о л о в ки к о н с трук т о р а и д е с тру к т о р а ; о б а
имеют о бл а с т ь в идимо с т и PuЬl i c }
Procedure SetA ( NewA : Integer ) ;
{ з а г о л о в о к ме т о д а ус т а н о в ки с в о й с т в а А п р о ц е дур а с п а раме тром , с о д е р ж а щим н о в о е
зн ачение поля ; име е т обла сть видимо сти PuЬl i c }
Funct i on GetA : Intege r ;
{ з а г о л о в о к ме т о д а ч т е н и я с в о й с т в а А функци я , в о з в р ащающа я з н а ч е н и е п о л я ; име е т
О бЛ а С Т Ь ВИДИМО С Т И PuЬ l i c }
end ;
Con s t ructor
begin
А := О;
end ;
TWri t e r . Init ;
{ о писание
конс труктора - о бнуление
свойства А }
469
Tu rbo Pascal 7 . 0
De s t ructor TWri t e r . Done ;
begin
end ;
{ о п и с а ние
д е с трук т о р а - н и ч е г о
не
де л а е т }
Procedure TWri t e r . SetA;
begin
А : = NewA;
{ описание ме тода устано вки значения свойства А ;
с в ой с т в у А при с в а и в а е т с я з н а ч е н и е п а р аметра }
end ;
Func t i on TWr i t e r . GetA;
begin
GetA : = А;
{ о пи с а н и е ме тода ч т е н и я з н а ч е н и я с в о й с т в а А ;
end ;
в каче с т в е возвращаемо г о з н а ч е ни я указыв а е т ся
значение с в ой с т в а А }
Var
Writer : PWr i t e r ;
Begin
New (Writer,
{ и ни ци а л и з а ц и я о бъе к т а , р а с пр е д е л е н и е в
дин амич е с кой п амяти и выз о в к о н с трук т о р а }
{ у с т а н о в к а з н а ч е н и я рrivа t е - с в о й с т в а А
Wr i t e r "' . SetA ( l O ) ;
с п омощь ю выз о в а рuЬl i с - ме т ода S e tA }
Wri t eLn ( Wr i t e r "' . GetA ) ;
{ вывод на экран значения рrivаtе- свойства А
с п омощь ю выз о в а рuЬl i с -ме т о д а G e tA }
Dispose (Writer, Done ) ; { деинициали зация объекта и выз о в де структора }
Init ) ;
End .
Конструкция такого объекта представлена на рис. 1 54. Возможно , описа
ние методов чтения и записи для каждого свойства объекта выглядит до
вольно громоздко , однако такой подход позволяет объекту контролировать
изменение своих свойств и тем самым поддерживать целостность внутрен
них данных, так как никакие их изменения не могут пройти незамечен
ными для объекта. Это особенно важно, если свойства взаимосвязан ы .
Например, объект, представляющий шкаф ,
имеет свойства L, w, н, содержащие соответ
ственно, его длину, ширину и высоту. Также
есть два свойства v и s, содержащие соответ
ственно объем и площадь. Тогда при изме
нении свойств w или L необходимо пересчи
тывать свойства s и v , а при изменении
свойства н
пересчитывать v. Если разре
шить доступ внешних подпрограмм к одно
му из этих пяти свойств, то может появиться
несоответствие данных, хранимых в объекте.
-
Рис.
1 54. Доступ к свойствам
объекта через методы чтения/
установки зна чения
470
Глава 1 5 . Объектно-ориенти рованное п рограм м и р ование
1 5 . 2 . Н аследов а н ие
1 5.2. 1 .
Понятие н аследо в а н и я
И нтересн ы м свойством объектов, называемым наследованием, является
возможность формирования нового объекта на основе ранее описан н о
го. П р и этом н о в ы й объект, называемый объектом-потомком , получает все
свойства и м етоды родительского объекта и может добавить свои свой
ства и (или) методы . Описан ие объекта с использован ием н аследования
выглядит следующим образом .
Туре
<Имя о б ъе �<: т а - р од и т е л я > = Obj ect
< Имя поля 1> : <Тип поля 1 > ;
< Имя П О Л Я N> : <Тип П О Л Я N> ;
< З а г ол о в о J<: ме т о д а 1> ;
< З а г о л о в о J<: ме т ода М> ;
end ;
{ и н т ер ф е й с н а я
р о ди т е л ь с �<: о г о
часть
о б ъ е �<: т а }
< Имя о бъ е J<: т а > = Obj ect ( <Имя о бъе �<: т а -р о д и т е л я > )
< Имя П О Л Я N + 1 > : < Т и п П О Л Я N + 1 > ;
<Имя поля N+К> : <Тип поля N+К> ; { д о б а вл е н и е
< З а г о л о в о J<: ме т о д а М+ 1 > ;
< З а г о л о в о J<: ме т о д а M+L> ;
{ до б а в л е ни е
К
полей }
L ме т о д о в }
end ;
Полученный в результате такого описания объект имеет такие же свой
ства и методы , как и объект-родитель, и добавляет свои свойства и мето
ды . Заметим , что при наследовании теряется доступ к тем полям и мето
дам родительского объекта, которые были описаны с областью видимости
Privat e . Соответственно, при проектировани и программ ы необходимо
учесть, какие методы объектов-родителей должны вызываться в объекте
потомке. Область видимости таких свойств и методов должна быть PuЬl i c .
В описательной части необходимо реализовать только добавленные ме
тоды . Наследуемые методы реализовы вать не нужн о .
Приведем пример построен ия объектн о-ориентированной графической
библиотеки на основе стандартной библиотеки Graph. Б и блиотека бу
дет содержать графические объекты <<точка» , «линия» и «пря моугольнию> .
Замети м , что все эти фигуры имеют общие свойства, а и м е н н о : в с е о н и
выводятся в некоторую опорную точ ку и и м еют цвет. Также в с е графи
ч еские объекты предназначены для вы вода н а экра н , поэтому объекты ,
47 1
Turbo Pascal 7 . 0
п редставляющие их, должны обладать как и м -либо м еханизмом для это
го . Создад и м н о в ы й тип данных - объект с и менем TGraphi c s , кото
р ы й будет о п и с ы вать некоторый абстрактны й графический объект, об
ладающий дан н ы м и свойствам и .
{ з а г о л о в о к о бъ е кт а }
{ н а ч а л о о бл а с ти видимо с т и Privat e }
Х , У : Intege r ;
{ с во й с т ва Х и У определяют коорди н а ты опорной
точки графич е с к о г о объекта }
Color : Intege r ; { с в о й с т в о о п р е д ел я е т ц в е т о б ъ е к т а }
puЬ l i c
{ н а ч а л о о б л а с т и видимо с т и PuЬl i c }
Constructor Init ; { з а г о л о в о к к о н с трук т о р а }
Destructor Done ; { з а г о л о в о к д е с трук т ор а }
Procedure Draw ; { заголовок процедуры вывода объекта на экра н }
Procedure Set Point ( aX , аУ : Integer ) ;
{ м е т о д уст а н о в ки з н ач е ний с в о й с т в Х и У
н е д о с туп ных вызыв ающим п о д п р о г р амма м }
Funct ion GetX : Int ege r ;
{ м е т о д получ е н и я з н а ч е ни я с в о й с т в а Х 1
н е д о с ту п н о г о в ызыв ающим п о д п р о гр а мма м }
Funct i on GetY : Intege r ;
{ м е т о д получ е н и я з н а ч е ни я с в о й с т в а У 1
н е д о с т у п н о г о вызыв ающим п о д п р о г р амма м }
Procedure SetColor ( aColor : Integer ) ;
{ ме т од у с т а н о в ки з н а ч е н и я с в о й с т в а C o l o r
н е д о с ту п н о г о вызыв ающим п о д п р о г р аммам }
Funct ion GetColor : Int eger ;
{ м е т о д получ е н и я з н ач е ни я с в о й с т в а C o l or
н е д о с т у п н о г о вызыв ающим п о д п р о г р амма м }
end ;
{ о кончание интерфейсной ча сти описания объекта }
ТGraphics
privat e
=
obj ect
1
1
1
Как реализуются методы, аналогичные S e t P o i n t , GetX, GetY, S e t C o l o r
и GetCo l o r , мы уже рассматривали в ы ш е . В конструкторе, видимо, дол
жно содержаться только обнуление свойств х, У и C o l or , а с методом
Draw все еще проще : объект TGraphi c s не знает точно, какому именно
графическому объекту он соответствует - точке, линии или прямоуголь
н и ку, поэтому метод Draw будет пустым , то есть н е будет содержать ка
ких-либо команд. М етоды установки опорной точки и цвета изменяют
состояние графического объекта, значит, при их вызове объект должен
перерисовываться , то есть вызывать метод Draw.
Итак, описательная часть объекта TGraphic s выглядит следующим образом:
Con s t ruct o r
begin
Х
у
: =
: =
end;
472
О;
О;
TGraphi c s . In i t ; { к о н с т рук т о р ;
о б нул е н и е
свойств }
Глава 1 5 . Объектно-ориенти рованное п рограмм ирование
D e s t ruct o r TGraphi c s . Done ;
begin
{ де с трук т о р ;
нич е г о
не
дела е т }
end;
P rocedure
begin
{ ме т од ри с о в а ни я ;
TGraphic s . Draw ;
ниче г о
не
дела е т }
end;
P rocedure
begin
х
У
: =
: =
Draw ;
end ;
TGraphi c s . S e t Point ;
{ ме т о д ус т а н о в ки н о вых коорди н а т
у с т а н а влив а е т н о вые ко ордин а ты и
п е р е ри с о в ки о б ъе к т а }
аХ ;
аУ ;
Procedure
begin
Color
Draw ;
end;
оп орной точки ;
вызыв а е т ме т о д
: =
TGraphi c s . S e t Co l o r ;
aColor ;
{ м е т о д у с т а н о в ки н о в о г о цв е т а графич е с к о г о
о б ъ е к т а ; у с т а н а в ли в а е т н о в о е з н а ч е н и е с в о й с т в а
C o l o r и вызыв а е т ме т од п е р е р и с о в ки о бъе к т а }
Func t i on TGraphi c s . GetX :
begin
GetX : = Х ;
end;
Intege r ;
{ ме т од
чтения
свойства
Х}
Funct ion TGraphi c s . Ge t Y :
Int ege r ;
{ ме т о д
чтения
свойства
Х}
begin
GetY
: =
end;
У;
Function ТGraphic s . GetColor :
Color }
begin
GetColor
: =
Integer;
{ ме тод ч т е ни я
свойства
Colo r ;
end;
Теперь на основе объекга TGraphi cs построим объекг TPoint, соответствую
щий rрафическому объекгу <<точка». Заметим, что объекг TGraphi c s обладает
всеми свойствами и методами, необходимыми для описания такого rрафичес
кого объекга. Интерфейсная часть описания объекга TPoint выглядит так:
473
Turbo Pascal 7 . 0
TPoint
end ;
=
obj ect ( TGraphic s ) { з а голо в о к и н т е р ф е й с н о й ч а с т и ;
T P o i n t строи т с я н а о с н о в е о б ъ е к т а
TGraph ics и н а следуе т в с е е г о
с в о й с т в а и ме тоды }
{ о к о н ч а ни е
и н т ер ф е й с н ой
о бъ е к т
ч а с ти }
Допустим , м ы создадим экземпляр такого объекта, установим его опор
ную точ ку и цвет и попытаемся вывести на экран , вызвав метод Draw.
Метод Draw определен для объекта типа TPoint , так как наследуется от
родительского объекта TGraphi c s . Но он ничего не делает, поэтому же
лаем ый результат не будет достигнут. Для того чтобы объект- потомок мог
измен ить функциональность некоторых методов объекта- родителя , пре
дусмотрено так называемое переопределение методов.
1 5.2.2.
П ереопределение методов
Переопределение методов объекта-родителя в объекте - п отом ке произво
дится так же , как и простое описан ие метода. Те методы объекта-роди
теля , которые подлежат переопределению в объектах-потомках, должны
быть помеч е н ы ключевым словом virtual . Для переопределения конст
руктора и деструктора указания ключевого слова virtual не требуется.
Тур е
<Имя о бъе к т а - роди т е л я > = Obj ect
< З а г оло в о к ме т о да > ; virtual ;
end ;
{ и н т ер ф е й с н а я ч а с т ь роди т ел ь с ко г о объе кт а }
<Имя объе к т а > = ОЬj есt ( <Имя о бъе к т а -роди т е л я > )
<Заголовок переопределяемого метода > ;
{ переопределение мета -
да }
end ;
Допустимо переопределение любого количества методов. Еще раз напомина
ем, что переопределяются только те методы, которые помечены ключевым
словом virtual . Данные методы реально не пристыковываются к программе
на этапе компиляции - это происходит на этапе выполнения программы.
Адреса виртуальных методов заносятся в специальную таблицу виртуальных
методов (ТВМ) и вызываются с помощью нее при обращении к н и м . Та
кое связывание объектов с методами называется поздним связыванием. Если
метод не является виртуальн ы м , то есть не помечен в описани и объекта
ключевым словом virtual, то его адрес заранее известен и м етод при
стыковывается к объекту уже на этапе компиляции програм м ы . Такое свя
зывание объекта с методом называют ранним.
474
Глава 1 5 . Объектно-ориенти рованное п рогра м м и рован ие
Примечание.
Табл и ца в и ртуал ь н ы х м етодов - это как раз и есть т е в нутре н н и е ( служеб
н ы е ) дан н ы е объекта, работа с кото р ы м и ведется автоматически . Одн ако ,
п о м и м о ТВ М , существует еще м н ожество разл и ч н ы х в идов таких данн ы х.
Возвращаясь к примеру с графическими объектами , м ожно описать объект
T P o i n t , п е р е о п р едел и в в н е м м етод D r a w р оди тел ьского объекта
TGraphi c s , добави в в него, функциональность, необходи мую для вывода
на экран точки . Для этого сначала нужно указать в оп исани и объекта
TGraphi c s , что м етод Draw я вляется виртуальн ы м .
TGraphic s
obj ect
=
privat e
Х , У : Intege r ;
Color :
Int eger ;
pub l i c
Const ructor Init ;
De structor Done ;
P rocedure Draw ;
Procedure
virtual ;
SetPoint ( aX ,
аУ :
Integer ) ;
SetColor ( aColor :
Integer ) ;
Funct i on GetX :
Int ege r ;
Funct i on GetY :
Int ege r ;
Procedure
Funct ion GetColor :
{ и н т е р ф е й с н а я ч а с т ь о п и с а ни я о б ъ е к т а TGraphi c s ;
ме т о д Draw о б ъ я в л е н виртуаль ным , то е с т ь
доступным дл я переопределения в объе к т а х - п о т омках }
end;
TPoint
Intege r ;
=
obj ect ( TGraphi c s )
{ з а г о л о в о к и н т е р ф е й с н о й ч а с ти ; о б ъ е к т T P o i n t
с т р о и т с я н а о с н о в е о б ъ е к т а TGraphi c s
и н а сл едуе т в с е е г о с в о й с т в а и ме т о ды }
Procedure Draw ; virtual ;
{ ук а з а н и е о п е р е о пр е д е л е нии ме т о д а
р о ди т е л ь с к о г о о б ъ е к т а }
end;
{ окончание
и н т ерфей с н ой
Draw
ч а с ти }
При ведем библиотеку, содержащую о писан и е объектов T G r aph i c s и
TPoint полностью (см. листин г 239) .
:;i::�:�<?��,��t���i:J!����-!j,��,J������R����!���r9�e�99p.����������:��!ri��·�·:·
Uni t GrObj ect ;
I n t e r f a ce
Туре
TGraphics
=
obj ect
private
Х , У : Int ege r ;
475
Turbo Pascal 7 . 0
Color :
Int eger ;
puЬl i c
Con s t ructor Ini t ;
De s t ructor Done ;
Procedure Draw ;
Procedure
virtual ;
Set Point ( аХ ,
аУ :
Integer ) ;
SetColor ( aColor :
Integer ) ;
Funct i on GetX :
Integer ;
Funct i on GetY :
Int ege r ;
Procedure
Funct i on GetColor :
Intege r ;
{ ин т ерфейсная ч а с т ь описания о б ъ е к т а
ме т о д Draw п оме ч е н к а к виртуаль ный ,
д о с туп ный д л я п е р е о пр е д е л е н и я }
end;
TPoint
=
TGraph i c s ;
то е с т ь
obj e c t ( TGraphi c s )
Proc edure
Draw ;
virtual ;
{интерфейсная
переопределен
end ;
часть описания
ме т о д Draw }
объе кта
TPoint ;
Imp l ement a t i on
Uses
Graph ;
Con s t ru ct o r TGraphi c s . In i t ; { о п и с а н и е
begin
Х
у
:=
О;
:=
О;
end;
De s t ruc t o r TGraphi c s . Done ;
begin
end;
P rocedure
TGraphi c s . Draw ;
begin
end ;
P rocedure
begin
Х
У
:=
: =
Draw ;
TGraphi c s . S e t Point ;
аХ ;
аУ ;
end;
Procedure
TGraphi c s . SetColor ;
begin
Color
476
:=
aColor ;
ме т о д о в
о б ъе к т а
TGraphi c s }
Глава 1 5 . Объектно-ор иенти рованное п рограм м и рование
Draw ;
end;
Funct ion
begin
GetX
: =
end;
TGraphi c s . GetX :
Х;
Func t ion TGraphic s . GetY :
begin
GetY
: =
end;
Int ege r ;
Int ege r ;
У;
Func t ion TGraphi c s . GetColor :
Intege r ;
begin
GetColor
Color ;
: =
end;
Procedure
TPoint . Draw ;
begin
Put Pixel ( Ge t X ,
GetY ,
GetColor ) ;
end;
{ о пи с а ни е п е р е о п р е д е л е н н о г о ме т о д а т а ким
о бр а з ом , ч т о бы о н выв одил т о ч ку в к о орди н а ты
о п о р н о й т о чки }
End .
{ о ко нч а н и е
б и б ли о т е ки }
А теперь приведе м простейПiий пример использования объекта T P o i n t
из описанной библиотеки (см . листин г 240) .
•�;nrr�щ���;��g·;;�;�;;,,�g�,��g:!'i�!f���.����E�:&'�:��я��r�ш�����д.���i�9_t,��j-�'si::;,�
Program UseGro ;
Uses
Graph ,
Va r
Gd ,
Gm :
Point :
CRT ,
GrObj ect ;
Int ege r ;
" TPoint ;
{ о п и с а н и е п е реме н н о й - у к а з а т е л я
о б ъ е к т а т и п а TPoint }
на
э к з емпл я р
Begin
Gd
Gm
:=
Det ec t ;
: =
О;
InitGraph ( Gd ,
New ( Point ,
Gm ,
1 1);
{ установка
г р а ф ич е с к о г о
р е жима }
Init ) ; { с о зд а н и е э к з емпл яра о бъе к т а в д и н ами ч е с к о й
памяти и выз о в к о н с трук т о р а I n i t ,
п р о и з в одяще г о о б н ул е н и е с в о й с т в ( ун а сл е д о в а н
о т объекта-родителя ) }
477
Turbo Pascal 7 . 0
Point л . setPo int ( l O , 1 0 ) ;
{ ус т а н о в к а ко орди н а т о n о р н о й т о ч к и ; с р а з у же
вызыв а е т nерери с о в ку , н о цвет п о умолч а нию
ч е р ный , n о э т ому т о ч ки н е в и д н о }
Point л . setColor ( Whi t e ) ;
{ ус т а н о в к а т е куще г о цв е т а ; с р а з у же
n е р е ри с о в ку , ц в е т у с т а н о в л е н б елый ,
т о ч к а n о я в л я е т с я н а э кр а н е }
Dispo s e ( Po i nt ,
Done ) ; { у н и ч т о ж е н и е
вызыв а е т
n о э т ому
о б ъе к т а }
ReadKey ;
end .
Заметим, что явного вызова метода Draw для объекта Point в программе нет,
этот метод вызы вается автоматически методами SetPoint и SetCo lor. Ме
тоды SetPoint и SetColor определены в объекте-родителе TGraphi c s и
вызывают метод Draw, который также описан в этом объекте. Но данный метод
переопределен в объекте-потомке, поэтому вызывается именно он и на экра
не появляется точка. В этом и состоит суть процесса наследования, переоп
ределения методов и позднего связывания . Родительский класс определял
только общее поведение абстрактного графического объекта, а объект-наслед
ник TPoint, переопределив всего один метод, стал полнофункциональным
объектом , описывающим некоторый графический объект (точку) на экране.
Теперь займемся остальными рассматриваемыми графическими объектами линией и прямоугольником. Для таких фигур в объекте TGraphi c s недоста
точно характеристик. Помимо опорной точки и цвета, необходимо иметь еще
и линейные размеры объектов. Эта задача решается , опять же, наследовани
ем. Создадим объект линии TLine на основе объекта TPoint, добавив еще
два свойства - Width и Height соответственно для ширины и высоты фигу
ры. Также необходимо описать методы чтения и записи данных свойств.
TLine
=
obj ect ( TGraphi c s )
{ н овый объект TLine являе тся nотомком TGraphi cs }
privat e
Width ,
He i ght :
Integer ;
{ рrivаt е - с в о й с т в а
для
шири ны и
в ыс о ты фигуры }
puЬ l i c
P roc edure
Set S i z e ( aWidth, aHeight : Integer ) ;
{ ме т о д у с т а н о в ки ширины и В Ы С О ТЫ
Funct i on GetWidth : Intege r ;
{ ме т од nолуч е н и я
ширины фигуры }
Funct ion GetHei ght : Integer ;
{ ме т о д nолуч е н и я
выс о ты фигуры }
фигуры }
P rocedure Draw ; virtual ;
{ nере оnределяем ме тод рисования фигуры на
end ;
478
экране }
Глава 1 5 . Объектно-ори енти рованное програ м м и рован ие
И описательная часть объекта:
Procedure
TLine . Se t S i z e ;
begin
Width
Height
:
aWidth ;
=
:
aHe ight ;
=
Draw ;
{ о п и с а н и е ме т о д а у с т а н о в ки р а зме р а : и зме н е ни е
з н а ч е ний priva t e - пoлeй Width и H e i ght и выз о в
ме т о д а п е р е ри с о в ки фигуры }
end;
Funct ion TL ine . GetWidth ;
beg i n
GetWidth
:
Width;
=
{ о пи с а н и е метода п олуч е н и я ширины :
з н а ч е н и е priva t e - п o л я Width }
end ;
Funct ion
в о з вр а ща е т с я
TLine . GetHe i ght ;
beg in
GetHei ght
:
=
Height ;
{ о писание ме тода п олуч е н и я высоты :
з н а ч е ни е priva t e - п o л я H e i ght }
Procedure TLine . Draw ;
end;
в о з в р а ща е т с я
beg i n
Graph . S e t C o l o r ( Ge t C o l or ) ;
Line ( GetX ,
Get Y ,
GetX +
GetWidth ,
GetY +
GetHeight ) ;
{ о писание ме тода прорисовки фигуры : выв од на
экран линии ; для до ступа к рrivаtе- полям исполь
зуют ся ме тоды GetX , GetY , GetWidth и
GetHeight ;
выражение Graph . S etColor означа е т , что искать
процедуру SetColor следует в библиотеке Graph , а не
в объекте , хотя он и имеет метод с таким названием}
end ;
В с е , ч т о и зм е н ил о с ь в объе кте T L i n e п о сра в н е н и ю с о б ъ е кто м
TGraphi c s ,
это появление новых свойств и методов для доступа к н и м ,
а также свой метод прорисовки . Все остальные методы, присущие объекту
TGraphi c s , унаследованы объе ктом TLine и могут использоваться в нем .
-
Теперь построим объект TRectangle, определяющий поведение прямоуголь
ника. Для него также необходимо иметь информацию о размерах, поэтому
удобно в качестве объекта-родителя выбрать объект TLine. Таким образом ,
в объекте TRec tangle следует переопределить метод вывода Draw, осталь
ные свойства и методы будут унаследованы. Переопределение метода Draw
объекта TL ine возможно, так как он отмечен ключевым словом vi rtua l .
TRec t angl e
=
obj ect ( TLine )
{ з а г ол о в о к интерфейсной ча сти ; о бъ е к т TRectang l e
с т р о и т с я н а о с н о в е объе к т а TGraphi c s
и н а с л е ду е т в с е е г о с в о й с т в а и ме т оды }
479
Turbo Pascal 7 . 0
Procedure Draw ; virtual ;
{ ук а з а ни е о п е р е о п р е д е л е нии ме т о д а
р о ди т е л ь с к о г о о б ъе к т а }
end ;
{ о к о н ч а ни е
интерфейсной
Draw
ч а с ти }
И описание переопределенного метода:
Procedure
TLine . Draw ;
begin
Graph . SetColor ( GetColor ) ;
Rectangle ( Get X ,
end;
GetY,
GetX +
GetWidth,
GetY +
GetHe i ght ) ;
{ о п и с а н и е ме т о д а прори с о в ки фигуры : выв од н а
э кр а н п р ямоугол ь ника ; для д о с ту п а к рrivа t е
п ол ям и с п о л ь зую т с я ме т о ды GetX , G e t Y , GetWidth
и GetHeight ; выражение Gr aph . S e t C o l o r о з н а ча е т ,
ч т о и с к а т ь процедуру S e t C o l o r с л е ду е т в
библи о т е к е Graph , а н е в о б ъ е к т е }
При ведем библиотеку с полным описанием объектов TGraph i c s , TPoint ,
TLine и TRec tang l e и пример ее использования (см . листин г 24 1 ) .
Uni t
GrObj ect ;
{ заголовок
библи о т е ки }
Interface
{ начало
и н т ер ф е й с н о й
Туре
{ начало
раздела
TGraphics
private
=
ч а с ти }
описания
obj ect { ин т ерфейсная часть
типов
д а н ных }
описани я о бъе кта ТGraphic s }
Х,
У: Int ege r ;
Color : Int eger ;
puЫ i c
Const ruc tor Init ;
De s t ructor Done ;
Procedure Draw ; virtual ;
Procedure Set Point ( aX , аУ : Integer ) ;
Funct i on GetX : Intege r ;
Funct i on GetY : Int ege r ;
Procedure SetColor ( aColor : Integer ) ;
Func t i on GetColor : Int ege r ;
end;
TPoint = obj e c t ( TGraphi c s ) { и н т е р ф е й с н а я ч а с т ь
о б ъе к т а TPoint }
Proc edure Draw ; virtual ;
end ;
480
о пи с а ни я
Глава 1 5 . Объектно- ориенти рованное п рогра м м ирование
TLine
=
obj e c t ( TGraphi c s ) { и н т е р ф е й с н а я ч а с т ь
о бъе к т а TLine }
privat e
Width , Height : Intege r ;
pub l i c
Procedure Set S i z e ( aWidth, aHei ght :
Funct ion GetWidth : Integer ;
Funct ion GetHe i ght : Integer ;
Procedure Draw ; virtual ;
end ;
TRe c t angle
=
obj ect ( TLine )
P rocedure Draw ;
end;
Imp l ement at ion
оnисания
Integer ) ;
{ и н т ер ф е й с н а я ч а с т ь
о бъе к т а TRe c t angl e }
оnисания
virtual ;
{ начало
о nи с а т е л ь н о й
ч а с ти
библи о т е к и }
Uses
Graph ;
Constructor TGraphi c s . Ini t ;
begin
Х
:=
у
: =
{ оnисатель ная часть
объекта ТGraphic s }
О;
О;
end;
De s t ructor TGraph i c s . Done ; .
begin
end;
Procedure TGraphi c s . Draw ;
begin
end;
Procedure TGraphi c s . S e tP oint ;
begin
Х
У
:=
: =
Draw ;
end ;
аХ ;
аУ ;
Procedure TGraphi c s . SetColor ;
beg i n
Color : = aColor ;
Draw ;
end ;
Funct ion TGraphi c s . GetX : Intege r ;
begin
GetX : = Х;
end ;
16
Зав:. 702
48 1
Turbo Pascal 7 . 0
Funct ion TGraphic s . GetY : Intege r ;
begin
GetY : = У;
end;
Func t ion TGraphi c s . GetColor : Intege r ;
begin
GetColor : = Color ;
end;
Proc edure TPoint Draw ;
{ о п и с а т ел ь н а я
begin
Put Pixel ( Get X 1 GetY 1 GetColor ) ;
end;
часть
объекта
TPo int }
Procedure TLine . S e t S i z e ;
{ описательная
begin
Width : = aWidth ;
He ight : = aHei ght ;
Draw ;
end;
Funct ion TLine . GetWidt h ;
begin
GetWidth : = Widt h ;
end ;
Funct ion TL ine . GetHe ight ;
begin
GetHeight : = Height ;
end;
часть
о бъе к т а
TLine }
•
Proc edure TLine . Draw ;
beg i n
Graph . S e t Color ( GetColor ) ;
Line ( GetX 1 GetY 1 GetX + GetWidth 1
end;
Procedure
GetY +
GetHe i ght ) ;
TRe c t ang l e . Draw ;
{ о п и с а т е л ь н а я ч а с т ь о бъ е к т а TRec tangle }
begin
Graph . S e t C o l or ( GetColor ) ;
Rect angl e ( Ge t X I Get Y 1 GetX +
end;
GetWidth 1
GetY +
GetHe i ght ) ;
End .
Использовани е библиотеки графических объектов продемонстрировано в
листинге 242 .
482
Глава 1 5 . Объектно-ор иенти рован н ое п рограм м и рование
·.j;.;p �·.�!�H�.•· ��·2 7.: �.c ;,():riь��I1·� ���··'•�·�·��������·}·���.Ф�.��:����11�:���-k!t����;!fi��
. •.
Program UseGro2 ;
Uses
Graph l
CRT 1
GrObj ect ;
Va r
Gd 1 Gm : Integer ;
Point : " TPoint ;
Line : "TLine ;
Rect : " TRect angl e ;
{ п о д ключ е н и е
библи о т е к }
{ о п и с а ни е с сыл оч ных n е р ем е н ных
э к з емпляры о б ъе к т о в }
на
Begin
Gd : = Detect ;
Gm : = О ;
Init Graph ( Gd 1 Gm 1 1 1 ) ; { у с т а н о в к а г р а фич е с к о г о р е жима }
New ( Point l Ini t ) ;
New ( Line l Init ) ;
New ( Rect l Init ) ;
{ выделение памяти и вызов конструкторов о бъектов }
Point " . SetP o i nt ( l 0 1 1 0 ) ;
Point " . SetColor ( Wh i t e ) ;
{ ус т а н о в к а о п ор н о й точки и ц в е т а э к з емпл яра
о б ъ е к т а т и n а TPoint , н а к о т орый у к а зыв а е т
п е р еме н н а я Point , с о д н о в р еме н ным выв о д ом
т о чки на э кран }
Line " . SetPoint ( 2 0 1 2 0 ) ;
Line " . Se t S i z e ( 3 0 1 4 0 ) ;
Line " . SetColor ( Red ) ;
{ ус т а н о в к а опорной точки , р а зме р о в и ц в е т а
э к з емпл яра объе к т а ти п а TLine , н а к о т о рый
у к а зыв а е т переме н н а я Line , с о д н о в р еме н ным
выв о дом линии на э кр а н }
Rect " . SetPo int ( 5 1 5 ) ;
Rec t " . Se t s i z e ( 1 0 0 1 8 0 ) ;
Rect " . S e t C o l o r ( L i ghtGray ) ;
{ ус т а н о в к а опорной точки , р а з ме р о в и ц в е т а
э к з емпляра объе к т а т ип а TRe c t ang l e , н а к о т орый
у к а з ыв а е т п ереме н н а я Rec t , с о д н о в р еме н ным
выв о д ом п р ямоу г ол ь ни к а н а э к р а н }
Di spo s e ( P o i nt 1 Done ) ;
Di spo s e ( L ine 1 Done ) ;
Di spo s e ( Rect l Done ) ; { р а зруше ние о бъе к т о в и выз о в д е с трук т о р о в }
ReadKey ;
end .
483
Turbo Pascal 7 . 0
1 5.2.3.
Иерархия объектов
Отношение объектов «родитель - потомок» графически изображают в
виде дерева. Рассмотрим рис. 1 55 . Объект 1 является родителем для объек
тов 2 и 3. Объект 2 я вляется потомком объекта 1 и, следовательно, со
держит все его методы и свойства, а также (возможно) добавляет сво и .
Объекты 4 и 5 я вляются потомками объекта 2 и содержат в с е м етоды и
свойства объектов 2 и 1 . Аналогично объект 6 я вляется п отомком объек
та 3 и содержит все м етоды и свойства объектов 3 и 1 .
Н а рис. 1 5 6 показано дерево объектов, описанных в разработанн о й нами
библиотеке GrObj e c t .
О бъекты-
Рис.
Рис.
1 55. Дерево (иерархия) объектов
1 56. Иерархия о бъ ектов
библиотеки GrObjec t
Количество объектов в иерархи и неограниченно и может дости гать не
скольких соте н .
Примечание .
В языке п рограм м и рования Java версии 1 .4 содержится более 1 840 объектов .
На первый взгляд при формировании объектов получается слишком объем
ный текст программ ы . Однако это не так. В нашем при мере при обыч
ном, не объектно-ориентированном, подходе для каждого типа графичес
кого объекта (точки, линии и прямоугольн ика) придется описать одни и
те же процедуры установки его положения, размеров и цвета. Далее во всех
этих процедурах следует предусмотреть параметры, определяющие, откуда
должна быть получена и нформация о положении конкретного объекта и
его цвете. При изменении положения объекта или его цвета необходимо
вызывать процедуру прорисовки . Таким образом, программа получилась бы
намного объемнее, ее структура была бы менее понятна, а внесение изме
нений в программу, таких как добавление еще одного объекта (например,
описывающего окружность) , приводило бы к существен н ы м изменениям
большинства ранее реализованных процедур.
484
Глава 1 5 . Объектно-ориенти рованное п рограммирование
Наследован ие п озволяет избежать этой рутинной работы . Также суще
ственно ускоряется процесс разработки программ ного продукта, поскольку
при правильном построен и и родительских объектов описание объектов
потомков состоит всего из нескольких методов, тогда как все эти объек
ты обладают довольно развитой функциональностью .
1 5. 2 .4.
И с п ользова н и е переоп ределен н ых м етодов
Итак, всем потомкам какого-либо объекта доступны для вызова его РиЬliс
методы . В нашем примере все объекты порожден ы от объекта TGraphi c s ,
в котором описан метод Draw для перерисовки объекта. Следовательно, все
объекты -наследн и ки (TPo i n t , TLine и TRe c t angle) могут его вызвать.
Однако данн ы й метод является виртуальным и, значит, может б ыть пере
определен каким -либо наследником.
Например, объект TLine переопределяет метод Draw таким образом , чтобы на
экран выводилась линия. Тогда все объе кты , находящиеся в иерархии ниже
объекта, переопределившего метод, будут вызывать не тот метод, который бьm
описан изначально, а уже переопределенный. Так, если бы в объекте TRectangle
не переопределялся бы метод Draw, то в результате его выполнения на экран
выводилась бы линия , потому что именно таким образом переопределен дан
ный метод в объекте-родителе TLine (см. иерархию на рис. 1 56) .
Одн ако иногда возни кает ситуация , когда необходим о и переопределить
какой-либо метод, и вызвать его в таком виде , в каком он был оп исан в
объекте-родителе. Приведем пример: допустим , некоторы й разработчи к
реал изовал объект для вычисления площади прямоугольного помещения
по его линейным размерам . Соответственно, объект должен и м еть свой
ства для хранения ширин ы и дл ины помещения , а также свойство для
хранения площади помещения. Для ширины и дли н ы необходимо о п и
сать методы чтения и изменения свойств, а для площади - м етод чте
ния свойства. Разработч и к поместил описан ия этих свойств в р аздел
Private. В результате получилось следующее описание объекта.
Туре
TSquare = obj ect
privat e
W, L : Real ;
S : Rea l ;
{ о п и с а н и я с в о й с т в для х р а н е н и я длины ( L ) ,
ширины (W) и площади ( S ) помещены в се кцию Private }
Publ i c
Const ructor Init ;
De s t ructor Done ;
P rocedure SetW ( aW : Real ) ;
Procedure SetL ( aL : Real ) ;
Funct i on GetW : Real ;
485
Turbo Pascal 7 . 0
Funct ion GetL :
Funct ion Get S :
Real ;
Real ;
{ о п и с а н и я ме т о д о в ч т е ни я ( GetW , GetL , G e t S ) и
з а п и с и с в о й с т в ( S e tW , S e t L ) , а т а кже о пи с а ни я
к о н с трук т о р о в п омеще ны в с е кцию PuЬl i c }
end ;
Con s t ructor
hegin
W := О;
L := О;
S := О;
end;
TSquare . Init ;
{ о пи с а н и е
De s t ructor TSquare . Done ;
heg i n
{ оп и с а н и е
end;
к о н с труктора -
о б н ул е н и е
д е с труктора - н и ч е г о
Procedure TSquare , SetW ( aW : Real ) ;
hegin
w : = aW;
S : = W * L;
{ о п и с а ни е ме т о д а у с т а н о в ки
end;
установка з начения свойства
не
свойств }
выпол н я е т }
ширины п ом е ще ни я ;
и п е р е с ч е т площади }
Procedure TSquare . S e t L ( aL : Real ) ;
hegin
L : = aL ;
S : = W * L;
{ о п и с а н и е метода у с т а н о в ки дли ны п омеще н и я ;
end;
установка значения свойства и пересчет площади }
Funct i on TSquare . GetW : Real ;
hegin
GetW : = W;
{ о п и с а ни е ме тода ч т е ни я ширины п оме ще ни я ;
end;
в о з в р а ща е т с я з н а ч е н и е с в о й с т в а W }
Fun c t i on TSquare . GetL : Real ;
hegin
GetL : = L;
{ о п и с а н и е ме тода ч т е ни я длины п омеще ни я ;
end;
в о з в раща е т с я з н а ч е н и е с в о й с т в а L }
Funct i on TSquare . Get S : Real ;
hegin
Get S : = S ;
end ;
{ о п и с а н и е ме тода ч т е ни я п л о щади п омеще н и я ;
в о з враща е т с я значение с в о й с т в а S ; само з на ч е ние
уже р а с сч и т а н о при и зме н е ни и ширины и длины }
486
Глава 1 5 . Объектно-ориенти рованн ое п рограмм ирование
Таким образом , значение свойства s вычисляется авто м атически при
изменении ширины или дл ины помещения. Поскольку при выдаче зна
чения площади методом Ge t S повторного вычисления не происходит, то
правильн ы м р е ш е н и е м будет помеще н и е свойств w , L и s в секцию
P r i va t e объекта , чтобы предотвратить н е корректное изменение этих
свойств и потерю целостности данн ых.
Таюке обратим внимание на конструктор описанного объекта. В нем произво
дятся существенные дпя безошибочной работы действия - обнуление свойств.
При инициализации объекта ему вьщеляется область памяти, которая могла
ранее использоваться другими программами, поэтому начальные значения
свойств могут бЬiть произвольными. В том числе и такими, что будут вызывать
ошибку выхода за пределы допустимого диапазона значений переменной при
выполнении оператора присваивания s :
w * L в методах SetW и SetL.
Обнуление свойств в конструкторе избавит объект от такого рода ошибок.
=
Теперь создадим еще один аналогичный объект тvolume дпя вычисления
объема помещения. Для этого необходимо описать объект-наследник объекта
TSquare и добавить в него два новых свойства: дпя хранения высоты поме
щения н и дпя хранения объема помещения v. Для свойства н , которое, так
же как и свойства w и L , следует поместить в Рrivа t е-секции объекта,
следует описать методы чтения и записи, дпя свойства v - только метод
чтения , так как значение данного свойства будет рассчитываться в программе.
В конструкторе нового объекта следует обиулить все эти свойства.
Здесь мы сталкиваемся с первой проблемой. Для того чтобы обиулить свой
ства, необходимо переопределить конструктор. То есть вместо конструкто
ра, описанного в объекте TSquare, будет вызываться новый конструктор.
Раз метод переопределяется , новый метод должен взять на себя функции
того, который он переопределяет, то есть новый метод, помимо обнуления
свойств н и v, должен обиулить еще и свойства w, L и s. Однако он не может
этого сделать, так как не имеет к ним доступа. Ведь эти свойства описаны
в Рrivаtе-секции объекта-родителя . Это как раз тот случай, когда должны
выполниться оба метода - переопределяемый и переопределяющи й . Одним
из решений данной проблемы может быть обнуление свойств объекта-ро
дителя объектом-потомком через методы установки свойств Setw и SetL.
Однако в каждом из них выполняется перерасчет значения свойства s , по
этому может возникнуть вышеописанная ошибка.
Для вызова переопределенного метода объекта-родителя предусмотрен о
ключевое слово I nhe r i t e d (англ . Inhe r i t ed - унаследованн ы й ) , после
которого осуществляется вызов метода в обыч ном порядке:
Inherited <Имя ме т о д а > ( < С пи с о к п а р аме тро в > ) ;
Следует отметить, что для переопределения конструктора нет необходи
мости помечать его ключевым словом Vi r tua l . Более того, это недопу
сти мо, и при попытке сделать это на экран будет выдана о ш ибка Error
487
Turbo Pascal
7.0
1 5 1 : Vi rtual cons tructors are not allowed : Ошибка 1 5 1 : Виртуальные
конструкторы недопустим ы . Поясни м , почему недопустим ы виртуальные
конструкторы. Виртуальный метод - это метод, адрес которого хран ит
ся в табл и це виртуальных методов. ТВМ создается конструкторо м , а для
вызова кон структора его адрес должен быть известен заранее, соответ
ственн о , хранить его в таблице виртуальных методов незач е м .
Вторая проблема в создани и объекта для вычисления объема на основе
объекта TSquare связана с тем , что при изменении значений шири н ы или
дл ины помещения н е будет производиться перерасчет объема, ведь при
описании объекта TSquare н ичего не было известно об объекте тvo l uroe,
создаваемого на его основе . Свойство v будет п олучать свое знач е н и е
только при изменении высоты п омещения. Решение этой проблемы ана
логи ч н о решению п редыдущей - необходимо переопределить м етоды
установки значени й свойств w и L так, чтобы сначала вызывались их пре
дыдущие вариант ы , а затем производился перерасчет объема.
Н апомн и м , что для переопределения обычн ых м етодов, н е я вляющихся
конструктором или деструкторо м , необходимо пометить их в описан ии
объекта-родителя ключевым словом Vi r tual .
.·:,.·f"��:tr7r·.:����::::r:�т::�::��������{;��;��(f.����·· : �' ·
PrograiiL Square ;
·
Туре
TSquare
=
obj ect
privat e
W,
L:
S:
Rea l ;
Real ;
{ св о й с т в а W , L и S п омеще ны в с е к цию Priva t e ,
ч т о бы предо т в р а т и т ь их н е к орре к т н о е и з ме н е ни е }
puЬl i c
Cons t ruc tor Init ;
De s t ructor Done ;
Real ) ;
virtual ;
Procedure SetL ( aL : Real ) ;
Funct i on GetW : Real ;
Funct i on Get L : Real ;
Func t ion Get S : Real ;
end ;
Procedure
SetW ( aW :
virtual ;
TVolume = obj ect
privat e
Н : Rea l ;
V:
488
Rea l ;
( TSquare )
{ с в о й с т в а Н и V помеще ны в с е кцию Priva t e ,
ч т о бы предо т в р а ти т ь их н е к о рр е к т н о е и з ме н е ни е }
Глава 1 5 . Объектно-ориенти рованное программ ирование
puЬ l i c
Cons t ructor Init ;
De struct or Done ;
P rocedure SetW ( aW :
Real ) ;
virtual ;
P rocedure SetL ( aL : Real ) ; virtual ;
Procedure SetH ( aH : Real ) ; virtual ;
Funct i on GetH : Real ;
Funct ion GetV : Real ;
{ пере определяются ме тоды ус т а н о в ки ширины ( SetW)
и длины ( SetL) , чтобы пересчитать объем помещения }
end ;
Con s t ructor TSquare . In i t ;
begin
W := О;
L := О;
S := О;
end;
{ обнуление
D e s t ructor
begin
end ;
свойств ,
описанных
в
о бъе кте TSquar e }
TSquare . Done ;
Procedure TSquare . SetW ( aW :
begin
W : = aW;
S : = W * L;
end ;
Procedure TSquare . SetL ( aL :
begin
L : = aL ;
S : = W * L;
end ;
Real ) ;
Real ) ;
Funct ion TSquare . GetW :
begin
GetW : = W ;
end;
Real ;
Funct ion TSquare . Ge t L :
Real ;
begin
GetL
:=
L;
end;
Funct ion TSquare . Get s :
Real ;
begin
489
Turbo Pascal 7 . 0
Get S
:=
S;
end ;
Con s t ructor
TVolum.e . Init ;
begin
Inherited Ini t ;
Н
:=
V
:=
end ;
О;
О;
De s t ructor
{ в ы з о в п е р е о пр е д е л е н н о г о к о н с тр у к т о р а дл я
о б нул е н и я с в о й с т в , о п и с а н ных в о бъе к т е T s quare
( W , L и S ) , к к о т орым с ам о б ъе к т TVo lume н е
име е т до с т уп а , и о б нул е н и е с в о й с т в , о п и с а нных
в о бъ е к т е Tvo lume ( Н и V ) , к к о т орым о б ъ е к т
TVo lume д о с туп име е т }
TVo lume . Done ;
begin
end ;
Procedure
ТVolum.e . SetW ( aW :
Real ) ;
begin
Inhe r i t ed
V
:=
S e tW ( aW ) ;
GetS * Н ;
{ вызов переопределенного метода SetW для
у с т а н о в ки з н а ч е н и я с в о й с т в у W, к к о т о р ому
объект TVolume не име е т доступа , за тем пересчет
объема ; при устан овке свойства W унаследо в анным
ме т о дом S e tW прои з в оди т с я а в т омати ч е с ки й
п е р е с ч е т площади S }
end;
Procedure
TVolume . SetL ( aL :
Real ) ;
begin
Inhe r i t e d S e t L ( aL ) ;
v
:=
Get s * н ;
{ вызов переопределенного метода SetL для
у с т а н о в J<: и з н а ч е н и я с в о й с т в у L , к к о т о р ому
объект TVolume не име е т доступ а , з а тем пере счет
объема ; при ус т ан о вк е с в о й с т в а L у н а следо в а н ным
ме т о дом S e tL прои з в оди т с я а в т ома т и ч е ский
п е р е с ч е т площади S }
end;
Procedure
ТVolwne . S etH ( aH :
Real ) ;
begin
Н
:=
аН ;
V
:=
Get S * Н ;
end;
490
{метод установки значения свойства
з н а ч е ни я и п е р е с ч е т о б ъема }
Н
-
установка
Глава 1 5 . Объектно-ориенти рованное п рограм м и рование
Funct i on 'l'Vo lume . GetH :
Real ;
begin
GetH
Н;
:=
{ ме т од ч т е ни я выс о ты п омеще н и я ;
з начение свойства Н }
end;
Funct ion
'l'Volume . GetV :
в о з в р а ща е т с я
Real ;
begin
GetV
:=
V;
end;
{ ме т од ч т е ни я о бъема
з начение свойства V}
помещени я ;
в о з вр а ща е т с я
Var
S:
"TSquare ;
V:
" 'l'Vo lume ;
{ о п и с а н и е п е р еме н ных - у к а з а т е л е й
типа TSquare и TVo lume }
на
о б ъ е кты
Begin
New ( S ,
Init ) ;
New ( V ,
Init ) ;
{ р а с п р е д е л е н и е э к з емпл я р о в о бъе к т о в в
дин амич е с кой памяти и выз о в их к о н с трук т о р о в
дл я о б нул е ни я с в о й с т в }
S " . Se tW ( l O ) ;
S " . Set L ( 2 0 ) ;
V " . S e tW ( l O ) ;
V" . S e tB ( l S ) ;
{ ус т а н о в к а р а з л и ч ных с в ой с т в э к з емпл я р о в
о бъе ктов S и V ; п р и и змене нии каждог о с в о й с т в а
а в т оматич е с ки п е р е считыв ают с я п л о щади и о бъем }
S " . Get S : 0 : 2 ) ;
V " . S e tL ( 2 0 ) ;
Wri t eLn ( • s
=
Wri teLn ( ' V =
Di spo se ( S ,
Di spose (V,
V " . GetV : 0 : 2 ) ;
{ вы во д н а э к р а н з н а ч е н и й
и о бъема о бъе к т а V }
площади
о бъе к т а
S
Done ) ;
Done ) ;
{ вы з о в д е с трук т о р о в о бъе к т о в и
э к з емпл я р о в о бъе к т о в в п амяти }
р а зруш е н и е
End .
1 5.3.
П ол и м ор физм
Для переменных, представляющих экземпляры объектов, определен опе
ратор присваивани я . Перемен м ая -экземпляр объекта может ссылаться на
объект того типа, с которым она описана, ил и на объект лю б о го другого
типа, н аходящийся в иерархии объектов ниже данного , то есть на своего
наследника. Таким образом , в программе, использующей разработанную
491
Turbo Pascal
7.0
нам и библиотеку GrOb j e c t , переменная , представляющая объект типа
TGraphi c s , может реально ссылаться на объекты типа TPoint , TLine или
TRec t angl e , так как все о н и расп оложены в иерархии н иже объекта
TGraphi c s , то есть я вляются его наследниками (см . листи нг 244 ) .
;::::n�"б��ц:r,: ;2:4-� ::Jta����?��,��rз,и�Щ�A��-; �·� ��·�&�нo'й'-·��·ьiJ1��,_.н:�гeics��l<f:',:::,';iJ!\
Program Po ly.morphl ;
Uses
GrObj ect ;
Var
Point : "TPo int ;
Line : " TLine ;
Rect : " TRectangl e ;
AЬst r : " TGraphi c s ; { о п и с а н и е с сыл оч ных п е р еме н ных н а
э к з емпляры о бъе к т о в }
Begin
New ( Po int , I n i t ) ;
New ( Line , Init ) ;
{ вьщеление памяти и вызов конструкторов о бъектов }
New ( Rect , Init ) ;
{ при с в о е ни е п е р еме н н о й Abs t r с сылки н а о б ъ е к т
AЬstr : = P o int ;
Point - объект т и п а TPoint }
{ при с в о е ни е п е р еме н н о й Abs t r с сыл ки н а о б ъ е к т
AЬstr : = Line ;
L in e - о б ъ е к т т и п а TLine }
AЬstr : = Rect ;
{ при с в о е ни е переме н н о й Abs tr с сылки н а о б ъ е к т
Rec t - о б ъ е к т т и п а Trec t }
Di spo s e ( L ine , Done ) ;
{ р а зруше н и е о бъе к т а Line }
Line : = Rect ;
{ при с в о е ни е переме н н о й Li ne с сыл ки н а о бъ е к т
Rec t - о б ъ е к т т и п а Trec t }
Di spo s e ( Point , Done ) ;
{ р а зруше н и е о б ъе к т о в Point и Rec t }
Di spo s e ( Re c t , Done ) ;
end .
Вне зависимости от того , какой именно ти п объекта и меет экзе м пляр,
на который ссылается переменная , возможен доступ только к тем сво й
ствам и методам , которые соответствуют т и п у с а м о й переме н н о й . Та
ким образом , даже если переменная Ab s t r сс ылается на объект типа
TLine, что допусти м о , так как объект типа TLine я вляется н аследни
ком TGraphi c s , нельзя вызвать из этой переменной те методы объекта
T L i ne , которых н ет в объекте TGraph i c s . К так и м м етодам относятся
S e t S i z e , GetWidth и G e t H e i ght , определенные в объекте T L i n e и не
известн ые в объекте TGraphi c s .
Если переменной присnаивается ссылка н а экземпляр объекта, в котором
переопределен некоторый метод, описанный в объекте, тип которого имеет
изменяемая переменная, то будет вызываться переопределенный метод. Та
ким образом, если переменной типа TGraphi c s присвоена ссылка на экзем492
Глава 1 5 . Объектно-ор иенти рованное програ м м ирование
пляр объекта T L i n e , то при вызове метода Draw (определен в объекте
ТGraphics, но переопределен в объекrе TLine) на экран будет выведена линия .
Такое поведение объектов обусловлено применением виртуальных мето
дов и позднего связывания при переопределении методов объекта при на
следовани и . Ко гда переменной-ссылке на объект присваивается ссылка
на реальный экземпляр объекта, ей также передаются указатели на вспо
могательные данные объекта, в том ч исле и на табли цу виртуальных ме
тодов. В таблице виртуальных методов хранится адрес метода Draw объекта
TLine, следовательно , именно он будет вызван в качестве м етода Draw
переменной (см . листинг 245 ) .
,;::i/.1.�c.r��н���s;.\�в9##��-��:�;�������:��!1�m��i!\��a:Qi����,��:.6 �,-ь�.кf���:�·1i·.:f�·�f,:,
Program Polymorph2 ;
Uses
Graph ,
Var
Gd ,
CRT ,
Gm :
Point :
GrObj ect ;
{ п о д ключ е н и е
библи о т е к }
Intege r ;
" TPoint ;
Line :
"TLine ;
Rect :
" TRect angle ;
Graphic s :
{ о п и с а н и е с сыл о чных п е р ем е н ных
на э к з емпл яры о б ъе к т о в }
TGraphi c s ;
Begin
Gd
: = Detec t ;
Gm
:=
О;
InitGraph ( Gd ,
New ( Point ,
Gm ,
1 1
)
;
{ ус т а н о в к а
г р а фи ч е с к о г о
р е жима }
Init ) ;
New ( Line ,
Init ) ;
New ( Rect ,
Init ) ;
{ выделение памяти и выз о в
конс трукторов объе к т о в }
Point " . S e t Po i nt ( 1 0 ,
10 ) ;
Point " . S e t C o l o r ( Wh i t e ) ;
{ ус т а н о в к а о п ор н о й т о ч к и и ц в е т а э к з емпл я р а
о бъ е к т а т и п а TPoint 1 н а к о т орый у к а зыв а е т
п ереме н н а я Point 1 с о д н о в р еме н ным выв одом
т о ч ки н а э к р а н }
Line " . Set P o i nt ( 2 0 ,
Line " . Se t S i z e ( З O ,
20) ;
40 ) ;
Line " . S e t Co l o r ( Re d ) ;
{ ус т а н о в ка о по р н ой точки 1 р а зме р о в и ц в е т а
э к з емпл яра о бъе к т а т и п а TLine 1 н а к о т о рый
ука зыв а е т п е р еме н н а я L i n e 1 с о д н о в р еме н ным
выв одом линии н а э кр а н }
Rect " . S e t P o int ( S , 5 ) ;
493
Turbo Pascal 7 . 0
Rect A , Se t S i z e ( l O O ,
80) ;
Rect A , S e t C o l o r ( Li ght Gray ) ;
{ ус т а н о в ка о п ор н ой точки , р а зм е р о в и ц в е т а
э к з емпляр а о бъе к т а т и п а TRectang l e , н а к о т орый
у к а з ыв а е т п е р еме н н а я Rec t , с о д н о в р еме н ным
в ы в о дом пр ямоуг оль н и к а н а э кр а н }
{ очистка
C l earDevi c e ;
Graphics
:=
Point ;
Graph i c s A . Draw ;
Graphics
:=
Line ;
э кр а н а }
{ пр и с в о е н и е переме н н о й Graph i c s т и п а TGraphi c s
с сыл ки н а э к з емпл яр о б ъ е к т а т и п а TPo i n t }
{ вызов ме тода Draw т о г о о б ъ е к т а , н а к о т орый
с сыл а е т с я п ереме н н а я Graph i c s , т о е с т ь о б ъ е к т а
Point ; следо в а т ель н о , на э к р а н выводи т с я точка }
{ при с в о е ни е переме н н ой Graph i c s т и п а TGraph i c s
с сыл ки н а э к з емпляр объе к т а ти п а TLine }
Graphi c s A , Draw ;
{ вы з о в м е т о д а Draw т о г о о б ъ е к т а , н а к о т орый
с сыл а е т с я п е реме н н а я Graph i c s , т о е с т ь о бъ е к т а
Line ; сле д о в а т е л ь н о , н а э кр а н в ы в о ди т с я лини я }
Graphic s : = Rec t ; { при с в о е ни е переме н н ой Graphi c s т и п а TGraphi c s
с сыл ки н а э к з емпляр объе'кт а ти п а TRec t }
Graphi c s A . Draw ;
{ выз о в ме т о д а Draw т о г о о б ъ е к т а , н а к о т о рый
с сыл а е т с я п е реме н н а я Graph i c s , то е с т ь о б ъ е к т а
Re c t ; следо в а т е л ь н о , н а э кр а н выв о ди т с я
п р ямоуг о л ь н и к }
Di spo s e ( Point , Done ) ;
Dispose ( L ine , Done ) ;
Di spo s e ( Rec t , Done ) ;
{ р а зруше ние о б ъ е к т о в и выз о в д е с тр у к т о р о в }
ReadKe y ;
end .
Возможность обратиться к объекту через и нтерфей с , оп исан н ы й в роди
тельском п о отношению к нему, объекте , назы вается полиморфизмом. В
представленном примере как раз и используется полиморфизм - мы об
ращаемся к объектам P o i n t , L ine и Rec t по и нтерфейсу, оп исанн о му в
общем для н их родительском объекте TGraphi c s .
для
1 5 .4. Исп ользование ООП
п роекти рова ния сл ожн ых систем
З адач и , решаемые программированием , становятся все объемнее, поэто
му новые методы программирования развиваются в сторону упрощения
разработки и поддержан ия сложных програм м н ых продуктов . Основное
направление развития - попытка приблизить программу как описание
алгоритма к автом атизируемой (моделируемой) области .
494
Глава 1 5 . Объектно-ориенти рованное п рогра м м и рование
Объектн о-ориентирован ное програм мирован ие является воruюще нием такого
подхода и делает возможн ым построен ие алгоритм а програм м ы исходя из
описани я объекто в решаемо й задач и . То есть основой програм мы становят
ся объекты , я вляющи еся отображением объектов описываемой модел и . Да
лее на основе сконстру ированн ых объектов описываются связи между ними,
в результате чего получается полное описани е модели .
В отличие от аналогич ного описания через перемен ные и процедуры, разбро
санные по разным частям програм мы, объектное описани е модели в програм
ме намного более читабельно, что существе нно упрощает работу с моделью
.
Испол ьзование таких возможностей ООП, как наследование и полиморфизм,
приводит, как к более ясному описани ю самих объектов, так и к удобству их
использования в програм ме. Объектн о-ориентированн ый подход к разработке
позволяет провести ее «сверху вниз>�, описывая предметную область на языке
программ ирования, а не <<снизу вверх>> , создавая множество програм м»ых мо
дулей и соединяя их для получени я конечно го описани я модели.
Интерес ным моменто м в объектн о-ориен тирован ном подходе я вляется то,
что первы м шагом разработ ки может быть описани е только и нтерфей с
ных частей объекто в , без реал изации их методов , что позволя ет избежат ь
множест ва ошибок , связанн ых с взаимодействие м отдельн ых програм м
ных модулей , так или инач е возника ющих в процедурном програм миро
ван и и . При этом упрощается процесс разделен ия труда несколь ких про
граммистов, работаю щих над одним проекто м , так как их работа сводится
к реал изации описательных частей объекто в с заданны м и нтерфей сом .
Рассмотрим в качеств е примера проектирован ие такой сложной задачи , как
1 Иnентиd>икаu ия
введИТе,nitрЬл�:
,
РещiКтированИе
м ногооко нная графич еская среда (ана
'j
', 1
П оле для ввода
логичная среде Window s) . Н а рис. 1 57
: _ , _/, _ : ��-�а в�� и6." . .
ногострочного
н
изображен экран , н а котором находит
L-:, , ,' " , , , , : , ' : ,
кета, располо·
ся три <<Окна>> с заголов ками Иден'I'и
.:;
енное в окНе
1
,
фикация , Уnравле ние и Редак'I'иров а
1 •• ,
1 Выход ,, 1 •
н и е . Кажд о е из этих о к о н м о жет
содерж ать в себе е ще нескол ько , на
,
, IСшФанИть 1
пример : окно Иден'I'ификация содержит
Рис. 1 5 7. Пример
о к н о с тексто в о й строко й В в е д и 'I' е
МНО ГООКОННОЙ средЬ/
nароль и п оле ввода одн о й стро к и ;
окно Редак'I' иров ание содерж ит многос трочны й редакто р и кнопку
Со
храни'I' ь . О кна могут частич н о и л и полнос тью перекр
ывать друг друга, а
пользо ватель имеет возмож ность перекл ючатьс я между окнам и ,
изменя ть
их распол ожени е и размер ы .
IT
•••••••••
.= .
· ·· ·
·
,
: _ :- · :-_
1 ·.
'· ·
Разрабо тка такого и нтерфе йса являетс я сложно й задачей , а получа
емая
програм ма имеет большо й объем. Однако объектно-ори ентиро ванный
под
ход к реализа ции такой среды позвол яет существенно снизит ь
сложно сть
задачи за счет описан ия свойств некоторого абстрактного окна
и правил
взаи модействия абстрактных окон. Затем на основе абстрактного
окна с
495
Turbo Pascal 7 . 0
помощью наследования описываются все остальные объекты око н , имею
щие свою функциональность (например, объект кнопки или строки вво
да) , а полиморфизм , являющийся неизменным спутником наследования ,
обеспечит единообразие работы со всеми окнами в той части , которая
касается их общих свойств, которые и должны быть описаны в объекте аб
страктного окна. Под специфической функциональностью окна в данном
случае подразумевается его отображение и поведение при нажатии пользо
вателем клавиш на клавиатуре и выполнении каких-либо действий с мы
шью (перемещение и нажатие кнопок) .
Выделим свойства и методы , характерные для всех о кон на экране :
1 . Положение верхнего левого угла о к н а и возможность е г о и зменения.
2. Размеры о к н а и возможность и х изменени я .
3 . Возможность о к н а выводить свое изображени е на экран .
4. Возможность окна реагировать на события мыши и клавиатуры .
5 . Ссылка на родительское окно ( в котором находится данное окно) ,
чтобы известить его об изменениях размеров ил и п ол ожения дан
ного окна.
Таким образом , интерфейсная часть описания объекта окна может выг
лядеть следующи м образом :
TAЬs t ractWindow
=
obj ect
puЬl i c
Procedure
Procedure
SetParent ( Parent : ТWindow ) ; virtua l ;
{ ме т о д у с т а н о в ки р о ди т е л ь с к о г о
окна }
S e t P o s i t i on ( X , У : Int eger ) ; virtual ;
{ ме т од у с т а н о вки п ол о ж е н и я о к н а }
Procedure
Set Si z e ( w ; Н : Integer ) ; virtua l ;
{ ме т од ус т а н о в ки р а зме р о в о к н а }
Procedure
Paint ;
vi rtual ;
{ м е т о д вывода
о к н а н а э кр а н }
Func t i on MouseDown ( X , У : Integer ) : Bool ean ; virtual ;
{ ме т од , вызыв а емый при н а ж а тии к н о п ки
н а д дан ным о к н ом }
мыши
Funct i on Mous eUp ( X , У : Int eger ) : Bool ean ; virtua l ;
{ ме т од , вызыв а емый при о т пу с к а ни и н а ж а т о й
к н о п ки мыши н а д д а н ным о к н ом }
Funct ion Mous eMove ( X , У : Integer ) : Bool ean ; virtual ;
{ ме т од , вызыв а емый при п е р еме т е нии мыши
д а н н ым о кн ом }
Funct i on KeyPre s s ( Key : Char ) : Bool ean ;
{ ме т о д , вызыв а е мый при
на к л а в и а т ур е }
end ;
496
virtual ;
н а ж а тии кл а в иши
над
Глава 1 5 . Объектно- ориенти рованное прогр ам м и рование
Так как окно , представляемое объектом TAb s t r a c tWi ndow, я вляется
абстрактны м , то есть его внешний вид и поведение при событиях с м ы
ш ь ю и клавиатурой неизвестн ы , методы P a in t , Mous eDown , Mou s eUp ,
Mous eMove и KeyPre s s не нуждаются в реализации. Следует описать толь
ко методы S e t Paren t , S e t Po s i t i on и Set S i z e , которые будут изменять
значен ия внутренних переменных. Как будут называться эти внутренние
переме н н ы е , на дан н о м этапе разработки совершенно неважно - мы
оп исываем только п оведение объекта.
Замети м , что методы S e t P o s i t i on и S e t S i z e должны вызывать метод
Paint родительского окна, чтобы не оставить на нем следов от предыду
щего своего состоян и я . Методы Mous eDown , Mou s eUp , Mou s eMove и
KeyPres s я вляются функциями и возвращают значение True , в случае
если они обработали сообщение, и значение Fal s e , если такое сообще
ние они обрабатывать не могут.
Теперь опишем некоторые особенности поведения окна, которое может
являться родительски м , то есть содержать в себе другие окна:
1 . Родительское окно должно содержать в себе ссылки н а все свои
дочерние окна. Удобнее всего реал изовать хранение этих ссылок с
помощью с п иска объектов типа TAbs trac twindow, что даст воз
можность хранить в таком списке ссылки н а окна любого тип а , так
как все окна в нашей системе будут я вляться н аслед н и ками объекта
TAЬs t r a c tWindow.
2. При изменени и пол ожения родительского окна всем дочер н и м ок
н а м также сл едует и зм е н и т ь п ол ож е н и е , в ы з в а в их методы
S e t P o s i t i on . Не стоит забывать, что родительское окно также
может быть и дочер н и м для какого-либо другого, п оэтому необхо
димо сохранить п о ведение абстрактного окна TAb s t ra c tWindow,
вызы вающего метод Paint родительского окна, воспол ьзовавш и сь
оператором вызова переопределенного метода Inher i t ed.
З . После перерисовки р одительского окна следует перерисовать все
дочерние окна, принадлежащие ему, вызвав м етод P a i n t этих о ко н .
4 . П р и п олучении событий о т м ы ш и родительское о к н о должно опре
делить самое верхнее из своих дочерних окон и вызвать его метод,
соответствующ и й данному событию ( Mous eUp , Mous eDown или
Mous eMove ) .
По приведе и ному оп исан ию можно сконструировать объект тwi n dow,
являющийся н аследн иком TAЬs trac tWindow:
ТWindow = obj ect ( TAЬ s t ractWindow )
puЬl i c
P rocedure S e t P o s i t ion ( X , У : Integer ) ; virtual ;
{ ме т од ус т а н о в ки п о л о ж е н и я о к н а }
497
Turbo Pascal 7 . 0
Procedure
Func t ion
Funct i on
Func t ion
Funct ion
Paint ;
vi rtual ;
{ ме т од вывода о к н а н а э кр а н }
Mous eDown ( X , У : Integer ) : Boolean ; virtua l ;
{ ме т од , вызыв а емый при н а ж а тии к н о п ки мыши
н а д д а нным о к н ом }
MouseUp ( X , У : Integer ) : Boolean ; virtua l ;
{ ме т од , вызыв а емый при о т пу с к а ни и н а ж а т о й
к н о п ки мыши н а д д а н ным о к н ом }
Mous eMove ( X , У : Integer ) : Boolean ; virtual ;
{ ме т о д , вызыв а емый при п е р емеще нии мыши
н а д д а н ным о к н о м }
KeyPre s s ( Кеу : Char ) : Boolean ; virtual ;
{ ме т о д , вызыв а емый при н а ж а ти и кл а в иши
на кл а в и а тур е }
end;
Теперь следует предусмотреть главное окно , которое будет на самом деле
отлавли вать событи я , происходящие в нашей системе, то есть следить за
состоянием клавиатуры и м ыши и рассылать их всем своим дочерним
окнам . Все окна в системе будут являться дочерними для этого окна. Такое
окно должно и меть метод Run , в котором будет происходить определе
ние нажатой клавиши (с помощью функци и KeyPr e s s ed и п роцедуры
ReadKey модуля CRT) и состояния мыши (например, с помощью библио
теки мou s e , разработанной в предыдущей главе) , далее метод Run будет
вызы вать собстве н н ы е методы M o u s eD own , M o u s eUp , M o u s e M o v e и
KeyPr e s s , передавая и м н еобходимые параметр ы . В соответст в и и с
принцилом наследования данные события будут распределяться п о до
черним окнам , как это реализовано в объекте тwindow.
TMainWindow
=
obj ect
( TWindow )
pub l i c
Proc edure
Paint ;
Procedure Run ;
vi rtual ;
{ ме т од выв ода о к н а н а э кр а н }
{ ме т о д сл ежения з а с о с т о ян ие м с и с т емы и
д и с п е т ч е р и з а ции с о бытий }
end;
Главное окно будет занимать весь экран, а все остальные окна будут пе
ремещаться внутри него . Далее стоит заняться окнами , которые могут
перемещаться по экрану при перетаскивании их м ы ш ью . Данные окна
будут я вл яться н а с л едн и ка м и тw i n d o w и п е р е о п р едел я т ь м етоды
MouseDown (определение факта нажатия кнопки мыши н а заголовке окна) ,
Mous eMove (определение факта перемещения мыши п осле нажатия ее
кнопки на заголовке окна) и Mous eUp (определение факта п рекращения
нажатия кнопки мыши) . Если данные события произошли не на заголовке
окна, то следует вызвать переопределенные в этом объекте м етоды с
помощью оператора :Inherit ed.
498
Глава 1 5. Объектно-ориенти рованное п рограм м ирование
TCapt ionWindow = obj ect ( TWindow )
PuЫ i c
Procedure Paint ; virtual ;
{ ме т од выв ода о к н а н а э к р а н }
Funct ion Mou s eDown ( X , У : Integer ) : Bool ean ; virtual ;
{ ме т од , вызыв а емый при н а ж а ти и к н о п ки мыши
н а д д а н ным о к н о м }
Funct i on Mouset1p ( X , У: Integer ) : Boolean ; virtua l ;
{ ме т о д , вызыв а емый при о т п у с к а нии н а ж а т о й
к н о п ки мыши над д а н ным о к н ом }
Func t i on Mous eMove ( X , У : Integer ) : Boolean ; virtua l ;
{ ме т о д , вызыва емый при п е р емеще нии мыши н а д
д а н ным о к н о м }
end;
На этом заканчивается описание сложных окон и можно перейти к о п и
санию объектов , отображающих простые окна - например, кнопку. Все
простые окна будут я вляться наследниками объекта TAbs trac tWi ndow и
переопределять методы , необходимые для поддержания собственной фун
кциональности . Например, окно-кнопка должно п ереопределить метод
P a i n t для правильного отображе н и я кнопки и м етоды M o u s e D o wn ,
мous eUp для определения факта нажатия н а кнопку.
TButton = obj ect TAЬs t ractWindow
puЬl i c
Procedure Paint ; virtual ; { ме т од выв о д а о к н а н а э к р а н }
Funct ion Mous eDown ( X , У : Integer ) : Bool ean ; virtual ;
{ ме т од , вызыв а емый при н ажа тии к н о п ки мыши
н а д д а н ным о к н о м }
Funct ion Mous et1p ( X , У: Integer ) : Bool ean ; virtua l ;
{ ме т о д , вызыв а емый при о т пу с к а нии н а ж а т о й
к н о п ки мыши н а д д а н ным о к н ом }
Funct ion Mous eMove ( X , У : Integer } : Boolean ; virtual ;
{ ме т о д , вызыв а емый при п е р емещении мыши н а д
д а н ным о к н о м }
end ;
Окно , содержащее строку ввода, должно переопределить метод Paint для
правил ьного отображения строки ввода и метод KeyPres s для формиро
ван ия строки.
TEdit = obj ect TAЬst ractWindow
puЬl i c
Procedure Paint ; vi rtual ;
{ ме т о д выв ода о к н а н а э кр а н }
Funct i on KeyPre s s ( Key : Char } : Boolean ; virtual ;
{ ме т о д , вызыв а емый при н а жа тии кл а в иши
на к л а в и а туре }
end ;
499
Turbo Pascal
7.0
В результате несложной работы мы
полностью описали поведение мно
гоо кон н о й с и сте м ы и п олуч ил и
иерархию объектов , изображен ную
на рис. 1 5 8 .
Сл едую щ и й ш а г р а з р а б от к и р а с п редел е н и е о б ъ е кт о в м ежду
участн иками проекта, каждый из
к о т о р ы х д о л ж е н р е а л и з о в ат ь
о бъект п о задан н о му о п и са н и ю .
Поскольку взаи м од е й ст в и е о к о н
продумано н а уро в н е вызова и н
терфей сн ых м етодов , то о ш и б ки
при реализации п р о е кта практи
Рис. 1 58. Иерархия объектов,
чески исключ ен ы , а в резул ьтате
описывающих окна
и с п ол ь з о в а н и я н а с л ед о в а н и я в
многооконной системы
каждом объекте необход и м о о п и
сать только т е ч асти , которые уникальны только для того окна, кото
рое он представляет, то есть объем работы сокращен до м и н и му м а .
Трудно даже представить, как аналогичную систему можно было бы ре
ализовать без использования объектов. М н ожество структур данных при
шлось бы объединять в списки , для каждого из которых следует описать
вспомогательные записи. Для каждого вида окна пришлось бы описывать
одни и те же процедуры установки размеров и положения, в каждой та
кой процедуре необходимо было бы повторить всю структуру м ногоокон
ной систем ы для поддержания взаимодействия окон. Поскольку окна не
обладал и бы еди ным и нтерфейсом доступа, как в нашем случае , то при
шлось бы реализовывать дополнительные процедуры диспетчеризации со
общени й от мыши, клавиатуры и окон на основе каких-либо ч исловых
или текстовых параметров , определяющих окна, что привело бы к массе
ошибок и усложнению структуры проекта.
Внесение изменений в такой проект было бы крайне трудоемкой опера
цией , так как для этого необходимо изменить структуру межоконного об
щен ия . Например, для реализации многозадачности - параллельной ра
боты нескольких окон на основе вызова какого-либо метода в те моменты ,
когда пользователь не выполняет каких-либо действий - в нашей систе
ме достаточно просто описать один метод в объе кте TAbstractWi ndow
(назовем его ldle) , вызы вать его из объекта TMainWindow , в случ ае если
не нажата клавиша на клавиатуре и не произошло никаких изменений с
м ышью , и вызывать аналогичный метод дочерних объектов в объекте
TWindow. Далее кажды й объект в случае необходимости будет переопре
делять метод ldle и выполнять в нем действия как бы в фоновом режиме.
При процедурном построении системы для реализации такой <<многоза
дачности» придется внести в программу знач ительно больше изменени й .
500
Глава 1 5 . Объектно-ориентированное программирование
Конечно, здесь приведен всего лишь учебный пример, в котором не пре
дусмотрено множество необходимых возможностей . Например , нами не
введено понятие фокуса
объекта, который в данный момент может по
лучать сообщения от клавиатуры. Однако м ы хотели только продемонст
рировать сам подход к проектированию системы , а не построить ее на
самом деле, хотя и сделали все возможное, чтобы оставшаяся часть ра
боты не была трудоемко й .
-
Заметим, что структура программы, описанная нам и , называется програм
мой , управляемой событиями, и может быть п редставлена в виде схе м ы ,
показа и ной на рис. 1 59 . Основной особенностью такой структуры я вля
ется то, что только один программный модуль может прерывать программу
для ожидания , напри мер , нажатия пользователем клавиши на клавиату
ре. Данный модуль называется ядром (в нашей м ногооконной программе
таким ядром будет я вляться экземпляр объекта TMainWindow) . Все ос
тал ь н ы е п р о грам м н ы е м одул и н е долж н ы
выполнять такого рода действия , а получают
Подп ро грамма 2
<<СООбщеНИЯ>> О «СОбЫТИЯХ>> , ТО еСТЬ ИХ М еТО
ДЫ вызываются ядром или другими методами,
которые вызваны ядром , но не обрабатывают
Подпрограмма N
события . Такая структура позволяет просто и
ясно реализовать п отоки сообщени й в про
Рис .
1 5 9 . С труктур а
грамме, что крайне необходимо при разработпрограммы, управляемой
ке сложных приложени й .
событиями
К о н трол ь н ые в опросы и ответы
Что та кое объе кт н о - о р иентированное п рогра м м и р о в а н и е (ООП ) ?
Объектно-ориенти рован ное програм мирование (ООП) я вляется передовой
техн ол огией современного программ и рования и является логическим про
должен и ем структурн ого и процедур ного п рограм м и рован и я . Объектн о
о р и е нтирован н ы й п одход к разработке поз воляет п ровести ее «све рху
вниз» , описы вая предметную обл асть на языке п рограмми рован и я , а н е
«сн изу вверх» , создавая множество п рограм м н ых м одулей и соеди няя и х
для получ е н и я конечн ого описан и я модел и .
Дайте оп ределения основных поняти й , ис пол ьзуе мых в ООП .
И н капсуляция - объеди н е н и е записи с подп рограм м а м и , которые рабо
тают с экзем п л я рами этой зап иси, в резул ьтате чего получается н ов ы й тип
дан н ых - объект . П р и это м поля зап иси н азы вают свойствами о бъек
та, а п одп рограм м ы - м етодами объекта .
501
Turbo Pascal
7.0
О п и ш ите два с п е циальных метода объект а :
ко нструктор и деструкто р .
Существует два специальных метода объекта, н азываемых конструктор и
деструктор , которые вызываются соответственно сразу же после выделе
ния памяти под объект и непосредствен н о перед разруш ен ием объекта в
памяти . Конструктор и деструктор позволя ют локализовать критические дей
ствия объекта по использован ию системных ресурсов и прои н и циализиро
вать свойства (поля) объекта . Также при вызове конструктора автоматически
форми руются вспомогательные структуры для поддержания работоспособ
ности объекта, например табли ца виртуальных методов. В конструкторе и де
структоре обычно размещаются команды , которые необходимо выпол н ить,
соответственно, перед и после работы с экземпляром объекта.
Ка ки м о б р азом производится созда ние объектов
в ди н а м и ческой п а мяти?
Кон структоры необходим ы для корректной работы с объектами при исполь
зова н и и н екото рых их возможносте й , одн а из которых - созда н и е объек
то в н е в статической области памяти , а в ди нам ическо й . Дл я д и н а м ичес
к о г о р а с п р е де л е н и я о б ъ е кта в Н е а р - п а м я т и н е о б х о д и м о о п и с а т ь
перемен ную - ти п изи рован н ы й указател ь н а объект - и п р о и н и ци ал и з и
ро вать его ( выделить память) с п о м о щ ь ю рас ш и р е н н ого варианта п роце
дуры N ew: П роцедура N ew выделяет место под пере м е н н ую , задан н ую па
р а м ет р о м У к а з а тел ь н а о б ъ е кт , и в ы з ы вает к о н структор о бъе кта ,
зада н н ы й параметром Имя конструктор а . При этом все внутре н н и е струк
тур ы , необходи мые для нормального фун кционирования объекта, будут раз
мещены в п амяти автомати ческ и .
Какие области види мости могут иметь свойства и методы о бъек
тов?
Сво йства и методы объекто в им еют определенные разработч иком области
видим ости - возможность огран ичения доступа к н и м из каких-л ибо фраг
ментов програм м . Существует две области види мости : P rivate (указы вает
ся ключевым словом private) - свойство или метод доступ н ы тол ько в биб
лиотеке (или п рограмме) , где описан объект, и PuЫic - свойство или метод
доступ н ы любому фрагменту л юбой п рограм м ы . П рименение областей ви
димости повышает возможн ость объекта контрол ировать изменение значе
ний своих свойств для поддержания целостн ости внутрен н е й и н формаци и .
В чем з а ключ ается я вление н аследо вания?
Дл я объектов реал изована возможность наследов а н и я - фор м и рован ия
объекта - п отомка н а основе другого объе кта - о бъект а - родител я , в ре
зул ьтате чего объект- потомок получает все свойства и методы , реализо
ван н ы е в объекте- родителе , но в соответствии с п равилами их областей
видимости . П р и этом некоторые методы объекта - родителя могут б ыть пе
реопредел е н ы в объекте- потомке, есл и п р и их о п исан и и было использо
вано указа н и е н а возможн ость переоп редел е н и я с помощью кл ю ч евого
слова virtu a l . Из переоп ределенн ого м етода и м еется возможн ость выз
в ать т а к о й же м етод объекта- родител я с п о м о щ ью кл ю ч е в о г о сл о в а
l n herite d , что поз воляет обеспечить преемств е н н ость м етодов объе кта и
502
Глава
1 5.
Объектно-ориенти рованное п рограммирование
не потерять фун кциональность объекта-родителя при переоп редел е н и и его
методо в .
Что та кое пол и м о рфизм?
Для перемен н ых, ссылающихся на экземпляры объектов, о п ределен опера
тор п рисваи ван и я , причем переме н ной м ожет б ыть п рисвоена ссылка на
объект такого типа, н а который она может ссылаться в соответстви и со сво
им оп исан ием, либо ссылка на объект- н аследн ик дан ного объекта . Есл и ме
тод, вызы ваем ы й с помощью перемен ной, которой был присвоен экземпляр
объекта-потомка для ее базового типа, переопределен в этом объекте-по
томке, то будет вызван именно переопределен н ы й метод. Такое свойство
объектов называется полиморфизмом. Локализация и н формации и мето
дов работы с ней в объекте в сочетан ии с наследованием и полиморфизмом
дает возможность разработки сложных систем методом «сверху вниз» и опи
сания математических ил и других моделей с помощью объектов, участвую
щих в них.
503
Turbo P a s c a l 7 . 0
а в а
К а ч ес т во
п ро гр а м м н ых п родукто в
Качество программнога продукта - понятие сложное и имеющее мно
жество различных аспектов. Разобьем их на отдельные груп п ы и пояс
ним, зачем нужно следовать тем или иным правилам разработки .
Фун кци о н альность п р о гр ам м ы
Программа должна отвечать ожиданиям пользователя , который собирается
с ней работать. Таким образом , программа должна полностью реализовать в
себе все свойства, в которых заинтересован конечный пользователь, и при этом
не содержать в себе функций, которые пользователю не 11ужны, чтобы не тра
тить его время на изучение ненужных возможностей программ ы .
Второе требование функциональности заключается в безошибочности програм
мы и ее близком контакте с пользователем. Например, программа-кальку
лятор при просьбе разделить какое-либо число на ноль должна не заканчи
ваться с фатальной ошибкой Error 2 0 0 : Divi sion Ьу zero ( Ошиб к а 2 0 0 :
Деление н а ноль ) , а выдавать пользователю сообщение о том , что он со
бирается произвести некорректное действие. После этого следует возобно
вить работу, ведь то число, которое пользователь собирался поделить на ноль,
могло быть получено в результате получасового вычисления этой же про
граммой и при досрочном завершении программы будет утеряно.
К понятию функциональности также можно отнести и требован ие доста
точного быстродействия. Если программа создана дЛЯ автоматизации сле
жения за параметрами атомной электростанци и , но в силу каких-либо
причин не успевает опраши вать аппаратуру два раза в секунду, как это
следует делать, а делает это, например, раз в м инуту, то данный программ
ный продукт не должен использоваться или должен использоваться на более
скоростной технике.
т
�
504
Примечание .
М ы точ н о н е з н аем , с како й частото й сл едует о п р а ш и в ать п а р а м етр ы АЭС ,
да н н ы й п р и м е р и н терес ует н ас л и ш ь с теорети ч е ской то ч к и з р е н и я .
Глава 1 6 . Качество п рогра м м ных продуктов
Оформление и сходных тексто в
Современные программвые продукты находятся в постоянном развитии, при
чем одни программисты сменяют других, ответственность за поддержание
различных фрагментов программы переходит от одного разработчика к дру
гому, постоянно возникает необходимость внесения изменений в ранее со
зданные тексты. Это накладывает жесткие требования к оформлению ис
ходных текстов программ - они должн ы быть понятны и ч итабельн ы .
Возможна ситуация, когда какая-либо подпрограмма написана недостаточ
но эффективно, но совершенно недопустимо, когда в ней не может разоб
раться другой разработчик, так как ее структура не ясна, не содержит ком
ментариев и нет документации, поясняющей хотя бы основные моменты
реализации алгоритма.
Ка чество и нтерфейса
Этой теме в нашей кни ге уже посвящено несколько разделов, п оэтому
мы не будем подробно на ней останавли ваться . Просто нап о м н и м , что
пользовательский интерфейс - это как раз то , что пользователь и назы
вает програм м о й , п оэтому в нем не должно быть недостатков.
1 6 . 1 . Оф ор млен ие п р о г р ам мн ы х п р одукт ов
Рассмотрение этого вопроса, который крайне необходимо уч итывать при
разработке любого , даже самого мален ького, программнога продукта, м ы
построим на примере библиотеки , содержащей функцию перевода задан
ного числа в его «русскоязычное>> представление (см . листинг 246) . То
есть при задан ии в качестве параметра числа 1 2 3 0 1 2 данная фун кция
выдает строку « с т о дв а дц а т ь три тыс ячи дв е н адцат ь » . Такая фун к
ция часто необходима при разработке программных продуктов , автома
тизирующих финансово-экономические процессы . Сама функция имеет
не очень большо й объе м , но даже ее разработчик не сможет внести в нее
изменения через полгода после ее создани я , если исходн ый текст биб
лиотеки не будет содержать хотя бы общих комментариев и если пере
менвые не будут иметь хоть сколько-нибудь осмысленные имена.
>���,��f�-�E:;�·� �;:�����]Pi�:��j'�jФ:�!i������H�R��:ьA�{���,�#j��,:��R!f��r.?t)::�:ri€;;
unit nToS ;
interface
Funct ion NumberToWord ( Nuш : Longint ) :
imp l ement a t i on
Туре ntwSt r = S t ring [ 4 0 ] ;
Const Mt 1 = 4 ; AЬc : ntwSt r = ' Hoль ' ;
Т е : array [ 1 . . Mt 1 , · о 9 ] of ntwStr =
•
String ;
•
505
Turbo Pascal 7 . 0
' семь • , ' в о с емь • ,
( ' • , • один • , • дв а • , ' три ' , • четыре ' , ' nять • , • шесть • ,
девять ' ) , ( ' тысяч ' , ' одна тысяча ' , ' две тысячи ' , ' три тысячи ' ,
' четыре тысячи ' , ' nять тысяч ' , ' шесть тысяч ' , ' семь тысяч ' ,
1
В О СеМЬ Т Ы С Я Ч 1 1 1 деВЯТЬ Т Ы СЯ Ч 1 ) 1 ( 1 МИЛЛИОНОВ 1 1 1 ОДИН МИЛЛИОН 1 1
' дв а миллиона ' , ' три миллиона ' , ' ч етыре миллион а ' , ' nять милли
онов ' ,
' шесть миллионов ' , ' семь миллионов ' , ' восемь миллионов ' ,
' девять миллионов ' ) , ( ' миллиардов ' , ' один миллиар д ' ,
' дв а миллиарда ' ,
' три миллиарда ' , ' четыре миллиарда ' ,
' nять миллиардов ' ,
' шесть миллиардов ' , ' семь миллиардов ' ,
' девять миллиардов ' ) ) ;
' в о семь миллиардов ' ,
CЬa : array [ 1
• • 9 ] of
ntwStr= ( ' дecять ' , ' двадцать ' , ' тридцать ' , ' сорок • ,
' nятьде сят • , • ше стьде сят ' , ' семьде сят • , • в о семьде с ят ' , ' д е в я н о ст о ' ) ;
• • 1 9 ] of
ntwS t r = ( ' одиннадцат ь ' , ' две надцать ' ,
' тринадцать ' , ' ч еть�надцат ь • , • nятнадцать • , • ше с т н адцать • ,
' семнадцать • , • в о с емнадцать ' , ' девятнадцат ь ' ) ;
ВЬЬ : array [ 11
Hundreds : array [ 1
•
•
9 ] of ntwStr= ( ' сто ' , ' две сти ' , ' триста • , • четь�еста ' ,
' nятьсот ' , • ше с т ь с о т • , • семь сот • , • в о с емь сот ' , ' де в я т ь с о т '
)
;
Funct ion Numberтoword ( Num : Longint ) : S t ring ;
Var H : Longint ; L , C , R : Byte ;
CurrentTri : Byt e ; S : S t r i ng ;
begin
if Nwn= O then begin NwnЬerToWord : =AЬc ; Exit ; end ;
S [ O ] : = # O ; CurrentTri : = O ; H : =Num ;
Wh i l e Н > О do begin CurrentTri : =CurrentTr i + 1 ;
R : =H mod 1 0 ; Н : =Н div 1 0 ; С : =Н mod 1 0 ; Н : =Н div 1 0 ;
L : =H mod 1 0 ; Н : =Н div 1 0 ;
i f ( not ( ( C = 1 ) and ( R > O ) ) ) and ( L+C+R> O ) then S : =Te [ CurrentTri , R ] + '
' +S;
i f ( С= 1 ) and ( R> O ) then S : =Bbb [ C * 1 0 +R ] + ' ' +Т е [ Current Tri , О ] + ' ' + S ;
i f ( ( С = 1 ) and ( R= O ) ) o r ( С > 1 ) then S : = СЬа [ С ] + ' ' + S ;
i f L > O then S : =Hundreds [ L ] + ' ' + S ; end ; NwnЬerToWord : = S ;
end ;
end .
Что мы можем сказать о таком оформлении программ ы ? Текст довольно
компактен и не зан и мает много места. Это единственное достоинство дан
ной програ м м ы , которого в общем-то от нее никто и не требует. Про
грамма я вляется совершенно неч итабельно й , в ней не ясна структура,
крайне непросто выделить какие-либо фрагменты, а если предваритель
но не объяснить, что она делает, то и это будет непонятно. Конечно, это
надуман ный пример, специально создан ный для демонстраци и того, как
нельзя писать программ ы (однако достаточно потратить о коло получаса,
чтобы найти в сети l nternet аналогичное творение - проверено авторо м ) .
1 6. 1 . 1 .
Оформление и сходного текста
Оформление текста программ ы - важная часть ее разработки , включаю
щая в себя следующие прием ы :
506
Глава 1 6 . Качество програм м н ых п родуктов
•
•
•
использовани е ком м ентариев для пояснения действи й , выполняе
мых фрагментом программ ы ;
форматирование текста с помощью пробелов и пустых строк для
визуального отделения фрагментов программ ы друг от друга;
ясное именование идентификаторов - и ме н переме н н ых и других
программ н ых объектов.
Коммента р и и
Ком ментариями называются части программ ы , ограниченные фигурны
м и скобками . В с е ком ментарии игнорируются компиляторо м , поэтому
могут содержать любой текст:
{ Ко мм е н т а рий }
В место фигурн ых скобок могут использоваться последовательности сим
волов «(*>> для указан ия начала комментария и <<*)» для указан ия окон
чания комментария:
( * К о мм е н т арий * )
Комментарии могут занимать много строк или находиться в одной стро
ке с командам и программ (см . листин г 247 ) .
��\��'�j��i���?{·:�"g��������r�:�f��·����:if�q�;�'·itJ:i� ::i;�;:�w:·�,::jl.� fi�;;:�[:��ш:�:; :·:.;i.;i::7'r!i:.' \r
Var
i:
Integer ;
{ описание
п е р еме н н о й
дл я
сче тчика
ци кл а }
Begin
{ п е р е в о д с т р о ки }
{ Вывод н е с к ол ь ки х с т р о к на э к р а н с и с п ол ь з о в а ни е м цикла }
For i : = 1 То 1 0 Do
Wri t eLn ( 1 Стро ка номер 1 , i ) ;
{ выв од строки - константы и
значения сче тчика цикла }
Wr i t e Ln ;
End .
Распол оже н и е фрагментов программы по строкам
Рекомендуется располагать одну команду программ ы на одной строке,
однако это не всегда удобн о , поэтому в каждом конкретном случае сле
дует искать наиболее оптимальное решение. Например, если в процеду
ре используются две переменные А и в, а в начале подпрограмм ы их
следует обнулить, то это , видим о , м ожно сделать и в одной строке , что
придаст процедуре более компактный вид (это особенно важно для под
программ , так как с ними удобно работать, когда они полностью поме
щаются на одну страницу используемого текстового редактора) :
507
Turbo Pascal
7.0
Procedure Calculat e ;
Var
А, В : Intege r ;
begin
{ Инициали з а ц и я п е р еме н ных }
А : =О ; В : =О ;
{ Р е ал и з а ци я п р о ц е дуры }
end;
Логически законченные фрагменты программы (например, процедуры или
функции) м ожно отделять друг от друга пустыми строками, причем чем
больше объем проrрам м ы , тем большее расстояние требуется для разде
ления фрагментов (от одной до трех строк) . Использование пустых строк
продемонстрировано в листинге 248 .
�\��;�f:���:;:2����,;.и����:����i���::f1ygf�i�i!#r���i� ' : ;"-:·
Prograш Calculat o r ;
Procedure
begin
end;
Prepare ;
Procedure Calculat e ;
Var
А, в : Intege r ;
begin
{ и нициали з а ция
А : =О ; В : =О ;
end;
п е р еме н н ых }
Begin
End .
Если не следовать изложенным правилам распределения программы по
строкам , то она будет выглядеть непрерывным потоком сим волов , соот
ветственно, в ней будут с трудом улавливаться логические фрагменты, что
необходимо для понимания структуры программ ы .
П робел ы после з наков п р е п и н а н и я
Правила оформления текстов любой направленности , в том числе и про
грамм , требуют, чтобы после знаков препинания находился один пробел .
Это касается команд, параметров, описаний констант и переменных и
вообще всех слов, которые используются в п рограм м е . Также удобно от
делять пробелами слева и справа операторы присваивани я , оператор ра
венства = , арифметические и логические операторы . Приведем пример
программы , при написани и которой учтены вышеизложенные правила:
508
Глава 1 6 . Качество п рограм м н ы х продуктов
Ту р е
А = Int ege r ;
Var
В , С , D : Array [ 1 2 0 ] Of А ;
Begin
В : = О; С : = О; D : = О ;
I f ( В = О ) AND ( С = О )
Then Wri t eLn ( ' Обнаружено равенств о !
End .
•
•
' (В
=
С) ' ) ;
А вот как выглядела бы эта программа без использования разделяющих про
белов:
Тур е
A=Int eger ;
Var
B , C , D : Array [ 1 2 0 ] 0f А ;
Begin
B : =O ; C : =O ; D : =O ;
I f ( B= O ) AND ( C = O )
Then Wri t eLn ( ' Обнаружено равенств о ! • , ' ( В
•
•
=
С) ' ) ;
End .
Отступ ы в начале стро к
Программа м ожет иметь несколько блоков, вложенных друг в друга, на
пример составные операторы , вы полняемые в качестве зацикленной ко
манды , вложенные циклы и так далее . В таких случаях рекомендуется
каждый блок выделять относительно других с п омощью отступов от ле
вого края окна редактирования . При испол ьзовании вложенных циклов
луч ше каждый из н их располагать на отдельной строке и также выделять
дополнительным отступом (см . листинг 249 ) .
Var
i,
j:
Intege r ;
tmpA :
Intege r ;
А:
Array
[1
•
•
11]
Of
Intege r ;
Begin
For i
:=
For j
1 То 1 0 Do
: = i + 1 То 11 Do
If A[i]
< A[j ]
Then
begin
tmpA
:= A[i] ;
A[i]
: = A[j ] ;
509
Turbo Pascal
A[j ]
7.0
:=
tmpA;
end;
End .
Чем большей степенью вложенности обладает некоторый блок, тем боль
ший отступ от левого края окна редактирования он будет и м еть. Коли
чество пробелов, которое следует использовать для выделения блока от
носительно предыдущего, зависит от предпочтений программ иста. Обычно
используется от одного до трех пробелов (в при ведеиной программе ис
пользовался один пробел) . Их может быть и больше. Например, иногда
удобно расположить команды следующим образом :
Va r
i , j : Int ege r ;
tmpA : Integer ;
А : Array [ 1 1 1 ]
•
•
Of
Integer ;
Begin
For i : = 1 То 1 0 Do
For j : = i+1 То 1 1 Do
I f A [ i ] < A [ j ] Then begin
tmpA
A[i]
A[j ]
end;
A[i] ;
A [j ] ;
: = tmpA ;
:=
:=
End .
Однако следует опасаться увеличения ширины текста, так как он может
не поместиться в окне редактирования, что крайне негативно сказывает
ся на читабельности программы (см . листинг 250 ) .
nоместилось в окне
Va r
i,
j:
Intege r ;
tmpA : Intege r ;
А : Array [ 1
11]
•
Begin
For i
End .
510
Не nоместилось в окне
•
Of
Integer ;
: = 1 То 1 0 Do
For j : = i + 1 то 1 1 Do
I f A [ i ] < A [ j ] Then
begin
tmpA : = A [ i ] ;
A[i] : = A [j ] ;
A [ j ] : = tmpA;
end;
Глава 1 6 . Качество програм м н ы х п родуктов
Еще одна ч асто встречающаяся ошибка - компоновка текста програм
мы «уголком>> . М ы даже не будем комментировать такой подход, так как
его п оложительные стороны абсолютно неясны, а отрицательные мы уже
обсудили (см. листин г 25 1 ) .
[к1JW����вt;;_2,�J:�����·��;§,�����'f_€��r���P:�re:igм:�z�:��§J:Ii{��:;���,i:!:·:j: :(·::: ·� ��'·.-.
Var
i , j : Integer ;
tmpA : Intege r ;
А : Array [ 1 . . 1 1 ] O f Integer ;
Min , Мах : Intege r ;
Begin
For i : = 1 то 1 0 Do
For j : = i+1 то 1 1 Do
I f A [ i ] < A [ j ] Then
begin
Min : = A [ i ] ;
Мах : = A [ i ] ;
tmpA : = A [ i ] ;
A[i] : = A[j ] ;
A [ j ] : = tmpA ;
end ;
End .
Использо в а н и е регистра с имвол ов и с и м вола п одчеркивания
Turbo Pascal является реrистронезависимым языком программирован ия , то
есть один и тот же идентификатор может быть набран пропи сными сим
волам и , строч н ы м и или тем и и другими одновременн о . Это свойство
удобно использовать для выделения отдельных слов в составе одного иден
тификатора. Например: Wr i t eLn, Get image , FreeMem вместо wri t e l n ,
get image, freemem.
Что касается собственных идентификаторов, то для отделения слов в них
м о ж н о и с п ол ь з о в ать с и м в о л п од ч е р к и ван и я , н а п р и м е р : my _a g e ,
computer_name , temporary_i'nt и так далее. Совместно с символом под
черкивания при именовании идентификаторов можно использовать и заг
лавные символ ы , например: My_Age, Computer_Name, Temporary_Int. Ре
комендуется все же отдавать предпочтение использован ию заглавных
символов, а не знаков подчеркивания .
Прописные символы привпекают внимание человека, читающего програм
му, поэтому не стоит злоупотреблять и м и . Часто встречающейся ошиб
кой является написание прописными символам и всей программ ы вооб
ще . Это совершенно недопустим о , так как резко снижает читабельность
программы (см. листи нг 252) .
51 1
Turbo Pascal 7 . 0
:i�., , ��r:�и�����ftii�i����� ,: - .,�, ,>�"����ft���:���,r��; :::,:., {·�- ;)г.
. .
· ·..
VAR
J:
INTEGER ;
ТМРА :
I,
INTEGER ;
ARRAY
А:
[1
•
•
11]
OF INТEGER ;
BEGIN
FOR I
1 ТО 10 DO
:=
FOR J
:=
IF A [ I ]
I + 1 ТО 1 1 DO
< A [ J]
ТНЕN
BEGIN
ТМРА
:=
A[I] ;
A[I]
:=
A [ J] ;
A [ J]
:=
ТМРА ;
END ;
END .
Именование идентифи каторов. Венгерская н отация
И менование идентификаторов - тема, которая заслуживает более при
стального рассмотрения. Идентификатор является отражением области па
мяти , в которой хранится информация какого-либо типа, относя щаяся к
какому-либо объекту автоматизации или моделирования, или подпрограм
м ы , которая выполняет совершенно определенные действия . Поэтому,
идентификатор должен точно и ясно описывать програм мный объект. Су
ществуют неофициальные правила именования идентифи каторов , приме
няемые в различных языках программ ирования и известные под назва
нием венгерская нотация. Венгерская нотация предложена сотрудником
фирмы Microsoft Чарльзом Симон и.
Приведем некоторые основные правила, изложенные в вен герской нота
ции (венгерская нотация сильно ориентирована на язык проrрамм ирова
ния С/С++ , поэтому мы не будем приводить п олный перечень ее реко
мендаций) :
Правило 1. Имя переменной должно начинаться с ирефикса в виде
одного или н ескольких строчных символов, определяющих ее тип .
Т о ж е относится и к именам функци й - о н и должны начинаться с
префиксов , определяющих тип возвращаемых функциям и значени й .
П р еф и кс ы , кото р ы е м о гут б ы т ь р е ко м е ндо в а н ы для я з ы ка Tu rb o
Pascal , и ти п ы д а н н ы х , кото р ы м о н и с оответствуют , п р и веде н ы в
табл . 9 и 1 0 :
51 2
Гла в а 1 6 . Качество п р ограм м н ы х п р одуктов
Префиксы для именования
переменных простых типов
Тип да нн ых
Таблица 9
Префиксы для именования
Таблица 1 0
переменных сложных типов данных
П реф и кс
Shortl nt
si
l nteger
i
Lon g l nt
Тип данных
П ре фикс
Stri пg
s
Array
а + пр ефи к с , со ответ ству ющ и й т и пу э ле м е нто в
Byte
1
Ьу
Word
w
File
f
Real
r
Text
t
Object,
а такж е все
оп ис ан и я т и по в
т
Set Of
set
ь
Boolean
Char
Pointer,
в то м ч исле и т и п и з и рован н ы е
с
р
Record
Trec
Правило 2. Сами идентификаторы записываются английскими слова
ми , сло восочетания м и , сокращениями слов или сло восочетани й , а
также аббревиатурами , приняты ми в автоматизируем о й ил и м оде
лируемой области , таким образом , чтобы из их н азвания было п о
нятно и х назначение.
П р и мечание .
Не следует и с n ол ьзо вать n ерем е н н ы е , н аз в а н н ы е транскр и n ци я м и русских
сло в , ти n а M o e l mya ( « м ое и м я » ) , так как такие идентифи като ры ч и таются с
т рудом . Н а м н ого n роще и меть n од руко й а н гло- русски й сло в а р ь для соста в
л е н и я и м е н из англи й ски х сло в ( в дан н о м случ ае M y N am e ) .
Сам Чарльз С и м о н и изложил факторы , рассматриваемые при о п исании
нового идентификатора в программ е , следующим образом :
•
•
•
•
Идентификатор должен легко запоминаться.
Роль иденти фикатора должна быть ясна из его названи я .
Похожие объекты должн ы и меть похожие идентифи каторы .
Придумы вани е , ввод и редактирование идентификатора не должны
зани м ать сл и ш ком м ного времени , то есть идентификатор н е дол
жен быть сли ш ком дл и н н ы м .
При ведем п р и м е р ы описания типов данных, пере м е н н ых, фун кци й и
процедур с использованием правил венгерской нотации (см . листинг 2 5 3 ) .
-tli,'&t';�&���,'��;�;:��fit����i;�t;�[��;!:�;�;������,����]};iti;�i��"�j;
P rogram HungarianNo t a t i on ;
Тур е
THшnan = Obj ect { имя THuman сформир о в а н о из п р е ф и к с а , у к а зы
в ающе го на то , что идентификатор является тип ом
д а н ных , и сл о в а Human ( ч е л о в е к ) , у к а з ыв ающе г о
н а т о , ч т о о б ъ е к т о пи с ыв а е т о д н о г о ч е л о в е к а }
17
Зах. 702
513
Turbo Pascal 7 . 0
sName :
byAge :
S t ring [ S O ] ;
{ имя sName сформир о в а н о и з nр е фик с а s , т а к
д а н н о е с в о й с т в о о б ъ е к т а име е т т и n S t r ing ,
и с л о в а Name ( имя ) , ч т о у к а зыв а е т н а х р а н е ни е
в д а н ном с в о й с т в е име ни ч е л о в е к а }
Byt e ;
{ имя byAge сф ормир о в а н о и з n р е ф и к с а Ьу , т а к
д а н н о е с в о й с т в о о бъе к т а име е т т и n Byt e ,
и с л о в а Age ( в о з р а с т ) , ч т о у к а з ыв а е т н а
х р а н е ние в д а н н ом с в о й с т в е в о з р а с т а ч е л о в е к а }
end ;
TahPeop1e
=
Array [ 1 . . 1 0 0 ] Of THWIIan ;
{ имя TahPeop l e сформир о в а н о из nр е фи к с а Т ,
ука зывающе г о н а т о , ч т о TahPeop l e я в л я е т с я
тиnом д а н ных , nрефи к с а а ( ти n д а н ных я в л я е т с я
ма с с и в ом ) , nрефи к с а h ( э т о ма с с и в э л еме н т о в
т и n а THuman ) и име ни Peop l e ( люди ) , ч т о
у к а з ыв а е т н а хр а н е н и е в n е р еме н ных д а н н о г о
т и n а информации о н е с к о л ь ких люд ях }
Var
hProgramme r :
THWIIa n ;
{ имя nереме н н ой hProgrammer с форми р о в а н о и з
n р е ф и к с а h ( име е т т и n THuman ) и сл о в а
Programmer ( nр о г р а мми с т ) , ч т о ука зыв а е т н а
х р а н е н и е в д а н н о й n е р е ме н н о й и н ф о рмации
о n р о грамми с т е }
hМanager : THWIIan ;
{ имя nереме н н ой hManager с ф о рмир о в а н о и з
n р е ф и к с а h ( име е т тиn THuman ) и сл о в а Manager
( уn р а в л яющий ) , что указыв а е т н а х р а н е н и е в
д а н н о й nереме нн о й и н ф орма ции о б уnр а в л яюще м }
ahpProgrammers : TahPeop1e ;
{ имя n е р е ме н н о й ahpProgramme r s с ф о рмир о в а н о и з
n р е фи к с а ahp ( име е т тиn TahPeop l e ) и сл о в а
Programmers ( nр о г р амми с т ы ) , ч т о у к а з ыв а е т н а
хра н е ни е в д а н н о й nереме н н о й и н ф о рмации о
н е с к о л ь ки х nр о гр амми с т а х }
iProgrammersNumЬer : Intege r ;
{ имя nереме нной iProgrammersNumЬer сформировано и з
nрефикса i ( име е т т и n Integer ) и сл о в о с о ч е т а ни я
Programmer sNumber ( к олич е с т в о n р о г р амми с т о в ) ,
ч т о указыв а е т на х р а н е ние в д а н н о й n е р еме н н о й
и н ф о рмации о колич е с т в е n р о г р амми с т о в }
Funct ion
514
iGetNumЬer : Intege r ;
{ имя функции iGetNumЬer сформировано
( в о з в ращаемо е з н а ч е н и е име е т тиn
сл о в о с о ч е т а ни я GetNumber ( выд а т ь
что указыв а е т на вид в о звраща емой
ко лич е с т в о ч е г о - л и б о }
и з nрефикса i
I n teger ) и
к о л ич е с т в о ) ,
информации -
Глава 1 6 . Качество програм мн ы х п родуктов
Va r
i:
{ описание локаль ной переме нной i
для про с той
п е р еме н н о й в нутри н е б ол ь шой п о д п р о гр аммы можно
н е и с п о л ь з о в а т ь в е н г е р с кую н о т а цию }
Int eger ;
-
begin
For i
:=
IGetNWDЬer
1 То 1 0 Do ;
:=
i;
end ;
Procedure
R e s e tVariabl e s ;
{ в о п и с а нии име ни проце дуры не и с п ол ь з о в а н
п реф и кс , т а к к а к процедур а н е в о з вр а ща е т
к а ки х - л и б о з н а ч е ний }
begin
iProgr8.111111e rsNumЬer
:
=
О;
end ;
Begin
End .
Программу, написанную с учетом венгерской нотации , удобно ч итать, но
этим не ограничиваются полезные стороны описанных правил. Обычно
описания переменных и их использование находятся на расстоянии друг
от друга в несколько десятков или даже сотен программных строк, по
этому правильное именован ие переменных поможет избежать некоторых
ошибок, связанных с переполиеннем переменных или потерей точности
в операторах присваивания , а также вовремя заметить использование
некорректных операций сравнения. Рассмотрим пример:
Va r
iCount :
Int ege r ;
lPeopl eNumЬer :
Longint ;
Begin
lPeopl eNumЬer
iCount
:=
:=
100000;
l P eopleNumЬe r ;
End .
Если при ком пиляции данной программы установить флаг Range checking
(проверять границы диапазона переменных) , то в момент выполнения опе
ратора присваивания iCount : = l PeopleNшnЬer программ а будет оста
новлена и на экране появится сообщение Error 2 0 1 : Range check error
(Ошибка 20 1 : Ошибка при проверке границ диапазона) . Если же флаг Range
checking не устанавливать, то переменная iCount будет иметь значение
515
Turbo Pascal
7.0
-3 1 072, что я вляется динамической ошибкой потери точности. Обе ошибки
связаны с выходом значения переменной l Peopl eNumЬer за границы ди
апазона типа данных Integer, который имеет персменная i c ount . Если
бы персменная l Peop l eNumЬer имела значение, подходящее для перемен
ной типа Integer, то ошибки бы не произошло. В этом и проявляется ее
динамичность - ошибка возникает в зависимости от конкретных условий
данного сеанса работы программы.
Венгерская нотация позволяет заметить такие ош ибки еще на этапе раз
работки программ ы . Действительно, переменной с префиксом i , указы
вающим на ее принадлежиость к типу Int eger, приспаи вается значен ие
переменной , принадлежаще й более широкому типу L ongin t , что видно
по префиксу 1. Соответственно, сразу же видна возможность ошибки .
П р и м еч а н и е .
С о в р е м е н н ы е я з ы к и п рограм м и рован и я , нап р и м е р J ava, уже на эта п е ком п и
л я ци и сооб щают о возможной о ш и б ке п отери то ч н ости . В Turbo Pascal такой
о ш и б ки к о м п и л я ц и и не п редусмотрено .
То же касается и некорректного использования операции сравнения значе
ний двух персменных разных типов. Например, встретив в программе строку
I f iAge < sName Then . . . . . . . . . . . ;
сразу же можно сказать, что она ошибочна, и для этого не нужно искать, где
описаны персменные iAge и sName, когда при компиляции будет вьщана ошибка
Error 2 6 : Тype Mismatch ( Ошибка 2 6 : Не соот ветствие типов ) .
И , наконец, остановимся на использовани и персменных с коротким и
именами ти па i . Основное правило, которым следует руководствоваться
при назначении таких имен - это их узкая область видимости. Таким
образом , в небольших подпрограммах локальные персмен ные с коротки
ми именами использовать м ожно , а вот описывать глобальные п ерсмен
ные с коротким и именами категорически не рекомендуется . Персменная
i обычно используется в качестве счетчи ка цикла, и ее глобальное опи
сание может привести к тому, что программист может забыть сделать такое
описание в подпрограм ме. При ведем пример:
Var
i:
Integer ;
{ описание
гл о б а л ь н о й
п е р еме н н о й
с име н е м
i}
Proc edure Wri teLine s ;
begin
For i : = 1 То 5 Do
516
{ и сп ол ь з о в ание гл обаль ной п е р еме н н ой в к а ч е с т в е
с ч е тчика ц и к л а в л о к а л ь н о й п р о ц е дур е , к о т ор а я
вызыв а е т с я о с н о в н ой ч а с т ь ю п р о г р аммы из цикла ,
т а кже и с п о л ь зующе г о п е р еме н н ую i в к а ч е с т в е
с ч е тчика цикл а }
Глава 1 6 . Качество п рогра м м н ых продуктов
Wri t eLn ( i ) ;
end;
Begin
For i
:=
1 То 1 0 Do
Wri t eLine s ;
{ цикли ч е с кий выз о в п р о ц е дуры Wr i t e L i n e s долже н
п р о и з о й т и 1 0 р а з , одна к о буд е т п р о и с х о д и т ь
б е с к о н е ч н о , т а к к а к процедура Wri t eL i n e s н е
д а с т п ереме нной i с т а т ь р а в ной 1 0 - ти , уме н ь ш а я
е е з н а ч е ние до 5 - ти }
End .
1 6 . 1 . 2 . Документирова н и е .
И спол ьзован и е блок- схем
Документирование - это процесс подготовки описания программнаго
продукта. Документирован ие обычно проводится в двух направлениях для пользователя (подготовка справочной системы и обучающей литера
туры) и для разработчика (описание концеп ции проекта, особен ностей
алгоритма и используемых в программе структур данн ых) .
Документирование для пол ьзователя происходит в конечной стадии разработки
проекта, когда уже известн ы все детали интерфейса и той части концепции
программнаго продукта, о которой необходимо знать пользователю .
Документирование для разработч иков начинается с самого первого эта
па разработки - постановки задачи , на котором разрабатывается так на
зываемое техническое задание (ТЗ) - основной документ, регламе нтиру
ющий необходимую функциональность программы . Далее в процессе
разработки описываются все создаваемые программные м одули - биб
лиотеки функци й , объекты , используемые в программе , и ал горитмы ,
применеиные в тех или иных подпрограммах. Вне зависимости от направ
ленности документации , она должна быть краткой и исчерпывающей. За
мети м , что наличие документации к програм мному продукту не отменя
ет т р е б о в а н и й к п р а в и л ь н о м у о ф о р мл е н и ю п р о гр а м м ы , т о е с т ь
использования в н е й комментариев, форматирования и так далее.
Для описания алгоритмов часто при меняются так называемые блок -сх е
мы - схематические изображения алгоритмов, состоящие из специаль
ных графи ческих блоков, называемых символами. Построение блок-схем
регламентируется несколькими государственными стандартам и системы
стандартов «Единая Система Программной Документации (ЕСПД)>> .
К блок-схемам существует неоднознач ное от н ошение среди программ и
стов. Приверженцы их построения утверждают, что программу, особен
но сложную , невозможно реализовать без изначального построения блок517
Turbo Pascal
7.0
схемы, а противники доказывают обратное на примере. На сам о м деле
блок-схемы были крайне важны в те времена, когда основным языком
программирования б ыл ассемблер и программы большого объема было
просто невозможно удержать в голове. При объектно-ориентированном
подходе к п рограмм ированию блок-схему вполне способно заменить де
рево объектов с краткими пояснениями , хотя алгоритмы , использован
ные в методах объектов, все-таки удобно описывать с помощью блок-схем.
Так или иначе, блок-схемы значительно упрощают понимание алгорит
ма и каждому программнету следует владеть навыками их составления.
Замети м , что блок-схема является универсальным средство м представле
ния схем алгоритмов, причем не только в нашей стране - существуют и
международные стандарты , описывающие такие правила. В соответствии
с ними и разработана ЕСПД.
Приведем некоторые общие правила построения блок-схем и основные
символы, испол ьзуемые в них.
1 . С и мвол <<Пусю> (см. рис. 1 60) определяет стартовую точку представ
ляемого алгоритма.
2. Символ <<Останов» (см. рис. 1 60) определяет конечную точку п ред
ставляемого алгоритма.
3 . Си м вол <<Процесс>> о пределяет логически законченный фрагмент
программ ы , за исключением вызова п одпрограмм ы . В каждом с и м
воле блок-схемы (не только в этом) можно указать н екоторую и н
формацию (описание, уточнение и л и какие-либо ссылки для более
полного п о н и мания функции данной части системы) . З ап иси внут
ри с и мвола должны быть представлены так, чтобы их можно было ч и
"П
"
(...___,,....-JJ - уск
тать слева направо и сверху вниз, это
касается и всех остальных надписей
"
"
н а блок-схе м е . В данн о м с и м воле
(..._
J) - Останов
указывается функциональность фраг
"
"
мента, в том числе возможно указа
- П роцесс
ние одн о й или нескольких программ
ных стро к (см. рис. 1 6 1 ) .
" П едоп еде е нны й
р
р
�
л
4. Символ <<Предопределенный процесс>>
процесс "
�
определяет вызов п одпрограммы.
5 . Символ <<Решение>> определяет ветв
"
"
- Решение
ление, испол ьзуемое в данном месте
ал горитма. Для п редставления зацик
л и вания отдельного с и мвола н е пре
,LJ - "Ввод - вывод"
дусм отр ен о , п р и ме н я ется этот же
''
''
символ в силу логической близости
....,.___ Ко мме нтар и й
ветвл е н и я и зацикливания. В нутри
Рис. 1 60. Символы,
символа указы вается условие, на ос__
�
_
�
-[
используемые в блок-схемах
51 8
Глава 1 6 . Качество програм м н ых п родуктов
Рис.
1 6 1 . Пример блок-схемы
нове которого принимается решени е , а н а и сходящих ветвях значения этого условия (см . рис. 1 6 1 ) .
6 . С и мвол <<Ввод-вывод>> о пределяет наличие ввода или вывода како й
либо и нформации в данном месте алгоритма (см. рис. 1 60 ) . Внутри
сим вола указывается характер вводим о й или в ыводим о й и нформа
ции, например названия переменных, значения которых выводятся
на экран или вводятся с клавиатуры (см. р и с . 1 6 1 ) .
7 . Если справочная и нформация н е помещается внутр и символа, то
используется символ <<Комментарий>> (см. р и с . 1 60 ) , находящ и й ся
рядом с с и м волом , к которому он относится (см. р и с . 1 6 1 ) .
Отдельные символы объединяются в блок-схему соединительными ли ни
я м и со стрелкам и (см. рис. 1 6 1 ) , определяющим и н аправление выполне
ния потока команд, однако при направлении п отока от одного с и мвола
к другому слева направо или сверху вниз стрелки могут не изображаться
(но только если линии не и меют изломов) . Линии потока должны быть
п араллельны линиям внешней рамки схемы, то есть быть горизонталь
ными или вертикальным и .
В схеме символу м ожет быть присвоен идентификатор, который должен
помещаться слева над символом (например, для ссылки в других частях
документации) . В качестве самого идентификатора могут использоваться
любые сочетания символов и цифр, например порядковые номера сим
волов (см. рис. 1 6 1 ) .
Отметим требование государственного стандарта к подпися м , находящим
ся на блок-схеме: «Записи внутри символа или рядом с ним должны быть
краткими. Сокращение слов и аббревиатуры, за исключением установлен
ных государственными стандартами , должны быть расшифрованы в ниж
ней части поля схемы или в документе, к которому эта схема относится>> .
М ы привели л и ш ь малую часть правил оформления блок-схем , однако
такого количества информации вполне достаточно, чтобы описать про
грамму практически любой сложности.
519
Turbo Pascal
7.0
1 6 . 1 .з.
П р и мер оформления и сходного текста
п рогр а м м ы и ее документирован и я
В заключение описания правил оформления программ приведем исправ
ленный пример библиотеки с функцией , переводящей число в его стро
кавое представл е н и е , п редставленной в нечитабельном виде в начале
настоящего раздела, а также небольшое описание алгоритма, который
используется в данной функции .
Кр аткое описание функцио н ал ь ности
Перевод целого числа в строкавое п редставление на русском языке осу
ществляется функцией sNumЬerToWords , находя щейся в библиотеке nTo s .
Функция рассчитана н а параметры в диапазоне о т О до 9999999999, что
полностью покрывает неотрицательную часть области допустимых значе
ний ти па данных Longint (максимальное значение 2 1 4748 3647 ) . Неболь
шие изменения в данной функции могут адаптировать ее к и спользова
нию во всем диапазоне допустимых значений типа L ongi n t .
При ведем несколько примеров использования функции :
•
•
•
Есл и в качестве аргумента задано число 1 0 , т о результатом , возвра
щаемы м функц ие й , будет строка «де с я т ь » .
Есл и в качестве аргумента задано числ о 1 5 , т о результатом , возвра
щаемы м функцией , будет строка «п я т н а дца т ь ».
Если в качестве аргумента задано число 2 1 4 7 4 8 3 6 4 7 , то результа
том , возвращаемым фун кцией , будет строка «дв а милли арда с т о
с о р о к с емь милли о н о в ч е тыре с т а в о с е мь д е с я т три тыс ячи
ш е с т ь с о т с о р о к семь » .
О п исание алгоритма
Ал горитм преобразования основан на разбиении ч исла, заданного в ка
честве параметра, на тройки цифр справа налево . Если количество цифр
в числе не кратно трем , то последняя (самая левая) тройка может содер
жать нули слева, например:
Число
Тро ii ки
1 23
1 23
1 23456
456, 1 23
1 2345
345, 0 1 2
289933 1 5
3 1 5 , 99 3, 0 28
И звлечение трой ки из ч исла производится троекратны м определением
остатка от деления исходного числа на 10 (с помощью оператора mod ) ,
результатом которого я вляется самая правая цифра числа. После каждо
го определения остатка из исходного ч исла удаляется последняя цифра
520
Глава 1 6. Качество п рограм мн ы х п родуктов
целочисленным делением данного ч исла на 1 О (с помощью оператора це
лочисленного деления div) . Процедура, выводящая на экран тро й ки ч и
сел , может выглядеть следующим образом (см . листинг 254) .
Procedure
Var
Get'l'rio s ( l :
Longint ) ;
byDigitRight :
Byt e ;
{ п ереме н н а я дл я х р а н е ния п р а в о й цифры
т е кущей т р о й ки }
byDigitCent e r : Byt e ;
{ л ереме н н а я дл я х р а н е н и я с р е д н е й цифры
те кущей т р о й ки }
byDigitLe f t : Byt e ;
{ п ереме н н а я дл я х р а н е н и я л е в ой цифры
т е к ущей т р о й ки }
lRemainde r : Longint ;
{ п е реме н н а я дл я х р а н е н и я т е куще г о с о с т о я н и я
ч и с л а , и з к о т о р о г о выдел яю т с я тр ойки }
begin
lRemainder
: =
1;
{ иници а ли з а ция п е р еме н н о й ,
в ыд е л я т ь с я тройки чи с е л }
из
к о т ор о й
будут
Wri t eLn ;
Whi l e lRemainder
> О Do
{ условный оператор цикла , условие продолжения
число , из которого выдел яются тройки , п оложи
тель н о , т о е с т ь с одержит цифры }
Begin
ЬyDigitRight
lRemainder
: =
byDigitCent e r
lRemainder
: =
lRemainder mod 1 0 ;
{ з а н е с е н и е п р а в о й цифры чи сл а , из к о т о р о г о
выд е л яю т с я тройки , в л ер еме н ную byDi g i t R i ght
( о с т а т о к о т д е л е н и я н а 1 0 и е с т ь пр а в а я
цифра т р о й ки ) }
lRemainder div 1 0 ;
{ ус е ч е н и е з н а ч е н и я переме н н о й l Rema inder н а
о д н у цифру с п р а в а , и л и з н а ч е н и е л е р еме н н о й
н е и зме н я е т с я , е сли о н о р а в н о О }
: =
lRemainder mod 1 0 ;
{ з а н е с е н и е пр а в о й цифры числа , из к о т о р о г о
выделяют с я тройки , в п е ремен ную byD i g i t C enter
( о с т а т о к о т д е л е н и я н а 10 и е с т ь с р е д н я я
цифра т р о й ки ) }
lRemainde r div 1 0 ;
{ ус е ч е ни е з н а ч е н и я п ер еме н н о й l Rema i nder н а
одну цифру спра в а , или з н а ч е н и е п е р еме н н о й
н е и зме н я е т с я , е сли о н о р а в н о О }
: =
52 1
Turbo Pascal 7 . 0
byDi g i t L e f t
l Rema inder mod 1 0 ;
{ з а н е с е н и е п р а в ой цифры чи с л а , и з к о т о р о г о
выд е л яют с я тройки , в п е ремен н ую byDi g i t L e f t .
( о с т а т о к о т делени я н а 1 0 и е с т ь л е в а я
цифр а т р о й ки ) }
l Remai nder : = l Rema inder div 1 0 ;
{ ус е ч е н и е з н а ч е ни я п е р еме н н о й lRema inder н а
одну цифру спр а в а , или з н а ч е н и е п е р еме н н о й
н е изме н я е т с я , е сли о н о р а в н о О }
Writ e ( byDi g i t L e f t , byDi gi tCenter , byDi g i t Ri ght ,
');
{ выв од п олуч е нн о й т р о й ки цифр на э кр а н }
end ;
:=
en d ;
После п олучения очередной тройки производится ее анализ, основанн ы й
на правилах построения числительного в русском язы ке . Формирован ие
языкового п редставления тройки происходит только тогда, когда хотя бы
одна цифра из тройки иенулевая (иначе данная тройка ничего не добав
ляет в строкавое представление числа) , следующим образом :
Добавление признака разрядности. К результирующей строке , в зависимо
сти от номера текущей тройки, добавляется признак разрядности (сле
ва) : <<МИЛЛИардЫ» , <<МИЛЛИОНЫ» , «ТЫСЯЧИ>> ИЛИ <<едИНИЦЫ» . Добавление ПрИ
знака разрядности производится в зави с и мости от п оследней цифры
тройки и и меет форму <<шесть миллионов>> , <<пять тысяч>> , <<девять м илли
ардов>> и так далее или просто «шестЬ» , <<ПЯТЬ» , «девять>> , если это самая
правая тройка. Для этого правила существует исключение, связанное с
особенностями названи й чисел от 1 1 до 1 9 . Если тройка оканчи вается на
такие цифр ы , то к ней добавляется признак разрядности не в описанной
форме, а в форме «шестнадцать» , а далее <<м иллионов>> или <<пятнадцатЬ» ,
а далее <<ТЫСЯЧ>> .
Добавление признака десятков. Если тройка содержит иенулевую среднюю
цифру, то есть число содержит десятки , то к результирующей строке при
бавляется (слева) признак десятков: «десять>> , <<двадцать>> , <<тридцать» и так
далее. Исключение - средняя цифра, равная еди нице, при последней
цифре, не равной нулю, так как это означает, что тройка оканчивается
на 1 1 . . 1 9 , а такая ситуация уже учтена при добавлении признака разряд
н ости.
Добавление признака сотен. Если тройка содержит иенулевую левую циф
ру, то есть число содержит сотни, то к результирующей строке прибав
ляется (слева) признак сотен: «СТО», <<двести» , <<Триста>> и так далее.
В результате перебора всех троек получим и скомое строкавое представ
ление числа.
522
Глава 1 6 . Качество п рогра м м н ы х п родуктов
Заметим , что одно число
О
не вписывается в данную схему, поэто
му в начале фун кции необходимо проверить параметр на равенство нулю
и вернуть строку «ноль» в качестве результирующей строки .
-
-
Блок- схе ма алгоритма фун кции
Блок-схема алгоритма функции представлена на рис. 1 62 .
Ниже приведен текст рассмотренной нами в самом начале этой главы
библиотеки , но уже в п равильно оформленном в иде (см . л истин г 255 ) .
Воз в р а щаемое з н а че н и е
·
"Ноль''
Возв ращае мое з н а ч е н и е - сфо р м и р ованная строка
Вычисление номера тройки
byCurrentTrio
: = ЬyCurrentТrio + 1
Выделение цифр тройки
ЬyDigitRight, byDig itCenter и by Digitleft
и уменьшен и е I R e m aind e r в
1 000 р аз
Нет
Нет
Кон е ц
Рис. 1 62. Блок-схема функции sNumberTo Word
523
Turbo Pascal
7.0
J-,'�����м�;����;:�;:;��;�;����:���R��@�-���-\чt�1f���J�,;:, �"�i;,)��\t:±:'пe
{ Модул ь nTo S с одержи т функцию sNumberToWord , выдающую н а о с н о в е
параме тра т и п а Longint е г о с т р о к а в о е предс т а в л е н и е н а русс ком языке .
Фун кция р а б о т а е т т о л ь к о с п о л о жи т е л ь ными чи сл ами .
Приме р . sNumЬerToWord ( 1 2 3 6 5 4 ) в о з в р а ща е т с т р о к у ' с т о д в а дц а т ь три
тыячи ш е с т ь с о т п я т ь д е с я т ч е тыр е ' . Ал г о ритм п е р е в о д е о с н о в а н н а
р а з би е нии ч и с л а н а тройки цифр спр а в а н а л е в о , з а т е м п е р е в о д а э тих
тро е к в с тр о к с в о е п р е д с т а в л е ни е . С т ро к о в с е п р е д с т а вл е ни е д л я оче
р е д н о й тройки з а писыв а е т с я сле в а от п р е дыдущи х , в р е зуль т а т е ч е г о
п олуч а е т с я п о л н о е с т р о к о в с е пре д с т а в л е ни е в с е г о ч и с л а }
Uni t
nTo S ;
{ Начало
Int e r f a c e
Funct i on
Impl ementat i on
Тур е
TsWords
интерфейсной
sNumЬerToWords ( lNum :
=
{ Начало
о п и с а т е л ь н ой
String [ 2 0 ] ;
{ Оп и с а н и е
ч а с ти
Longint ) :
библи о т е ки }
St ring ;
ч а с ти
библи о т е ки }
т и п а д а нных н а о с н о в е с т р о ки }
Con s t
{ М а к симал ь н о е колич е с т в о тр о е к , п оддержи в а емо е функци е й }
iмaxтri o s = 4 ;
{ К о н с т а н т а дл я числа н оль - о н о н е в пи сыв а е т с я в о бщую с х е му }
sTheNu l l : T sWords = ' Ноль ' ;
{ М а с си в в с е в о зможных при з н а к о в р а зрядн о с т и в з а в и симо с т и о т
н оме р а тройки и е е п о сл е д н е й цифры . И с п о л ь з уе т с я , к о г д а
с р е д н я я ц и ф р а т р о й к и н е р а в н а единице , пр а в а я ц и ф р а т р ойки
равна нулю и с р е ди цифр тройки е с т ь х о т я бы о д н а н е нул е в а я }
aswTrioEnds : Array [ 1 . . iMaxTrios , О . . 9 ] Of TsWords =
(
1 1
,
• один • ,
' дв а • ,
' три ' ,
' четыре ' ,
' nять ' ,
' ше сть ' ,
• семь • ,
' в о семь • ,
' девять '
),
( • тысяч ' ,
' одна
тысяча ' ,
' дв е
тысячи ' ,
' три
тысячи ' ,
' четыре
' nять
524
тысячи ' ,
тысяч ' ,
Глава 1 6 . Качество п рограм м н ых п родуктов
' шесть
' семь
тысяч ' ,
тысяч ' ,
' в о семь
тысяч ' ,
' девять
тысяч '
)
,
( 1 миллионов
1,
1 ОДИН МИЛЛИОН 1 ,
' дв а
миллиона ' ,
' три
миллио на ' ,
' четыре
' nять
миллиона ' ,
миллионов ' ,
' шесть
' семь
миллионов ' ,
миллионов ' ,
' во семь
миллионов ' ,
' девять
миллионов '
)
,
( ' миллиардов ' ,
' один
миллиард ' ,
' дв а
миллиарда ' ,
' три
миллиарда ' ,
' четыре
' nять
' шесть
' семь
миллиарда ' ,
миллиардов ' ,
миллиардов ' ,
миллиардов ' ,
' в о семь
миллиардов ' ,
' девять
миллиардов '
)
;
{ Элементы ма с с и в а д о б а вл яю т ся к с т р о к е , е сли т р о й к а з а к а нч и в а е т
с я н а 1 0 или ух , г д е у > О , а х
люб о е , т о е с т ь е сли т р о й к а
с о д е ржит д е с я т ки , н о они еще не уч т е ны при д о б а в л е ни и п ри з н а к а
р а з р яд н о с т и дл я о к о нч аний т р о е к в и д а 1 1 1 9 }
a swDecima l s : Array [ l 9 ] Of тswords =
-
.
•
.
•
( ' десять ' ,
' дв адцать ' ,
' тридцать ' ,
' соро к ' ,
' nятьдесят ' ,
' ше стьдесят ' ,
' семьдесят ' ,
' в о семьдесят ' ,
' девяносто '
)
;
{ Эл еме нты ма с с и в а д о б авляютс я к с т р о ке п е р е д при з н а ком
р а з р я дн о с ти , е сли т р о й к а з а к а нчив а е т с я н а чи сл о о т 11 д о
aswтeen s : Array [ 1 1 1 9 ] O f TsWords =
•
19}
•
( ' одиннадцат ь ' ,
525
Turbo Pascal
7.0
1 дв еи адца'l'Ь 1 1
1 '1'рииадца'l'Ь 1 1
1 Ч е'1'ыриадца'l' Ь 1 1
1 nя'l'иадца'l'Ь 1 1
1 шес'l'иадца'l'ь 1 1
1 семиадца'l'Ь 1 1
1 в о семиадца'l'Ь 1 1
1 девя'l'иадца'l'ь 1
);
{ Э леме н ты ма с с и в а д о б а в л яют с я к с т р о к е , е сли ле р в о е
т р о й к и - н е н о л ь , т о е с т ь тройка с одержи т с о т ни }
aswНUndreds : Array [ 1 9 ] Of TsWords =
( 1 C'l'0 1 1
•
число
•
1 двес'l'И 1 1
1 '1'рИС'l'а 1 1
1
че'l'ыре с 'l' а 1 1
1 ПЯ'l'ЬС0'1' 1 1
1 Ш&С'l'Ь СО'l' 1 1
1 семь со'1' 1 1
1 в о семь со'l' 1 1
1 Д8ВЯ'l'Ь С0'1' 1
);
Funct i on sNumЬerToWords ( lNum : Longint ) : String;
Var
lRemainder : Longint ;
byDigitLeft l byDigit Center l byDigitRight : Byt e ;
byCurrentTrio : Byt e ;
sCurrent Str : S t r ing ;
begin
If lNum = О Then
begin
sNumЬerToWords : = sTheNu l l ;
Exi t ;
end ;
sCurrent S t r [ O ] : = # 0 ;
byCUrrentTrio : = О ;
lRemainder : = lNum ;
Whi l e lRemainder > О Do
begin
ЬyCurrentTrio : = byCurrentTrio + 1 ;
ЬyDigitRight : = lRemainder mod 1 0 ;
lRemainder : = lRemainder div 1 0 ;
ЬyDigitCent e r : = lRemainder mod 1 0 ;
lRemainder : = lRemainder div 1 0 ;
byDigitLeft : = lRemainder mod 1 0 ;
lRemainder : = lRemainder div 1 0 ;
I f ЬyDigitLeft + byDigitCent er + byDigitRight >
526
О
Then
Глава 1 6 . Качество п рограм мн ы х п родуктов
+
begin
{ Д о б а вл е н и е при з н а к а ра зрядн о с ти }
i f NOT ( ( byDigitCent er = 1 ) AND ( byDigitRight > О ) )
Then s Current S t r : = a swTrioEnds [ byCurrentTrio , byDigitRight ] +
1 1 + sCurrent Str
{ О б н аруже н о число т и п а x l l - x 1 9 }
E l s e sCurrent S t r : = aswтeens [ byDigit Cent e r * 1 0 + byDigitRight ]
1
1
1
1
+ aswTrioEnds [ byCurrentTrio , 0 ] +
+ sCurrent St r ;
{ До б а в л е н и е при з н а к а д е с я т к о в }
I f ( ( byDigitCente r = 1 ) AND ( ЬyDigitRight = О ) )
( byDigitCent er > 1 )
Then s Current S t r : = aswDe c ima l s [ byDigitCent e r ] +
1 1 + scurrent s t r ;
{ До б а вл е н и е при з н а к а с о т е н }
I f byDigitLeft > О
Then sCurrent S t r : = a swHundreds [ byDigitLe f t ] +
1 1 + sCurrent St r ;
end;
end ;
sNumЬerToWords
end;
end .
:=
OR
s Current S t r 1
1 6 . 2 . Ф у н кционал ь н ость
Общие вопросы обеспечения качества программнога продукта в разрезе
его функциональности мы обсудили во вводной части настоящей главы ,
а сейчас п одробнее остановимся на некоторых аспектах обеспеч ения бе
зошибочности программы как в смысле обнаруже н ия и исправления ло
гических и динамических о шибок, так и в смысле защиты от некоррек
тных действий пользователя , проблем защиты программных продуктов от
несанкционированного использования и доступа программ к об�емам
динамической памяти , большим , чем 640 Кб .
1 6.2. 1 .
Тести рование прогр а м м ы
После разработки программы, исправления синтаксических ошибок, ком
п иляции и построения программы начинается этап ее тестирования - оп
ределения соответствия реализованной программы поставленной задаче.
Процесс тестирования нач и нается с проверки возможности ввода всех не
обходимых исходных данных, их корректной обработки и п равильного хра
нения . Далее провернется правильиость работы алгоритма с п омощью, на527
Turbo Pascal 7 . 0
пример, тестовых примеров, которые должен подготовить сам разработ
чик или заказчик программнога продукта. При выявлении логических
ошибок (неправильной реализации алгоритма) их следует исправить и на
чать тестирование заново.
Обработка о ш и бок . Использование директив компилято р а
Программы, написанные на Turbo Pascal , очень чувствительны к неправиль
ным действиям пользователя, особенно при вводе информации. При исполь
зовании процедур ввода информации Read и ReadLn мя получения значе
ний ч и сленных типов пользовател ь должен стро го соблюдать формат
вводимой информации. Но, поскольку пользователь обычно не является про
фессионально подготовленным в области информационных технологий или
просто может допускать ошибки при вводе информаци и , программа долж
на брать на себя большую часть проверки ее корректности. Ошибки нару
шения допустимых форматов данных, работы с файлами и графической
системой и многие другие обслуживаются модулями , автоматически добав
ляемыми к программе при компиляции . Основой работы таких систем об
работки ошибок является положение, что лучше закончить программу, вы
дав пользователю сообщение о фатальной ошибке, чем продолжить ее работу
с некорректными данными. Отчасти это справемиво, однако обычно при
водит к потере больших массивов информации , введенных пользователем
до возникновения ошибки, а также к невозможности программы выполнить
собственную деи нициализацию, например закрыть файлы, в которые про
изводилась запись, и освободить занятую динамическую память.
Наиболее оптимальным решением в дан ном случае является отключение
автоматических систем обработки ошибок и проверка корректности вы
полненных действий самой программой. Это значительно увеличи вает ее
размер и сложность, однако обеспеч и вает удобство работы пользовател я ,
в том числе и выдачу более понятных ему сообщени й об ошибках. Для
отключения систем обработки ошибок используются так называемые ди
рективы компилятору, которые разделяются на глобальные - действующие
на всю программу, и локальные
действующие только на некоторый
фрагмент программ , указываем ы й разработчико м .
-
К глобальным директи вам относятся настройки компилятора, задаваемые
в главном меню интегрирован ной среды разработчика Op t i ons 1 Compi l e r :
Range checking
подключение системы проверки выхода значений
индексов массивов и строк за грани цы допустимого диапазона мя
данного типа, а также обработки ошибок потери точности при выпол
нении некоторых операторов. В случае возникновения такой ошибки
система обработки завершает программу с о шибкой Error 2 0 1 : Range
check error (Ошибка 20 1 : Ошибка при проверке грани ц диапазона) .
Если данный флаг не установлен при компиляци и , то программ а
продолжает нормальную работу с некорректными данными.
-
528
Глава 1 6 . Качество п рограм м н ых продуктов
подключение систем ы обработки ошибок испол ь
зования стекавой области п амяти. П р и установке флага в резул ьти
рующую программу добавляется код, проверяющий возможность
вызова процедур и функц и й , п отребляющих память стека. Если
такой вызов невозможен , то программа прерывается с выдачей ошиб
ки Error 2 0 2 : S tack over f l ow error ( О ш иб ка 202: Ошибка
перепол нения стека) . Если система обработки о ш и бо к стека откл ю
ч е н а , т о стек при переполнении начинает запол няться заново, в
результате чего теряются адреса возврата из п одпрограм м , что, ско
рее всего , при ведет к краху операционной систе м ы .
S t ack checking
-
r.jo checking
п одключение систе м ы обработки о шибок ввода/вы
вода. К данной группе ошибок относятся о ш ибки открытия и зак
рытия файлов, а также чтения и записи значен и й переменных , в
том числе и с испол ьзованием файлов.
-
Overflow checking
подключение систем ы проверки выхода значений
переменных за границы диапазона значений для их тип а данных.
-
При разработке программы рекомендуется устанавливать все системы обра
ботки ошибок - это даст возможность выявить ошибки самой программы
по обработке данных. При тестировании следует ставить программу в такие
условия, которых, возможно, даже и не будет при ее использовании на прак
тике. Предельные значения переменных помогут найти ошибки в алгоритме.
После того как программа начнет работать у заказчи ка, автом атические
системы обработки ошибок можно отключить, чтобы они не вызывали
досрочного завершения програм м . Одн ако в этом случае пользователь
может столкнуться с некорректными результатам и программ ы , что часто
намного хуже потерян ных данн ых.
Глобал ьные директи вы ком пилятору не всегда удобны в использовани и ,
так как действуют н а всю программу в целом . Для более гибкого управ
ления областям и действия систем обработки ош ибок предусмотрены ло
кальные директивы компилятору. Для выключения систем ы обработки
ошибок, н ачиная с какой-л ибо программной строки , необходимо доба
вить в программу следующее указание:
{ $ < Код дире кти вы> - }
Для включения системы обработки о шибок, нач иная с какой -либо про
граммной строки , следует добавить в программу указани е :
{ $ <Код дир е к ти вы> + }
Коды систе м , указываемые в данных командах (директивах) ком п илято
ру, состоят из одной заглавной латинской буквы и перечислены в табл . 1 1 .
Заметим , что директивы ком пилятору заключаются в фигурные кавыч
ки , характерные для комментариев, что отражает их сущность - дирек
тивы не попадают в резул ьтирующую программу, а только указывают,
каким образом ее необходимо строить.
529
Turbo Pascal
7.0
Таблица 1 1
Дирекrивы компилятору
Дире к тива
$А
$В
$С
$D
$Е
$F
$G
$1
$L
$М
$N
$0
$Р
$0
$R
$S
$Т
$V
$W
$Х
$У
530
По
ум оп-
Впия ние вкпючения директивы
ч ан ию
Вкл ю ч ение выравн иван ия переме н н ы х и т и п и з и ро ванн ых констант по гран и це
маш и нного сло ва для увел и чения быстродействия nро грам м
Вклю ч ен ие полного в ар ианта проверк и ло г ич еск их выражен и й . Даже , есл и в
се редине ло ги ческого в ыражен ия уже ясен его р езул ьтат, все ра вн о данное
выражен ие будет вы ч и сляться до конца. Такая воз можность уменьшает быстро действие про граммы , однако позволяет выпол нить все фу нкции , в ключенные
в усл о в ное выражен ие
Указывает атрибуты про граммн а го сегмента модуля и п рименяется в в иде
{ $С < Атрибуты > } . Рассмотрение директивы вы ход ит за пределы н аш ей книги
Включает воз можность добавления отладочной ин форма ции для программ-отладчи ков , в то м ч исле и встроенны х в Turbo Pascal . При вы клю чении данной директивы
отладка будет невозможна, зато текст программы существенно сократится . Рекомен дуется не вкл ючать отладочную информацию в про граммы , передаваемые заказч и ку
Вклю ча ет э мул я ци ю математическо го сопро цессо ра 8087 . П роцессо ры 80486
и выше имеют встроенный сопро цессор
Вкл ючает модель вызо ва подпрограмм Fаг. Рассмотрение директивы вы ходи т
за пределы нашей кн иги
Указывает список библиоте к. которые нео бходимо расположить в одном сегменте .
Рассмотрение директивы вы ходит за пределы нашей книг и
Вкл ючает систе му о бработки о шибок ввода/вывода ( 1 0 checki n g )
Включ ает возможность до бавле ния отладоч ной ин фо рмации о пе ре мен н ы х , о п и санны х в п ро цедурах , функциях и разделах l m p le m e ntatio n библиотек. Реко мендуется не включать отладоч ную инфо рмацию в программы , передаваемые заказчи ку
Задает раз ме р ы памяти , необ ходимой для работы программ ы , и используется в
виде { SM < Размер стека>, < Минимальный размер Неар-памяти>, < Максимальный размер
Неар-памяти> }
Включает э мул я цию математическо го сопро цессора 8087 для вычислен и й
выражен ий с плавающей точкой (типа Real)
Вкл ючает специальную подгото вку для передачи стро ковы х п араметров и параметров-мно жеств в про цедуры и фу нкции . расположенные в оверлеях - специальн ы х
библиотеках , динами ч ески подгружаемы х к программе в случае нео б ходи мост и для
эко номии памяти . Расс мотрение директивы вы ходит за пределы наш ей книги
Вкл ючает возможность использован ия открытых строк в качестве параметро в подпро грам м. П ри включенной воз можност и в качестве строко вого параметра может
передаваться реальная переменная или констанl'а другого строкового типа (то есть
сmоки, размер которы х отличается от размера, указанного при описании параметра)
Вкл ючает систе му обработки о шибок переполнения (overflow checki n g )
Вкл ю ча ет систему о бработки о шибок вы хода з а п ределы диапазо н а и ндексо в
( range checki n g )
Вкл ю чает систе му обработки ошибок использо ван ия стека ( stack checking)
Заставляет о перато р @ (о пределен ие адреса заданной перемен н о й или
подпрограм м ы ) возвращать типизированны й указатель
Включает систе му п ро верки соответствия дл ины строко во го параметра дл и не
параметра, заданной п р и описании подпрограммы. Не рекомендуется использовать
данную директиву, так как она оставлена в Turbo Pascal только для совмест и мости
с предыдущими версиями. Вместо директивы $V следует использовать директиву $Р
Вкл ючает до бав л ен ие пролога и э п ило га для подпрограмм с моделью вызова Fаг .
Р а ссмотре н ие директивы вы ходит за nределы нашей книги
Вкл ючает так называемы й расширенный синтаксис Turbo Pascal
возможность
обраще н ия к функции как к про цедуре , то есть без рассмотрен ия з начен ия ,
которое она воз!!р_а щает
Включает возможность добавления отладочной информации о переменных библиотек
-
$А +
$В-
$ D+
$Е+
$1+
$L+
$N-
$Р$0$А$S +
$Т$V+
$Х+
$У+
Глава 1 6 . Качество п рограм м н ых п родуктов
Ош ибки ввода информации
В качестве при мера использования локальных директив ком пилятору
рассмотрим отключение и включение системы проверки ошибок ввода/
вывода. Рассмотрим следующую ситуацию. Программ а должна получить
от пользователя значение целочисленной переменной , допустим , его воз
раст. Пользователь может ошибиться и ввести вместе с ч исловым знач е
н и е м какие-либо нецифровые символы, например, указать с в о й возраст
как 1 5 . 5 . В результате такого ввода программа закон чится с ошибко й
Error 1 06 : I nva l i d numer i c format (Ошибка 1 06 : Неправильны й фор
мат числового значения) . Это и есть стандартное поведение системы об
работки ошибок вода/вывода, которую можно отключ ить директивой { $ I
} , а затем включить директивой { $ I + } . Далее следует воспользоваться
функцией I ORe sul t, возвращающей неиулевое значение, если последняя
операция ввода/вывода была ошибочна (см. листинг 256) .
Program Noi OErro rs l ;
Var
IAge :
Int ege r ;
Begin
Wri t eLn ;
Wri t eLn ( ' Вв о д возрас'l'а ( целое число O'l' О до 1 5 0 ) ' ) ;
{ о п и с а н и е форма т а для п о л ь з о в а т е л я }
{ $I - }
{ отключение системы обработки ошибок ввода / выв ода }
Repeat
Wri t e ( ' Вв еди'l'е
в аш
возрас'l' :
'
);
ReadLn ( iAge ) ;
Unt i l
IORe sult
=
О;
{ в в о д з н а ч е н и я , п о к а о н о н е буд е т в в е д е н о
п р а виль н о , т о е с т ь з н а ч е ни е фун кции I OResul t
н е с т а н е т р а в ным О }
{ $I+}
{ в ключение
Wri t eLn ( ' Cnacиб o ,
вв еденный
End .
{ и сп ол ь з о в ание
системы обработки ошибок в в ода / вывода }
в озрас'l' :
iAge ) ;
Результат работы программы пред
ставлен на рис. 1 63 . Пользователю
предлагается вводить свой возраст
до того момента, пока он не сде
лает это корректно. В приведеином
примере пользователь сумел ввес
ти правильное значение только с
пятой попытки . Однако м ы сдела-
значения и
з а в ершение
программы}
Ввод возраста (целое число о т О до 1 50 )
Введите Ваш возраст: мн е десять с половино й лет
Введите Ваш возраст: десять с половино й
Введите Ваш возраст: 1 0 , 5
Введите Ваш возраст: 1 0. 5
Введите Ваш возраст: 1 О
Спасибо, введенны й возраст: 1 0
Рис.
1 63. Результат работы
программы No/OErrors 1
53 1
Turbo Pascal
7.0
ли все возможное, чтобы помочь ему: в начале программ ы был о писан
формат, в котором требуется вводить возраст, затем при неправильном
вводе предлагалось ввести возраст заново. Такой подход совершенно уме
стен, и п ол ьзователю можно навязать некоторые правила работы с про
грам м о й . Желательно , конечно , сократить их до м инимума, но это не
всегда возможно. Однако следует запомнить, что если такие п равила су
ществуют, то пользователь должен о них знать.
Предложенная структура программ ы позволяет избежать ошибок набора
значения пользователем в смысле использования некорректных сим волов,
но не предотвращает возможности ввода неверного значения , выходя ще
го за пределы допустимого диапазона (см . рис. 1 64) . В этом случае программа будет завершена и н а э кран
будет выдана ошибка. Для того чтобы
Ввод возраста (целое число о т О д о 1 50)
такая ошибка не выдавалась и програм
Введите Ваш возр аст: 9999999
ма сама имела возможность проверить
Ruлtime error 201 at ОВЕВ :ООС6
корректность в в од и м о го з н ач е н и я ,
Рис. 1 64.
можно отключить и эту систему обра
Результа т некорректной
ботки ошибок с помощью директивы
ра боты программы No/OErrors 1
{ $R- } (см. листинг 257) .
&'
t1
f
'
�
�
�
�
�
�
�
i�
f
l{
j
�
�
�
�
�
�
�
�
1
,
'
'
�:
�
�
Program No10Erro rs 2 ;
Var
1Age : 1nt ege r ;
Begin
Wri t eLn ;
Wri teLn ( ' Вв о д в озраста ( целое число от О до 1 5 0 ) ' ) ;
{ о п и с а н и е форма т а дл я п ол ь з о в а т е л я }
{$1-}
{ о т ключ е н и е си с т емы о б р а б о тки о ши б о к в в од а / вы в о д а }
{ $R- }
{ о т ключ е н и е си с т емы о б р а бо т ки о ши б о к вых о д а з а п р е де л ы
ди а п а з о н а }
Repeat
Wri t e ( ' Введите в аш возраст : ' ) ;
ReadLn ( iAge ) ;
Unt i l 10Re sult = О ;
{ в в о д з н а ч е ния , п о к а о н о н е буд е т в в е д е н о п р а в и л ь н о ,
т о е с т ь з н а ч е ни е фун кции IOResul t н е с т а н е т р а в ным О }
{ $R+ }
{ в ключ е н и е с и с т емы о бр а б о т ки оши б о к вых о д а
з а п р е д е л ы ди а п а з о н а }
{ $1 + }
{ в ключ е н и е с и с т емы о бра б о т ки о ши б о к в в од а / в ы в о д а }
iAg e ) ;
Wri t eLn ( ' С п а си б о , в в ед е н ный в о з р а с т : '
{ и с п о л ь з о в а н и е з н а ч е ни я и з а в ерше н и е п р о г р аммы }
End .
,
532
Глава 1 6 . Качество п рограммных п родуктов
В таком варианте выполнения програм
Ввод возраста (целое число от О д о 1 50)
Введите Ваш возраст: 9999999
мы ошибка времени выполнения не по
Спасибо, введен ны й возраст: -27009
я вится , однако значение, занесенное в
Рис. 1 65. Результа т ра боты
перемен ную , м ожет быть не коррект
программы No/0Errors2
ным. Причем оно может и соответство
вать допусти м ы м п р еделам (от О до
1 50) , и не соответствовать им (см . рис . 1 65 ) . Поэтому после ввода пользо
вателем значения следует попросить его подтвердить корректность вво
да . Такое подтверждение можно выполнить с помощью е ще одного цик
ла Rep e a t . . . Un t i l , в который будет вложен ц и кл , осуществляющий
синтаксически корректный ввод значения (см . листинг 258).
�!i!JЦ�i��-�:.��-�·;;�:n ��;��P'-��i��.�.�9�,@r�·:(����!:l�1�s�P'i�fЯJ:���@Jt��i�.���
Program NoiOErro rs З ;
Uses
CRT ;
Var
IAge : Intege r ;
Ch : Char ;
Begin
Wri t eLn ;
Wri teLn ( • Ввод в озрас'l'а ( целое число o'l' О до 1 5 О ) • ) ;
{ о п и с а н и е ф орма т а дл я п ол ь з о в а т е л я }
{ $I- }
{ о т ключ е ни е с и с т емы о бра б о т ки оши б о к в в о д а / в ы в о д а }
{ $R - }
{ о т ключ е н и е с и с т емы о б р а б о т ки о ши б о к вых о д а
з а п р е д е л ы диап а з о н а }
Repeat
{ в н е шний ци кл , вых о д из к о т о р о г о в о зможе н
т ол ь к о по о с о з н а н н ому выбору п о л ь з о в а т е л я }
Repeat
{ в нутр е н ний цикл , вых од из к о т о р о г о прои з в о ди т с я
в случ а е с и н т а к с и ч е с к о й в е р н о с т и в в одимо г о ч и сл а }
Wri te ( ' Введи'l'е ваш возрас'l' : • ) ;
ReadLn ( iAge ) ;
Unt i l IORe sult = О ;
Wri t eLn ( ' Ваш возрас'l' :
iAge ,
nравил ьно ? ( Y/ N ) • ) ;
{ выв од з н а ч е н и я переме н н о й и з а п р о с н а
п о д т в е ржд е ни е }
Unt i l ( Ch = ' У ' ) OR ( Ch = ' У ' ) ;
{ усл о в и е вых ода и з цикл а - п ол ь з о в а т е л ь
н ажал кла вишу У }
{ $R+ }
{ в ключ е ни е с и с т емы о б р а б о тки о ши б о к вых ода
з а пределы диапа з о н а }
{ $!+}
{ включение системы обработки ошибок в в ода / вывода }
Wri t eLn ( ' C п a c и б o , в в е д е н ный в о зр а с т :
iAge ) ;
End .
{ и спол ь з о в ание значения и з а в ершение про граммы }
Ch
:=
Read.Кey ;
533
Tu rbo Pascal
7.0
Ввод возраста ( целое число· о т О д о
Введите Ваш возраст:
Ваш возраст:
1 00.
-27009.
Введите Ваш возраст:
Ваш возраст:
1 5.
9999999
n рав ильно? (Y/N)
15
правильно? ( Y/N)
Спасибо. в веде нный возраст:
Рис.
1 50)
правильно? (Y/N)
Введите Ваш возраст:
Ваш возраст:
100
15
1 66. Результат ра боты
программы No/OErrorsЗ
Результат работы программ ы , в кото
рой учтены все возможные ошибки,
приведен на рис. 1 66 . Пользователь
вводил синтаксически верные числа
1 00 и 9999999, после чего отказывал
ся от в веде н н ы х з н а ч е н и й . З атем
было введено синтаксически верное
ч и сл о 1 5 , к о р р е кт н о сть кото р о го
пользователь подтвердил , и цикл ввода закончился .
Аналогичные конструкци и можно использовать и при работе с файлами ,
например, п р и их открыти и , когда может возникать ошибка из-за того ,
что файл не существует или занят другим приложением , а также при за
писи , когда может возн и кать ошибка недостаточности места на используемом носителе , и так далее .
Можно еще больше усилить внутреннюю защиту программы от некоррект
ности значений, проверяя еще и факт попадания введенного возраста в за
данный интервал (от О до 1 50) . Это следует сделать в одном месте с провер
кой синтаксической корректности введенного значения (см . листинг 259) .
·,;;�h.й.ci���J:��·� ;·{fi�i�J.�'�����:�ii���������[��1g����i!�
�ii�!�1ЖIIIII
Program No iOErrors 4 ;
Uses
CRT ;
Va r
IAge : Intege r ;
Ch : Char;
Begin
Wri t eLn ;
Writ eLn ( ' Вв о д в озраста ( целое число от О до 1 5 0 ) ' ) ;
{ $I-}
{ $R- }
Repeat
Repeat
Wri t e ( ' Вв едите в аш в озраст : ' ) ;
ReadLn ( iAge ) ;
Unt i l ( IORe sult = О ) AND ( iAge < = 1 5 0 ) AND ( iAge > = О ) ;
{ д о п ол н и т е л ь н а я про в е р к а н а п о п а д а н и е
в з а д а н ный ди а п а з о н }
Wri t eLn ( ' Ваш в озраст : ' , iAge , ' , nравильно ? ( Y/ N ) ' ) ;
Ch : = ReadКey;
Unt i l ( Ch = ' У ' ) OR ( Ch = ' У ' ) ;
{ $R+ }
{ $I+}
Wri teLn ( ' Сnасиб о , введе нный в озраст :
iAge ) ;
End .
534
Глава 1 6 . Качество п рограм мн ы х продуктов
О ш и б ки графической с исте мы
При испол ьзовани и графической систем ы Turbo Pascal , реализованной
в библиотеке Graph , могут возникать разного рода ошибки. Они не я в
ляются фатальн ы м и , т о есть не вызывают досрочного прекращения п р о
грам м ы , однако требуют собственной обработки . Результат работы п о с
ледней вызванной процедуры или функци и графической систем ы можно
получить с помощью функции GraphRe sult библиотеки Graph. Данная
функци я , так же как и функция I OResul t , не и м еет параметров и воз
вращает нулевое значение в случае успешного выпол нения предыдущей
подпрограммы графической систе м ы . Функцию GraphResult н еобхо
димо вызывать после процедуры I n i tGraph , чтобы п роверить факт ус
т а н о в к и г р а ф и ч е с к о г о р е ж и м а , а т а кж е п о с л е ф у н к ц и й
I n s t a l lUs erDriver и I n s tal lUs erFont , часто вызывающих ош ибки
из-за отсутствия файлов с графически м и драй верами и дополнительны
ми шрифтам и в доступных програм ме каталогах. Приведем пример о п
ределения корректности установки графического режима. В случае н е
возможн ости е г о установки выдадим пользователю предупреждение о б
ошибке и зако н ч и м программу. Для сравнения результата, возвращае
мого функцией GraphRe s u l t с константой О , м ожно воспользоваться
константой grOK , о п исанной в модуле Graph (см . листин г 260) .
Program
Set GraphМode ;
Uses
Graph ,
CRT ;
Va r
GraphDrive r ,
GraphМode :
Intege r ;
Begin
GraphDriver
:=
Detec t ;
Init Graph ( GraphDriver , GraphМode , 1 1 ) ;
{ n о nы т к а и н и ци али зир о в а т ь
I f GraphResult
г р а фич е с ки й
р е жим }
< > grOk Then
begin
Wri t e l n ( 1 Не в озможно
Wri t e l n ( 1 Пр ограмма
Wri t e l n ( 1 Нажмите
установить
гр афич е с кий
завершена . 1 ) ;
клавишу . 1 ) ;
режим •
•
•
1 );
будет
любую
ReadКey ;
Hal t ;
end ;
{ е сли n о с л е д н я я n о д n р о г р амма г р а фи ч е с к о й
библи о т е ки выnолн е н а с о ши б к о й ( в н а шем
случ а е э т о Ini tGraph ) , т о в ыд а е м с о о бщ е н и е
и з а к а нчи в а ем nро гр амму }
535
Turbo Pascal 7 . 0
Line ( О ,
О,
GetMaXX ,
GetмaxY ) ;
{ е сли упр а в л е н и е п е р е шл о к д а н н ому фрагменту
п р о г р а ммы , з н а ч и т г р а фи ч е с ки й р е жим у с т а н о в л е н
корре к т н о , и можн о и с п ол ь з о в а т ь д руги е
п о дп р о граммы г р а фи ч е с к о й б и бл и о т е ки }
ReadKey ;
C l o seGraph ;
End .
Аналогичным образом следует проверять возможные ошибки при инстал
ляции дополн ительных графических драйверов и шрифтов.
1 6.2.2.
Отладка .
И с п ользова н и е встроенного отладч и ка
Основы отладки прогр а м м
Процесс отладки заключается в устранении выявленных на этапе тести
рования логических и динамических ошибок. По своей сути отладка свя
зана с исследованием работы алгоритма, то есть определен и е м , каки м
именно образом выполняется программа и какие значения и меют те или
иные переменные в определенный момент времени при о пределенных
условиях. Для получения такой информации можно добавлять в программу
команд ы , вы водящие на экран всю необходимую информацию , называе
мую отладочной. Такой подход к отладке не всегда возможе н , не очень
удобен и и меет ряд совершенно определенных недостатков:
•
•
•
•
Трудоемкость. Для программы в н есколько сотен стро к п ридется
предусмотреть десятки о пераций вывода. К тому же п р и добавле
нии команд вывода отладочной информации также м ожно допус
тить о ш ибку, в результате чего отладочная информация будет не
верна.
При удалении команд, выводящих отладочную и нформац и ю , иногда
можно удал ить п олезные программные строки, в результате чего
будет испорчена уже отлаженная программа, не содержащая ошибок.
Отладочная и нформация на экране может помешать просмотру ре
зультатов , которые программа должна выводить на само м деле.
Некоторые п рограммы в зависи мости от алгоритма могут выводить
отладоч ную и нформацию с такой скоростью, что за ней невозмож
но будет следить. Хотя эта проблема решается выводом отладочной
информаци и не н а экран , а в файл , это также неудобно.
Для упрощения процесса отладки применяются специал ьные програм м ы
отладчи ки (англ . Debugger
отладч ик) , позволяющие выпол нить сле
дующие основные действия:
-
536
Глава 1 6 . Кач е ство програм мн ы х продуктов
1 . Остановить в ы п ол нение программ ы в любом , заранее указанном
месте (наз ы ваем о м точкой останова) , в ыведя п р и этом на э кран
собственное окно , содержащее текст отлажи ваемой п рограмм ы .
2. Просмотреть и п р и желании изменить значения п еременных, ис
пользуе м ых в п рограмме.
3 . В ы п ол н ить п р ограмму далее, до следующей точки останова, удали в
с экрана собственный и нтерфейс и восстановив на нем р езультаты
работы п ро грамм ы , в ыведенные ею до останова отладчи ко м .
4. В ы п ол нять п рограмму п о ш агам (за один ш а г в ы п ол н я ются коман
ды , н аходящиеся в одной программной строке) . Если в текущей
стро ке находится п одп рограмма, и меется возможность в ы п ол нить
ее цел и ком ил и зайти в нее для отладки само й п одпрограмм ы .
5 . Вместо продолжения выпол нения п рограмм ы закончить е е досроч
но. При этом п рограмм а не и м еет возможности в ы п ол н ить свою
деи н и циал и зационную часть.
И нтегрированная среда разработчика Turbo Pasca1 снабжена собственным
отладчико м , позволяющим выполнить все вышеперечисленные действия,
не покидая интегрирован ную среду. Рассмотрим правила работы со встро
енным отладчико м .
Уста новка точки оста нова
Установка точки останова возможна в любой строке программ ы , содержа
щей какую-либо команду (оператор присваи вания, вызов подпрограмм ы
и так далее) , и производится вызовом пункта главного меню интегриро
ванной среды Debug 1 Add breakpoint
или нажатием комбинации кла
виш <<Ctr1 -F8>>. О наличии точки останова в строке интегрированная среда
подсказывает изменением фона этой строки на красный (см. рис. 1 67 ) .
. . .
Рис.
1 6 7. В строке 1 8 отлаживаемой программы установлена точка останова
537
Turbo Pascal
7.0
Указанные методы установки
точки останова несколько от
личаются друг от друга. Нажа
т и е к о м б и н а ц и и кл а в и ш
«Ctrl-F8» устанавливает точку
сразу же, а выбор пункта меню
Debug 1 Add breakpoint
вы
водит на экран д и ал о го в о е
окно, показанное на рис . 1 68 .
В дан ном диалоге можно на
строить следующие параметры
точки останова:
. . .
Рис.
1 68. Диалоговое окно установки
точки останова
Condi t i on . . . . . условное выражение, по которому отладчи ко м опре
деляется , должна ли программа быть остановлена в
данной строке. Условие строится п о обычным пра
вилам Turbo Pascal и м ожет включать в себя значе
ния переменных и констант. Есл и условие не задан о ,
т о программа всегда будет останавл и ваться в данной
строке ;
Pas s c ount . . . . с колько раз должна выполниться данная строка до
того момента, как програм м а будет остановлена в
ней;
Fi l e name . . . . . . и м я файла , содержащего программу, в которой уста
навл ивается данная точка останова. Таким образо м ,
можно поставить точ ку останова не только в том
м одуле, который находится в активном окне, н о и в
како м -либо друго м ;
L i n e nwnЬe r . . . н о м е р строки , в которой необходимо установить точку останова.
После настройки свойств точки останова следует нажать на кно п ку Ok
данного диалогового окна. Если не изменять значени я , заданные в стро
ках ввода окна по умолчанию, а сразу нажать на кнопку Ok, то такое
действие будет эквивалентно нажатию комбинации клавиш <<Ctri - F8>> .
.
.
.
Для выполнения программы под управлением отладчи ка н е нужно пред
принимать каких-либо действий. Факт отладки определяется и нтегриро
ванной средой автом атически п о наличию в программе точек останова.
Достаточно запустить программу на выполнение обычным образом , и она
начнет работать до тех пор, пока не встретится точка останова, условие
Condi t i on которой будет иметь истинное значение, а количество про
ходов через данную строку будет соответствовать п араметру Pas s c oun t
точки останова. После достижения точки останова программ а п р иоста
навливается, на экран выводится окно интегрированной среды , причем
строка программ ы , которая будет выполняться п осле возобновления ра
боты, п одсвечивается зеленым фоном (см. рис. 1 69) .
538
Глава 1 6 . Качество п рограм м н ых п родуктов
Рис.
1 69. Цветовой указа тель текущей команды
Для снятия точки останова из какой -либо строки необходимо установить
текстовый курсор в эту строку и нажать комбинацию клави ш «Ctrl-F8)>
либо выбрать пункт главного меню Debug 1 Breakpoint s , в результате чего
на экран будет выведено диалоговое окно управления всеми точками
останова, использованными в программ е . Дан н ы й диалог содержит спи
сок точек останова, в котором можно выбрать какую - н ибудь одну, и
позволяет:
изменить характеристики точки останова (кноп ка Edi t ) ;
удал ить точку останова ( кнопка De lete) ;
• переместиться к точке останова (кнопка view) .
Также с п о мощью этого диалога можно удалить все точки останова, ус
тановленные в программе (кнопка Clear al l ) .
•
•
П о ш а го вое выполнение прогр а м м ы
После остановки программ ы можно возобновить ее работу до следующей
строки останова или до момента естественного завершения с помощью
выбора пункта главного меню Run 1 Run или нажатием комбинаци и кла
виш <<Ctrl-F9)> . Однако м ожно выпол нять программу по шагам двумя ме
тодами :
•
Н ажатие клавиши <<F8)> или выбор пункта меню Run 1 Step over
п р иводит к полному выполнению строки , в которой находится ука
затель текущей команды (см . рис. 1 69) , вне зависимости от того,
какие п одпрограмм ы используются в данн о й строке.
539
Turbo Pascal 7 . 0
•
Нажатие клави ш и <<F7>> или вы бор пункта меню Run 1 Trace into
приводит к п ереходу к первой строке первой подпрограмм ы , и с
п ользованн о й в строке , н а которой находится указатель текущей
команды (см. рис. 1 70 ) . После пошагавого выпол н е н ия п одпрог
рам м ы управление возвращается в строку, из которой в ызвана п од
программ а , и вызывается следующая п одпрограмм а , испол ьзован
ная в данн о й строке.
Рис.
1 70. Управление передано в процедуру
П р осмотр значений переме н н ых
Для просмотра значений переменных необходимо добавить их в так называ
емый список просматриваемых переменных (Watches). Для этого следует уста
новить текстовый курсор в любое место переменной, значение которой не
обходимо просматривать в процессе выполнения программы, и воспользоваться
комбинацией клавиш <<Ctrl-F7>> либо пунктом главного меню DeЬug i Add watch,
выводящим на экран диалог с преДIIожением ввести имя переменной, добав
ляемой в список просмотра. Добавляться могут как глобальные переменные,
так и локальные. Также имеется возможность просмотра значений логичес
ких и арифметических выражений с использованием переменных и констант.
Список просматриваемых переменных watches отображается в отдельном
окне, которое программист может разместить в любом месте экрана по сво
ему усмотрению (см. рис. 1 7 1 - в окно просмотра добавлена переменная N) .
Переменные, выведенные в окно просмотра переменных Watche s , находятся
в нем до того момента, пока не будут удалены разработчиком с помощью
клавиши <<Delete» . Значения переменных будут оперативно изменяться по
ходу выполнения программы, отображая реальные значения переменных.
540
Глава 1 6 . Качество п рограм мных продуктов
Рис. 1 7 1 . В нижней части экрана находится окно просмотра переменных Watches
Изме н е н и е значений переме н н ых
Для изменения значения переменной во время работы программы исполь
зуется комбинация клавиш Ctrl - F4 или пункт меню Debug 1 Evaluate /
Modi fy. Результатом в обоих случаях будет отображение на экране диа
лога, показанного на рис. 1 72.
В с т р о к е в в од а
Expression дан но
го диалога указыва
ется имя перемен
но й ил и любое
выражение (ариф
метическое или ло
гическое ) , которое
м о жет с о д е р ж а т ь
переменные и конРис. 1 72. Диалог изменения зна чения переменной
станты . После . набора в ы раже н и я
следует нажать на кнопку Evaluate (вычислить) , в результате чего в поле
Result появится значение данного выражения или сообщение об ошиб
ке , если выражение неверно.
Есл и поле Exp r e s s i on содержит одну пере м е н ную , то в п ол е New
value м ожно указать ее новое значе н и е , п осл е ч е го следует н ажать
на к н о п ку Modi f y ( и з м е нить) . Н овое з н ач е н и е пере м е н н о й отобра
зится в п оле Re s u l t .
541
Turbo Pascal 7 . 0
Досрочное прекращение программы
Для досрочного прекращения программы следует н ажать комбинацию
клавиш <<Ctri-F2» или воспользоваться пунктом меню Run 1 Progra.m reset .
В любом случае програм ма завершится, а указатель текущей команды
будет удален с экрана.
1 6.2.3.
Доступ к большим объем а м п а м яти .
Испол ьзован и е защи щен ного режи м а п р о цессара
В проrраммах, использующих большие объемы информации , постоянно воз
никает проблема нехватки оператИвной памяти. Работа программиста в та
ких условиях очень сложна и способствует быстрому росту его профессиона
л изма, так как заставляет постоянно заботиться об оптимизации проrраммы.
Жесткие ограничения на объемы доступной памяти (максимум 640 Кб
Неар) вытекают из схемы адресации памяти, принятой для процессоров
Intel 808 6 , в которых возможно адресовать память лишь до одного мега
байта. Однако с появлением новых процессоров появился новый режим
их работы , называемый защищенным режимом. В данном режиме исполь
зуется описанная нами адресация памяти <<два байта н а сегмент и два бай
та на смещение>> , позвQляющая адресовать память в пределах 4 гигабайт.
Таким образом , DОS-программа, разработанная для выполнения в защи
щенном режиме работы процессора, может получить практически всю сво
бодную память, физически установленную в машине.
П р и м еч а н и е .
Р ежим п ро цессора, с котор ы м м ы ра б отал и до сих п о р , наз ы в ается реаль
ным режи м о м .
Разработку программ ы для защищенного режима следует производить в
интегрированной среде разработчи ка, вызываемой не с помощью програм
мы turb o . exe, а с помощью Ьр . ехе. Данная и нтегрирован ная среда н и
чем существенно не отличается от
той , которую мы рассм атривали до
с и х п о р , одн ак о в м е с т о п у н кта
Des t i nat i on меню C omp i l e и меет
пункт Targe t (от ан гл . Target цель) , выбор которого приводит к
выводу на экран диалога, показан
ного на рис. 1 7 3 . Данное окно п о
Рис. 1 73. Диалоговое окно Target
зволяет выбрать платформу, под которую следует строить п риложение:
Real mode Appl ication . . . . . . . . . прил ожение реального режима ра
боты п роцессора.
.
542
.
.
Глава 1 6 . Качество програ м м н ы х продуктов
Protected mode Application . приложени е защищен ного режима
работы п роцессора.
Windows Appl ication . . . . . . . . . . . . . . построение прил ожения для работы
в операционной системе Windows.
.
.
.
.
В связи с тем , что из меню Compile удален пун кт De st inat ion, указы
вающи й , где должна быть создана вы полняемая программа - в памяти
или на диске , - ехе-файл всегда создается на диске .
Приведем пример програм м ы , определяющей объем доступ н о й памяти
при работе в защищенном режи ме процессора. Для этого воспользуемся
функцией MemAvai l , выдающей такую информацию (см . листин г 26 1 ) .
ri��;�,����:���:,,;': :9���:.�������::������"�,�!?� ,;���o�,���it�!�,;:i/;:��:,�;, ��;r:�����K,
. . . ·с• . . · , , .
Begin
Wr it eLn ( MemAva i l ) ;
End .
При выполнении дан ной программы в реальном режиме работы процес
сара можно п олуч ить на экране результат, не превышающий 640 Кб,
например 578576. При установке в диалоге Target пункта Protected mode
Applicat ion результат может быть знач ительно большим и составлять,
например, 1 1 953984, что является удо влетворительным объемом для по
давляющего большинства программных продуктов.
Следует заметить, что при использовании защищенного режима процес
сара возникают некоторые ограничения в работе с обыч н ы м и функция
ми. Кон кретная и нформация об ограничениях содержится в справочной
системе, где о п исание каждой подпрограм м ы имеет подраздел Target . В
этом подразделе содержится список платформ , под которые работает дан
ная подпрограмма. Например, в о п исании процедуры :InitGraph указа
но: Targe t : Rea l , P r o t ec t ed, что означает нормальную работу данной
процедуры и в реальном режи ме процессора, и в защищенном.
543