Страница произведения
Войти
Зарегистрироваться
Страница произведения

Руководство по Фокалу


Автор:
Жанр:
Изобретательство
Опубликован:
22.04.2025 — 23.04.2025
Читателей:
1
Аннотация:
Нет описания
Предыдущая глава  
↓ Содержание ↓
↑ Свернуть ↑
  Следующая глава
 
 

ему не указали количество символов, удаляет одну из этих трёх частей. А вот

если указано, то... Например в А2: "123456789 абвгдеёжз 123456789 ийклмнопр"

маркер стоит вот в этой позиции: ~~~~~ (попал он сюда: ^13~5)

/3 удалит:


* * *

-/3 удалит:


* * *

+/3 удалит:


* * *

Сразу и заранее предупреждаю: форматное выражение оператора Write это

всегда одно "слово": как только встретился конец оператора, например точка с

запятой, или запятая, разделяющая его части, или даже просто пробел — значит

форматное выражение кончилось. (Эти символы могут быть там только в составе

текстовых констант. То есть в кавычках.)

Поэтому в роли пробела там символ '_' (подчеркивание) — пустая операция,

которая ничего не делает, за-то всегда успешно.

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

Вернее, дело обстоит так: чтобы немедленно прекратить выполнение форматного выражения есть операция '!', которая еще и вывод текущей строки запрещает. (А если надо всё наоборот: строку вывести, а выполнение форматного выражения продолжить — есть операци '.' (точка).) А для того, чтобы в зависимости от успешности/неуспешности выполнения очередной операции поступить по-разному — есть "постфиксы" '&' '' '?'. Например в: 'x&y' 'xz' 'x?yz' операция y выполняется если x выполнилась успешно, а операция z — если нет. Но во всех случаях обработка строки после этого продолжается. А вот если её таки надо завершить, то: 'х&'. (Другие варианты тоже грамматически правильны, но смысла не имеют: 'x\' это то же самое, что просто 'x'; 'x?y' то же самое что просто 'xy'; а 'x?z' делает то же что и 'х&'.

Но это мы таки сильно забежали вперёд... Вернёмся к нашим баранам.

Вот например надо во всех копируемых строчках заменить "Вася" на "Петя".

Запросто: Write %"Вася"*"Петя" (изначально '+' был необязателен)

W %^+"Вася"*"Петя" (^ чтобы точно с начала строки)

— Ага, один раз. А если слов "Вася" в строке несколько?

— Нам нужен префикс повторения!

Ага.

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

А у нас их здесь две: найти и заменить.

— Значит еще нужны скобки, группирующие несколько операций в одну.

Вот где-то так: Write %@(+"Вася"*"Петя")

Замечательно.

— А когда этот наш цикл кончится?

— Когда +"Вася" больше ничего не найдёт.

Ага.

Отсюда идея, что если очередная операция выполнилась неуспешно, то на

этом — всё: выполнение форматного выражения прекращается. (Ага: это для текущей

строки прекращается. Write сбрасывает её в канал вывода, берёт следующую из

канала ввода и всё по-новой...)

— А если всётаки надо продолжить?

— На этот случай введём "постфиксы" '&' и '' которые берут этот самый статус

успешности/неуспешности предыдущей операции и либо выполняют либо пропускают

следующую. То есть '&' если да, а '' если нет. А еще универсальный '?' сразу

для обоих случаев.

(Сначала я его было сделал как скобки — по аналогии с условным выражением

? : языка Си, задействовав в качестве закрывающей скобки символ '|', но потом

таки одумался: просто две следующие операции, а скобки у нас и так уже есть.)

Кстати о птичках, то есть о скобках: префиксы + и — (в отличии от @)

действуют на операции только "персонально". Поэтому +(...) не даст никакого

эффекта: префиксу действовать не на кого. И он выполнит свою исходную миссию:

сдвиг маркера на одну позицию.

Ах, да: уж коли у нас маркер приобрёл размер, то надо бы и его научиться

устанавливать: ~45 (вот — в 45 символов). А так же ~$ и ~^ — от текущего места

до конца и до начала строки. (А еще ~. — до "метки", но про метку — потом...)

А кроме этого операция вставки устанавливает маркер по размеру

вставленного, поиска — по размеру найденного, а вот перемещение и удаление его

размер обнуляют.

В том числе и сдвиг на 0 позиций. Но просто 0 или -0 оставляют маркер там,

где он был (только размер у него теперь будет нулевой, как и после любого

перемещения), а вот +0 таки его сдвигает — на размер самого маркера.

А что это мы всё без молока да без молока? В смысле — исключительно с

константами? У нас здесь язык программирования, или я где?! У нас же

переменных полно — пусть пользу приносят! (Чем мы хуже кота Матроскина?)

В общем текущее положение маркера... А вернее размер любой из трёх частей,

на которые он делит строку в А2, сохраняем в переменной следующим образом: =Х

+=Х и -=Х чтобы потом применить (вместо числовой константы) как #Х (где Х -

одна буковка). И пусть в миру (то есть в самом Фокале) и имя у этой переменной

