WWW.DISSERS.RU

БЕСПЛАТНАЯ ЭЛЕКТРОННАЯ БИБЛИОТЕКА

   Добро пожаловать!


Pages:     | 1 || 3 | 4 |

тельность выполнения выражений – слева направо и сверху вниз с Примеры:

учетом приоритета операторов;

every i:=1 to 100 by 10 do write(i) во-вторых, возврат назад для того, чтобы найти подвыражеВыход: ние, генерирующее более одного значения, взять новое значение и повторить процесс.

Этот возврат с перебором называется бэктрекингом. Прото....

типами бэктрекинга являются различные конструкции, органи зующие циклы. Бэктрекинг – «главный кит» Пролога, наряду с every {writes(" ",1 to 5); writes(" ",6 to 10)} подстановкой и унификацией. Он использует его, как нечто само Выход: 1 6 7 8 9 собой разумеющееся. Например, человек, знакомый только с Си, Но не сможет понять, что предикат p:

every (writes(" ",1 to 5), writes(" ",6 to 10)) p:-fact1(_,_,X,_),fact2(_,Y,_), X

дает на выходе:

1 6 7 8 9 10 2 6 7 8 9 10 3 6 7 8 9 10 4 6 7 8 9 10 5 6 7 8 9 переберет все экземпляры фактов fact1, fact2, чтобы найти первую их комбинацию, удовлетворяющую условию X

Icon'е контекст перебора почти всегда должен быть указан явно, 1. После генерации первого из возможных значений вырат. е. одного оператора, имеющего статус генератора, недостаточ- жения eно. Например: управление передается выражению e2.

2. e2 генерирует все возможные значения.

f:=open("myfile.txt,"rt") 3. Затем e1 генерирует следующее значение и т. д.

..........................

S:=!f # читается одна запись файла e1 и e2 могут быть успешными и неуспешными.

Но выражение every(write(!f)) выведет построчно на экран every i:=1 to 5 do writes(" ",i) все записи (несколько ниже приведен пример кода в чисто «про- S:=every S<4 do writes(" ",17 to 18) логовском» стиле).

Выход: нет выхода.

Если же мы напишем every S<4, то будет напечатано число 2.1. Every, to, every do 17.

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

13 2.2. !e – генерация элементов end Выход: – исходная строка S и O'key с новой строки.

Если e – некоторая структура, то !e берет первый элемент Проверка каждого символа на равенство символу перевода структуры, а в контексте генерации генерирует множество элестроки порождает неуспех вплоть до последнего символа, что заментов этой структуры.

ставляет первое подвыражение (sim:=!S) генерировать новые симПримеры:

волы. В итоге напечатается строка S, а затем O'key.

L:=[1,2];every writes(" ",!L).#Выход: 1 s:="cat";every writes(" ",!s).#Выход: c a t 2.5. Проверка на &null Бинарные операции, содержащие генераторы:

every writes(" ",5 to 6)+(10 to 20)) Унарный оператор ‘\’ успешен, если его операнд имеет знанапечатает 15 25 16 26 чение, отличное от &null, а ‘/’ – в противном случае, т. е. мы мо жем написать 2.3. Оператор & – and if \x & \y then...".

Если x не присвоено значение, мы не можем написать if e1&e~x…, но должны написать if /x ….

Этот оператор возвращает значение правого операнда и имеет наинизший приоритет.

2.6. Альтернатива | every i:=|seq(1,2)\3 & j:=|seq(2,2)\3 & i~= j & writes(" ",i+j) Выход: 3 5 7 5 7 9 7 9 11 Вертикальная черта ‘|’, читаемая как «или», смотрится как бинарный оператор, но появляется и в ином контексте. Выраже2.4. Backtracking и неуспех ние:

e1 | e2 означает генерацию всех элементов e1, а затем – всех Перебор прекращается, когда перебирать уже нечего, и e2.

управление переходит к следующему выражению. Например, наprocedure main() печать 12345 можно так (не рассматривая очевидный вариант local x,y,z write("12345")): every writes (1 to 5).

L:=["Vera","Manja","Tanja"] Этот же результат можно получить, если использовать x:=встроенное в Icon выражение &fail, которое всегда порождает неif (\x | \y) then z:=успех.

(writes(" ",!L) | write(" ",z)) write (1 to 5) + &fail.

every (writes(" ",!L) | write(" ",z)) write("\n","O'key") #while (writes(" ",!L)) | write(" ",z)) Знак ‘+’ нужен только для конструирования синтаксически end правильного выражения, т. е. контекст генерции задается "неуспеВыход: Vera Vera Manja Tanja хом".

