После завершения стадии проектирования можно приступить к стадии реализации проекта. Теперь нашей задачей является написание предикатных выражений и вспомогательных правил, которые потребуются основным модулям.
ГЛАВНЫЙ МОДУЛЬ
Главный модуль программы 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(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 :- !.
/* Диалог с этой БД осуществляется по принципу меню. При этом используются оконнные средства Турбо-Пролога. Основываясь на запросе пользователя, СУБД активизирует соответствующие процессы для удовлетворения этого запроса. Меню можно расширить за счет включения новых функций. */