
- •Часть I. Работа в среде
- •Глава 1. Интегрированная среда
- •1.1. Окно просмотра результатов Output
- •1.2. Окно просмотра переменных Watch
- •1.3. Структура меню
- •1.3.1. Пункт File (работа с файлами)
- •1.3.2. Пункт Edit (работа с редактором)
- •1.3.3. Пункт Run (запуск на выполнение)
- •1.3.4. Пункт Compile (компиляция)
- •1.3.5. Пункт Options (установка параметров системы)
- •1.3.6. Пункт Debug (установки отладчика)
- •1.3.7. Пункт Break/Watch (точки останова/обзор)
- •1.4. Интерактивная справка
- •Глава 2. Настройка системы
- •2.1. Система настройки среды программирования
- •2.2. Принятые в системе расширения имен файлов
- •Часть II. Язык турбо паскаль
- •Глава 3. Построение программ
- •3.1. Алфавит языка и зарезервированные слова
- •3.2. Общая структура программ
- •3.3. Комментарии и ключи компиляции
- •3.4. Условная компиляция программ
- •Глава 4. Введение в систему типов языка
- •4.1. Простые типы языка
- •4.1.1. Целочисленные типы
- •4.1.2. Вещественные числа
- •4.1.3. Логический тип
- •4.1.4. Символьный тип
- •4.1.5. Строковый тип
- •4.1.6. Адресный тип
- •4.1.7. Перечислимые типы
- •4.1.8. Ограниченные типы (диапазоны)
- •4.2. Сложные типы языка
- •Глава 5. Константы и переменные
- •5.1. Простые константы
- •5.2. Переменные
- •5.2.1. Совмещение адресов директивой absolute
- •5.2.2. Переменные со стартовым значением или типизированные константы
- •5.3. Операция присваивания и совместимость типов и значений
- •5.4.Изменение (приведение) типов и значений
- •Глава 6. Управляющие структуры языка
- •6.1. Простой и составной операторы
- •6.2. Условный оператор (if...Then...Else)
- •If Условие then Оператор1 else Оператор2;
- •6.3. Оператор варианта (case)
- •6.4. Оператор цикла с предусловием (while)
- •6.6. Оператор цикла с параметром (for...Do)
- •6.7. Оператор безусловного перехода Goto
- •6.8. Операторы Exit и Halt
- •6.9. Процедуры и функции
- •6.9.1. Параметры. Глобальные и локальные описания
- •6.9.2. Опережающее описание процедур и функций
- •6.9.3. Объявление внешних процедур
- •6.9.4. Процедуры и функции как параметры
- •6.9.5. Переменные-процедуры и функции
- •6.9.6. Специальные приемы программирования
- •6.10. Модули. Структура модулей
- •6.11. Особенности работы с модулями
- •6.12. Система библиотечных модулей языка
- •Часть III. Средства языка турбо паскаль
- •Глава 7. Массивы, записи и множества в деталях
- •7.1. Массивы (Array) и работа с ними
- •7.2. Тип «запись» (Record) и оператор присоединения With
- •7.3. Тип «множество» (Set). Операции с множествами
- •Глава 8. Обработка символов и строк
- •8.1. Символьный и строковый типы (Char и String)
- •8.2. Операции над символами
- •8.3. Операции над строками
- •8.3.1. Редактирование строк
- •8.3.2. Преобразование строк
- •8.3.2.1. Процедура Str( X [: Width [: dec ] ]; var s : String)
- •Глава 9. Математические возможности Турбо Паскаля
- •9.1. Базовые операции
- •9.2. Битовая арифметика
- •9.3. Логические вычисления и операции отношения
- •9.4. Математические процедуры и функции
- •9.4.1. Обсуждение математических функций языка
- •9.4.2. Генераторы случайных чисел
- •9.4.3. Оптимизация сложения и вычитания
- •9.5. Использование математического сопроцессора 80x87
- •Глава 10. Код программы, данные, адреса
- •10.2. Распределение памяти при выполнении программ
- •10.3. Анализ расположения кода и областей данных программы
- •10.5. Средства для работы с адресами
- •10.5.1. Определение адреса переменных
- •10.5.2. Создание адреса функцией Ptr
- •10.5.3. Определение размеров типов и переменных
- •Глава 11. Ссылки, динамические переменные и структуры
- •11.1. Ссылочные переменные
- •11.2. Операция разыменования
- •11.3. Организация памяти области кучи
- •11.4. Управление размерами области кучи и стека
- •11.5. Процедуры управления кучей
- •11.5.1. Размещение динамических переменных.
- •11.5.2. Освобождение динамических переменных.
- •11.5.3. Управление состоянием кучи.
- •11.5.4. Анализ состояния кучи.
- •11.5.5. Более детальный анализ состояния кучи
- •11.5.6. Обработка ошибок распределения памяти
- •11.6. Ссылки, работающие не с кучей
- •11.7. Как организовать структуры, большие чем 64к?
- •11.8. Практический пример построения стека
- •Глава 12. Ввод-вывод данных и файловая система
- •12.1. Понятие логического файла
- •12.2. Физические файлы в ms-dos
- •12.3. Понятие буфера ввода-вывода
- •12.4. Файловые типы Турбо Паскаля
- •12.5. Общие процедуры для работы с файлами
- •12.5.1. Связывание файлов
- •12.5.2. Открытие файлов
- •12.5.3. Закрытие файлов
- •12.5.4. Переименование файлов
- •12.5.5. Удаление файлов
- •12.5.6. Анализ состояния файлов
- •12.6. Текстовые файлы
- •12.6.1. Текст-ориентированные процедуры и функции
- •12.6.2. Операции ввода-вывода в текстовые файлы
- •123 1.23 [Клавиша ввода]
- •123 [Клавиша ввода] 1.23 [Клавиша ввода]
- •12.7. Типизированные файлы и операции ввода-вывода
- •12.8. Бестиповые файлы и операции ввода-вывода
- •12.9. Последовательный и прямой доступ к файлам
- •12.9.1. Опрос размеров файлов и позиции в них
- •12.9.2. Позиционирование в файлах
- •12.9.3. Усечение файлов
- •12.10. Процедуры для работы с каталогами
- •12.11. Обработка ошибок ввода-вывода
- •12.11.1. Функция ioResult
- •12.11.2. Примеры обработки ошибок ввода-вывода
- •12.11.3. Сводка номеров ошибок ввода-вывода
- •Глава 13. Объектно-ориентированное программирование
- •13.1. Определения объектов
- •13.2. Область действия полей объекта и параметр Self
- •13.3. Наследование
- •13.4. Присваивание объектов
- •13.5. Полиморфизм
- •13.5.1. Статические методы
- •13.5.2. Виртуальные методы
- •13.5.3. Выбор вида метода
- •13.6. Динамические объекты
- •13.6.1. Создание динамических объектов
- •13.6.2. Освобождение объектов. Деструкторы
- •13.6.3. Обработка ошибок при работе с динамическими объектами
- •13.7. Функции TypeOf и SizeOf
- •13.8. Задание стартовых значений объектам
- •13.9. Модули, экспортирующие объекты
- •Глава 14. Специальные средства языка
- •14.1. Работа с командной строкой. Функции ParamCount и ParamStr
- •14.2. Доступ к памяти пэвм. Массивы Mem, MemW, MemL
- •14.3. Доступ к портам ввода-вывода. Массивы Port и PortW
- •14.4. Процедура заполнения FillChar
- •14.5. Процедура перемещения данных Move
- •14.6. Функции обработки машинных слов Lo, Hi и Swap
- •14.7. Вставки машинного кода в программе
- •14.7.1. Оператор inline
- •14.7.2. Процедуры с директивой inline
- •14.8. Процедура завершения и обработка ошибок программ
- •14.8.1. Оператор RunError
- •14.8.2. Сводка номеров фатальных ошибок
- •Часть IV. Специальные библиотеки языка
- •Глава 15. Модуль crt
- •15.1. Вывод специальных символов
- •15.2. Модификация операторов Read, ReadLn
- •15.3. Системные переменные модуля crt
- •15.3.1. Переменные управления выводом на дисплей
- •15.3.2. Переменные управления работой клавиатуры
- •15.3.3. Переменная TextAttr
- •15.4. Процедуры и функции модуля crt
- •15.4.1. Работа с экраном в целом
- •15.4.2. Позиционирование курсора
- •15.4.3. Работа со строками
- •15.4.4. Настройка цвета
- •15.4.5. Подача звуковых сигналов
- •15.4.6. Использование встроенного таймера
- •15.4.7. Опрос клавиатуры
- •If KeyPressed then Действие ;
- •15.4.8. Переназначение стандартных файлов
- •Глава 16. Модуль dos
- •16.1. Опрос и установка параметров ms-dos
- •16.1.1. Управление параметрами break и verify 16.1.1.1.
- •16.1.2. Опрос системных переменных ms-dos
- •16.2. Работа с часами и календарем
- •16.2.1. Опрос и назначение даты
- •16.2.3. Работа с датой создания файлов
- •16.3. Анализ ресурсов дисков
- •16.4. Работа с каталогами и файлами
- •16.4.1. Типы и константы модуля dos для работы с файлами
- •16.4.2. Переменная DosError
- •16.4.3. Процедуры поиска файлов на диске
- •16.4.4. Работа с атрибутами файлов
- •16.4.5. Анализ имен файлов
- •16.5. Работа с прерываниями ms-dos
- •16.5.1. Чтение и перестановка адресов подпрограмм прерываний
- •16.5.2. Вызов прерывания процедурой Intr
- •16.5.3. Процедура MsDos
- •6.6. Организация субпроцессов и резидентных программ
- •16.6.1. Программирование субпроцессов
- •Глава 17. Модуль Printer
- •7.1. Содержимое модуля Printer
- •17.2. Низкоуровневые средства работы с принтером
- •17.3. Работа с двумя принтерами одновременно
- •Глава 18. Модуль Overlay
- •18.1. Оверлейное построение программ
- •18.2. Правила оформления оверлейных программ
- •18.3. Инициализация работы оверлеев
- •18.3.1. Включение администратора оверлеев
- •18.3.2. Анализ результата инициализации
- •18.3.3. Размещение оверлейного файла в ems-памяти
- •18.4. Управление оверлейным буфером
- •18.4.1. Опрос размера буфера
- •18.4.2. Установка размера буфера
- •18.4.3. Принудительная очистка буфера
- •18.5. Оптимизация работы оверлеев
- •18.5.1. Установка размера области испытаний
- •18.5.2. Подсчет вызовов оверлеев
- •18.6. Предопределенные переменные для работы с оверлеями
- •18.7. Включение оверлеев в ехе-файлы
- •Глава 19. Модуль Graph
- •19.1. Файлы bgi и содержимое модуля Graph
- •19.2. Управление графическими режимами
- •19.2.1. Инициализация и закрытие графического режима
- •19.2.2. Обработка ошибок инициализации
- •19.2.3. Классификация и анализ графических режимов
- •19.2.4. Очистка экрана и переключение режимов
- •19.2.5. Управление режимом вывода отрезков на экран
- •19.3. Системы координат и «текущий указатель»
- •19.3.1. Координаты устройства и мировые координаты
- •19.3.2. Управление «текущим указателем»
- •19.4. Рисование графических примитивов и фигур
- •19.4.1. Линии и их стили
- •1100110011001100 — Всего 16 разрядов.
- •19.4.2. Коэффициент сжатия изображения
- •19.4.3. Окружности, эллипсы и дуги
- •19.4.4. Построение прямоугольников и ломаных
- •19.5. Управление цветами и шаблонами заливки (заполнения)
- •19.5.1. Немного о цветах
- •19.5.2. Задание типа заливки
- •19.5.3. Заливка областей изображения
- •19.5.4. Опрос и установка цветов пера и фона
- •19.5.5. Управление палитрой
- •19.6. Битовые графические операции
- •19.6.1. Битовые операции
- •19.6.2. Работа с фрагментами изображений
- •19.7. Управление видеостраницами
- •19.8. Графические окна
- •19.9. Вывод текста
- •19.9.1. Выбор шрифта и стиля
- •19.9.2. Предварительная загрузка и регистрация шрифтов
- •19.9.3. Непосредственный вывод строк
- •19.9.4. Размер букв и его масштабирование
- •19.9.5. Опрос стиля и ориентации шрифтов
- •19.10. Включение шрифтов и драйверов в ехе-файл
- •19.11. Подключение новых драйверов
- •19.12. Один полезный совет
- •Часть V. Практические
- •Глава 20. Профессиональная работа с
- •20.1. Программный опрос режимов текстового дисплея
- •20.2. Организация доступа к видеопамяти
- •20.3. Запоминание окон экрана и их восстановление
- •20.3.1. Общие принципы работы с окном
- •20.3.2. Модуль Win
- •20.4. Работа с образом экрана на диске
- •20.5. Крупные надписи на экране
- •20.6. Управление формой курсора
- •Глава 21. Как осуществить полный доступ к клавиатуре
- •21.1. Как организовать опрос алфавитно-цифровой клавиатуры
- •21.2. Опрос клавиши в регистре Ctrl
- •21.3. Опрос расширенных кодов и функциональных клавиш
- •21.4. Опрос служебных клавиш
- •21.5. Анализ клавиш регистров и их состояния
- •21.6. Скэн-коды клавиатуры и работа с ними
- •21.7. Эффект обратной записи в буфер ввода
- •Глава 22. Работа с оперативной
- •22.1. Многобитовое и многоплоскостное озув
- •22.2. Карта дисплейной памяти
- •22.3. Вывод текста на графический экран
- •22.4. Работа с графическими образами на диске
- •Приложение 2 Ключи и директивы компилятора
- •Ключи режимов компиляции
- •Директивы с параметрами
- •Приложение 3
- •Файл tpc.Cfg
- •Приложение 4 Список утилит пакета Турбо Паскаль (версия 5.5)
- •Программа администрирования библиотек
- •Утилита поиска текстов grep
- •Утилита преобразования двоичных файлов binobj
- •Приложение 5
- •Основные команды перемещения курсора
- •Расширенный набор команд перемещения курсора
- •Команды вставки и удаления
- •Команды работы с блоками
- •Поиск и замена
- •Прочие команды
- •Приложение 6
- •If False then Оператор;
- •Приложение 7
- •Глава 6. Управляющие структуры языка
- •Глава 8. Обработка символов и строк
- •Глава 9. Математические возможности Турбо Паскаля
- •Глава 16. Модуль dos
- •Глава 17. Модуль Printer
- •Глава 18. Модуль Overlay
- •Глава 19. Модуль Graph
- •Глава 20. Профессиональная работа с текстовыми изображениями
- •Глава 21. Как осуществить полный доступ к клавиатуре
- •Глава 22. Работа с оперативной памятью видеоадаптеров
- •Литература
- •Оглавление
- •Часть I. Работа в среде программирования
- •Часть II. Язык турбо паскаль
- •Часть III. Средства языка турбо паскаль
- •Часть IV. Специальные библиотеки языка
- •Часть V. Практические приемы работы с пэвм
7.2. Тип «запись» (Record) и оператор присоединения With
Для компактного представления комбинаций разнотипных данных их можно объединять в структуры-записи. Каждая запись состоит из объявленного числа полей. Тип «запись» определяется конструкцией
RECORD
Поле1 : ТипПоля1;
Поле2 : ТипПоля2;
...
ПолеN : ТипПоляN
END;
Если тип нескольких полей совпадает, то имена полей могут быть просто перечислены, например:
TYPE
PointRecType = RECORD x,y : Integer END;
После объявления в программе переменной типа «запись»
VAR
Point : PointRecType;
к каждому ее полю можно обратиться, указав сначала идентификатор переменной-записи, а затем через точку — имя поля: Point.x и Point.y — значения полей записи (но просто Point — уже комбинация двух значений). {136}
Независимо от количества объявленных переменных данного типа, поля каждой из них будут называться одинаково, как они названы в описании типа. Поскольку имена полей «скрыты» внутри типа, они могут дублировать «внешние» переменные и поля в других описаниях записей, например:
TYPE
PointRecType = RECORD X,Y : Integer END;
ColorPointRecType = RECORD X,Y : Integer; Color:Word END;
VAR
X, Y : Integer;
Point : PointRecType;
ColorPoint : ColorPointRecType;
В программе X, PointX и ColorPoint.X — совершенно разные значения. Поле записи может иметь практически любой тип (массив, другая запись, множество). Доступ к вложенным элементам таких структур осуществляется по тем же правилам, что и обычно:
Переменная_СложнаяЗапись.ЕеПоле_Запись.ПолеПоляЗаписи
или
Переменная_С_полем_массивом.ПолеМассив[i]
Порядок описания полей в определении записи задает их порядок хранения в памяти. Так, значения полей переменной ColorPoint хранятся как шесть последовательных байтов:
2 ( это X, тип Integer) + 2 ( Y, тип Integer) + 2 (для Color типа Word).
Запись может иметь вариантную часть. Это означает, что можно задать в пределах одного типа несколько различных структур. Непосредственный выбор структуры будет определяться контекстом или каким-либо сигнальным значением. Вариантные поля указываются после того, как перечислены поля фиксированные. Вариантные поля и оформляются особым образом. Рассмотрим пример описания типа VRecType — записи с вариантами.
TYPE
VRecType = RECORD { тип записи с вариантами }
Number : Byte; { номер измерения длины }
case Measure : Char of { признак единицы длины }
'д','Д' (inches : Word); {длина в дюймах}
'с','С' (cantimeters : LongInt); { длина в см }
'?' (Comment1, Comment2 : String[16]) { тексты }
END; {137}
В данном случае в записи имеется обычное фиксированное поле Number. Другое фиксированное поле — Measure. Оно всегда присутствует в структуре записи, но параллельно с этим выполняет роль селектора (иногда его называют полем тега от английского «Tag Field»). Поле-селектор обрамляется словами CASE и OF, и за ним следует перечисление вариантов третьего поля, взятых в круглые скобки. Какой именно вариант поля будет принят при работе с записью, обозначается содержимым селектора (Measure в приведенном примере). Значения селектора, указывающие на тот или иной вариант, записываются перед соответствующими вариантами (аналогично тому, как это происходит в операторе выбора CASE). Пусть объявлена переменная VRec типа VRecType. В зависимости от содержимого поля-селектора Measure будут корректно работать поля записи, показанные в табл. 7.1.
Таблица 7.1
Measure = |
‘д’ или ‘Д’ |
‘с’ или ‘С’ |
‘?’ |
прочие |
Поля Vrec, к которым обращение будет корректным. |
Number Measure inches
|
Number Measure cantimeters
|
Number Measure Comment1 Comment2 |
Number Measure
|
Важно понимать, что в любое время доступны поля только одного из всех возможных вариантов, описанных в типе (или ни одно из них). Все варианты располагаются в одном и том же месте памяти при хранении, а размер этого места определяется самым объемным из вариантов. Так, запись типа VRecType будет храниться как 36 байт (1 байт — Number, 1 байт — Measure и 2*(16+1) байт на самый длинный вариант — с типом поля String[16]) независимо от выбора варианта.
Следствием такого способа хранения вариантов является опасность наложения значений при неправильных действиях с записями:
VAR
VRec : VRecType;
BEGIN
VRec.Measure := 'Д'; { выбираем дюймы }
VRec.Inches := 32; { запишем 32 дюйма }
{ Теперь, не изменяя значения поля Comment1, опросим его: } WriteLn(VRec.Comment1);
END. {138}
Результатом будет печать значения числа 32 в формате String. Подобные ошибки никак не диагностируются, и вся ответственность ложится на программиста. Хуже того, поле-селектор — не более чем указание, какое поле соответствует его значению. Можно, игнорируя поле-селектора, обращаться к любому из полей-вариантов. Но поскольку значение для всех вариантов одно, оно будет трактоваться по-разному согласно типу каждого поля.
Несмотря на подобные неприятности, использование записей с вариантами и полем-селектором иногда очень удобно (если, конечно, не ошибаться). Например, если есть набор изделий с параметрами в различных системах измерения, то его можно представить в программе как массив записей с типом, подобным VRecType. Корректно заполнив поле каждой записи в массиве, мы можем потом легко опрашивать их: сначала значение поля селектора, а затем в зависимости от его значения один из вариантов хранения длины или комментария, например для массива AVRec из 100 записей типа VRecType:
for i:=1 to 100 do
case AVRec[i].Measure of
'д','Д' :WriteLn('Длина в дюймах ', AVRec[i].inches);
'с','С' :WriteLn('Длина в см ', AVRec[i].cantimeters);
'?' :WriteLn('Нет данных из-за', AVRec[i].Comment1);
end; {case}
Если не нужен явный указатель на использование определенного варианта, можно обойтись без поля селектора, заменив его именем любого перечислимого типа. Нужно лишь, чтобы этот тип имел элементов не меньше, чем будет вариантов. Запись VRec может быть описана иным способом:
TYPE
VRecType = RECORD { тип записи с вариантами }
Number : Byte; { номер измерения длины )
case Byte of { признак единицы длины }
: (inches : Word); { длина в дюймах}
: (cantimeters : LongInt); { длина в см }
: (Comment1, Comment2 : String[16]) { тексты }
END;
Поля-варианты по-прежнему разделяют общую область памяти, а имя поля, записанное в программе, определяет, в каком типе будут считаны данные, т.е., как и в предыдущем случае, можно считать значение, записанное ранее в другом формате. И это никак не будет продиагностировано. Значения констант перед вариантами в задании {139} типа — чистая условность. Они могут быть любыми, но только не повторяющимися. Обычно для двух вариантов в CASE вписывают тип Boolean (значения True и False), для большего числа вариантов — любой целочисленный тип.
При отказе от поля-селектора теряется возможность определить во время работы программы, какой вариант должен быть принят в текущий момент.
Обычно записи с вариантами, но без поля-селектора используются для обеспечения разнотипного представления одних и тех же данных. Например;
TYPE
CharArrayType = Array [1..4] of Char;
VAR
V4 : RECORD
case Boolean of
True : ( С : CharArrayType );
False : ( B1, B2, B3, B4 : Byte );
END;
Размер переменной V4 — четыре байта (оба варианта равны). Обращение к V4.C — это обращение к массиву из четырех символов к V4.C[1] — к первому элементу этого массива. Но одновременно можно обратиться и к ASCII-кодам элементов V4.C[1], V4.C[2], .... V4.C[4], используя поля V4.B1, V4.B2 V4.B4.
Переменная типа «запись» может участвовать только в операциях присваивания. Но поле записи может принимать участие во всех операциях, применимых к типу этого поля. Для облегчения работы с полями записей в языке вводится оператор присоединения. Его синтаксис таков:
WITH ИмяПеременной_Записи DO Оператор;
Внутри оператора (он может быть и составным) обращение к полям записи уже производится без указания идентификатора самой переменной:
VAR
DemoRec : RECORD X,Y : Integer END;
...
WITH DemoRec DO
BEGIN
X:=0; Y:=120
END; {with}
Внутри области действия оператора WITH могут указываться и {140} переменные, не имеющие отношения к записи. Но в этом случае надо следить, чтобы они не совпадали по написанию с полями записи (рис. 7.1).
PROGRAM MAIN; VAR X, Y : Integer; RecXY : RECORD X,Y: Integer END; BEGIN X:=10; Y:=20; { значения переменных X и Y } WITH RecXY DO BEGIN { работаем с записью RecXY } X := 3.14*X; { Где какой X и Y ? } Y := 3.14*Y END; {with} ... END. |
Рис. 7.1
На рис. 7.1 действия внутри оператора WITH проводятся только над полями записи RecXY. Чтобы сохранить оператор WITH и «развязать» имена X и Y, надо к переменным X и Y приписать так называемый квалификатор — имя программы или модуля (UNIT), в которой они объявлены (для этого программа должна иметь заголовок). Так, оператор присоединения с рис. 7.1 можно исправить следующим образом:
WITH RecXY DO
BEGIN
X := 3.14*Main.X;
Y := 3.14*Main.Y
END;
и проблема исчезнет.
В случае, если одно из полей записи само является записью (и снова содержит поля-записи), можно распространить оператор присоединения на несколько полей вглубь, перечислив их через запятую. Но в этом случае внутри тела оператора можно обращаться только к последним полям:
WITH ИмяЗаписи, Поле_3апись Do
BEGIN
Обращения к именам полей Поля_3аписи,
т.е. к тем, которым предшествовала конструкция
"ИмяЗаписи.Поле_3апись."
END; {with} {141}
Так как записи естественным образом отражают табличную форму хранения данных, они очень удобны для различных приложений — от бухгалтерских задач до системного программирования.