Copyright (C) 1998-2010 MKTMK Moscow, Russia

http://www.mktmk.narod.ru.

e-mail: mktmk<at>narod.ru

 

Code of this document is WIN1251 (Russian).

 

Пакет Open Basic.

Описание применения.

Версия 1.90.

 

 

                    Содержание

 

Аннотация. 3

Производитель. 3

Обратная связь. 3

Гарантии. 4

Ссылки. 4

Список версий и исправленных ошибок. 4

Перечень файлов поставки. 5

1. Описание задачи и назначение программы.. 7

2. Условия применения. 8

3. Входные и выходные данные. 8

3.1. Общие сведения. Как использовать интерпретатор. Как загрузить и запустить *.bas программу. 8

3.2. Обзор технических решений. 9

3.3. Обзор системы ввода-вывода. 10

3.4. Методы и перечисления класса ob_obasic, которые используются для загрузки и запуска *.bas программ   13

3.4.1. Конструктор ob_obasic. 13

3.4.2. Метод clear_project 13

3.4.3. Метод load_project 13

3.4.4. Метод run. 14

3.4.5. Метод set_current_input_stream.. 14

3.4.6. Метод get_current_input_stream.. 14

3.4.7. Перечисление typeend. 14

3.5. Методы и перечисления класса ob_obasic, которые используются для организации отладки в интерпретаторе Open Basic. 15

3.5.1. Перечисление step. 15

3.5.2. Метод setstep. 15

3.5.3. Метод getstep. 15

3.5.4. Класс ob_modestream.. 15

3.5.5. Функция ob_loadbreakstr 16

3.6. Методы и перечисления класса ob_obasic, которые используются для сопряжения ввода и вывода интерпретатора Open Basic с вводом и выводом операционной системы.. 17

3.6.1. Общие замечания. 17

3.6.2. Методы setoperatorbreak и getoperatorbreak. 17

3.6.3. Методы setin и setout 17

3.6.4. Перечисление ob_lex::typelex. 18

3.6.5. Методы gettypenextlex и restoreinputpointer 18

3.7. Синтаксис языка Open Basic. Общие сведения. 18

3.8. Типы данных, имена и метки Open Basic. 19

3.9. Пользовательские функции в Open Basic. 22

3.9.1. Тип возвращаемого значения для пользовательской функции. 23

3.9.2. Прототипы для пользовательской функции. 23

3.9.3. Параметры пользовательских функций. 24

3.9.4. Структура массивов параметров. 25

3.9.5. Выбор Basic-имени пользовательской функции. 27

3.9.6. Подключение пользовательской функции к исполняющей системе OB.. 27

3.10. Методы и перечисления класса ob_obasic для подключения и отключения пользовательских функций  30

3.10.1. Перечисление ob_type_del 30

3.10.2. Методы setfun. 30

3.10.3. Методы delfun. 30

3.11. Доступ из пользовательской функции к данным *.bas программы. 31

3.12. Методы и перечисления класса ob_obasic для доступа к данным Open Basic из пользовательских функций. 31

3.12.1. Методы и перечисления класса ob_obasic для определения типа переменных и массивов Open Basic. 31

3.12.1.1. Перечисление ob_type_ident 31

3.12.1.2. Метод typevar 31

3.12.1.3. Метод typearray. 32

3.12.2. Методы класса ob_obasic для определения длины строковых переменных и элементов строковых массивов Open Basic. 32

3.12.3. Методы класса ob_obasic для определения размеров массивов Open Basic. 34

3.12.4. Методы класса ob_obasic для записи переменных Open Basic. 34

3.12.5. Методы класса ob_obasic для чтения переменных Open Basic. 35

3.12.6. Методы класса ob_obasic для создания и удаления переменных и массивов Open Basic  36

3.12.6.1. Методы класса ob_obasic для создания переменных Open Basic. 36

3.12.6.2. Методы класса ob_obasic для создания массивов Open Basic. 37

3.13. Описание других методов класса ob_obasic. 37

3.14. Операторы.. 37

3.14.1. Оператор PRINT. 38

3.14.2. Оператор INPUT. 38

3.14.3. Операторы FOR и NEXT. 39

3.14.4. Оператор GOTO.. 40

3.14.5. Операторы GOSUB и RETURN.. 41

3.14.6. Оператор LET. 42

3.14.7. Оператор DIM... 43

3.14.8. Операторы STOP и END.. 43

3.14.9. Оператор REM... 44

3.14.10. Операторы OPEN и CLOSE. 45

3.14.11. Оператор KILL. 46

3.14.12. Операторы READ, DATA и RESTORE. 46

3.14.13. Оператор RANDOMIZE. 47

3.14.14. Оператор IF. 47

3.15. Встроенные функции. 49

3.15.1. Функция SGN%.. 49

3.15.2. Функция ABS. 49

3.15.3. Функция INT%.. 49

3.15.4. Функции SIN, COS, ATN, SQR, EXP, LOG и LOG10. 50

3.15.5. Функция RND.. 50

3.15.6. Функция LEN%.. 50

3.15.7. Функции DAT$ и CLK$. 51

3.15.8. Функции D2STR$, D2HEXSTR$, STR2FLOAT и STR2INT%.. 51

3.16. Обработка ошибок. 52

3.17. Таблица диагностических сообщений. 53

 

                   Аннотация

 

 Open Basic (OB) представляет собой реализацию интерпретатора языка Basic.

OB разработан для встраивания в приложения пользователя в качестве скриптового

языка.

 

OB поставляется в исходных текстах под лицензией LGPL.

 

OB имеет возможность расширения системы команд путем подключения

пользовательских функций к исполняющей системе Open Basic.

 

 Пользовательские функции могут быть написаны на C/C++, ассемблере или других

языках. Пользовательские функции могут вызываться из Basic-программы, получать

параметры разных типов из Basic-программы и возвращать результаты своей работы

в Basic-программу.

 

 Специально разработанный интерфейс вызова пользовательских функций позволяет

на этапе исполнения определить тип и порядок следования параметров в вызове.

 

 OB реализует подмножество команд языка Basic. OB написан полностью на C++ и

реализован в виде класса с именем ob_obasic.

 

 OB поддерживает данные трех типов:

 

-          с плавающей точкой

-          целые со знаком

-          строковые

-          а также массивы этих типов.

 

 OB имеет multithread-safe код.

 

 В документе описывается:

 

 - порядок работы с интерпретатором Open Basic

 - синтаксис операторов Open Basic

 - интерфейс к данным Open Basic из пользовательских функций

 - правила подключения пользовательских функций

 - типы данных Open Basic

 - возможности отладки

 

 OB не использует никаких графических библиотек.

 OB не использует никаких системных вызовов ОС.

 

                    Производитель

 

Copyright (C) 1998-2010 MKTMK Moscow, Russia

http://www.mktmk.narod.ru.

e-mail: mktmk<at>narod.ru

 

MKTMK software company. Moscow, Russia

 

                      Обратная связь

 

 Если Вы собираетесь применять интерпретатор, и хотите знать об выходе новых

версий и о возможных изменениях почтового и WWW адреса, то сообщите об этом

по e-mail.

 

 MKTMK software company заинтересована в опыте применения интерпретатора:

 

 - для чего Вы применяете интерпретатор

 - Ваш транслятор и номер его версии

 - найденные в программе ошибки

 - полнота документации и ошибки в ней 

 - подключали ли Вы пользовательские функции

 - какие замечания к интерфейсу пользовательских функций

 - с какой ОС Вы работаете

 - откуда Вы узнали об интерпретаторе

 

 Эти сведения помогут нам при сопровождении программы.

 

                          Гарантии

 

 Интерпретатор и документация поставляются на условиях "как есть". Фирма MKTMK

не несет ответственности за возможные убытки, понесенные из-за использования

интерпретатора.

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

 

                           Ссылки

 

 Все упомянутые в тексте торговые марки являются собственностью их владельцев.

 

                           Список версий и исправленных ошибок

 

03.jan.2010 –  версия 1.90 для Windows

 

1.    Исправлена ошибка в обработке оператора REM в при загрузке файла. Ранее при комментировании строковой метки с двоеточием возникало зависание при выполнении метода load_project.

 

2.    Добавлена возможность создавать проекты из нескольких файлов. Для этого в интерпретатор добавлены новые методы clear_project и load_project с помощью которых можно загружать несколько *.bas файлов. Между файлами проекта возможны переходы операторами GOTO и вызовы операторами GOSUB. Все метки и переменные проекта доступны из любого модуля.

 

3.    Добавлена возможность переходов GOTO и GOSUB на метку, расположенную в другом файле.

 

4.    Введено ограничение на количество вложенных вызовов GOSUB. По умолчанию количество вложенных вызовов не может превышать 4096. Возможно изменение этого параметра с помощью функций set_max_nested_gosub и get_max_nested_gosub.

 

5.    Добавлен новый механизм запуска пользовательского кода до и после указанного оператора. Старый механизм запуска пользовательского кода базировался на прерывании выполнения метода run. Новый механизм запуска пользовательского кода базируется на функторах и позволяет уменьшить количество кода, необходимого для организации ввода-вывода. Старый механизм запуска пользовательского кода признан устаревшим и оставлен для совместимости с существующим кодом. В последующих версиях старый механизм запуска пользовательского кода будет удален и поэтому он не рекомендуется к применению в новых разработках. Подробнее см. описание методов setoperatorbreak и getoperatorbreak.

 

18.feb.2007 –  версия 1.80 для Windows и Linux

 

1.    Исправлена ошибка в индексации массива элементом массива

 

2.    Теперь имя файла в операторе OPEN может задаваться не только строковой константой, но и строковой переменной.

 

3.    Начиная с версии 1.80 в *.bas программе кроме меток в виде чисел (номеров строк) поддерживаются строковые метки с двоеточием в конце

 

4.    Из класса ob_obasic исключены методы getstarttime() и getstoptime() как не относящиеся к основному назначению интерпретатора. Пользователь легко может самостоятельно проконтролировать время выполнения любого метода интерпретатора.

 

28.aug.2005 –  версия 1.71 для Windows и Linux

 

Исправлена ошибка в функции возвращения номера версии

 

21.aug.2005 –  версия 1.70 для Windows и Linux

 

Исправлена ошибка при работе с шестнадцатеричными числами

Созданы multithread библиотеки для MSVC7

 

23.feb.2005 –  версия 1.50 для Windows и Linux

 

1998        – первая версия для DOS

 

                  Перечень файлов поставки

 

                  Файлы примеров *.bas программ

 

.\bas

test_project1.bas

test_project2.bas

test1.bas

test2.bas

test3.bas

test4.bas

test5.bas

test6.bas

test7.bas

test8.bas

test9.bas

test10.bas

test11.bas

test12.bas

test13.bas

test14.bas

test15.bas

test16.bas

test17.bas   

test18.bas   

test19.bas   

test20.bas   

test21.bas   

test22.bas   

test23.bas   

test24.bas   

test25.bas   

test26.bas   

test27.bas   

test28.bas   

test29.bas       -   файлы примеров, которые могут выполняться в консольном

                     приложении ob190_msvc.exe

 

                  Командные файлы для запуска *.bas программ

 

.\bat

test1.bat

test2.bat

test3.bat

test4.bat

test5.bat

test6.bat

test7.bat

test8.bat

test9.bat

test10.bat

test11.bat

test12.bat

test13.bat

test14.bat

test15.bat

test16.bat

test17.bat   

test18.bat   

test19.bat   

test20.bat   

test21.bat   

test22.bat   

test23.bat   

test24.bat   

test25.bat   

test26.bat   

test27.bat    

test28.bat   

test29.bat       -   файлы примеров, которые запускают консольное

                     приложение ob190_msvc.exe

 

                  Файлы исходных текстов

.\source

ob1.bas   

ob2.bas   

ob3.bas   

ob4.bas   

ob5.bas   

ob6.bas   

ob7.bas   

ob8.bas   

ob9.bas   

ob10.bas   

ob11.bas   

ob11.bas         -   файлы исходных текстов

 

                  Файлы исходных текстов обработчика командной строки

 

.\comline

comline.cpp      -   функции для разбора командной строки

comline.h        -   функции для разбора командной строки

 

                  Файлы исходных текстов консольного приложения

 

.\example

ob.cpp           -   main() тестового примера ob190_msvc.exe, пользовательские

                     функции, примеры их подключения.

 

                  Пример использования Open Basic в виде консольного приложения

 

.\exe

ob190_msvc.exe   -   консольное приложение Open Basic MSVS 2008

                     Принимает в качестве параметра имя текстового файла с *.bas

                     программой и выполняет его. При запуске с ключем -? печатает

                     список своих ключей. Этот файл исполняется только в среде .NET (WinXP и старше)

 

                  Файлы описаний

 

.\htm

read_rus.htm     -   файл с текстом данного описания на русском языке

read_eng.htm     -   файл с текстом данного описания на английском языке

shortrus.htm     -   файл с текстом краткого справочника по методам и

                     перечислениям класса ob_obasic на русском языке

shorteng.htm     -   файл с текстом краткого справочника по методам и

                     перечислениям класса ob_obasic на английском языке

 

                  Заголовочные файлы

 

