Мегаобучалка Главная | О нас | Обратная связь


Краткие теоретические сведения. 2.1 Структуры Пролога



2015-12-04 387 Обсуждений (0)
Краткие теоретические сведения. 2.1 Структуры Пролога 0.00 из 5.00 0 оценок




2.1 Структуры Пролога

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

Структуры - это объекты, которые состоят из нескольких компонент, возможно разных типов.

Этими компонентами могут быть константы, переменные и, в свою очередь структуры.

Определение, которое использует внутри себя определяемое понятие называется рекурсивным. Таким образом, структура есть рекурсивный тип данных.

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

Например:

date(1, "май", 1996) - определяет дату 1 мая 1996 года;

date(X, Y, 1996) - определяет произвольный день 1996 года;

person(fam("Иванов", "Петр", 'Сергеевич".), "г. Уфа, ул. Ленина, дом 100, кв. 25", "50-49-01") .

/*определяет сложный объект сведения о человеке: имя лица, адрес, домашний телефон, где имя, в свою очередь, является структурой содержащий три компоненты: фамилию, имя, отчество.*/

Последний пример - пример вложенной структуры, когда одна из компонент структуры является структурой. Это первый уровень вложенности. Если вложенная структура имеет компоненту, которая, в свою очередь, является структурой, то это будет второй уровень вложенности и так далее. Количество уровней вложенности в языке Пролог не оговаривается.

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

2.2 Описание структур в Турбо-Прологе

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

Например:

domains

data=date(day, month, year)

month=string

day, year = integer

person=person(name, address, telno)

address, telno=string

name=(string, string, string)

Введенные имена домен структур используются далее в программе при описании предикатов, имеющих в качестве аргументов эти структуры. Имя домена и функтор могут - совпадать (person). Турбо-Пролог различают их из контекста.

 

2.3 Альтернативные домены

В общем случае описание типов структур в Турбо-Прологе выглядит следующим образом:

<domain>=<alternative1>(D11, D12...); <alternative2>(D21, D22);

где domain — имя типа /имя домена/

alternative1 и alternative2 — равноправные, но различные функторы

(D11, D12...) и (D21, D22) — список типов компонент структур (типы стандартные и определяемые пользователем)

Каждая альтернатива включает функтор и, возможно, список областей для соответствующих компонент. Альтернативные домены позволяют вводить общее имя типа данных для структур с разными именами (функторами) Это дает возможность определить единый предикат, обрабатывающий эти разнородные структуры. В случае отсутствия такой возможности пришлось бы определять свои предикаты обработки структур -для каждой альтернативы.

 

2.4 Встроенные предикаты ввода/вывода и некоторые другие

Турбо-Пролог обладает достаточно широкой библиотекой встроенных предикатов, обеспечивающих ввод и вывод данных.

- readln(X)

Переменная Х - строковая или символьная, должна быть свободной перед выполнением предиката. Вводимая строка должна заканчиваться нажатием клавиши Enter.

- readint(X)

Переменная Х должна быть целой. Символы вводятся до нажатия клавиши Enter.

Если вводимая строка не соответствует целому числу, то выполнение предиката readint прерывается и вырабатывается ошибка.

- readreal(X).

Переменная Х должна, быть вещественной. Символы вводятся до нажатия клавиши Enter. Если вводимая строка не соответствует синтаксису вещественного числа, то возникает ошибка.

- readchar(Х).

Переменная Х должна быть символьной Предикат readchar считывает отдельный символ с текущего устройства ввода.

- file_str(X).

Переменные F и Х являются строковыми, F - имя файла в DОS, Х - свободная переменная. Предикат file_str читает данные из файла, пока не будет введен символ конца строки файла ([Ctrl]+[Z]). Содержимое файла F пересылается в Х. Считываемый файл не должен превышать 64 Кб.

- readterm(D, Т)

Используется для чтения объектов, относящихся к определенному в программе домену D. Т - свободная переменная, которая получает вводимые значения

- write(Arg1, Arg2...).

Аргументами Arg1, Arg2,... Могут быть как константы, так и переменные. Предикат осуществляет вывод значений аргументов на текущее записывающее устройство (по умолчанию - экран).

- nl

Предикат осуществляет переход на новую строку на текущем записывающем устройстве.

- findall(X, P(...Х...),L)

Х - переменная и является одним из аргументов предиката Р, когда он может быть выполнен успешно.

-writef("string",Arg1,Arg2,...).

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

%[-]m[.p][type] или %[[-]m[.p]type]

где квадратные скобки означают, что соответствующая компонента может отсутствовать;

m -целое, определяющее минимальную ширину поля, отводимого под значение.

Если размер поля недостаточен, то отводится столько, сколько необходимо,

'дефис'- выравнивание выводимого значения на левую границу поля;

p - целое, определяющее количество знаков после запятой у вещественных значений;

type - тип выводимого значения, может иметь вид:

d - вывод в десятичном представлении значений типа char и integer,

х - вывод в шестнадцатеричном представлении значений типа char и: integer.

u - вывод в беззнаковом десятичном представлении значений типа char и integer;

c - вывод в виде символа значений типа char и integer;

s - вывод в строковом виде значений типа symbol и string;

f - вывод вещественных значений в форме с фиксированной точкой;

е - вывод вещественных значений в экспоненциальной форме;

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

Строка "string" может содержать управляющие символы:

\n - переход на новую строку;

\t - знак табуляции (пропуск определенного числа позиций);

\nnn - вывод символа с кодом nnn;

fail - константа неуспех (ложь);

true - константа успех (истина);

not(p) - завершается успешно, если предикат Р представляет цель, который является невыполнимой, и наоборот.

 

2.5 Примеры обработки структур и организации ввода/вывода

2.5.1 Формирование списка структур

В программе в виде фактов info хранится информация о результатах тестирования ряда лиц. Тест содержал 11 вопросов. Порядок задания вопросов мог варьироваться. Тестируемый мог ответить на вопрос (верно или неверно) или не отвечать. Ответы на тест представлены в виде списка, содержащего 1, если ответ верен, и 0, если ответ неверен. У разных лиц списки могут бить различной длины: от пустого (не смог ответил ни на один вопрос) до списка, содержащего одиннадцать элементов. Информация: лицо и его ответы представлены в виде структуры. Требуется найти тех, кто ответил более чем на половину вопросов и сформировать из них список структур .

domains

test=t(name, result)

name=string

result=integer*

number=integer*

list=test*

predicates

info (number, test).

len(result).

р(test).

do(list).

clauses

info(1, t("tom",[1, 0, 1, 1, 0]).

info(2, t("bob",[])

info(3, t("ann",[0, 0, 1, 1, 1, 1, 0]).

p(t( _, X)):-info( _, t( _, X)), len(X, N), N>3.

len([], 0).

len([Н|Т], N):-len(T, N1), N=N1+1.

dо(L):- findall(X, р(X), L).

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

 

2.5.2 Предикат управлении курсором

В приведенной программе вводятся функторы для обозначения различных горизонтальных и вертикальных перемещений курсора по экрану. В примере используется встроенный предикат управления курсором cursor(Row, Column), который перемещает курсор в позицию (Row - строка, Column - столбец) экрана. Если Row и Column свободные переменные, то они получают значение текущей позиции курсора.

domains

step =integer

movement =up(step); down(step); left(step); right(step); nо

predicates

move cursor(movement).

clauses

move_cursor(up(step)):-.cursor(R, C), R1=R-step, cursor(R1, С).

move_cursor(down(step)):-cursor(R, С), R1=R+stер, cursor(R1, С).

move_cursor(left(step)):-cursor(R, С), C1=C-step, cursor(R, C1).

move_cursor(up(step)):-cursor(R, С), С1=С+stер, cursor(R1, C1).

move_cursor(nо):-cursor(R. С).

Функторы структур определяют направление перемещения курсора по экрану от его текущего положения uр - вверх, down-вниз, left - влево, right - вправо, nо - на месте. Величину перемещения определяет компонента структуры step-шаг.

С помощью домена movement (движение), описывающего различные виды перемещения курсора по экрану, вводится предикат move_cursor — переместить курсор, осуществляющий перемещение курсора на указанное число позиций step в указанном направлении (за счет выбора функтора ). Перемещение курсора выполняется следующим образом: определяется текущее положение курсора (cursor(R, C)), вычисляется новое положение курсора ((R1, C) или (R, С1)); производится перемещение курсора в новое положение (cursor(R1, С) или cursor(R, С1))

 

2.5.3 Пример ввода и вывода элементов списка

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

domains

list=integer*

predicates

input(list, list).

read(list, list).

loop(list, list).

print(list).

work.

clauses

work:-input([], L), nl, nl, write("Список L=", L), nl, nl,

write("Состоит из элементов:"), nl, print(L).

input(L, L2):-write("Введите элемент:"), read(L, L1),

write( "Будете еще вводить? (y/n):"), loop(L1,L2).

read(L[Х|L]):-readint(X),!

read(L, L).

loop(L, L):-readchar(Ch), Ch='n',!

loop(L1,L2):-nl, input(L1, L2).

print([X|L]):-write(X), nl, print(L)

print([]).

Предикат work осуществляет всю необходимую по условию задачи работу.

Предикат input(L1, L2) вводит данные и, включая их в исходный список L1 , формирует выходной список L2. Ввод элемента и включение его в список осуществляется оператором read. Если при вводе элемента произошла ошибка то исходный список сохраняется. Предикат input после ввода каждого элемента спрашивает о продолжении ввода. Если ввод окончен, то необходимо нажать клавишу 'n'. Анализ введенного символа и выбор последующих действий осуществляет оператор loop. Предикат print осуществляет поэлементный вывод списка.

 

2.5.4 Пример ввода структурных данных и их обработка

Требуется ввести для ряда лиц данные в виде e структуры, содержащей имя и возраст, и подсчитать средний возраст.

domains

person=p(name, age)

name=string.

age,sum=integer

mean=real

predicates

readperson(person).

run(sum, sum, sum, sum).

do(mean).

clauses

readperson(p(Name, Age)):-write("Имя:" ), readln(Name)<

write("Возраст:" ), readint(Age).

run(S, N1, S2, N2):-write("Будете вводить? (у/и)"), readchar(Ch), nl,

Ch=' у ', !, readperson(p( _, А)),

S1=S+A, N1=N1+1, run(S1, N1, S2, N2).

run(S, S, N, N).

do(V):-run(0, S, 0,N), N<>0, !, nl, V=S/N.

do(0).

Предикат readperson осуществляет ввод данных, касающихся одного лица, формирует из них структуру р(Name, Age).

Предикат run спрашивает о наличии сходных данных. Для подтверждения необходимо нажать клавишу ' у '. В противном случае следует нажать любую другую клавишу, что приведет к прекращению ввода. При наличии исходных данных происходит их ввод с помощью предиката readperson. Введенный возраст (А) прибавляется к накапливаемой сумме возрастов: S - значение суммы до ввода текущего данного, S1- сумма после ввода и прибавления А к S, счетчик числа введенных данных увеличивается на единицу (N - количество данных до ввода, N1- после ввода).

В рассмотренном примере для ввода структуры вместо предиката readperson можно было бы воспользоваться встроенным предикатом readterm. Тогда изменение программы состояло бы в следующем: убрать из программы описание и определение предиката readperson; в предикате run заменить вызов readperson(р( _, А)) на readterm(person,р(_, А)); исходные данные набирать с указанием функтора (имени структуры), например p("Сергей", 18).

 



2015-12-04 387 Обсуждений (0)
Краткие теоретические сведения. 2.1 Структуры Пролога 0.00 из 5.00 0 оценок









Обсуждение в статье: Краткие теоретические сведения. 2.1 Структуры Пролога

Обсуждений еще не было, будьте первым... ↓↓↓

Отправить сообщение

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



©2015-2024 megaobuchalka.ru Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. (387)

Почему 1285321 студент выбрали МегаОбучалку...

Система поиска информации

Мобильная версия сайта

Удобная навигация

Нет шокирующей рекламы



(0.009 сек.)