Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Solomon.doc
Скачиваний:
17
Добавлен:
08.05.2019
Размер:
3.38 Mб
Скачать

Глава 6. Использование строк

Строка это набор символов. Например, слова и предложения,

которые вы сейчас читаете, это множество символов, являющихся

строками для компьютера. Термин "символ" включает буквы русско-

го (английского) алфавита, цифры, такие символы как +, @ и $, а

так же управляющие символы, соответствующие некоторым клавишам,

таким как Enter и Esc.

Фактически строки это наиболее распространенные объекты,

связанные с программированием. Примерами строк, используемых

при программировании, являются последовательности символов, ко-

торые вы набираете на клавиатуре для управления компьютером,

такие как DIR A:, команды управления программами, такие как

Print @25, и обрабатыавемые данные , такие как John Smith,

Boston MA.

Операции, обычно выполняемые над строками, включают:

- объединение строк для образования новой строки;

- расщепление строки для создания двух новых строк, каждая

из которых содержит некоторые из исходных символов;

- поиск символа или подстроки внутри данной строки.

Эти и другие операции со строками являются основными и

весьма важными при программировании на ПРОЛОГе.

Для удобства программистов Турбо-Пролог имеет несколько

встроенных предикатов, используемых при построении правил, ма-

нипулирующих строками. В этой главе вы будете иметь дело со

строками и строить правила для манипулирования ими.

6.1. Множество символов Турбо-Пролога

В компьютере символы представлены числами. Большая часть

персональных компьютеров, включая все IBM PC и совместимые с

ними машины, используют одну и туже систему числовых кодов, на-

зываемую Американским стандартным кодом для обмена информацией

(ASCII). Символы A, B и C , например, представлены числами 65,

66 и 67. Прописные буквы представлены числами, начинающимися с

32 и далее. Таким образом, a есть 97 (65+32).

Множество кодов ASCII включает следующие подгруппы:

- символы английского (и русского) алфавита (как строчные,

так и прописные);

- цифры от 0 до 9;

- специальные символы, такие как +, -, $, * и символы пун-

ктуации;

- управляющие символы, такие как Ctrl-C и Ctrl-Q.

В таблице 6.1 перечислены все символы ASCII, доступные для

использования в Турбо-Прологе.

6.2. Использование кодов ASCII для "записи" символов

При программировании на Турбо-Прологе символы могут быть

"записаны" при помощи их кодов ASCII. Обратный слэш (\), непос-

редственно за которым следует десятичный код ASCII (N) символа,

интерпретируется как символ. Для представления одиночного сим-

вола выражение \N должно быть заключено в одиночные кавычки

('\N'). Для представления строки символов их коды ASCII помеща-

ются друг за другом, и вся строка заключается в двойные кавычки

("\N\N\N").

В качестве примера рассмотрим символы A, B и C, десятичные

коды которых есть 65, 66 и 67. В Турбо-Прологе символ A с ис-

пользованием его ASCII кода записывается как '\65'. Представле-

ние в ASCII коде строки ABC есть "\65\66\67". Десятичная цифра

4 представляется в коде ASCII как '\52'. Десятичное число

436.375 записывается строкой Турбо-Пролога в коде ASCII как

"\52\51\54\46\51\55\53\".

В общем случае обратный слэш (\), непосредственно за ко-

торым следует код символа в ASCII, интерпретируется как этот

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

чены для управления процессом вывода на экран. Символ '\10'

есть символ окончания строки (line feed).

Программа ASCIIprint (листинг 6.1) иллюстрирует запись

символов при помощи их ASCII кодов. Результат работы программы

показан на рис.6.1.

6.3. Присваивание переменным строковых значений

Строка символов может быть присвоена переменной. Таким об-

разом, следующие присвавиания эквивалентны:

S = "\84\117\114\98\111\32\80\82\79\76\79\71\"

и

S = "Turbo PROLOG".

Представление символьных строк в коде ASCII весьма громоз-

дко и неудобно. Обычно более эффективно непосредственное алфа-

витно-цифровое представление. Однако представление символов и

строк в коде ASCII используется в машинно-ориентированных язы-

ках, таких как ассемблеры, а также при создании компиляторов,

операционных систем и контроллеров устройств связи. Это более

сложные вопросы, чем те, о которых вы узнаете в данной книге.

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

титься модули, в которых применяются обозначения в коде ASCII.

Листинг 6.1.

Таблица 6.1.

Рисунок 6.1.

Программа TeamPrint1 (листинг 6.2) использует операции

присваивания строк. Фиксированные строковые константы S1, S2,

S3, ... S9 объявлены в разделе доменов. Правило print_strings

включает десять предикатов присваивания строк, а так же десять

операторов ввода строк. Символ равенства (=) используется как

символ для обозначения отношения. Это обозначение является "ин-

фиксным" обозначением отношения. Результат работы программы по-

казан на рис.6.2.

В программе TeamPrint1 фиксированные строки размещены в

правиле, предназначенном для вывода их на печать. Однако сущес-

твует возможность размещать строки в одном правиле, а вызывать

и обрабатывать их в других правилах. Программа TeamPrint2 (лис-

тинг 6.3) иллюстрирует указанный способ обработки строк.

В этой программе правило data_strings содержит строки, а

правило print_strings выводит их на печать. Для того что бы пе-

редать строки из правила data_strings в правило print_strings

первое их них должно быть включено во второе. Кроме того, необ-

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

строк S1, S2, S3, ... S9 в списке объектов вызываемого правила.

Результаты работы программы TeamPrint1 и TeamPrint2 иден-

тичны. Описанный метод обработки строк приемлем, если число

строк невелико (менее 20). В противном случае процесс передачи

строк становится затруднительным.

Рисунок 6.2.

Листинг 6.3.

6.4.Длина строки

Длина строки измеряется полным числом символов в строке.

Турбо-Пролог имеет встроенный предикат str_len, который исполь-

зуется для нахождения длины строки. Синтаксис этого предиката

следующий:

srt_len(String_value, String_length).

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

srt_len("TODAY",L),

то она получит значение длины строки TODAY (сегодня). Этим зна-

чением будет целое число. Если же до начала выполнения вызова

