Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Основы программирования на языке Turbo Prolog.doc
Скачиваний:
56
Добавлен:
09.11.2019
Размер:
563.2 Кб
Скачать

4. Создание динамической базы данных

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

1) размер базы данных,

2) организацию элементов базы данных,

3) способы работы и содержания базы данных.

Использование баз данных, располагающихся в оперативной памяти (резидентных), оправданно, если эта БД имеет не слишком большой объем.

Для начала необходимо задать начальные данные и создать саму базу. Затем наступает черед системы управления базой данных (СУБД), ориентированной на диалог с пользователем. Любая система такого рода должна содержать, как минимум, такие возможности:

1) занесение в базу новых данных,

2) удаление данных из базы,

3) выборка и вывод содержащихся в базе данных.

Эти требования предполагают наличие в системе меню, предоставляющее пользователю возможность легко ориентироваться при обращениии к стандартным функциям СУБД, а также оконной системы, дающей четкое представление о доступных пользователю средствах.

5. Обсуждение проекта базы данных

Структурная схема нашей программы приведена на рис. 9.1.

рис. 9.1

Главный модуль программы do_mbase является одновременно и целью программы:

do_mbase :-

assert_database,

menu,

clear_database.

Он запускает поочередно три других модуля. Модуль assert_database засылает в базу информацию из ее статической части, затем управление передается модулю menu и, после выхода из menu, модулю очистки динамической БД clear_database.

Модули assert_database и clear_database были описаны ранее. Рассмотрим схему модуля menu. Она показывает, что модуль menu позволяет пользователю выбрать между шестью модулями:

process(1) для загрузки базы из файла,

process(2) для записи данных в базу,

process(3) для удаления данных,

process(4) для показа информации о члене,

process(5) для сохранения базы в файле,

process(6) для выхода из системы.

Все зти модули будут детализированы позднее.

6. Создание базы данных

Данные представляют собой информацию о членах парторганизации. Они включают имя, возраст, размер партвзноса и отметку об уплате. Далее создаются соответствующие имена и описания типов.

Предикаты динамической базы данных описываются в разделе программы database. В нашем случае необходим лишь один такой предикат.

domains

name,payment=symbol

age,rubel=integer

pay=integer

database

dmember_party(name,age,pay,payment)

Когда программа запускается на счет, утверждения динамической БД помещаются в оперативной памяти отдельно от «обычных» утверждений. (Это одна из причин того, что предикаты динамической БД описываются в специальном разделе программы.)

В разделе predicates следует описать все другие предикаты, используемые в программе.

Раздел программы goal содержит правило do_mbase:

goal

do_mbase.

Правила СУБД будут определены в разделе программы clauses. Также в этот раздел будут помещены утверждения статической базы.

7. Написание программных модулей

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

ГЛАВНЫЙ МОДУЛЬ

Главный модуль программы do_mbase засылает в базу информацию из статической базы, создает окно с номером 1, высвечивает в нем меню и очищает БД по окончании работы программы.

do_mbase :-

assert_database,

makewindow(1,7,7,"PARTY DATABASE",0,0,25,80),

menu,

clear_database.

Меню предназначено для удобства пользователя в выборе программных функций. Таковыми являются:

1. Load database (загрузка БД из файла).

2. Add a member_party to database (занесение в БД информации о новом члене).

3. Delete a member_party from database (удаление из БД).

4. View a member_party from database (выдача информации на экран).

5. Save database (сохранение БД в файле)

6. Quit from this program (окончание работы с программой).

Модуль menu содержит предикат бесконечного цикла repeat и предикат, запрашивающий у пользователя целое число в диапазоне от 1 до 6:

menu:-

repeat,

readint(Choise),

process(Choise),

Choise<>6,

!.

а так же предикаты, печатающие перечень доступных функций (эти предикаты находятся в окончательном тексте программы).