.\include

mstore.h         -   стратегии хранения данных

mvect.h          -   вектор

mlist.h          -   список

mstack.h         -   стек

mhash.h          -   хеш-таблица

ob.h             -   основной заголовочный файл Open Basic

 

1. Описание задачи и назначение программы

 

 Часто в пользовательских приложениях возникает необходимость в применении

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

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

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

 

Например:

 

 - запросы к базе данных с разными условиями выборки данных

 - тестирование оборудования и/или программного обеспечения

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

 - построение графических интерфейсов и манипуляции с объектами GUI

 - входной язык в программах-терминалах  для разбора командной строки

 - входной язык оператора-технолога в задачах АСУТП

 - входной язык сложных конфигурационных файлов

 - и многое другое

 

 Графический интерфейс пользователя затрудняет возможность автоматизации

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

которые предоставляет скриптовой язык.

 

 Интерпретатор Open Basic разработан для встраивания в приложения пользователя

в качестве скриптового языка.

 

 OB поставляется в исходных текстах под лицензией LGPL.

 

 OB имеет возможность расширения системы команд путем подключения

пользовательских функций к исполняющей системе Open Basic.

 

 Пользовательские функции могут быть написаны на C/C++, ассемблере или других

языках. Пользовательские функции могут вызываться из Basic-программы, получать

параметры разных типов из Basic-программы и возвращать результаты своей работы

в Basic-программу.

 

 Также пользовательские функции имеют доступ ко всем переменным и массивам

Basic-программы, а не только передаваемым через параметры. Этот доступ

осуществляется по именам переменных и массивов.

 

2.  Условия применения

 

 Пакет Open Basic написан полностью на C++ и не использует системные вызовы

какой-либо ОС. Пакет Open Basic может использоваться совместно с любой

графической библиотекой.

 

3.   Входные и выходные данные

 

3.1. Общие сведения. Как использовать интерпретатор. Как загрузить и запустить *.bas программу.

 

 Интерпретатор Open Basic реализован в виде класса с именем ob_obasic.

 Работа интерпретатора состоит в выполнении программы на языке Basic.

В данном описании эта программа называется *.bas-программой. Программа *.bas

является текстовым файлом или буфером в памяти, открытом как поток istream.

 

 Далее в описании:

 

 1. "оператор" - означает оператор языка Basic. Например PRINT, FOR и т.д.

 2. "пользовательская функция"  - означает пользовательскую функцию,

     присоединенную к исполняющей системе Open Basic

 3. "функция"  - означает функцию С++

 4. "метод"    - означает метод класса ob_obasic.

 5. "*.bas-программа" - программа на языке Basic

 

 Чтобы использовать интерпретатор нужно:

 

1.    скачать со страницы http://www.mktmk.narod.ru архив, содержащий:

-          исходные тексты интерпретатора

-          заголовочный файл ob.h

-          заголовочные файлы с реализацией шаблонных контейнеров(mstore.h,mvect.h,mlist.h,mstack.h,mhash.h)

 

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

3.    в проекте указать путь для подключения заголовочного файла интерпретатора ob.h

4.    в проекте указать путь для подключения заголовочных файлов шаблонных контейнеров(mstore.h,mvect.h,mlist.h,mstack.h,mhash.h)

5.    включить в свои C++ файлы директивой #include заголовочный файл интерпретатора ob.h

6.    сделать объявление об использовании пространства имен интерпретатора using namespace ob_charspace;

7.    создать экземпляр класса ob_obasic в своей C++ программе

8.    в случае использования для ввода-вывода потоков, отличных от стандартных cin и cout,      перехватить ввод и вывод интерпретатора с помощью методов setoperatorbreak, setin и setout.

9.    очистить проект с помощью метода clear_project

10.загрузить программу для выполнения с помощью метода load_project

11.запустить программу на выполнение с помощью метода run

 

Пример:

 

// загрузка и запуск программы test1.bas

ifstream inp1("test1.bas",ios::binary);//открытие входного потока

ob_obasic basic_interpreter;//создание экземпляра интерпретатора

basic_interpreter.clear_project();//очистка проекта

basic_interpreter.load_project(&inp1);//загрузка test1.bas с помощью метода load_project

basic_interpreter.run();//запуск программы test1.bas

 

ВНИМАНИЕ! Входной поток должен быть открыт в ios::binary режиме.

 

ПОЯСНЕНИЕ:

 

 Несмотря на то, что *.bas-программа является текстовым файлом, открываться как

поток она должна в ios::binary режиме. Это связано с особенностями обработки

символов возврата каретки и перевода строки в ios::text режиме.

 

Пример:

 

//после окончания программы test1.bas загрузка и запуск программы

//test2.bas и test3.bas

ifstream inp2("test2.bas",ios::binary);//открытие входного потока

ifstream inp3("test3.bas",ios::binary);//открытие входного потока

basic_interpreter.clear_project();//очистка проекта

basic_interpreter.load_project(&inp2);//загрузка *.bas программы

basic_interpreter.load_project(&inp3);//загрузка *.bas программы

basic_interpreter.set_current_input_stream(&inp2);//установка потока inp2 первым в очереди запуска

basic_interpreter.run();//запуск программы test2.bas

 

ВНИМАНИЕ! Входные потоки должны быть открыты в ios::binary режиме.

 

ВНИМАНИЕ! Если проект состоить из нескольких файлов (потоков), то первым запустится последний загруженый файл (поток). Для явного назначения файла (потока), который будет запущен первым, нужно использовать метод set_current_input_stream.

 

3.2. Обзор технических решений

 

При проектировании интерпретатора решались следующие основные проблемы:

 

1.    Возможность хранения Basic-программы в файле на диске или в буфере памяти. Для обеспечения этой возможности интерпретатор принимает входную программу в виде указателя на поток ввода istream*. Конкретный вид потока (файл или буфер) определяется пользователем. Аналогично входной поток оператора INPUT и выходной поток оператора PRINT тоже могут быть буферами или файлами.

 

2.    Для обеспечения гибкости функционирования применяется разделение выполнения программы на три этапа.

 

-          Первый этап это очистка проекта методом clear_project. В процессе очистки проекта происходит очистка внутренних таблиц интерпретатора от данных предыдущего проекта (очистка таблицы меток переходов, таблиц переменных и массивов и т.д.).

 

-          Второй этап это загрузка программы методом load_project. В процессе загрузки происходит создание таблицы меток переходов и подпрограмм и настройка внутренних переменных. Набор одновременно загруженных в экземпляр интерпретатора файлов (потоков) называется проектом. Для проекта применяется концепция общего пространства имен переменных, имен массивов и меток. Метки в во всех файлах (потоках) проекта должны быть неповторяющимися. Переменные, созданные в одном файле проекта, доступны во всех файлах проекта.

 

-          Третий этап это выполнение программы методом run. В процессе выполнения производится чтение текста программы и выполнение действий (создание переменных, массивов, вычисление и присвоение значений переменным, выполнение операторов и функций и т.д.).

 

Окончание метода run происходит по нескольким причинам:

 

-          Исчерпание входного потока

-          Синтаксическая ошибка в программе

-          Символ точки останова

-          Символ конца строки при установленном флаге пошагового режима работы

 

При окончании метод run возвращает код окончания. Анализируя этот код пользователь может узнать причину окончания метода.

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

 

3.    Один экземпляр интерпретатора может выполнять один проект в данный момент времени. В программе может быть несколько экземпляров интерпретатора. Интерпретатор не имеет статических членов данных (кроме доступных по чтению констант). Поэтому несколько экземпляров интерпретатора могут работать одновременно в разных нитях программы.

 

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

 

5.    Класс ob_obasic не является шаблоном. Поэтому его можно вынести в статическую или динамическую библиотеку. Это позволит уменьшить время трансляции.

 

3.3. Обзор системы ввода-вывода

 

Существует два альтернативных способа организации ввода-вывода данных из/в интерпретатор.

 

  1. С использованием операторов PRINT и INPUT и вспомогательных классов ввода-вывода (функторов)
  2. С использованием пользовательских функций ввода-вывода

 

3.3.1. Первый способ организации ввода-вывода.

 

Во время исполнения *.bas программы интерпретатор работает со внутренними переменными и массивами, и пользовательскими функциями. Эти объекты которые организованы в таблицы. Все действия с этими объектами выполняются без обращения к сервисам ОС только средствами исполняющей системы интерпретатора. Но операторы ввода и вывода PRINT и INPUT требуют обращения к сервисам ОС, так как конкретный вид и способ ввода-вывода может сильно различаться для разных ОС и разных приложений. Для сопряжения ввода-вывода интерпретатора с вводом-выводом операционной системы используются методы setoperatorbreak, setin, setout.

 

Оператор PRINT выводит данные в текстовый поток вывода. Этот поток вывода прикрепляется к интерпретатору методом setout. Обычно в качестве потока вывода используется класс ostrstream со статическим буфером. По умолчанию в качестве потока вывода используется cout.

 

Оператор INPUT вводит данные из текстового потока ввода. Этот поток ввода прикрепляется к интерпретатору методом setin. Обычно в качестве потока вывода используется класс istrstream со статическим буфером. По умолчанию в качестве потока ввода используется cin.

 

Для сопряжения операторов PRINT и INPUT с ОС пользователь должен создать два класса-функтора, производных от класса ob_functor_break_base:

 

class ob_functor_break_base{

public:

ob_functor_break_base(){}

virtual ~ob_functor_break_base(){}

virtual void run_before(ob_obasic* basicptr)=0;

virtual void run_after(ob_obasic* basicptr)=0;

};

 

В этих производных от ob_functor_break_base классах пользователь переопределяет методы run_before и run_after. После этого с помощью метода setoperatorbreak пользователь устанавливает ссылку на функторы в интерпретаторе.

 

Методы run_before и run_after будут запущены соответственно до и после выполнения операторов ввода-вывода. В методах run_before пользователь подготавливает потоки ввода-вывода для интерпретатора.  В методах run_after пользователь обрабатывает результаты ввода-вывода.

 

Экземпляры функторов должны находиться в той же области видимости, что и экземпляр интерпретатора ob_obasic. Если в программе есть несколько экземпляров интерпретатора ob_obasic, то для каждого из них нужны свои экземпляры функторов ввода-вывода.

 

Пример (из файла ob.cpp)

 

-          создание функтора для вывода (для оператора PRINT)

 

class ob_functor_break_print_def:public ob_functor_break_base{

char printbuffer[ob_maxlengthstring];

ostrstream pr;

public:

ob_functor_break_print_def():pr(printbuffer,ob_maxlengthstring){}

virtual ~ob_functor_break_print_def(){}

 

void run_before(ob_obasic* basicptr){

printbuffer[0]=0;

pr.clear();

pr.seekp(0);

basicptr->setout(&pr);

}

 

void run_after(ob_obasic* basicptr){

if(printbuffer[0]!=0){

pr<<ends;

 

//-------------------------------------------------

cout<<printbuffer;//your output code place here

//-------------------------------------------------

 

}//if

}

};

-          создание функтора для ввода (для оператора INPUT)

 

class ob_functor_break_input_def:public ob_functor_break_base{

char inputbuffer[ob_maxlengthstring];

char inputbuffer1[ob_maxlengthstring];

strstream pr;

public:

ob_functor_break_input_def():pr(inputbuffer1,ob_maxlengthstring){}

virtual ~ob_functor_break_input_def(){}

 

void run_before(ob_obasic* basicptr){

 

ob_lex::typelex tll=basicptr->gettypenextlex();

basicptr->restoreinputpointer();

 

if(tll!=ob_lex::SHARP){

 

inputbuffer[0]=0;

 

//-------------------------------------------------

cin>>inputbuffer;//your input code place here

//-------------------------------------------------

 

pr.clear();

pr.seekp(0);

 

pr<<inputbuffer;

 

pr.seekg(0);

basicptr->setin(&pr);

}//if

}

 

void run_after(ob_obasic* basicptr){}

};

 

-          создание экземпляров функторов

 

ob_functor_break_print_def ob_functor_break_print;

ob_functor_break_input_def ob_functor_break_input;

 

-          установка ссылки на функторы в экземпляре интерпретатора

 

example_basic_interpreter.setoperatorbreak("PRINT",&ob_functor_break_print);

example_basic_interpreter.setoperatorbreak("INPUT",&ob_functor_break_input);

 

В примере ввод-вывод осуществляется из/в стандартные потоки cin и cout. Приведенные примеры функторов можно использовать в программе с использованием GUI, если заменить выделенные строки

 

//-------------------------------------------------

cout<<printbuffer;//your output code place here

//-------------------------------------------------

 

//-------------------------------------------------

cin>>inputbuffer;//your input code place here

//-------------------------------------------------

 

пользовательским кодом ввода-вывода из/в соответствующего окна Windows.

 

3.3.2. Второй способ организации ввода-вывода.

 

Ввод-вывод может быть организован без использования операторов PRINT и INPUT с помощью пользовательских функций ввода-вывода. Пользователь пишет свои пользовательские функции ввода-вывода. Регистрирует эти  функции в интерпретаторе. И в тексте *.bas программ вместо операторов PRINT и INPUT используются для ввода-вывода свои пользовательские функции ввода-вывода.

 

