Ответ в теме: База данных – владельцы бытовой техники

      Комментарии к записи Ответ в теме: База данных – владельцы бытовой техники отключены
#2588

Вам нужно сначала описать типы данных, например – владельца можно задавать именем (строковый тип), а цену – дробным числом. При этом вид бытовой техники представляет собой составной тип данных, а т.к. у одного владельца может быть несколько видов техники – то потребуется тип данных для списка техники:

domains
  brand_d = string
  year_d = integer
  cost_d = real
  country_d = string
  appliance_d = appilance(brand_d, year_d, cost_d, country_d)
  appliances_d = appliance_d*
  owner_d = string

Связь владельцев с видами техники происходит в базе данных – запись БД хранит имя владельца и список техники:

database owner_db
  nondeterm owner(owner_d, appliances_d)

Нам потребуется несколько вспомогательных предикатов:

  1. read_appilance выполняет ввод данных о виде техники:
      read_appilance(appilance(Brand, Year, Cost, Country)):-
      	write("Brand: "), readln(Brand),
      	write("Year: "), readint(Year),
      	write("Cost: "), readreal(Cost),
      	write("Country: "), readln(Country).

  2. length определяет длину списка;
  3. add_owner проверяет наличие владельца с заданным именем в базе и при его отсутствии – добавляет в БД нового владельца с пустым списком техники:

      add_owner(Owner):-
      	owner(Owner, _Appliances), !;
      	assert(owner(Owner, [])).

  4. can_add_appliance – проверяет возможность добавления техники заданному владельцу при этом проверяет наличие владельца и длину списка принадлежащей ему техники:
      can_add_appliance(Owner):-
      	owner(Owner, Appliances), 
      	length(Appliances, AppliancesLength),
      	AppliancesLength < 5, !;
      	owner(Owner, _Appliances), !,
      	write("this owner already has 5 appliances\n"), !, fail;
      	write("such owner not exist\n"), !, fail.

Теперь реализуем меню, позволяющее:

  • выйти из программы;
  • вывести содержимое БД;
  • добавить владельца;
  • добавить вид техники владельцу.

Первое правило меню выводит список пункта, запрашивает целое число (номер пункта), вызывает обработчик, соответствующий этому номеру если он не равен нулю (таким образом реализовано завершение работы программы).

Для вывода БД на экран программа обращается к факту owner, выводит его аргументы и выполняет fail, тем самым запуская механизм поиска с возвратами. В результате все факты БД будут выведены на экран, после чего обращение к БД завершится неудачей управление будет передано коду, записанному после логического ИЛИ (точки с запятой). Этот код рекурсивно запускает функцию menu для запроса следующего действия у пользователя (таким же образом работают все остальные пункты меню).

При добавлении нового владельца программа вызывает предикат add_owner, а при добавлении техники – сначала can_add_appliance, а затем выполняет ввод информации о технике и ее добавление в БД. При добавлении в базу техники необходимо удалить старую запись при помощи retract, а затем добавить новую с увеличенным списком при помощи assert. Читать подробнее про assert и retract.

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

  menu(0):-
  	write("\t0 - exit\n"),
  	write("\t1 - dump database\n"),
  	write("\t2 - add owner\n"),
  	write("\t3 - add owner appliance\n"),
  	write(": "), readint(MenuPoint), 
  	MenuPoint <> 0, !, menu(MenuPoint); !.
  menu(1):-
  	owner(Owner, Appliances),
  	write(Owner), write(" -> "), write(Appliances), nl, fail; 
  	menu(0), !.
  menu(2):-
  	write("enter owner's name: "),
  	readln(Owner),
  	add_owner(Owner),
  	menu(0), !.
  menu(3):-
  	write("enter owner's name: "),
  	readln(Owner),
  	can_add_appliance(Owner), 
  	read_appilance(Appliance),
  	retract(owner(Owner, Appliances)),
  	assert(owner(Owner, [Appliance|Appliances])),
  	menu(0), !;
  	write("such owner not exist\n"), menu(0), !.
  menu(_):-
  	write("wrong menu point\n"),
  	menu(0).