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

Описание

uses stdio;

(* Считать символ из __stream *)

function getc(__stream:pfile):integer;

(* Поместить символ в __stream *)

function putc(__c:integer;__stream:pfile):integer;

Можно поместить обе процедуры в цикл для копирования одного файла в другой:

var

с:integer;

istream, ostream:PFILE;

(* Открыть файл istream для чтения и файл ostream для записи *)

.

.

.

с := getc (istream);

while c<>-1 do

begin

putc (с, ostream);

с := getc (istream);

end;

Значение -1 возвращается функцией getc при достижении конца файла, поэтому тип возвращаемого функцией getc значения определен как integer.

На первый взгляд, функции getc и putc могут вызывать определенное беспокойство, поскольку они работают с одиночными символами, а это, как уже было продемонстрировано на примере системных вызовов, чрезвычайно неэффективно. Процедуры стандартного ввода/вывода избегают этой неэффективности при помощи изящного механизма буферизации, который работает следующим образом: первый вызов функции getc приводит к чтению из файла BUFSIZ символов при помощи системного вызова fdread. Данные находятся в буфере, созданном библиотекой и находящемся в пользовательском адресном пространстве. Функция getc возвращает только первый символ. Все остальные внутренние действия скрыты от вызывающей программы. Последующие вызовы функции getc поочередно возвращают символы из буфера. После того как при помощи функции getc программе будут переданы BUFSIZ символов и будет выполнен очередной вызов getc, из файла снова будет считан буфер целиком. Аналогичный механизм реализован в функции putc.

Такой подход весьма удобен, так как он освобождает программиста от беспокойства по поводу эффективности работы программы. Это также означает, что данные записываются большими блоками, и запись в файл будет производиться с задержкой (для терминалов сделаны специальные оговорки). Поэтому весьма неблагоразумно использовать для одного и того же файла и стандартные процедуры ввода/вывода, и системные вызовы, такие как fdread, fdwrite или fdseek. Это может привести к хаосу, если не представлять четко, что при этом происходит. С другой стороны, вполне допустимо смешивать системные вызовы и процедуры стандартного ввода/вывода для разных файлов.

Кроме механизма буферизации стандартный ввод/вывод предоставляет утилиты для форматирования и преобразования, например, функция printf обеспечивает форматированный вывод:

printf('Целое число %d'#10, [ival]);

Кстати, функция printf неявно осуществляет запись в стандартный вывод.

Вывод сообщений об ошибках при помощи функции writeln

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

uses stdio; (* Для определения stderr *)

.

.

writeln (stderr, 'Ошибка номер ', linuxerror);

Отличие между использованием writeln и вызовом printf заключается в параметре stderr, являющемся указателем на текстовый файл, автоматически связанный с потоком вывода стандартной диагностики.

Следующая процедура расширяет возможности использования функции writeln в более общей процедуре вывода сообщения об ошибке:

(* Функция notfound - вывести сообщение об ошибке и выйти *)

uses linux;

function notfound(progname, filename: string):integer;

begin

writeln(stderr, progname, ': файл ', filename, ' не найден');

halt(1);

end;

В последующих примерах для вывода сообщений об ошибках будет использована функция writeln, а не printf. Это обеспечит совместимость с большинством команд и программ, применяющих для диагностики стандартный вывод диагностики.

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