предиката str_len обе его переменные уже означены, то предикат

будет успешным, только при условии, что значение String_length

равно длине строки String_value. Например, если S имеет значе-

ние ABC, а L имеет значение 3, то предикат str_len(S,L) успе-

шен. В противном случае он неуспешен.

Программа ShowLength1 (листинг 6.4) иллюстрирует использо-

вание внутренней цели для нахождения длины строки Turbo Prolog.

Результат показан на рис.6.3.

Листинг 6.4.

Программа ShowLength2 (листинг 6.5) демонстрирует простое

применение предиката str_len. Программа выводит длину объектов

утверждений базы данных. Правилом для нахождения длин строк яв-

ляется find_length. Это правило содержит lin(S), строку данных

str_len(S,L), где S имя строковой переменной, а L длина этой

строки и предикат write для выдачи длин строк.

Результат работы программы показан на рис.6.4. Числа в

скобках - это длины строк. Заметьте, что две "пустые" строки на

самом деле не пустые - каждая из них содержит 27 символов про-

бела.

Рисунок 6.3.

Листинг 6.5.

Рисунок 6.4.

* Упражнения

6.1. Модифицируйте программу ShowLength1 так, чтобы она

выдавала длины следующих строк:

"The father of an enemy of a friend of man owes that man

nothing".

"When I code without pressure of deadline, it's very

relaxing".

6.2. Модифицируйте программу ShowLength2, дополнив утверж-

дения базы данных утверждениями из вашего любимого стихотворе-

ния. Выполните программу.

6.5. Конкатенация строк

Конкатенация двух строк означает их объединение, то есть

образование одной новой строки. Например, результат конкатена-

ции двух строк

"one day"

"at a time"

может быть либо "one day at a time" или "at a time one day".

Эти две результирующие строки различны, так как образующие их

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

встроенный предикат concat, который выполняет соединение (кон-

катенацию) двух строк. Его синтаксис следующий:

concat(Input_string1, Input_string2, Output_String).

Объекты Input_string1 и Input_string2 являются двумя вход-

ными строками. Объект Output_string есть объединенная выходная

строка. Например

concat("TODAY", "TOMORROW", S).

означивает переменную S строкой "TODAYTOMORROW".

Программа Concat1 (листинг 6.6) демонстрирует применение

конкатенации строк. Эта программа использует внутреннюю цель.

Правило print_strings соединяет строки и выводит на печать ре-

зультат конкатенации. Результат работы программы показан на

рис.6.5.

Программа Concat2 (листинг 6.7) является модификацией

программы Concat1. В этой программе как входные, так и выходные

строки представлены переменными с односимвольными именами: R,

S, T, U, V, W, X, Y, Z, A, B, C. Эти переменные используются

как аргументы предиката concat. Данная форма использования пре-

диката конкатенации короче и удобнее в случае повторяющихся

операций конкатенации. Результаты работы программ Concat1 и

Concat2 идентичны.

Листинг 6.6.

Рисунок 6.5.

Листинг 6.7.

* Упражнения

6.3. Модифицируйте программу Concat1 так, чтобы она соеди-

няла следующие четыре строки, обрабатывая одновременно только

две из них:

1. "Logic puzzels me"

2. "Neither of us is old"

3. "What is difficult needs attention!"

4. "No riddles interest me if they can be solved"

Требуемый порядок соединения 1,2,3,4. Постройте строку

кратчайшим из возможных способов.

6.4. Измените программу Concat2 для соединения следующих

строк:

"Thunderstorms"

"very strong wind"

"heavy rainfalls"

"and"

"hailstorms"

"are"

"all"

"destructive."

В результате должно получиться предложение, сформированное

из этих строк в указанном порядке.

6.6.Создание подстрок

Подстрока это строка, являющаяся копией некоторой части

исходной строки. Например, двумя возможными подстроками строки

"Expert Systems" являются "Expert" и "Systems". Турбо-Пролог

имеет встроенный предикат frontstr, служащий для создания подс-

трок. Его синтаксис следующий:

fronsrt(Number, Source_string, Substring1, Substring2).

Аргумент Number задает полное число символов, которые дол-

жны быть скопированы в Substring1 из Source_String, являющейся

исходной строкой. Остальные символы строки Source_string будут

скопированы в Substring2. Например, утверждение

frontstr(6,"Expert systems", String1, String2).

присваивает String1 значение "Expert", а String2 значение

" systems". Заметьте, что число 6 соответствует полному числу

символов в "Expert".

Программа Substring (листинг 6.8) демонстрирует использо-

вание предиката frontstr. Программа находит две подстроки для

каждой входной строки. Например, первая входная строка есть

"Turbo Prolog is fast!", а предикат frontstr, применяемый для

ее обработки, имеет вид:

frontstr(12, "Turbo Prolog is fast!", R1, R2).

Правило print_strings выводит на печать две подстроки на

разные строчки экрана. Результат показан на рис.6.6.

Листинг 6.8.

Рисунок 6.6.

* Упражнение

6.5. Модифицируйте программу Substring так, чтобы она из

строк левого столбца генерировала подстроки , расположенные в

правом столбце:

Входная строка Подстроки

"LOTUS123" "LOTUS"

"123"

"Default Directory" "Default"

"Directory"

"Fifth Generation" "Fifth"

"Generation"

"Are they safe for my children?" "Are they safe"

"for my children?"

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

подстроки, расположенные в правом столбце, из заданных строк в

левом столбце:

Входная строка Выходные подстроки

"Tom Shallack is an "Tom Shallack"

account" "account"

"Juniper tar ia an "Juniper tar"

anti-itch treatment "anti-itch"

for skin disorders" "skin disorders"

6.7. Преобразование данных

Турбо-Пролог для преобразования данных из одного типа в

другой имеет следующие предикаты:

upper_lower

str_char

str_int

str_real

char_int.

Их применение целесообразно в случае, когда тип объектов

встроенного предиката отличается от типа объектов предиката,

определенного пользователем.

Например, предикат writef может вызвать разрушение систе-

мы, если ему будет передан объект типа char. Если символьная

переменная Drive_ltr_str означена символом 'a', то предикат

