Скачиваний:
56
Добавлен:
08.01.2014
Размер:
2.6 Mб
Скачать

11.5. Возврат символов в поток: процедура ungetc Описание

uses stdio;

function ungetc(c:integer; _stream:pfile):integer;

Процедура ungetc возвращает символ с в поток _stream. Это всего лишь логическая операция. Входной файл не будет при этом изменяться. В случае успешного завершения процедуры ungetc символ с будет следующим символом, который будет считан процедурой getc. Гарантируется возврат только одного символа. В случае неудачной попытки вернуть символ с процедура ungetc возвращает значение EOF. Попытка вернуть сам символ EOF должна всегда завершаться неудачей. Но это обычно не представляет проблемы, так как все последующие вызовы процедуры getc после достижения конца файла приведут к возврату символа EOF.

Обычно процедура ungetc используется для восстановления исходного состояния входного потока после чтения лишнего символа для проверки условия. Следующая процедура getword применяет это простой подход для ввода строки, которая содержит либо непрерывную последовательность алфавитно-цифровых символов, либо одиночный нетекстовый символ. Конец файла кодируется возвращенным значением nil. Процедура getword принимает в качестве аргумента указатель на структуру TFILE. Она использует для проверки два макроса, определенные в файле stdio. Первый из них, isspace, определяет, является ли символ пробельным символом, таким как символ пробела, табуляции или перевода строки. Второй, isalnum, проверяет, является ли символ алфавитно-цифровым, то есть цифрой или буквой.

(* В этом файле определены isspace и isalnum *)

uses stdio;

const

MAXTOK=256;

var

inbuf:array [0..MAXTOK] of char;

function getword (inf:pfile):pchar;

var

c,count:integer;

begin

count:=0;

(* Удалить пробельные символы *)

repeat

c := getc (inf);

until not isspace (c);

if c = EOF then

begin

getword:=nil;

exit;

end;

if not isalnum (c) then (* символ не является алфавитно-цифровым *)

begin

inbuf[count] := char(c);

inc(count);

end

else

begin

(* Сборка "слова" *)

repeat

if count < MAXTOK then

begin

inbuf[count] := char(c);

inc(count);

end;

c := getc (inf);

until not isalnum (c);

ungetc (c, inf); (* вернуть символ *)

end;

inbuf[count] := #0;

(* нулевой символ в конце строки *)

getword:=inbuf;

end;

var

word:pchar;

begin

while true do

begin

word := getword (stdin);

if word <> nil then

puts (word)

else

break;

end;

end.

Если подать на вход программы следующий ввод

Это данные

на входе

программы!!!

то процедура getword вернет следующую последовательность строк:

Это

данные

на

входе

программы

!

!

!

Упражнение 11.3. Измените процедуру getword так, чтобы она распознавала также числа, которые могут начинаться со знака минус или плюс и могут содержать десятичную точку.

11.6. Стандартный ввод, стандартный вывод и стандартный вывод диагностики

Стандартная библиотека ввода/вывода обеспечивает две структуры TFILE, связанные со стандартным вводом и стандартным выводом, и переменная типа TEXT, связанная со стандартным выводом диагностики. (Еще раз напомним, что не следует путать эти потоки с одноименными дескрипторами ввода/вывода 0, 1 и 2.) Эти стандартные структуры не требуют открытия и задаются предопределенными указателями:

stdin Соответствует стандартному вводу

stdout Соответствует стандартному выводу

stderr Соответствует стандартному выводу диагностики

Следующий вызов получает очередной символ из структуры stdin, которая так же, как и дескриптор файла со значением 0, по умолчанию соответствует клавиатуре:

inchar := getc (stdin);

Так как ввод и вывод через потоки stdin и stdout используются очень часто, для удобства определены еще две процедуры – getchar и putchar. Процедура getchar возвращает очередной символ из stdin, а процедура putchar выводит символ в stdout. Они аналогичны процедурам getc и putc, но не имеют аргументов.

Следующая программа io2 использует процедуры getchar и putchar для копирования стандартного ввода в стандартный вывод:

(* Программа io2 - копирует stdin в stdout *)

uses stdio;

var

c:integer;

begin

c := getchar;

while c <> EOF do

begin

putchar (c);

c := getchar;

end;

end.

Программа io2 ведет себя почти аналогично приведенному ранее примеру – программе io из главы 2.

Так же, как getc и putc, getchar и putchar могут быть макросами. Фактически getchar часто просто определяется как getс(stdin), a putchar – как putc(stdout).

stderr обычно предназначена для вывода сообщений об ошибках, поэтому вывод в stderr обычно не буферизуется. Другими словами, символ, который посылается в stderr, будет немедленно записан в файл или устройство, соединенное со стандартным выводом диагностики. При включении отладочной печати в код для тестирования рекомендуется выполнять вывод в stderr. Вывод в stdout буферизуется и может появиться через несколько шагов после того, как он в действительности произойдет. (Вместо этого можно использовать процедуру fflush(stdout) после каждого вывода для записи всех сообщений из буфера stdout.)1

Упражнение 11.4. При помощи стандартной команды time сравните производительность программы io2 и программы io, разработанной в главе 2. Измените исходную версию программы io так, чтобы она использовала вызовы fdread и fdwrite для посимвольного ввода и вывода. Снова сравните производительность полученной программы и программы io2.

Упражнение 11.5. Перепишите программу io2 так, чтобы она более соответствовала команде cat. В частности, сделайте так, чтобы она выводила на экран содержимое файлов, заданных в качестве аргументов командной строки. При отсутствии аргументов она должна принимать ввод из stdin.

Соседние файлы в папке Полищук, Семериков. Системное программирование в UNIX средствами Free Pascal