Скачиваний:
201
Добавлен:
17.06.2016
Размер:
2.69 Mб
Скачать

Работа с фактами, как с термами

С фактами, которые описываются предикатами базы данных, можно рабо-

тать также, как с термами. Это становится возможным благодаря домену

dbasedom (который автоматически объявляется системой Турбо Пролога) или

любому, определенному пользователем имени домена базы данных.

Для каждого предиката в базе данных Турбо Пролог создает одну аль-

тернативу. Он описывает каждый предикат базы данных с помощью функтора и

доменов аргументов этого предиката. Например, такое объявление базы дан-

ных:

database

person(name,telno)

city(cno,cname),

Турбо Пролог превратит в соответствующий домен dbasedom:

domains

dbasedom=person(name,telno);city(cno,cname)

Этот домен может быть использован как любой другой домен.

Примеры

1. Следующий пример показывает, как вы можете построить предикат

my_consult, аналогичный стандартному предикату consult.

/* Предикат my_consult,определенный с помощью readterm */

domains

file= dbase

database - dba1

/* ...Объявление предикатов базы данных,которые будут

считываться из файла */

pradicates

my_consult(string)

repfile(file)

clauses

my_consult(FileName) :-

openread(dbase,FileName),

readdevice(dbase),

repfile(dbase),

readterm(dba1,Term),

assertz(Term),

fail.

my_conult(_) :-eof(dbase).

repfile(_).

repfile(F):-not(eof(F)),repfile(F).

Если, например, секция database содержит описание:

p(string,string)

и файл, с именем DD.DAT, существует (его содержание описано в преды-

дущем разделе), вы можете получить следующий диалог:

Goal:my_consult("dd.dat").

Yes

Goal:p(X,Y).

X = "Peter",Y = "28th Street"

X = "Curt",Y = "Wall Street"

2 solutions

2. Следующий пример программы показывает, как можно создать несколь-

ко новых предикатов, аналогичных assertz и retract с тем исключени-

ем, что база данных располагается в файле,а не в памяти. Это расши-

ряет возможности обычной внутренней базы данных, так как факты внут-

ренней базы данных являются частью Пролог-программы и поэтому огра-

ничены размером доступной памяти прямого доступа. База данных, реа-

лизованная с помощью файлов, ограничивается только размером доступ-

ного пространства на диске. Эти средства позволяют базе данных ваше-

го Турбо Пролога достигать размера до 100 Мбайт.

В программе следующего примера реализованы два определенных пользо-

вателем предиката dbassert и dbretract. Предикат indexfile использу-

ется для записи позиций фактов в файле данных. Каждая позиция предс-

тавлена вещественным числом, определяющим, где данный факт хранится

относительно начала файла. (Использование индексного файла при таком

способе не является необходимым, но для двоичного поиска или техники

хеширования для увеличения скорости доступа к фактам в базе данных

оно может быть основным.)

domains

file = datafile;indexfile

name, address = string

age = integer

sex = m or f

interest = symbol

interests = interest*

/* record = person (name,adress,age,sex,interests) */

filename = string

filepos = ral

database - record

person(name,address,age,sex,interests)

predicates

dbassert(record)

dbretract(record)

dbread(record)

dbass(record,filename)

dbaaccess(record,filepos)

dbret(record,filename,filename)

dbretl(record,filepos)

dbrd(record,filename,filename)

clauses

/* * * * * * * * * * * * * * * * * * *

* Входные программы. Они могут быть изменены для *

* применения: например, расширяя пул открытых файлов *

* в соответствии с доступом к нескольким базам *

* данных одновремено или иметь более чем один файл *

* данных *

* * * * * * * * * * * * * * * * * * */

dbassert(Term) :-dbass(Term,"dba.ind","dba.dat").

dbretract(Term) :-dbret(Term,"dba.ind","dba.dat").

dbread(Term) :-dbrd(Term,"dba.ind","dba.dat").

/*dbass прибавляет терм к файлу данных и записывает данные

в индексный файл */

dbass(Term,IndexFile,DataFile):-

existfile(DataFile),existfile(IndexFile),!,

openappend(datafile,DataFile),

writedevice(datafile),

filepos(datafile,Pos,0),

write(Term),nl,

