Интернет Университет информационных технологий Твой путь к знаниям
регистрация || зачетка | дипломы || настройки | корзина | заказы | личный счет
  Издательство «Открытые Системы» Курсы | Учебные программы | Учебники | Новости | Форум | Помощь  

 
  Лекции
Основы программирования на языке Пролог
1.   Введение в язык логического прог...
2.   Логические основы Пролога
3.   Основные понятия Пролога
4.   Рекурсия
5.   Основы Турбо Пролога. Структура ...
6.   Управление выполнением программы...
7.   Списки
8.   Сортировка списков
9.   Множества
10.   Деревья
11.   Строки
12.   Файлы
13.   Внутренние (динамические) базы д...
14.   Пролог и искусственный интеллект
    Экзамен
    Сдать экзамен экстерном
    Литература
    Предметный указатель
    Примеры

Основы программирования на языке Пролог версия для локальной работы
11. Лекция: Строки
Страницы: « | 1 | 2 | 3 | 4 | вопросы | » | учебники | для печати и PDA
  Если Вы заметили ошибку - сообщите нам, или выделите ее и нажмите Ctrl+Enter  

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

Отличаться предыдущее решение будет заменой предиката frontchar на предикат fronttoken. Да еще надо не забыть в разделе описания предикатов заменить домен второго параметра со списка символов на список строк.

Запишем эту идею:

str_a_list("",[]). /* пустой строке по-прежнему 
                 соответствует пустой список */
str_a_list(S,[H|T]):–
              fronttoken(S,H,S1), 
                    /* H — первый атом строки S, 
                       S1 — остаток строки */
              str_a_list(S1,T). 
                      /* T — список, состоящий 
                        из атомов, входящих 
                        в строку S1*/

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

Пример. Разработаем предикат, который будет преобразовывать список символов в строку. Предикат будет иметь два аргумента. Первым аргументом будет список символов, вторым — строка, образованная из элементов списка.

Базис рекурсии: пустому списку соответствует пустая строка. Шаг: если исходный список не пуст, то нужно перевести в строку его хвост, после чего, используя стандартный предикат frontchar, приписывать к первому элементу списка строку, полученную из хвоста исходного списка.

Запишем эту идею:

list_str([],""). /* пустой строке соответствует 
                пустой список */
list_str([H|T],S):–
            list_str(T,S1), 
                  /* S1 — строка, образованная 
                    элементами списка T */
            frontchar(S,H,S1). 
                  /* S — строка, полученная 
                    дописыванием строки S1 
                    к первому элементу списка H */

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

Решение, как обычно, будет рекурсивным. Рекурсия по строке, в которой ведется подсчет количества вхождений данного символа. Если строка пустая, то не важно, вхождения какого символа мы считаем, все равно ответом будет ноль. Это базис. Шагов рекурсии будет два в зависимости от того, будет ли первым символом строки символ, вхождения которого мы считаем, или нет. В первом случае нужно подсчитать, сколько раз искомый символ встречается в остатке строки, и увеличить полученное число на единицу. Во втором случае (когда первый символ строки отличен от символа, который мы считаем) увеличивать полученное число не нужно. При расщеплении строки на первый символ и хвост нужно воспользоваться уже знакомым нам предикатом frontchar.

char_count("",_,0). /* Любой символ не встречается 
                  в пустой строке ни разу*/
char_count(S,C,N):–
              frontchar(S,C,S1),!, 
                /* символ C оказался первым символом 
                  строки S, в S1 — оставшиеся 
                  символы строки S */
              char_count(S1,C,N1), 
                    /* N1 — количество вхождений 
                       символа C в строку S1 */
              N=N1+1. 
                /* N — количество вхождений 
                  символа C в строку S получается 
                  из количества вхождений символа C
                  в строку S1 добавлением единицы */
char_count(S,C,N):–
              frontchar(S,_,S1), 
                  /* первым символом строки S 
                    оказался символ, отличный
                    от исходного символа C, в S1 — 
                    оставшиеся символы строки S */
              char_count(S1,C,N). 
                  /* в этом случае количество 
                    вхождений символа C в строку S 
                    совпадает с количеством 
                    вхождений символа C 
                    в строку S1 */

Пример. Попробуем разработать предикат, который по символу и строке будет возвращать первую позицию вхождения символа в строку, если символ входит в строку, и ноль, если не входит. У предиката будет три параметра. Первые два — входные — символ и строка, третий — выходной — первая позиция вхождения первого параметра во второй параметр или ноль.

