Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекция ФилП.docx
Скачиваний:
10
Добавлен:
19.09.2019
Размер:
401.58 Кб
Скачать

Ввод и вывод

До сих пор мы рассматривали программы котторые работали в режиме вопрос ответ. В прологе есть встроенные предикаты, которые могут обращаться к у ввода вывода. Такие предикаты имеют побочный эффект они еще изменяют состояние буфера устройства ввода вывода. Правда они нарушают логии модель пролога.

Входные потоки

Входные файлы

Выходные потоки

Вых файлы

э

терминал

Программа на прологе

файлы

user

Потоки, связанные с файлами обозначаются именами этих файлов.

В каждый момент работы программы может быть активным один поток ввода и один поток вывода.

Нельзя несколько потоков сразу….и из них…

Предикат see /1 определяет текущий поток ввода.

А tell /1 поток вывода.

Закрыть файлы можно предикатами

seen /0

told /0

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

Теперь об обработке термов

Предикат read /1 вызывает чтение из текущего входного потока терма

?- read(T).

Будет прочитан терм и связан с переменной T. Терм может быть любой сложности.

Аргумент предиката read и входные данные долдны быть сопоставимы. Унификация тут используется.

?- read(pnt(X,Y)).

Если предикат read потерпит неудачу, то старое состояние буфера не восстанавливается.

write /1.

Любой терм может быть выведен в выходной поток.

Рассмотрим пример ввода данных.

Рассмотрим как можно ввести последовательность термов.

vhod

See open

Seen close

Tell told for vivod!.

Нужно открыть файл

?-see(‘d:\work\data.txt’), rd_lst(X), seen, see(user), write(X).

rd_lst(X) вводит все термы, которые есть в файле.

rd_lst(Ts):-

read(T),

rd_next(T,Ts).

Прочитали терм и посмотрели нет ли конца файла. Это делает rd_next.

rd_next имеет 2 варианта. Если при чтении конец файла то прочитанный терм будет атомом end_of_file

rd _next(end_of_file, []).

rd _next(T, [T|Ts]):- rd_lst(Ts).

Рассмотрим ввод вывод алфавитно – цифровых символов

Символы задаются числами от 0 до 127 в кодировке ASCII.

Предикат put /1 выводит один символ в выходной поток.

?- put(65).

A

Yes

Можно исп сам символ в кавычках.

?- put(“?”).

?

Yes

Кавычки могут быть как одинарные, так и двойные.

Для ввода есть 2 основных предиката get0 /1. Этот предикат читает символ из входного потока.

Предикат get /1 читает первый входной символ, имеющий графическое изображение.

Он игнорирует табуляцию, пробелы, …

Когда вводится последовательность символов нам нужно из них строить атомы и или числа.

Для этого есть предикат name /2, который ставит в соответствие атому или числу список символов.

?- name(X, [‘a’,’b’]).

X = ab

То же самое можно и числами.

Рассмотрим программу которая читает посимвольно список и преоб его в прологовские термы.

getLx(R):-

get0(Ch),

( Ch = 46 -> % если точка то…

R = [];

getLx(Rt),

R = [Ch|Rt]).

digit(D) --> [D], {between(48,57,D)}. % 0..9

letter(L) --> [L], {between(97,122,L)}. %a..z

num([D|Ds]) -->digit(D), num(Ds).

num([D])--> digit(D).

p :- b,:,e1.

p:- e2.

Этот предикат p можно рассматривать как условие if b then e1 else e2.

Есть синтаксическое расширение для этой конструкции след вида:

( b-> e1; e2)

b, e1, e2 – любые последовательности целей.

определим 2 синтаксические категории цифры и буквы

digit терм D, D переменная, она имеет дополнит условие ( в фиг скобах дополнительный предикат) что она в диапазоне…48…57…

сам предикат digit имеет дополнительный параметр, распознанная цифра.

letter аналогично.

Нетерминал имеет параметр L.

После этого можно определить число. Число – это цифра за которой следует число и одна цифра.

Здесь мы исп дополнительные параметры. Число имеет дополнит параметр – список из цифр. этот список будет результатом трансляции. Эти обозначения соответствуют атрибутной грамматике.

Пример

% как исп num

% ?- getLx(X), num(Y,X,[]).

|: 123.

% X = Y, Y = [49, 50, 51].

% ?- getLx(X), num(Y,X,[]).

% |:12q.

% False.

Правые 2 параметра это входная последовательность . далее дополн параметры . тут это Y. далее оператор ввел 123, пролог выдал ответ … X = Y, Y = [49, 50, 51].

Рассмотрим как определить идентификатор

Идентификатор – последовательность букв или цифр, начинающихся с буквы.

Id([L|LDs]) --> letter(L), lod(LDs).

lod([L|LDs]) --> letter(L), lod(LDs).

lod([D|LDs]) --> digit(D), lod(LDs).

lod([]) --> [].

lpar --> [40]. %левая круглая скобка

rpar --> [41]. %пр

space --> [32]. % пробел

delim --> space, delim. % разделитель, 1 или более пробелов

delim --> space.

Пример

Elem – элемент списка

Id –список символов, обознач идентфиикатор

elem(Ida) --> id(Id), {name(Ida,Id)}.

elem(Nt) --> num(N), {name(Nt,N)}.

elem(L) --> list(L).

list(L) --> lpar, elem(L), rpar.

elems([H|T]) --> elem(H), delim, elems(T).

elems(A) --> elem(A).

elems([]) --> [].

?- getdx(X), list(Y, X,[]).

|: (let ((x 12) (y 13)) (add x y)).% контсрукция на Лиспе. Наша программа разберет его как список Лисп….

Y = [let, [[x,12], [y, 13]], [add, x, y]].

Сложные структуры можно так разобрать, расписать.