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

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


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

уравнения А-ИКС-квадрат плюс Бэ-ИКС плюс Це равняется нулю ( A*X^2+B*X+C=0 )

с конкретными А, Бэ и Цэ, которые нам дадут потом.

(Да: по-мне, так это тоже банально. Но искать например корни кубического

уравнения по формуле Кардано — громоздко. Да и не общеизвестно: в школе этого

обычно не проходят.)

Инструмент — интерпретатор Фокала. Это один выполняемый ДОС`овский файл

foc.exe и к нему еще один текстовый файл foc.hlp (или foc-1b.hlp) — справка.

Он же — основная документация. Его наличие не обязательно, но оператор Help

не будет работать.

Еще более необязателен файл _fpks.txt, но если он есть, то в нём сохраняются

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

А в файле sav.f интерпретатор обычно предлагает сохранить программу. И если

он есть — при запуске пытается загрузить её обратно. (Но только если в

командной строке при запуске интерпретатора на этот счет ничего не указано.)

В оные времена Фокал работал на "голой" машине и был сам себе операционной системой. Самое близкое к этому — ДОС, который сидит себе в уголочке памяти, предоставляет файловый сервис и больше ни во что не вмешивается. Всё остальное Фокал делает сам или через функции БИОС`a. Версии под другие ОС планируются после отработки основных концепций и получатся они только ограниченные: например функцию FX реализовать там не представляется возможным...

Впрочем, ДОС`овские программы и под виндой работают — до XP включительно.

Запустим интерпретатор любым способом. Например набрав в командной строке

операционной системы: foc

Что видим: черный экран и на нём * (звёздочка). Это интерпретатор ждёт ввода

очередной командной строки. Хотя сперва мог выдать некоторое "приветствие".

(Чтобы не выдавал — см. в файле справки — строки этак с двадцать пятой: там

еще написано "сам себе ини-файл"...)

Вошли — сразу выйдем, набрав оператор Quit и нажав кнопку ввод. (Достаточно

просто Q.)

Но можно было нажать кнопку ЕСЦ. Тогда, если в памяти есть несохраненные

строки, интерпретатор предложил бы их сохранить, сформировав командную строку,

в конце которой — всё тот же оператор Quit. Её можно малость отредактировать,

например стерев это Q в конце. Или изменив имя файла, в котором сохранять. Или

вообще отказаться, еще раз нажав ЕСЦ — командная строка просто станет пустой.

И тогда по следующему ЕСЦ интерпретатор завершит свою работу.

Quit это в любом Фокале, а ЕСЦ — только в данной реализации.

Вышли — запустим по-новой.

Самой первой всегда пишут такую программу, которая бы проявила хоть какую-то

видимую активность. Например написала на терминале "Ха!" Или "Привет, люди!",

или еще какую подобную фразу, но на буржуйском языке. (С русскими буквами

бывают проблемы. В том числе злонамеренно созданные...) А для микроконтроллера,

у которого никакого терминала нет — хотя бы светодиодом помигала, припаянным к

одному из его выводов...

Написать:

Type 2*2

конечно тоже можно, но лучше всётаки:

Type "Привет, люди!", !

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

переход на следующую строку. А всё, что в кавычках — выводится один в один.

(Якобы как пояснение к выводимым числам.) Запятую, которая разделяет эти два

элемента списка вывода, впринципе можно и не писать: и кавычки и

восклицательный знак и пробелы (которые можно вставлять в любых количествах)

сами по себе символы-разделители.

И, да: если нам нужно чтобы в тексте были кавычки — заключаем его в кавычки

другого типа, благо их три: " ' `

Но мы же хотели программу! Поэтому пишем:

1.1 Type "Привет, люди!", !

А потом:

Go

Или Do; или Go All; или Go 1; или Go 1.1; Эффект будет один и тот же.

Впрочем, нет: если вдруг в каталоге был файл sav.f а мы и не заметили, то в

памяти будет его содержимое, и уж что оно сделает... Вот если бы написали

Do 1.1

то точно бы выполнилась только и исключительно строка с номером 1.1, а вот

по другому... (Go — просто передача управления, а Do — подпрограмме, "взаймы".)

Поэтому перед вводом программы часто пишут Eraze Ales; (разумеется E A вполне

достаточно) чтобы в памяти уж точно ничего "лишнего" небыло.

А мы возьмём и проверим:

Write

или:

Write A

Во втором случае перед текстом программы будет добавлен заголовок — у данной

реализации в виде двух строчек комментариев: номер версии и текущие дата/время.

Вот кстати полезный оператор Comment весь остаток строки после которого

просто игнорируется. Предназначен для написания пояснений. Но можно например

взять и "закомментировать" ненужную пока програмную строчку, просто дописав в

её начале букву Ц — чтобы потом, когда понадобится, заново не вводить. Если