writef("The current drive is %:", Drive_ltr_str)

вызовет отказ системы.(Во время компиляции сообщения об ошибках

и предупреждения не выдаются). Данная проблема легко может быть

преодолена с помощью предикатов, указанных выше.

Например:

str_char(Drive_ltr_srt, Drive_ltr),

writef("The current drive is %:", Drive_letter).

Преобразования столь же необходимы, когда значение одного

типа должно быть присвоено переменной другого типа.

Все предикаты преобразования данных содержат два объекта.

Вы вероятно заметили, что имена предикатов показывают тип вы-

полняемого преобразования. Например, str_char преобразует стро-

ку, состоящую из одного символа и имеющую тип string, в значе-

ние типа char. Имена предикатов также указывают и порядок объ-

ектов. Например, объект типа string является первым объектом в

str_char, а объект типа char - вторым.

Эти предикаты имеют два направления преобразования данных.

Например, если переменная S1 уже означена и имеет значение

STARS AND STRIPES, то предикат

upper_low(S1,S2)

присваивает строку stars and stripes переменной S2. Но, если S2

означена, а S1 не означена, то значение STARS AND STRIPES полу-

чает переменная S1. В случае же, когда обе переменные означены,

предикат успешен, если одна из переменных имеет значение стро-

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

буквами.

Предикат str_char используется для преобразования объектов

типа string в объекты типа char. Предикат str_int используется

для преобразования строчного представления целых чисел в пере-

менные типа integer. Предикат str_real используется для преоб-

разования действительных чисел в строки. Предикат char_int ис-

пользуется для присвавиания числа (кода ASCII символа) данному

объекту.

Программа Coversions1 (листинг 6.9) содержит примеры пре-

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

бо-Пролога. Результат работы программы показан на рис.6.7.

Листинг 6.9.

Рисунок 6.7.

* Упражнение

6.6. Напишите программу для выполнения следующих преобра-

зований. Используйте внутренную цель.

1. upper_lower("PREDICATE LOGIC", L).

2. upper_lower(V, "expert systems").

3. upper_lower("LOTUS123", S).

4. upper_lower("Oral_Cavity", Q).

5. str_char("A", C8).

6. str_char("Z", C9).

7. char_int('Q', N6).

8. char_int('#', N9).

6.8. Преобразования, определяемые пользователем

Преобразования действительных чисел в целые или целых в

действительные весьма удобны при выполнении математических вы-

числений. Преобразования строк в символы удобны при подготовке

обработки данных и их записи во внешнюю память. В этом разделе

будет показано как строить правила для выполнения этих преобра-

зований.

Рассмотрим преобразование действительного числа в целое. В

этом примере целое значение, соответствующее действительному

числу 5432.765, есть 5432. Правило преобразования построено при

помощи символа равенства (=):

conv_real_int(R,N) :- R=N.

Здесь R это переменная для действительных чисел, а N - пе-

ременная для целых чисел.

Объявление в разделе predicates следующее:

conv_real_int(r,n).

Правило пытается вычислить значение R. Если текущее значе-

ние R действительное число, то правило успешно; в противном

случае правило завершается неуспешно. При успешном завершении

правила целая часть действительного числа присваивается цело-

численной переменной N. В Турбо-Прологе целые числа ограничены

диапазоном от -32768 до 32767, поэтому рассматриваемое правило

преобразования не будет работать, если значение действительного

числа меньше, чем -32768.0 или больше, чем 32767.0.

Правило для преобразования целого числа в действительное

следующее:

conv_int_real(N,R) :- N=R.

Здесь N это целочисленная переменная , а R - переменная

для действительных чисел. Если N имеет значение 1234, то R по-

лучит значение 1234 (десятичная точка подразумевается, но не

пишется).

Правило пытается вычислить значение N. Если текущее значе-

ние N есть целое число, то правило успешно; в противном случае

правило неуспешно. При успешном завершении правило выбирает це-

лое число и присваивает его переменной R. И в этом случае пра-

вило преобразования работает только при условии, что целое чис-

ло находится внутри допустимого диапазона.

Преобразование строки в символ также может быть выполнено

при помощи простого правила:

conv_str_symb(S,Sb) :- S=Sb.

Например, если S="Turbo PROLOG", то Sb=Turbo PROLOG. Объ-

ект S объявлен как объект типа string, а Sb объявлен как объект

типа symbol.

Программа Conversion2 (листинг 6.10) использует все расс-

мотренные правила. Результат ее работы показан на рис. 6.8.

Листинг 6.10

Рисунок 6.8.

* Упражнение

6.7. Напишите результат обработки следующих входных дан-

ных, используя правила, определенные в программе Conversiоn2:

1. Входное действительное число: 1697.432284

Выходное целое число:_____________________

2. Входное целое число: 3333

Выходное действительное число: __________

3. Входная строка: "Turbo_Prolog_Compiler"

Выходной символ: ________________________

6.9. Создание символьных префиксов

Создать "префиксный" символ - это значит присоединить этот

символ к началу строки. Например, присоединение префикса 'A' к

"BCDEF" дает строку "ABCDEF". Эта операция в Турбо-Прологе реа-

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

frontchar(String,Char,Rest_of_string).

Объекту String присваивается значение, состоящее из Char и

Rest_of_string (остаток строки).

Рассмотрим в качестве примера три предиката. Первый из них

frontchar(Str, 'F', "OX").

присваивает символьной переменной Str значение "FOX" (лиса).

Второй

frontchar("SPRING", C, "PRING").

присваивает символьной переменной C значение 'S'.

Третий

frontchar("dBASE", 'd', X).

присваивает X значение BASE.

Предикат frontchar аналогичен предикату concat, за исклю-

чением того, что он присоединяет значение типа char к началу

строки. Как и предикаты, выполняющие преобразование типов, пре-

дикат frontchar имеет несколько направлений обработки данных.

Программа Frontchar (листинг 6.11) демонстрирует использо-

вание предиката frontchar. Результат работы программы показан

на рис.6.9.

* Упражнение

6.8. Напишите программу на Турбо-Прологе, которая цикли-

чески присоединяет символы к началу строки "POEM.TXT". В ре-

зультате должна получиться строка "type POEM.TXT".