Если раскомментировать выражение перед end, то получим Тогда мы можем использовать чисто «прологовский» стиль:

бесконечную печать слова Vera.

procedure main() S:="tak pit hochetsa, chto perenochevat negde\n" (sim:=!S, writes(sim),sim=="\n") write("O'key") 15 2.7. Повторы с ограничением. Функция генерации после- every writes(" ",(!S,1 to 3)) довательностей write() every writes(" ",(!S & 1 to 3)) Генератор «с перезарядкой» |e позволяет генерировать все end значения e, затем происходит реинициализация и процесс повтоВыход:

ряется бесконечно.

q q q w w w e e e r r r t t t y y y u u u Чтобы избежать бесконечного повторения процесса, исполь1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 зуется ограничитель числа повторений: |e\n.

1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 Например: every |(writes(7))\7 выведет 7777777, так же, как и every (writes(|7\7)), и every i:=1 to 7 do writes(7).

2.9. Множественные арифметические операции сравнения Специальная функция seq() предназначена для генерации бесконечных рядов значений Такие операции, как a



seq(i,j) генерирует i+j,i+2j,i+3j.. x:=x>y или x>:=y every writes(" ",seq(2,2)\5) выведет 2 4 6 8 как и every writes(" ",seq(2,2))\2.8. Coevaluation – «Совычисления» В общем виде совычисления представляются так:

e0(e1,e2,...,eN), где e0 – выражение, вычисляющее номер выражения в скобках, которое генерирует значения, и может быть переменной, значение которой есть целое число, вычисляемое где-то в другом месте программы. Действия остальных заключаются в активации бэктрекинга.

«Вырожденная» форма:

(e1,e2,...,eN) эквивалентна N(e1,e2,...,eN) или (e1&e2&...&eN).

Пример:

procedure main() K:=S:="qwertyu" every writes(" ",K(!S,1 to 3)) write() 17 3.4. until do 3. Управляющие структуры until e1 do e3.1. if...

Эквивалентно while not e1 do eПример: Печать чисел Фибоначчи if e1 then e2 else eprocedure main() if e1 then elocal i,j e1 может генерировать не более одного значения i:=1;j:=e3 могут генерировать столько значений, сколько позволяет until i>100 do {write(i,j);i+:=j;i:=:j} контекст.

end 3.2. case of 3.5. repeat – повторять до бесконечности.

case e1 of i:={ repeat e2 : e{ if i<10 then {write("i меньше 10");i:=i+1} else break e4 : e}...

e2n : e2n+default : e2n+ } 3.3. while do while e1 do ewhile eГенерируется одно значение e1, и если НЕ ЛОЖЬ, то выполняется e2.

Пример:

i:=while i<2 do {writes(" ",i);i+:=1} Выход: 0 В следующем примере будут бесконечно «печататься» на экране вводимые Вами строки символов:

while write(read( )) 19 4. Символьные множества 5. Строки Множества символов заключается в апострофы: 'abcd'. В S:="This is string" Icon'е существуют следующие встроенные множества символов:

&ascii – 128 символов ASCII.

Для того чтобы выбрать i-ый символ строки, следует рас&cset – 256 символов.

сматривать строку как массив символов s:=S[i]. Вы можете при&digits – цифры ('0123456789').

своить иное значение символу в строке, заданной переменной, но &lcase – множество символов латиницы в нижнем регистре.

не можете сделать то же самое для строки – литерала:

&ucase – множество символов латиницы в верхнем регистре.

S[1]:="t" – допустимо. "This is string"[1]:="t" – недопустимо.

&letters – все символы латиницы (объединение &lcase и Значение индекса может быть отрицательным целым.

&ucase).

procedure main() S:="This is string" 4.1. Операции с множествами символов writes(S[1]) writes(" ",S[14]) -c – производит множество cset, состоящее из символов, не writes(" ",S[-1]) встречающихся в c.

end *c – число элементов c.

Выход: T g g c1**c2 – пересечение c1 с c2.

c1++c2 – объединение c1 и c2.

5.1. Подстроки c1--c2 – «разность» между c1 и c2. Итоговое множество включает только те символы из c1, которых нет в c2.

Выделяя подстроки индексированием, следует иметь в виду неочевидное:

4.2. Принадлежит ли символ множеству Функция any при указании индексов слева направо первый индекс есть номер левого символа подстроки, второй – правый выбираемый any(c,s) – возвращает 2, если s[1] существует и является элесимвол, указываемый как <порядковый номер> + 1;

