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

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

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

Рассмотрим теперь так называемый метод отсечения и отката. В основе этого метода лежит использование комбинации предикатов fail (для имитации неудачи и искусственной организации отката) и "!" (отсечение или cut), который позволяет прервать этот процесс в случае выполнения какого-то условия. Об отсечении мы уже говорили в третьей лекции. Разберем этот метод на примере.

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

show_names3(Daughter):–
mother(_,Name), /* означивает переменную Name именем
                   дочки */
write(" ", Name), nl, /* выводит значение переменной
                         Name */
Name=Daughter, /* проверяет совпадение имен дочек Name
                  и Daughter. В случае несовпадения
                  вызывает откат на место, указатель
                  на которое хранится в стеке точек
                  возврата. В случае совпадения, за счет
                  наличия отсечения, завершает поиск
                  и вывод имен дочек */
write("Искомый человек найден!"),!.

Этот предикат будет конкретизировать переменную Name именем чьей-то дочери, выводить на экран значение этой переменной. После этого будет сравниваться значение переменной Name со значением переменной Daughter. В случае несовпадения эта подцель терпит неудачу, вызывая откат на первую подцель правила. В случае совпадения имен подцель успешна, управление получает предикат отсечение. Он всегда истинен и запрещает откат для подцелей, расположенных левее. На этом работа предиката show_names3 завершается. То есть откаты в этом правиле будут продолжаться до тех пор, пока текущее значение переменной Name не совпадет со значением переменной Daughter.

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

repeat.
repeat:–
     repeat.

Этот предикат всегда успешен. После выполнения первого предложения процедуры в стек точек возврата запоминается указатель, поскольку имеется еще один альтернативный вариант для него. В теле второго предложения опять вызывается предикат repeat.

Предикат repeat не является встроенным предикатом, а имя "repeat" — зарезервированным словом. Соответственно, вместо этого имени можно использовать какое-нибудь другое.

С помощью этого предиката можно организовывать циклы, подобные циклам в императивных языках программирования. Нужно не забыть добавить в правило, организующее цикл, кроме предиката repeat, условие завершения цикла и отсечение, чтобы не получилось зацикливания.

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

double_char:–
        repeat,
        readchar(C), /* читаем символ с клавиатуры
                        в переменную C */
        write(C,C), nl,/* выводим на экран значение
                          переменной C */
        C=’.’,!, /* сравниваем значение переменной C
                    с символом ‘.’*/
        nl,write("Была введена точка. Закончили.").

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

Далее, используя стандартный предикат readchar, осуществляем чтение символа с клавиатуры в переменную C. Посредством встроенного предиката write выводим два экземпляра введенного пользователем символа на экран; стандартным предикатом nl переводим курсор на следующую строку. Затем значение переменной C сравнивается с символом точка (‘.’). Это условие, которое, с одной стороны, обеспечивает откат на первую подцель (предикат repeat), а с другой обеспечивает выход из цикла. Если поступивший с клавиатуры символ отличен от точки, подцель C=’.’ терпит неуспех. Пролог-система осуществляет откат на последнее место, указатель на которое записан в стеке точек возврата. Из подцелей, расположенных левее, альтернативы имелись только у первой подцели (предиката repeat). Все повторяется еще раз. Пользователь вводит символ, он дважды отображается на экране, сравнивается с точкой. Процесс повторяется до тех пор, пока введенный символ не окажется точкой. В этом случае подцель C=’.’ окажется успешной, управление перейдет на подцели, расположенные правее. Предикат nl сдвинет курсор на начало следующей строки, стандартный предикат write выводит на экран сообщение: "Была введена точка. Закончили." — и процесс дублирования символов на этом завершается.

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

GOAL
write("Вводите символы, которые нужно повторить (точка —
завершение)"),nl,
double_char.
Перейти к вопросам »
  Если Вы заметили ошибку - сообщите нам, или выделите ее и нажмите Ctrl+Enter  
Страницы: « | 1 | 2 | 3 | вопросы | » | учебники | для печати и 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