Nl is N + 1,
показфайла( Nl).
Вот другой пример программы обработки файлов, построенной по подобной схеме. Пусть есть файл с именем файл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( С)
вызовет пропуск всех непечатаемых символов (в частности пробелов) от текущей позиции во входном потоке до первого печатаемого символа. Этот символ затем тоже считывается и С конкретизируется его ASCII-кодом.
В качестве примера использования предикатов, переносящих одиночные символы, давайте рассмотрим процедуру сжатие, выполняющую следующую работу: считывание из входного потока произвольного предложения и вывод его же, но в форматированном виде - все группы идущих подряд пробелов заменены на одиночные пробелы. Для простоты будем считать, что все предложения входного потока, обрабатываемые процедурой сжатие, оканчиваются точками, а слова в них отделены одно от другого одним или несколькими пробелами, и только ими. Тогда следующее предложение будет допустимым:
Робот пытался налить вина из бутылки.
Цель сжатиевыведет его в таком виде:
Робот пытался налить вина из бутылки.
Процедура сжатиебудет иметь такую же структуру, как и процедуры обработки файлов из предыдущего раздела. Сначала она прочтет первый символ, выведет его, а затем завершит обработку, в зависимости от того, каким был этот символ. Есть три альтернативы, которые соответствуют следующим случаям: символ является точкой, пробелом или буквой. Взаимное исключение этих трех альтернатив обеспечивается в программе отсечениями:
Читать дальше