Листинг 6.11.

Рисунок 6.9.

6.10.Преобразование строк в список символов

Предикат frontchar полезен при преобразовании строки в

список символов. Пусть, например, необходимо преобразовать

строку STARS в список ['S','T','A','R','S']. Метод этого преоб-

разования, заключается в циклическом использовании предиката

frontchar для "вырезания" первого символа и размещения его в

списке. Правило, которое выполняет эту процедуру, следующее:

convert("", []).

convert(Str, [Head|Tail]) :-

frontchar(Str, Head, Str1),

convert(Str1, Tail).

В правиле convert первым параметром является строка, а

вторым параметром - список. Предикат frontchar рекурсивно изв-

лекает первый символ из Str и помещает его в список.

Программа Charlist1 (листинг 6.12) использует данное пра-

вило. Как вы видите, в разделе domains программы объект

char_list является списком символов, а str - строкой.

Диалог с программой во время ее выполнения показан на

рис.6.10. Заметьте, что второй список - это список цифр, кото-

рые образуют строку. Они не имеют числового смысла, т.е. ариф-

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

Листинг 6.12.

Рисунок 6.10.

Программа Charlist2 (листинг 6.13) является вариантом

программы Charlist1. Она имеет внутреннюю цель, состоящую из

правила do_convert_print. Это правило использует правило

convert для преобразования строки "STARS AND STRIPES" в список

символов. (Вспомните правило print_list из гл. 5). Charlist2

выводит на печать строки чисел в удобном формате (см.

рис.6.11).

Листинг 6.13.

Рисунок 6.11.

* Упражнения

6.9. Запустите программу Charlist1 и введите следующие це-

ли:

1. convert("National Football League" ,B).

2. convert("Material Girl", G).

3. convert("phenylpropanolamine hydrochloride", M).

Проанализируйте результат для каждого случая.

6.10. Модифицируйте программу Charlist2 так, чтобы каждый

элемент списка печатался на своей строке.

6.11.Специальные строки Турбо-Пролога

На протяжении данной главы строки рассматривались только

как цепочки символов. Однако в Турбо-Прологе определены специ-

альные строки, используемые для определенных целей. Эти строки

называются именами. Имена используются для обозначения симво-

лических констант, доменов, предикатов и переменных. По опреде-

лению специальные строки Турбо-Пролога имеют следующие пять

свойств:

1. Строка строится из прописных и строчных букв, цифр и

символов подчеркивания.

2. Между символами не должно быть пробелов.

3. Строка начинается с буквы.

4. Строка не может начинаться любым из специальных симво-

лов, указанных в табл. 6.1.

5. Строка не может содержать управляющих символов.

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

чия между строками общего вида и именами:

1. "A ROSE IS A ROSE IS A ROSE" не является именем Тур-

бо-Пролога, так как содержит пробе-

лы."A_ROSE_IS_A_ROSE_IS_A_ROSE" является именем Турбо-Пролога.

2. "123LOTUS" не является именем Турбо-Пролога, так как

оно начинается с цифры, а "LOTUS123" уже является специальной

строкой Турбо-ПРОЛОГа, так как порядок следования символов был

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

3."_intelligence" не является именем Турбо-Пролога, так

как она начинается специальным символом "_". Но "artificial_" -

это строка Турбо-Пролога; наличие подчерка не влияет на ее "до-

пустимость", так как подчерк не первый символ.

4. Ctrl-P не является именем Турбо_Пролога, так как это

управляющий символ.

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

верять является ли строка специальной строкой Турбо-Пролога.

Синтаксис этого предиката следующий:

isname(String).

Если String это строка Турбо-Пролога, то предикат будет

успешным; в противном случае он будет неуспешным.

Программа Isname (листинг 6.14) использует предикат isname

для проверки, что строка есть имя Турбо-Пролога. Диалог с прог-

раммой показан на рис.6.12.

В программе Isname правило test_good_names (проверка до-

пустимых имен) использован предикат isname, проверяющий являет-

ся ли employee_ID именем Турбо-Пролога. Так как это есть имя

Турбо-Пролога, то правило успешно и сообщение на экране следую-

щее:

employee_ID is a legal name

Это правило проверяет также $employee_ID. Так как префикс

$ делает его недопустимым именем Турбо-Пролога, то предикат

isname неуспешен, но отрицание предиката

not(isname($employee_ID)).

успешно, и поэтому правило test_bad_names (проверка недопусти-

мых имен) успешно. Сообщение на экране имеет вид:

$employee_ID is not a legal name

( .......... недопустимое имя)

Предикат isname весьма удобен при программировании на Тур-

бо-Прологе операций преобразования исходного текстового файла

на одном языке в исходный текстовый файл на другом языке. Если

команда введена, то isname может определить будет ли она преоб-

разована в формат Турбо-Пролога в соответствии с определением

имени, принятом в языке. Другое использование isname это обра-

ботка введенных с клавиатуры данных и генерация исходных (текс-

товых) файлов, которые могут быть скомпилированы Турбо-Проло-

гом.

Рисунок 6.12.

* Упражнение

6.11. Напишите программу, которая проверит являются ли

следующие строки допустимыми именами:

1. %COPY

2. _town

3. addres

4. Prescription

5. iodochlorhydroxyquin

6.12 Формирование атомов из строк

Атом (token) это последовательность символов. Такая группа

символов является специальной строкой Турбо-Пролога. Атом может

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

этот знак рассматривается как отдельный атом. Атом может быть

символом, но только не символом пробела. Переменные используют-

ся для передачи параметров. Переменные являются атомами, но не

все атомы есть переменные.

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

атома из строки. Это предикат fronttoken. Его синтаксис следую-

щий:

fronttoken(String, Token, Rest_of_string).

Либо String должна быть означена, либо оба Token и

Rest_of_string должны быть означены.

Если первый символ строки есть символ из групп с 1 по 4 в

табл.6.1, то этот символ присваивается переменной Token, а ос-

тавшиеся символы присваиваются Rest_of_string. Либо, если стро-

ка имеет значение, то Token получает это значение, а

Rest_of_string получает значение пустой строки ("").