3.4. Методы и перечисления класса ob_obasic, которые используются для загрузки и запуска *.bas программ

 

3.4.1.  Конструктор ob_obasic

 

ob_obasic(ostream* o=&cout,istream* read=&cin);

 

создает экземпляр интерпретатора Open Basic.

 

Параметры конструктора:

 

 1. Параметр o - указатель на выходной поток, в который выводятся данные

оператором PRINT.

 

ВНИМАНИЕ! Выходной поток должен быть открыт в ios::text режиме.

 

ПОЯСНЕНИЕ:

 

 Выходной поток является обычным текстовым потоком в который выводятся

текстовые данные.

 

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

данные оператором INPUT.

 

ВНИМАНИЕ! Этот поток должен быть открыт в ios::binary режиме.

 

3.4.2.  Метод clear_project

 

В процессе работы интерпретатор создает таблицы:

 

 1. таблица переменных

 2. таблица массивов

 3. таблица пользовательских функций

 4. таблица (поток) данных оператора DATA

 5. таблица меток

 6. таблица циклов операторов FOR

 7. таблица открытых файлов

 8. таблица (стек) подпрограмм GOSUB

 

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

 

Таблица пользовательских функций очищается только при вызове метода

void clrtablfun();

 

3.4.3.  Метод load_project

 

 Метод void load_project(istream* i); - загружает *.bas-программу.

 

Параметр метода это указатель на поток, в котором содержится *.bas-программа.

 

ВНИМАНИЕ! Этот поток должен быть открыт в ios::binary режиме.

 

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

После окончания работы интерпретатора внутренний указатель указывает на

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

внутренний указатель методом seekg и перезагрузить программу методом load_project.

 

Метод load_project может загрузить несколько потоков. Набор одновременно загруженных потоков называется проектом.

 

3.4.4.  Метод run

 

 Метод typeend run(); - запускает загруженную программу или продолжает

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

 

3.4.5. Метод set_current_input_stream

 

Метод set_current_input_stream(ob_istreamcommon* i) указывает поток, который должен начать исполняться первым при вызове метода run(). Поток i должен быть предварительно загружен с помощью метода load_project.

 

3.4.6. Метод get_current_input_stream

 

Метод ob_istreamcommon* get_current_input_stream() возвращает текущий исполняемый поток.

 

3.4.7. Перечисление typeend

               

 Перечисление

 

enum typeend{

DUMMYEND,ENDFILEEND,ENDOPERATORDETECT,EOLEND,BREAKPOINTEND,NOLOADEND,

BREAKBEFOREOPERATOR,BREAKAFTEROPERATOR

};

 

определяет код завершения метода run.

 

Коды завершения:

 

 1. typeend=DUMMYEND - при нормальной работе никогда не возвращается методом

    run. Используется для внутренних переходов.

 

 2. typeend=ENDFILEEND метод run окончился из-за исчерпания входного потока.

    Это нормальное завершение *.bas-программы при отсутствии в программе оператора END

 

 3. typeend=ENDOPERATORDETECT метод run окончился при обнаружении оператора

    END. Это нормальное завершение *.bas-программы

 

 4. typeend=EOLEND метод run окончился после исполнения очередной строки, т.к.

    был установлен флаг step=STEP методом setstep

 

 5. typeend=BREAKPOINTEND метод run окончился после считывания символа '@',

    который является символом точки останова для Open Basic

 

 6. typeend=NOLOADEND метод run окончился т.к. не был выполнен метод load_project и

    входной поток не открыт

 

 7. typeend=BREAKBEFOREOPERATOR - метод run окончился перед выполнением

    оператора OB. Этот режим окончания оставлен для совместимости со

    старым кодом и не рекомендуется в новых разработках. В последующих версиях

    этот режим поддерживаться не будет.

 

8. typeend=BREAKAFTEROPERATOR - метод run окончился после выполнения

   оператора OB. Этот режим окончания оставлен для совместимости со

   старым кодом и не рекомендуется в новых разработках. В последующих версиях

   этот режим поддерживаться не будет.

 

3.5.  Методы и перечисления класса ob_obasic, которые используются для организации отладки в интерпретаторе Open Basic

 

 В OB есть два режима отладки: пошаговое выполнение *.bas-программ и назначение

точек останова.

 Возможность пошагового выполнения *.bas-программ реализована с помощью метода

setstep.

 Символ '@' отдельной строке в тексте *.bas-программы реализует точку останова.

Точек останова в *.bas-программе может быть несколько. После внесения точек

останова *.bas-программу нужно перезагрузить методом load_project.

 При передаче управления на строку с символом '@' произойдет останов программы.

Код завершения метода run будет BREAKPOINTEND. Для продолжения программы нужно

снова запустить метод run();

 

3.5.1.  Перечисление step

 

 Перечисление enum step{NOSTEP,STEP}; - определяет режим пошагового выполнения

программы. Используется в методах setstep и getstep. По умолчанию step=NOSTEP.

 При step=NOSTEP программа выполняется непрерывно.

 При step=STEP программа завершается с кодом typeend=EOLEND после выполнения

каждой строки программы.

 

3.5.2.  Метод setstep

 

 Метод

void setstep(step ts) - устанавливает или снимает режим пошагового выполнения

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

При установки пошагового режима метод run(); будет завершаться после выполнения

каждой строки *.bas программы. Для продолжения программы нужно снова запустить

метод run();

 

3.5.3.  Метод getstep

 

 Метод

 

step getstep() - возвращает текущий режим режим пошагового выполнения

программы.

 

3.5.4. Класс ob_modestream

 

Класс ob_modestream будет использоваться для обработки файлов в UNICODE и UTF-8. В версии 1.90 эти режимы не поддерживаются. Соответствующие поля в вызовах функций задаются равными конструктору по умолчанию ob_modestream().

 

3.5.5. Функция ob_loadbreakstr

 

 Функция

 

bool ob_loadbreakstr(

ob_istreamcommon* in1,

ob_type_stringsize lengthbuffers,

ob_type_char* ptrbefore,

ob_type_char* ptrcurrent,

ob_type_char* ptrafter,

ob_modestream ms=ob_modestream()

);

 

где:

 

istream* in1   - текущий входной исполняемый *.bas-файл

lengthbuffers  - длина буферов ptrbefore, ptrcurrent, ptrafter

ptrbefore      - буфер для строки, предшествующей текущей исполняемой

ptrcurrent     - буфер для текущей исполняемой строки

ptrafter       - буфер для строки, следующей за текущей исполняемой

ob_modestream  - признак формата входного файла. В версии 1.90 задается по умолчанию.

 

 Функция ob_loadbreakstr загружает в указанные буфера соответствующие строки

выполняемой программы.

 

 Функция ob_loadbreakstr не является методом класса ob_obasic.

 

Пример:

 

//Создание интерпретатора и запуск программы в пошаговом режиме.

//с печатью выполняемых строк

 

ob_type_char strbefore[ob_maxlengthstring];//буфер

ob_type_char strcurrent[ob_maxlengthstring];//буфер

ob_type_char strafter[ob_maxlengthstring];//буфер

 

ob_obasic basic_interpreter;//Создание интерпретатора

//загрузка и запуск программы test1.bas

//с пошаговым выполнением программы

//и с печатью выполняемых строк

ifstream inp1("test1.bas",ios::binary);//открытие входного потока

basic_interpreter.clear_project();//очистка проекта

basic_interpreter.load_project(&inp1);//загрузка программы test1.bas

basic_interpreter.setstep(ob_obasic::STEP);//установка пошагового режима

 

while(1){

 

if(basic_interpreter.run()!=ob_obasic::EOLEND) break;//запуск *.bas-программы

 

ob_loadbreakstr(&inp1,ob_maxlengthstring,strbefore,strcurrent,strafter);

cout<<endl<<"String current: "<<strcurrent;

 

}//while

 

3.6. Методы и перечисления класса ob_obasic, которые используются для сопряжения ввода и вывода интерпретатора Open Basic с вводом и выводом операционной системы

 

3.6.1. Общие замечания

 

Во время исполнения *.bas программы интерпретатор работает со внутренними переменными и массивами, и пользовательскими функциями. Эти объекты которые организованы в таблицы. Все действия с этими объектами выполняются без обращения к сервисам ОС только средствами исполняющей системы интерпретатора. Но операторы ввода и вывода PRINT и INPUT требуют обращения к сервисам ОС, так как конкретный вид и способ ввода-вывода может сильно различаться для разных ОС и разных приложений. Для сопряжения ввода-вывода интерпретатора с вводом-выводом операционной системы используются методы setoperatorbreak, setin, setout.

 

3.6.2. Методы setoperatorbreak и getoperatorbreak

 

В OB для каждого оператора (PRINT, INPUT, FOR и т.д.) имеется возможность выполнить пользовательский код до и после выполнения оператора. Обычно эта возможность используется для операторов PRINT, INPUT т.е. для организации ввода-вывода при работе интерпретатора в GUI приложении.

 

bool setoperatorbreak(ob_type_char* name,ob_functor_break_base* b);

 

Параметры:

 

 1. name - имя оператора

 2. ob_functor_break_base* b – указатель на функтор

 

возвращаемое значение:

 

true  - успешное завершение

false - если ошибка задания имени оператора

 

Подробнее о работе с методом setoperatorbreak см. п. “Обзор системы ввода-вывода”

 

Метод

 

bool getoperatorbreak(ob_type_char* name,ob_functor_break_base** b);

 

Позволяет получить указатель на функтор. Если для указанного оператора функтор не был установлен, то b=0. Возвращает false при ошибке задания имени оператора. По умолчанию для всех операторов функторы не установлены.

 

3.6.3. Методы setin и setout

 

 Методы позволяют переопределить входной и выходной потоки, ранее определенные

в конструкторе.

 

void setin(ob_istreamcommon* i);

void setout(ob_ostreamcommon* o);

 

ВНИМАНИЕ! Входной поток должен быть открыт в ios::binary режиме.

ВНИМАНИЕ! Выходной поток должен быть открыт в ios::text режиме.

 

Метод setin переопределяет поток “rd” конструктора.

Метод setout переопределяет поток “o” конструктора.

 

3.6.4.  Перечисление ob_lex::typelex

 

 Перечисление определяет текущую лексему.

 

enum typelex{

PLUS,MINUS,MUL,DIV,POWER,ASSIGN,LP,RP,STRING,SEMICOLON,COMMA,ENDPROGRAMM,EOL,

LESS,GREAT,SHARP,BREAKPOINT,

DECINTNUMBER,HEXINTNUMBER,FLOATNUMBER,

FUNC,OPERATOR,

OLDVARIABLE,OLDARRAY,NEWNAME,

BAD

};

 

3.6.5.  Методы gettypenextlex и restoreinputpointer

 

Методы предназначены для облегчения реализации операторов ввода и вывода.

 

 - ob_lex::typelex gettypenextlex();

 - void restoreinputpointer();

 

 Метод

ob_lex::typelex gettypenextlex();

 

Возвращает следующую лексему из входного потока. Некоторые операторы (например

оператор INPUT) имеют одинаковый синтаксис для ввода из файла и с консоли.

Текущее направление ввода определяется следующей лексемой #. С помощью метода

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

ожидается ввод.

 

 Метод

 void restoreinputpointer();

 

Предназначен для восстановления состояния входного потока после применения

метода gettypenextlex().

 

В примере п. “Обзор системы ввода-вывода” методы gettypenextlex и restoreinputpointer используются для определения направления ввода в операторе INPUT. Если обнаружена лексема SHARP, то ввод с консоли не производится. Соответствующий код для оператора PRINT не нужен, так как вывод не блокирует работу.

 

3.7.  Синтаксис языка Open Basic. Общие сведения

 

ВНИМАНИЕ! Все объекты в *.bas-программе: переменные, массивы, и

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

 

 Интерпретатор Open Basic поддерживает подмножество операторов языка Basic.

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

с плавающей точкой, целыми и строками. Имеется возможность работать с массивами

из этих трех типов.

 

 Переменные в Open Basic не нужно описывать перед первым использованием.

Первое появление переменной в программе должно быть слева от оператора

присвоения.

 

Массивы в Open Basic нужно описывать до первого использования оператором DIM.

Массивы могут быть многомерными. Данные для массивов и переменных располагаются

в свободной памяти оператором new. Общий размер массива зависит от ограничений

на оператор new в конкретной ОС.

 

 В Open Basic индекс массива начинается с единицы.

 

 В отличие от стандартного языка Basic оператор DIM в Open Basic является

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

 

 Допускается повторное описание массива с тем же именем в операторе DIM.

Новый массив может иметь другие размерности. Старые данные при этом теряются.

Этот механизм можно применять для освобождения памяти. После захвата большого

массива оператором DIM можно освободить память, описав массив с тем же именем

и размерностью в один элемент.

 

 При описании массива в операторе DIM в качестве размерностей могут

использоваться целые переменные.

 

 При создании числовые переменные и массивы инициализируются нулем. Строковые

