- •Введение
- •1. Составление программ
- •1.1. Основные определения
- •1.2. Декларации в программах
- •1.3. Объявление предикатов и типов их аргументов
- •1.4. Другие разделы программы
- •Упражнения
- •2. Механизмы доказательства правил
- •2.1. Сопоставление с откатом
- •2.2. Рекурсия
- •Упражнения
- •3.Операции в Visual Prolog. Ввод-вывод
- •3.1. Операции
- •3.2. Предикаты ввода-вывода
- •4. Управление процессом доказательства правил
- •4.1. Искусственный откат
- •4.2. Отсечение
- •4.3. Повтор, определяемый пользователем
- •5. Списки
- •5.1. Процедуры обработки списков
- •5.2. Организация стеков и очередей
- •6. Внутренняя база фактов
- •7. Иерархическая организация данных
- •8. Работа с деревьями и графами
- •8.1. Двоичные деревья
- •8.2. Графы
- •9. Работа с именами и строками
- •Заключение
- •Библиографический список
- •Оглавление
9. Работа с именами и строками
Имена и строки в программах автоматически преобразуются друг в друга (компилятор VIP выдает предупреждение), и все предикаты, определенные для строки, могут быть применены и к символическим именам. Доступ к именам осуществляется быстрее, чем к строкам, обработка которых ведется посимвольно.
Ниже мы рассмотрим наиболее часто используемые встроенные предикаты для работы с именами и строками, имеющимися в Visual Prolog 5.1.
1.Предикаты преобразования типов из string в другие встроенные и наоборот.
str_int(String, Int) /* (i, o), (o, i), (i, i)*/
преобразует строку String, содержащую целое число, в целое число Int; например,
GOAL
str_ int ("123", X).
X=123
GOAL
str_int (“asd”, X) .
No solution
б) str_char(String, Char) /* (i, o), (o, i), (i, i) */
преобразует строку из одного символа в символ.
в) str_real(String, Real) преобразует строку, содержащую вещественное число, в вещественное число.
str_real ("12.3", 12.3)
2. Предикат frontchar/З используется для выделения первого символа строки:
frontchar(Строка, Символ, Остаток) /* (i,o,o) (i,i,o) (i,o,i) (i,i,i) (o,i,i) */
Предикат связывает три параметра: первый символ Строка заносится в Символ, оставшаяся часть – в Остаток. Согласно flow patterns предикат frontchar/З может использоваться для соединения строки и символа (о, i, i), разделения строки на символ и строку (i,o,o), для посимвольного просмотра и анализа строки и т. п.
3. Предикат fronttoken/З разделяет текст или строку Строка на первую лексему Слово и оставшуюся часть текста или строки Остаток, и имеет формат:
fronttoken(Строка, Слово, Остаток) /* (i,o,o) (i,i,o) (i,o,i) (i,i,i) (o,i,i) */
(Лексема - слово, знак препинания, число.)
Предикаты frontchar и fronttoken используются для организации рекурсии по схеме, аналогичной процедурам работы со списками: аргументом рекурсивного вызова является Остаток; вызовы повторяются до тех пор, пока Остаток не станет пустой строкой.
В качестве примера приведем программу, преобразующую заданную строку в список символов (процедура «строка_список») и в список лексем (процедура «строка_список_имен»).
DOMAINS
список1 = char* /* Список символов */
список 2 = symbol* /* Список имен */
PREDICATES
nondeterm строка_список (string, список1)
nondeterm строка_список_имен(string, список 2)
CLAUSES
строка_список ("",[ ]):-!. /* терминальный пре
дикат*/
строка_список(S,[H|T]) :-frontchar(S, H, S1),
строка_список (S1, T).
строка_список_имен ("", [ ]):-!./* терминальный
предикат*/
строка_список_имен(S,[H|T]):-fronttoken(S, H,
SI), строка_список_имен (SI, T).
GOAL
Y="Языки Lisp и Prolog",
строка_список(Y, X), write(X),
строка_список_имен (Y, Z), write(Z).
X=['Я','з','ы','к','и',' ', 'L','i','s','p',' ','и','P','r','o','l','o','g'],
Z=["Языки","Lisp","и","Prolog"]
Ниже приведена программа, распознающая в заданном тексте лексемы, символы и числа и возвращающая соответствующий список с элементами различных типов(см. разд. 7). Так, текст “Год рождения Иванова П. - 1990” будет преобразован в список
[name("Год"), name("рождения"), name("Иванова"), name("П"),
char('.'), char('-'), numb(1990)].
DOMAINS
лексема = numb(integer); name(string);
char(char) /* смешанный список */
список = лексема *
PREDICATES
nondeterm scanner(string, список)
nondeterm выделить (string, лексема)
CLAUSES
scanner("",[]). %терминальныйпредикат
scanner(Str,[H|Rest]):- fronttoken(Str, L, Str1), выделить(L, H), scanner(Str1, Rest).
выделить (S,name(S)):-isname(S).
/*Стандартный предикат isname проверяет, является ли аргумент строкой */
выделить (S,numb(N)):-str_int(S,N).
выделить (S,char(C)):-str_char(S, C).
GOAL
write("Введите текст:"),nl,
readln(Text),nl, scanner(Text,List),write(List).
4. Предикат concat/З соединяет две строки в одну String3:
concat(Stringl, String2, String3) /* (i,i,o) (i,o,i) (i,x,i) (o,i,i) */
GOAL
соnсаt("Моя", "внучка", String3).
String3="Моя внучка".
5. Предикат str_len/2 используется для определения длины строки или для создания строки пробелов заданной длины. Например, при доказательстве цели str_len("строка", Dlina) получим Dlina = 6, а для цели str_len(X, 3) результат X = " ".
6. Предикаты выделения части строки.
subchar(String, Position, Char) возвращает символ Char строки String, находящийся в заданной позиции Position;
substring(Str_in, Pos, Len, Str_out) копирует из строки Str_in подстроку Str_out, начиная с позиции Pos длиной Len.
GOAL
substring(“Прощай”, 4, 3, Str_out).
Str_out = "щай".
searchchar(String, Char, Position) возвращает позицию Position первого местонахождения символа Char в строке String.
7. Сравнение символов, строк и символических имен.
При сравнении символов происходит сравнение их кодов.
GOAL
'л' > 'т'
При сравнении строк последовательно сравниваются символы в соответствующих позициях. Как только найдены отличающиеся символы, так результат определяется по сравнению их кодов.
GOAL
"варежка" > "вареник"
Сравнение символических имен не может выполняться непосредственно. Сначала символические имена надо связать с переменными, а затем сравнивать последние. Пример успешного сравнения:
GOAL
PI = холод, Р2 = холодный, Р1 < Р2.
