Чтение онлайн

на главную - закладки

Жанры

UNIX — универсальная среда программирования
Шрифт:

Глава 6

Программирование с помощью стандартных функций ввода-вывода

До сих пор мы использовали существующие инструменты, чтобы разрабатывать новые, но сейчас уже достигнут разумный предел в создании новых средств с помощью

shell
,
sed
и
awk
. В этой главе нам предстоит написать простые программы на языке программирования Си. Основополагающая философия конструирования объектов, функционирующих совместно, будет по-прежнему оказывать влияние на построение программ, так как наша цель — подготовить инструменты, с которыми можно работать и на которые можно положиться. В каждом случае мы также попытаемся показать вам приемлемую
стратегию реализации таких инструментов: начинать с минимума, обеспечивающего некоторые полезные свойства, а затем добавлять новые средства, если в них возникает необходимость.

Существуют веские причины для того, чтобы писать новые программы "с нуля". Так, может оказаться, что проблема, с которой мы столкнулись, просто не может быть решена с помощью имеющихся программ. Часто приходится иметь дело с нетекстовыми файлами. Например, большинство программ, которые демонстрировались ранее, действительно хорошо работали лишь с текстовой информацией либо слишком трудно достигалась должная ясность или эффективность, если применялись только

shell
и другие средства общего назначения. В подобных случаях реализация с использованием
shell
может быть полезна для апробирования программы и ее интерфейса с пользователем. (Если же программа работает достаточно хорошо, нет причины для ее переделки.) Уже знакомая вам программа zap является в этом смысле неплохим примером: требуется всего несколько минут, чтобы написать первую версию на
shell
, которая имеет адекватный пользовательский интерфейс, но слишком медленна.

Мы будем писать программы на языке Си — стандартном языке системы UNIX (ядро и все пользовательские программы написаны на Си), поскольку нет иного языка, хотя бы отчасти также хорошо поддерживаемого. Вы должны знать этот язык, по крайней мере в такой степени, чтобы свободно разбираться в предлагаемом здесь материале. Если это не так, прочтите книгу "Язык программирования Си" Б. Кернигана и Д. Ритчи (М.: Финансы и статистика, 1985) [13] . Мы также воспользуемся "стандартной библиотекой ввода-вывода" — набором функций, обеспечивающих программы на Си эффективными и переносимыми средствами ввода-вывода и системными услугами. Стандартные библиотеки ввода-вывода есть во многих, отличных от UNIX, системах, поддерживающих Си, поэтому программы, взаимодействия с системой которых ограничены возможностями таких библиотек, могут быть легко перенесены.

13

Сейчас выпущено как переиздание этой книги, так и новое, третье издание на русском языке

Примеры, подобранные в настоящей главе, имеют общее свойство: они представляют собой небольшие "инструменты", которые используются регулярно, но не являются частью седьмой версии системы. Если ваша система обладает подобными программами, вам будет легче сравнивать системы. Если же вы с ними еще не знакомы, то они могут оказаться вам чрезвычайно полезными. Эти программы помогут вам понять, что совершенной системы не существует, и для того чтобы добиться улучшения и устранить те или иные дефекты, достаточно приложить лишь небольшие усилия

6.1 Стандартные входной и выходной потоки: программа

vis

Многие программы читают только из одного входного потока и пишут в один выходной поток: для таких программ полностью подходят функции ввода-вывода, использующие лишь стандартные входной и выходной потоки, и для того чтобы начать работу, этого почти всегда достаточно.

Проиллюстрируем изложенное с помощью программы

vis
, которая копирует свой стандартный входной поток в стандартный выходной, изображая при этом все непечатаемые символы в виде
\nnn
, где
nnn
восьмеричное значение символа.
Vis
полезна для обнаружения "посторонних" или нежелательных символов, которые могут попасть в файлы. Например,
vis
будет печатать каждый символ "шаг назад" как \010, что является его восьмеричным значением:

$ cat x abc

$ vis < x

abc\010\010\010 ___

$

Чтобы просмотреть несколько файлов с помощью этой элементарной версии

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 <stdio.h>

#include <ctype.h>

main {

 int c;

 while ((c = getchar) != EOF)

if (isascii(c) &&

(isprint(с) || c=='\n' || c=='\t' || c==' '))

putchar(c);

else

printf("\\%03o", c);

Поделиться:
Популярные книги

Газлайтер. Том 3

Володин Григорий
3. История Телепата
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Газлайтер. Том 3

Новик

Ланцов Михаил Алексеевич
2. Помещик
Фантастика:
альтернативная история
6.67
рейтинг книги
Новик

Иной. Том 3. Родственные связи

Amazerak
3. Иной в голове
Фантастика:
боевая фантастика
рпг
аниме
5.00
рейтинг книги
Иной. Том 3. Родственные связи

Последний Паладин. Том 2

Саваровский Роман
2. Путь Паладина
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Последний Паладин. Том 2

Бастард Императора. Том 14

Орлов Андрей Юрьевич
14. Бастард Императора
Фантастика:
городское фэнтези
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Бастард Императора. Том 14

Двойник Короля

Скабер Артемий
1. Двойник Короля
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Двойник Короля

Камень. Книга 3

Минин Станислав
3. Камень
Фантастика:
фэнтези
боевая фантастика
8.58
рейтинг книги
Камень. Книга 3

Зауряд-врач

Дроздов Анатолий Федорович
1. Зауряд-врач
Фантастика:
альтернативная история
8.64
рейтинг книги
Зауряд-врач

Геном хищника. Книга пятая

Гарцевич Евгений Александрович
5. Я - Легенда!
Фантастика:
рпг
фэнтези
попаданцы
6.00
рейтинг книги
Геном хищника. Книга пятая

Кодекс Крови. Книга II

Борзых М.
2. РОС: Кодекс Крови
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Крови. Книга II

Изыскатель

Назимов Константин Геннадьевич
5. Травник
Фантастика:
фэнтези
7.00
рейтинг книги
Изыскатель

Главный рубильник. Расцвет и гибель информационных империй от радио до интернета

Ву Тим
Деловая литература:
о бизнесе популярно
5.00
рейтинг книги
Главный рубильник. Расцвет и гибель информационных империй от радио до интернета

Адепт

Листратов Валерий
4. Ушедший Род
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Адепт

Я все еще барон

Дрейк Сириус
4. Дорогой барон!
Фантастика:
боевая фантастика
5.00
рейтинг книги
Я все еще барон