Краткие теоретические сведения. file = textfile или file = my_file
1. Концепция работы с файлами Турбо Пролог поддерживает работы с файлами, а также работу с внутренней и внешней базами данных. Одновременно в системе можно производить операции с двумя файлами (устройствами): одним входным и одним выходным. Файлы объявляются в секции domains следующим образом: domains file = name _file Например: domains file = textfile или file = my_file В системе имеются предопределенные файлы с именами: keyboard (клавиатура), printer (устройство печати), com1 (коммуникационный порт), screen (экран), stdin (стандартное устройство ввода), stdout (стандартное устройство вывода), stderr (стандартное устройство для сообщений об ошибках). По умолчанию stdin и stdout открыты и назначены соответственно на keyboad и screen. Набор предикатов для ввода ориентирован на простые типы данных и включает в себя: 1) предикаты для работы с клавиатуры: – inkey(Символ) (сhar): прототип (o) - читает символ со стандартного устройства ввода, если он доступен, иначе inkey считается невычисленным (fail). Например: сlauses ready(X):-inkey(Y),X=Y,!. При трассировке предикатов с inkey рекомендуется с помощью клавиш Alt-T установить Edit window в режим Off. – keypressed – проверяет была ли нажата какая-либо клавиша на клавиатуре, если не была, то fail. 2) предикаты ввода данных: – readln(Строка) (string), (o) - читает строку с текущего устройства ввода и связывает ее с заданной переменной. Например: readln(S) – readterm(Область,Терм) (Name,Variable), (i,о) - читает объект, который был записан предикатом write. С помощью readterm осуществляется доступ к фактам в файле. Например: domains person=p(name,surname,height) clauses readterm(person,p(N,S,H)) Файл, открытый при помощи предикатов openread и readdevice, содержит: p("Seep","Maier",195) Соответственно: N = Seep S = Maier H = 195. – readint(Целочисленная_переменная) (integer), (o) - читает целое число с текущего устройства вывода и связывает его с заданной переменной.
– readreal(Переменная_вещественного_типа) (real), (o) - читает действительное число с текущего устройства ввода и связывает его с заданной переменной. – readchar(Символьная_Переменная) (char), (o) - читает символ с текущего устройства ввода и связывает его с заданной переменной. В отличие от inkey устанавливает режим ожидания ввода. –file_str(ИмяФайлаDOS,Строка) (string,string), (i,o) - читает строку из заданного файла и связывает ее с параметром "Строка". Максимально допустимый размер строки - 64 К. Признаком конца строки является символ Ctrl -Z (десятичный код ASCII = 26). Например: file_str("B:TEXT1",X) 3) предикаты вывода данных: – write(А1,А2,А3,…) (А1,А2,А3,… - константы или переменные), (i) - записывает заданные значения на текущее устройство вывода. Наряду с константами и переменными может использоваться также и обратный слэш. Он встречается в следующих комбинациях: \n – выдается пробел; \t – происходит переход к следующей позиции табуляции; \номер – код ASCII выдаваемого символа. Например: write(“введенное имя”,name) – на экране, который обычно является текущим устройством вывода, появляется текст: “введенное имя максим”, если переменная name связана со строкой “максим” – nl - выводит пустую строку – writef(Формат, А1,А2,А3,…) (i) – предикат форматного вывода данных. В строке формат после знака процента используются следующие ключи: % g числа с плавающей точкой в наиболее компактном формате (по умолчанию). % e числа с плавающей точкой в экспоненциальной форме. % f числа с плавающей точкой в формате с фиксированной точкой. Например: writef(²%5.2²,X) – результат 2.80, если X=2.8. При работе с дисковым файлом его сначала следует открыть с указанием типа выполняемых затем действий: чтения, записи, добавления текста в конец файла или модификации содержимого файла. Это делается с помощью следующих предикатов:
– openread(Символическое_имя_файла, Имя_файла_в_DOS) (file, string), прототип (i,i) – открывает файл для чтения. Например: openread(td,²C:text.dat²) – файл DOS text.dat на устройстве С будет открыт для чтения под именем td. – openwrite (Символическое_имя_файла, Имя_файла_в_DOS) (file, string), прототип (i,i) – открывает файл для записи. Например: openwrite(users,²B:us.dat²) – файл DOS us.dat на устройстве B будет открыт для записи под именем users. – openappend(Символическое_имя_файла, Имя_файла_в_DOS) (file, string), прототип (i,i) – открывает файл для дополнения. Например: openappend(persons,²B:person.txt²) – файл DOS person.txt на устройстве B будет открыт для дополнения под именем persons. – openmodify(Символическое_имя_файла, Имя_файла_в_DOS) (file, string), прототип (i,i) – открывает файл для модификации (как для чтения, так и для записи). Например: openmodify(addr,²A:ADDRESSES²) – файл DOS ADDRESSES на устройстве A будет открыт для чтения или записи под именем addr. Если в предикате openwrite задано имя файла уже существующего на диске, то после выполнения openwrite содержимое этого файла будет стерто. Проверить наличие на диске указанного файла, особенно если файл открывается не для записи, можно до выполнения операции его открытия с помощью предиката – existfile(Имя_файла_в_DOS) (string), прототип (i) – выполняется успешно, если заданный файл присутствует в текущем каталоге, и завершается неудачно в противном случае. Одновременно может быть открыто несколько файлов, но только два их них могут являться текущими файлами (устройствами) ввода и вывода, которые объявляются предикатами: – readdevice(Имя_файла) (symbol): прототип (i) – присваивает текущему устройству вводимое заданное символическое имя файла; протопит (o) – связывает с параметром ²Имя_файла² символическое имя файла текущего устройства ввода. Например: readdevice(adr) – последующие команды чтения осуществляют чтение из файла adr. readdevice(X) – результат Х=keyboard. – writedevice(Символическое_имя_файла) (symbol): прототип (i) - ставит в соответствие текущему устройству вывода заданное символическое имя файла; протопит (o) – связывает с параметром имя текущего устройства вывода. Например: writedevice(addresses) – последующие команды записи могут использовать символическое имя файла addresses; writedevice(X) – результат X= addresses.
По умолчанию файлы считаются текстовыми, однако установив режим работы с файлом можно работать с ним как с двоичным, однако при этом следует использовать только посимвольный ввод. – filemode(Символическое_имя_файла, Тип Файла) (file,integer): прототип (i,i) режим: 0 – текстовый файл, 1 –двоичный файл – устанавливает тип заданного файла; прототип (i,o) – читает тип заданного файла и связывает его с параметром ²Тип файла². Например: filemode(users,0) – тип файла users устанавливается как текстовый; filemode(users,Х) – результат Х=0, если файл users – текстовый. По завершению работы с файлом его следует закрыть: – closefile(Символическое_имя_файла) (file): прототип (i) – имя файла не должно быть заключено в кавычки. Выполняется успешно, даже если файл перед этим не был открыт. Например: domains file = textfile goal openread(textfile, "goo.txt"), readdevice(textfile), readln(Str),write(Str),closefile(textfile). Файлы на диске из программы могут быть переименованы или удалены: – renamefile(Старое_DOS_имя, Новое_DOS_имя) (string,string), (i,i) – deletefile(Имя_файла_в_DOS) (string),(i). К вспомогательным предикатам относятся: – filepos(Символическое_имя_файла, Позиция_в_файле, Режим) (file,real,integer) - устанавливает указатель данного файла на заданную позицию. Режим 0 = относительно начала файла; 1 = относительно текущего положения указателя; 2 = относительно конца файла. Например: filepos(abc,10,0) – устанавливает указатель в файле abc на десятом байте. – eof(Символическое_имя_файла) (file),(i) – выполняется успешно, если указатель текущей позиции файла указывает на конец файла, и завершается неудачно в противном случае. – flush(Символическое_имя_файла) (file), (i) – содержимое внутреннего файлового буфера пересылается в заданный файл. – disk(DosPath) /* (string): прототип (i) – устанавливает путь и накопитель; (o) – связывает с параметром текущий накопитель и путь. Например: disk(²C:\Prolog²) – на накопителе С будет установлен путь \Prolog. disk(Х) – результат X = C:\Prolog\Bin\qwer. 2. Внутренняя база данных Турбо Пролог поддерживает работу с внутренней (ВБД) и внешней (дисковой - ДБД) базами данных, а также работу с дополнительной оперативной памятью (EMS ОЗУ).
ВБД состоит из фактов, которые добавляются/удаляются и существуют в ОЗУ только во время работы программы. Однако, их можно сохранить на диске. Для работы с ВБД Турбо Пролог использует следующие встроенные предикаты [1]: – assert(факт) – заносит факт в базу данных перед другими фактами. В результате данный факт будет добавлен в начало базы данных. Факт должен быть термом, принадлежащим домену dbasedom. – asserta(факт) - добавляет факты в ВБД перед существующими фактами. – assertz(факт) - добавляет факты в ВБД после существующих фактов – retract(факт) - удаление существующего факта из ВБД – retractall(факт) - удаление существующих фактов из ВБД – consult(имя_файла) – записывает в базу данных текстовый файл, который может быть создан в результате выполнения предиката save. Этот файл содержит факты, которые должны быть описаны в разделе database. Выполнение предиката consult не будет успешным, если в файле имеются синтаксические ошибки. – save(имя_файла) - сохранение ВБД в файле или на жесткий диск. Эти предикаты могут иметь один или два аргумента. Второй аргумент является необязательным и обозначает имя ВБД. Факты в ВБД хранятся в виде таблицы, которую легко модифицировать. В ВБД можно добавлять факты, но не правила. В фактах ВБД не может быть свободных переменных. Если ВБД не дано имя, то ей будет присвоено имя dbasedom.dba. Пример программы с использованием внутренней базы данных: domains database base(integer,string,integer) predicates write_base(integer) ch_base(integer) clauses write_base(N):-base(N,Name,Group), write("Номер ",N),nl, write("Фамилия ",Name),nl, write("Группа ",Group),nl, write("----------------"),nl. ch_base(N):-write("Фамилия:"),readln(S),write("Группа"),readint(S1), retract(base(N,_,_)),assert(base(N,S,S1)). goal consult("dd.dba"), write("Изменить запись.Номер-"), readint(N), write_base(N), ch_base(N), save("dd.dba"). 3. Внешняя база данных Внешняя база данных создается в случае, если объем данных больше объема свободной части ОЗУ или предполагается значительное расширение БД. ДБД состоит из двух компонент: элементов данных (термы Турбо Пролога) и цепочек (chain), в которых хранятся термы. В цепочке может храниться неограниченное количество термов. ВДБД может быть любое число цепочек. Цепочка выбирается по имени. Имя цепочки – это просто строка символов. Для быстрого поиска данных цепочка может быть индексирована методом В+дерева [1]. ДБД может быть расположена:
Имена предикатов, работающих с ДБД, построены следующим образом: db_ <тип объекта данных><операция>.
Например: db_term_delete. Если имя объекта не указано подразумевается вся база данных. Объявление имени ДБД: domains db_selector = имя_базы1, имя_базы2,... Ссылка на ДБД осуществляется по ее имени. 3. 1. Предикаты для работы со всей ДБД. – db_create(имя_базы, имя_файла, расположение), (i,i,i) – создание новой ДБД: Например: db_create(db_name, "F.TXT", in_file) db_create(db_mark, "marks", in_memory) – db_open(имя_базы, имя_файла, расположение), (i,i,i) – открытие ранее созданной базы данных. – db_copy(Имя_базы, имя_файла, Новое_расположение), (i,i,i) – перемещение бызы данных в другое место (например, из файла в ОЗУ или наоборот. – db_close(Имя_базы), (i) – в конце работы ДБД должна быть закрыта. – db_delete(Имя_базы), (i) – ДБД можно удалить. 3.2. Предикаты для работы с цепочками Цепочки [3] ДБД аналогичны внутренней базе данных. Цепочки, в некотором смысле, можно отожествить с записями в обычной реляционной СУБД. Они хранят данные в форме термов Пролога (т.е. в виде сложных объектов: списков, структур; или значений простых типов данных). ДБД может хранить любые допустимые в Турбо – Прологе типы термов. Цепочки термов запоминаются последовательно и одновременно доступна только одна цепочка. Каждая цепочка имеет собственное имя. Имя цепочки нигде специально не объявляется, цепочка создается, когда ее имя впервые встретилось в предикатах записи фактов в ДБД. Поэтому в именах цепочек не следует допускать опечаток, иначе можно создать ненужную цепочку и таким образом "потерять данные". Следующие предиката служат для работы с цепочками в ДБД: – chain_inserta(X,W,S,T,_) – вставляет терм в начало базы; – chain_insertz(X,W,S,T,_) – вставляет терм в конец базы; – db_chains(X,C) – создает ссылку на цепь; – chain_first(X,C,R) – позиционирует указатель на первый элемент цепи; – ref_term(X,S,R,TERM) – возвращает терм на который указывает указатель; – chain_next(X,R,NEXT) – возвращает указатель на следующий терм, где X – селектор базы описывается в DOMAINS как DB_SELECTOR = mydba Y – имя базы по стандарту ДОС в кавычках Z – место расположения базы (в памяти или в виде файла) W – описатель цепи S – описатель структуры файла базы данных T – терм _ – необъязательная переменная возвращающая код ошибки если она есть C – ссылка на описатель цепи R – положение указателя в цепи TERM – переменная конкретизированная термом на котором находится указатель NEXT – переменная конкретизированная указателем на следующий терм dbman – описатель структуры файла базы данных 4. Индексация цепочек методом В+дерева. При добавлении термов с использованием для индексации В+дерева с каждым ссылочным числом связан ключ. Так как это число ссылается на уникальную запись (вход) БД, нахождение правильного ключа быстро приводит к искомой записи данных. В+дерево (индексная цепочка) создается с помощью предиката: – bt_create(Имя_ДБД, Имя_В+дерева, Селектор_В+дерева, Длина_Ключа, Длина_Узла), так как информация В+дерева хранится в том же файле ДБД, что и индексируемая цепочка, то необходимо указывать "Имя_ДБД" базы, в которой находится эта цепочка. "Имя_В+дерева" - это имя, которое ему дает пользователь; оно является строкой. Третий аргумент является выходным, он относится к специальному встроенному простому типу bt_selector и используется в ряде других предикатов для идентификации созданного В+дерева. "Длина ключа" - длина самого длинного ключа по которому осуществляется поиск записи. Однако не следует злоупотреблять этим аргументом, так как хранение слишком длинных ключей в большой ДБД может потребовать значительного объема дисковой памяти. В+дерево разбито на отдельные страницы или узлы. Каждый узел В+дерева является либо последним, либо порождает два нижележащих узла. Каждый узел содержит группу ключей из заданного диапазона. Так как никакие два узла не содержат одинаковые значения ключей, то можно быстро проверить не находится ли искомый ключ внутри диапазона конкретного узла. Если да, то быстро находится ссылочное число, если ключ меньше, то поиск ведется по левой ветви В+дерева, если больше - по правой. Аргумент "Длина_Узла" в bt_create определяет сколько ключей запоминается в каждом узле В+дерева. Для баз данных среднего размера рекомендуется "Длина_Узла" = 4. Как и цепочки ДБД, В+деревья могут быть закрыты и снова открыты с помощью предикатов: bt_open() и bt_close(). Чтобы В+дерево было правильно сохранено, оно должно закрываться до закрытия соответствующего файла базы данных. Как и с ДБД В+дерево может быть модифицировано удалением или добавлением ключей. При индексировании ключи автоматически сохраняются системой. Для модификации используются два предиката: key_insert() и key_delete() Для поиска по заданному ссылочному номеру следует использовать предикат key_search(), если заданный ключ не найден, возникает ситуация fail. Если существует 2 одинаковых ключа, то возвращается первый найденный. Чтобы найти следующий (предыдущий) нужно применить, соответственно, предикат key_next() или key_prev(). Полный список предикатов для работы с внутренней и внешней базами данных можно получить в процессе работы нажав клавишу F1. Они находятся в файле PROLOG.HLP. Примеры программ для работы с ДБД: 1) domains db_selector = mmm predicates count_dba(integer) count(REF,INTEGER,INTEGER) clauses count_dba(N):- chain_first(mmm,name,REF),count(REF,1,N). count(REF,N,N):-ref_term(mmm,string,REF,S),write(S). count(REF,N,N2):-chain_next(mmm,REF,NEXT),!,N1=N+1, count(NEXT,N1,N2). goal db_create(mmm, "aaaa.ile", in_file), db_statistics(mmm,_,_,_,_), write("\nБаза имен.\n"), write("Введите номер не больше 8"), readint(N), chain_inserta(mmm,name,string,"ДМИТРИЙ",_), chain_insertz(mmm,name,string,"АЛЕКСЕЙ",_), chain_insertz(mmm,name,string,"МАКСИМ",_), count_dba(N), db_close(mmm).
2) domains db_selector = mydba dbman = person(firstname,age,city) firstname,city = srting age = integer predicates rd(ref) clauses rd(REF):-ref_term(mydba,dbman,REF,TERM),write(TERM),nl,fail. rd(REF):-chain_next(mydba,REF,NEXT),!,rd(NEXT). rd(_). goal clearwindow, db_create(mydba,"dd.bin",in_file), db_close(mydba), db_open(mydba,"dd.bin",in_file), chain_inserta(mydba,mychain,dbman,person ("Унру Артур Яковлевич",21,"Комсомольск-на-Амуре"),_), chain_insertz(mydba,mychain,dbman,person ("Смирнов Николай Семенович",20,"Благовещенск"),_), db_chains(mydba,CHAIN), chain_first(mydba,CHAIN,REF), rd(REF),readchar(_), db_delete("dd.bin",in_file).
Воспользуйтесь поиском по сайту: ©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...
|