переменные и массивы инициализируются пустой строкой ("").

 

 Диапазон представления данных с плавающей точкой и целых зависит от того, как

транслируется пакет. Обычно целые это int, а плавающие это float. В файле ob.h

типы переменных определены с помощью typedef:

 

typedef char                     ob_type_char;                 

typedef float                    ob_type_flo;

typedef int                      ob_type_int;

 

 Максимальная длина строковых переменных определяется константой

ob_maxlengthstring в файле ob.h. Для версии OB v1.90 ob_maxlengthstring=4096.

 В *.bas-программе могут быть пустые строки.

 

 Интерпретатор Open Basic поддерживает следующие операции над целыми данными и

данными с плавающей точкой:

 

 + - сложение

 - - вычитание

 * - умножение

 / - деление

 ^ - возведение в степень

 - - унарный минус

 + - унарный плюс

 = - присвоение

 

выражения отношения

 

 <  - "меньше"

 >  - "больше"

 =  - "равно"

 <> - "не равно"

 <= - "меньше или равно"

 >= - "больше или равно"

 

Выражения отношения используются в операторе IF.

 Для строковых данных поддерживаются только операции сложения,

сравнения и присвоения строк.

 

3.8.  Типы данных, имена и метки Open Basic

 

 Как и в стандартном языке Basic тип переменной или массива в Open Basic

определяется по имени. А именно:

 - если в имени последним символом является символ '%', то это переменная

   или массив целого типа.

 - если в имени последним символом является символ '$', то это переменная

   или массив строкового типа.

 - если в имени последним символом является любой другой символ, то это

   переменная или массив с плавающей точкой

 

 Многие типы Open Basic описаны в ob.h с помощью typedef.

Тип ob_type_flo отображается в тип float с помощью typedef.

Тип ob_type_int отображается в тип int   с помощью typedef.

В пользовательских функциях рекомендуется использовать типы ob_type_flo и

ob_type_int. При смене, например, ob_type_flo с float на double будет

обеспечена совместимость типов.

 

 В качестве имен переменных, массивов и пользовательских функций можно

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

буквы.

 Буквы в имени могут быть прописные или строчные. Символ подчеркивания '_' и

символы '$' и '%' считаются буквами.

 Приведения букв в именах к одному регистру не производится. Имена MASS, mass

и Mass являются разными именами.

 Максимальная длина имени определяется константой ob_maxlengthstring в файле

ob.h. Для версии OB v1.90 ob_maxlengthstring=4096.

 

Пример:

 

 Объявление массива и инициализация двух переменных - целой и с плавающей

точкой. Последнее измерение массива задано переменной. Тип элементов массива

mass - с плавающей точкой. Переменная counter% имеет целый тип. Переменная data

имеет тип с плавающей точкой.

 

      counter%=7

      DIM mass(2,3,10,counter%)

      data=counter%+37.77

 

Пример:

 

Объявление массива и использование его. Повторное объявление

массива с тем же именем, но другой размерностью и использование его.

  

      DIM mass(10)

 

      FOR i%=1 TO 10 STEP 1

      mass(i%)=i%+37.77

      NEXT i%

 

      counter%=7

 

      DIM mass(counter%,3)

 

      FOR i%=1 TO counter% STEP 1

      mass(i%,2)=i%+37.77

      NEXT i%

 

Если в выражении используются данные разных типов, то производится

приведение типов.

 Если в выражении используется целые данные и данные с плавающей точкой,

результирующий тип будет с плавающей точкой.

 При присвоении тип правого выражения приводится к типу выражения слева от

знака присвоения =.

 Если слева от знака присвоения целая переменная, а справа с плавающей точкой,

то дробная часть отбрасывается.

 

 Интерпретатор Open Basic поддерживает метки в виде номеров строк. Эти номера

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

пронумерована. Осуществить переход операторами GOTO и GOSUB можно только на

пронумерованную строку. Можно поставить метку и у пустой строки.

 

Пример:

 

   ii%=6

   ik%=8

 

   IF ii%<>6 THEN GOTO 10

 

   PRINT "ii%=";ii%;

10 PRINT " ii%!=6"

 

   IF ik%=7 THEN GOSUB 11

 

   PRINT "ik%=";ik%;

   GOTO 12

11

   PRINT " ik%!=7"

   RETURN

12

   STOP

   END

 

Начиная с версии 1.80 в *.bas программе кроме меток в виде чисел (номеров строк) поддерживаются строковые метки с финальным двоеточием. Двоеточие является частью идентификатора метки и должно следовать за идентификатором метки без разделителя. В операторах GOTO и GOSUB идентификатор строковой метки пишется без финального двоеточия. В программе могут одновременно применяться метки в виде чисел (номеров строк) и строковые метки. Строковая метка должна начинаться с буквы.

 

Пример:

 

  REM Test string label

 

  PRINT

  PRINT "Start--------------------------------"

 

  loop_counter%=10

 

  FOR i%=1 TO loop_counter%

 

  PRINT "-------------------------------- ";"pass=";i%

 

  GOSUB gosub_label_1

  GOSUB gosub_label_2

  GOSUB gosub_label_3

  GOSUB gosub_label_4

 

  NEXT i%

 

  PRINT "End program OK"

 

10

  STOP

  END

 

gosub_label_1:

  PRINT "gosub_label_1"

 

  a%=i%/2*2

 

  IF a%=i% THEN GOTO goto_label_1

  PRINT "do not goto detect"

  ENDIF

 

goto_label_1:

 

  RETURN

 

gosub_label_2:  PRINT "gosub_label_2"

 

                a%=i%/2*2

 

                IF a%=i% THEN GOTO goto_label_2

                PRINT "do not goto detect"

                ENDIF

 

 

                goto_label_2:RETURN

 

gosub_label_3:

  PRINT "gosub_label_3"

  RETURN

 

gosub_label_4:

  PRINT "gosub_label_4"

  RETURN

 

3.9. Пользовательские функции в Open Basic.

 

 OB имеет возможность расширения системы команд путем подключения

пользовательских функций к исполняющей системе Open Basic.

 

 Параметры пользовательских функций позволяют определить тип и порядок

следования аргументов в вызове во время исполнения программы.

 

 Пользовательские функции подключаются к исполняющей системе Open Basic под

некоторыми именами (Basic-именами). Каждая пользовательская функция

подключается под своим Basic-именем. После подключения их можно вызывать в

тексте *.bas-программы по этим именам. Можно передавать им параметры и получать

от них результаты. Можно вызывать пользовательские функции без параметров.

 Пользовательские функции могут быть написаны на C/C++, ассемблере или других

языках.

 

 Все пользовательские функции имеют 2 имени:

 

 1. С++ имя функции в составе проекта по которому пользовательскую функцию

    можно вызывать из С++ программы.

 2. Basic-имя функции, по которому пользовательскую функцию можно вызывать из

    *.bas-программы.

 

 Первое имя пользовательские функции получают при их написании. Второе имя

пользовательские функции получают на этапе подключения к исполняющей системе

Open Basic с помощью метода setfun.

 

Пользовательская функция может иметь один из трех прототипов:

 

-          Функция, возвращающие значение с плавающей точкой

-          Функция, возвращающие целое значение

-          Функция, возвращающие строку

 

 Чтобы создать пользовательскую функцию и подключить ее к исполняющей системе

Open Basic необходимо:

 

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

 2. Выбрать C++ имя пользовательской функции

 3. Написать пользовательскую функцию по одному из трех прототипов

 4. Выбрать Basic-имя пользовательской функции

 5. Подключить пользовательскую функцию к исполняющей системе OB с помощью

    метода setfun используя Basic-имя и C++ имя в качестве параметров

 

 После этого можно использовать Basic-имя пользовательской функции в *.bas

программе.

 

3.9.1.  Тип возвращаемого значения для пользовательской функции

 

 Пользовательская функция может возвращать значения трех типов:

 

 - с плавающей точкой ob_type_flo

 - целое              ob_type_int

 - строковое          ob_type_char*

 

 

3.9.2.  Прототипы для пользовательской функции

 

 Пользовательская функция может иметь один из трех прототипов:

 

 1. Функции, возвращающие значение с плавающей точкой

 

ob_type_flo name_flo(

ob_obasic* basic_ptr,

const ob_type_char* parstring,

const ob_type_parnum *descrf,

const ob_type_parnum *descri,

const ob_type_parnum *descrc,

const ob_type_flo* parf,

const ob_type_int* pari,

const ob_type_char* parc

);

 

 2. Функции, возвращающие целое значение

 

ob_type_int name_int(

ob_obasic* basic_ptr,

const ob_type_char* parstring,

const ob_type_parnum *descrf,

const ob_type_parnum *descri,

const ob_type_parnum *descrc,

const ob_type_flo* parf,

const ob_type_int* pari,

const ob_type_char* parc

);

 

 3. Функции, возвращающие строку

 

ob_type_char* name_char(

ob_obasic* basic_ptr,

const ob_type_char* parstring,

const ob_type_parnum *descrf,

const ob_type_parnum *descri,

const ob_type_parnum *descrc,

const ob_type_flo* parf,

const ob_type_int* pari,

const ob_type_char* parc

);

 

 Эти прототипы различаются только типом возвращаемого значения.

 

 В файле ob.h содержится макрос OB_DECLARE_USER_FUNCTION(name,typeret), который можно

использовать для объявления пользовательских функций. Параметр name - это имя

функции в C++, параметр typeret - это тип возвращаемого значения.

 

Пример:

 

Объявление пользовательской функции с помощью макроса OB_DECLARE_USER_FUNCTION.

C++ имя пользовательской функции "myfun1".

Тип возвращаемого значения - ob_type_flo.

 

OB_DECLARE_USER_FUNCTION(myfun1,ob_type_flo);

 

Пример:

 

Определение пользовательской функции с помощью макроса OB_DECLARE_USER_FUNCTION.

C++ имя пользовательской функции "myfun2".

Тип возвращаемого значения - ob_type_int.

 

OB_DECLARE_USER_FUNCTION(myfun2,ob_type_int){

return 365;

}

 

Пример:

 

Определение пользовательской функции с помощью макроса OB_DECLARE_USER_FUNCTION.

C++ имя пользовательской функции "myfun3".

Тип возвращаемого значения - ob_type_char*.

 

OB_DECLARE_USER_FUNCTION(myfun3,ob_type_char*){

return "Hello world";

}

3.9.3. Параметры пользовательских функций

 

Интерфейс пользовательских функций Open Basic разработан для того, чтобы

обеспечить возможность контроля фактических параметров в вызове на этапе

исполнения программы.

 

 Для этого набор параметров пользовательских функций содержит две группы

массивов.

 

 Первая группа это три массива описаний параметров descrf, descri, descrc.

Эти массивы содержат информацию о количестве и порядке следования фактических

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

 

 Вторая группа это три массива значений параметров parf, pari, parc. Эти

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

функции.

 

 Назначение и структура массивов descr* и par* подробнее описана в следующем

разделе.

 

3.9.4. Структура массивов параметров

 

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

параметры и разный тип возвращаемого результата.

 

 Рассмотрим параметры пользовательских функций на примере Функции, возвращающей

значение с плавающей точкой.

 

ob_type_flo name_flo(

ob_obasic* basic_ptr,

const ob_type_char* parstring,

const ob_type_parnum *descrf,

const ob_type_parnum *descri,

const ob_type_parnum *descrc,

const ob_type_flo* parf,

const ob_type_int* pari,

const ob_type_char* parc

);

 

  Параметры:

 

1. ob_obasic* basic_ptr - указатель на экземпляр интерпретатора ob_obasic, к которому

   подключена функция. Используется для доступа к переменным программы с

   помощью методов ob_obasic.

 

2. const char* parstring - строковые представления параметров.

 

Пример:

 

   если в качестве параметров функции USER_FUN1 в ее вызове указано

   USER_FUN1(1.123,a_a%,1+2), то в массиве parstring будут находиться следующие

   строки: "1.123","a_a%","1+2".

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

   байтом.

 

3.

   массивы описания параметров descr*:

 

   const ob_type_parnum *descrf - для параметров с плавающей точкой

   const ob_type_parnum *descri - для целых параметров

   const ob_type_parnum *descrc - для строковых параметров

 

   это массивы, описывающие количество, типы и местоположение всех параметров,

   переданных пользовательской функции из *.bas-программы. Используются для

   контроля количества, типа и порядка следования параметров в вызове

   пользовательской функции.

 

   Структура массива descrf (остальные массивы имеют аналогичную структуру):

 

   descrf[0] - общее число параметров с плавающей точкой в текущем вызове

   Остальные элементы массива descrf(их количество равно descrf[0])

   это порядковые номера параметров с плавающей точкой в текущем вызове.

   Порядковые номера считаются с 1.

 

Пример:

   если в качестве параметров функции USER_FUN1 в ее

   вызове указано USER_FUN1(1.123,a_a%,1+2), то

   в массиве descrf будут находиться следующие числа:

   1,1

   в массиве descri будут находиться следующие числа:

   2,2,3

   в массиве descrc будут находиться следующие числа:

   0

 