текст программы набирается отдельно — с помощью текстового редактора, то

сделать это ничего не стоит. А вот удалить, а потом вспоминать, что в

удалённой строке было написано, да еще и не ошибиться при её повторном наборе...

Но и в Фокале есть оператор Modify чтобы исправлять уже имеющиеся в памяти

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

Ну ладно, побаловались и будя. Решаем уравнение A*X^2 + B*X + C = 0

для чего нам дали три конкретных числа и сказали что вот это и есть А, Бэ и Цэ.

Элементарно — через "дискриминант": D = B^2 — 4*A*C; и если D>=0

то x1= (-A + корень(D))/(2*B)

а x2= (-A — корень(D))/(2*B)

Все эти действия можно проделать и на калькуляторе и на линейке

(логарифмической) и просто с помощью карандаша и бумаги, и даже на счетах.

Вот только корень... Хотя раньше в школе учили и корни тоже вручную вычислять.

(А вот нас — уже нет.)

Но вот следующей задачей будет: решить не одно такое уравнение, а сорок

тысяч штук! Типа кто-то выдаст нам файл, содержащий сорок тысяч комплектов по

три числа в строчке. И вот тут уже бумажкой с карандашом не обойдёшься...

Поэтому не ленимся — пишем:

Set A=.....; Set B=.....; Set C=.....

где вместо точек — конкретные, данные нам числа

Set D = B^2 — 4*A*C; Type D

и если число D — неотрицательное, то:

Type (-A + FSQrt(D))/(2*B)

Type (-A — FSQrt(D))/(2*B)

всё — для одного конкретного набора чисел задачу решили.

Так сказать "единичную" задачу. А теперь решим "массовую": сделав из этого

подпрограмму. Предусмотрительно поместим её не в первую, а например в пятую

группу — просто напишем в начале строчек номера. Но пусть всётаки параметры

А, Бэ и Цэ будут не константами, а пусть программа каждый раз просит ввести их

с терминала. Для этого нам понадобится оператор ввода Ask:

Ask A,B,C; или даже: Ask "введите А, Бэ и Цэ: ", A,B,C

Пишем:

5.1 Ask "введите А, Бэ и Цэ: ", A,B,C

5.2 Set D = B^2 — 4*A*C; Type "Д = ", D

5.3 Type " X1,X2 = "

5.4 Type (-A + FSQrt(D))/(2*B)

5.5 Type (-A — FSQrt(D))/(2*B) !

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

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

Ага. Но если дискриминант вдруг получится отрицательный, то при попытке

вычислить из него корень — будет ошибка: программа остановится, и

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

само проверяло сей факт и писало что ни будь типа: "корней нет".

Для этого нам понадобится оператор условной передачи управления: If(X)a,b,c;

Он сравнивает значение X с нулём и для трёх случаев, когда оно меньше нуля,

равно и больше — передаёт управление на строки с номерами a, b и c. Здесь

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

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

Кстати, в правильном, полноценном Фокале произвольное выражение может быть

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

операторах перехода (передачи управления) Go, Do, If — получается "вычисляемый

переход", аналогичный например оператору switch языка Си. И даже когда ввода

ожидает оператор Ask — он тоже вводит вовсе не константу, а ищет в полученной

текстовой строке выражение и вычисляет его. (Ну калькулятор же!)

Константа — только номер в начале нумерованной (косвенной) строки, да еще в

таинственной конструкции "формат" оператора Type.

Формат указывает как выводить числа: ширину поля и количество значащих цифр: %N.M, или это может быть одиночный символ % восстанавливающий формат по-умолчанию. Заметим, N.M это не одно дробное число (как в номере строки) а два целых. Потому что например 7.10 и 7.1 это одно и то же число,

но если написать что: Set pi=3.14159265358979324;

то Type %7.10 pi выдаст 3.141592654

а Type %7.1 pi выдаст 3

Итак, рассматриваем условный оператор

If(X)a,b,c

В "базовом" (1.0) Фокале последние из a,b,c могут быть опущены, и тогда в

соответстующих случаях выполняется остаток строки. А в "продвинутом" (1.5)

можно пропустить любые — при условии сохранения запятых. Тот же эффект даёт

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

делать. Всё это — чтобы можно было использовать оператор If вообще без каких

либо реальных номеров строк. Например:

If (X) 0, ,0; Type "икс равен нулю"

If (X) ,0 ; Type "икс не равен нулю"

Так как a,b,c — могут быть какие хотим выражения, в том числе и такие у

которых запросто могут быть "побочные эффекты" (например изменятся значения

некоторых переменных), то вычисляется только одно из них. Остальные — просто

пропускаются.

Да, условный оператор Фокала (по сравнению например с Бейсиком) не очень

удобен: сравнивать два числа приходится вычитанием одного из другого. Операции

сравнения > >= < <= = и <> (не равно), как там — куда нагляднее. Но разрешить