будет такое-же: #Х. Мы еще не забыли, что всякие # $ & |... там тоже считаются

буквами, и такое имя — вполне допустимо?

Получились еще две операции: '=' и '#' — "сохранить" и "применить",

нуждающиеся в уточнении, где именно сохранять (и что потом применять). В том

числе текущее положение маркера в некотором тихом месте: =. чтобы потом

обменять их с маркером местами: #. т.е. это вот та самая, уже упоминавшаяся

"метка". Штука, кстати, весьма удобная...

Вот, значит, какая задача: копируем строки с помощью оператора Write %...

и если в строке есть символ : (двоеточие), то само это двоеточие удалить, а

текст перед ним перенести в конец строки и "отгородить" от её содержимого

символом ; (точка с запятой). (Это мы ассемблерную программу покалечить хотим:

превратить все метки в комментарии.)

— Ага, разбежались! Надо где-то сохранять вот этот переносимый фрагмент

строки. (А то придётся таскать по одному символу...)

Поэтому по аналогии с переменными для чисел, введём "регистры" для таких

вот текстовых фрагментов. И обозначим их цифрами 0..9, а в остальном — всё то

же самое. И сразу договоримся: что если пишем фрагмент в седьмой регистр =7 то

в переменную #7 пусть автоматически записывается его размер. Вот теперь:

Write %+":"/-=1-/$*';'+*#1

Непонятно? А навставляем _ (аналог пробела), пронумеруем и прокомментируем:

Write %___+":"___/___-=1___-/___$___*';'___+*#1

0 1 2 3 4 5 6 7

0. думаем, что изначально маркер стоит в начале строки (так оно и есть)

1. ищем символ "двоеточие" (если не найдём, то на этом всё и кончится)

2. удаляем найденное

3. сохраняем в регистре 1 всё, что перед маркером (было перед двоеточием)

4. всё что перед маркером — удаляем

5. ставим маркер в конец строки

6. вставляем туда точку с запятой

7. после того что под маркером (а там только что вставленная ';') вставляем

фрагмент, ранее сохраненный в регистре 1

Пробуем.

Фокус не получился — факир был пьян! Нет, с терминала-то всё нормально,

а вот из файла... Там оказывается в конце каждой строки символ перехода на

следующую. (Даже два: перевод строки и возврат каретки.) Вот после них мы

этот текст и пристроили! А редактор командной строки, с помощью которого мы

набираем строчки на терминале, оказывается таковых не вставляет. Надо бы не

конец строки искать, а вот их...

Забегая вперёд, скажу, что это будет выглядеть: +{!}

Write %___+":"___/___-=1___-/___+{!}___*';'___+*#1

1 2 3 4 5а 6 7

Пробуем. (Но сейчас уже только с файлом)

Опять не слава богу! Нет, всё сработало, кроме последней строки, где

оказывается нету перехода на следующую. Вот там +{!} ничего не нашла и

соответственно операции 6 и 7 уже не выполнились.

Ладно, пишем так:

Write %___+":"___/___-=1___-/___$___-{!}____-*';'___+*#1

1 2 3 4 5 5б 6 7

Здесь: 5 — ставит маркер в конец строки и 5б — ищет этот самый переход на