Пример:

   если в качестве параметров функции USER_FUN1 в ее

   вызове указано USER_FUN1("str1","srt2"+"str3",1.1,1.2,1.3,1.4),

   то в массиве descrf будут находиться следующие числа:

   4,3,4,5,6

   в массиве descri будут находиться следующие числа:

   0

   в массиве descrc будут находиться следующие числа:

   2,1,2

 

4. массивы значений параметров par*:

 

   const ob_type_flo*  parf  - для параметров с плавающей точкой

   const ob_type_int*  pari  - для целых параметров

   const ob_type_char* parc  - для строковых параметров

 

   это массивы, описывающие значения всех параметров соответствующих типов,

   переданных пользовательской функции в текущем вызове из *.bas-программы.

 

   Параметры лежат подряд, в массиве parc строки, как и в массиве parstring,

   отделяются нулевыми байтами.

 

Пример:

 

   ([a_a%] - значение переменной с именем a_a%)

 

   если в качестве параметров функции USER_FUN1 в ее

   вызове указано USER_FUN1(1.123,a_a%,1+2), то

   в массиве parf будут находиться следующие числа:

   1.123

   в массиве pari будут находиться следующие числа:

   [a_a%],3

   в массиве parc не будет значений

 

Пример:

 

   если в качестве параметров функции USER_FUN1 в ее

   вызове указано USER_FUN1("str1","srt2"+"str3",1.1,1.2,1.3,1.4),

   то в массиве parf будут находиться следующие числа:

   1.1,1.2,1.3,1.4

   в массиве pari не будет значений

 

   в массиве parc будут находиться следующие строки:

   "str1","srt2str3"

 

 В файле ob.h содержится макрос OB_DECLARE_USER_FUNCTION(name,typeret), который можно

использовать для объявления пользовательских функций. Параметр name - это имя

функции в C++, параметр typeret - это тип возвращаемого значения.

 

 Максимальное число параметров определяется константой ob_maxnumpar в файле

ob.h.

 Для версии OB v1.90 ob_maxnumpar=64;.

 

 Используя массивы описания порядка следования параметров descr* и массивы

значений параметров par* пользователь может организовать контроль типов и

порядка следования параметров в текущем вызове пользовательской функции на

этапе выполнения программы.

 Анализ массивов descr* дает полную информацию о типах, количестве и порядке

следования параметров в текущем вызове пользовательской функции.

 

Пример:

 

 В пользовательскую функцию, вычисляющую синус передана в качестве параметра

строковая переменная.

 При этом массивы descrf, descri и descrc будут содержать значения:

 

descrf[0]=0

descri[0]=0

descrc[0]=1

 

Анализируя эту информацию, пользователь может совершить нужные ему действия,

например:

 

 1. генерировать пользовательское исключение

 2. подставить аргумент по умолчанию, например 0.

 3. выполнить останов программы с печатью предупреждения

 4. попытаться преобразовать строку в число с помощью atof

 

 Для облегчения доступа к строковым данным Open Basic предоставляет функцию

 

const ob_type_char*

ob_getstringparam(

const ob_type_parnum *descrc,

const ob_type_char* parc,

const ob_type_parnum i);

 

  Параметры:

 

  1. descrc - массив описания строковых параметров

  2. parc   - массив значений строковых параметров

  3. i      - номер строки, переданной в параметрах (нумерация с нуля)

 

 С помощью этой функции можно получить доступ к i-й строке, записанной в

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

 Если i больше, чем descrc[0], то функция возвращает 0.

 Если descrc[0] равно нулю, то функция возвращает 0.

Функция ob_getstringparam не является методом класса ob_obasic.

 

3.9.5. Выбор Basic-имени пользовательской функции

 

 Basic-имя пользовательской функции должно отличаться от имен операторов, переменных,

массивов и других пользовательских функций *.bas-программы.

 

3.9.6. Подключение пользовательской функции к исполняющей системе OB

 

 Подключение пользовательской функции к исполняющей системе OB производится с

помощью методов setfun.

 

bool setfun(ob_type_char* name,ob_type_flofun f);

bool setfun(ob_type_char* name,ob_type_intfun f);

bool setfun(ob_type_char* name,ob_type_charfun f,ob_type_del dt);

 

 Параметры:

 

 1. name - Basic-имя пользовательской функции

 2. f    - указатель на пользовательскую функцию

 3. dt   - тип размещения размещения в памяти возвращаемого значения (только

           для функций, возвращающих строку)

 

Пример:

 

//подключается функция userfun1

//эта функция возвращает значение с плавающей точкой

//эта функция печатает сообщение "hello world" и возвращает значение 3.1416

//при подключении она получает Basic-имя "TEST_FUN1"

//то есть в *.bas-программах ее можно вызывать по имени "TEST_FUN1"

 

OB_DECLARE_USER_FUNCTION(userfun1,ob_type_flo){

cout<<endl<<"hello world";

return (ob_type_flo)3.1416;

}

 

main(){

ob_obasic onebasic;//создается экземпляр интерпретатора

 

onebasic.setfun("TEST_FUN1",userfun1);//подключается функция TEST_FUN1

 

ifstream inonebasicf("EXAMPLE.BAS",ios::binary);//открывается файл EXAMPLE.BAS

 

onebasic.clear_project();

onebasic.load_project(&inonebasicf);//файл EXAMPLE.BAS загружается в интерпретатор

 

onebasic.run();//запуск *.bas-программы

}

 

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

Возможно два варианта размещения в памяти возвращаемого значения:

 

 - в куче оператором new[]

 - в статической памяти

 

 В первом случае пользовательская функция подключается с параметром

dt=OB_DELETE.

После окончания работы такой функции Open Basic освободит память оператором

delete[].

 

Пример:

 

 В примере создается экземпляр интерпретатора, открывается файл с именем

EXAMPLE.BAS и загружается в интерпретатор. После этого к исполняющей системе

подключаются четыре функции TEST_FUN1-TEST_FUN4.

 

 Функция TEST_FUN1 печатает список своих параметров с плавающей точкой и

возвращает значение с плавающей точкой, равное сумме своих параметров с

плавающей точкой.

 

 Функция TEST_FUN2 печатает список своих целых параметров и возвращает целое

значение равное сумме своих целых параметров.

 Функции TEST_FUN3 и TEST_FUN4 печатают свой первый строковый параметр и

возвращают строку "This is string".

 При этом функция TEST_FUN4 располагает возвращаемое значение в статической

памяти, а функция TEST_FUN3 в свободной памяти.

 Все функции контролируют правильность типов своих параметров. В случае

отсутствия параметров нужного типа печатают сообщения.

 

#include <ob.h>

 

char* s="This is string";

 

OB_DECLARE_USER_FUNCTION(userfun1,ob_type_flo){

ob_type_flo summ=0;

ob_type_parnum i;

if(descrf[0]==0) cout<<endl<<"Not float parameters";

for(i=0;i!=descrf[0];i++){

summ+=parf[i];

cout<<endl<<"parameters["<<i<<"]="<<parf[i];

}

return summ;

}

 

OB_DECLARE_USER_FUNCTION(userfun2,ob_type_int){

ob_type_int summ=0;

ob_type_parnum i;

if(descri[0]==0) cout<<endl<<"Not int parameters";

for(i=0;i!=descri[0];i++){

summ+=pari[i];

cout<<endl<<"parameters["<<i<<"]="<<pari[i];

}

return summ;

}

 

OB_DECLARE_USER_FUNCTION(userfun3,char*){

if(descrc[0]==0) cout<<endl<<"Not string parameters";

cout<<endl<<parc;

char* p=new char[strlen(s)+1];

strcpy(p,s);

return p;

}

 

OB_DECLARE_USER_FUNCTION(userfun4,char*){

if(descrc[0]==0) cout<<endl<<"Not string parameters";

cout<<endl<<parc;

return s;

}

 

main(){

ob_obasic onebasic;//создается экземпляр интерпретатора

 

onebasic.setfun("TEST_FUN1",userfun1);//подключается функция TEST_FUN1

onebasic.setfun("TEST_FUN2",userfun2);//подключается функция TEST_FUN2

onebasic.setfun("TEST_FUN3",userfun3,OB_DELETE);//подключается TEST_FUN3

onebasic.setfun("TEST_FUN4",userfun4,OB_NODELETE);//подключается TEST_FUN4

 

ifstream inonebasicf("EXAMPLE.BAS",ios::binary);//открывается файл EXAMPLE.BAS

 

onebasic.clear_project();

onebasic.load_project(&inonebasicf);//файл EXAMPLE.BAS загружается в интерпретатор

 

onebasic.run();//запуск *.bas-программы

}

 

 При обнаружении в тексте *.bas-программы имени подключенной функции

исполняющая система Open Basic производит следующие действия:

 

 1. вычисляет все аргументы в текущем вызове *.bas-программы

 2. заполняет массивы descr*

 3. заполняет массивы par*

 4. заполняет указатель ob_obasic* basic_ptr адресом текущего объекта Open Basic

 5. заполняет строку parstring

 6. передает управление пользовательской функции

 

 Пользовательская функция должна контролировать типы, количество и порядок

следования параметров в текущем вызове.

 

3.10. Методы и перечисления класса ob_obasic для подключения и отключения пользовательских функций

 

3.10.1.  Перечисление ob_type_del

 

 Перечисление enum ob_type_del{OB_DELETE,OB_NODELETE}; - определяет тип

размещения в памяти возвращаемого пользовательской функцией значения.

Используется в методе setfun чтобы подключить пользовательские функции,

возвращающие тип ob_type_char*.

 

 При dt=OB_DELETE возвращаемое значение располагается в свободной памяти

оператором new. После окончания пользовательской функции оно будет удалено

оператором delete[].

 При dt=OB_NODELETE возвращаемое значение не будет удалено оператором delete[].

 

3.10.2.  Методы setfun

 

 Методы

 

bool setfun(ob_type_char* name,ob_type_flofun f);

bool setfun(ob_type_char* name,ob_type_intfun f);

bool setfun(ob_type_char* name,ob_type_charfun f,ob_type_del dt);

 

подключают пользовательскую функцию к исполняющей системе Open Basic.

 

 Параметры:

 

 1. name - Basic-имя пользовательской функции

 2. f    - указатель на пользовательскую функцию

 3. dt   - тип размещения размещения в памяти возвращаемого значения (только

           для функций, возвращающих строку)

 

Если функция с именем name еще не подключена к исполняющей системе Open Basic, метод подключает ее возвращает false.

 

Если функция с именем name уже подключена к исполняющей системе Open Basic, метод заменяет ее на новую и возвращает true.

 

Типы ob_type_flofun, ob_type_intfun, ob_type_charfun это указатели на функции,

описанные в ob.h. Они отличаются типом возвращаемого значения.

 

3.10.3.  Методы delfun

 

 Метод

 

bool delfun(ob_type_char* name);

 

отключает пользовательскую функцию от Open Basic.

 

 Параметры:

 

 1. name - Basic-имя пользовательской функции

 

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

в случае, если такой функции не существует.

 

3.11.  Доступ из пользовательской функции к данным *.bas программы.

 

Пользовательская функция может принять параметры из *.bas программы.

Пользовательская функция может передать в *.bas программу выходное значение.

Пользовательская функция имеет доступ к переменным *.bas-программы по чтению и записи.

 

 Если в *.bas-программе используется переменная или массив, то пользовательская

функция может считывать и записывать эту переменную и элементы массива.

 

Пользовательская функция имеет средства проверки наличия переменной с заданным

именем в программе. Пользовательская функция имеет средства создания переменных

с заданным именем в таблице переменных *.bas-программы.

 

 Эти возможности реализованы в Open Basic с помощью методов, описанных в

следующем разделе.

 

3.12. Методы и перечисления класса ob_obasic для доступа к данным Open Basic из пользовательских функций

 

 Методы этого раздела запускаются обычно в пользовательских функциях, поэтому

в примерах они запускаются с помощью указателя ob_obasic* basic_ptr. Такое имя во всех

пользовательских функциях имеет первый параметр пользовательской функции, если определять пользовательские функции с помощью макроса OB_DECLARE_USER_FUNCTION.

 В общем случае методы этого раздела могут запускаются в любом месте C++

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

*.bas-программы с помощью точки останова, можно распечатать значения переменных

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

некоторые переменные.

 

3.12.1.  Методы и перечисления класса ob_obasic для определения типа переменных и массивов Open Basic

 

3.12.1.1.  Перечисление ob_type_ident

 

 Перечисление

 

enum ob_type_ident {OB_IDENTFLO,OB_IDENTINT,OB_IDENTSTR,OB_NOIDENT};

 

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

typevar и typearray чтобы определить тип переменной и массива.

 

Если ob_type_ident=OB_IDENTFLO переменная имеет тип с плавающей точкой.

Если ob_type_ident=OB_IDENTINT переменная имеет целый тип.

Если ob_type_ident=OB_IDENTSTR переменная имеет строковый тип.

Если ob_type_ident=OB_NOIDENT переменная не обнаружена.

 

3.12.1.2.  Метод typevar

 

 Метод

 

ob_type_ident typevar(ob_type_char* name);  - возвращает тип переменной с

именем name.

 

 Параметры:

 

 1. name - имя Basic-переменной

 

