Сибирский университет потребительской кооперации
Опубликован: 04.05.2005 | Доступ: свободный | Студентов: 4321 / 1347 | Оценка: 4.45 / 4.22 | Длительность: 12:28:00
ISBN: 978-5-9556-0034-5
Лекция 11:

Строки

< Лекция 10 || Лекция 11: 1234 || Лекция 12 >
Аннотация: Обработка строк.

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

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

Начнем со встроенного предиката str_len, который предназначен для определения длины строки, т.е. количества символов, входящих в строку. Он имеет два аргумента: первый — строка, второй — количество символов. Имеется три варианта использования данного предиката.

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

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

И, наконец, третий, не столь распространенный вариант использования, в случае, когда второй аргумент связан, а первый — свободен. В этой ситуации первый аргумент будет означен строкой, состоящей из пробелов, причем количество пробелов будет равно второму аргументу.

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

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

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

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

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

Следующие три встроенных предиката предназначены для "разделки" строки на составляющие.

Предикат frontchar служит для разделения исходной строки на первый символ и "хвост", состоящий из оставшихся после удаления первого символа символов строки. Это чем-то напоминает представление списка в виде головы и хвоста. Причем первый и третий аргументы данного предиката принадлежат строковому домену, а второй — символьному. У этого предиката пять вариантов использования.

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

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

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

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

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

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

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

И, наконец, предикат fronttoken также дробит исходную строку, указанную в качестве первого параметра предиката, на две части. Во второй аргумент предиката попадает первый атом, входящий в строку, размещенную в первом аргументе, в третий — остаток входной строки, полученный после удаления из нее атома. Напомним, что атом — это или идентификатор, или беззнаковое число (целое или вещественное), или символ. У этого предиката существует пять вариантов использования.

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

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

Третий вариант получается, когда первый и второй аргументы означены, а третий нет. В этой ситуации в третий аргумент будут переписаны все символы первого аргумента, остающиеся после удаления первого атома, в случае, если первый атом первого аргумента совпадает со вторым аргументом. В противном случае предикат терпит неудачу.

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

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

Для полноты картины следует еще упомянуть о предикате isname, который истинен, если его строковый аргумент является идентификатором, и ложен в противном случае.

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

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

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

str_list("",[]). /* пустой строке соответствует 
               пустой список */
str_list(S,[H|T]):–
            frontchar(S,H,S1), 
                  /* H — первый символ строки S, 
                    S1 — остаток строки */
            str_list(S1,T). 
                  /* T — список, состоящий 
                    из символов, входящих 
                    в строку S1*/
< Лекция 10 || Лекция 11: 1234 || Лекция 12 >
Виктор Бондарь
Виктор Бондарь

После приведения формулы вида ПНФ к виду ССФ вы получаете формулу, в безквантовой матрице которой дизъюнкт содержит оба контранрных атома:. Как тогда проводить его унификацию, если в случае замены x на f(x) весь дизъюнкт обратится в единицу?

Ольга Потапенко
Ольга Потапенко

никак не могу увидеть тексты самих лекций.