ментом множества c.

при указании подстроки справа налево с использованием any(c,s,i) – возвращает i+1, если s[i] существует и является отрицательных значений, 0 – есть крайний правый символ, -(n+1) элементом множества c.

указывает на крайний левый выбираемый символ (n-ый справа).

……………………………………………….

S:="This is string" write(S[9:15])# Получим на выходе string.

write(S[0:-6])# Получим на выходе string.

write(S[15:9])# Получим на выходе string.

#Как видим, таким способом подстрока не реверсируется.

write(S[2:0])# Получим на выходе his is string write(S[-1:1])# Получим на выходе This is strin write(S[9:12])" Получим на выходе str 21 Вы можете подстроке строки, заданной переменной, при- map(s1,s2,s3) – каждый символ в s1, встречающийся в s2 в своить подстроку, но не литералу: позиции j, заменяется на s3[j].

S[9:15]:="xxxxxx" – нормально, mapstrs(s,L1,L2) – замена подстрок, L1 и L2 – списки подно не "This is string"[9:15]:="xxxxxxx". строк. Каждая подстрока в s, являющаяся элементом L1, заменяетS[i+:j] эквивалентно S[i:i+j], S[i-:j] эквивалентно S[i:i-j], ся на соответствующий элемент L2. (Следуют подключить модуль mapstrs из библиотеки Icon'а, т. е. link mapstrs).

5.2. Операторы для работы со строками replace(s1,s2,s3) – каждое появление s2 в s1 заменяется на s3.

repl(s,i) – i раз повторяет строку s: s||s...||s.

procedure main() revers(s) – реверсирует s.

s1:="String 1" string(x) – преобразует число или множество символов (cset) s2:="String 2" в строку.

s3:="String 3" trim(s) – удаляет концевые пробелы из s.

s4:="String 2" s5:="STRING 2" 5.4. Функции сканирования строк s7:="string string string" write(s1||" "||s2||" "||s3||" "||s4||" "||"STRING 2") Общая форма функций сканирования строк:

if s1==s2 then write("s1==s2") # Не верно function(x,s,i,j), где x – это то, что мы ищем, s – просматриif s1==s3 then write("s1==s3") # Не верно ваемая строка, i – позиция начала поиска, j – позиция завершения if s2==s4 then write("s2==s4") # Верно поиска.

if s1»s2 then write("s1»s2") # # Не верно Некоторые функции возвращают первую позицию найденif s1»s2 then write("s1»s2") # Верно ного, другие – все позиции вхождения.

if s5»s4 then write(s5»s4) # Верно any(c,s) – возвращает 2, если s[1] существует и является every write(" ",!s3) # ! – выбор первого символа символом в множестве (cset), иначе – неуспех.





every write(s3[1 to *s3]) # эквивалентно any(c,s,i) – возвращает i+1, если s[i] существует и является write(s3) # s3 – выбор произвольного символа символом в множестве (cset) c, иначе – неуспех.

end any(c,s,i,j) – возвращает i+1 (i

5.3. Функции для преобразования строк find(s1,s2) – возвращает все начальные позиции вхождения s1 в s2.

center(s,i) – выравнивание по центру на длину i, если i>*s, то в пределах от 1 до *s2-*1 (естественно, в контексте генерафункция возвращает i центральных символов. Работает с кирилции, иначе возвращает только позицию первого вхождения).

лицей.

Пример:

center(s,i,s2) – выравнивание по центру на длину i с добавлеprocedure main() нием слева и справа символов из строки s2.

s:="1D2a3b4c5d2a12342a" char(i) – возвращает односимвольную строку, соответствуюevery writes(" ",find("2a",s)) щую представлению символа в виде целого числа (от 0 до 255).

end map(s) – удобно использовать для преобразования строки из Выход: 3 11 верхнего в нижний регистр.

23 many(c,s) – возвращает позицию, следующую за наиболее procedure idents(s) длинной подстрокой в s, все символы которой принадлежат сим- local i, j, initIdChars, idChars вольному множеству c. Возвращает *s+1, если все символы из s initIdChars := &letters++’_’ принадлежат c. Неуспешна, если s[1] не принадлежит c. idChars := initIdChars++&digits many(c,s,i) – все то же, только поиск начинается с позиции i. i := many(c,s,i,j) – все то же, только рассматривается подстрока while j := upto(initIdChars,s,i) & s[i:j] (состоящая из символов s[1],s[2],…,s[j-1]). not any(idChars,s[j-1]) & Примеры k := many(idChars,s,j) do { s:=”abcd”; write(many(&lcase,s)) suspend s[j:k] Выход: 5 i:=k } s:=”abcD”; write(many(&lcase,s)) end Выход: Давайте изменим эту программу так, чтобы она работала и с s:=”Dabcd”; if many(&lcase,s) then write(“O’KEY”) кириллицей и выводила информацию в файл:

else write(“NO!!”) global allRus Выход: NO!! procedure main() allRus:='АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЬЪЫЭ match(s1,s2) – возвращает *s1+1, если s2[1:*s1+1]==s1 ЮЯабвгдеёжзийклмнопрстуфхцчшщьъыэюя' match(s1,s2,i) – возвращает *s1+I, если s2[i:*s1+i]==s1 s:="Это кириллические идентификаторы с первым непраmatch(s1,s2,i,j) – то же самое, только j ограничивает поиск вильным: 17и а_85 б56" справа. s1:="a111_d t75" upto(c,s) – возвращает позиции в s от 1 to *s, которые содер- my_file:=open("idents.txt","wt") жат символы из c. every write(my_file,idents(s)) Пример: end s:=”1D2a3b4c5d” procedure idents(s) every writes(upto(&digits,s)) local i, j, initIdChars, idChars Выход 13579 initIdChars := &letters++'_'++allRus idChars := initIdChars++&digits upto(c,s,i) – то же, только поиск в s начинается с позиции i. s suspend tab(upto(initIdChars)) & upto(c,s,i,j) – поиск в s начинается с позиции i и заканчивает- pos(1) | (move(-1),tab(any(~idChars))) & ся в позиции j. tab(many(idChars)) В [3] приведен пример программы, выделяющий из строки end правильные идентификаторы – цепочки символов, состоящие Выход:

только из букв латиницы, знаков подчеркивания и цифр (не в пер- Это кириллические идентификаторы с первым неправильвой позиции): ным а_85 б#generate identifiers in string 25 5.5. Более мощные варианты функций сканирования s {writes(tab(4));writes(move(4))} end Функции any, many, match, find не слишком удобны, поВыход: aaa bbbc скольку требуют сохранять позицию в строке, а также имя строчной переменной.

Теперь с использованием оператора сканирования строки Улучшить ситуацию позволяет оператор сканирования строподпрограмма выделения идентификаторов будет выглядеть так ки ‘’, используемый в виде s e, где s – строка, а e – некоторое [3, с. 78]:

выражение.

#generate identifiers in string Вычисляя выражение e, Icon использует специальные переprocedure idents(s) менные &subject и &pos.

local i, j, initIdChars, idChars При этом Icon делает следующее:

initIdChars := &letters++’_’ Устанавливает конкретное значение s.

idChars := initIdChars++&digits Сохраняет предшествующие значения &subject и &pos.

s suspend tab(upto(initIdChars)) & &subject присваивает значение s, а &pos устанавливает на 1.

pos(1) | (move(-1),tab(any(~idChars))) & Вычисляет e.

tab(many(idChars)) Восстанавливает сохраненные на шаге 2 значения &subject и end &pos.

Возвращает значение e.

В случае использования оператора ‘’ наилучший способ изменения &pos – это использование функций tab(i) и move(j).

Первая присваивает &pos некоторое абсолютное значение i, а вторая «перемещает» позицию на &pos+j. Обе функции возвращают подстроку между начальной и новой позициями.

Примеры:

procedure main() s:="aaabbbccc" s write(tab(4)) end Выход: aaa procedure main() s:="aaabbbccc" s write(move(4)) end Выход: aaab procedure main() s:="aaabbbccc" 27 6.4. Функции для работы со списками 6. Списки copy(L) – создает копию L (L1:=copy(L)).

Список – последовательность элементов, разделенных запяset(L) – создает множество из списка (seT:=set(L)).

той и заключенных в квадратные скобки. Элементами одного спиsort(L) – создает новый отсортированный список. Элементы ска могут быть различные структуры данных, допустимые в Icon'е, одного типа группируются вместе, составные объекты размещав том числе и списки.

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

Pages:     | 1 || 3 | 4 |










© 2011 www.dissers.ru - «Бесплатная электронная библиотека»

Материалы этого сайта размещены для ознакомления, все права принадлежат их авторам.
Если Вы не согласны с тем, что Ваш материал размещён на этом сайте, пожалуйста, напишите нам, мы в течении 1-2 рабочих дней удалим его.