Директивы компилятораВыручают директивы, – особые сочетания символов, избирательно настраивающие компилятор. Директивы не являются элементами языка, поэтому вставляются в программу по-хитрому – внутри комментариев. Ведь комментарии, как известно, компилятор должен игнорировать, пропускать мимо ушей. Но компилятор просматривает и комментарии, «процеживая» их в поисках директив (подобно тому, как мы «процеживали» строки в поиске заменяемых символов).
Большинство директив выглядит как сочетание символа доллара «$» с латинской буквой и последующего знака «+» или «–». Все это заключается внутрь комментария. Знак «+» включает действие директивы, а «–» – отключает, что равносильно установке или сбросу флажков на вкладке опций компилятора. Например, директива, управляющая реакцией на ошибки ввода-вывода, записывается так:
{ $I+ - включить контроль ввода-вывода }
{ $I- - отключить контроль ввода-вывода }
В один комментарий можно вместить несколько директив. Перечень директив вы найдете в справке по компилятору и в приложении Ж.
Директиву – в студию!Сейчас мы извлечем первую пользу из директив: сотворим функцию, определяющую наличие файла на диске. Применим для этого директиву $I. Наша булева функция будет возвращать TRUE, если файл, имя которого передано в параметре, существует. Вот её текст, а заодно и фрагмент тестирующей программы.
{ P_27_1 – определение наличия заданного файла }
function FileExists(const aName: string): boolean;
var F: text;
begin
FileExists:= false; { предполагаем, что файла нет }
Assign(F, aName);
{$I-} Reset(F); {$I+} { контроль отключен на время Reset }
if IOResult=0 then begin { если файл существует }
Close(F); { закрываем файл }
FileExists:= true;
end;
end;
begin {--- главная программа ---}
Writeln( FileExists('AUTO.BAT') ); { печатает false }
Writeln( FileExists('C:\AUTOEXEC.BAT') ); { печатает true }
end.
В выделеной строке процедура открытия файла Reset заключена между парой директив. Первая из них отключает контроль ошибок ввода-вывода, а вторая снова включает его. Это значит, что при выполнении процедуры Reset программа не прервется даже при отсутствии открываемого файла. Причем это уже не будет зависеть от состояния флажка в опциях компилятора, поскольку директивы имеют преимущество перед флажками, то есть более высокий приоритет.
Как сработает наша функция? После попытки открыть файл вызовем функцию IOResult. Если она вернула ноль, значит, файл существует, и его надо закрыть, поскольку никаких действий с ним внутри функции FileExists не намечается. Проверьте работу этой полезной функции, она ещё пригодится вам!
Парад директивРазбогатев со временем собственными программами, вам, вероятно, захочется поделиться ими. При передаче исходных текстов важно передать и настройки опций компилятора, иначе EXE–файл может быть построен неправильно. Эти настройки лучше передать путём вставки директив компилятора прямо в программу. Но директив много, – запомнить их трудно, а ошибиться легко. Впрочем, есть один волшебный способ…
Откройте опции компилятора (рис. 61) и настройте в нём флажки так, как нужно, не забыв сохранить их кнопкой ОК. Затем откройте файл с программой и нажмите волшебную комбинацию клавиш Ctrl+O+O. То есть, удерживая клавишу CTRL, дважды нажмите латинскую букву «O». И – о, чудо! – в начале программы появятся строчки с настройками всех директив, например, такие.
{$IFDEF NORMAL}
{$H-,I+,OBJECTCHECKS-,Q-,R-,S-}
{$ENDIF NORMAL}
{$IFDEF DEBUG}
{$H-,I+,OBJECTCHECKS-,Q+,R+,S-}
{$ENDIF DEBUG}
{$IFDEF RELEASE}
{$H-,I-,OBJECTCHECKS-,Q-,R-,S-}
{$ENDIF RELEASE}
Здесь представлены настройки директив для трех вариантов компиляции. Эти варианты (Normal/Debug/Release) выбираются в пункте меню Options –> Mode…. Знаки «+» и «–» соответствуют состоянию флажков в окне опций. Директивы вида $IFDEF нужны для выбора одного из вариантов компиляции (об условных директивах я расскажу в главе 60). Можно упростить эту конструкцию, оставив, лишь одну строку.
{$H–, I+, OBJECTCHECKS–, Q–, R–, S–}
Потребовалось изменить настройки? Пожалуйста! – Удалите эти строчки и повторите «волшебные заклинания». Или расставьте плюсы и минусы вручную.
Итоги• Программист допускает два рода ошибок: синтаксические и семантические (смысловые).
• Синтаксические ошибки обнаруживает компилятор. Пока вы не исправите все такие ошибки, исполняемый файл не сформируется.
• Смысловые ошибки проявляются в ходе выполнения программы, – это ошибки времени исполнения. Такие ошибки кроются либо в алгоритме программы, либо в неправильных действиях пользователя.
• Реакция программы на некоторые ошибки определяется настройкой опций компилятора. Программа может либо пренебречь ошибкой, либо аварийно завершиться.
• Опции компилятора настраивают двумя способами: в диалоговом окне и вставкой директив непосредственно в программу.
• Директивы в тексте программы имеют преимущество (приоритет) перед настройками опций в диалоговом окне.
А слабо?А) Выясните код ошибки, возвращаемый функцией IOResult при попытке открыть для чтения несуществующий файл. Напишите для этого небольшую программу.
Б) Сделайте то же самое, когда программа пытается открыть для записи файл с установленным атрибутом «только чтение». Для настройки атрибутов файла щелкните по файлу правой кнопкой мыши и выберите пункт «Свойства».
В) Дан файл, строки которого содержат круглые скобки (это может быть программа или математические выкладки – неважно). Ваша программа должна распечатать строки, где скобки расставлены неверно, вот примеры.
2+3 – правильно, хотя скобок нет;
(2+3 – ошибка – здесь нет закрывающей скобки;
()2+3() – это правильно (хоть и лишено смысла);
))2+3(( – ошибка – скобки закрываются до открытия.
Рекомендация: для исследования строки напишите булеву функцию Check, возвращающую TRUE, если скобки расставлены без ошибок.
Г) Дребезг контактов давно уже бесит специалистов по электронике. Дребезг возникает кратковременно при замыкании-размыкании кнопок, тумблеров, реле и других подобных устройств. Сигнал от контактов поступает в микропроцессор с периодичностью, скажем, 100 раз в секунду. Если контакт постоянно разомкнут, микропроцессор принимает «0», а если замкнут – «1». При замыкании-размыкании контакт неустойчив, и процессор получает пачки чередующихся нулей и единиц, – надо отфильтровать эти ложные срабатывания.
Ваша программа будет моделировать поведение микропроцессора. Входной файл содержит последовательность нулей и единиц (по одному символу в строке). Первый символ примите как исходное значение сигнала, а дальше сигнал на выходе программы формируется так: если три подряд идущие значения совпадают, то берется это новое значение, а иначе сохраняется текущее, например:
На входе На выходе 0 1 0 1 1 1 0 0 0 0 0 0 1 1
В выходной файл запишите в две колонки входной и выходной сигналы.
Глава 28Редактор и справочная система
Ошибки, ошибки… Мы отбиваемся от них всеми средствами, и компилятор, как вы убедились, – важный рубеж в этой обороне. Важный, но не единственный. Согласитесь, лучше не допускать ошибок, чем устранять их. Хорошо, когда рядом есть мудрый советчик, – вовремя подскажет, объяснит, остережет. К счастью, в IDE есть такие «советчики» – это редактор текста и справочная система, – о них спою в этой главе.
Сегодня никого не удивишь возможностями нынешних IDE: тут и встроенный редактор и справочная система. Но так было не всегда. В начале 90-х годов прошлого века появление замечательных продуктов фирмы Borland было сродни чуду. Подумать только! Куча окон, «умная» раскраска текста, встроенная справочная система и отладчик, – это ли не чудеса?
Небьющиеся окнаВстроенный многооконный редактор – одно из новшеств Borland Pascal, он появился там едва ли не раньше самой MS Windows. Пока мы обходились одним окном редактора, но так будет не всегда, – в сложных проектах приходится одновременно открывать несколько файлов. Впрочем, это нужно уметь и сейчас, например, для копирования частей одной программы в другую.
Окна встроенного редактора схожи с окнами Windows: они открываются и закрываются, меняют размер и положение, допускают перенос кусков текста из одного окна в другое. Для управления окнами IDE служит раздел меню «Window». На рис. 62 рядом с названиями пунктов этого раздела показаны соответствующие им горячие комбинации клавиш.