- •Часть 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. Практические приемы работы с пэвм
12.6.2. Операции ввода-вывода в текстовые файлы
Ввод и вывод числовой и текстовой информации в Турбо Паскале осуществляется операторами:
ввод – Read( f, X ) или Read( f, X1,X2,...,Xn ) и
ReadLn( f, X ) или ReadLn( f, X1,X2,…,Xn );
вывод – Write( f, X ) или Write( f, X1,X2,…Xn ) и
WriteLn( f, X ) или WriteLn( f, X1, X2,…,Xn ).
Если в операторе ввода-вывода первым параметром стоит логическое имя файла, то это означает, что поток данных будет приниматься (Read) или направляться (Write) на конкретное физическое устройство компьютера, связанное в данный момент с логическим именем этого файла.
Если операторы содержат один лишь список ввода-вывода, то считается, что ввод сопряжен со стандартным логическим файлом Input (под ним подразумевается клавиатура с «эхом» ввода на экране), а вывод — с логическим файлом Output (что соответствует выводу на экран дисплея).
Имена Input и Output являются предопределенными в системной библиотеке (модуле System). Напомним, что в стандартном Паскале любая программа, использующая ввод-вывод, должна начинаться со слов
PROGRAM имя( Input, Output);
что, по сути, открывает каналы ввода-вывода. В Турбо Паскале можно смело опускать описание PROGRAM и не надо описывать имена Input и Output.
Таким образом, оператор Read( x1, x2) полностью эквивалентен оператору Read( Input, x1, x2 ), а оператор Write( х3, х4) — оператору Write( Output, х3, х4 ).
12.6.2.1. Операторы Read/ReadLn. Рассмотрим сначала операторы ввода информации — Read и ReadLn. Их аргументами должен быть список переменных, значения которых будут считаны (введены). Тип переменных при вводе из текстового файла (в том числе и {238} с клавиатуры) может быть только целым, вещественным, символьным (Char), строковым или совместимым с ними. Сложные структурированные типы (такие, как массивы, множества, записи и др.) могут быть введены только по элементам (по полям для записей). Например:
VAR
i : Word
l : Longint;
r : Real;
Rec RECORD { запись }
x, у : Real
ch : Char
END;
Dim : Array [0...99] of Byte; { массив }
S : String;
BEGIN
{ . . . ЧИТАЮТСЯ С КЛАВИАТУРЫ: . . . }
Read( i, l); { два целых числа,}
Read( l, r, s); { целое, вещественное число и строка,}
Read( Rec.x, Rec.у, Rec.ch ); { запись по полям,}
for i:=0 to 99 do Read( Dim[i] ); { ввод массива }
END.
Всякие попытки вставить «сокращения» типа Read (Rec) или Read (Dim) вызовут понятное возмущение компилятора. Такое возможно лишь при вводе из типизированного файла (см. разд. 12.7).
При вводе из текстового файла, будь то файл на диске или клавиатура, необходимо помнить правила чтения значений переменных. Когда вводятся числовые значения, два числа считаются разделенными, если между ними есть хотя бы один пробел, или символ(ы) табуляции (#9), или символ(ы) конца строки (#13). Так, при выполнении оператора Read( i, r ) можно ввести значения с клавиатуры несколькими способами:
123 1.23 [Клавиша ввода]
или
123 [Клавиша ввода] 1.23 [Клавиша ввода]
При вводе с клавиатуры последней всегда должна нажиматься клавиша ввода, ибо именно она заставляет программу принять введенные перед этим буквы и цифры. При чтении из других текстовых файлов символ конца строки (код клавиши ввода), вообще говоря, ничем не лучше пробела или табуляции. {239}
Если читается символьное значение, то в соответствующую переменную запишется очередной символ за последним введенным до этого. Здесь уже нет никаких разделителей:
VAR
ch1, ch2 : Char;
...
Read( ch1, ch2 );
В этом случае надо не спешить нажать клавишу ввода на клавиатуре:
аб[ВВОД] --> ch1 = 'а', ch2 = 'б'
а[ВВОД]б[ВВОД] --> ch1 = 'а', ch2 = #13
[ВВОД][ВВОД] --> ch1 = #13, ch2 = #13
И, наконец, ввод строк. Начало строки идет сразу за последним введенным до этого символом (с первой позиции, если соответствующая строчная переменная стоит первой в списке ввода). Считывается количество символов, равное объявленной длине строки. Но если во время считывания попался символ #13, то чтение строки прекращается. Сам символ #13 (конец строки) служит разделителем строк и в переменную никогда не считывается.
Рассмотрим пример комплексного списка ввода:
Read( realVar, intVar, Ch, String11, String88).
При вводе последовательность символов будет разбита на разнотипные части следующим образом ([#13] обозначает один символ
┌───────игнорируется─────────────┐
┌┴┐ ┌─┴┐
-1.234E-5 +12930 abcdefghijk FGTH[#13]…
└──−─−┘ └────┘┬└───−──┘ └─────────┘
realVar intVar | String11 String88
Ch
с кодом 13):
Обратите внимание, что символьная переменная Ch здесь может заполучить себе только пробел (или #13 и #9), иначе, если следом сразу начнется строка, произойдет сбой при чтении целого значения! Строка StringSS будет заполнена не целиком, а на ту часть, которая успела считаться до символа #13 (нажатия клавиши ввода или конца строки в файле).
Понятно, что лучшим способом избежать заложенных во вводе текстовой информации подвохов будет отказ от смешанных списков ввода, по крайней мере при чтении с клавиатуры. {240}
Спецификация формата ввода чисел как таковая отсутствует, и единственное требование состоит в том, чтобы написание числовых значений соответствовало типам переменных в списке ввода.
При вводе с клавиатуры («с экрана») особой разницы между Read и ReadLn нет. Процедура ReadLn (Read Line) считывает значения в текущей строке и переводит позицию на начало следующей строки, даже если в текущей строке остались непрочитанные данные. Так, при чтении в текстовом файле f строки:
12.3 13.4 14.5 15.6
оператором ReadLn( f, r1, r2) вещественные переменные r1 и r2 получат значения 12.3 и 13.4, после чего произойдет переход на другую строку, и следующие два числа (14.5 и 15.6) будут проигнорированы. Вызов ReadLn ( f ) вообще пропустит строку в файле f. Вызов ReadLn без указания файла сделает паузу до нажатия клавиши ввода.
Символ-признак конца текста #26 также является разделителем и ограничивает строку, но за ним чтение уже невозможно. Файл на нем кончается! Конец файла может быть считан в символьную переменную, в строчную он не войдет (как не входит символ #13), а чтение #26 вместо ожидаемых числовых значений эквивалентно прочтению 0.
12.6.2.2. Операторы Write/WriteLn. Операторы Write и WriteLn выводят значение X или список значений X1, Х2,..., Хn в текстовый файл f. Если файл не указан, то считается, что вывод направлен в файл Output (на дисплей). Значения, как и при вводе, могут иметь лишь целые, вещественные, символьные и строковые типы, а также производные от них. Всевозможные структуры (записи, массивы) должны выводится по их полям или элементам. Множества, указатели (Pointer), файловые переменные также не могут быть выведены без предварительного их преобразования в выводимые составляющие. Исключение составляет лишь тип Boolean:
CONST
tr : Boolean = True;
fa : Boolean = False;
...
Write( tr, ' ... ' , fa );
Оператор Write напечатает на экране: 'TRUE ... FALSE'. Предостерегаем от попыток прочитать эти значения из файла в том же виде. Из этого ничего не выйдет. Чтобы получить из файла логическое значение, закодируйте его байтом:
0 = False
1 = True {241}
и считайте в байтовую переменную, а затем преобразуйте в логическое значение:
VAR
by : Byte; { байтовое значение }
boo : Boolean absolute by; { логическое значение }
...
Read( by ); { вводится значение-байт 0 или 1 }
if boo then ... ; {и считается логическим значением }
Вернемся, однако, к выводу данных. Процедура Write выводит данные в текущую строку и не закрывает ее, т.е. следующие данные запишутся в ту же строку. Формально во внешнем файле размер строки не ограничен. Исключение составляет вывод на дисплей. Если выводимый текст «уперся» в правую границу окна экрана, то он на этом месте разрывается и продолжается с начала следующей строки. Кроме того, вывод символа в нижний правый угол окна автоматически сдвинет изображение вверх на строку, т.е. все-таки совершит переход на следующую строку.
Процедура WriteLn (Write Line) выводит именно строку данных и закрывает ее: приписывает символ #13 в ее конец (точнее, символы #13 и #10, но последний как бы «сливается» с основным кодом). Это автоматически открывает следующую строку, а на экране возвращает курсор в крайнюю левую позицию и опускает его на строку вниз.
Оператор WriteLn или WriteLn( f ), где f — имя логического файла, данный без списка вывода, создает пустую строку, содержащую один только признак конца.
Список вывода Write и WriteLn может содержать константы, переменные, выражения, вызовы функций — лишь бы они имели соответствующие типы и были разделены запятыми:
Write( RealVar, ' номер ', intVar, #10#10'сумма=' );
WriteLn( RealVar+IntVar, '+', Cos(5*5) );
Все, что стоит в кавычках или является строковыми (символьными) константами и переменными, выведется в том виде, в каком подставлено, и лишнего места не займет. Но числовые значения будут выводится по-разному. Целые — как пробел или знак '-', а затем число, вещественные — как пробел или знак и затем экспоненциальная запись числа. Имеется возможность управлять форматом вывода данных.
12.6.2.3. Форматы вывода данных. При выводе значений в текстовые файлы или на экран можно указывать формат, т.е. отводить поле для размещения этих значений. Для строчных и символьных значений формат задается одним числом, отделенным от значения двоеточием: {242}
Write( Ch : 2, St : 20 );
Это число показывает, сколько позиций отводится под значение. Так, значение Ch (символ) будет размещено в двух позициях, хотя реально займет лишь одну, а строка St — в 20 позициях. Если реальное значение «короче» формата, излишек будет заполнен пробелами. Но если наоборот (формат «мал»), то значение будет выводиться, игнорируя спецификацию. Ошибки при этом не возникает. Выравнивание значения в поле формата здесь происходит по правому краю. На этом можно сыграть следующим образом. Часто надо выводить значения с середины строки. При выводе на экран можно использовать специальную процедуру из модуля CRT для установки курсора, но при выводе в файл на диске это работать не будет. А как передвинуть значение? Решение очевидно:
Write( ' ', ChapterNameStr );
Но так же очевидно, что это неэффективно (в программе будет попусту «болтаться» столько пробелов!). Разумное решение таково:
Write( ' ' : 25, ChapterNameStr );
Один пробел, но в поле из 25 символов. Эффект будет тот же. Можно даже выкинуть пробел и поставить пустую строку ".
Логические значения False и True выводятся как строковые константы и могут быть помещены в заданном поле.
Формат целочисленных значений задается почти так же, как и для строковых — размером поля за значением:
Write( intVar:5, 123:4, (6*8):10 );
Целое число, включая знак минус, если нужен, будет размещено в заданном числе позиций и выровнено по правому краю. Излишки заполнятся пробелами, а если формата не хватит, то он проигнорируется. Формат удобно использовать для вывода таблиц. Пусть надо красиво вывести 10 столбцов целых значений в 80 колонок экрана. Для этого можно задать формат
WriteLn( х1:7, х2:7, х3:7,...х10:7 );
Сложнее формат для вещественных значений. Для записи числа в дробной форме используется удвоенное описание формата: сначала, как обычно, указывается общий размер поля под значение, а затем, снова через двоеточие, число знаков после запятой:
Write( RealVar : 12 : 3, 123.456 : 8 : 1 ); {243}
Реальная длина числа равна сумме одной позиции под знак, числа знаков до десятичной точки, одной позиции под точку и значения второго параметра формата. Поэтому бессмысленны форматы типа ':4:3'. В примере переменная RealVar на экране будет иметь три знака после точки, и если полная ее длина не превысит двенадцать позиций, то она будет выровнена по правому краю. Оставшееся место будет пусто. При некорректном задании формата игнорируется только первый его параметр, а число знаков после точки устанавливается всегда корректно, но не превышает точности типа.
В том же примере второе значение будет выведено как 123.5, потому что при форматировании дробная часть округляется до заданного числа знаков. Само значение переменной при этом, конечно, не изменяется.
Можно выводить вещественные числа без дробной части. Для этого следует задать второй параметр равным 0:
Write( 123.456 : 6 : 0 ); { ' 123' }
При необходимости вывода вещественных значений в экспоненциальном формате надо задавать вновь только одно поле. Это поле указывает число позиций, в которых надо разместить число. Само число будет иметь вид -5.5678Е+00 или 0.0012Е-20. При задании подобного формата надо учесть место под знак числа, одну цифру до точки, саму точку, хотя бы одну цифру после точки, и четыре знака под степень — всего восемь позиций.
При формате, меньшем чем восемь позиций, он устанавливается автоматически равным восьми:
Write( 123.456 : 8, ' ', 123.456 : 6 ); { одно и то же }
Увеличивая формат, мы тем самым увеличиваем число значащих цифр после запятой. Максимальное их число определяется типом вещественного числа, и дальнейшее увеличение формата эффекта не даст.
Ряд проблем вызывает использование сопроцессора. В этом случае все вещественные типы при выводе в экспоненциальном формате показывают степень в виде Е+0000, т.е. минимальный формат становится равным ':10', и чтобы сохранить равное число знаков в самом числе при разных режимах работы с сопроцессором, надо менять форматы. Этот момент подробно рассмотрен при описании строковой процедуры Str (разд. 8.3.2.1).
Подобные проблемы переменных форматов, вообще говоря, решаются легко. В Турбо Паскале разрешено задавать форматы целочисленными переменными или константами: {244}
VAR
F, n : ShortInt;
BEGIN
F:=8; n:=3;
WriteLn( 123.456 : F : n );
END.
До сих пор мы рассматриваем форматы, размещающие и форматирующие одновременно. Но когда длина значения заранее неизвестна, размещение-выравнивание по правому краю может дать некрасивые форматы:
Короткое число в формате 10 = 12
Длинное число в формате 10 = 12345678
Можно задать выравнивание по левому краю. В этом случае значение форматируется (если оно числовое) и пишется без предшествующих пробелов: сразу с текущей позиции. При этом занимается поле, равное длине значения. Никаких пробелов справа уже не дописывается:
Короткое число в формате -10 = 12
Длинное число в формате -10 = 12345678
Для задания такого режима надо ближнюю к значению спецификацию формата задавать отрицательной:
Write( 123.456 : 6 : 1, 22 : 4 ); { ' 123.5' и ' 22' }
Write( 123.456 :-6 : 1, 22 :-4 ); { '123.5' и '22' }
Несмотря на некоторое отсутствие гибкости в способе задания формата (нельзя задавать форматы-шаблоны — как в Фортране, Бейсике, а надо описывать каждое значение), механизм форматированного вывода текстовой информации Турбо Паскаля достаточно мощный. Помните только, что форматы имеют смысл лишь при работе с текстовыми файлами. Во всех остальных случаях они неприменимы.