closefile(datafile),

openappend(indexfile,IndexFile)

writedevice(indexfile),

writef("%7.0\n",Pos),

closefile(indexfile).

dbass(Term,IndexFile,DataFile):-

openwrite(datafile,DataFile),

writedevice(datafile),

filepos(datafile,Pos,0),

write(Term),nl,

closefile(datafile),

openwrite(indexfile,IndexFile)

writedevice(indexfile),

writef("%7.0\n",Pos),

closefile(indexfile)

/ * * * * * * * * * * * * * * * * * * *

* *

* dbrd возвращает термы из базы данных. Файл *

* закрывается после чтения. *

* *

* * * * * * * * * * * * * * * * * * */

dbrd(Term,IndexFile,DataFile):-

openread(datafile,DataFile),

openread(indexfile,IndexFile)

dbaaccess(Term,-1).

dbrd(_,_,_):-

closefile(datafile),closefile(indexfile),fail.

dbaaccess(Term,Datpos):-

Datpos>=0,

filepos(datafile,Datpos,O),

readdevice(datafile),

readterm(record,Term).

dbaaccess(Term,_):-

readdevice(indexfile),

readreal(Datposl),

dbaaccess(Term,Datpos1).

/ * * * * * * * * * * * * * * * * * * * *

* dbret удаляет термы из базы данных. Терм удаляется *

* посредством записи отрицательного числа в *

* индексный файл *

* * * * * * * * * * * * * * * * * * * */

dbret(Term,Indexfile,Datafile) :-

openread(datafile,DataFile),

openread(indexfile,IndexFile)

dbretl(Term,-1).

dbret(Term,Datpos):-

Datos >= 0,

filepos(datafile,Datpos,O),

readdevice(datafile),

readterm(record,Term),!,

filepos(indexfile,-9,1),

fluch(indexfile),

writedevice(indexfile),

writef("%7.0\n",-1),

writedevice(screen).

dbret(Term,):-

readdevice (indexfile),

readreal(Datposl),

dbreatl(Term,Datposl).

/* Программа CH12EX12.PRO */

domains

file = datafile;indexfile

name, address = string

age = integer

sex = m or f

interest = symbol

interests = interest*

/* record = person(name,adress,age,sex,interests )*/

filename = string

filepos = ral

database - record

person(name,address,age,sex,interests)

predicates

dbassert(record)

dbretract(record)

dbread(record)

dbass(record,filename)

dbaaccess(record,filepos)

dbret(record,filename,filename)

dbretl(record,filepos)

dbrd(record,filename,filename)

clauses

/* * * * * * * * * * * * * * * * * * * * * * * * * * * *

* Входные программы. Они могут быть изменены для *

* конкретной задач. Например, расширяя пул открытых *

* файлов в для с доступом к нескольким базам *

* данных одновремено или иметь более чем один файл *

* данных *

* * * * * * * * * * * * * * * * * * * * * * * * * * * */

dbassert(Term) :-dbass(Term,"dba.ind","dba.dat").

dbretract(Term) :-dbret(Term,"dba.ind","dba.dat").

dbread(Term) :-dbrd(Term,"dba.ind","dba.dat").

/*dbass прибавляет терм к файлу данных и записывает данные

в индексный файл */

dbass(Term,IndexFile,DataFile):-

existfile(DataFile),existfile(IndexFile),!,

openappend(datafile,DataFile),

writedevice(datafile),

filepos(datafile,Pos,0),

write(Term),nl,

closefile(datafile),

openappend(indexfile,IndexFile)

writedevice(indexfile),

writef("%7.0n",Pos),

closefile(indexfile).

dbass(Term,IndexFile,DataFile):-

openwrite(datafile,DataFile),

writedevice(datafile),

filepos(datafile,Pos,0),

write(Term),nl,

closefile(datafile),

openwrite(indexfile,IndexFile)

writedevice(indexfile),

writef("%7.0n",Pos),

closefile(indexfile)

/ * * * * * * * * * * * * * * * * * * * * * * * *

* dbrd возвращает термы из базы данных. Файл *

* закрывается после чтения. *

* *

* * * * * * * * * * * * * * * * * * * * * * * */

dbrd(Term,IndexFile,DataFile):-