Ниже приводится несколько примеров отношения, определяемо-

го этим предикатом:

1. Предикат fronttoken(Str,"Default","Directory") присваи-

вает Str значение "Default directory".

2. Предикат fronttoken(Str,"$default","$directory") прис-

ваивает Str значение "$default$directory".

3. Предикат fronttoken("Pointer",Token,Rest) присваивает

Token значение "Pointer", а переменной Rest присваивает значе-

ние ""(пустая строка).

4. Предикат fronttoken("$Command",Token,Trail) присваивает

Token значение "$", а переменной Trail значение "Command".

5. Предикат fronttoken("$$command",Token,Trail) присваива-

ет Token значение "$", а переменной Trail значение "$command".

6. Предикат fronttoken("!default",Token,Rest) присваивает

переменной Token значение "!", а переменной Rest значение

"default".

7. Предикат fronttoken("$RUN AI.BAS",Token,Rest) присваи-

вает переменной Token значение "$", а переменной Rest значение

"RUN AI.BUS".

Программа Token1 (листинг 6.15) иллюстрирует эти примеры.

Результат работы этой программы показан на рис.6.13. Заметьте,

что результаты существенно различаются в зависимости от типа

аргументов.

Предикат fronttoken может быть использован в правиле пре-

образования строки в список атомов. Это правило аналогично пра-

вилу, которое использовалось для преобразования строки в список

аргументов:

convers(Str, [Head|Tail]) :-

fronttoken(Str,Head,Str1),!,

convers(Str1,Tail).

convers(_ , []).

Листинг 6.15.

Вариант предиката convers(_ , [ ]) будет успешен, если

список будет пустым, и это условие определяет точку, с которой

должно быть начато преобразование. Например, строка "one two

three" должна быть преобразована в список атомов:

[one, two, three] .

Рисунок 6.13.

Программа Token2 (листинг 6.16) демонстрирует преобразова-

ние строк в список атомов. Результат программы показан на

рис.6.14. Заметьте, что строка "STARS AND STRIPES" преобразует-

ся в список символов:

["STARS", "AND", "STRIPES"].

Пробелы были устранены.

Листинг 6.16.

Рисунок 6.14.

* Упражнение

6.12. Запустите программу Token2 и введите следующие внеш-

ние цели:

1. convers("from New_York to Los_Angeles").

2. convers("123 infinity").

3. convers("1 2 34 9 636").

4. convers("%%$@@##").

Какие будут результаты?

Программа Token3 (листинг 6.17) является вариантом Token2.

Эта программа использует внутренную цель, которая является пра-

вилом do_convert_and_print. Эта цель состоит из двух подцелей.

Подцель convers преобразует строку "STARS AND STRIPES FOREVER"

в список атомов, а подцель print_list печатает получившийся

список. Результат работы программы показан на рис.6.15.

Листинг 6.17.

Рисунок 6.15.

* Упражнение

6.13. Модифицируйте программу Token3 так, чтобы она преоб-

разовывала следующие строки в списки:

"C>DIR C:\INVERT\AUTOPRT.FIL"

"A>TYPE ACCOUNTS.BUS"

6.13. Преобразование строк в списки атомов с функторами.

Часто удобно преобразовывать данные, введенные с клавиату-

ры, в термы, которые могут быть обработаны Турбо-Прологом. Нап-

ример, вам может потребоваться поместить множество утверждений

в базу данных в следующем виде:

fruit(apple).

fruit(peach).

fruit(orange).

fruit(pear).

Эти утверждения могут быть построены на основе строки

apple peach orange pear. Этот метод включает преобразование

строки в список, который содержит имя функтора. В данном случае

имя функтора есть fruit (фрукт). Результатом преобразования яв-

ляется следующий список:

[fruit(apple),fruit(peach),fruit(orange),fruit(pear)].

Этот список может быть записан в базу данных (или файл).

Соответствующее правило на Турбо-Прологе может быть построено

таким образом, чтобы каждый элемент этого списка находился на

отдельной строке. Это правило должно присоединять точку к каж-

дому элементу с функтором.

После построения правила для записи списка необходимо пос-

троить правило преобразования. Предикат fronttoken является ос-

новной компонентой этого правила. Для соответствующего примера

будет использоваться transf.

Это правило должно удовлетворять нескольким требованиям.

Во-первых, оно должно отображать пустую строку в пустой список:

transf("", []).

В начальный момент преобразования это правило должно быть

успешным при пустом списке.

Цель этого правила состоит в трансформации строки в спи-

сок. Во время этого процесса правило также проверяет тип каждо-

го элемента. Если элемент является целым числом, то выбирается

имя функтора n; если элемент является символом, то имя функтора

есть ch; если элемент является строкой, то имя функтора s.

Целиком это рекурсивное правило имеет следующий вид:

transf(Str, [Token_head|Token_tail]) :-

fronttoken(Str, Symbol_type, Strx),

choose_token(Symbol_type, Token_head),

transf(Strx, Token_tail).

Подправило chose_token имеет вид:

choose_token(S,n(N)) :- str_int(S,N).

choose_token(S,c(C)) :- str_char(S,C).

choose_token(S,s(S)) :- isname(S).

Правило transf допускает строки, состоящие из символов и

чисел. Когда это правило вызывается, значение Symbol_type может

быть числом, символом или именем. Если это число, то

choose_token определяет этот тип, и тогда Token_head имеет вид

n(N), где N - число. Если объект является символом, то правило

choose_token присваивает Token_head строку вида c(C), где C -

символ. Если объект является строкой, то Token_head имеет вид

s(S), где S - строка.

Программа Token4 (листинг 6.18) использует это правило

трансформации. Раздел domains включает объявления трех типов

атомов и объявления типа для token_list, являющегося списком,

каждый элемент которого есть атом.

Листинг 6.18.

Два возможных варианта внешней цели могут иметь следующий

вид:

transf("STARS AND STRIPES", FT).

и

transf("LOTUS 123", FT).

Результат ввода этих целей показан на рис.6.16. В первом

списке все элементы имеют тип string, в то время как во втором

списке содержатся смешанные типы: тип string для первого эле-

мента и тип integer для второго элемента.

Рисунок 6.16.