их только в условном операторе, как это там и было сделано — нарушение

принципов! (Да и неоправданное усложнение грамматики, а значит и

программы-интерпретатора — бесцельный расход ресурсов, которых и так в обрез.)

А разрешить их везде — так они потащат за собою "логический" тип значений, а

он — еще и дополнительные "логические" операции, не применимые больше ни к

чему. (А за ним и другие типы потянутся...) И всё это ради чего? Ради пошлого

удобства и наглядности... Нам такого счастья не надо!

К тому же бинарная логика — ущербная. Фокал ненавязчиво приучает к

трёхзначной. Или даже к "нечеткой". Но вот логические операции таки нужны.

И если за "инверсию", "отрицание" сойдёт смена знака, то на роль И и ИЛИ в

(1.4) ввели функции FMIn и FMAx просто выдающие самый маленький и самый

большой из своих аргументов. С них кстати и началась эта эпопея (1.7) с

синтаксическим сахаром — что мол надо разрешить функциям иметь произвольное,

какое угодно количество параметров. Де лишние они пусть просто проигнорируют...

Но вернёмся к нашим баранам. Итак, добавляем:

5.25 If(D) 6.1

6.1 Type "корней нет" !

И всё — "массовая" задача решена.

Надеюсь, всё понятно?

И то, что номер строки это вовсе не два целых числа (как склонны думать

некоторые, бейсиком ушибленные), а одно вещественное? Поэтому строчка с

номером 5.25 не окажется в конце группы, а встанет между 5.2 и 5.3

Обратим внимание: наша программа расползлась на две группы. Если запускать

её командой Go, то группа 6 тоже будет выполнена — вслед за группой пять,

чего нам совсем не надо. Поэтому либо запускаем Do 5; либо в конец пятой

группы помещаем еще одну строку с оператором Quit, останавливающим программу.

Но он же остановит нам её и после обработки первой же строки из сорока

обещанных тысяч. Поэтому от 5.6 Quit; воздержимся, a таки напишем: 5.6 Ret

Этот оператор возврата из подпрограммы мы просто забыли написать. Или даже

скорее поленились: понадеялись на то, что группа строк (да и отдельная строка)

и без того "естественная подпрограмма" — возврат управления происходит по

достижении её конца автоматически — даже если там нет оператора Ret. Но это

когда обращение идёт к группе (или к одной строке). А у нас тут запускается

"вся" программа, вот и...

Можно констатировать факт, что и следующая задача тоже уже решена процентов

на восемьдесят. Чего там не хватает? Двух вещей: переключения каналов ввода и

вывода на файл с исходными данными и на тот куда поместить результат. А так же

цикла по строчкам этих файлов.

С циклом всё просто: у каждого файла есть указатель чтения/записи. Сразу

после открытия он в самом начале. А при каждом чтении (или записи) смещается

на размер прочитанного (или записанного). Так что вполне достаточно нужное

число раз вызвать нашу подпрограмму в группе 5:

3.7 Do 5; Go 3.7

и всё.

Такой цикл не завершается никогда. Но в данном случае программа не

"зациклится": как только строчки в файле закончатся — произойдёт ошибка

"конец носителя" и программа остановится сама собою. Что нам и надо.

(В смысле: сойдёт для сельской местности.) И даже каналы ввода и вывода сама

собою на терминал переключит. (Правда заругается.)

А открытые файлы при выходе из Фокала сами собою корректно закроются.

Но сначала их таки надо открыть и переключить на них каналы ввода и вывода:

3.1 Op "файл_с_данными" XR; Op X

3.2 Op "файл_под_результат" YW; Op Y

Вот собственно и всё.

А всё остальное у нас уже написано. Вот правда надо бы скопировать в файл

результата еще и исходные данные (а то непонятно к какой задаче ответ).

Добавим:

5.15 Type A,B,C

И вот теперь действительно всё — вторая задача тоже решена. Ну разве что

вписать правильные названия файлов с исходными данными и результатом. И,

разумеется, запустить.

Ну и конечно объяснить, что мы такое сделали. Поэтому еще немножко теории.

У Фокала есть один канал ввода и один канал вывода. Оперирует ими оператор

Operate, где вторым ключевым словом указывается куда такой канал переключить.

Из канала ввода читает оператор Ask (построчно), функция FCHR (побайтно),

ну и сам интерпретатор, когда ему нужна очередная командная строка (тоже

построчно). А в канал вывода пишет оператор Type, функция FCHR и еще оператор

Write. Вот такая у Фокала простенькая система ввода/вывода.

Оператор Modify позволяющий редактировать уже находящиеся в памяти строчки

формально тоже к ней относится. Но не использует каналы ввода/вывода, а

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

сильно зависит от реализации.

1234 ... 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)
Закрыть
Закрыть
Закрыть
↑ Вверх