Обратим внимание на технику, использованную для обеспечения повторных вызовов модуля menu. Если пользователь введет число, не равное 6 (6 вызывает окончание программы), подцель Choice = 6 становится неуспешной, что вызывает возврат к предикату repeat. В случае успеха отсечение ! не даст вернуться к repeat и обеспечит выход из меню.

МОДУЛЬ ДЛЯ ЗАГРУЗКИ БАЗЫ ИЗ ФАЙЛА

Если файл party.dba уже существует и содержит данные, то их можно загрузить в динамическую БД.

process(1):-

consult(”party.dba”),!.

При попытке загрузить из несуществующего файла process(1) даст отказ, и произойдет возврат в меню.

МОДУЛЬ ДЛЯ ВВОДА ДАННЫХ

Правило process(2) предназначено для занесения в базу данных. Этот модуль

— создает окно для текста,

— просит пользователя ввести данные с клавиатуры,

— считывает их

— и заносит в БД новое утверждение dmember_party.

Вслед за этим модуль убирает вновь созданное окно и возвращает управление главному меню.

process(2) :-

makewindow(2,23,7," Add member to DATABASE ",

2,20,18,58),

shiftwindow(2),

write("Enter member_party name: "),

readln(Name),

write("Enter member_party age: "),

readint(Age),

write("Enter party dues: "),

readint(Rub),

write("Enter answer 'y' or 'n' about payment: "),

readln(Answer),

assertz(dmember_party(Name, Age, thousands(Rub), Answer)),

write(Name," has been added to the database."),

nl,

write("Press space bar. "),

readchar(_),

removewindow.

Последние строки сигнализируют об окончании процесса ввода и убирают дополнительное окно.

МОДУЛЬ ДЛЯ УДАЛЕНИЯ ДАННЫХ

Назначением модуля process(3) является удаление информации из базы данных. Это правило, также как и правило process(2), создает свое собственное окно, запрашивает у пользователя имя и удаляет из БД утверждение, содержащее информацию об этом члене партии. После очистки окна управление вновь передается главному меню.

Вслед за предикатами, создающими окно и сдвигающими его, идут предикаты, запрашивающие имя члена партии. Введенное пользователем значение присваивается переменной Name.

Следующая часть правила осуществляет операцию удаления утверждения из БД, посылает короткое сообщение об этом пользователю, ждет нажатия им произвольной клавиши и убирает с экрана дополнительное окно.

process(3) :-

makewindow(3,23,7,"Delete member from DATABASE", 10,30,7,40),

shiftwindow(3),

write("Enter name to DELETE: "),

readln(Name),

retract(dmember_party(Name,_,_,_)),

write(Name,"has been deleted from the database."),

nl, !,

write("Press space bar."),

readchar(_),

removewindow.

Для удаления из базы выбранного пользователем утверждения применен предикат retract. Так как любая другая информация о члене, кроме его имени, не представляет интерес в данной операции, то на месте всех других объектов стоят анонимные переменные.

МОДУЛЬ ДЛЯ ВЫБОРКИ ДАННЫХ

Назначением модуля process(4) является поиск содержащихся в базе данных. Этот модуль, как и два уже разобранных, создает свое собственное окно, а затем запрашивает имя. Если в БД находится утверждение, содержащее введенное имя, модуль производит выборку данных и выводит их на экран в удобном формате.

process(4) :-

makewindow(4,23,7," View Window ",

7,30,16,47),

shiftwindow(4),

write("Enter name to view: "),

readln(Name),

dmember_party(Name,Age,Thousands,Pay),

nl, write(" PARTY MEMBER "),nl,

nl, write(" Party Name: ",Name),

nl, write(" Age: ",Age),

nl, write(" Thousands rubel : ",Thousands),

nl, write(" Payment: ",Pay),

nl, nl, !,

nl, write("Press space bar"),

readchar(_),

removewindow.