* Упражнение

6.14. Запустите программу Token4 и введите следующие цели:

1. transf("beyond the year 2000",L)

2. transf("THREE SMALL HATS DO NOT MAKE ONE BIG HAT",L)

3. transf("Y = 27 * X + 6",L)

Какой результат будет в каждом случае?

Обзор содержания главы

В этой главе вы узнали как используется набор символов

Турбо-Пролога, их представление при помощи кода ASCII и как за-

писывать и использовать эти коды. Вы так же узнали, как пользо-

ваться встроенными предикатами для обработки строк: str_len для

нахождения длины строки, concat - для соединения двух строк,

frontstr - для расщепления строки на подстроки, и fronttoken -

для выборки атома из строки.

Вы так же узнали как преобразовывать элементы данных одно-

го типа в элементы данных другого типа: строку из прописных

букв в строку из строчных букв и наоборот, целые числа в дейст-

вительные и наоборот, символы в строки и наоборот, а так же

символы в ASCII код.

Эти средства использовались в двух ситуациях: предикат

frontchar использовался для правила преобразования строки в

список символов, а предикат fronttoken использовался для пост-

роения правила преобразования строки в список атомов с функто-

рами. Эти применения демонстрируют использование обработки

строк при преобразовании входной строки в формат, воспринимае-

мый Турбо-Прологом. Эти применения весьма полезны при построе-

нии правил для модулей, реализующих интерфейс программы на Тур-

бо-Прологе с пользователем. Они так же полезны при подготовке

данных для их более простой обработки и хранения.

- 27 -

Названия рисунков главы 6

Рис. 6.1. Результат работы программы ASCIIprint.

Рис. 6.2. Результат работы программв TeamPrint1.

Рис. 6.3. Диалог с программой Showlegth1.

Рис. 6.4. Результат работы программы ShowLength2.

Рис. 6.5. Результат работы программы Concat1.

Рис. 6.6. Результат работы программы Substring.

Рис. 6.7 Результат работы программы Conversions1.

Рис. 6.8. Результат работы программы Conversions2.

Рис. 6.9. Результат работы программы Frontchar.

Рис. 6.10. Диалог с программой Charlist1.

Рис. 6.11. Результат работы программы Charlist2.

Рис. 6.12. Диалог с программой Isname.

Рис. 6.13. Результат работы программы Token1.

Рис. 6.14. Диалог с программой Token2.

Рис. 6.15. Результат работы программы Token3.

Рис. 6.16. Диалог с программой Token4.

- 28 -

Надписи на рисунках главы 6

N рисунка N надписи и ее текст

6.1. -

6.2. -

6.3. -

6.4. -

6.5. -

6.6. -

6.7 -

6.8. -

6.9. -

6.10. -

6.11. -

6.12. -

6.13. -

6.14. -

6.15. -

6.16. -

- 29 -

Названия таблиц главы 6

Табл. 6.1 Коды ASCII.

Надписи к таблицам главы 6

N таблицы N надписи и ее текст

6.1 1) Управляющие символы

2) Специальные символы

3) Цифры

4) Символ Код

5) Символ Код

6) Символ Код

7) Символ Код Действие

8) Прерывание выполнения программы

9) Продвижение курсора назад на одну позицию

10) Табуляция

11) Конец строки

12) Возврат коретки

13) Посылка сообщения принтеру для вывода ее

на печать

14) Продолжение выполнения программы ( после ее

прерывания при помощи символа Ctrl-S)

15) Создание паузы во время выполнения программы

16) Включение и выключение трассировки

17) Конец файла

18) Символы английского алфавита

19) Символ Код Символ Код

- 30 -

Листинги программ главы 6

Листинг 6.1.

_______________________________________________________________

/* Программа: ASCIIPrint Файл: PROG0601.PRO */

/* Назначение: Демонстрация использования кодов ASCII */

/* для печати символов */

/* Указание: Запустите программу. Цель содержится в */

/* этой программе */

predicates

print_by_ascii_numbers

goal

print_by_ascii_numbers.

clauses

print_by_ascii_numbers :-

nl,

write("Числа : "),

nl,nl,

write( 41, " ", 42," ", 43),

nl,

write($41, " ",$42," ",$43),

nl,nl,

write("Строки :"),

write('\10','\10'),

write('\65'," ",'\66'," ",'\67'),

write("\10\10"),

write("\65\66\67"),

nl,

write("\84\117\114\98\111\32"),

write("\80\82\79\76\79\71").

_______________________________________________________________

- 32 -

Листинг 6.2.

_______________________________________________________________

/* Программа: TeamPrint1 Файл:PROG0602.PRO */

/* Назначение: Демонстрация использования строк */

/* Турбо-Пролога */

predicates

print_strings

goal

print_strings.

clauses

print_strings :-

nl,

write("Желаю удачи ! "),

nl,nl,

/* Названия спортивных команд */

S1 = "Cleveland Browns ",

S2 = "Cincinnati Bengals ",

S3 = "Dallas Cowboys ",

S4 = "Denver Broncos ",

S5 = "Indianapolis Colts ",

S6 = "New York Giants ",

S7 = "Los Angeles Raiders ",

S8 = "St.Louis Cardinals ",

S9 = "Tampa Bay Buccaneers ",

write(S1), nl,

write(S2), nl,

write(S3), nl,

write(S4), nl,

write(S5), nl,

write(S6), nl,

write(S7), nl,

write(S8), nl,

write(S9).

_______________________________________________________________

- 34 -

Листинг 6.3.

_______________________________________________________________

/* Программа: TeamPrint2 Файл:PROG0603.PRO */

/* Назначение: Демонстрация использования строк */

/* Турбо-Пролога */

domains

s1,s2,s3,s4,s5,s6,s7,s8,s9 = string

predicates

data_strings(s1,s2,s3,s4,s5,s6,s7,s8,s9)

print_string

goal

print_strings.

clauses

data_strings(S1,S2,S3,S4,S5,S6,S7,S8,S9) :-

/* Названия спортивных команд */

S1 = "Cleveland Browns ",

S2 = "Cincinnati Bengals ",

S3 = "Dallas Cowboys ",

S4 = "Denver Broncos ",

