6.2.
6.2.4. Обработка произвольного файла термов
Типичная последовательность целей для обработки файла F от начала до конца будет выглядеть примерно так:
... , see( F), обработкафайла, sеe( user), ...
Здесь обработкафайла
— процедура, которая читает и обрабатывает последовательно каждый терм файла F один за другим до тех пор, пока не встретится конец файла. Приведем типичную схему для процедуры обработкафайла
:
обработкафайла :-
read( Терм),
обработка( Терм).
обработка( end_of_file) :- !.
% Все сделано
обработка( Терм) :-
обраб( Терм),
% Обработать текущий элемент
обработкафайла.
% Обработать оставшуюся часть файла
Здесь обраб( Терм)
представляет процедуру обработки отдельного терма. В качестве примера такой обработки рассмотрим процедуру, которая выдает на терминал каждый терм вместе с его порядковым номером. Назовем эту процедуру показфайла
. У нее должен быть дополнительный аргумент для подсчета прочитанных термов:
показфайла( N) :-
read( Терм),
показ( Терм, N).
показ( Терм, N) :- !
write( N), tab( 2), write( Терм),
N1 is N + 1,
показфайла( N1).
Вот другой пример программы обработки файлов, построенной по подобной схеме. Пусть есть файл с именем файл1
, термы которого имеют форму
изделие( НомерИзд, Описание, Цена, ИмяПоставщика)
Каждый терм описывает одну строку каталога изделий. Нужно построить новый файл. содержащий только те изделия, которые выпускаются каким-то конкретным поставщиком. Поскольку поставщик в этом новом файле у всех изделий будет одинаков, его имя нужно записать только один раз в самом начале и убрать из всех остальных термов. Процедура будет называться
создатьфайл( Поставщик)
Например, если исходный каталог хранится в файле файл1
, а мы хотим создать специальный каталог в файле файл2
, содержащий всю информацию о том, что поставляет Гаррисон, тогда мы применим процедуру создатьфайл
следующим образом:
?- seе( файл1), tеll( файл2), создатьфайл( гаррисон),
see( user), tell( user).
Процедуру создатьфайл
можно определить так:
создатьфайл( Поставщик) :-
write( Поставщик), write( '.'), nl,
создатьостальное( Поставщик).
создатьостальное( Поставщик) :-
read( Изделие),
обработать( Изделие, Поставщик).
обработать( end_ot_file) :- !.
обработать( Изделие( Ном, Опис, Цена, Поставщик),
Поставщик) :- !,
write( Изделие( Ном, Опис, Цена) ),
write( '.'), nl,
создатьостальное( Поставщик).
обработать ( _, Поставщик) :-
создатьостальное( Поставщик).
Обратите внимание на то, что обработать
вписывает точки между термами, чтобы впоследствии файл мог быть прочитан процедурой read
.
6.1. Пусть f
— файл термов. Определите процедуру
найтитерм( Терм)
которая выводит на терминал новый терм из f
, сопоставимый с Терм
'ом.
6.2. Пусть f
— файл термов. Напишите процедуру
найтивсетермы( Терм)
которая выводит на экран все термы из f
, сопоставимые с Tepм
'ом. Обеспечьте при этом, чтобы во время поиска Терм
не конкретизировался (это могло бы помешать ему сопоставиться с другими термами дальше по файлу).
6.3. Обработка символов
Символ записывается в текущий выходной поток при помощи цели
put( С)
где С — символ, который нужно вывести, в кодировке ASCII (число от 0 до 127), например, вопрос
?- put( 65), put( 66), put( 67).
породит следующий вывод:
АВС
65 — ASCII-код 'А', 66 — 'В', 67 — 'С'.
Одиночный символ можно считать из текущего входного потока при помощи цели
get0( С)
Она вызывает чтение символа из входного потока, и переменная С конкретизируется ASCII-кодом этого символа. Вариантом предиката get0
является get
, который используется для чтения символов, отличных от пробела. Поэтому цель
get( С)
вызовет пропуск всех непечатаемых символов (в частности пробелов) от текущей позиции во