Если в БД отсутствует утверждение с введенным пользователем именем, программа выдает сообщение об ошибке.

Окно для этого сообщения должно располагаться на видном месте, например, в центре экрана. Вариант process(4), отвечающий за выдачу сообщения об ошибке, выглядит так:

process(4) :-

makewindow(5,23,7," No Luck ",14,7,5,60),

shiftwindow(5),

write("Can't find that member in the database."),

nl, write("Sorry, bye!"),

nl, !,

write("Press space bar."),

readchar(_),

removewindow,

shiftwindow(1).

shiftwindow(1) делает активным окно с меню.

МОДУЛЬ ДЛЯ СОХРАНЕНИЯ БАЗЫ В ФАЙЛЕ

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

Правило del_statbase составляется по образу и подобию правила assert_database:

del_statbase :-

member_party(N,_,_,_),

retract(dmember_party(N,_,_,_)),

fail.

del_statbase :- !.

Первое правило с помощью возврата после неудачи перебирает все утверждения предиката member_party, которые удаляются из динамической БД с помощью retract. Второе обеспечивает успешное завершение цели. Отсечение запрещает передоказывать предикат del_statbase при возвратах. Само правило имеет вид:

process(5) :-

write("Are you want to save database (y/n)"),

readln(Answer),

upper_lower(Answer),

frontchar(Answer,'y',_),

del_statbase,

save("party.dba"), !.

Предикат upper_lower заменяет все прописные буквы строчными. Предикат frontchar успешен только в том случае, если ответ пользователя на запрос программы начинается с буквы y. Если вводится иная буква, предикат неуспешен, поэтому происходит возврат к предикату repeat модуля menu.

МОДУЛЬ ОКОНЧАНИЯ РАБОТЫ С ПРОГРАММОЙ

Модуль process(6) обеспечивает нормальное окончание сеанса работы с базой данных. Этот модуль не создает своего собственного окна. Новое окно здесь излишне, так как сообщения не требуют много места на экране.

process(6) :-

write("Are you sure want to quit (y/n)"),

readln(Answer),

frontchar(Answer,'y',_), !.

МОДУЛЬ РЕАКЦИИ НА ОШИБКУ

Аккуратно написанная программа должна надлежащим образом реагировать на допущенные пользователем ошибки при вводе. Если пользователь введет число, меньшее 1 или большее 6, будет успешным одно из правил:

process(Choice) :-

Choice < 1,

error.

process(Choice) :-

Choice > 6,

error.

Оба эти правила вызывают модуль error:

error :-

write("Please enter a number from 1 to 6."),

write("(Press the space bar to continue)"),

readchar(_).

/* Программа 9.1. Партийная жизнь.

Назначение: Демонстрация работы с динамической базой данных. База данных допускает следующие операции: добавление, удаление и выборку данных. Выборка включает просмотр данных. Замечание:эта программа:

создает динамическую базу данных,

считывает статическую базу данных в динамическую,

загружает динамическую базу данных из party.dba,

сохраняет динамическую базу данных в файле party.dba в текущем каталоге. */

domains

name, payment = symbol

age,rubel = integer

pay = integer

database

dmember_party(name, age, pay, payment)

predicates

repeat

do_mbase

assert_database

clear_database

del_statbase

menu

process(integer)

member_party(name, age, pay, payment)

error

goal

do_mbase.

clauses

/* Статическая база данных */

member_party("Вольфович",50,100,"n").

member_party("Фомич",65,1,"y").

member_party("Кузьмич",45,50,"n").

repeat.

repeat :- repeat.

/* Загрузка фактов статической БД в динамическую */

assert_database :-

member_party(Name,Age,Pay,Flag),

assertz(dmember_party(Name,Age,Pay,Flag)),

fail.

assert_database :-!.

/* Очистка динамической БД */

clear_database :-

retractall(dmember_party(_,_,_,_)).

/* Удаление фактов статической БД из динамической */

