Чтение и запись информации с файлов

При вводе и выводе информации в Прологе используется понятие потоков. Файлы для чтения - это входные потоки. Файлы для записи - это выходные потоки.

Для пользователя определены два потока:

· информация вводимая с клавиатуры - входной поток.

· информация выводимая на монитор - выходной поток.

Эти потоки являются псевдофайлами с именем user.

В каждый момент времени для Пролога активны два файла:

для ввода - текущий входной поток.

для вывода - текущий выходной поток.

 

Обработка входных потоков

 

Входные потоки Пролог "видит".  Поэтому определены следующие предикаты:
  • see(F)- открывает файл F, например 'a.dat' и он становится текущим входным потоком.
  • seeing(F) - связывает F с именем файла, являющегося текущим входным потоком.
  • seen- закрывает текущий входной поток и связывает его с user.
Примеры: p1:-see('a.dat'),read(X),write(X),seen. p2:-see('a.dat'),seeing(F),write(F),seen, read(A),write(A).  
 

Обработка выходных потоков

В выходные потоки Пролог "говорит".
  • tell(F) - открывает файлF,как текущий выходной поток. Если файла нет, то создает его.
  • telling(F)- связывает F с именем файла, являющегося текущим выходным потоком.
  • told- закрывает файл, являющийся текущим выходным потоком. Текущим выходным потоком становится user.
 
   

Пример:

P3:- tell('a.dat'),write(a),told,write(a).

 

Обработка символов

Пролог имеет несколько предикатов для обработки символов.

put(X). Символы записываются в текущий выходной поток при помощи предиката put(C), где C - символ, который нужно вывести, представленный в кодировке ASCII (число от 0 до 127).

Пример:

P4:-put(65),put(66),put(67).

?-p4.
A B C

get(X). Печатный символ (код по ASCII больше 31) читается предикатом get(X). Аргумент X принимает числовое значение. Непечатный символ игнорируется.

Пример:


P4:- get (A), get (B), get (C).

?-p4.
65 66 67

get0(X)   читает любой (печатный или нет) символ.

Предикат repeat - цель, которая всегда успешна. Ее особое свойство состоит в том, что она всегда находит альтернативу. Поэтому всякий раз, когда до нее доходит перебор, она порождает новую ветвь вычислений.


Хотя repeat встроенный предикат, он может быть определен следующим образом:

repeat. repeat:- repeat.
     
     

Применение repeat можно посмотреть на примере процедуры sq, которая читает последовательность чисел и выдает их квадраты.
Последовательность чисел заканчивается атомом stop.

sq:-repeat, read(X),(X=stop,!, Y is X*X, write(Y)).

Рассмотрим предикаты, которые дают положительный ответ в случае соответствия переменной ее назначению:

  • atom(X) - да, если X -атом.
  • integer(X) - да, если X -целое.
  • atomic(X) - да, если X -целое или атом.
  • var(X) - да, если X -не конкретизированная переменная.
  • nonvar(X) - да, если X - терм, отличный от переменной, или уже конкретизированная переменная.

Рассмотрим в качестве примера универсальной предикат суммирования:

plus(X,Y,Z):-integer(X),integer(Y),integer(Z), S is X + Y, S=Z. plus(X,Y,Z):-integer(X),integer(Y),var (Z), Z is X + Y. plus(X,Y,Z):-var (X),integer(Y),integer(Z),   X is Z - Y. plus(X,Y,Z):-integer(X),var(Y),integer(Z),   Y is Z - X.

Примеры:

?-plus(1,2,Z). Z=3.?-plus(X,2,4). X=2.?-plus(1,Y,2). Y=1.?-plus(1,2,4). no.
     
     

 




Метапредикаты. Встроенные предикаты обработки термов

  Т=..L (читается "univ") истина, если L- список, начинающийся с главного функтора терма T, вслед за которым идут его аргументы.
   

Примеры:

?-f(a,b)=..L.
L=[f,a,b]

?-T=..(like,tom,mary).
T=like(tom,mary).

functor(Term,F,N) будет истиной, если F - главный функтор
терма Term,a N -количество его аргументов. Он позволяет из списка получать структуру и наоборот.

Примеры:

?-functor(f(a,S),F,G).
F=f
G=2
?-functor(b,F,G).
F=b
G=0
?-functor(F,d,4).
F=d(_,_,_,_).

arg(N,T,A) - обеспечивает доступ к конкретному аргументу структуры, где

N - номер аргумента, T - терм, A - значение аргумента.

Пример:

?-arg(2,f(a,b),X)
X=b

?-F=..[a,2,3,4,5],arg(4,F,X).
X=5

 













Предикаты работы с базой данных

Программа в Прологе   рассматривается, какбаза данных. Можно добавлять к базе данных новые предложения и удалять старые предложения.
Аналогично, в ходе выполнения программы ее можно изменять.
Для этого используются специальные предикаты.

  • assert(C) - добавляет к базе данных предложение С.

?-assert(a(b)).
?-listing.
a(b).

?-assert(a(a)).
?-assert(a(c)).
?-listing.
a(a).
a(c).

В базу данных можно добавлять целые предложения:

assert((a(X):-X>0))

?-F=..[a,b,c],assert(F).
a(b,c).

·

assert используется иногда для сохранения промежуточных результатов.
Может служить для передачи значений переменных между предложениями.
Использование assert лучше ограничивать из-за усложнения понимания программы.

Также на практике используется команда обратная assert, а именно retract(C), которая  удаляет предложения, согласуемые с C.

 












Поиск в лабиринте

 

Рассмотрим следующую задачу и ее решение средствами языка Пролог.


Существует дом с комнатами b, c, d, e, f, g. Между некоторыми комнатами есть двери. В одной из комнат (g) находится клад. Требуется пройти через комнаты к кладу.

Запишем информацию о дверях:

  door(a,b). door(b,c). door(b,e). door(d,e). door(d,c). door(e,g). door(e,f).
       
       

Переход из комнаты в комнату будет производиться через предикат:


Path(X,Y,T)

  • X - исходная комната;
  • Y - конечная комната;
  • T - список пройденных комнат. Он необходим, чтобы не проходить дважды через одну комнату.

Введем терминальное (целевое) условие:

Path(Y,Y,T)

Т.е. мы находимся в нужной комнате.

Правило перехода из комнаты в комнату можно записать следующим образом:

path(X,Y,T):-door(X,Z),not(member(Z,T)),   path(Z,Y,[Z|T]).

Характер рекурсии другой. Один аргумент всегда увеличивается. В этой программе каждая дверь в одну сторону. Чтобы избежать этого, есть два варианта:

 

   

Поиск пути в комнату f:

?-path(a,f,[]).

Добавим факт о кладе:

Money(g).

Тогда найдем путь к комнате с кладом.

Цель- запрос  будет выглядеть так:

?-path(a,X,[]), money(X).

         
         

Это вопрос типа "создать и проверить" находит достижимые комнаты, а затем проверяет наличие в них клада.

Запрос вида:

?-money(X),path(a,X,[]).
         
         

требует сначала найти комнату, а затем путь к ней.

Задачи для самостоятельного решения:

  • Как вывести путь T?
  • Как найти самый короткий путь?

 

 


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: