Сибирский университет потребительской кооперации
Опубликован: 04.05.2005 | Доступ: свободный | Студентов: 4322 / 1347 | Оценка: 4.45 / 4.22 | Длительность: 12:28:00
ISBN: 978-5-9556-0034-5
Лекция 13:

Внутренние (динамические) базы данных

< Лекция 12 || Лекция 13: 1234 || Лекция 14 >

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

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

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

  1. Получение информации о телефонном номере по фамилии человека.
  2. Получение информации о фамилии абонента по телефонному номеру.
  3. Добавление новой записи в телефонную базу.
  4. Изменение существующей в телефонной базе записи.
  5. Удаление записи из телефонной базы.

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

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

Эти действия выполняет следующее правило (символ '0' означает, что пользователь нажал соответствующую клавишу):

m('0'):– 
       save("phones.ddb "), /* сохраняем телефонную базу 
                               в файл */
       retractall(_)./* удаляем все факты из внутренней 
                        базы данных */

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

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

start:–
      existfile("phones.ddb"),!, 
      /* если существует файл с телефонной базой */
      consult("phones.ddb "), 
           /* , то загружаем факты во внутреннюю базу 
              данных */
      menu. /* и вызываем меню */
start:–
      menu. /* если такого файла еще нет, просто 
               вызываем меню */

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

Это реализуют два приведенных ниже предиката.

m('1'):–
       write("Введите фамилию"), nl, 
               /* выводим приглашение ввести фамилию */
       readln(Name), /* читаем введенную фамилию 
                        в переменную Name */
       name_phone(Name, Phone), 
                     /* вызываем предикат, который 
                        помещает в переменную Phone 
                        телефонный номер, соответствующий 
                        фамилии Name или сообщение 
                        об отсутствии информации */
       write("Номер телефона: ",Phone), 
                     /* выводим значение переменной 
       Phone */
       readchar(_), /* ждем нажатия любой клавиши */
       menu. /* возвращаемся в меню */
name_phone(Name,Phone):– 
                       phone(Name,Phone),!. 
name_phone(_,"Нет информации о телефонном номере"). 
                    /* если	нужного факта во внутренней 
                       базе данных не нашлось, 
                       то вместо телефонного номера 
                       возвращаем соответствующее 
                       сообщение */

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

Соответствующие предикаты будут выглядеть следующим образом:

m('2'):– 
       write("Введите номер телефона"),nl,
       readln(Phone),
       phone_name(Name, Phone),
       write("Фамилия абонента: ",Name),
       readchar(_),
       menu. /* вызываем меню */
phone_name(Name,Phone):– 
                       phone(Name,Phone).
phone_name("Нет информации о владельце телефона",_). 
                   /* если нужного факта во внутренней базе 
                      данных не нашлось, то вместо фамилии 
                      абонента возвращаем соответствующее 
                      сообщение */

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

Это будет выглядеть следующим образом:

m('3'):– 
       write("Введите фамилию"),nl,
       readln(Name),
       write("Введите номер телефона"),nl,
       readln(Phone),
       assert(phone(Name,Phone)), 
                       /* добавляем факт во внутреннюю 
                          базу данных */
       menu. /* вызываем меню */

Если пользователь желает выполнить четвертую операцию, то нужно дать ему возможность ввести фамилию абонента и его новый телефонный номер, после чего удалить устаревшую информацию из телефонной базы (с помощью предиката retract ) и добавить туда новую информацию (используя встроенный предикат assert ).

Соответствующее этим рассуждениям предложение:

m('4'):– 
       clearwindow, 
       write("Введите фамилию"),nl,
       readln(Name),
       write("Введите новый номер телефона"),nl,
       readln(Phone),
       retract(phone(Name,_)), 
                    /* удаляем устаревшую информацию 
                       из внутренней базы данных */
       assert(phone(Name,Phone)), 
                    /* добавляем новую информацию 
       в телефонную базу */
       menu. /* вызываем меню */

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

Запишем это предложение:

m('5'):– 
       write("Укажите номер телефона, запись о котором 
       нужно удалить из телефонной базы"), nl, 
       readln(Phone), 
       retract(phone(_,Phone)), 
                     /* удаляем соответствующий факт 
                        из внутренней базы данных */
       menu. /* вызываем меню */

Приведем полный текст программы.

DOMAINS /* раздел описания доменов */
name, number = String /* фамилию абонента и телефонный 
                         номер будем хранить в виде 
                         строк */
file=f /* файловый домен будем использовать для 
          считывания с диска и записи на диск нашей 
          телефонной базы */
DATABASE /* раздел описания предикатов внутренней 
            базы данных */
phone(name, number)
PREDICATES /* раздел описания предикатов */
name_phone(name, number) /* этот предикат находит номер 
                            телефона по фамилии абонента */ 
phone_name(name, number) /* этот предикат находит фамилию 
                            абонента по номеру телефона */ 
m(char) /* этот предикат реализует выполнение 
           соответствующего пункта меню */
menu /* этот предикат реализует вывод меню и 
        обработку выбора пользователя */
start /* этот предикат проверяет наличие файла 
         с телефонной базой на диске и либо загружает 
         факты из нее во внутреннюю базу данных, 
         если такой файл существует, либо создает 
         этот файл, если его не было */
CLAUSES /* раздел описания предложений */
name_phone(Name,Phone):– 
                   phone(Name,Phone),!. 
name_phone(_,"Нет информации о телефонном номере"). 
                /* если	соответствующего факта 
                   во внутренней базе данных не нашлось, 
                   вместо телефонного номера возвращаем 
                   соответствующее сообщение */
phone_name(Name,Phone):– 
                      phone(Name,Phone).
phone_name("Нет информации о владельце телефона",_). 
                /* если соответствующего факта 
                   во внутренней базе данных не нашлось, 
                   вместо фамилии абонента возвращаем 
                   соответствующее сообщение */
menu:–
     clearwindow, /* очистка текущего окна */ 
     write("1– Получение телефонного номера 
     по фамилии "),nl,
     write("2 — Получение фамилии абонента по номеру 
     телефона "),nl,
     write("3 — Добавление новой записи в телефонную 
     базу."),nl, 
     write("4 — Изменение номера абонента"),nl, 
     write("5 — Удаление записи из телефонной базы"),nl,
     write("0 — Выйти"),nl,
     readchar(C), /* читаем символ с клавиатуры */ 
m(C). /* вызываем выполнение соответствующего пункта 
         меню */
m('1'):– 
       clearwindow, 
       write("Введите фамилию"), nl, 
       readln(Name),
       name_phone(Name, Phone), 
       write("Номер телефона: ",Phone), 
       readchar(_), 
menu.
m('2'):– 
       clearwindow, 
       write("Введите номер телефона"),nl,
       readln(Phone),
       phone_name(Name, Phone),
       write("Фамилия абонента: ",Name),
       readchar(_),
       menu.
m('3'):– 
       clearwindow, 
       write("Введите фамилию"),nl,
       readln(Name),
       write("Введите номер телефона"),nl,
       readln(Phone),
       assert(phone(Name,Phone)), 
                         /* добавляем факт во внутреннюю 
                            базу данных */
       menu.
m('4'):– 
       clearwindow, 
       write("Введите фамилию"),nl,
       readln(Name),
       write("Введите новый номер телефона"),nl,
       readln(Phone),
       retract(phone(Name,_)), 
                          /* удаляем устаревшую информацию 
                             из внутренней базы данных */
       assert(phone(Name,Phone)), 
                          /* добавляем новую информацию 
                             в телефонную базу */
       menu.
m('5'):– 
       clearwindow, 
       write("Укажите номер телефона, запись о котором 
       нужно удалить из телефонной базы"), nl, 
       readln(Phone), 
       retract(phone(_,Phone)), /* удаляем соответствующий 
                                   факт из внутренней базы 
                                   данных */
       menu.
m('0'):– 
save("phones.ddb "), /* сохраняем телефонную базу 
                        в файл */
retractall(_)./* удаляем все факты из внутренней 
                 базы данных */
m(_):– 
       menu. /* если пользователь по ошибке нажал клавишу, 
                отличную от тех, реакция на которые 
                предусмотрена, ничего плохого 
                не произойдет, будет отображено меню 
                еще раз */
start:–
       existfile("phones.ddb"),!, /* если файл с телефонной 
                                     базой существует */
       consult("phones.ddb "), /* загружаем факты во 
                                  внутреннюю базу данных */
       menu. /* вызываем меню */
start:–
       openwrite(f,"phones.ddb"), 
                          /* если файла с телефонной 
                             базой не существует, создаем 
                             его */
       closefile(f),
       menu. /* вызываем меню */
GOAL /* раздел внутренней цели*/
Start
Листинг 13.1. Программа, реализующая компьютерный вариант телефонного справочника.
< Лекция 12 || Лекция 13: 1234 || Лекция 14 >
Виктор Бондарь
Виктор Бондарь

После приведения формулы вида ПНФ к виду ССФ вы получаете формулу, в безквантовой матрице которой дизъюнкт содержит оба контранрных атома:. Как тогда проводить его унификацию, если в случае замены x на f(x) весь дизъюнкт обратится в единицу?

Ольга Потапенко
Ольга Потапенко

никак не могу увидеть тексты самих лекций.