Краткие теоретические сведения. 2.1 Базы данных в Турбо-Прологе
2.1 Базы данных в Турбо-Прологе
Файл базы данных представляет собой набор связанных между собой записей. Файл базы данных (БД) имеет вид обычного файла, однако содержащиеся в нем данные имеют свою внутреннюю организацию. Данные внутри каждой записи имеют одну и ту же структуру.
В Турбо-Прологе имеются специальные средства для организации базы данных. Эти средства рассчитаны на работу с реляционными базами данных, т.к. Турбо-Пролог особенно хорош для написания диалоговой системы именно для реляционной БД: внутренние унификационные структуры языка осуществляют автоматическую выборку фактов с нужными значениями известных параметров и присваивают значения еще не определенным. К тому же механизм отката позволяет находить все имеющиеся ответы на сделанный вопрос.
Основные понятия реляционной БД: отношение, атрибут, элемент отношения, мощность соответствуют определенным понятиям Турбо-Пролога: предикат БД, объект, отдельное утверждение, количество утверждении (соответственно).
Таким образом, например, информация о студенте (фамилия, год рождения, номер группы, название улицы, номер дома, номер квартиры) может быть представлена предикатом:
dstud(name, year, team, street, house, flat).
Описание предикатов БД производится в разделе database:
database
dstud(name, year, team, street, house, flat),
при этом используемые в предикате домены должны быть уже описаны. Все различные утверждения этого предиката составляют динамическую БД Турбо-Пролога. База данных называется динамической, если во время работы программы. из нее можно удалять любые содержащиеся в ней утверждения, а также добавлять новые. В этом состоит ее отличие от статической базы данных, где утверждения являются частью кода программы и не могут быть изменены во время счета. Другая важная особенность динамической базы данных состоит в том, что она может быть записана на диск и считана с диска в ОЗУ.
Иногда бывает предпочтительнее иметь часть информации базы данных в виде статической БД; эти данные заносятся в динамическую БД сразу после активизации программы. Например, предикат статической БД, соответствующий предикату dstud динамической базы данных, есть
predicates
stud(name, year, team, street, house, flat).
clauses
stud("Белов А. Е.", 1964, 3, "Парковая"," 14/2; 22).
stud("Евдокимов А. М.", 1970, 9, "P. Зорге","34",91).
stud(''Ерофеев Е. B.", 1973, 3, "Аксакова"," 62", 32).
stud("Петров В. Е.", 1964, "Лысый проезд","13'', 666).
Используемые домены имеют следующие типы:
name, street, house = string
year, team, flat = integer
Правилом для занесения в динамическую БД информации из утверждений предиката stud служит
assert_database:-stud(name, year, team, street, house, flat),
assertz(dstud(name, year, team,street,house,flat)),
fail.
assert_database:-!.
2.2 Предикаты динамической БД Турбо-Пролога
Для работы с утверждениями динамической БД в Турбо-Прологе используются следующие предикаты.
asserta(<факт>).
Заносит факт(утверждение) в начало резидентной БД.
Например, чтобы поместить в БД утверждение dstud(John, 1972) перед уже имеющимся там утверждением dstud("Ann'', 1973), необходимо следующее предикатное выражение:
asserta(dstud("John", 1972)).
Теперь БД содержит два утверждения, причем утверждение со сведениями о John предшествует утверждению со сведениями об Аnn.
assertz(<факт>)
Заносит факт (утверждение) в конец резидентной БД.
retract((<факт>)).
Удаляет утверждение из динамической БД. Модуль очистки динамической БД с использованием- retract следующим образом:
clear_database:-
retract(dstud(_,_,_,_,_,_ )),
fail.
clear_ database:-!.
save(DOS_file_name).
Сохраняет находящуюся в памяти динамическую базу данных в файле с именем DOS_file_name.
consult(DOS_file_name).
Считывает в память из файла DOS_file_name содержимое динамической БД.
findall(Variable_name, Predicate_expression, List name)
Variable name обозначает объект входного предиката Predicate expression, а List name является именем переменной выходного списка. Предикат осуществляет сбор данных из БД в список для последующей их обработки.
Пусть в базе данных имеются следующие утверждения:
stud("John", 1972).
stud("Ann",1973).
stud("Benne",1976).
stud(''Stone",1971).
Сбор информации о годах рождения студентов осуществляется одним - единственным выражением:
findall(X, stud(_, Х), Year_list).
Работа предиката скрыта от глаз пользователя. Х - служебная переменная. После выполнения предиката список Year_list примет вид
[1972, 1973,1970,1971)
До определения оператора список Year_list должен быть описан как список целочисленных элементов.
2.3 Резидентные базы данных
Использование баз данных, располагающихся в оперативной памяти (резидентных) вполне оправдано, если эти БД имеют не слишком большой объем. Для начала необходимо задать начальные данные (размер БД организация элементов БД, способы работы и содержание БД) и создать саму базу. Затем под управлением СУБД осуществляется диалог с пользователем БД. Любая система такого рода должна содержать как минимум следующие возможности:
a) занесение в базу новых данных;
б) удаление данных из базы;
в) выборка и вывод содержащихся в базе данных.
Пример. Организация БД о студента. Имеющиеся сведения о студентах приведены и таблице 6.
Таблица 6
Фамилия | Год рождения | № группы | Средний бал аттестата |
Белов | |||
Здорин | |||
Гришанов | 4,95 | ||
Смирнов | |||
Алексеев | 3,6 |
Предикат статической БД, хранящей информацию о студентах, имеет вид:
stud(name, year team, mark);
динамической БД:
dstud(name, year, team mark),
которые описываются соответственно в разделах predicates и database.
Описание доменов, используемых в предикатах, производится следующим образом:
domains
name=string
year, team=integer
mark=real
Исходное содержимое БД задается при помощи утверждений с использованием статических предикатов. Правилом для занесения в базу этой информации служит
assert_database:- stud(Name, Year, Team, Mark),
assertz(dstud(Name, Year, Team, Mark)),
fail
assert_database:-!.
Модуль menu высвечивает четыре доступные пользователю опции:
a) занесение в БД новой информации о студентах;
б) удаление информации о студентах;
в) выдача интересующих пользователя информации;
г) окончание работы программы.
Модуль также запрашивает у пользователя режим работы согласно опции.
Операторами Repeat и Choice=4 осуществляется цикличность работы программы.
В соответствии с выбранными режимом работы осуществляется выбор правил:
- process(1) для занесения информации в БД;
- process(2) для удаления информации из БД;
- process(3) для выборки данных;
- process(4) для окончания работы с программой.
Каждый из этих модулей создает свое диалоговое окно. В программе предусмотрена реакция программы на ошибки при вводе опций работы (в модуле menu).
Программа организации БД о студентах:
domains
name=string
year, team=integer
mark=real
database
dstud(name, year, team, mark)
predicates
repeat.
assert_database
menu.
process(integer).
clear_database.
stud(name, year team, mark). ,do_goal
clauses
repeat.
repeat:-repeat.
/" БД о студентах "/
stud("Белов А.E.", 1964, 103, 4.0).
stud("Евдокимов A. M.", 1970, 186, 3.0).
stud("Ерофеев Е. В.", 1973, 286, 4.99).
stud("Петров В. Е.", 1964, 386, 5.5).
assert_database:-
stud(Name, Year, Team, Mark),
assertz(dstud(Name, Year, Team, Mark),
fail.
assert_database:-!.
clear_database:- retract(dstud(_,_,_,_)),
fail.
clear_database:-!.
do_goal:-
assert_database,
makewindow(1, 7, 7, ''БД о студентах", 0, 0, 25, 80),
menu,
clear_database,
menu:-
repeat
Clearwindow,
write("***********************************"), nl,
write("* *"), nl,
write("* 1. Занесение в БД новой информации* "), n1,
write("* 2. Удаление информации о студентах * "), nl,
write("* 3. Выдача информации пользователя * "), n1,
write("* 4. Окончание работы * "), nl,
write("* *"), nl,
write("***********************************"), nl, nl,
write("Пожалуйста введите цифру, соответствующую''),
write("режиму работы (1,23 или 4)"),
readint(Choice), nl,
Choice>0, Choice<5.
process(Choice),
Choice=4, !.
process(1):-
makewindow(2, 7, 7, "Занесение информации о студентах в БД'', 2, 20, 18, 58),
shiftwindow(2),
write("Введите фамилию студента" ),
readln(Name),
write("Введите год рождении студента: ''),
readint(Year),
write("Введите номер группы: "),
readint(Team),
write("Введите средний балл аттестата: "),
readreal(Mark),
assertz(dstud(Name, Year, Team, Mark)),
write("Студент", Name,''занесен в БД"), nl, !,
write("Нажмите клавишу для продолжения"),
readchar(_),
removewindow.
process(2):-
makewindow(3, 7, 7,"Удаление студентов из БД", 10, 36, 7, 40),
shiftwindow(3),
write( ''Введите фамилию студента, информация о котором будет удалена:''),
readln(Name),
retract(dstud(Name,_,_,_)),
write("Информация о студенте'', Name, ''удалена из БД''), nl, !.
write(''Нажмите клавишу для продолжения"),
readchar( ),
removewindow.
process(3):-
makewindow(4, 7, 7, "Выдача информации", 7, 30, 16, 47),
shiftwindow(4),
write(" Введите имя студента, информацию о котором вы хотите получить:"),
readln(Name),
dstud(Name, Year, Team, Mark), nl,
write(''Фамилия студента -'', Name), nl,
write(Год рождения -, Year), nl,
write("Номер группы - ", Team), nl,
write(''Средний балл - ", Mark), nl,nl, !,
write(" Для продолжения нажмите клавишу''),
readchar(_),
removewindow,
process(3):-
makewindow(5, 7, 7,."'Ошибка поиска ", 14, 7, 5, 60),
shiftwindow(5),
write('Поиск безуспешен!"), nl, nl, !,
write("Для продолжения нажмите клавишу" ),
readchar(_),
shiftwindow(1),
process(4}:-
write("Вы действительно хотите выйти из программы (y/n)?"),
readchar(Answer), Answer='у', !.
goal
do_goal.