Не самая легкая задачка, но мы с ней справимся. Можно, конечно, записать в качестве базиса, что в пустой строке не встречаются никакие символы, но мы пойдем другим путем.

Вначале с помощью предиката frontchar разделим исходную строку на первый символ и остаток строки. Если первым символом строки окажется тот самый символ, позицию которого мы ищем, значит, больше ничего делать не нужно. Ответом будет единица. В этом случае нам даже неважно, какие символы оказались в хвосте строки, поскольку мы ищем первое вхождение данного символа в строку.

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

Давайте попробуем записать эти рассуждения.

str_pos(C,S,1):–
          frontchar(S,C,_),!. 
                /* Искомый символ C оказался первым 
                  символом данной строки S */
str_pos(C,S,N) :–
          frontchar(S,_,S1), 
                /* S1 — состоит из всех символов 
                 строки S, кроме первого, который 
                 отличается от искомого символа C */
          str_pos(C,S1,N1), 
                /* N1 — это позиция, в которой
                  символ C встречается первый раз 
                  в хвосте S1 или ноль*/
          N1<>0,!, /* если позиция вхождения  
                   символа C в строку S1 не равна  
                   нулю, то есть если он встречается 
                   в строке S1, /
          N=N1+1. /* то, увеличив позицию его 
                  вхождения   на единицу, мы получим 
                  позицию его вхождения в исходную 
                  строку */
str_pos(_,_,0). /* искомый символ не входит в данную 
              строку */

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

Решение, как обычно, будет рекурсивным. Если строка пустая, значит, в ней нет символов, и, следовательно, заменять нечего. Результатом будет тоже пустая строка. Если же строка непустая, то мы должны разделить ее с помощью предиката frontchar на первый символ и строку, состоящую из остальных символов исходной строки.

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

В первом случае заменим все вхождения первого символа вторым символом в хвосте исходной строки, после чего, опять-таки с помощью предиката frontchar, приклеим полученную строку ко второму символу. В итоге в результирующей строке все вхождения первого символа будут заменены вторым символом.

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

str_replace("",_,_,""):–!. /* из пустой строки можно 
                       получить только пустую 
                       строку */
str_replace(S,C,C1,SO):–
                frontchar(S,C,S1),!, 
                    /* заменяемый символ C оказался 
                       первым символом строки S, 
                       S1 — остаток строки S */
                str_replace(S1,C,C1,S2), 
                    /* S2 — результат замены 
                       в строке S1 всех вхождений 
                       символа C на символ C1 */
                frontchar(SO,C1,S2). 
                    /* SO — результат склейки 
                       символа C1 и строки S2 */
str_replace(S,C,C1,SO):–
                frontchar(S,C2,S1), 
                    /* разделяем исходную строку S 
                       на первый символ C2 
                       и строку S2, образованную 
                       всеми символами строки S, 
                       кроме первого */
                str_replace(S1,C,C1,S2), 
                      /* S2 — результат замены 
                        в строке S1 всех вхождений 
                        символа C на символ C1 */
                frontchar(SO,C1,S2). 
                      /* SO — результат соединения 
                        символа C1 и строки S2 */

Если нам понадобится предикат, который будет заменять не все вхождения первого символа на второй, а только первое вхождение первого символа, то нужно просто из первого правила удалить вызов предиката str_replace(S1,C,C1,S2).

Дальше »
  Если Вы заметили ошибку - сообщите нам, или выделите ее и нажмите Ctrl+Enter  
Страницы: « | 1 | 2 | 3 | 4 | вопросы | » | учебники | для печати и PDA

Внимание! Если Вы увидите ошибку на нашем сайте, выделите её и нажмите Ctrl+Enter.
Нужна помощь?
• Забыли пароль? Вам сюда...
• Есть вопрос? Спрашивайте!
Вы можете:
• Изменить персональные данные
• Изменить параметры подписки
Интернет-магазин:
• Ваши заказы здесь
• Ваш личный счет
Курсы | Учебные программы | Учебники | Новости | Форум | Помощь

Телефон: +7 (495) 253-9312, 253-9313, факс: +7 (495) 253-9310, email: info@intuit.ru
© 2003-2007, INTUIT.ru::Интернет-Университет Информационных Технологий - дистанционное образование
Хостинг предоставлен компанией РМ Телеком.
Сервер предоставлен компанией KRAFTWAY COMPUTERS.
Rambler's Top100