Средства отладки
Основная процедура программы strings вызывает функцию strings для каждого файла – аргумента:
Вы, наверное, удивлены, что strings не читает стандартный ввод, если не было дано ни одного имени файла. Сначала именно так и было. Для того чтобы объяснить, почему теперь это изменилось, требуется рассказать историю об отладке.
Очевидный тест программы strings – пропустить ее через саму себя. Это сработало отлично под Unix, но под Windows 95 команда:
С:\> strings <strings.exe
Выдала ровно пять строк:
IThis program cannot be run in DOS mode. ' .rdata @.data .idata .reloc
Первая строка "Эта программа не может исполняться под DOS" выглядела как сообщение об ошибке, и мы потеряли некоторое время, пока не поняли, что это на самом деле строка из файла с программой, так что результат был правилен, по крайней мере до какого-то момента. Не секрет, что некоторые отладочные сессии терпели крушение из-за неверного понимания источника сообщения.
Но в любом случае должны быть еще строки! Где они? Однажды поздно ночью наконец забрезжил свет. ("Я где-то уже видел это!") Это – проблема с переносимостью, описанная подробнее в восьмой главе. Изначально мы написали программу так, чтобы она читала только из стандартного ввода, используя функцию getchar. Под Windows, однако, getchar возвращает EOF, когда она встречает определенный байт (0x1 А или Control-Z) в текстовом режиме ввода,4 и именно это и приводило к преждевременному завершению.
Это абсолютно законное поведение, но совсем не то, что ожидали мы, с нашим опытом работы с Unix. Было решено открывать файл в двоичном режиме, используя "rb". Но stdin уже открыт, а стандартного способа изменить режим его работы не существует. (Можно использовать функции fdopen или setmode, но они не являются частью стандарта.) Таким образом, мы столкнулись с набором неприятных альтернатив: заставить пользователя всегда задавать имя файла, чтобы программа работала под Windows за счет неудобства для пользователей Unix; без пред упреждения выдавать неправильный ответ, если пользователь Windows пытается задействовать стандартный ввод; использовать условную компиляцию, чтобы адаптировать поведение к различным системам ценой пониженной переносимости. Мы выбрали первый вариант, чтобы программа везде работала одинаково.
Упражнение 5.2
Программа strings печатает строки длиной MINLEN или более символов, и иногда при этом обнаруживается гораздо больше строк, чем надо. Реализуйте необязательный аргумент, устанавливающий минимальную длину строки.
Упражнение 5.3
Напишите программу vis, которая копирует стандартный ввод на стандартный вывод, отображая непечатаемые символы типа "забоя", контрольных символов и не-АЗСП-символов в виде \Хhh, где hh – шестнадцатеричное представление непечатаемого байта. В отличие от strings программа vis полезна при обработке файлов, содержащих лишь несколько непечатаемых символов.
Упражнение 5.4
Что выдает vis, если во входном потоке попадается строка \ХОА? Можете ли вы устранить двусмысленность результатов работы этой программы?
Упражнение 5.5
Расширьте функциональность программы vis, чтобы она могла обрабатывать набор файлов, разбивать слишком длинные строки на части и полностью удалять непечатаемые символы. Какие еще возможности, хорошо совместимые с назначением этой программы, можно реализовать?