следующую, но от конца к началу, а если не нашла, то конструкция _ (не

делающая ничего содержательного) просто не даст прекратить выполнение.

Ну вот сейчас наконец-то всё отработало правильно...

Выражения: {...}

{!} — это вот как раз было оно, причем экзотического "текстового" типа...

Для универсальности одних переменных недостаточно! Тем более, что в нашем

распоряжении вся хилая мощь КАЛькулятора ФОрмул! Но фокаловское выражение

"изолируем" от форматного с помощью фигурных скобочек. И используем как

числовой параметр целую часть его значения. В {...} кроме выражения (которое

там должно быть только одно) могут быть символы _ (подчеркивание) в роли

пробела и конструкции =Х ("присваивание", где Х — буква) чтобы при

необходимости сохранять вычисленное в переменных.

Разумеется, в таком выражении ничто не мешает использовать функцию FSBr,

которая вообще-то обращение к подпрограмме. И таким образом для каждой

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

маркера таки попортит... (Впрочем, дело поправимое: =Х{fsbr(....)}~#X)

Выражение текстового типа устроено в точности так же, но отличается тем,

что начинается с чего-то однозначно текстового, результатом имеет строку, а

в присваивании =N должна быть цифра, указывающая номер регистра чтобы её

сохранить. Единственная операция — сцепление элементов ("конкатенация")

специально никак не обозначается. А числовые значения, которые там тоже могут

присутствовать, обозначают коды символов.

Ради них по большому счету это и затеяно: ну нету в Фокале концепции

"экранирующего символа". Как например в Си (и вообще в UNIX`е), где это

(обратная косая черта), позволяющая в "..." изобразить как служебные символы,

включая самоё себя и огораживающие эту константу кавычки, так и коды,

графических обозначений просто не имеющие. (И потому известные как "слепые".)

Так уж исторически сложилось, что коды символов в Фокале сами по себе: с

ними работала исключительно функция FCHR, а текстовые константы тоже сами по

себе — исключительно для общения программы с пользователем. И вместе сошлись

они вот только сейчас. Вот и.

Еще в текстовом выражении кроме констант вида "..." и кодов символов,

включая обозначающий конец строки восклицательный знак, могут быть конструкции

#N и :NNN, где N — номер регистра, а NNN — номер программной строки.

(N — одна цифра, а NNN — выражение общего вида).

Конструкция {...} понравилась и тут же нашлось множество желающих её

использовать: @{...} #{...} ={...} %{...}

Префикс повторения конечно же самый первый! (Куда уж без него...) Нет,

если всего лишь надо указать количество повторений — нет проблем. Например:

@12+*'*' вставит ровно двенадцать звёздочек. (+* а не просто * потому, что

оно не вставить, а заменить норовит — то, что под маркером. А под маркером то,

что вставлено в прошлый раз, т.е. предыдущая звёздочка.)

А вот полноценный заголовок, с переменной-счетчиком, начальным, конечным

значением и шагом — всё как в операторе For i=0,44,2;.... — @{0,44,2=i}....

— Ага-ага! А как же запятые?! Их же в форматном выражении — низзя...

— Так ведь в фигурных скобочках. Там в выражении и они и в обращении к функции

могут быть и между индексами... Ну ладно, поелику это и в самом деле вроде как

нарушение принципов, от сего момента заменим все запятые на '|' хотя пока

(временно!) разрешим оба варианта. Тогда аналог For i=0,44,2;.. — @{0|44|2=i}..

— н-да, а с запятыми-то лучше смотрится... Привычнее...

И к тому же символ | это ведь буква? Ну да — не цифра и не разделитель.

И назначать её разделителем только вот ради этого случая... В общем нехорошо

получилось! Вернём-ка мы всё это в зад. Но попозже...

Заголовок цикла может быть и в виде текстовой константы. Он сопоставляется

с фрагментом строки начиная с текущего положения маркера. И отличается

возможностью дополнительно содержать ^ и $ указывающих начало и конец строки.

Если учесть, что конструкция из заголовка цикла и постфикса (без "тела

цикла") — суть условное выражение, где заголовок цикла отрабатывает ровно один

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

еще небыло. К тому же строчное значение, не будучи чьим-то правым операндом,

даже без + (как сейчас) так и норовило пройтись по всей строке...

Конструкция %{...} это обращение к одной из программных строк, номер

которой указан выражением в скобках. Выражение — только числовое. (Хотя по

аналогии с :номер_строки в строчном выражении и может начинаться с двоеточия.)

Смысла в текстовом выражении в данном случае нет ровно никакого: к подпрограмме

в регистре N обращаемся: %N, а модная нынче "лямбда" (где она есть), дающая

анонимную подпрограмму, нужна вовсе не для того, чтобы эту подпрограмму сразу

же и выполнить (что нам мешает сделать эти действия просто так?), а чтобы

заховать куда-то на черный день, или передать кому-то в виде параметра...

Как и любой уважающей себя подпрограмме, этим тоже полагаются параметры.

Хотя бы один. В качестве которого — следующая после %N или %{...} конструкция.

Она не выполняется и доступна в "подпрограмме" как текстовый фрагмент (без

ограничивающих её скобочек или кавычек, если конструкция составная) с помощью

#%. Хотя можно и выполнить: %%.

Обратим внимание: кроме %{...} и %N может быть еще и %Х (где Х — буква).

— Ну и чем же это %Х отличается от просто Х?

— А вот этой самой возможностью получения следующего за ним параметра.

Вообще-то сложилось забавное положение: всё наше форматное выражение

задумано как Write %Буква; — каковая буква укажет одно из встроенных

преобразований, которых до сих пор... (Вот именно!)

А Write %_какие_то_операции_; — это чисто от бедности. Однако, если среди

них эта самая Буква таки встретится... То должна отработать то, что ей

поручено — применительно к тому фрагменту строки в А2, который в этот момент

под маркером. Для чего сделано так, чтобы в самом начале — когда строчка

только-только прочитана, маркер стоял в её начале и включал её всю.

Но теперь вдруг появилось два варианта: просто Буква и %Буква, отличающийся

вот как раз наличием параметра... Которого, как оказалось, нам так не хватало!

Дело в том, что предполагалось, что все эти встроенные преобразования будут

перекодировками — чтобы просматривать тексты, записанные не одной только 866-й

(ДОС`овской)... А вот захотим мы преобразовать из одной кодировки в другую...

Можно конечно и в два этапа — сначала в текущую ДОС`овскую, а потом из неё. Но

честно говоря, это не есть хорошо: в ДОС`овской может например не быть

некоторых символов, которые есть в этих двух — в обоих. А тут пожалуйста: %Xy.

123 ... 56789 ... 121314
Предыдущая глава  
↓ Содержание ↓
↑ Свернуть ↑
  Следующая глава



Иные расы и виды существ 11 списков
Ангелы (Произведений: 91)
Оборотни (Произведений: 181)
Орки, гоблины, гномы, назгулы, тролли (Произведений: 41)
Эльфы, эльфы-полукровки, дроу (Произведений: 230)
Привидения, призраки, полтергейсты, духи (Произведений: 74)
Боги, полубоги, божественные сущности (Произведений: 165)
Вампиры (Произведений: 241)
Демоны (Произведений: 265)
Драконы (Произведений: 164)
Особенная раса, вид (созданные автором) (Произведений: 122)
Редкие расы (но не авторские) (Произведений: 107)
Профессии, занятия, стили жизни 8 списков
Внутренний мир человека. Мысли и жизнь 4 списка
Миры фэнтези и фантастики: каноны, апокрифы, смешение жанров 7 списков
О взаимоотношениях 7 списков
Герои 13 списков
Земля 6 списков
Альтернативная история (Произведений: 213)
Аномальные зоны (Произведений: 73)
Городские истории (Произведений: 306)
Исторические фантазии (Произведений: 98)
Постапокалиптика (Произведений: 104)
Стилизации и этнические мотивы (Произведений: 130)
Попадалово 5 списков
Противостояние 9 списков
О чувствах 3 списка
Следующее поколение 4 списка
Детское фэнтези (Произведений: 39)
Для самых маленьких (Произведений: 34)
О животных (Произведений: 48)
Поучительные сказки, притчи (Произведений: 82)
Закрыть
Закрыть
Закрыть
↑ Вверх