3.12.1.3.  Метод typearray

 

 Метод

 

ob_type_ident typearray(ob_type_char* name); - возвращает тип массива с

именем name.

 

 Параметры:

 

 1. name - имя Basic-массива (без скобок и индексов)

 

Пример: Если есть *.bas программа

 

        DIM array1%(10,10), array2$(10,10), array3(10,10)

        a%=10

        b$="string example"

        c=101.4

 

после выполнения этого участка кода в пользовательских функциях, подключенных

к интерпретатору, применение этих методов даст следующие результаты:

 

 ob_type_ident ident;

 ident=basic_ptr->typevar("a%");// ident имеет значение OB_IDENTINT

 ident=basic_ptr->typevar("b$");// ident имеет значение OB_IDENTSTR

 ident=basic_ptr->typevar("c"); // ident имеет значение OB_IDENTFLO

 

 ident=basic_ptr->typearray("array1%");// ident имеет значение OB_IDENTINT

 ident=basic_ptr->typearray("array2$");// ident имеет значение OB_IDENTSTR

 ident=basic_ptr->typearray("array3"); // ident имеет значение OB_IDENTFLO

 

 Где basic_ptr-первый параметр в пользовательских функциях, указатель на экземпляр

интерпретатора.

 

В примере *.bas-программы нет переменной с именем VAR и массива с именем ARR.

Поэтому применение этих методов даст следующие результаты:

 

 ident=basic_ptr->typevar("VAR");// ident имеет значение OB_NOIDENT

 ident=basic_ptr->typearray("ARR");// ident имеет значение OB_NOIDENT

 

3.12.2.  Методы класса ob_obasic для определения длины строковых переменных и элементов строковых массивов Open Basic

 

 Метод

 

ob_type_ident

strlenvar(

ob_type_char* name,

ob_type_stringsize* len,

ob_type_arraysize* as=OB_NULL);

 

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

name.

 

 Параметры:

 

 1. name - имя Basic-переменной или Basic-массива

 2. *len - для строковых переменных содержит длину строки без завершающего

           нуля. Для переменных с плавающей точкой и целых содержит

           sizeof(ob_type_float) и sizeof(ob_type_int) соответственно.

 3. *as  - индексы массива в случае если name имя массива

 

 Метод strlenvar можно вызывать для Basic-переменных или элементов

Basic-массивов.

 Для Basic-массивов есть 2 способа вызова метода strlenvar.

 

 1. С указанием текущих индексов в имени (параметр as=OB_NULL)

 2. С указанием текущих индексов в параметре *as (параметр as!=OB_NULL)

 

 Метод возвращает OB_NOIDENT в случае ошибки задания имени, например если оно

начинается не с буквы или является именем не описанного на момент использования

массива или переменная не существует. При нормальном завершении метод

возвращает тип переменной.

 Параметр *len для строковых переменных содержит длину строки без завершающего

нуля. Параметр *len для переменных с плавающей точкой и целых содержит

sizeof(ob_type_float) и sizeof(ob_type_int) соответственно.

 

Пример: Вызов метода strlenvar для элемента массива с указанием текущих

индексов в имени

 

Если есть *.bas программа:

 

        DIM array2$(10,10)

        array2$(5,5)="array string example"

 

после выполнения этого участка кода в пользовательских функциях, подключенных

к интерпретатору, применение метода strlenvar даст следующие результаты:

 

 ob_type_stringsize len;

 

 ob_type_ident ident;

 ident=basic_ptr->strlenvar("array2$(5,5)",&len);// ident==OB_IDENTSTR len==20

 

Пример: Вызов метода strlenvar для элемента массива с указанием текущих

индексов в параметре *as

 

Если есть *.bas программа:

 

        DIM array2$(10,10)

        array2$(5,5)="array string example"

 

после выполнения этого участка кода в пользовательских функциях, подключенных

к интерпретатору, применение метода strlenvar даст следующие результаты:

 

 ob_type_stringsize len;

 

 ob_type_ident ident;

 ob_type_arraysize as[]={5,5};

 ident=basic_ptr->strlenvar("array2$",&len,as);// ident==OB_IDENTSTR len==20

 

Пример: Вызов метода strlenvar для переменных

 

Если есть *.bas программа:

 

        DIM array1%(10,10), array3(10,10)

        a%=10

        b$="string example"

        c=101.4

 

после выполнения этого участка кода в пользовательских функциях, подключенных

к интерпретатору применение метода strlenvar даст следующие результаты:

 

 ob_type_ident ident;

 ob_type_stringsize len;

 

 ident=basic_ptr->strlenvar("a%",&len);// ident==OB_IDENTINT len==4

 ident=basic_ptr->strlenvar("b$",&len);// ident==OB_IDENTSTR len==14

 ident=basic_ptr->strlenvar("c",&len); // ident==OB_IDENTFLO len==4 

 

3.12.3. Методы класса ob_obasic для определения размеров массивов Open Basic

 

 Метод

 

const ob_type_arraysize* getarraysize(

ob_type_char* name,ob_type_arraydimension* kr); - возвращает

количество измерений массива и размер каждого измерения.

 

 Параметры:

 

 1. name - имя массива.

 2. *kr  - количество измерений массива. Он заполняется методом getarraysize.

 

 Возвращаемый параметр - массив размеров каждого измерения. Он создается при

описании массива оператором DIM. Этот параметр представляет собой внутренний

буфер Open Basic и должен только читаться.

 

Пример:

 

 Массив описан оператором DIM Array_1(10,11,12).

 

Применение метода getarraysize.

 

const ob_type_arraysize *sr;

ob_type_arraydimension kr;

sr=basic_ptr->getarraysize("Array_1",&kr);

 

После применения getarraysize kr=3, а указатель sr указывает на

массив {10,11,12}.

 

3.12.4.  Методы класса ob_obasic для записи переменных Open Basic

 

 Методы

 

bool

writevar(ob_type_char* name,ob_type_flo val,ob_type_arraysize* as=OB_NULL);

 

bool

writevar(ob_type_char* name,ob_type_int val,ob_type_arraysize* as=OB_NULL);

 

bool

writevar(ob_type_char* name,ob_type_char* val,ob_type_arraysize* as=OB_NULL);

 

 Параметры:

 

 1. name - имя Basic-переменной или Basic-массива

 2. val  - значения, записываемые в переменные или элементы массива

 3. *as  - индексы массива в случае если name имя массива

 

 Методы writevar можно вызывать для Basic-переменных или элементов

Basic-массивов.

 Для Basic-массивов есть 2 способа вызова методов writevar.

 

 1. С указанием текущих индексов в имени (параметр as=OB_NULL)

 2. С указанием текущих индексов в параметре *as (параметр as!=OB_NULL)

 

 Методы записывают переменную с именем name в таблицу переменных и присваивают

ей значение val.

 

 Если переменная не существует, то она создается.

 

 Производится проверка на тип имени, т.е. создается переменная соответствующая

имени.

 

 Если тип присваиваемого значения не соответствует типу имени (например при

попытке создать переменную целого типа со вторым аргументом ob_type_char* val),

то метод генерирует исключение.

 

 Имя name может быть именем элемента массива. Тогда оно должно содержать

индексы конкретного элемента по правилам Basic.

 

 Методы возвращают false в случае ошибки задания имени, например если оно

начинается не с буквы или является именем не описанного на момент использования

массива. При нормальном завершении методы возвращают true.

 

Пример: Чтобы в пользовательской функции присвоить переменной VAR

        значение 10.4, нужно написать следующий код:

 

if(basic_ptr->writevar("VAR",10.4)==false) cout<<endl<<"error in writevar";

 

Пример: Чтобы в пользовательской функции присвоить третьему элементу

        массива array_string$(10) значение "Hello world",

        нужно написать следующий код:

 

if(basic_ptr->writevar("array_string$(3)","Hello world")==false)

cout<<endl<<"error in writevar";

 

3.12.5.  Методы класса ob_obasic для чтения переменных Open Basic

 

  Методы

 

bool

readvar(ob_type_char* name,ob_type_flo* val,ob_type_arraysize* as=OB_NULL);

 

bool

readvar(ob_type_char* name,ob_type_int* val,ob_type_arraysize* as=OB_NULL);

 

bool

readvar(ob_type_char* name,ob_type_char* val,ob_type_arraysize* as=OB_NULL);

 

 Параметры:

 

 1. name - имя Basic-переменной или Basic-массива

 2. *val - значение, прочитанное из переменной или элемента массива

 3. *as  - индексы массива в случае если name имя массива

 

 Методы readvar можно вызывать для Basic-переменных или элементов

Basic-массивов.

 Для Basic-массивов есть 2 способа вызова методов readvar.

 

 1. С указанием текущих индексов в имени (параметр as=OB_NULL)

 2. С указанием текущих индексов в параметре *as (параметр as!=OB_NULL)

 

 Методы считывают переменную с именем name из таблицы переменных в указатель

val.

 

 Если переменная не существует, то она не создается.

 

 Имя name может быть именем элемента массива. Тогда оно должно содержать

индексы конкретного элемента по правилам Basic.

 

 Методы возвращают false в случае ошибки задания имени, например если оно

начинается не с буквы или является именем не описанного на момент использования

массива или переменная не существует. При нормальном завершении методы

