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

2.1.11. Пример: гостиница

В качестве несколько надуманного, но возможно наглядного примера, предположим, что имеется файл residents, в котором записаны фамилии постояльцев гостиницы. Первая строка содержит фамилию жильца комнаты 1, вторая – жильца комнаты 2 и т.д. (очевидно, это гостиница с прекрасно организованной системой нумерации комнат). Длина каждой строки составляет ровно 41 символ, в первые 40 из которых записана фамилия жильца, а 41-й символ является символом перевода строки для того, чтобы файл можно было вывести на дисплей при помощи команды UNIX cat.

Следующая функция getoccupier вычисляет по заданному целому номеру комнаты положение первого байта фамилии жильца, затем перемещается в эту позицию и считывает данные. Она возвращает либо указатель на строку с фамилией жильца, либо нулевой указатель в случае ошибки (мы будем использовать для этого значение nil). Обратите внимание, что мы присвоили переменной дескриптора файла infile исходное значение –1. Благодаря этому мы можем гарантировать, что файл будет открыт всего один раз.

(* Функция getoccupier - получить фамилию из файла residents *)

uses linux;

const

NAMELENGTH=41;

var

namebuf:array [0..NAMELENGTH-1] of char; (* Буфер для фамилии *)

const

infile:integer=-1; (* Для хранения дескриптора файла *)

function getoccupier(roomno:integer):pchar;

var

offset, nread:longint;

begin

(* Убедиться, что файл открывается впервые *)

if infile = -1 then

begin

infile := fdopen ('residents', Open_RDWR);

if infile = -1 then

begin

getoccupier := nil; (* Невозможно открыть файл *)

exit;

end;

end;

offset := (roomno - 1) * NAMELENGTH;

(* Найти поле комнаты и считать фамилию жильца *)

if fdseek (infile, offset, SEEK_SET) = -1 then

begin

getoccupier := nil;

exit;

end;

nread := fdread (infile, namebuf, NAMELENGTH);

if nread <= 0 then

begin

getoccupier := nil;

exit;

end;

(* Создать строку, заменив символ перевода строки на '\0' *)

namebuf[nread - 1] := #0;

getoccupier := namebuf;

end;

Если предположить, что в гостинице 10 комнат, то следующая программа будет последовательно вызывать функцию getoccupier для просмотра файла и выводить каждую найденную фамилию при помощи процедуры writeln из стандартного модуля system:

(* Программа listoc выводит все фамилии жильцов *)

const

NROOMS=10;

var

j:integer;

p:pchar;

begin

for j := 1 to NROOMS do

begin

p := getoccupier (j);

if p<>nil then

writeln('Комната ', j:2, ', ', p)

else

writeln('Ошибка для комнаты ', j);

end;

end.

Упражнение 2.9. Придумайте алгоритм для определения пустых комнат. Измените функцию getoccupier и файл данных, если это необходимо, так, чтобы он отражал эти изменения. Затем напишите процедуру с названием findfree для поиска свободной комнаты с наименьшим номером.

Упражнение 2.10. Напишите процедуру freeroom для удаления записи о жильце. Затем напишите процедуру addguest для внесения новой записи о жильце, с предварительной проверкой того, что выделяемая комната свободна.

Упражнение 2.11. Объедините процедуры getoccupier, freeroom, addguest и findfree в простой программе с названием frontdesk, которая управляет файлом данных. Используйте аргументы командной строки или напишите интерактивную программу, которая вызывает функции writeln и readln. В обоих случаях для вычисления номера комнаты вам потребуется преобразовывать строки в целые числа. Вы можете использовать для этого библиотечную процедуру StrToInt:

i := StrToInt(str);

где string – указатель на строку символов, а i – целое число.

Упражнение 2.12. В качестве обобщенного примера напишите программу на основе системного вызова fdseek, которая копирует в обратном порядке байты из одного файла в другой. Насколько эффективным получилось ваше решение?

Упражнение 2.13. Используя вызов fdseek, напишите процедуры для копирования последних 10 символов, последних 10 слов и последних 10 строк из одного файла в другой.

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