S5 = "Indianapolis Colts ",

S6 = "New York Giants ",

S7 = "Los Angeles Raiders ",

S8 = "St.Louis Cardinals ",

S9 = "Tampa Bay Buccaneers ",

print_strings :-

nl,

write("Желаю удачи ! "),

nl,nl,

data_strings(S1,S2,S3,S4,S5,S6,S7,S8,S9),

write(" ",S1),nl,

write(" ",S2),nl,

write(" ",S3),nl,

write(" ",S4),nl,

write(" ",S5),nl,

write(" ",S6),nl,

write(" ",S7),nl,

write(" ",S8),nl,

write(" ",S9).

_______________________________________________________________

- 36 -

Листинг 6.4.

_______________________________________________________________

/* Программа: ShowLength1 Файл:PROG0604.PRO */

/* Назначение: Демонстрация использования предиката */

/* str_len(строка, длина_строки) */

predicates

fing_string_length

goal

fing_string_length.

clauses

fing_string_length :-

str_len("Turbo Prolog", Length),

nl,nl,

write(" Turbo Prolog"),

nl,nl,

write(" Length = ", Length).

_______________________________________________________________

- 37 -

Листинг 6.5.

_______________________________________________________________

/* Программа: ShowLength2 Файл:PROG0605.PRO */

/* Назначение: Демонстрация использования предиката */

/* str_len(строка, длина_строки) */

/* Указание: Запустите программу. Цель включена в */

/* программу. */

predicates

lin(string)

find_length

goal

fing_length.

clauses

lin(" Открытие ").

lin(" Это было путешествие, ").

lin("- путешествие в ночь,").

lin("- путешествие в день,").

lin("- путешествие в мечту.").

lin(" Когда я достиг этой земли,").

lin("я нашел себя").

lin(" ").

lin(" Khinzu ").

fing_length :-

lin(S),

str_len(S,L),

write(S, " (",L,")"),nl,

fail.

_______________________________________________________________

- 39 -

Листинг 6.6.

_______________________________________________________________

/* Программа: Concat1 Файл:PROG0606.PRO */

/* Назначение: Демонстрация использования предиката */

/* concat(строка1,строка2,строка3) */

predicates

print_strings

goal

print_strings.

clauses

print_strings :-

concat("Turbo Prolog","is fast!",R),

nl,nl,write(R),

concat("Every body loves ",

"somebody sometime.",S),

nl,nl,write(S),

concat("Artificial",

"Intelligence.",T),

nl,nl,write(T),

concat("A thing of beauty ",

"is a joy forever.",U),

concat("Turbo Prolog","is fast!",R),

nl,nl,write(R),

nl,nl,write(U),nl,nl.

_______________________________________________________________

- 41 -

Листинг 6.7.

_______________________________________________________________

/* Программа: Concat2 Файл:PROG0607.PRO */

/* Назначение: Демонстрация использования предиката */

/* concat(строка1,строка2,строка3) */

predicates

print_strings

goal

print_strings.

clauses

print_strings :-

nl,nl,

O = "Turbo Prolog",

P = " is fast !",

concat(O,P,Q),

write(Q),nl,nl,

R = "Every body loves ",

S = "somebody sometime.",

concat(R,S,T),

write(T),nl,nl,

U = "Artificial",

V = "Intelligence",

concat(U,V,W),

write(W),nl,nl,

X = "A thing of beauty ",

Y = "is a joy forever.",

concat(X,Y,Z),

write(Z),nl,nl.

_______________________________________________________________

- 43 -

Листинг 6.8.

_______________________________________________________________

/* Программа: Substring Файл:PROG0608.PRO */

/* Назначение: Демонстрация использования предиката */

/* front_str(целое,строка1,строка2,строка3) */

predicates

print_strings

goal

print_strings.

clauses

print_strings :-

nl,nl,nl,

frontstr(12,

"Turbo Prolog is fast!",

R1,R2),

write(R1),nl,

write(R2),nl,nl,

frontstr(10,

"Every body loves somebody",

S1,S2),

write(S1),nl,

write(S2),nl,nl,

frontstr(10,

"Artificial Intelligence",

T1,T2),

write(T1),nl,

write(T2),nl,nl,

frontstr(17,

"A thing of beauty is a joy.",

U1,U2),

write(U1),nl,

write(U2).

_______________________________________________________________

- 45 -

Листинг 6.9.

_______________________________________________________________

/* Программа: Conversions1 Файл:PROG0609.PRO */

/* Назначение: Демонстрация преобразования типов данных */

predicates

do_conversions

goal

do_conversions.

clauses

do_conversions :-

upper_lower("STARS AND STRIPES",S1),

write("STARS AND STRIPES"),nl,

write(S1),nl,nl,

upper_lower(S2,"one day at a time"),

write("one day at a time"),nl,

write(S2),nl,nl,

write("T"),nl,

str_char("T",C1),

write(C1),nl,nl,

write("U"),nl,

char_int('U',N1),

write(N1),nl.

_______________________________________________________________

- 47 -

Листинг 6.10.

_______________________________________________________________

/* Программа: Conversions2 Файл:PROG0610.PRO */

/* Назначение: Демонстрация преобразования: */

/* (1) действительного числа в целое */

/* (2) целого числа в действительное */

/* (3) строки в символ */

predicates

conv_real_int(real,integer)

conv_int_real(integer,real)

conv_str_symb(string,symbol)

goal

X1 = 5432.765,

conv_real_int(X1,N1),nl,nl,

N2 = 1234,

conv_int_real(N2,X2),nl,nl,

S = "TURBO PROLOG",

conv_str_symb(S,Sb),nl.

clauses

conv_real_int(R,N) :-

R = N,

write("Input real - ",R),nl,

write("Output integer - " N).

conv_int_real(N,R) :-

N = R,

write("Input integer - ",N),nl,

write("Output real - ",R).

conv_str_symb(S,Sb) :-

S = Sb,

write("Input string - ",S),nl,

write("Output symbol - ",Sb).

_______________________________________________________________

- 49 -

Листинг 6.11.

_______________________________________________________________

/* Программа: Frontchar Файл:PROG0611.PRO */