del_statbase :-

member_party(N,_,_,_),

retract(dmember_party(N,_,_,_)),

fail.

del_statbase :- !.

/* Диалог с этой БД осуществляется по принципу меню. При этом используются оконнные средства Турбо-Пролога. Основываясь на запросе пользователя, СУБД активизирует соответствующие процессы для удовлетворения этого запроса. Меню можно расширить за счет включения новых функций. */

do_mbase :-

assert_database,

makewindow(1,23,7," PRO PARTY DATABASE ",

0,0,25,80),

menu,

clear_database.

menu :-

repeat,

clearwindow,

write("* * * * * * * * * * * * * * * * * * * * *"), nl,

write("* 1.Load database *"), nl,

write("* 2.Add a member_party to database *"), nl,

write("* 3.Delete a member_party from database *"), nl,

write("* 4.View a member_party from database *"), nl,

write("* 5. Save database *"), nl,

write("* 6. Quit from this program *"), nl,

write("* * * * * * * * * * * * * * * * * * * * *"), nl,

write("Please enter your choice — 1,2,3,4,5 or 6:"),

readint(Choice),nl,

process(Choice),

Choice = 7,

!.

/* Загрузка базы данных из файла */

process(1) :-

consult("party.dba"), !.

/* Добавление информации о новом члене в БД */

process(2) :-

makewindow(2,23,7," Add member to DATABASE ",

2,20,18,58),

shiftwindow(2),

write("Enter member_party name: "),

readln(Name),

write("Enter member_party age: "),

readint(Age),

write("Enter party dues: "),

readint(Rub),

write("Enter answer 'y' or 'n' about payment: "),

readln(Answer),

assertz(dmember_party(Name,Age,Rub,Answer)),

write(Name," has been added to the database."),

nl,

write("Press space bar. "),

readchar(_),

removewindow.

/* Удаление информации о члене партии из БД */

process(3) :-

makewindow(3,23,7," Delete member from DATABASE ", 10,30,7,40),

shiftwindow(3),

write("Enter name to DELETE: "),

readln(Name),

retract(dmember_party(Name,_,_,_)),

write(Name," has been deleted from the database."),

nl, !,

write("Press space bar."),

readchar(_),

removewindow.

/* Просмотр информации о члене партии */

process(4) :-

makewindow(4,23,7," View Window ",

7,30,16,47),

shiftwindow(4),

write("Enter name to view: "),

readln(Name),

dmember_party(Name,Age,Rub,Pay),

nl, write(" PARTY MEMBER "),nl,

nl, write(" Party Name : ",Name),

nl, write(" Age : ",Age),

nl, write(" Rubel : ",Rub),

nl, write(" Payment : ",Pay),

nl, nl, !,

nl, write("Press space bar"),

readchar(_),

removewindow.

process(4) :-

makewindow(5,23,7," No Luck ",14,7,5,60),

shiftwindow(5),

write( "Can't find that member of party in the database."),

nl, write("Sorry, bye!"),

nl, !,

write("Press space bar."),

readchar(_),

removewindow,

shiftwindow(1).

/* Сохранение динамической БД в файле "party.dba" */

process(5) :-

write("Are you want to save database (y/n)"),

readln(Answer),

frontchar(Answer,'y',_),

del_statbase,

save("party.dba"), !.

/* Выход из программы */

process(6) :-

write("Are you sure want to quit (y/n)"),

readln(Answer),

upper_lower(Answer),

frontchar(Answer,'y',_), !.

/* Неправильное обращение к БД */

process(Choice) :-

Choice < 1,

error.

process(Choice) :-

Choice > 6,

error.

error :-

write("Please enter a number from 1 to 6."),

write("(Press the space bar to continue)"),

readchar(_).

/* конец программы */

Упражнение 9.1.

Дополнить меню новой функцией, осуществляющей просмотр всех членов партии.