$
Чтобы просмотреть несколько файлов с помощью этой элементарной версии vis
cat для сбора файлов$ cat файл1 файл2 ... | vis
...
$ cat файл1 файл2 ... | vis | grep '\\'
...
и избежать тем самым выяснения способа доступа к файлам из программы.
Между прочим, может показаться, что подобную работу следует выполнить с привлечением sed
'1' выдает на экран непечатаемые символы в наглядном виде:$ sed -n 1 x
abc←←←___
$
Результат выполнения программы sed
vis. Но применение sed к нетекстовым файлам бессмысленно:$ sed -n 1 /usr/you/bin
$
(Так получилось на PDP-11; в одной из систем для VAX sed
sed нам не подходит, и мы вынуждены писать новую программу.Простейшие функции ввода и вывода getchar
putchar. При каждом вызове getchar появляется очередной символ из стандартного входного потока, которому может быть поставлен в соответствие файл, конвейер или терминал (последнее принимается по умолчанию). Программа "не знает", что конкретно он собой представляет. Аналогично putchar(c) помещает символ в стандартный выходной поток, который по умолчанию также связан с терминалом.Функция printf(3)
printf и putchar могут следовать в любом порядке; выходной поток отразит порядок этих вызовов. Для форматного преобразования входного потока предусмотрена функция scanf(3); она читает входной поток и разбивает его, как требуется, на строки, числа и т.п. Вызовы scanf и getchar также могут чередоваться.Приведем первую версию vis
/* vis: make funny characters visible (version 1) */
#include
#include
main() {
int c;
while ((c = getchar()) != EOF)
if (isascii(c) &&
(isprint(с) || c=='\n' || c=='\t' || c==' '))
putchar(c);
else
printf("\\%03o", c);
exit(0);
}
Getchar
int (целая), а; не как char (символьная), так что она может хранить значение EOF. Строка#include
должна находиться в начале каждого исходного файла. Это заставляет компилятор Си читать
/usr/include/stdio.h), в котором специфицированы стандартные функции и имена, в том числе и EOF. Мы будем использовать как краткую запись полного имени файла.Файл
/usr/include, который задает машинно-независимые макрокоманды (макросы) для классификации символов. Чтобы выяснить, принадлежит ли входной символ набору ASCII (т.е. его значение меньше 0200) и печатается ли он, мы использовали здесь isascii и isprint. Остальные макросы перечислены в табл. 6.1. Отметим, что определяет символы "перевод строки", "табуляция" и пробел как непечатаемые.isalpha(c) | Буква принадлежит алфавиту: a-z A-Z |
isupper(c) | Прописная буква: A-Z |
islower(с) | Строчная буква: a-z |
isdigit(c) | Цифра: 0-9 |
isxdigit(c) | Шестнадцатеричная цифра: 0-9 a-f A-F |
isalnum(c) | Буква или цифра |
isspace(c) | Пробел, символ табуляции, символ перевода строки, символ вертикальной табуляции, символ перевода страницы, символ возврата |
ispunct(c) | Не буквенно-цифровой символ, не управляющий, не пробел |
isprint(c) | Печатаемый: любой графический символ |
iscntrl(c) | Управляющий символ: 0 <= с < 040 || с == 0177 |
isascii(c) | Символ ASCII: 0 <= с <= 0177 |
Таблица 6.1: Макросы классификации символов