/* Назначение: Демонстрация использования предиката */

/* frontchar(строка,первый_символ,строка) */

predicates

print_all

goal

print_all.

clauses

print_all :-

frontchar(Str1,'A',"BCDEF"),

nl,write(" Str1 = ", Str1),

frontchar(Str2,'8',"is enough"),

nl,write(" Str2 = ", Str2),

frontchar(Str3,'?',"Show"),

nl,write(" Str3 = ", Str3),

frontchar(Str4,'#',"&%#!!!"),

nl,write(" Str4 = ", Str4),

frontchar(Str5,'1',"23LOTUS"),

nl,write(" Str5 = ", Str5),

frontchar(Str6,' ',"//"),

nl,write(" Str6 = ", Str6).

_______________________________________________________________

- 51 -

Листинг 6.12.

_______________________________________________________________

/* Программа: Charlist1 Файл:PROG0612.PRO */

/* Назначение: Демонстрация преобразования строки */

/* в список символов с использованием */

/* предиката frontchar */

domains

char_list = char *

str = string

predicates

conver(str, char_list)

clauses

conver("",[]).

conver(Str, [Head|Tail]) :-

frontchar(Str,Head,Str1),

conver(Str1,Tail).

_______________________________________________________________

- 52 -

Листинг 6.13.

_______________________________________________________________

/* Программа: Charlist2 Файл:PROG0613.PRO */

/* Назначение: Демонстрация преобразования строки */

/* в список символов с использованием */

/* предиката frontchar */

domains

char_list = char *

str = string

predicates

conver(str, char_list)

print_list(char_list)

do_convert_and_print

goal

do_convert_and_print.

clauses

conver("",[]).

conver(Str, [Head|Tail]) :-

frontchar(Str,Head,Str1),

conver(Str1,Tail).

print_list([]).

print_list([Head|Tail]) :-

write(Head," "),

print_list(Tail).

do_convert_and_print :-

nl,nl,

write("STARS AND STRIPES"),nl,nl,

conver("STARS AND STRIPES",List),

print_list(List),

nl,nl,

write(" All done!"),nl.

_______________________________________________________________

- 54 -

Листинг 6.14.

_______________________________________________________________

/* Программа: Isname Файл:PROG0614.PRO */

/* Назначение: Демонстрация использования встроенного */

/* предиката isname(строка). */

predicates

test_good_names

test_bad_names

goal

test_good_names,

test_bad_names.

clauses

test_good_names :-

Name = "employee_ID",

isname(Name),

nl, write(Name, " is a legal name.").

test_bad_names :-

Name = "$employee_ID",

not(isname(Name)),

nl, write(Name, " is not a legal name!").

_______________________________________________________________

- 55 -

Листинг 6.15.

_______________________________________________________________

/* Программа: Token1 Файл:PROG0615.PRO */

/* Назначение: Демонстрация использования встроенного */

/* предиката */

/* fronttoken (строка,атом,остаток_строки). */

predicates

print_all

goal

print_all.

clauses

print_all :-

fronttoken(Str1, "Default","Directory"),

nl,write(" Str1 = ",Str1),

fronttoken(Str2, "$default","$directory"),

nl,write(" Str2 = ",Str2),

fronttoken("Pointer",Token1,Rest1),

nl,write(" Token1 = ",Token1),

nl,write(" Rest1 = ",Rest1),

fronttoken("$Command", Token2,Trail1),

nl,write(" Token2 = ",Token2),

nl,write(" Trail1 = ",Trail1),

fronttoken("$$command", Token3,Trail3),

nl,write(" Token3 = ",Token3),

nl,write(" Trail3 = ",Trail3),

fronttoken(Str3, "!default","$default"),

nl,write(" Str3 = ",Str3),

fronttoken("$RUN AI.BAS",Token4,Rest2),

nl,write(" Token4 = ",Token4),

nl,write(" Rest2 = ",Rest2).

_______________________________________________________________

- 57 -

Листинг 6.16.

_______________________________________________________________

/* Программа: Token2 Файл:PROG0616.PRO */

/* Назначение: Демонстрация преобразования стоки в */

/* список строк при помощи предиката */

/* fronttoken (строка,атом,остаток_строки). */

domains

str_list = symbol *

str = string

predicates

convers(str,str_list)

clauses

convers(Str,[Head|Tail]) :-

fronttoken(Str,Head,Str1),!,

convers(Srt1,Tail).

convers(_,[]).

_______________________________________________________________

- 58 -

Листинг 6.17.

_______________________________________________________________

/* Программа: Token3 Файл:PROG0617.PRO */

/* Назначение: Демонстрация преобразования стоки в */

/* список строк при помощи предиката */

/* fronttoken (строка,атом,остаток_строки). */

domains

str_list = symbol *

str = string

predicates

convers(str,str_list)

print_list(str_list)

do_convert_and_print

goal

do_convert_and_print.

clauses

convers(Str,[Head|Tail]) :-

fronttoken(Str,Head,Str1),!,

convers(Srt1,Tail).

convers(_,[]).

print_list([]).

print_list([Head|Tail]) :-

write(" ",Head),nl,

print_list(Tail).

do_convert_and_print :-

nl,nl,

write("STARS AND STRIPES FOREVER"),

nl,nl,

convers("STARS AND STRIPES FOREVER",List),

print_list(List),

nl,nl,

write(" All done !"),nl.

_______________________________________________________________

- 60 -

Листинг 6.18.

_______________________________________________________________

/* Программа: Token4 Файл:PROG0618.PRO */

/* Назначение: Демонстрация преобразования стоки в */

/* список атомов с функторами */

domains

token_type = n(integer);

c(char);

s(string)

token_list = token_type *

predicates

transf(string,token_list)

choose_token(string,token_type)

clauses

transf("",[]).

transf(Str, [Token_head|Token_Tail]) :-

fronttoken(Str, Symbol_type, Strx),

choose_token(Symbol_type, Token_head),

transf(Str, Token_tail).

choose_token(S,n(N)) :-

str_int(S,N).

choose_token(S,c(C)) :-

str_char(S,C).

choose_token(S,s(S)) :-

isname(S).

_______________________________________________________________

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]