возвращают true.

 

 Если тип переменной и параметра val не совпадают (например при попытке

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

исключение.

 

Пример: Чтобы в пользовательской функции считать значение переменной

        VAR1 в C++ переменную с именем val1, нужно написать следующий

        код:

 

ob_type_flo val1;

if(basic_ptr->readvar("VAR1",&val1)==false) cout<<endl<<"error name var in readvar";

 

Пример: Чтобы в пользовательской функции считать значение четвертого

        элемента массива array_string$(10), нужно написать следующий

        код:

 

ob_type_char buf[256];

ob_type_char* pchar=buf;

if(basic_ptr->readvar("array_string$(4)",pchar)==false)

cout<<endl<<"error name var in readvar";

 

3.12.6.  Методы класса ob_obasic для создания и удаления переменных и массивов Open Basic

 

3.12.6.1.  Методы класса ob_obasic для создания переменных Open Basic

 

  Метод

 

void createvar(ob_type_char* name);

 

 Параметры:

 

 1. name - имя Basic-переменной или Basic-массива

 

 Создает переменную с именем name в таблице переменных интерпретатора.

 Тип переменной определяется по наличию в имени символов '%' и '$'.

 

3.12.6.2.  Методы класса ob_obasic для создания массивов Open Basic

 

void createarray(

ob_type_char* name,ob_type_arraydimension kr,ob_type_arraysize* as);

 

 Параметры:

 

 1. name - имя Basic-переменной или Basic-массива

 2. kr   - количество измерений массива.

 3. *as  - массив размеров каждого измерения.

 

 Создает массив с именем name в таблице массивов интерпретатора. Если массив с

таким именем уже существует, он удаляется и создается заново с указанными

параметрами.

 Тип элементов создаваемого массива определяется по наличию в имени массива

символов '%' и '$'. Метод эквивалентен оператору DIM.

 

 Параметры аналогичны параметрам метода getarraysize.

 

Пример: Чтобы из пользовательской функции создать массив целых

        ARRAY1%(5,10,20), нужно написать следующий код:

 

ob_type_arraysize as[]={5,10,20};

basic_ptr->createarray("ARRAY1%",3,as);

 

3.13. Описание других методов класса ob_obasic

 

 ~ob_obasic(); - деструктор.

 

 Метод static const ob_type_char* about()- возвращает строку информации о

программе. Строка может содержать символы новой строки.

 

Пример:

 

cout<<ob_obasic::about();//печать информации о программе

 

 Метод static const ob_type_serialnum serial_number() - возвращает номер

экземпляра программы.

 

 Метод static const ob_type_int version() - возвращает номер текущей версии

программы, умноженный на 100. Для версии 1.90 метод возвращает 190.

 

Методы

 

void set_max_nested_gosub(ob_type_countlist m);

ob_type_countlist get_max_nested_gosub();

 

Определяют максимальное количество вложеных вызовов для оператора GOSUB. По умолчанию количество вложеных вызовов для оператора GOSUB равно 4096. При превышении заданного значения генерируется исключение. Установка значения “ноль” отменяет проверку на максимальный уровень вложенности оператора GOSUB

 

3.14.  Операторы

 

 Операторы могут располагаться в одной строке и отделяться друг от друга

пробелами.

 Некоторые операторы, например DATA и PRINT должны быть единственными

операторами в строке, т.к. нужно явно ограничить список аргументов этих

операторов.

 При описании операторов символы в квадратных скобках означают необязательные

символы.

 

 Open Basic поддерживает следующие операторы:

 

3.14.1.  Оператор PRINT

 

 Выводит в выводной поток, указанный при создании ob_obasic, список переменных.

 

 Формат оператора:

 

 [N] PRINT [#EXP,][LIST]

 

где

 N    - номер строки

 LIST - список элементов, представленных в виде констант, переменных, строковых

        или числовых выражений.

 EXP  - выражение, определяющее номер канала вывода, открытого оператором OPEN

 

 Оператор PRINT без списка элементов выводит символ новой строки.

 Если элементом списка является выражение, Open Basic вычисляет его и печатает

результат.

 

Пример:

 10 TT%=40

    TTT=101.3

 20 PRINT "TT%=";TT,"TTT=";TTT+0.3

 

 Результат работы оператора

 

 TT%=40       TTT=101.6

 

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

 Там, где элементы списка отделены запятыми, производится вывод символа

табуляции между элементами.

 Если в конце списка элементов стоит запятая или точка с запятой, то после

оператора PRINT не производится перевод строки.

 Оператор PRINT со списком элементов должен быть единственным оператором

в строке.

 

3.14.2.  Оператор INPUT

 

 Вводит из вводного потока, указанного при создании ob_obasic, данные.

 

 Формат оператора:

 

 [N] INPUT [#EXP,]VAR1,[VAR2,VAR3,...]

 

где

 N    - номер строки

 VAR1,[VAR2,VAR3,...] - список переменных

 EXP - выражение, определяющее номер канала ввода, открытого оператором OPEN

 

 Встретив оператор INPUT Open Basic вводит из потока данные, представленные в

числовой форме и присваивает их переменным из списка. Строковые данные в

потоке должны быть заключены в кавычки.

 

Пример:

10 TT%=40

   TTT=101.3

20 INPUT TT%,TTT

 

3.14.3.  Операторы FOR и NEXT

 

 Позволяют организовать цикл так, что Open Basic автоматически проверяет

условие при каждом проходе.

 

 Формат оператора FOR:

 

 [N] FOR VAR=EXP1 TO EXP2 [STEP EXP3]

 

где

 N    - номер строки

 VAR  - управляющая переменная (индекс цикла)

 EXP1 - начальное значение индекса. Любое числовое выражение.

 EXP2 - конечное значение индекса. Любое числовое выражение.

 EXP3 - приращение величины индекса. Любое числовое выражение.

        может быть положительным или отрицательным. По

        умолчанию равен 1.

 

Управляющая переменная (индекс цикла) может быть элементом массива.

 

 Операторы FOR и NEXT используются только в паре. Оператор FOR определяет

начало цикла, оператор NEXT - конец цикла.

 

 Формат оператора NEXT:

 

 [N] NEXT VAR1

 

где

 N    - номер строки

 VAR1  - управляющая переменная, использованные в операторе FOR

 

 Если начальное значение переменной цикла больше конечного значения, то цикл

не выполняется.

 Передавать управление внутрь цикла недопустимо.

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

избежании ошибок округления.

 Циклы можно вкладывать друг в друга, внутренний цикл должен заканчиваться до

внешнего.

 Оператор FOR имеет некоторые особенности выполнения. Они связаны с тем, что

Open Basic это интерпретатор. При входе в цикл производится проверка условия

цикла. Если условие цикла не выполняется, цикл не будет выполнен ни разу.

В этом случае производится поиск соответствующего оператора NEXT и передача

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

операторами GOTO.

 

Пример:

 

   GOTO 30

10

   NEXT i%

   GOTO 20

 

30 FOR i%=10 TO k% STEP 1

 

   GOTO 10

 

 

20

   STOP

   END

 

Этот пример будет работать, если k% больше 10. Но если это не так, то

произойдет аварийный останов.

 

Пример:

 

 FOR i%=1 TO 3

  FOR ii%=4 TO 1 STEP -2

   PRINT "Work FOR operator","ii%=";ii%,"i%=";i%

  NEXT ii%

 NEXT i%

 

 Результат работы оператора

 

Work FOR operator       ii%=4   i%=1

Work FOR operator       ii%=2   i%=1

Work FOR operator       ii%=4   i%=2

Work FOR operator       ii%=2   i%=2

Work FOR operator       ii%=4   i%=3

Work FOR operator       ii%=2   i%=3

 

Пример:

 

FOR i%=1 TO 3

  FOR ii%=4 TO 1 STEP -2

    PRINT "Work FOR operator","ii%=";ii%,"i%=";i%

  NEXT ii%

NEXT i%

 

 Результат работы оператора

 

Work FOR operator       ii%=4   i%=1

Work FOR operator       ii%=2   i%=1

Work FOR operator       ii%=4   i%=2

Work FOR operator       ii%=2   i%=2

Work FOR operator       ii%=4   i%=3

Work FOR operator       ii%=2   i%=3

 

3.14.4.  Оператор GOTO

 

 Вызывает непосредственный переход к указанной строке с нарушением

естественного порядка выполнения операторов программы.

 

 Формат оператора:

 

[N] GOTO line_number

 

или

 

[N] GOTO label_string

 

где

 N    - номер строки

 line_number  - номер строки, к которой осуществляется переход

 label_string - метка

 

Пример:

20 GOTO 50

   PRINT "This operator do not work in example"

50 PRINT "Work GOTO operator"

 

 Результат работы оператора

 

Work GOTO operator

 

Пример:

 

20       GOTO label_1

         PRINT "This operator do not work in example"

label_1: PRINT "Work GOTO operator"

 

Результат работы оператора

 

Work GOTO operator

 

3.14.5.  Операторы GOSUB и RETURN

 

 Осуществляют связь программы с подпрограммой.

 

 Формат оператора:

 

[N] GOSUB line_number

 

или

 

[N] GOSUB label_string

 

где

 N    - номер строки

 line_number  - номер строки, к которой осуществляется переход

 label_string - метка

 

 Встретив в программе оператор GOSUB, Open Basic передает управление строке,

заданной в операторе GOSUB. Программа продолжает выполняться с этой строки.

Когда встретится оператор RETURN управление передается строке, следующей за

строкой с оператором GOSUB.

 

 Операторы GOSUB и RETURN используются только в паре.

 

 Формат оператора RETURN:

 

 [N] RETURN

где

 N    - номер строки

 

 Подпрограммы можно вкладывать друг в друга.

 

Пример:

 

   GOSUB 10

   GOTO 100

 

10

   PRINT "Work GOSUB operator 1"

   GOSUB 20

   PRINT "Work GOSUB operator 2"

   RETURN

20

   PRINT "Work GOSUB operator 3"

   PRINT "Work GOSUB operator 4"

   RETURN

  

100

 

   STOP

   END

 

Результат работы оператора

 

Work GOSUB operator 1

Work GOSUB operator 3

Work GOSUB operator 4

Work GOSUB operator 2

 

Пример:

 

   GOSUB label_gosub_1

   GOTO  label_goto_1

 

label_gosub_1:

 

   PRINT "Work GOSUB operator 1"

   GOSUB label_gosub_2

   PRINT "Work GOSUB operator 2"

   RETURN

 

label_gosub_2:

   PRINT "Work GOSUB operator 3"

   PRINT "Work GOSUB operator 4"

   RETURN

  

label_goto_1:

 

   STOP

   END

 

Результат работы оператора

 

Work GOSUB operator 1

Work GOSUB operator 3

Work GOSUB operator 4

Work GOSUB operator 2

 

3.14.6.  Оператор LET

 

 Оператор присваивает значение переменной.

 

 Формат оператора:

 

 [N] [LET] VAR=EXP

 

где

 N    - номер строки

 LET  - необязательное имя оператора

 VAR  - переменная, принимающая новое значение

 EXP  - выражение, определяющее новое значение

 

Пример:

 

 20 LET a=100.1

    PRINT "Work LET operator","a=";a

 

Результат работы оператора

 

 Work LET operator   a=100.1

 

3.14.7.  Оператор DIM

 

 Оператор резервирует место для числового или строкового массива.

 

 Формат оператора:

 

 [N] DIM LIST

 

где

 N    - номер строки

 LIST - список имен массивов, разделенный запятыми

 

 Массивы в Open Basic могут быть любой размерности и объема. В связи с тем, что

место под них резервируется оператором C++ 'new', ограничения на размер связаны

с особенностями реализации оператора 'new' на конкретной платформе. Например в

MS DOS 'new' не запрашивает более 64К байт. Поэтому в MS DOS Open Basic общий

размер массива не может быть больше 64К байт, при этом количество измерений

также не может превышать 64К байт.

 

 Массивы в Open Basic могут менять размерность. При повторном описании уже

описанного массива, он уничтожается и создается вновь, возможно уже с новыми

размерностями и размером.

 При создании числовые массивы инициализируются нулем. Строковые массивы

инициализируются пустой строкой.

 Тип создаваемого массива определяется по правилам определения типа переменной,

по наличию в имени символов % и $.

 

Пример:

 DIM a%(2,2,3),b(3,2,4)

 DIM a$(2,2,3,2)

 

 a$="variable string"

 a$(1,1,3,2)="array string"

 a%(2,2,3)=10

 b(1,1,1)=101.1

 

 

 PRINT a$(1,1,3,2)

 PRINT a$

 PRINT "a%=";a%

 PRINT "b=";b

 

 Результат работы оператора

 

 array string

 variable string

 a%=10

 b=101.1

 

3.14.8.  Операторы STOP и END

 

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

 Оператор STOP вызывает очистку всех таблиц Open Basic - переменных, массивов

и т.д.

 Оператор END также вызывает очистку всех таблиц Open Basic и дополнительно

выставляет внутренний флаг останова. Сброс этого флага производится в методе

ob_obasic::load_project.

 Операторы не вызывают очистку таблицы пользовательских функций.

 

 Формат операторов:

 

 [N] STOP

 [N] END

 

где

 N    - номер строки

 

Пример:

   PRINT "example STOP and REM operator"

10 STOP

20 END

 

3.14.9.  Оператор REM

 

 Вводит комментарии в программу.

 

Формат оператора:

 

 [N] REM COMMENT

 

где

 N    - номер строки

 COMMENT - текст комментария

 

Операторы REM и пустые строки увеличивают время выполнения программы и

занимают место в памяти.

 

Пример:

 

a=1

 

10 REM this text is comment

 

PRINT "a=";a

 

STOP

END

 

 Если на оператор REM никогда не передается управление, то он не увеличивает

время выполнения программы.

 

Пример:

 

a=1

b=2

c=3

 

GOSUB label1

GOSUB label2

 

STOP

END

 

label1:

        a=b+c

        RETURN

 

 REM this text is comment

 REM this text is comment

 REM this text is comment

 REM this text is comment

 REM this text is comment

 

label2:

        b=a+c

        RETURN

 

3.14.10.  Операторы OPEN и CLOSE

 

 Оператор OPEN открывает файл. Оператор CLOSE закрывает файл.

 

 Формат оператора OPEN:

 

[N] OPEN filename FOR INPUT  AS FILE #EXP

[N] OPEN filename FOR OUTPUT AS FILE #EXP

 

где

 N    - номер строки

 filename - имя файла

 EXP - выражение, которое вычисляется и приводится к целому типу. Обычно

       используют константы.

 AS FILE - ключевые слова

 

 Оператор OPEN FOR INPUT открывает файл для чтения.

 Оператор OPEN FOR OUTPUT открывает файл для записи.

 

 Формат оператора CLOSE:

 

 [N] CLOSE #EXP1,[#EXP1,#EXP2,...]

 

где

 N    - номер строки

 EXP - выражение, которое вычисляется и приводится к целому типу. Обычно

       используют константы.

 

Пример:

 

   k%=10

 

   OPEN "F000.TXT" FOR OUTPUT AS FILE #k%+1

   OPEN "F001.TXT" FOR OUTPUT AS FILE #k%+2

 

   FOR i%=1 TO KOL% STEP 1

     PRINT "i%=",i%

     PRINT #k%+1,i%

     f=i%+0.1

     PRINT #k%+2,f

   NEXT i%

 

   CLOSE #k%+1

   CLOSE #k%+2

 

   OPEN "F000.TXT" FOR INPUT AS FILE #k%+2

   OPEN "F001.TXT" FOR INPUT AS FILE #k%+3

 

   FOR i%=1 TO KOL% STEP 1

     INPUT #k%+2,ii%

     INPUT #k%+3,ff

     PRINT "ii%=",ii%

     f=i%+0.1

     IF ii%<>i% THEN PRINT " Error test OPEN-CLOSE command" GOTO 10

     IF ff<>f THEN PRINT " Error test OPEN-CLOSE command" GOTO 10

   NEXT i%

 

   CLOSE #k%+2

   CLOSE #k%+3

 

10 STOP

   END

 

3.14.11.  Оператор KILL

 

 Удаляет файл.

 

 Формат оператора:

 

 [N] KILL STR1[,STR2,STR3,...]

 

где

 N    - номер строки

 STR1, STR2 ,STR3  - имена файлов

 

Пример:

 

 10 KILL "F000.TXT","F001.TXT"

 

3.14.12.  Операторы READ, DATA и RESTORE

 

 Операторы READ и DATA используются для организации блока данных, который

считывается интерпретатором Open Basic во время выполнения программы.

 

 Формат оператора READ:

 

 [N] READ VAR1[,VAR2,VAR3,...]

 

где

 N    - номер строки

 VAR1,VAR2,VAR3 - переменные, которым присваиваются значения из списка

 оператора DATA

 

 Формат оператора DATA:

 

[N] DATA EXP1,[EXP1,EXP2,...]

 

где

 N    - номер строки

 EXP1,EXP2,EXP3, - выражение, которое вычисляется и

 присваивается переменной из списка READ. Могут быть числовыми

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

 

 Формат оператора RESTORE:

 

 [N] RESTORE

 

где

 N    - номер строки

 

 Перед выполнением программы Open Basic просматривает все операторы DATA в

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

встречается оператор READ, блок данных выдает последовательно соответствующее

значение для переменных этого оператора в том порядке, в котором они заданы

в блоке данных.

 После выполнения оператора READ положение последних считанных данных

запоминается. Следующий оператор READ начинает выбирать данные с той позиции,

которая была установлена предыдущим оператором READ.

 Open Basic осуществляет повторное чтение одних и тех же данных с помощью

оператора RESTORE.

 Оператор DATA должен быть единственным оператором в строке.

 

Пример:

 

 DATA 1.1,2,3,4,"1 string for data"

 DATA 5.1,6,7,4+4,"2 string for data"

 

 DIM z%(3)

 

 READ a2,z%(1),z%(2),z%(3),e2$

 

 READ a,b%,c%,d%,e$

 PRINT "a=";a;" b%=";b%;" c%=";c%;" d%=";d%;" e$=";e$

 READ a1,b1%,c1%,d1%,e1$

 PRINT "a1=";a1;" b1%=";b1%;" c1%=";c1%;" d1%=";d1%;" e1$=";e1$

 RESTORE

 READ a1,z%(1),z%(2),z%(3),e1$

 PRINT "a1=";a1;" z%(1)=";z%(1);" z%(2)=";z%(2);" z%(3)=";z%(3);

 PRINT " e1$=";e1$

 

 Результат работы оператора

 

 a=1.1 b%=2 c%=3 d%=4 e$=1 string for data

 a1=5.1 b1%=6 c1%=7 d1%=8 e1$=2 string for data

 a1=1.1 z%(1)=2 z%(2)=3 z%(3)=4 e1$=1 string for data

 

3.14.13.  Оператор RANDOMIZE

 

 Инициализирует случайный генератор новым значением. В качестве нового значения

используется текущее системное время в секундах. Поэтому повторно оператор

RANDOMIZE нужно применять не раньше, чем через 1 секунду после его предыдущего

применения.

 

 Формат оператора:

 

[N] RANDOMIZE

 

где

 N    - номер строки

 

 Оператор RANDOMIZE помещается перед первым использованием функции случайных

чисел (функция RND). При выполнении функции RND оператор RANDOMIZE изменяет

начальное значение случайного числа таким образом, что при последующем проходе

функция RND дает другие числа.

 

Пример:

 

 10 RANDOMIZE

 

3.14.14.  Оператор IF.

 

 Служит для организации условных переходов. Имеет три формата: строковый,

блочный и блочный укороченный.

 

Строковый формат оператора IF:

 

 [N] IF REL-EXP THEN operators

 

где

 N    - номер строки

 THEN - ключевое слово

 REL-EXP - проверяемое условие. Выражение отношения может быть арифметическим

или строковым.

operators - оператор или группа операторов

 

 Если условие REL-EXP истинно, то выполняются операторы в строке за ключевым

словом THEN, если условие ложно, то выполняется оператор в следующей за

оператором IF строке.

 

Пример:

   TT%=40

20 IF TT%=40 THEN GOTO 50

   PRINT "This operator do not work in example"

50 PRINT "Work IF operator","TT%=";TT%

 

 Результат работы оператора

 

 Work IF operator         TT%=40

 

Пример:

 

   TT%=40

   IF TT%=40 THEN PRINT "Work IF operator","TT%=";TT% GOTO 10

   PRINT "This operator do not work in example"

10 PRINT "Work IF operator","TT%=";TT%

 

 Результат работы оператора

 

Work IF operator         TT%=40

Work IF operator         TT%=40

 

Пример:

 

   TT%=40

   IF TT%=40 THEN a=101.1 b=102.1 c=103.1 GOTO 10

   a=1101.1 b=1102.1 c=1103.1

   PRINT "This operator do not work in example"

10 PRINT "a=";a,"b=";b,"c=";c

 

 Результат работы оператора

 

 a=101.1   b=102.1   c=103.1

 

Блочный формат оператора IF:

 

 [N] IF REL-EXP THEN

      operators1

     ELSE

      operators2

     ENDIF

 

где

 N    - номер строки

 THEN - ключевое слово

 REL-EXP - проверяемое условие. Выражение отношения может быть арифметическим

или строковым.

operators - оператор или группа операторов

 

 Если условие REL-EXP истинно, то выполняются операторы в блоке между ключевыми

словами THEN и ELSE. Если условие REL-EXP ложно, то выполняются операторы в

блоке между ключевыми словами ELSE и ENDIF.

 

Блочный укороченный формат оператора IF:

 

 [N] IF REL-EXP THEN

      operators1

     ENDIF

 

где

 N    - номер строки

 THEN - ключевое слово

 REL-EXP - проверяемое условие. Выражение отношения может быть арифметическим

или строковым.

operators - оператор или группа операторов

 

 Если условие REL-EXP истинно, то выполняются операторы в блоке между ключевыми

словами THEN и ENDIF. Если условие REL-EXP ложно, то выполняется оператор в

следующей за ключевым словом ENDIF строке.

 

3.15.  Встроенные функции

 

3.15.1.  Функция SGN%

 

 Функция SGN% - функция знака.

 

Формат: SGN%(EXP)

 

где EXP - целое или выражение с плавающей точкой.

 

Функция возвращает +1 если EXP>0, -1 если EXP<0 и 0 если EXP=0.

Если аргумент задан неверно(строковый), то генерируется ошибка.

 

Пример:

 

 PRINT "This is example SGN function"

 PRINT "<0";SGN%(-1-2);" >0";SGN%(2*3);" =0";SGN%(9+1-10)

 

3.15.2.  Функция ABS

 

 Функция ABS - определяет абсолютное значение аргумента.

 

Формат: ABS(EXP)

 

где EXP - целое или выражение с плавающей точкой.

 

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

Если аргумент задан неверно(строковый), то генерируется ошибка.

 

Пример:

 

 PRINT "This is example ABS function"

 PRINT "abs(-20.5)=";ABS(-20.5);" abs(20.5)=";ABS(20.5)

 

3.15.3.  Функция INT%

 

 Функция INT% - определяет целую часть аргумента.

 

Формат: INT%(EXP)

 

где EXP - выражение с плавающей точкой.

 

Функция возвращает целый результат.

Если аргумент задан неверно(строковый), то генерируется ошибка.

 

Пример:

 

 PRINT "This is example INT% function"

 PRINT "int(-20.3)=";INT%(-20.3);" int(20.3)=";INT%(20.3)

 

3.15.4.  Функции SIN, COS, ATN, SQR, EXP, LOG и LOG10

 

 Функции вычисляют синус, косинус, арктангенс, квадратный корень, экспоненту,

логарифм, и десятичный логарифм соответственно.

 

Форматы:

 SIN(EXP),

 COS(EXP),

 ATN(EXP),

 SQR(EXP),

 EXP(EXP),

 LOG(EXP),

 LOG10(EXP)

 

где EXP - целое или выражение с плавающей точкой.

 

Функции возвращают результат с плавающей точкой.

Если аргумент задан неверно(строковый), то генерируется ошибка.

 

Пример:

 

 PRINT "This is example trigonometric function"

 a=SIN(3.14/2)

 b=COS(0)

 c=ATN(1)

 d=SQR(4.0)

 e=EXP(1)

 f=LOG(EXP(1))

 g=LOG10(10)

 PRINT "a=";a;" b=";b;" c=";c;" d=";d;" e=";e;" f=";f;" g=";g

 

3.15.5.  Функция RND

 

 Функция RND - генерирует псевдослучайное число в интервале 0-1.

 

Формат: RND().

 

Функция возвращает результат с плавающей точкой.

Аргументы игнорируются.

 

Пример:

 

 PRINT "This is example RND function"

 PRINT RND(),RND(),RND(),RND();

 RANDOMIZE

 PRINT RND(),RND(),RND(),RND();

 

3.15.6.  Функция LEN%

 

 Функция LEN% - определяет длину строки.

 

Формат: LEN%(EXP)

 

где EXP - строковое выражение.

 

Функция возвращает целый результат.

Если аргумент задан неверно(целый или с плавающей точкой), то генерируется

ошибка.

 

Пример:

 

 PRINT "This is example LEN function"

 STRing_this$="aaa bbb ccc ddd"

 PRINT "len=";LEN%(STRing_this$)

 

3.15.7.  Функции DAT$ и CLK$

 

 Функции возвращают дату и время соответственно.

 

Форматы:

 

DAT$(),

CLK$()

 

Функции возвращает строковый результат.

Аргументы игнорируются.

 

Формат даты: day-month-year

Формат времени: hour:min:sec

 

Пример:

 

 PRINT "This is example DAT$ & CLK$."

 PRINT "data=";DAT$;" time=";CLK$

 

3.15.8.  Функции D2STR$, D2HEXSTR$, STR2FLOAT и STR2INT%

 

 Функция D2STR$ - конвертирует число в строку с его десятичным представлением

 

Формат: D2STR$(EXP)

 

где EXP - целое число или число с плавающай точкой

 

Функция возвращает строковый результат.

 

 Функция D2HEXSTR$ - конвертирует целое число в строку с его шестнадцатеричным

представлением

 

Формат: D2HEXSTR$(EXP)

 

где EXP - целое число

 

Функция возвращает строковый результат.

 

 Функция STR2FLOAT - конвертирует строку в число

 

Формат: STR2FLOAT(EXP)

 

где EXP - строка

 

Функция возвращает число с плавающай точкой. Если строка не может быть

конвертирована в число, возвращается ноль.

 

 Функция STR2INT% - конвертирует строку в целое число

 

Формат: STR2INT%(EXP)

 

где EXP - строка

 

Функция возвращает целое число. Если строка не может быть конвертирована в

целое число, возвращается ноль.

 

Пример:

 

 PRINT "converter from digit to string =";D2STR$(123)

 PRINT "converter from string to float =";STR2FLOAT("1.234")

 PRINT "converter from string to int =";STR2INT%("1234")

 PRINT "converter from digit to hex string =";D2HEXSTR$(4660)

 

 

3.16.  Обработка ошибок

 

 При обнаружении ошибки Open Basic генерирует исключение типа ob_err с кодом

ошибки. Пользователь должен перехватывать это исключение и обрабатывать его.

Для этого класс ob_err имеет специальные методы. Типовая схема работы с

исключениями ob_err:

 

int main(int argc, char * argv[]){

 

int ret=0;//код возврата main

 

ifstream fi;//входной поток

 

  try{

 

  ob_obasic basic_interpreter(OB_NULL);//Создание интерпретатора

 

  fi.open("test1.bas",ios::binary);//открытие входного потока в бинарном режиме

 

  basic_interpreter.clear_project();

  basic_interpreter.load_project(&fi);//загрузка *.bas-программы

 

  ob_obasic::typeend te=basic_interpreter.run();//запуск *.bas-программы

 

  cout<<endl<<"Stop by stop code";//печать кода останова

  cout<<endl<<"Stop code=";

 

  switch(te){

  case ob_obasic::ENDOPERATORDETECT  :cout<<"ENDOPERATORDETECT";break;

  case ob_obasic::ENDFILEEND         :cout<<"ENDFILEEND";break;

  case ob_obasic::BREAKPOINTEND      :cout<<"BREAKPOINTEND";break;

  case ob_obasic::NOLOADEND          :cout<<"NOLOADEND";break;

  case ob_obasic::BREAKBEFOREOPERATOR:cout<<"BREAKBEFOREOPERATOR";break;

  case ob_obasic::BREAKAFTEROPERATOR :cout<<"BREAKAFTEROPERATOR";break;

  case ob_obasic::EOLEND             :cout<<"EOLEND";break;

  default:cout<<"Unknown stop code";break;

  }//switch

 

  }//try

 

  catch(ob_err& e){

 

  cout<<endl<<"Stop by OB exception catch";//обработка исключения

  ret=e.getcode();                         //получение кода ошибки

  e.release(&cout,&ob_englmessage);        //печать текстового сообщения в cout

 

  }//OB catch

 

return ret;

}

 

Класс ob_err имеет методы getcode и release.

 

virtual ob_type_codeerror getcode();

virtual void release(ostream* os,ob_message* currentmessage);

 

Метод getcode не имеет аргументов и возвращает код ошибки.

Метод release имеет два аргумента: указатель на поток и таблицу диагностических

сообщений. Метод release записывает в указанный поток текстовое сообщение из

таблицы диагностических сообщений, соответствующее коду ошибки.

 Open Basic предоставляет таблицу диагностических сообщений на английском языке

ob_englmessage. Пользователь может создать собственную таблицу диагностических

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

release.

 Чтобы получить строку, в которой произошла ошибка, надо воспользоваться

функцией ob_loadbreakstr.

 

Более подробно обработку исключений можно посмотреть в файле .\example\ob.cpp.

 

3.17.  Таблица диагностических сообщений

 

Таблица диагностических сообщений расположена в файле ob5.cpp.