Ввод-вывод

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

Основной предикат ввода – read (X). При решении такой цели считывается терм из текущего входного потока; обычно это данные, вводимые с терминала. Введенный терм унифицируется сX, цель read выполнена или не выполнена в зависимости от результата унификации.

Основной предикат вывода – write (X). Решение этой цели приводит к записи терма Х в текущий выходной поток, определяемый операционной системой; обычно это данные, выводимые на терминал. Ни read, ни write не дают альтернативных решений при возврате.

Обычно в предикате read в качестве аргумента используется переменная, которая приобретает значение первого терма в текущем входном потоке. Сопоставление переменной Х какого-либо значения, определенного вне программы, не входит в логическую модель, так как каждое новое обращение к процедуре read(X) будет выполняться с (возможно) различными значениями X.

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

Внелогическая природа предикатов read и write различна. Если в программе заменить все обращения к предикату write на обращения к всегда выполняемому предикату true, то семантика программы не изменится. Для предиката read это не так.

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

Полезным вспомогательным предикатом является предикат writeln(Xs), аналогичный соответствующей команде языка Паскаль. Решение цели writeln(Xs) приводит к печати списка термов Xs в виде выходной строки. Предикат описан в программе 12.1. В ней использован системный предикат пl, вызывающий переход к выводу с новой строки.

 

Writeln([X | Xs]) ¬write(X), writeln(Xs)

Writeln([ ]) ¬nl.

Программа 12.1. Вывод списка термов.

 

Строка литер заключается в апострофы. Например, решение цели writeln ([ 'Значение Х равно', X]) приводит к печати текста

Значение Х равно 3

если переменной Х сопоставлено число 3.

В Прологе можно выполнять и более общие операции со строками литер, обрабатывая строки как списки кодов литер. Если, например, используются коды ASCII, то список [80,114,111,108,111,103] соответствует строке «Prolog». Код ASCII для литеры Р равен 80 для литеры r – 114 и т.д. Строка литер, заключенная в кавычки, является другим способом обозначения списка, состоящего из кодов ASCII. В нашем примере список можно задать с помощью строки «Prolog». Такие строки просто являются более удобной синтаксической записью подобных списков. Обработка строк может производиться с помощью стандартных методов работы со списками.

Системный предикат name(X, Y) используется для преобразования названия константы в строкулитер и обратно.Цель name(X,Y) выполнена, если X – атом, а Y – список кодов ASCII, соответствующих литерам атома X, например, цель name (log,[108, 111, 103])? выполнена.

Ввод-вывод может выполняться не только на уровне термов с помощью предикатов read и write, но и на более низком уровне – на уровне литер. Основной предикат вывода на уровне литер имеет вид put(N), он помещает литеру, соответствующую коду ASCII для N, в текущий выходной поток. Основной предикат ввода get (X)1), сопоставляющий аргументу Х код ASCII первой литеры во входном потоке.

1) Это несколько отличается от операторов Edinburgh-Пролога.

Программа 12.2 задает вспомогательный предикат read_wordlist (Words), читающий список слов Words. В построении программы использован предикат gel. Слова могут быть разделены произвольным числом пробелов (код ASCII для пробела – 32) и могут состоять из любого числа строчных и прописных букв и символов подчеркивания. Последовательность слов завершается точкой.

 

read_word_list(Ws)¬

get(C),

read_word_list(C, Ws).

read_word_list(C,[W |Ws]) ¬

word_char(C),

read_word(C,W,C1),

read_word_list(C1,Ws).

read_word_list(C,Ws) ¬

fill_char(C),

get(Cl),

read_word_list(C1,Ws). read_word_list(C,[ ]) ¬

end_of_words_char(C).

read_word(C,W,C1) ¬

word_chars (C, Cs, С1), name(W.Cs).

word_chars(C, [С | Cs],C0)¬

word_char(C),

!,

get(C1),

word chars (C1,Cs, C0). word_chars(C,[ ],C)¬

not word_char(C).

 

word_char(C)¬97£C,C£122. % строчные буквы

word char(C)¬ 65 £C, С£90. %прописные буквы

word_char(95). %подчеркивание

 

fillchar(32). % пробел

end of words_char(46). % точка