openread(datafile,DataFile),

openread(indexfile,IndexFile)

dbaaccess(Term,-1).

dbrd(,,):-

closefile(datafile),closefile(indexfile),fail.

dbaaccess(Term,Datpos):-

Datpos>=0,

filepos(datafile,Datpos,O),

readdevice(datafile),

readterm(record,Term).

dbaaccess(Term,):-

readdevice(indexfile),

readreal(Datposl),

dbaaccess(Term,Datpos1).

/ * * * * * * * * * * * * * * * * * * * * * * * * * * *

* dbret удаляет термы из базы данных. Терм удаляется *

* посредством записи отрицательного числа в *

* индексный файл *

* * * * * * * * * * * * * * * * * * * * * * * * * * * */

dbret(Term,Indexfile,Datafile) :-

openread(datafile,DataFile),

openread(indexfile,IndexFile)

dbretl(Term,-1).

dbret(Term,Datpos):-

Datos >= 0,

filepos(datafile,Datpos,O),

readdevice(datafile),

readterm(record,Term),!,

filepos(indexfile,-9,1),

fluch(indexfile),

writedevice(indexfile),

writef("%7.0n",-1),

writedevice(screen).

dbret(Term,):-

readdevice (indexfile),

readreal(Datposl),

dbreatl(Term,Datposl).

Информация о внешней системе базы данных содержится в Главе 15.

Обзор

Отметим наиболее важные моменты, встречающиеся в этой главе:

1. Турбо Пролог обеспечивает три стандартных предиката для за-

писи:

a. write (для простого вывода);

b. writef (для вывода, форматированного в

соответствии с форматными спецификаторами);

c. nl ( для генерации новой строки);

2. Базовые стандартные предикаты Турбо Пролога для чтения:

a. readln (для чтения целиком строки символов);

b. readint, readreal, readchar (для чтения целых,

вещественных и символьных значений

соответственно);

c. readterm (для чтения составных объектов).

3. Другие, более специализированные предикаты чтения:

a. file_str (для чтения целиком текстового файла в

строку);

b. inkey (для чтения символа с клавиатуры, если

клавиша нажата);

c. keypressed (для определения, была ли нажата

какая-либо клавиша);

d. unreadchar (для посылки символов обратно в буфер

клавиатуры).

4. Турбо Пролог использует устройство current_read_device

(обычно это клавиатура) для ввода и current_write_device (обыч-

но это экран) для вывода. Вы можете указать другие устройства и

можете переопределить текущие устройства ввода-вывода во время

выполнения. (Такое переопределение известно как изменение нап-

равления ввода-вывода.)

5. Основные предикаты доступа к файлам Турбо Пролога:

a. openread (открытие файла для чтения);

b. openwrite ( открытие файла для записи);

c. openappend (открытие файла для добавления);

d. openmodify (открытие файла для модификации);

e. filemode (установка файла в текстовый или

двоичный режим);

f. closefile (закрытие файла);

g. readdevice (переназначить текущее устройство

чтения или дать его имя);

h. writedevice (переназначить текущее устройство

записи или дать его имя);

6. Для доступа к файлам вы используете домен file, который име-

ет семь альтернатив:

a. com1 (для записи в стандартный порт связи);

b. keyboard (для чтения с клавиатуры);

c. printer (для записи в параллельный порт

принтера);

d. screen (для записи на экран);

e. stdin (для чтения со стандартного ввода ДОС);

f. stdout (для записи на стандартный вывод ДОС;

g. stderr (для записи на стандартную ошибку ДОС.

7. Для работы с файлами вы используете следующие стандартные

предикаты:

a. filepos (контролирует позицию в которой

происходит чтение или запись);

b. eof (проверяет достигнут ли конец файла);

c. flush (записывает содержимое внутреннего буфера

в файл);

d. existfile (проверяет существует ли файл);

e. deletefile (стирает файл);

f. renemefile (переименовывает файл);

g. disk (изменяет текущий диск и

каталог/подкаталог).

8. Стандартный предикат readterm позволяет вашей программе по-

лучить доступ к фактам в файле во время исполнения. readterm

может считывать любой объект, записанный write, плюс факты,

описанные предикатами базы данных.

Соседние файлы в папке Документация