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

11.7. Стандартные процедуры опроса состояния

Для опроса состояния структуры TFILE существует ряд простых процедур. Они, например, позволяют программе определять, вернула ли процедура ввода, такая как getc, символ EOF из-за того, что достигнут конец файла или в результате возникновения ошибки. Эти процедуры описаны ниже:

Описание

uses stdio;

function ferror(_stream:pfile):integer;

function feof(_stream:pfile):integer;

procedure clearerr(_stream:pfile);

function fileno(_stream:pfile):longint;

Функция ferror является предикатом, который возвращает ненулевое значение, если в потоке _stream возникла ошибка во время последнего запроса на ввод или вывод. Ошибка может возникать в результате вызова примитивов доступа к файлам (fdread, fdwrite и др.) внутри процедуры стандартного ввода/вывода. Если же функция ferror возвращает нулевое значение, значит, ошибок не было. Функция ferror может использоваться следующим образом:

if ferror(_stream) <> 0 then

begin

(* Обработка ошибок *)

end

else

begin

(* Ошибок нет *)

end;

Функция feof является предикатом, возвращающим ненулевое значение, если для потока _stream достигнут конец файла. Возврат нулевого значения просто означает, что этого еще не произошло.

Функция clearerr используется для сброса индикаторов ошибки и флага достижения конца файла для потока _stream. При этом гарантируется, что последующие вызовы функций ferror и feof для этого файла вернут нулевое значение, если за это время не произошло что-нибудь еще. Очевидно, что функция clearerr бывает необходима редко.

Функция fileno является вспомогательной и не связана с обработкой ошибок. Она возвращает целочисленный дескриптор файла, содержащийся в структуре TFILE, на которую указывает параметр _stream. Это может быть полезно, если нужно передать какой-либо процедуре дескриптор файла, а не идентификатора потока TFILE. Однако не следует использовать процедуру fileno для смешивания вызовов буферизованного и небуферизованного ввода/вывода. Это почти неизбежно приведет к хаосу.

Следующий пример – процедура egetc использует функцию ferror, чтобы отличить ошибку от достижения конца файла при возврате процедурой getc значения ЕОF.

(* Процедура egetc - getc с проверкой ошибок *)

uses stdio;

function egetc (stream:pfile):longint;

var

c:longint;

begin

c := getc (stream);

if c = EOF then

begin

if ferror (stream) <> 0 then

begin

writeln (stderr, 'Фатальная ошибка: ошибка ввода');

halt (1);

end

else

writeln (stderr, 'Предупреждение: EOF');

end;

egetc:=c;

end;

11.8. Построчный ввод и вывод

Существует также набор простых процедур для ввода и вывода строк (под которыми понимается последовательность символов, завершаемая символом перевода строки). Эти процедуры удобно использовать в интерактивных программах, которые выполняют чтение с клавиатуры и вывод на экран терминала. Основные процедуры для ввода строк называются gets и fgets.

Описание

uses stdio;

function gets(buf:pchar):pchar;

function fgets(buf:pchar; nsize:integer; inf:pfile):pchar;

Процедура gets считывает последовательность символов из потока стандартного ввода (stdin), помещая все символы в буфер, на который указывает аргумент buf. Символы считываются до тех пор, пока не встретится символ перевода строки или конца файла. Символ перевода строки newline отбрасывается, и вместо него в буфер buf помещается нулевой символ, образуя завершенную строку. В случае возникновения ошибки или при достижении конца файла возвращается значение nil.

Процедура fgets является обобщенной версией процедуры gets. Она считывает символы из потока inf в буфер buf до тех пор, пока не будет считано nsize-1 символов или не встретится раньше символ перевода строки newline или не будет достигнут конец файла. В процедуре fgets символы перевода строки newline не отбрасываются, а помещаются в конец буфера (это позволяет вызывающей функции определить, в результате чего произошел возврат из процедуры fgets). Как и процедура gets, процедура fgets возвращает указатель на буфер buf в случае успеха и nil – в противном случае.

Процедура gets является довольно примитивной. Так как она не знает размер передаваемого буфера, то слишком длинная строка может привести к возникновению внутренней ошибки в процедуре. Чтобы избежать этого, можно использовать процедуру fgets (для стандартного ввода stdin).

Следующая процедура yesno использует процедуру fgets для получения положительного или отрицательного ответа от пользователя; она также вызывает макрос isspace для пропуска пробельных символов в строке ответа:

(* Процедура yesno - получить ответ от пользователя *)

uses stdio;

const

YES=1;

NO=0;

ANSWSZ=80;

pdefault:pchar = 'Наберите "y" (YES), или "n" (NO)';

error:pchar = 'Неопределенный ответ';

function yesno (prompt:pchar):integer;

var

buf:array [0..ANSWSZ-1] of char;

p_use, p:pchar;

begin

(* Вывести приглашение, если он не равно nil.

* Иначе использовать приглашение по умолчанию

* pdefault *)

if prompt <> nil then

p_use := prompt

else

p_use := pdefault;

(* Бесконечный цикл до получения правильного ответа. *)

while true do

begin

(* Вывести приглашение *)

printf ('%s > ', [p_use]);

if fgets (buf, ANSWSZ, stdin) = nil then

begin

yesno:=EOF;

exit;

end;

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

p := buf;

while isspace (byte(p^)) do

inc(p);

case p^ of

'Y','y':

begin

yesno:=YES;

exit;

end;

'N','n':

begin

yesno:=NO;

exit;

end;

else

printf (#$a'%s'#$a, [error]);

end;

end;

end;

var

ans:integer;

begin

ans := yesno (nil);

printf ('Получен ответ: ',[]);

if ans = YES then

printf ('Да'#$a,[])

else

printf ('Нет'#$a,[]);

end.

В этом примере предполагается, что stdin связан с терминалом. Как можно сделать эту процедуру более безопасной?

Обратными процедурами для gets и fgets будут соответственно процедуры puts и fputs.

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