Writer HOLY 2016/06/18

Writer HOLY
2016/06/18
使用雑感
・構造化 BASIC
・フリーです
・汎用性があるコードです
・日本語対応:Linux 版
・コツはあるけど日本語対応:Windows 版
・非日本語:Android 版
X11-BASIC とは、Markus Hoffmann 氏が開発した由緒正し
い GNU GPL のフリーで使える BASIC です。コードの汎用性
について触れますと X11-BASIC の Windows 版、Linux 版互換
です。PC を持ってるのでしたら、SouceForge から
X11-BASIC をダウンロードして使うことができます。で、そ
の PC 版と Android 版のコードは、ハードウェア固有の命令
でなければ修正せずに動きます。ここが美味しいところで
す。ただし同じ BASIC というカテゴリーでも、X11-BASIC の
コードと、VisualBasic や GAMBAS とは色々違います。それ
でもプログラム構造が同じなら移植もそんな苦ではありま
せん。
SouceForge で X11-BASIC と検索して、その説明を読むと
「UNIX の基本」と一文だけ書かれている。それほど UNIX で
はお手軽に使える BASIC だと思います。"BASIC of UNIX"が
直訳されたんでしょうが。私も、仕事で Solaris や Linux
を使いますが、大きなプログラムを作るためではなくて、
スクリプト感覚で計算させるのに使ったりします。今はス
マフォで Android 版を使うけれども、将来的に PC を使うよ
うになったらコードの使い回しが効くんじゃないかなと。
機能とか流行とかはさておき、使うのにお手軽な BASIC だ
と思います。
コンパイラソースやサンプルプログラム
を/usr/share/doc/packages/X11Basic/examples 以下に探す
ことができます。他のサンプルプログラムは、
Sourceforge.net の X11-BASIC から、
X11-Basic-examples-1.22.zip をダウンロードできます。同
じく最新マニュアルの PDF(英語)もそこにあります。
更にために情報はファイル./doc/X11-Basic-manual.txt
を読んでください(これも英語ですな)。
X11-BASIC は、オープンソースソフトウェアであり、NO
WARRANTY です。Copy Right は次のとおりです。ありがたや。
VERSION 1.22
(C) 1997-2014 by Markus Hoffmann
([email protected])
Name
: X11Basic
Version
: 1.22
Vendor
: Markus Hoffmann
Group
: Development/Languages
License
: GPL
Packager
: Markus Hoffmann <[email protected]>
URL
: http://x11-basic.sourceforge.net/
Summary
: A Basic Interpreter and compiler with graphics
capabilities
基本的にオープンソースなので好きなように修正してい
ただいて結構ですが、そうすることで発生するあらゆる種
類のトラブルに我々は一切関知しない。(ということです)
導入前の注意
BASIC というプログラミング言語には、方言がつきものに
なっています。国際標準で定義された仕様もあるんですが、
技術レベルや時代の要求に追いついてない状況で、使用場
面に応じた文法や決めごとがまかり通っています。
X11-BASIC もそんな方言の中のひとつで、言語仕様どころ
か、その名称も似た BASIC が存在してます。ここでは、そ
ういう言語名称による誤解を避けるためいくつか注意を促
しておきます。
名前の似た BASIC として、
(1)X11-BASIC
(2)XBasic
(3)X-BASIC
という名前の BASIC が存在しています。べつに商標とか本
家本元論とかを話したいわけじゃなくて、名前の勘違いを
しないようにね、ということです。うっかりした勘違いで
回り道をしないように。
それぞれの違いは、こんな感じです。
(1)X11-BASIC
この本で取り扱おうとしてる BASIC です。対応機種/OS
は、Linux、Windows、Android です。
もともとは、ATARI GFA-BASIC のクローンを目指して開発
が始まりました。
名称の先頭が「X11」で、その後にハイフンを付ける人や、
付けない人もいるようです。
(2)XBasic
XBasic という名称の BASIC は結構あるようです。検索す
ると知ってるのも知らないのも出てきます。
その中でも、もっとも熟れているのは次の XBasic でしょ
う。
http://www.maxreason.com/software/xbasic/xbasic.html
これは今でも開発が続いていて、SourceForge でも活発な
動きがあります。
http://sourceforge.net/projects/xbasic
対応機種/OS は、Linux、Windows です。
Microsoft Quick-BASIC 風な文法の流れを汲むそうです。
GUI 開発用の IDE も相当作り込まれています。
名称は頭文字が X で、B は大文字、asic は小文字で書く
人が多いようです。
(3)X-BASIC
SHARP が販売していた X68000 の BASIC です。現在でも日
本で X-BASIC と言えばコレをあげなければモグリと言われ
ます。その辺が、X11-BASIC がいまいち日本で浸透しない理
由なんですかねぇ。
X68000 の技術は、本舗 SHARP が仕様を公開していること
から、エミュレータに移植したり未だに活動が行われてい
ます。
その中で、iOS で動かせる「X-BASIC for iOS」(AIG
Soft)が App Store に公開されています。
このようにアルファベット「X」には、どうもマニア心を
くすぐるものがあるらしいです。
インストール
X11-Basic SourceForge のコメント(機械翻訳)より
『UNIX の基本』
詳細情報
開発状況: 5 - プロダクション/安定, 6 - 成熟
対象ユーザ: 開発者, 教育, 科学/研究
ライセンス: GNU General Public License v2 (GPLv2)
主要対話語: 英語, ドイツ語
オペレーティングシステム: Cygwin (MS Windows), Android, POSIX
(Linux,BSD,Solaris など), Linux, その他, Windows XP
プログラミング言語: BASIC, C
トピック: SourceForge.net, CGI ツール/ライブラリ, インタプリタ, 仮想
マシン
ユーザインタフェース: フレームバッファ, タブレット PC, X11 アプリケー
ション, コマンドライン, SDL, Win32 (MS Windows)
X11-BASIC はグラフィック機能のある BASIC です。その文
法は、昔の ATARI-ST(アタリ社)が 1985 年発売したパソコン
用(CPU は MC68000)の GFA-BASIC(初版 1986 年)のクローンを
目指して開発が始められました。日本にはあまりいないと
思いますが、GFA-BASIC の経験者は若干の修正で習熟できる
はずです。当時のパソコンの世界では各社独自の GUI の開
発花盛りでして、ATARI でも独自の GEM という GUI システム
を提供してました。GUI 関係の命令にその一端を垣間見るこ
とができます。
また、MS-DOS の QBASIC(Borland 社対抗の Microsoft
QuickBASIC の簡易版)のプログラマーもほぼコンパチブルで
す。おそらくこっちのほうが馴染みのある人が多いことで
しょう。
UNIX/Linux 版
X11-BASIC のマニュアルやら ReadMe を読むと、
./configure
make
sudo make install
でいけると思います。不肖私が行ったインストールの備忘
録をさらしますと、こんなことをしていました。
$ ls (saucefoege.com からダウンロードしたファイル)
X11Basic-1.22.tar.gz
$ gzip -d X11Basic-1.22.tar.gz (圧縮ファイルを解凍)
X11Basic-1.22.tar
$ tar -xvf X11Basic-1.22.tar (tar アーカイブを展開した)
$ ls
X11Basic-1.22 X11Basic-1.22.tar
$ cd X11Basic-1.22
$ ./configure
(中略)
$ make
(中略)
(make するとディレクトリに x11basic.a や libx11basic.so.ver ができる)
$ cd ..
$ su (root になります)
パスワード:
(make install はしないで動かせるように細工をしました)
# mv X11Basic-1.22 /usr/local (/usr/local 以下に作ることにした)
# cd /usr/local/X11Basic-1.22
# cp libx11basic.so.1.22 (ver.1.22 なら 1.22 をコピー)
# cp x11basic.a /usr/lib
# chmod 755 /usr/lib/libx11basic.so.1.22
# chmod 755 /usr/lib/x11basic.a
最後に、ホームディレクトリ直下の.bashrc の
alias xbasic='/usr/local/X11Basic-1.22/xbasic'
alias xbc='/usr/local/X11Basic-1.22/xbc'
のように入れました。
X11-BASIC のパッケージには、xbasic というインタプリ
タと一連のコンパイラが含まれています。インタープリタ
は、basic-script とでも言えるようなシェルスクリプト風
に利用することもできます。
パッケージにはコンパイラ(xbc)も、含まれます。コンパ
イラはインタプリタに比べてだいたい 10 倍早くなります。
恐らく saucefoege.com には、deb パッケージもダウン
ロードできるようになってるので Ubuntu 系のディストリ
ビューションなら、パッケージインストーラーでインス
トールする手もあります。ただこの場合だと、コマンドラ
インインタプリタを試す分には問題ありませんでしたが、
xbc でコンパイルしようと実行するとリンクエラーが出て上
手くいきませんでした。
X11-BASIC プログラムを、中間バイトコードにコンパイル
することもできます(xbbc)。このバイトコードは、仮想マ
シンによって動作できます(xbvm)。その中間バイトコード
は、環境ネイティブの C 言語でコンパイル可能な C ソース
コードに変換できます(xb2c)。
古の ANSI-Basic プログラム(行番号つき)を、
bas2x11basic を使うことで X11-BASIC コードに変換できま
す。
Android 版
Android バージョンの X11-BASIC は、通常のアプリとして
Android Market からダウンロードできます。他のバージョ
ンの X11-BASIC のとは異なり、Android バージョンでは、イ
ンタープリタ、それを動かす仮想マシン、Load して、Run
して、Edit して、コンパイルする一連の操作ができるよう
な IDE として組み込まれます。同じく標準出力となるテキ
ストコンソールにも、少なからずな修正が加えられてます。
標準入力デバイスはキーボードとしてます。
それらのアイデアは、起動直後にダイレクトステートメ
ントを実行できることに配慮して、シンプルに扱えるよう
にしたからです。もちろん、拡張子.bas のソースプログラ
ムを Load して Run させても大丈夫です。それに拡張子.b の
コンパイル済みのバイトコードを実行させることもできま
す。
Android では、BASIC プログラムのソースファイルは bas
フォルダ(/mnt/sdcard/bas)に保存して実行してください。
ソースファイルの拡張子は.bas です。コンパイルした実効
ファイル(拡張子.b)もそこで Load してから Run するという
形式になります。また、Android 版でも、コンソールに直接
命令や式(数字を含む)を入力して実行するダイレクトス
テートメントを使うことが出来ます。
Android 版の X11-BASIC ではエディタアプリも一緒にイン
ストールしましょう。詳しく書くとちょっと長くなるので
ここでは書きませんが、X11-BASIC のメニューに「どのアプ
リをエディタに使う?」という項目があります。そのほう
が絶対楽です。
Windows 版
適当なフォルダを作成しておきます(例えば「X11BASIC」
とか)。場所は Program Files 以下でも、マイドキュメント
フォルダ以下でも構いません。SaurceForge などから
Windows 用 zip ファイルをダウンロードして解凍します。
WindowsXP 以上ならダブルクリックすれば中身が表示される
と思うので、それらをドラッグして先ほど作っておいた
フォルダに移します。
その中に、xbasic.exe という実行形式ファイルがあるの
で、それをダブルクリックしてください。コマンドプロン
プトみたいな黒いスクリーンが現れると思います。それが
X11-BASIC のコンソールです。閉じるにはウィンドウの
「x」ボタンを押して終了させても構わないんでしょうが、
丁寧に終了するにはプロンプトで「quit」と入力して終了
しましょう。
注意ですが、解答したファイルの中に setup.exe があり、
あたかもこれを実行すればインストールし始めますよ、み
たいな雰囲気をだしてると思います。私の経験ではそれは
実行させないほうが良いですね。確かに実行すると
X11-BASIC をインストールするんですが、X11-BASIC が C ド
ライブの直下に作られたり、拡張子「BAS」とつくファイル
をすべて X11-BASIC に関連付けられてアイコンも変わりま
す。親切とも言えなくはないのですが、余計なお世話です。
解凍したファイルの xbasic.exe で BASIC が起動できて使え
るならそれでいいじゃん?と思います。
あとコンパイラ xbc を使うには、ソースファイルを
X11-BASIC をインストールしたフォルダに持ってきて、
「xbc [ソースファイル名]」とするのがお約束みたいです。
このフォルダにパスが通ってるかではなく、lib フォルダが
直下にあることが重要みたいです。それを裏付けるために
試してみました、パスを通しただけではダメでしたね。
Windows 版 X11-BASIC を Windows の制御下で利用できる日
本語コードは SHIFT-JIS です。これは xbasic.exe を実行し
てのコンソールを表示するとおかしいと思うでしょう。コ
ンソールのメッセージの文字が化けるんです。
けれど SHIFT-JIS & CR+LF コードで書いたソースファイ
ルを load して run すると日本語が表示されます。同じコー
ドを xbasic.exe と同じディレクトリに置いてコマンドプロ
ンプトで
xbasic [ソースコード名].bas
で実行するとやはり日本語が表示できるます。これは
X11-BASIC コンソールやコマンドプロンプトが Windows の制
御下にあるからそうなるんです。
これは X11-BASIC を Unicode(UTF-8)を表示させるターミ
ナルで使うことをはじめから意図してるようです。試しに
Cygwin をインストールしてる WindowsPC で、TeraTerm に付
属してくる Cygterm で UTF-8 & LF コードと指定して
xbasic.exe を起動すると、化けずにメッセージが表示され
るんです。
色々と思惑があるんでしょうな。GNU 関係のプロジェクト
同志とか、世の中は Unicode が標準だからいいかげん移行
しろよとか。なんでこんなややこしいことをしたんだろう
と思います。私が見落としてるのかもしれませんが公式な
説明は見当たりません。こういう「わかってるでしょ?」
みたいな姿勢を変えないことにはユーザはつかないですよ
ね。現に日本人ユーザってホント見かけませんし。
MacOSX にて…
MacOSX には、OSX ver2.0 の頃から X11 環境がインストー
ルできるようになりました。このおかげで、UNIX で作られ
た X11 アプリケーションをソースから MacOSX でコンパイル
すれば、MacOSX でも使える恩恵に授かりました。
今の MacOSX ではいったいどうなってるかわからないんで
すが、私の持ってる MacOS10.6.8 SnowLeopard では、OS の
DVD-ROM の中にオプションとして、Xcode や X11 環境を含む
その他設定が用意されていて、OS とは別に任意でインス
トールを行うようになっています。
結論を述べますと、私の環境では X11-BASIC のインス
トールは上手く生きませんでした。ちなみに、X Window
System は、XQuartz 2.3.6。gcc は
i686-apple-darwin10-gcc-4.2.1 です。この試行をするため
だけに Xcode をインストールしたので DVD からインストー
ルした状態からアップデートはしてません。そういう
ニュースはないので OSX の X11 や gcc の初期不具合とかでは
なさそうです。
./configure
は、うまくいったのですが、make で
ld: symbol(s) not found
collect2: ld returned 1 exit status
make: *** [xbasic] Error 1
で異常終了してしまいました。リンク関係すか・・・。
わたくしの修行が足りないもありまして、原因究明には
いたらず。つまりその調べるのもめんどくさくてですね。
Linux でも Windows でも Android でも動いている現状では、
わざわざ MacOS で動かしたいとは思わないわけで。
どうしても、MacOS で動かしたい方は、がんばってくださ
い。おそらくチャレンジしてる人はきっといます。
よう、世界
ここでは、Android 版の X11-BASIC のメニューを上から順
番に説明するスタイルをとります。Windows や Linux に
X11-BASIC をインストールした方なら、改めて読むほどの内
容ではないかもしれません。それでも、X11-BASIC を使う上
での約束事もあったりするのでご覧になってください。
X11-BASIC はスクリプト・インタプリタです。コマンドを
羅列したファイル(プログラム)を実行します。X11-BASIC の
プログラムでは通常、拡張子に「.bas」とか「.xbas」と付
けます。または、一行ずつコマンドを実行させるインタラ
クティブモードで実行することもできます。
Android でご利用の方は、X11-BASIC アプリのアイコンを
タップすると最初からインタラクティブモードになります。
Windows や Linux で X11-BASIC インタプリタを開始するに
は、いくらか方法があります。一番簡単な方法は、xbasic
とコマンドを打ち込む方法です。そうするとインタラク
ティブモードでインタプリタを使うことができます。
インタラクティブモード
X11-BASIC を起動させると画面はこうなると思います。
*************************************
*
xbasic
V. 1.23
*
*
by Markus Hoffmann 1997-2015 (c) *
*
*
* lib
Sun Dec
7 11:53:25 CET 2014 *
*************************************
>
この「>」印はプロンプトと呼びます。このプロンプトの
後にカーソルがあると思います。
プロンプト「>」の後ろに入力したコマンドは、エンター
キーを押せばそのまま実行されます。
キーボード等の入力で
> print "Hello,World"
と入力して改行(Enter)してください。すると、
> print "Hello,World"
Hello,World
>
と表示されてると思います。
入力したコマンド文字列はメモリにバッファされるので、
上下キーを押して過去に入力した履歴を遡ることができま
す。
このようにコンソール画面に直接コマンドを入力してコ
ンピュータから返事を得る方法を、X11-BASIC ではインタラ
クティブモードと呼びます。いにしえの旧制 BASIC では、
ダイレクトステートメントと言ってたことができます。ち
なみに、英字は大文字でも小文字でも区別しません。
それでは次に足し算をします。
> print 1+1
2
となったと思います。
print という命令はなんだろうと察するに、コンソールに
結果を出力する命令なんだと推測できると思いますよね。
プログラムはこういう命令を書いたコードをコンピュータ
に順番に実行させることです。
ここでコードを記述するために、いったん X11-BASIC を
終了させます。X11-BASIC を終了するには、右上のメニュー
から「Quit」を選ぶか、先ほどのプロンプトに「> quit」
と入力して改行(Enter)するか、またはキーボード付きの端
末なら Ctrl-C を押せば終了します。
プログラミング
さて、プログラミングする前にやることがあります。な
んでもいいのでエディタアプリをインストールしてくださ
い。Android でもプログラムを書くにはエディタを使ったほ
うが楽です。私は「920 Text Editor」(有償版)と
「Jota+」(フリー/有償版)を使わせていただいております。
「Jota+」は BASIC のコマンドの強調表示に対応してるので
結構良いです。有償版にアップグレードするかは、あなた
のお好みで。
Android 版 X11-BASIC ではプログラムを Load しようとす
ると、ローカルディスクの下にある BAS ディレクトリを開
きます。パスで表記すると私の Android 端末では、
/mnt/sdcard/bas になります。おそらく Android OS のセ
キュリティの制約によるアプリの決め事なんだと思います。
ファイルはその下にある拡張子.bas ファイルを選択する
ことになります。そのため自分で新たにプログラムを書く
場合は、直接 BAS ディレクトリ以下に作成するか、他の
ディレクトリから X11-BASIC ソースファイルをコピーして
くることになります。私は他のディレクトリ(例えば work
とか作成して)にソースを作成して、./BAS にコピーするこ
とにしてます。その方がバックアップになりますしね。
まずは慣例に倣い"Hello, World"を表示させます。
簡単に言えば、
(1)「print」という命令を使って"Hello,World"という文字
を表示させる。
(2)最後に「End」と書く。
の二点です。
ではエディタを開いて
print "Hello, World"
end
と書き込んでください。半角英文字なら大文字でも小文字
でもいいです。
プログラムを書いたら保存しましょう。とりあえずお好
きなフォルダに保存してください。ファイル名は好きな名
前でいいです。Android OS のファイルシステムが全角日本
語をサポートしてるのでファイル名が漢字でもカタカナで
も読むことはできます。けど X11-BASIC が全角文字の入出
力は対応してませんので英字にしとくのが無難だと思いま
す。
拡張子は「.bas」としてください。
ファイル名に悩むなら日付で作ってみてください。2014
年 09 月 20 日なら「20150220.bas」みたいな感じで。題名
が思いつかなくても、いつ作ったのかわかるので悩んだと
きは良いです。
所望のディレクトリにプログラムを保存したら、その
ファイルを./BAS へコピーします。
では X11-BASIC を起動させてください。
*************************************
*
xbasic
V. 1.23
*
*
by Markus Hoffmann 1997-2015 (c) *
*
*
* lib
Sun Dec
7 11:53:25 CET 2014 *
*************************************
>
LOAD
右上のメニューから「Load」を選んでコピーしたファイ
ルを選択してください。
またはダイレクト・ステートメントで
> load "ファイル名.bas"
で LOAD することができます。ここでフィアル名に全角文字
を使っていると、Android 版 X11-BASIC ではコンソールに文
字を入力できないわけです。
LIST
プロンプトに
> list
と入れて Enter してください。
すると先ほどエディタで作成したコードが表示されると
思います。
RUN
右上のメニューから「Run」を選んでください。またはプ
ロンプトの後に
> run
と入れて Enter してください。
すると
> run
Hello,World
と出力されると思います。
NEW
NEW というコマンドは、読み込んだ X11-BASIC プログラム
をクリアする命令です。
右上のメニューから「New」を選んでください。または
> new
と入力します。その後に、
> list
と入力してもリストが表示されないことがわかります。
またプログラムを読み込みたいなら再度「Load」すれば
いいです。
QUIT
最後は QUIT で X11-BASIC を終了します。
Android の場合は、QUIT コマンドの使い方に注意してく
ださい。QUIT は本当に X11-BASIC というアプリを終了する
コマンドです。プログラム終了即ちアプリの終了というの
なら構わないんですが、計算結果を出力するプログラムだ
とアウトプットを読むことができなくなります。この場合
は、STOP や END を有効に使ってください。
ここまでの一連の操作の流れです
(Result)
> load "test.bas"
> list
print "Hello, World"
end
> run
Hello, World
> new
> list
> quit
最初のプログラムとして、まずは以上でございます。
文法と構文の基礎
プログラミングとは
「コンピュータ、ソフトなければただの箱」とは聞き古
した格言ですが、実際コンピュータを動かす際には、ソフ
トウェアが必要不可欠になってきます。このソフトウェア
によって、ワープロ、ゲーム、インターネットなど、私た
ちはコンピュータを様々な形で使うことができるのです。
「じゃぁ、ソフトウェアはどうやって作ってるの?」
それは、プログラミングによって作られます。ソフト
ウェアを正しく動かすには、その手順書、プログラムを作
る必要があります。その作業をプログラミングといいます。
これから、X11-BASIC でのプログラミングを色々書いてい
きます。まずはどんな入門書にも書かれているようなその
言語の生い立ちでも書いておきます。別に読み飛ばしても
困る話ではないのですが、なんというかこれから使い方を
思える言語への愛着というか、親しみというか持っている
といないのでは継続に違いはあると思うんですよね。意気
込みっていうんですか?そういうのを感じていただければ
いいと思います。
BASIC の生い立ち
BASIC は、1964 年ころにダートマス大学の J.G.ケメニー
と T.E.カーツによって開発された教育用プログラミング言
語です。当時、主流だった FORTRAN を手本としながらも、
FORTRAN の使いにくいところを初学者向きに改めて作成され
た言語です。 ケメニーとカーツの BASIC は、現在、True
BASIC と呼ばれ、Windows、Mac、UNIX などに対応したバー
ジョンがあります。
マイコン用 BASIC
現在、多くの人が BASIC だと思って使っている言語は、
本来の BASIC とは異なるものです。NEC の N88-BASIC や富士
通の F-BASIC、シャープの Hu-BASIC などです。これらの言
語は、見かけはよく似ていますが、根幹となる部分で本来
の BASIC と相違する点があります。
これらの言語は、マイコン用に改変された文法を継承し
ています。初期のマイクロコンピュータは現在の PC とは異
なり、メモリをふんだんに使うことはできませんでした。
いかにして限られた容量の ROM のなかに BASIC 処理系を詰
め込むかが勝負となったのでした。そのために採用された
手法の 1 つがインタプリタです。インタプリタは、書かれ
たコードを一行ずつ順番にマシン語に変換し実行します。
そのためプログラム全体としての実行は遅いです。その代
わり、一行に print 1+1 と入力して Enter すればすぐに 2 と
返答するようなダイレクトステートメントのような使い方
ができて電卓くらいの意識で気軽に使えたわけです。
ちなみにこれが Microsoft の Quick BASIC みたいな構造
化 BASIC になりますと話は変わります。それまでは1行1
行機械語に翻訳してたわけですが、構造化 BASIC の仕様上
プログラムリストを読み込んで構造を分析しなければなら
なくなりました。その段階でダイレクトステートメントと
いう小技は使えなくなりました。じゃあ代わりに、という
わけでしょうか、構造分析する手間があるんだったら文法
のミスとかエラーも添削しましょうというわけになりまし
た。そういういきさつが現在の一般的な IDE の親切機能に
反映されてるわけですね。
BASIC 言語の標準化
マイコン時代に各社各様の BASIC が乱発されたことによ
り、BASIC の仕様に危機が訪れます。そこで BASIC の標準化
をしようという活動が始まりました。BASIC の標準化のため
の作業は 1974 年に始まり、4 年後の 1978 年に米国および欧
州で Minimal BASIC(最小 BASIC)として規格化されました。
1982 年には国際標準化機構(ISO)原案が作成され、1984 年
には Minimal BASIC の国際規格が制定されました。日本で
は、ISO 規格案に基づいて、1982 年に「基本 BASIC」という
名称で Minimal BASIC が規格化されました。
Minimal BASIC の規格化に引き続いて、BASIC の完全バー
ジョン(Full BASIC)の規格化作業が開始されたのですが、
その作業はかなり難航したようです。1982 年に原案が作成
され、1986 年に欧州、1987 年に米国で規格として成立しま
した。国際標準化機構(ISO)は、1991 年に欧州規格と米国規
格を包含する形で Full BASIC の ISO 規格を制定しました。
日本では、ISO 準拠の形で 1993 年に Full BASIC の JIS が制
定されました。
1989 年、米国でモジュールおよび単文字入力に関する追
加の規定が規格化されました。これは、JIS では参考として
収録されています。
問題解決指向
現在、広く用いられているプログラム言語のほとんどは、
プログラムを書く人自身の問題を解決するために書かれる
のではなく、他の誰かがユーザとして使うことを考えて作
り始めるのが普通です。プログラミングという体験に向か
う姿勢に違いがあるということがわかると思います。
しかし、本来の BASIC は、問題解決指向です。プログラ
ムを書くのは、他者に使わせるためではなく、プログラム
を作成する人自身の問題を解決するためです。他者に使わ
せるプログラムでは入力をわかりやすくするための装飾的
部分が重要になりますが、自分で使うプログラムでは装飾
的な部分や説明的な部分に手間をかけたいとは思いません。
Full BASIC はコンピュータの専門家でない人が問題を解
決するツールとして使うのを考えています。Visual Basic
は、割と他の人が使うことを想定して作るもんです。じゃ、
X11-BASIC は?ということになりますが、これは割とバラン
スのとれてる仕組みでどうとでも作ることができる気がし
ます。GUI 風に部品を綺麗に配置することも、または武骨に
ターミナル上でコマンドラインで使うこともできます。ま
あ、Visual Basic が GUI ベースの Windows を普及させるた
めの先人になってしばらく、だいぶこなれてきたというこ
とでしょう。
なんにしても、プログラミングという作業はお給料をも
らったり、クライアントさまのことを考えながら作るもの
だという思い込みは捨ててしまってかまいません。プログ
ラミングは日々の日記をブログに載せたり、チラシの裏に
描いた絵をスキャンして投稿したり、YouTube に動画を投稿
したりと同じく個人的体験だという。そこがポイントです。
BASIC バッシング
おおむね好意的に受け入れられてきた BASIC ですが、コ
ンピューターの世界には反対意見も存在していました。特
に目立って論陣を張っていたのが、オランダのコンピュー
ター科学者であるエドガー・ダイクストラ教授でした。
2002 年に亡くなったダイクストラ教授は BASIC に関して
「BASIC に一度でも触れたことがあるものに対して良いプロ
グラミングを教えることは事実上不可能である」と発言す
るなど、強硬な反 BASIC 論者として知られていました。
実際には、PL/I は「致命的疾病」、FORTRAN につい COBOL
に至っては「犯罪行為」とまで批判していたために BASIC
のみを標的にしていたものではなかったのです。まあ、批
判屋稼業というのはいつの時代もどんなところにもいるっ
てことでしょうか。ネガティブで不安を煽るニュースの方
が記憶にはよく残るもので、そういうわけで何かと BASIC
というと「ちょろい言語」という先入観を持たれるように
なりました。
しかし、現在でも Microsoft 謹製の他にもいろいろな
BASIC が生き残ってることを考えるとそうした印象が的はず
れだったとわかると思います。なぜでしょう。理由があり
ます。そもそも BASIC が初学者のプログラミングスキル習
得を目的としたプログラミング言語だからです。そこをよ
く誤解しますよね。新しいプラットホームができて、そこ
でプログラミングしてみようとする人が現れる限り、そこ
に BASIC があるわけなんです。
コンソールへの出力
Print 文
Print は、コンピュータに出力をさせるための命令です。
Print 文を利用して文字列を表示することができます。文字
列は、その前後を引用符(")で囲んで表します。
基本的に、プログラムは上から下に読まれます。命令は
こんな風に、複数行にわたって書くこともできます。
まずは X11-BASIC を起動してプログラムリストを Load し
て実行する方法で実行してみます。
holy@901:~$ xbasic
**********************************************************
*
xbasic
V. 1.23
*
*
by Markus Hoffmann 1997-2014 (c) *
*
*
* version date:
Mon Aug
4 21:15:31 CEST 2014 *
* library V.1.23 date:
Mon Aug
4 21:13:35 CEST 2014 *
**********************************************************
> load "test.bas"
> list
Print "Hello, World"
Print
Print "I am X11-BASIC"
End
> run
Hello, World
I am X11-BASIC
>
Print の隣に何も記述しないで、ただ Print とだけ書くと
空白行が出力されます。
Print の隣に式を直接書くと、コンピュータに計算させる
ことができます。
今度はターミナル上で実行させてみましょう。コードの
先頭に「#! パス名」と終わりに Quit 文が入ってるのがポ
イントです。Quit 文により、処理が終了したら X11-BASIC
インタプリタも終了するようにしています。Andoroid を試
用されてる方は、Quit 文は外したほうがいいでしょう。い
ちいちアプリが閉じてしまいますから。
holy@901:~$ ls -l test.bas
-rw-rw-r-- 1 holy holy 35
3月
4 21:40 test.bas
holy@901:~$ chmod +x test.bas
holy@901:~$ ls -l test.bas
-rwxrwxr-x 1 holy holy 35
3月
4 21:40 test.bas
holy@901:~$ cat test.bas
#! /usr/bin/xbasic
Print 1+3
Quit
End
holy@holy-901:~$ ./test.bas
4
代数を使うこともできます。
仮に a を底辺、b を高さとしたら、出力される結果は三角
形の面積ということになります。
すでに実行権を付加してる test.bas を編集して使いまわ
します。Android を使ってる人は、メニューから Edit を選
択してコードを書き換えてみてください。書き換えたら保
存して、再ロードしてください。
holy@901:~$ cat test.bas
#! /usr/bin/xbasic
a = 3
b = 4
Print (a * b) / 2
Quit
End
holy@901:~$ ./test.bas
6
Print 文では計算結果を出力するときにその様式を制御す
ることができます。そのうち、特に重要なものを説明しま
す。
Print 文には、コンマまたはセミコロンで区切って複数の
項目を書くことができます。
項目の区切り記号にセミコロンを用いると、各項目は詰
めて表示されます。項目の区切りにコンマを用いると、各
項目は一定の桁位置まで空白を出力した後に出力されます。
たとえば、
(X11-BASIC)
Print 1;2;3,4
End
(Result)
123 4
通常、Print 文を実行すると、最後に改行します。改行し
たくない場合には、Print 文の末尾にコンマかセミコロンを
書いておきます。
たとえば、
(X11-BASIC)
Print 1;2;
Print 3;4
End
(Result)
1234
のように出力されます。
コンソールからの入力
Input 文
プログラムの実行時に変数に値を代入したいときには
Input 文を用います。Input 文では、Input に続けて数値を
代入したい変数をコンマで区切って並べます。
次のプログラムは、入力された 2 数の平均を表示します。
例ではセミコロンを末尾につけた Print 文を直前に入れ
ることで、何を入力するのか表す小技を使っています。
(X11-BASIC)
Input " a= ? "; a
Input " b= ? "; b
Print (a + b) / 2
End
(Result)
a= ? 35
b= ? 66
50.5
命題
数値
加減乗除の演算を、それぞれ、+、−、*、/で表します。
また、ベき乗の演算は、^という記号を用いて、たとえば、
2 3 を 2^3 のように表します。
異なる演算記号を含む式を書くと、最初にべき乗を実行
し、次に乗除算を実行して、最後に加減算を実行します。
同順位の演算は左から実行します。
計算を実行してその結果を表示させるのに Print 文を用
います。
(X11-BASIC)
Print 2+3*4^2
Print 3/4*5
Print (2^4)^5
End
(Result)
50
3.75
1048576
1 行目は 2+3×4^2 を計算します。
2 行目は 3÷4×5 を計算します(3/(4×5)ではありません)。
3 行目は (2^4)^5 を計算します。ここで、ちゃんと( )で
囲まないと
Print 2^4^5
1048576
となります。
X11-BASIC は、-2147483648 から 2147483647 までの 32
ビット整数を使います。浮動小数点は 64 ビット IEEE754 標
準にしたがいます。それらは、52 ビットの仮数(常用対数小
数部)と 11 ビットの指数と符号ビットを持っています。そ
れらは 16 桁目を+ー符号として使って 1e-308 から 1e+308
の値に置き換えられます。乗数でも+ーの符号を使った表
現ができます。
253 67.3 0.25 -127.42E-3 -1.3E7 1
10 進数整数を 16 進数や 2 進数表記に置き換えることがで
きます。16 進数は$(または 0x)と表現されます。2 進数表記
では%を用います。
%101010 -$FFE0 0xA0127BD -%10001001 %00011010
算術関数
X11-BASIC は基本的な算術関係の関数を取り扱っています。
三角関数:SIN()とか ATAN()
対数:LOG()
ビット演算:AND とか OR
最大最小:MIN()と MAX()
余りとか整数:MOD とか INT()
演算子
数値演算子はおおよそ、以下のような分類で分類されて
います。
算術演算子(arithmetical operators): ^ * / + 比較演算子(comparison operators): = <> < > <= >=
論理演算子(logical operators): NOT AND OR XOR ...
X11-BASIC の演算では、次のような優先順位で認識します。
優先度 演算子
1
( )
parenthetical expression
2
^
exponent/power
3
sign (negation)
3
+
sign
4
NOT
bitwise not
5
=
divide
5
*
multiply
5
"
integer division
5
MOD
modulus (rest of division)
6
+
add
6
-
subtract
7
<<
bitwise shift to the left
7
>>
bitwise shift to the right
8
=
logical "equals"
8
<>
logical "not equal"
8
<
logical "less than"
8
>
logical "greater than"
8
<=
logical "less than or equal"
8
>=
logical "greater than or equal"
9
AND
bitwise and
9
OR
bitwise or
9
XOR
bitwise xor
9
IMP
implies
9
EQV
equivalence
10
=
assignment
変数
X11-BASIC での変数は、動的型付けでグローバルです。
どういうことかと言いますと、まず変数を使用するのに
どんな型の変数を使うのか宣言する必要がありません。
X11-BASIC のほうで勝手に判断してくれます。
またどこから変数を使い始めても、その変数はプログラ
ム内ならどこでも使えます。プロシージャや関数ないでも
それが通用します。
具体的な例を示します。
(X11-BASIC)
A = 1
Print A
@Flip()
@Flop()
End
Procedure Flip()
A = A + 1
Print A
Return
Procedure Flop()
A = A - 1
Print A
Return
(Result)
1
2
1
となりますし、あえてプロシージャや関数でのみ使いたい、
使い捨ての変数なら
(X11-BASIC)
A = 1
Print A
@Flip()
@Flop()
End
Procedure Flip()
Local A
A = A + 1
Print A
Return
Procedure Flop()
Local A
A = A - 1
Print A
Return
(Result)
1
2
0
となります。
X11-BASIC は二つのスコープを使います。すなわち
Global か Local かです。Global がデフォルトとなります。
Global 変数は、プログラム内ならどこでも使えます。Local
と宣言しない限り、X11-BASIC の変数はデフォルトで
Global 変数です。しかしグローバル変数を多用することで
プログラムコードの可読性や理解が低下するという弊害も
あります。とはいえコードのどんな場所でも変数の値を変
えたいときに変えることができるというのもいいことです
よ。Global 変数は他の Local スコープの変数と名前がかち
合う恐れが多々あります。
そういうわけで X11-BASIC も、注意を払う必要のあるプ
ロシージャや関数で使えるように Local 変数を供します。
もし同じ名称の Global 変数があったとしても、Local に使
われてる変数とは別物と扱われます。
命名
変数の名前を命名するのに文字と数字を使うことができ
ます。変数名の中にスペースを入れることはできません。
そういうときはアンダースコアで代用してください。変数
名は複数文字を使ってある程度長くてもいいです。変数名
の最初の文字に数字やアンダースコアを使うことはできま
せん。X11-BASIC の命令に似た変数名にはしないでください。
トラブルの元になります。例えば、TRUE, FALSE, TIMER,
PC, TERMINALNAME$とかいうのも避けるべきでしょう。
確かに変数の命名はユーザに任せてます、しかし既に内
部変数として使われてる名前は使えません。それと次のよ
うな名前もつけるべきではありません。
x, auto%, lives%, bonus1%, x`1, city`name$
次のような変数にも X11-BASIC は警告を出します。
`blank, 1x, ?value%, 5s$.
変数の頭文字は A-Z で始まるようにするのが安全です。
変数名がコマンド名とか他の型の変数や配列名と区別の
つきにくい名前もよくありません。例えば、A$という文字
列変数があるとすれば、A とか A(1,1)とか A$(1,1)見分けが
つきにくいと思います。
コマンド間のスペースは無視されます。しかし、とりわ
け括弧の前後、ASC("A")とするのを ASC( "A" )とか ASC
("A")とかするのはダメです。
(例)
整数型:
i%=25
my`adr%=VARPTR(b$)
b%=MALLOC(100000)
実数(浮動小数点)型:
a=1.2443e17
b=@f(x)
文字列型:
t$="Hello everybody !"
配列:
i%(),a(),t$(), [1,3,5;7,6,2]
変数の型
変数に入ってる中身がなんなのかどうすれば知ることが
できるでしょう。X11-BASIC では、変数名そのものが変数の
型式を語ります。
X11-BASIC は特殊な印をつけることでデータ型を見分けま
す。X11-BASIC は、浮動小数点や整数、文字列や配列も扱え
るインタプリタです。配列の宣言には DIM 命令を使うもの
の、変数の型の宣言は必要ありません。X11-BASIC インタプ
リタは、変数名文字列の末尾で変数の型を認識するからで
す。
整数は「変数名%」、文字列は「変数名$」、配列は「変
数名()」。末尾にこれらの識別記号のない変数は実数
(Float)として扱われます。整数のポインタや関数の呼び出
しには文字列の先頭に「@」が使われます。それと論理型は、
整数と同じ記号が使われます。
注意していただきたいのは、個々の変数の用途や区別は、
名付け親であるあなたの命名センスを以って実現できてる
ことです。変数名の名付けで不精しないようにしてくださ
い。
(例)
x=10.3 : 64bit 浮動小数点実数型
x$="Hello" : 文字列型
x%=5 : 32bit 整数型
@x : 関数プロシージャのコール
x()=[1,2,3,4] : 配列参照
式
値を計算するためには式が必要です。最も単純な式は、
数値または文字列定数です。定数、変数、演算子、関数呼
び出しを使うともっと複雑な式になります。X11-BASIC の式
の表現形式は、他の多くの BASIC と同じです。演算子には
通常の優先順位があり、括弧を使用して演算の順序を変更
することができます。
PRINT (x-1)*10+SIN(x)
X11-BASIC では条件と式が同等に扱われます。X11-BASIC
はブール演算の条件と式を区別する術を持たないため、演
算演算(AND、OR、XOR、NOT)はバイナリ値で操作します。し
たがって、TRUE が-1 であるとすれば、全てのビットにおい
てそうなります。オペレータはそうビット操作をすること
になるでしょう。式が FALSE でない限り状態は TRUE と考え
られます。この場合、FALSE は必然的に 0 以外の数となる。
TRUE はすべてのビットが 1 であることを意味し-1 です。そ
こでオペレータは、これらの各ビットで動作します。この
ような条件式が FALSE でない場合は TRUE とみなされます。
(結果がゼロ以外の値でなければならないことを意味しま
す)
代入文
変数に数値を記憶させることを代入といいます。変数に
新たな数値を代入すると、それ以前に保持していた数値は
消滅して参照できなくなります。
変数に数値を代入するのに数値式を用いると、右辺の値
が計算されて左辺の変数名が示す変数に代入されます。
文字列
文字列変数は、任意の長さのキャラクター(バイト)です。
仮想メモリが許す限りの長さを得ます。文字列は一般に
ASCII テキストで、必要ならば任意の長さのバイトコードも
保持することもできます。X11-BASIC は必要に応じて自動的
に解釈します。もしバイトコードを X11-BASIC が文字列と
判断すれば、長さ等も変わり、メモリ上の位置は変わるこ
とでしょう。文字列変数は「$」と決められています。文字
列定数は「" "」で囲みます。文字列に特殊文字を連結す
ることもできます。通常、文字列をサブストリングに分け
といて、実行するとキャラクタコードの断片を「+」で連
結するという手を使います。
st$="This is a special string, containing a bell character at the
end"+chr$(7)
ちなみに、ダブルクォーテーション文字は chr$(34)で表
現できます。
配列
DIM 命令によって配列を宣言します。
配列はいくつもの型の変数を同時にメモリ上に保持しま
す。通常の変数は一度に一つだけの値を持ってますが、配
列は数個の値を持つことができます。変数にインデックス
と言う添字をつけることでそれぞれの値と対応付けます。
インデックスは「(」と「)」に囲まれた数値です。イン
デックスの数値に制限はありません。配列の次元にも制限
はありません。ただしインデックスと次元は、正の整数値
でかつメモリが許すだけになります。X11-BASIC の配列は、
文字列形式も含む任意のデータ型です。X11-BASIC 基本の特
殊な機能としては、配列の暗黙的な定義と配列定数の存在
です。
Dim b(10)
a()=b()
ここで、b()は事前に DIM 命令で定義されているものとし
ます。
a()=[1,2,3,4;6,7,8,9]
配列定数を割り当てます(この例では、2 次元配列が作成
され、行がセミコロン「;」で分離されています)。
書式指定
Print <expression> Using"<format string>"
Print 文に書式指定を追加するときは、Print 文の後に
Using 書いて" "で囲まれた内部に節を書きます。
Print 数値式 Using "書式指定文字列"[,数値式 using "書式指定文字列"])
です。書式を作成するとき、整数部の桁数が不足しないよ
うに注意してください。特に、負数の場合、負号を出力す
る分の桁の確保を忘れないように。書式を指定すると、小
数部は指定された桁数に合わせて四捨五入されます。
数値の表現
数値表現の書式の詳細は次のようになります。
+ 数値の符号を書きます(任意)。
- 負である場合のみ数値の符号を書きます(任意)。
# 十進数の数値の桁数を指定します。指定された桁数より小さい場合は、
右詰めになります。
0 必要ならば(任意)。
. 小数点の位置を表します。
, 1000区切りで「、」を挿入します。
^ 10の乗数を書きます。
例1
Print Pi Using "-#.###"
3.142
Print Pi Using "+0#.###0"
+03.1420
Print -11^11 Using "##.##^^^^"
-2.85e+11
例2
(X11-BASIC)
For i = 0 To 17
n = 10 ^ i
Print n Using "####################.##############", (1 + 1 / n)
^ n
Next i
End
(Result)
1.00000000000000 2
10.00000000000000 2.5937424601
100.00000000000000 2.704813829422
1000.00000000000000 2.716923932236
10000.00000000000000 2.718145926825
100000.00000000000000 2.718268237192
1000000.00000000000000 2.718280469096
10000000.00000000000000 2.718281694133
100000000.00000000000000 2.718281798339
1000000000.00000000000000 2.718282051996
10000000000.00000000000000 2.718282052691
100000000000.00000000000000 2.71828205298
1000000000000.00000000000000 2.71852349587
10000000000000.00000000000000 2.716110033705
100000000000000.00000000000000 2.716110033666
1000000000000000.00000000000000 3.035035206235
10000000000000000.00000000000000 1
100000000000000000.00000000000000 1
例3
(X11-BASIC)
For x = 3.14159265 To 3.14159266 Step 0.000000001
Print x Using "#.#########", Sin(x) Using "-#.###############"
Next x
End
(Result)
3.141592650 0.000000003589793
3.141592651 0.000000002589793
3.141592652 0.000000001589793
3.141592653 0.000000000589793
3.141592654 -0.000000000410207
3.141592655 -0.000000001410207
3.141592656 -0.000000002410208
3.141592657 -0.000000003410208
3.141592658 -0.000000004410208
3.141592659 -0.000000005410208
例4
(X11-BASIC)
' case-a
a = Sqr(2)
Print " Plain Output"
Print " Print Sqr(2) = "; a
Print a Using "##.#####"
Print a Using "##.####"
Print a Using "##.###"
Print a Using "##.##"
Print
' case-b
b = 0.00001
Print " Plain Output"
Print " Print 0.00001 @ ###.### = "; b
Print b Using "###.###"
Print b Using "+0###.###0"
Print b Using "###.###^^^^"
Print
' case-c
c = 10000.0
Print " Plain Output"
Print " Print 10000.0 @ ###.### = "; c
Print c Using "###.###"
Print c Using "+0###.###0"
Print c Using "###.###^^^^"
Print
' case-a,b,c
Print a, b, c
Print a Using "###.###", b Using "###.###^^^^", c Using
"#.###^^^^"
End
(Result)
Plain Output
Print Sqr(2) = 1.414213562373
1.41421
1.4142
1.414
1.41
Plain Output
Print 0.00001 @ ###.### = 1e-05
0.000
+0
0.0000 <= 小数点の位置を基準にそろえる
1.000e-05
Plain Output
Print 10000.0 @ ###.### = 10000
******* <=桁が足りないので表示できない
********** <=桁が足りないので表示できない
1.000e+04
1.414213562373 1e-05 10000
1.414
1.000e-05 1.000e+04
プロシージャと関数
X11-BASIC は構造化された手続き型プログラミング言語で
す。それぞれが単一のユニットのように動作する複数のセ
クションで、プログラムは構成される、いわばカプセル化
された構造形態を持ちます。ブロックの始めと終わりは、
明示的なキーワードによって区切られます。
伝統的 BASIC の実装とは違い、X11-BASIC で行番号は使用
されません。一行はすべて何かしらの命令を持ちます。
Goto でのジャンプも可能ですが、そこはループと中止コマ
ンド(Exit If や Break)をご利用していただきたい。
任意の型の戻り値を持つプロシージャと関数は再利用可
能です。これによりプログラムをモジュール単位で構造化
できます。プログラムは、プロシージャや関数をコールす
るメインとなる部分を持ちます。その他のライブラリを
マージコマンドで追加することもできます。
1.プロシージャと関数
X11-BASIC には、プロシージャと関数の 2 つサブルーチン
の種類があります。この違いは、プロシージャは値を返さ
ず、関数は単一の値を返す点です。プロシージャや関数は、
メインブロックの後に書かれなければなりません。した
がって一般的な X11-BASIC プログラムの次の構造になりま
す。
Main program block
:
End
Procedures and Functions
:
プロシージャは、プログラムのどこからでも呼び出すこ
とができるブロックです。これらのサブルーチンは引数を
取ることができます。しかしプロシージャ内で処理された
結果を返すことはしません。それらは、プロシージャロー
カルの変数だけでなく、すべての変数に言えます。
関数は他の式から呼び出すことができるブロックです。
例えば、A = 3 * @MyFunction(b)とか指定することができ
ます。関数の中での変数は、Local 宣言しない限り変数は
Global です。同じ名前を持つ、Local 変数の関数外での変
更は、明示的に関数内で指定しない限り関数内の値を保持
しません。関数の引数は、任意のデータ型の変数や配列に
なります。関数は、任意のデータ型の変数を返すことがで
きます。デフォルトでは、引数は値渡し(ByVal)で渡されま
す。
次のは、割と関数を使う典型的な例です。
(X11-BASIC)
'Main
x = 0.0
y = 0.0
z = 0.0
For i = 1 To 100
x = x + 1.0
For j = 1 To 100
y = y + 1.0
z = @Equation(x, y)
Print " x="; x; " y="; y; " z="; z
Next j
y = 0.0
Next i
Quit
End
Function Equation(X, Y)
Equation = (X + Y) / 2.0
Return Equation
End Function
2.プロシージャ
プロシージャは、キーワード Procedure に続く”プロ
シージャ名”で始まり、引数(parameters)はプロシージャ
に渡されます。すべてのプロシージャの終わりは、RETURN
で終了します。プロシージャの形式はだいたい次の形式に
なります。
Procedure ProcName(parameters)
Local vars
:
Procedure logic
:
Return
サブルーチンの変数は、サブルーチン名の後ろの括弧の
間に配置され、メインプログラムでプロシージャを呼び出
した変数の配置と同じ順序でなければなりません。サブ
ルーチン内で使用されるすべての変数は、Local ステートメ
ントを使用して、ローカルに宣言する必要があります。
プロシージャは次の 2 つの方法で呼び出すことができま
す。Gosub または@を使用します。次の例、テキストコン
ソール上の進行状況バーを示す progress()プロシージャで
は、次の方法で呼び出し、総量 a と区分 b の変数が引き渡
されます。
Gosub progress(100,i)
@progress(100,i)
Procedure progress(a,b)
Local t$
If verbose
Print Chr$(13);"[";string$(b/a*32,"-");">";
Print String$((1.03-b/a)*32,"-");"_
(int(b/a*100),3,3);"%
";str$
]";
Flush
Endif
Return
3.関数
関数は、関数名に続く Function ヘッダーで始まり、キー
ワード Endfunction で終了します。関数は、数値や文字列
の関数いずれかです。デフォルトでは数値関数です。文字
列関数は文字列を返し、「関数名$」で定義されます。関数
は、少なくとも 1 つの関数の値を返すための Return 文が必
要です。だいたい次のような形式で使用します。
Function FuncName[$](parameters)
Local vars
:
function logic
:
Return value[$]
Endfunction
戻り値の型は、関数の型と一致する必要があります。文
字列関数は文字列を返しますし、数値関数は数値を返しま
す。数値はデフォルトでは実数として扱われます。Return
文が実行されると関数は呼び出し元に戻ります。E
ndfuncction 文は、関数の終わりを意味し、プログラムがこ
の文だけを実行しようとするとエラーになります。関数は
「@関数名」で呼び出されます。例として、文字列関数の
Copy$()を呼び出す例を示します。
Right$ = @Copy$("X11-Basic", 4)
ここで呼び出される Copy$()という関数が次の様になりま
す。
Function Copy$(a$, p)
Local b$
b$ = Mid$(a$,
p)
Return b$
Endfunction
次の様に書くこともできます。
Function Copy$(a$, p)
Return Mid$(a$, p)
Endfunction
(X11-BASIC)
'Main
A = 1
A = @Test(A)
Print " A = "; A
Quit
End
Function Test(B)
B = 12
' ...
B = 123
Return B
End
(Result)
A = 123
関数 Function の置き換え命令として Deffn 文があります。
これは関数式を一行で記述する命令です。上の例で使用し
た Copy$()関数は、Deffn 文では次の様に表すことができま
す。
Deffn Copy$(a$, p) = Mid$(a$, p)
ローカル変数は使わないものとして、サブプロシージャ
と関数の違いは核心部を Deffn で置き換えれるかどうかの
違いとも言えます。Deffn と Function の違いは、コンパイ
ラは Deffn を一行の表現として扱いシンボル名を要しない
ことです。余計なコードを実行するよりもその方がいくら
か早くなります。
4.パラメータ引数とローカル変数
X11-BASIC の変数ならどんな型でも、プロシージャや関数
に渡すことができます。デフォルトではすべて値わたし
(ByVal=”by value”)で渡されます。Var 命令によって参照
渡し(ByRef=”by reference”で渡すこともできます。
Local 命令は、そのプロシージャまたは関数でだけ通用す
る変数を定義します。サブルーチンのパラメータは、ロー
カル変数です。サブルーチンが別のサブルーチンを呼び出
すとき、呼び出しルーチンのローカル変数は、グローバル
変数のように呼び出されたルーチンでは認識されます。
Local 命令の後に、カンマで区切って複数のローカル変数
を表記することもできますし、べつに Local 行が複数あっ
てもかまいません。
注意した方がいい例を次にあげます。X11-BASIC ではサブ
プロシージャでローカル宣言をしてますが、そこで初期値
を何も入れてないためにメインの値がそのまま入っていま
す。GAMBAS で同じコードを書いて実行した例もつけておき
ます。GAMBAS では、サブプロシージャで定義したローカル
変数は宣言と同時に初期化されてます。こういう「仕様」
と言えばそうなんだーと言える細かい意外性があることに
注意が必要ですね。
(X11-BASIC)
'Main
a = 1
Print " [email protected]: "; a
@Test1()
Print " [email protected]: "; a
Quit
End
Procedure Test1()
Local a
Print " [email protected]: "; a
a = 2
Print " [email protected]: "; a
Return
End
(Result)
[email protected]: 1
[email protected]: 1
[email protected]: 2
[email protected]: 1
(GAMBAS)
' Gambas module file
Public Sub Main()
Dim a As Integer
a = 1
Print " [email protected]: "; a
Test1()
Print " [email protected]: "; a
Stop
End
Sub Test1()
Dim a As Integer
Print " [email protected]: "; a
a = 2
Print " [email protected]: "; a
End
(Result)
[email protected]: 1
[email protected]: 0
[email protected]: 2
[email protected]: 1
End 文と Quit 文、Stop 文
X11-BASIC の End 文は、プログラム全体の終了を意味しま
す。プロシージャの終了は Rturn、関数の終了は End
Function で締めくくります。
Quit 文はすべてのウィンドウを閉じてメモリを開放し、
プログラムを終了させます。
Android のショートカットで X11-BASIC プログラムを起動
した場合や、Linux/Windows でシェル風に X11-BASIC を起動
した場合、プログラムの実行した終わりに Quit 文があると、
ウィンドウを自動で閉じて終了します。
どちらのコードでも、終わりに"Quit"があると、人間が
インタプリタを閉じるアクションが必要がなくなります。
Android 版で注意が必要なのは、Quit は本当にアプリを
終了すことです。そうすると計算されて出てくるはずのア
ウトプットを読むことができなくなります。この点が UNIX
バージョンとは異なります。End を有効に使ってください。
プログラムの一時中断は Stop 文を使います。Stop 文の箇
所で一旦インタプリタのプロンプトがあらわれます。そこ
から Cont と入力することで、その続きを再開することがで
きます。行がスクロールするのを一旦止めたりするのに使
うとよいと思います。
制御構文
読みやすいプログラムとは何でしょう。そういう問いを
ダイクストラ(Edsger Wybe Dijkstra)という人がプログラ
ミング技法『構造化プログラミング』で提唱しています。
ダイクストラは、どんなプログラムの流れも順次、選択、
反復の三つ(3 大制御構造)で構成されているからそれらに制
限すべきだと主張しています。
順次:上から順番に実行する
選択:条件によって分かれる2つ以上を別々に記述してどれかを実行する
反復:ある範囲を条件を満たす間だけ繰り返して実行する
つまり『ジャンプを使うな』といっているわけです。こ
の世にあるほとんどのプログラムがこの単純な制御構造を
駆使して作られています。X11-BASIC にも Goto 文はあるわ
けですが、制御構文はその教えにしたがっています。逆に
言えば、これをマスターすれば大抵のプログラムの構造を
読めるってわけです。
分岐処理
指定した条件に応じて、プログラムのコードブロックの
みを実行させたい場合などは、分岐ステートメントを使用
します。
If...Then...Else
If ステートメントは以下のように使用します。
(X11-BASIC)
Input A
If A > 3 Then
B = 2
Print B
Endif
End
このサンプルコードで B=2 の行が実行されるのは、変数 A
の値が 3 より大きい場合だけです。
(Result)
holy@mint ~ $ xbasic testx.bas
? 1
> quit
holy@mint ~ $ xbasic testx.bas
? 5
2
> run
? 1
>
If ステートメントのバリエーションとして、If/Else 句
があります。
(X11-BASIC)
Input A
If A > 3 Then
B = 2
Else
B = 0
Endif
Print B
End
このサンプルコードで変数 B に代入される値は、変数 A
が 3 より大きい場合は 2 となり、それ以外の場合は 0 となり
ます。
(Result)
holy@mint ~ $ xbasic testx.bas
? 5
2
> run
? 1
0
>
If ステートメントをカスケード化して、以下のようなよ
り複雑な条件分岐を行わせることもできます。
(X11-BASIC)
Input A
If A = 0 Then
B = 0
Else If A < 3 Then
B = 1
Else
B = 2
Endif
Print B
End
このサンプルコードでは、変数 A の値が 0 であれば、変
数 B には 0 が代入されます。変数 A の値が 3 よりも小さけれ
ば(ただし 0 とは等しくない)、変数 B には 1 が代入されます。
これら以外の場合(つまり変数 A の値が 3 以上の場合)、変
数 B には 2 が代入されます。
(Result)
holy@mint ~ $ xbasic testx.bas
? 0
0
> run
? 2
1
> run
? 5
2
>
If 文を二重、三重にすることもできます。そういう時は、
字下げをしてどの条件の処理なのかわかりやすく記述する
のがコツです。字下げをすることは必須ではないんですが、
デバッグが楽になりますのでやっといた方が自分のためで
す。
(X11-BASIC)
Input A
Input B
C = 0
If A = 0 Then
If B = 0 Then
C = 1
Endif
Endif
Print C
End
この例では、変数 A を判定した後に、変数 B を判定する
という二重の関門を設けています。それにより、変数 A=0
かつ変数 B=0 である場合だけ変数 C に 1 が入ります。
(Result)
holy@mint ~ $ xbasic testx.bas
? 0
? 0
1
> run
? 0
? 1
0
>
条件の書き方
不等式 a≦b、a≧b は、それぞれ、a<=b、a>=b のように書
きます。
また、a と b とが等しくないこと(a≠b)は、a<>b と書き
ます。
And、Or、Not と括弧を用いて複雑な条件を記述すること
ができます。
たとえば、「p かつ q」という条件を X11-BASIC では p
And q と書きます。また、「p または q」を p Or q と書き
ます。数学では「a<x かつ x<b」のことを a<x<b と書きま
すが、BASIC ではこういう書き方はできません。
すると、上の二重に関門を設けたプログラムを次のよう
に書くことができます。
(X11-BASIC)
Input A
Input B
C = 0
If A = 0 And B = 0 Then
C = 1
Endif
Print C
End
Select...Case
Select...Case ステートメントは、If ステートメントの
カスケード化と同等の機能を果たすもので、複数の条件に
対する分岐を行う際に使用します。
このサンプルでは、変数 DayOfWeek の値が 1 であれば
Sunday、2 であれば Monday というように、各曜日の名前を
番号で識別させています。
(X11-BASIC)
Input "Number(1-7) ? "; DayOfWeek
Select DayOfWeek
Case 1
NameOfWeekday$ = "Sunday"
Case 2
NameOfWeekday$ = "Monday"
Case 3
NameOfWeekday$ = "Tuesday"
Case 4
NameOfWeekday$ = "Wednesday"
Case 5
NameOfWeekday$ = "Thursday"
Case 6
NameOfWeekday$ = "Friday"
Case 7
NameOfWeekday$ = "Saturday"
Default
NameOfWeekday$ = "Out of Number"
EndSelect
Print NameOfWeekday$
Stop
End
(Result)
holy@mint ~ $ xbasic testx.bas
Number(1-7) ? 1
Sunday
> run
Number(1-7) ? 5
Thursday
> run
Number(1-7) ? 10
Out of Number
>
Select コマンドによる条件判定は、単純な 1 対 1 に限定
されるものではなく、Case による個々の分岐指定部には複
数の条件式をリスト化して一括指定することが可能です。
以下のサンプルコードでは、特に多用される条件判定の例
を示します。
(X11-BASIC)
a = Int(Rnd(1) * 6 + 1)
Select a
Case 1
Print "1: ";a
Continue
Case 2
Print "1 or 2: "; a
Case 3, 4
Print "3 or 4: "; a
Case 5
Print "5: "; a
Default
Print "Default: "; a
EndSelect
Stop
End
(Result)
holy@mint ~ $ xbasic testx.bas
Default: 6
> run
3 or 4: 3
> run
5: 5
> run
5: 5
> run
Default: 6
> run
1 or 2: 2
> run
3 or 4: 3
>
ループ
ループは、特定のコードブロックを指定した回数繰り返
し実行させる場合などに使用します。またループの実行回
数は、不特定値とすることも可能です。
For...Next
For...Next は繰り返しの構文です。For と Next は常に対
にして用いられる命令で、For 文に指定された変数の値を順
に変化させながら For 行と Next 行にはさまれた各行を繰り
返し実行させます。次に示すプログラムは n=1,2,3,...,10
の n^2 について計算します。
(X11-BASIC)
' 例1
For n = 1 To 10
Print n, n ^ 2
Next n
Stop
End
(Result)
holy@mint ~ $ xbasic testx.bas
1 1
2 4
3 9
4 16
5 25
6 36
7 49
8 64
9 81
10 100
>
例 1 では、まず n=1 に対して Print 行が実行され、次に
n=2 に対して Print の行が実行されます。次は n=3 に対し
て...(以下同様のことを順に繰り返して、最後に n=10 を実
行して終了します。ステップ実行を選択して、変数の値の
変化と実行順序を調べてみてください。
もう少し For...Next を詳しく知るため、次のプログラム
を実行してみてください。
(X11-BASIC)
' 例2
Input "n ? "; n
For k = 1 To n
Print k
Next k
Print "Last", k
Stop
End
(Result)
holy@mint ~ $ xbasic testx.bas
n ? 10
1
2
3
4
5
6
7
8
9
10
Last 11
>
このプログラムを実行して n に 10 を入力してみると、
Last 行の Print 文を実行したときには k の値が 11 になって
います。上のプログラムでは、最初 k に 1 が代入され、
Next 文を実行するごとに k の値に 1 が加算され、それが n
より大きくなると Next 文の次に進むという動作をしていま
す。
それでは、n に 0 を入力するとどうなるでしょうか。
X11-BASIC の場合、ループ内の処理が一度は実行されます。
言語仕様にもよりますがが、For 文の条件をすでに満たして
いれば実行されない言語と挙動が変わるので注意が必要で
す。
一度処理したら、次は k の値が n より大きいので
For...Next 内の文を実行せずに Last 行に進みます。この性
質は重要ですの覚えておきましょう。
(Result)
holy@mint ~ $ xbasic testx.bas
n ? 0
1
Last 2
>
For...Next の応用(数列の和と積)
次のプログラムは自然数 n を入力すると n^2 の総和を計
算します。
和を媒介変数 S を用いて求めます。まず、ループに入る
直前に初期値として S に 0 を代入しておき、ループ内で
k=1,2,3,...,n について S に k^2 を加算します。
(X11-BASIC)
' 例3
Input "n ? "; n
S = 0
For k = 1 To n
S = S + k ^ 2
Next k
Print S
End
(Result)
n ? 5
55
同様の手法で数列の積を計算できます。順列の数
nPr(=n(n–1)(n–2)... (n–r+1))は次のように計算できます。
(X11-BASIC)
' 例4
Input " nPr: n ? "; n
Input " nPr: r ? "; r
p = 1
For k = (n - r + 1) To n
p = p * k
Next k
Print p
Stop
End
(Result)
holy@mint ~ $ xbasic testx.bas
nPr: n ? 5
nPr: r ? 3
60
>
For...Next の応用(漸化式で定義された数列)
変数の値を順に更新していく手法を用いると、漸化式で
定義された数列の計算ができます。
次のプログラムは、a(1)=5、a(n+1)=3*a(n)+2 で定義され
る数列{a(n)}の第 n 項を計算します。
(X11-BASIC)
' 例5
Input "n ? "; n
a = 5
For k = 2 To n
a = 3 * a + 2
Next k
Print a
Stop
End
(Result)
holy@mint ~ $ xbasic testx.bas
n ? 3
53
> run
n ? 2
17
> run
n ? 1
17
>
n=1 の場合の結果は a=5 になって欲しいんですが、n=2 の
場合と同じになってます。これは条件を満たしていても
For...Next 内の文を 1 回は実行するためです。ですので、
そこに注意して例 5 を書きなおすと、
(X11-BASIC)
' 例 5'
Input "n ? "; n
a = 5
If n > 1 Then
For k = 2 To n
a = 3 * a + 2
Next k
Endif
Print a
Stop
End
(Result)
holy@mint ~ $ xbasic testx.bas
n ? 3
53
> run
n ? 2
17
> run
n ? 1
5
>
のように、If 文で n=1 の場合は、For...Next を実行しない
ように回避する必要があります。
Step 文
For...Next 構文で繰り返しのたびごとに制御変数に加算
される数値を 1 以外の数値にすることができます。次のプ
ログラムでは、x の値を 0 から 1 まで 0.1 ずつ加算しながら
x2 を計算して出力します。
(X11-BASIC)
' 例6
For x = 0 To 1 Step 0.1
Print x, x ^ 2
Next x
Stop
End
(Result)
holy@mint ~ $ xbasic testx.bas
0 0
0.1 0.01
0.2 0.04
0.3 0.09
0.4 0.16
0.5 0.25
0.6 0.36
0.7 0.49
0.8 0.64
0.9 0.81
1 1
>
また、数値を大きい値から小さい値へ変化させる目的で
この構文を用いることができます。
(X11-BASIC)
' 例7
For k = 10 To 1 Step -1
Print k
Next k
Stop
End
(Result)
holy@mint ~ $ xbasic testx.bas
10
9
8
7
6
5
4
3
2
1
>
While...Wend
While の後に書かれた式の条件が成立する間、繰り返しを
実行する構文です。
(X11-BASIC)
a = 1
While a <= 10
Print " No."; a
a = a + 1
Wend
End
(Result)
holy@mint ~ $ xbasic testx.bas
No.1
No.2
No.3
No.4
No.5
No.6
No.7
No.8
No.9
No.10
>
ループからの脱出
エスケープシーケンスというんでしょうが、それよりも
脱出(ジェイルブレーク)と言ったほうがかっこいいので、
まあ「脱出」としておきました。まあ、ちょっと言ってみ
たかっただけです。どうでもいんですが。
Break
Break 文の実行によって、すぐに現在回ってるループから
外に抜け出します。
(X11-BASIC)
For X = 1 To 10
If X = 5 Then
Break
Endif
Print X
Next X
Print " - Break Loop@"; X
End
(Result)
holy@mint ~ $ xbasic testx.bas
1
2
3
4
- Break Loop@5
>
Exit If [式]
[式]が真(TRUE)の場合、ループから外に抜け出します。
(X11-BASIC)
For X = 1 To 10
Exit If X = 5
Print X
Next X
Print " - End@ "; X
End
(Result)
1
2
3
4
- End@ 5
>
他の言語では、ループの途中からループの先頭へ戻る命
令に Continue という名前の命令を用意してるのもあります。
けれど X11-BASIC には、そういう用法の Continue はありま
せん。
X11-BASIC にある Continue は、Stop で一時中断したプロ
グラムを再開する場合と、Select...Case...EndSelect の選
択肢中で使う場合の 2 通りについてです。
(X11-BASIC で数値計算をさせていて、ある条件になったら
ループから抜け出す BREAK を仕掛けたんですけど、どうし
ても BREAK されず、代わりに Exit If で回避したことがあ
りました。かなりこなれた X11-BASIC でもそういうことが
あるので言語処理系を信用しすぎないことも必要だと思い
ます)
他のループ命令
X11-BASIC には他にもループ命令が用意されています。も
ともと BASIC には、こんなに似たような命令いらないだろ
というのが多いです。おそらくそれは、他の言語を使って
きた人への配慮なんだと思うんです。使い慣れた言葉がな
いとイラッとしますよね。そういうストレスを感じさせな
いための。
Do...Loop
繰り返しを実行する構文です。エスケープする条件を途
中に儲けないと無限ループするので注意が必要です。
(X11-BASIC)
Do
Input a$
Exit If a$=""
Loop
End
(Result)
holy@mint ~ $ xbasic testx.bas
? r
? e
?
>
Repeat...Until
Until の後に書かれた式の条件が成立する間、繰り返しを
実行する構文です。For や While がループの頭で判定してる
のに対して、ループの末尾で判定してるのが特徴です。
(X11-BASIC)
a = 1
Repeat
Print " No."; a
a = a + 1
Until a > 10
End
(Result)
holy@mint ~ $ xbasic testx.bas
No.1
No.2
No.3
No.4
No.5
No.6
No.7
No.8
No.9
No.10
>
文字列
制御構文や数値処理のあとに残った計算機でやることと
言ったら九割方は文字列操作と言えます。
そもそも現代的な計算機の出自からして戦争中敵軍の暗
号を解読する作戦から始まったことですし、数字も含めて
記号一般を取り扱う機械だと考えてよいでしょう。
社会において人とのコミュニケーション以外の仕事と
いったら、結局は記号の操作(移し替え)に終始していると
思いませんか?
そういう訳で、まずは文字列変数について説明します。
一般にプログラミング文法の説明するとき、文字列は
「String」と呼びます。X11-BASIC は動的型付けでして、変
数を扱うのにプログラムの先頭で変数の宣言をしなくても
思いのままに作って代入できます。しかも特にローカルだ
と宣言しない限り、全てグローバル変数となります。それ
が気持ちいいか悪いかは、作成してるプログラムの性質や
目的によると思います。X11-BASIC ではそうなってるという
ことです。
そして、X11-BASIC で文字列変数は、「変数名$」と表現
されます。これが文字列の配列とすると「変数名$()」と
なります。
文字列変数への代入は、
A$ = "はじめまして"
のようにします。ダブルクォーツで囲んでるのをわかって
ください。
Print A$
とすれば
はじめまして
と表示されます。
次に変数の変換について説明します。
命令:Val
書式:Expression = Val ( String )
String の内容にしたがって文字列を、数値に変換します。
日付や時間、小数点、論理値などで試してみましょう。
(X11-BASIC)
Print Val("09/06/72 01:00")
Print Val("3.1415")
Print Val("-25")
Print Val("True")
Print Val("False")
End
(Result)
9
3.1415
-25
0
0
文字列から数値に変換できない場合は「0」を返します。
最初の「日付 時間」は最初の区分「09」だけ数値に変換
されたようです。True/False みたいな文字列を論理値に変
えることはできないようですね。
今度は逆に数値を文字列に変換してみます。そうしたい
時は、Str$(Number)を使います。
(X11-BASIC)
A = 3.0E-3
B$ = Str(A)
Print A
Print B$
End
(Result)
holy@holy-901:~$ xbasic testx.bas
0.003
0.003
>
文字列連結
X11-BASIC での文字列連結演算子は「+」です。
Microsoft BASIC では"2"+"3"で"23"になりますが、Full
BASIC では同じことを"2"&"3"と書きます。GAMBAS で
は"2"&"3"です。X11-BASIC の場合は"2"+"3"という話です。
(X11-BASIC)
A$ = "おはよう"
B$ = "こんにちは"
C$ = A$ + "、" + B$
Print C$
(Result)
おはよう、こんにちは
Print 文による文の出力は、";"で続けることができます。
これは改行しないで続けて、という意味になります。また、
","でつなげると間にタブが挿入されます。
(X11-BASIC)
A$ = "おはよう"
B$ = "こんにちは"
Print A$; "、"; B$
Print A$, "、", B$
C$ = A$; "、"; B$
Print C$
(Result)
holy@holy-901:~$ xbasic testx.bas
おはよう、こんにちは
おはよう 、 こんにちは
>
となります。C$の内容が出力されないのは、文字列どうし
の接続を"+"ではなく、";"にしてしまってるからです。
ここは、
C$ = A$ + "、" + B$
とするのが正解です。
文字列の分割
命令:Split
書式:Split t$, d$, mode, a$, b$
説明:t$という文字列を d$で分けて、a$という部分と b$と
いう部分にします。つまり、t$=a$+d$+b$という関係になり
ます。
mode は、
0:デフォルト
1:do not search in parts of t$ which are in
brackets. Quoted parts of the string are not split
up.
例
> Split "Hello, this is a string.", " ", 0, a$, b$
> print a$
Hello,
> print b$
this is a string.
関数:Word$()
書式:a$ = Word$(b$, n[, delimiter$])
説明:文字列 b$の n 番目の文字を返します。文字をスペー
ス、または delimiter$で与えられる文字で分割します。
例
> a$ = Word$("Hello, this is a string.", 3)
> Print a$
this
> b$ = Word$("Hello, this is a string.", 2, ",")
> Print b$
this is a string.
関数:Trim$
書式:b$ = Trim$(a$)
b$ = Xtrim$(a$)
説明:a$で与えられる文字列を整形して返します。X のつい
てる方は、大文字になります。
1.タブをスペースにします。
2.二重スペースを一つのスペースにします。
3.文字列の後ろに続いてるスペースを取り除きます。
4.ダブルクォーツで囲まれた部分は変えません。
例
> Print Trim$(" a b c
a b c d
d")
部分文字列の取り出し
文字列から任意の部分を取り出すには、Right$, Left$,
Mid$などの関数を使います。
Left$は、任意の長さを指定されれば与えられた文字列の
左側から数えた文字までを返します。Right$は、任意の長
さを指定されれば与えられた文字列の右側から数えた文字
までを返します。
ここでは、Mid$の例を下記に示します。
関数:Mid$
書式:m$ = Mid$(t$, s[, l])
説明:t$で与えられた文字列から、整数 s から開始して、
長さ(整数)l までの文字列を m$に返します。もし l が与え
られなければ、開始位置の文字を返します。また l に負の
整数を与えるとエラーにはなりませんが何も返されません。
例
> Print Mid$("X11-BASIC", 3, 2)
1> Print Mid$("X11-BASIC", 4)
> Print Mid$("X11-BASIC", 2, -1)
>
また、文字列の右側や左側をピックアップしたいのなら、
t$ = Right$(a$ [, n]) 文字列 a$の右側(終わり)から n 文字ぶんの文字列を
t$に返します。
t$ = Left$(a$ [, n]) 文字列 a$の左側(頭)から n 文字ぶんの文字列を t$に
返します。
を使う手もあります。
Len は、文字列の長さを数えるときに使う関数です。
Left$, Right$, Mid$では、どこからどこまでと指定する
ときに文字列の長さを指定します。これを指定したりする
ときに便利なので覚えとくといいと思います。
関数:Len
書式:l = Len(t$)
説明:引数として与えられた文字列の数を返します。これ
は ASCII 文字で何文字ぶんになるかを返します。
X11-BASIC には Python や Ruby みたいに文字エンコードの
宣言はありません。公式では ANSI 標準の ASCII コードに対
応とだけ言ってます。アルファベット+α 以外の文字につ
いては、X11-BASIC を動かしてる環境しだいのように、利用
者に任せてるって感じです。
Tips というか、運用上のノウハウなんですが例えば
Linux で UTF-8 コードによる日本語を使ってるならば、
(X11-BASIC)
A$ = "うーん、この"
Length = Len(A$)
Print A$; ":"; Length
Quit
End
Result
うーん、この:18
それぞれの文字は、UTF-8 の文字コードでは
「う」の UTF-8 コード : E3 81 86
「ん」の UTF-8 コード : E3 82 93
「こ」の UTF-8 コード : E3 81 93
「の」の UTF-8 コード : E3 81 AE
に対応してまして、ひらがな・カタカナ・漢字は 2 バイト、
ASCII コードにすると 3 文字ぶんに相当するので、Len()で
得られる文字数は 3x6 文字=18 とカウントされてるわけです。
Windows で SHIFT-JIS コードでソースを書いて、コマンド
プロンプトで実行させるなら ASCII コードにすると 2 文字
ぶんとなります。
部分文字列の置換
関数:Replace$
書式:t$ = Replace$(a$, s$, r$)
説明:Replace 関数は、文字列 a$の中にあるパターン s$に
相当する文字列を r$に置き換えます。a$が空なら、空の文
字列が返されます。また s$が空なら文字列 a$がそのまま返
されます。
(例)
> Print Replace$("x11-basic is a cool basic", "bas","BAS")
x11-BASic is a cool BASic
> Print Replace$("x11-basic is a cool basic", "a", "")
x11-bsic is
cool bsic
> Print Replace$("x11-basic is a cool basic", " ", "--")
x11-basic--is--a--cool--basic
他にめぼしいのは
t$ = Reverse$(a$) 文字列 a$の並び順を逆転します
t$ = Space$(i) i 個の連続したスペースを返します。
のような文字列関数があります。
(例)
> Print Reverse$("abcdef")
fedcba
> Print "abc" + space$(2) + "def"
abc
def
文字列の検索
X11-BASIC には、文字列内の部分文字列の検索用に、
Instr 関数が用意されています。
a=Instr(s1$, s2$ [,n]) s2$のあたまから何文字目に s1$があるか調べる
a=Rinstr(s1$, s2$ [,n]) s2$の後ろから数えて何文字目に s1$があるか調べ
る
この関数は、文字列変数 s2$内に文字列 s1$と一致する部
分があるかを調べます。関数の戻り値としては、文字列内
で最初に現れる位置を整数で返します。該当する文字列が
ない場合は「0」が返されます。
また、該当する部分文字列が何カ所もあるような場合は、
何文字目から検索を始めるかをオプション指定できます。
このオプションは、整数 n で与えます。
(例)
> Print Instr("x11-basic is basic", "bas")
5
> Print Instr("x11-basic is basic", "bas", 6)
14
> Print Instr("x11-basic is basic", "not")
0
他に、あるパタンに文字列が合致してるか調べる関数と
しては、Glob()があります。
f = Glog(a$, b$ [,flags])
は、文字列 a$がパタン b$に合致してれば True を返します。
関数:Glob()
書式:<bool> = Glob(name$, pattern$ [, flags])
説明:Glob()は name$がワイルドカードを含むようなパタン
pattern$に合致するか調べて合致していれば-1(True)、し
ていなければ 0(False)を返します。チェックする種類はパ
ラメータ flags に依ります。
flags
0 : デフォルト
1 : name$のファイル関係の記号('/')は対象にしない
2 : バックスラッシュを特殊文字とする
4 : '.'を特別扱いにする
8 : name$のファイルパスをチェックする
16 : 比較的ゆるい
(例)
Glob("abcd", "abc?")
Result: -1
Glob("abcd", "*")
Result: -1
Glob("abc", "ab??")
Result: 0
Glob("*a[0-9]*", "sad33333")
Result: 0
X11-BASIC にはもっと文字列操作のコマンドや関数が取り
揃えられているんですが、とりあえずこのくらいにしてお
きます。
ファイル入出力
普通「ファイルを開く」というと、引き出しから所望の
ファイルを取り出してパラパラ頁をめくる動作を想像しま
す。イメージとしてはそんな感じです。
ワープロや表計算ソフトから、すでに作成済みのデータ
を読むとき、メニューバーにある[ファイル]-[開く]のよう
に操作すると思います。これと同じ文脈です。
早い話が、普段からパソコンで「ファイルを開く」、
「フォルダを開く」、「デスクトップに置く」とか言って
るのは、文房具のメタファーなんです。計算機という道具
が20世紀になってできた新しい道具のため、この計算機
であれやこれや操作するときに、操作の対象を示す名詞や、
その動作を表現する動詞もなかったんですね。それですで
にある日常語をメタファーとして使おうと。そんないきさ
つで今でも使い続けられてるわけです。
マイクロソフト系 BASIC でのファイル操作には、
Input,Output,Append の 3 つのアクセスモードがありました。
X11-BASIC もだいたい同じです。
ファイルのオープン
命令:Open
書式:Open <mode>, #<device-number>, <filename> [,
<port-value>]
説明:Open は読み込みまたは書き込みのためのコマンドで
す。<device-number>には番号が入ります。読み込みまたは
書き込みしたい番号です。デバイス番号は X11-BASIC を使
う機器によって 0 から 99 の番号です。ファイルを閉じたい
ときは、そのデバイスの番号を明示して閉じます。
<mode>は開こうとしてるファイルをどんな風に開くかを
指示する文字です。その文字は"O","I","U","A"のどれかで
す。それらの記号の意味するところは、
"I" ~ Input
"O" ~Output
"A" ~ Append
"U" ~ Unspecified
です。
読み込みたいファイルがあれば Open 命令の Input で読み
込みモードにします。ファイルに書き出したいなら Output
モードで出力します。もし保存したいファイルがすでに存
在するとしたら、新しいデータが上書きされて、元のデー
タを失うってしまいます。元のデータに付け加える形で、
新しいデータを書き込みたいのなら、Append モードを使っ
てください。ランダムアクセスファイルとして使いたい場
合は"U"を指定して開きます。そうすれば任意の位置での読
み書きができます。例えば、ファイルの途中に新しいデー
タを入れ込むとかです。Input でファイルを読み込むとき、
存在しないファイルを開くことはできません。そういう場
合が考えられるなら、Exist()関数を用いて事前にファイル
の存在を確認しといてください。
第二文字はファイルの形式を指示します。
"" デフォルト
"U" データグラムソケット接続を開きます
"C" 接続状態のクライアント側ソケットのストリームを開きます
"S" サーバ側ソケットのストリームを開きます
"A" ソケットの接続を許可します(アクセス許可)
"X" 特殊デバイスを設定します
(例:"UX:baud,parity,bits,stopbits,AEow")
<port-nr>は、Open "UC"と OPEN "UU"で繋げるときだけ使い
ます。これは FTP、WWW、TELNET、MAIL などの TCP/IP の
ポート番号になります。
(X11-BASIC)
' 入力ファイル data.dat を開く
' opens file "data.dat" for input
Open "I", #1, "data.dat"
' localhost のポート 80 を読み込み可/書き込み可にして開く
' opens port 80 of localhost for read and write
Open "UC", #1, "localhost", 80
' COM2 ポートを入出力で開く
Open "UX:9600,N,8,1,XON,CTS,DTR", #1, "/dev/ttyS1"
ファイルの Close
Open により開いたファイルを閉じるのが Close です。書
式はシンプルで、以下の通りです。
Close #<device-number>
Open 命令で開いた#device-number とペアになります。
書式は簡単ですが、ファイルのクローズは重要な操作で
す。ファイルのクローズは、本を閉じる動作に例えて説明
されますが、重要な操作です。
閉じることでファイルへの読み書きができなくなります
ので、うっかりファイルに誤った書き込みをしてしまうと
いうことを防止できます。プログラムミスでファイルを
Close し忘れて、おかしなデータを書き込んでしまう、なん
てことが起こったらたいへんです。
よくあるのは、プログラムミスでファイルをクローズし
ないでプログラムを終了したり、プログラムが異常終了し
て、ファイルをクローズしないまま、プログラムが終了し
てしまうケースです。
この場合、ファイルはオープンのままなので、もう一度
同じプログラムを再起動して、そのファイルをオープンし
ようとしても、”そのファイルは既に開かれています。”
のようなエラーが出てしまいます。開いたファイルは必ず
クローズするように気をつけましょう。
シーケンシャルファイルの読み書き
ファイルへのテキスト書き込み
テキストファイルを書き出すための手続きは、
・ファイルを開く
・ファイルを書く
・ファイルを閉じる
という流れで行われます。
ファイルを行ごとに分かれたテキストファイルとするな
ら、ファイルのそれぞれの行を Print 命令で書き込みます。
Print #<device-number>, Line
ここで、Line はテキスト文字列でも数値でもいいです。
この命令をループの中に入れておくと順次ファイルに書
き込んでいきます。ループで回すからには、事前に書き込
みたい一連のデータが何行なのか、配列数がいくらか知っ
ておく必要があります。
(X11-BASIC)
Dim Text$(6)
Text$(0) = "a"
Text$(1) = "a"
Text$(2) = "a"
Open o, #1, filname$
For i = 0 To 2
Print #1, Text$(i)
Next i
Close #1
End
(Result)
holy@holy-901:~$ xbasic testx.bas
> quit
holy@holy-901:~$ cat output.txt
a
b
c
テキストファイルの読み込み
すでに存在するテキストファイルを読み込む場合も、書
き込みと同様な手順を踏みます。すなわち、
・ファイルを開く
・ファイルを読む
・ファイルを閉じる
という感じでです。
ファイルがテキストファイルならば、一行ごとにファイ
ルを読み込むことができます。文字列変数にテキストデー
タを読み込みます。特に指定されなければ、標準入力が使
われます。ただし Eol(文末)デリミタ(Eol: End of line)は
含みません。
t$ = Input$(#n, num) : ファイル(チャンネル)n から num バイト読みます
t$ = LineInput$(#n) : ファイル(チャンネル)n から 1 行読みます
行を読み込む操作は、ループの中に LineInput$をおくこ
とで繰り返し読むことができます。もしそのファイルの行
数を知らず、何回ループさせればいいのかわからないなら、
Eof()関数を用いてファイルの終端を検出することができま
す。だいたい、While (Eof(#n) = 0) 〜 Wend のループで
ファイルにアクセスするのが定石でしょう。
b = Eof(#n) : ファイルの終わりに達したら TRUE を返します
l = Lof(#n) : ファイルの長さを返します。テキストファイルなら、行の数
ではなく全文字数を返します。
例 1 はファイルの終わり Eof(End Of File)まで 1 行ずつ
読み込むプログラム。例 2 は Lof の数を返すプログラムで
す。Lof だから"Lines Of File"の略かと思ったらそうでは
ないみたいです。
例1
(X11-BASIC)
filname$ = "X11BASreference.txt"
If Exist(filname$) = True Then
Open "i", #1, filname$
i = 0
While (Eof(#1) = 0)
LineInput #1, T$
Print Word$(T$, 1, ",")
i = i + 1
Wend
Close #1
Endif
Print "Total:"; i, "LastLine:"; T$
End
(Result)
:
:
m=MAX(f()) not implemented yet
m=MIN(a
m=MIN(array()) not implemented yet
m=MIN(function()) not implemented yet
Total:571 LastLine:m=MIN(function()) not implemented yet
> quit
holy@holy-901:~$ wc -l X11BASreference.txt
571 X11BASreference.txt
例2
(X11-BASIC)
filname$ = "X11BASreference.txt"
If Exist(filname$) = True Then
Open "i", #1, filname$
Lmax = Lof(#1)
Print Lmax
For i = 0 To 10
Input #1, Text$
Print i; ":"; Text$
Next i
Close #1
Endif
Print i
End
(Result)
holy@holy-901:~$ xbasic testx.bas
26851
0:6 Quick Reference
1:
2:6.1. 予約された変数名
3: すでに予約済みの変数があります。これらは普通の変数として使えない
キーワードです。うっかりこの名前を使うことで、エラーになることがあり
ます。そういうときは、LET 命令を使ってみてください。ふつう変数名の終
わりはコマンド名とは違うものです。
4:
5:int ANDROID? Android OS なら-1。それ以外なら 0。
6:int COLS テキストターミナルの行数
7:int CRSCOL 現在テキストカーソルがある行の位置
8:int CRSLIN 現在テキストカーソルがある列の位置
9:flt CTIMER CPU システム時計(秒)
10:int FALSE 最後に発生したエラー番号
11
>
例 3 は指定したファイル名に順番に計算結果を出力して、
いったん閉じます。その後で、作られたファイルを開いて
一行ずつ読み込んで、配列に分けます。最後にもう一度、
配列内容を表示します。こんな感じでシーケンシャルファ
イル入出力の一連の流れの雛形にしてみました。
例3
(X11-BASIC)
' fileiox.bas
' File Output/Input => Print
filname$ = "output.dat"
Open "o", #1, filname$
For i = 0 To 99
Print #1, i; ","; sin(Pi * i / 30)
Next i
Close #1
If (Exist("output.dat") < 0) Then
i = 0
Open "i", #1, filname$
While (Eof(#1) = 0)
LineInput #1, oneLine$
i = i + 1
Wend
Close #1
Lmax = i
Print "Line(max)="; Lmax
Dim time(Lmax), wave(Lmax)
Open "i", #1, filname$
For j = 0 To (Lmax - 1)
LineInput #1, oneLine$
time(j) = Val(Word$(oneLine$, 1, ","))
wave(j) = Val(Word$(oneLine$, 2, ","))
Next j
Close #1
Endif
Print "time","wave"
For j = 0 To (Lmax - 1)
Print time(j), wave(j) Using "###.###^^^^"
Next j
Quit
End
(Result)
holy@holy-901:~$ xbasic fileiox.bas
Line(max)=100
time wave
0
0.000e+00
1
1.045e-01
2
2.079e-01
3
3.090e-01
: :
: :
98 -7.431e-01
99 -8.090e-01
あと、ファイル関係でその他によく使いそうな命令を説
明しておきます。
Exist
関数:Exist()
書式:<boolean-result> = Exist(<filename$>)
説明ファイルシステムに存在するなら、真(TRUE)-1 を返し
ます。
FileSelect
命令:FileSelect
書式:FileSelect <title$>, <path$>, <default$>,
<string-variable>
説明:ファイル選択のダイアログを表示します。
<title$> ダイアログボックスの名前
<path$> ファイルのリストを表示させるパス(絶対パスでも相対パスでも
可)
<default$> 選択箇所にデフォルトで表示させるファイル名(ただし""ならデ
フォルトなし)
<string-variable> 選択したファイル名を代入する変数
もし CANCEL したしたなら、変数には空白が代入されます。
(X11-BASIC)
FileSelect "LOAD File", "/home/holy/*.dat", "input.dat", file$
Print file$
End
(Result)
このダイアログボックスは見た目のクラッシックさとは
裏腹によくこなれてます。スクロールバーはもちろん、上
位ディレクトリへ移動するボタンや現在いるディレクトリ
の情報、ホームへ戻るボタンなど知恵が込められています。
FileEvent$
関数:FileEvent$
書式:t$ = FileEvent$
説明:ファイルやディレクトリを監視してエベントが発生
したらその情報を文字列に返します。
文字列が空白なら特にイベントがない状態です。
イベントは 3 文字とブランクで表されます。
1st: "d" ならディレクトリであることを意味します。
2nd: "X" 初期化, "O" オープン, "C" クローズ, "M" 移動, "D" 削除
3rd: "r" 読み込み, "w" 書き出し, "a" アトリビュートの変更
(X11-BASIC)
Watch "/home/holy/testx.bas"
Do
a$ = Fileevent$
If Len(a$)
Print a$
Endif
Loop
End
(Result)
holy@mint ~ $ xbasic testx.bas
Watch descriptor for /home/holy/testx.bas is: 1.
---O--r
-c-
-O-
--r
-c-
-O-
--r
-c-
-O-
--r
-c-
-O--r
-c-
---O-
--r
-c-O--r
-c-O-O--r
-c-
--r
-c-O-
--r
-c-
ファイル関係の補足
Windows 版の X11-BASIC ではうまくいかない件があります。
現象は、ファイルを先頭から末尾まで一行ずつ読むはずが、
途中で読み終えてしまうという症状です。
テキストファイルを一行ずつ読む流れは、ファイル
Open、LineInput をループさせて Eof()でファイルの末行を
検出して、最後に Close というのが一種のテンプレートで
す。公式マニュアルでも、下のリストのように「While Not
Eof(#)」のサンプルが提示されています。
しかしこれが Windows で実行するとうまくいかないよう
です。実行したのは文字コードを SHIFT-JIS にして DOS プ
ロンプトで英文テキストを読ませようとした場合です。こ
れが文字コードを UTF-8 にして Cygwin で実行したらうまく
いってたかは不明。
これは、For〜Next でループさせて、途中に Exit If
(Eof(#) =0)を入れて途中でループを抜けるようにしたらう
まくいきました。
(X11-BASIC)
' eofilex.bas
' ファイルの行数を数えるそれぞれの方法
sFile$ = "input.dat"
Print "<< ex.1 >>"
iCount = 0
Open "i", #1, sFile$
While Not Eof(#1)
LineInput #1, sLine$
Print iCount, sLine$, Eof(#1)
iCount = iCount + 1
Wend
Close #1
Print "<< ex.2 >>"
Open "i", #2, sFile$
For k = 0 To 1000
Exit If (Eof(#2) < 0)
Lineinput #2, sLine$
Print k, sLine$, Eof(#2)
Next k
Close #2
Quit
End
イベント処理
X11-BASIC におけるイベント関係コマンドです。とりあえ
ず、公式マニュアルを検索して見つけた範囲で列挙します。
いろいろ取り揃えられております。
<string-result> = Inkey$ : 押されたキーの ASCII キャラクタ文字を返しま
す
Event : KeyEvent や MouseEvent や MotionEvent が起こるまで待機します
a = EVENT?(mask%) : 待機中のイベントと mask 値のタイプが一致するのなら
真を返します
MouseEvent x,[y, k, xroot, yroot, s] : マウスボタンを押すまで待機し
ます
MotionEvent x, y, xroot, yroot, s : マウスが動くまで待機します
<int-result:x> = MouseX : マウス座標 x
<int-result:y> = MouseY : マウス座標 y
<int-result:k> = MouseK : マウスボタンの状態(k)
<int-result:s> = Mouse : Shift キーや Control キーの状態(s)
KeyEvent kc, ks[, t$, k, x, y, xroot, yroot] : キーを押すまで待機し
ます
これらの代表的なものを実例を交えて説明していきます。
テキストスクリーンでのキーイベント
旧制 BASIC を好んで使う人たちに、Inkey 命令に相当する
コマンドある/なしで、その BASIC の評価がかなり変わる
と思います。テキストキャラクタを使った、いわゆるアク
ション系「ピコピコゲーム」を作るのに便利だからです。
X11-BASIC はもともと ATARI GFA-BASIC の互換を目指して始
まったそうで、そのへんをさすがに分かってますね。この
命令と Locate 文を使えばテキストだけでいろいろとゲーム
を作れます。
さて、X11-BASIC 公式マニュアルによると、
変数:Inkey$
書式:<string-result> = Inkey$
説明:キーボードで押されたキーの ASCII キャラクタを文
字列として返します。
(例)
Repeat ! Wait until a
Until Len(Inkey$) ! Key was pressed
ということです。
Inkey$のキーイベントを使ったサンプルプログラムを次
に示します。テキスト表示のシンプルなゲーム「ぴこげー
スカッシュ 」です。
(X11-BASIC)
' scashx.bas
' 河西朝雄、QuickBASIC 初級プログラミング入門(下)、H2.05.30、技術評論
社
' p.30
Cls
' 壁作成
Print
FOR k = 1 TO 58
Print "O";
Next k
Print
For k = 1 To 17
Print "O"; Space$(56); "O"
Next k
For k = 1 To 58
Print "O";
Next k
Print
Score = 0 ! 得点
y1 = 7
! ラケットの初期位置
dx = 1
! 反射因子
dy = 1
Locate 0, 10
Print "SCORE="; Score
Locate y1, 53
Print "["
For n = 5 To 1 Step -1
Locate 0, 40
Print "BALL="; n
x = 15
y = INT(2 + 10 * RND(1)) ! ボールの初期位置
While (x < 53)
Locate y, x
Print "o"
'
キー入力
K$ = INKEY$
If K$ = "z" Then
@Up()
Else If K$ = "x" Then
@Down()
Endif
'
ラケットとのあたり判定
If x = 52 And (y1 - 3) < y And y < (y1 + 3) Then
@Hit()
Endif
'
縦壁での反射
If x = 1 Then
dx = -dx
Endif
'
横壁での反射
If y = 2 or y = 18 Then
dy = -dy
Endif
'
前のボールを消す
Delay 0.2
Locate y, x
Print " "
'
ボールを進める
x = x + dx
y = y + dy
Wend
Next n
End
' ラケットを上に
Procedure Up()
Locate y1, 53
Print " "
If y1 > 2 Then
y1 = y1 - 1
Endif
Locate y1, 53
Print "["
Return
' ラケットを下に
Procedure Down()
Locate y1, 53
Print " "
If y1 < 18 Then
y1 = y1 + 1
Endif
Locate y1, 53
Print "["
Return
' ラケットに当たった時
Procedure Hit()
dx = -dx
Score = Score + 1
Locate 0, 10
Print "SCORE="; Score
Return
グラフィクス画面でのイベント
ここからのイベント処理は、グラフィクス画面にフォー
カスがあるときのイベントになります。つまり Openw 命令
なんかを使ってグラフィクスウィンドウを開く必要があり
ます。Linux 版ではグラフィック命令を使えば勝手に開くよ
うですし、Android でも勝手に切り替わるようです。
イベント処理に関係ありそうな項目を、とりあえず全部
まとめてみましたという命令がこちらです。
命令:Event
書式:Event typ,[x, y, xroot, yroot, s, k, ks, t$]
説明:KeyEvent や MouseEvent や MotionEvent が起こるまで
待機します。
次のような値が typ に決められています。
typ = 6 : MotionEvent
typ = 14 : MouseEvent
typ = 2 : KeyEvent
x, y : ウィンドウに対するマウスポインタの位置
xroot, yroot : 画面に対するマウスポインタの位置
s : Alt, Caps, Shift キーの状態
t$ : 押されたキーのキャラクタ
命令:Event?()
書式:a = Event?(mask%)
説明:グラフィクスで待機中のイベントと mask 値のタイプ
が一致するのなら、真(True)を返します。
mask = 1 : キープレス(押す)イベント
mask = 2 : キーリリース(離す)イベント
mask = 4 : マウスボタンプレスイベント
mask = 8 : マウスボタンリリースイベント
mask = 64 : マウス動作イベント
マウスイベント
PC の場合はマウス。Android の場合はタッチパネルにな
ります。ただし、マルチタッチとかには対応してません。
命令:MouseEvent
書式:MouseEvent x,[y, k, xroot, yroot, s]
説明:マウスボタンを押すことで、待機中のイベントを実
行します。
(x,y) ウィンドウに対するマウスポインタの座標
xroot,yroot 画面に対するマウスポインタの座標
それとマウスボタンの状態と Alt/Shift/Caps キーの状態で
す。
変数:MouseX, MouseY, MouseK, MouseS
書式:<int-result:x> = MouseX
<int-result:y> = MouseY
<int-result:k> = MouseK
<int-result:s> = MouseS
説明:次の値が入ってます。
マウス座標(x,y)
マウスボタンの状態(k)
k=0 ボタンが押されてない
k=1 左ボタン
k=2 中央ボタン
k=4 右ボタン(またはそれを類する状態)
Shift キーや Control キーの状態(s)
s=0 特に押されてない
s=1 Shift
s=2 CapsLock
s=4 Control
s=8 Alt
s=16 NumLock
s=64 Windows-Key
s=128 ScrollLock またはそれに類する状態
命令:MotionEvent
書式:MotionEvent x, y, xroot, yroot, s
説明:マウスが動くまで待機するイベントです。
(x, y) ウィンドウに対する新しいマウスポジション
(xroot, yroot) 画面に対する当たらしいマウスポジション
Alt/Shift/Caps キーの状態
キーイベント
端末や OS によってキーコードが違います。私が試した中
では、Linux であり Debian Ubuntu 系である Mint と Lubuntu
ではキーコードは同じでした。しかし、Android 端末は違っ
ていました。Android 端末はタブレットだったので、Blue
Tooth キーボードを使ったのでこのせいかもしれません。
Windows も異なってました。
X11-BASIC のシステム変数として OS を見分ける変数があ
りますので、マルチプラットホームを目指したプログラム
を作成されたかたは、それを利用したら良いと思います。
命令:KeyEvent
書式:KeyEvent kc, ks[, t$, k, x, y, xroot, yroot]
説明:キーを押すことで、待機中のイベントが実行します。
キーイベントの変数は次のとおりです。
kc キーコード
ks Shift/Control/Alt 等の状態
t$ corresponding character
x ウィンドウに対するマウスポインタの座標 x
y 同じく座標 y
xroot 画面に対するマウスポインタの座標 x
yroot 同じく y 座標
k マウスボタンの状態
まずは、キーコードを調べる方法。
> keyevent a
なにかキーを押す。するとプロンプトが出るので
> Print a
すれば、変数 a に代入されたキーコードが出力されます。
いちいち、そんなこと入力してられないので連続打鍵し
てコードを調べられるようにしましょう。それがこちら。
(X11-BASIC)
' keypressx.bas
' 端末のキーコードを取得するプログラム
' Main()
Openw 1
Text 1, 10, "Press Any Key"
ShowPage
Do
Keyevent kp
Print Str$(kp)
Delay 0.5
Loop
End
Android センサ
Android 端末のセンサーを X11-BASIC で制御する方法を紹
介します。主に Sensor と名のつく関係のコマンドです。ご
承知だと思いますが Android 端末一般は、Google が
Android OS を搭載する端末として認めてるだけで、基本ど
んなセンサーを搭載するかはメーカにより異なります。で
すので各自の端末にどんなセンサが搭載されてるかは機器
のマニュアルを参照してください。ただし OS は Google の
管轄下なので、どのチャンネルがどんなセンサに対応する
かは仕様で決められてるはずです。
まあ壊れるものじゃないので、X11-BASIC をインストール
すると付いてくるサンプル sensortest.bas を実行してどん
な反応があるのか試してみればいいと思います。そういう
お気楽さが BASIC のいいところです。
Sensors 関係の命令
センサー機器について、Sensor コマンドにより取り扱え
るようになりました。詳しくは、サンプルプログラムの
sensortest.bas を参照してください。
命令:Sensor
書式:Sensor ON
Sensor OFF
説明:センサのスイッチを ON/OFF します。加速度センサ、
温度センサ、気圧センサ、光センサ、湿度センサ、ジャイ
ロスコープ、等。
変数:Sensor?
書式:a = Sensor?
説明:この端末で使用できるセンサ数を返します。使える
センサがなければ、このシステム変数は 0 になります。加
速度センサ、温度センサ、気圧センサ、光センサ、湿度セ
ンサ、ジャイロスコープ、等。
(例)
(X11-BASIC アプリを起動して「>」というプロンプトが現れたら)
> Print Sensor? [Enter]
32 ←32 個あるよと返ってきました。
>
関数:Sensor()
書式:a = Sensor(n)
説明:第 n 番のセンサーの値を返します。通常、
0 : 温度
1 : 照度
3 : 近接
4 : バッテリー
6 : 加速度 x
7 : 加速度 y
8 : 加速度 z
9 : 姿勢 x
10 : 姿勢 y
11 : 姿勢 z
X11-BASIC のサンプルプログラム sensortest.bas より、
Temperature: 0 ー C
Pressure: 1 hPa
Light: 2 lux
Proximity: 3 cm
OrientationX: 4 deg
OrientationY: 5 deg
OrientationZ: 6 deg
GyroX: 7 rad/s
GyroY: 8 rad/s
GyroZ: 9 rad/s
Mag. fieldX: 10 uT
Mag. fieldY: 11 uT
Mag. fieldZ: 12 uT
Accel.X: 13 m/s2
Accel.Y: 14 m/s2
Accel.Z: 15 m/s2
Temperature: 16 ー C
Humidity: 17 %
RotationX: 18
RotationY: 19
RotationZ: 20
GravityX: 21 m/s2
GravityY: 22 m/s2
GravityZ: 23 m/s2
Lin.Acc.X: 24 m/s2
Lin.Acc.Y: 25 m/s2
Lin.Acc.Z: 26 m/s2
MotionX: 27
MotionY: 28
MotionZ: 29
Game rot.X: 30
Game rot.Y: 31
Game rot.Z: 32
Mag. uncal.X: 33 uT
Mag. uncal.Y: 34 uT
Mag. uncal.Z: 35 uT
Gyr. uncal.X: 36
Gyr. uncal.Y: 37
Gyr. uncal.Z: 38
Step count: 39
Step detect: 40
サンプルに磁気センサの数値を 1 秒おきに表示していく
プログラムを載せます。
(X11-BASIC)
' gausens1x.bas
' most simple Gauss Sensor xyz
Sensor On
Print "Magnetic[uT]", "(x)", "(y)", "(z)"
For i = 0 To 100
Delay 1
Print Time$, Sensor(10), Sensor(11), Sensor(12)
Next i
Sensor Off
End
他のセンサといえば、GPS センサがあります。
命令:GPS
書式:GPS ON, GPS OFF
説明:GPS(Global positioning System receiver)の ON/OFF
命令:GET`LOCATION
書式:GET`LOCATION
lat,lon,alt[,bearing,accuracy,speed,time[,provider$]]
説明:GET`LOCATION は、位置デバイスから得られるデータ
を返します。ここで位置デバイスとは、GPS に限らず、地理
上のデータを返すサービス一般をさします。GPS は事前にス
イッチオンしてから使ってください。
コメント:この命令は Android 端末だけ対象です。
(例)
GET`LOCATION x,y,a
サンプルプログラム
センサを使うので PC のひとたちはごめんなさい。楽しめ
ません。Android でお楽しみのひとたちは、これをネタにし
て色々楽しんでください。ここで使っているグラフィック
ス関係の命令は次章で説明します。
磁場測定
リアルタイムにグラフを表示して、最終的にデータを
ファイルに保存するプログラムです。
センサを備えてれば温・湿度や気圧も測れますね。加速
度計もあるので振動解析もできます。ただ測定間隔をどこ
まで狭められるか、センサの追従性がどの程度か、細かい
諸元はわかりません。数値として表示されてるからといっ
て、その値が正しいのかは判断できませんから。汎用携帯
端末のセンサなので、ちゃんとした計測機器ではなく、
ツール程度と受け止めていただきたいと思います。
プログラムの基本は SensorOn して、ループで回して、終
了したら SensorOff するというものです。ループの中で
Delay 命令(または Pause 命令)を入れて測定時間間隔を決め
ています。
加速度計はわりとキビキビ反応しました。手でカシャカ
シャ動かすとそれに応答してます。まあ、手で振る程度の
確認なのでそんなに早い振動まで試せていません。携帯端
末として使う範囲ですし、せいぜい 0.01 秒(=100Hz)程度が
信頼できる値じゃないでしょうか。ですのでエンジンや
モーターの振動とかは観察できるかな?
(X11-BASIC)
' jibanyan3x.bas
' Display Gauss Sensor xyz with Array form and FileI/O
Dim T$(2048), GMX(2048), GMY(2048), GMZ(2048) ! 配列を 2048 個分確保
Count = 32 ! 測定個数を仮に初期値 32 個にしておく
dt = 0.5 ! 測定時間間隔
YX0 = 0 ! プロット開始初期値 x
YY0 = 0 ! プロット開始初期値 y
YZ0 = 0 ! プロット開始初期値 z
filname$ = "gausens.dat"
' センサのスイッチを ON
Sensor On
' 画面設定
ShowPage
Pause 1
Get_Geometry 1, bx, by, Width, Height
If Height > 320
' big screen
brafan = Height / 5
inpfac = 0.75
inphf = 0.8
depth = 6
density = 5
Else
' small screen
brafan = Width / 3.2
inpfac = 1
inphf = 1
depth = 4
density = 3
Endif
Clearw
' 座標系の設定。上限 2048 個として画面の横幅を測定個数にする。
If Width > 2048 Then
Count = 2048
Else
Count = Width
Endif
' X 軸の描画と測定条件の表示
Y0 = Height / 2
Line 0, Y0, Width, Y0
Wsize$ = "Width=" + Str$(Width) + " Height=" + Str$(Height) + " dt="
+ Str$(dt)
Deftext 0, 0.1, 0.1, 0
LText 0, 0, Wsize$
' センサーの値をグラフィクス
For i = 1 To Count
Delay dt ! センサ on から起動するまで時間かかることがあるので先に
Delay を置いた。
Disp$ = Str$(i) + "/" + Str$(Count)
White = Get_Color(64000, 64000, 64000)
Color White
Text 0, 25, Disp$ ! 更新するテキストは"Text"命令を使うのが便利
T$(i) = Time$
' chX
GMX(i) = Sensor(10)
YX1 = GMX(i)
Red = Get_Color(64000, 0, 0)
Color Red
Line i - 1, (YX0 * 5) + Y0, i, (YX1 * 5) + Y0
YX0 = YX1
' chY
GMY(i) = Sensor(11)
YY1 = GMY(i)
Green = Get_Color(0, 64000, 0)
Color Green
Line i - 1, (YY0 * 5) + Y0, i, (YY1 * 5) + Y0
YY0 = YY1
' chZ
GMZ(i) = Sensor(12)
YZ1 = GMZ(i)
Blue = Get_Color(0, 0, 64000)
Color Blue
Line i - 1, (YZ0 * 5) + Y0, i, (YZ1 * 5) + Y0
YZ0 = YZ1
ShowPage
Next i
' センサのスイッチを OFF します。
Sensor Off
' 色を戻しておく
White = Get_Color(64000, 64000, 64000)
Color White
' 測定データを保存するか
Print "<< Measure Complete >>"
Input " Data Save (Y/N) "; Ans$
If Ans$ = "Y" or Ans$ = "y" Then
Open "O", #1, filname$
For i = 1 To Count
Print #1, T$(i); ","; GMX(i) Using "+##.##"; ","; GMY(i) Using
"+##.##"; ","; GMZ(i) Using "+##.##"
Next i
Close #1
Endif
End
(Result)
重力センサでコロコロ
Android の Sensor()命令の応用です。Android の傾きセン
サ値を読んで、端末の傾いた方向へ線が伸びるようにして
ます。
(X11-BASIC)
' ballcororox.bas
' 2015/12/23
' グラフィクス画面設定
ShowPage
Pause 1
Get_Geometry 1, bx, by, Width, Height
If Height > 320 Then
' big screen
brafan = Height / 5
inpfac = 0.75
inphf = 0.8
depth = 6
density = 5
Else
' small screen
brafan = Width / 3.2
inpfac = 1
inphf = 1
depth = 4
density = 3
Endif
Clearw
' Print "-Width,Height = "; Width; ","; Height
x0 = Width / 2
y0 = Height / 2
Sensor On
Grau = Get_Color(64000, 64000, 64000) ! お好みの色で
Color Grau
Do
MouseEvent x
If x > 0
Break
Endif
dx = Sensor(6)
dy = Sensor(5)
x1 = x0 + dx
y1 = y0 - dy
If x1 < 0 Then
x1 = 0
Else If x1 > (Width - 1) Then
x1 = (Width - 1)
Endif
If y1 < 0 Then
y1 = 0
Else If y1 > (Height - 1) Then
y1 = (Height - 1)
Endif
Line x0, y0, x1, y1
x0 = x1
y0 = y1
ShowPage
Delay 0.2
Loop
Sensor Off
Stop
'Quit
End
グラフィクス描画
グラフィック描画するのに必要な命令を解説します。こ
こでは、これだけ知ってれば結構なことができるという命
令を紹介します。少なくとも、この章に掲載するサンプル
プログラムのグラフィクス関連の命令はこれだけでまか
なっています。
パソコン版の人ならわかりやすいのですが、X11-BASIC は
起動するとテキスト文字を入力するプロンプトが表示され
ます。この画面を X11-BASIC では、インタラクティブモー
ドと呼んでいます。これに対してグラフィックスウィンド
ウは、グラフィックコマンドが実行されると自動的に開か
れます。Android 版の X11-BASIC を使ってる人は、Android
OS がシングルウィンドウなので、テキストでやりとりする
インタラクティブモードの上にグラフィックスウィンドウ
が被さってる状態だと考えていただければよいと思います。
ですのでグラフィックス命令がないプログラムでなら、テ
キストコンソール下だけでプログラムを実行されます。
標準状態なら、640x400 ドットの画面上に Line や Circle
や Box を描画ます。Get_Color()と Color 命令を使えば、総
天然色で出力することができます。実行したグラフィック
ス命令は、ShowPage コマンド実行の後で画面に反映されま
す。逆に言えば、ShowPage が実行されないと画面上は特に
変化がありません。これによって高速なアニメーションを
可能にします。
ビットマップによるグラフィックス表示を可能にするた
め、文字列に矩形のグラフィック領域の内容を入れたり、
文字列からグラフィック画面にビットマップデータを表示
させるコマンド Get、Put があります。Get、Put で使用され
るファイル形式は、標準ビットマップのため、外部で作成
したアイコンを使用することができます。透過性やアル
ファチャンネルもサポートされてます。ちなみにグラ
フィックス画面には日本語文字はありません。英語だけに
なります。
命令:Openw
書式:Open n
説明:グラフィックウィンドウを開きます。最大で 16 枚の
ウィンドウを開くことができます。グラフィクスの出力は
すべて、最後に開いたウィンドウに描かれます。Openw は複
数のウィンドウを切り替えることに使えます。最初に開く
ウィンドウはデフォルトでは自動でウィンドウ1になりま
す。
命令:Closew
書式:Closew [<num>]
説明:グラフィックウィンドウを閉じます。数字が与えら
れれば、その番号が付与されているウィンドウを閉じます。
次のグラフィックコマンドが実行されるとウィンドウは再
び開かれます。
命令:Clearw
書式:Clearw [<num>]
説明:グラフィックウィンドウをクリアします。数値が与
えられれば、それに対応する番号のウィンドウをクリアし
ます。
命令:ShowPage
書式:ShowPage
説明:ShowPage はグラフィクス出力を画面に反映させます。
通常、ShowPage を実行しない限りグラフィクス出力はウィ
ンドウ上に反映されません。ただし、TomTom 端末は即座に
反映されるようになってます。
命令:Get_Geometry
書式:Get_Geometry <winnr>, <varx%>, <vary%>, <varw
%>, <varh%>
説明:Get_Geometry はウィンドウサイズを返します。この
コマンド実行前にウィンドウは開かれていなければなりま
せん。
(例)
Get_Geometry 1, bx, by, Width, Height
関数:Color_RGB()
書式:c% = Color_RGB(r, g, b [, a])
説明:Color_RGB()は色相を定義する値を返します。RGB 値
は 0(暗)から 1.0(明)までです。返り値は環境のグラフィク
ス環境に依存します。8 ビットカラーセル、またはフリーセ
ルなしの場合、色を指定した内容に最も近く設定でします。
オプションパラメータ a は、アルファ(0...1)値です。
(例)
yellow = Color_RGB(1,1,0)
Color yellow
関数:Get_Color()
書式:<num-result> = Get_Color(<red-value>,
<green-value>, <blue-value>)
説明:Get_Color()は RGB で表現される色相値を返します。
数値は 0(暗)から 65535(明)までです。ここで定義した色相
を COLOR へ渡します。
注:この関数はなるだけ使わないで、なるだけ Color_RGB()を使うようにして
ください。
(例)
yellow = Get_Color(65535,65535,0)
Color yellow
命令:Color
書式:Color <foreground-color> [, <background-color>]
説明:グラフィックウィンドウの前面色を指定します。オ
プションで背景色も指定できます。通常 Color 命令は
Color_RGB()関数とペアで使います。
(例)
yellow = Color_RGB(1,1,0)
blue = Color_RGB(0,0,1)
Color yellow,b lue
命令:Line
書式:Line <x1>, <y1>, <x2>, <y2>
説明:座標(x1, y1)から(x2, y2)への直線を描画します。
線の太さなどのパラメータは Defline で定義できます。
(例)
Line 0, 0, 639, 199
命令:Circle
書式:Circle <x>, <y>, <r> [, <w1>, <w2>]
説明:円を描画します。x と y は円の中心座標、r は円の半
径です。オプションで円弧にすることもできます。w1 は描
画開始角度で w2 が終了角度です。
(例)
Circle 100, 100, 50
命令:Deftext
書式:Deftext flag%, width, height, angle
説明:Ltext 命令で使われるラインフォントの設定をします。
スタイル、回転、サイズを定義します。色は Color で、線
種は Defline で定義してください。
flag% : テキストスタイル 0=normal 1=monospace
angle : 回転角
width and height : パーセンテージで指定 (100%が 100 Pixel フォントにな
ります)
(例)
Deftext 0, 0.1, 0.1, 270
命令:Ltext
書式:Ltext x,y,t$
説明:座標 x, y にテキストを描画します。Ltext コマンド
はライン描画テキストです。フォントスタイルや線種は
Deftext や Defline 命令で定義してください。
(例)Ltext 10, 10, "test"
命令:Text
書式:Text x, y, t$
説明:t$で与えられるテキスト(Bitmap Font)文字を座標 x,
y に描画。テキスト内容を更新する処理のときはこれを使う
ほうが便利。
(例)Text 0, 25, "test"
(X11-BASIC)
' Show the complete ASCII Font
Setfont "*writer*18*"
Color Get_Color(65535, 10000, 10000)
For x = 0 to 15
For y = 0 to 15
Text 320 + 16 * y, 20 + 24 * x, Chr$(y + 16 * x)
Next y
Next x
Showpage
End
サンプルプログラム
グラフのテンプレート
典型的な時系列グラフのテンプレート(ひな型)として、
ロジスティック写像の時系列グラフを描画します。
(X11-BASIC)
' timeseriesx.bas
Count = 100
A = 3.8
' 描画ウィンドウの表示
Openw 1
' 描画セッションの開始
ShowPage
Pause 1
Get_Geometry 1, bx, by, Width, Height
If Height > 320
' big screen
brafan = Height / 5
inpfac = 0.75
inphf = 0.8
depth = 6
density = 5
Else
' small screen
brafan = Width / 3.2
inpfac = 1
inphf = 1
depth = 4
density = 3
Endif
Clearw
' グラフの X 軸と Y 軸の設定
Xorg = 30
Yorg = Height / 2
Xmax = Width
Ymax = 0
Xmin = Xorg
Ymin = Height
Y0 = 0.2 ! ロジスティック写像の初期値
Xpos = Xorg
Ypos0 = Yorg
' 縦軸と横軸の描画
Line Xorg, Yorg, Xmax, Yorg
Line Xorg, Ymin, Xorg, Ymax
' 縦軸と横軸の名称を追加
Deftext 0, 0.1, 0.1, 270
Xstr$ = "Gene. n"
Ltext 10, Yorg - Ymin * 1 / 4, Xstr$
Deftext 0, 0.1, 0.1, 0
Ystr$ = "X(n)"
Ltext Xmax * 0.80, Yorg + 10, Ystr$
' 縦軸と横軸の目盛りを決める
dX = Xmax / Count
dY = (Ymin - Ymax) / 2
' 計算して結果をプロットするループ
For i = 0 To Count
Y1 = A * Y0 * (1.0 - Y0)
Ypos1 = Yorg - dY * Y1
Line Xpos, Ypos0, Xpos + dX, Ypos1
ShowPage ! 逐次表示させる場合
Xpos = Xpos + dX
Ypos0 = Ypos1
Y0 = Y1
Next i
' ShowPage ! 全部計算した後に表示させる場合
' 最後に描画セッションを終了
' Closew
' Quit
End
(Result)
モアレ画像表示
CRT モニターのテストでよくある、ライン模様を描画して
モアレ像を表示するプログラム。X11-BASIC の描画準備が上
手くいってるよね、という確認。
(X11-BASIC)
' For Loop and Line Draw.
' Set the text that we're going to use for the axis titles
ShowPage
Pause 1
Get_Geometry 1,bx,by,Width,Height
' Tree Data
If Height > 320
' big screen
brafan = Height / 5
inpfac = 0.75
inphf = 0.8
depth = 6
density = 5
Else
' small screen
brafan = Width / 3.2
inpfac = 1
inphf = 1
depth = 4
density = 3
Endif
Print " - Width,Height = "; Width; ","; Height
Clearw
For i = 1 To Width Step 4
Line i, 0, Width - i, Height
Next i
For j = 1 To Height Step 4
Line Width, Height - j, 0, j
Next i
' Finish with the DrawingArea object
ShowPage
End
(Result)
ラインが踊るプログラム
画面の端(壁)にあたったらラインの両端が反射するよう
に描画するプログラムです。もともとのサンプルは、SHARP
X-1 用のプログラムを集めた本だったと思います。ここでは、
それを X11-BASIC で動くようにしました。
オリジナルのサンプルは、単色ラインの配列を記憶しと
いて、50 本描いたら(配列 50 になったら)、古い順に線を消
す(黒線で上書きする)仕組みになってました。そうするこ
とで、ひとまとまりのラインがウネウネ動いてるように見
せる効果をみせていました。
今回の X11-BASIC では、X-1 当時に比べたら色数が豊富な
ので、線の色がグラデーションで変わるようにしました。
もとは無限ループで延々と動くようにしてありましたが、
1000 回のループ内で実行するように変更してます。
それと実行する度に初期書き出し位置を乱数で決定する
ようにしてます。そのためプログラムの init(x,y)箇所で、
Randomize 文を使って乱数の種を初期化してるところがポイ
ントです。あと線の色がグラデーションで変わるようにし
ました。画面に描画される模様をお楽しみ下さい。
(X11-BASIC)
' spaceox.bas
' For Loop and Line Draw.
Dim CCX(2)
Dim CCY(2)
Dim VX(2)
Dim VY(2)
' Set the text that we're going to use for the axis titles
ShowPage
Pause 1
Get_Geometry 1,bx,by,Width,Height
If Height > 320
' big screen
brafan = Height / 5
inpfac = 0.75
inphf = 0.8
depth = 6
density = 5
Else
' small screen
brafan = Width / 3.2
inpfac = 1
inphf = 1
depth = 4
density = 3
Endif
Clearw
' init(x,y)
XLIM = Width
YLIM = Height
Randomize
CCX(0) = int(Rnd(1) * Width)
CCY(0) = int(Rnd(1) * Height)
CCX(1) = int(Rnd(1) * Width)
CCY(1) = int(Rnd(1) * Height)
' init direction
VX(0) = int(Rnd(1) * 20)) - 10
VY(0) = int(Rnd(1) * 20)) - 10
VX(1) = int(Rnd(1) * 20)) - 10
VY(1) = int(Rnd(1) * 20)) - 10
' init color
C1 = int(Rnd(1) * 64000))
C2 = int(Rnd(1) * 64000))
C3 = int(Rnd(1) * 64000))
dC1 = int(Rnd(1) * 800) + 200
dC2 = int(Rnd(1) * 800) + 200
dC3 = int(Rnd(1) * 800) + 200
' Loop
For i = 0 To 1000
C1 =C1 + dC1
C2 =C2 + dC2
C3 =C3 + dC3
If C1 >= 63000 Or C1 < 200 Then
dC1 = -1 * dC1
Endif
If C2 >= 63000 Or C2 < 200 Then
dC2 = -1 * dC2
Endif
If C3 >= 63000 Or C3 < 200 Then
dC3 = -1 * dC3
Endif
Grau=get_color(C1, C2, C3)
Color Grau
Line CCX(0),CCY(0),CCX(1),CCY(1)
IF (CCX(0) + VX(0) >= XLIM) Or (CCX(0) + VX(0) <= 1) Then
VX(0) = -VX(0)
Endif
If (CCY(0) + VY(0) >= YLIM) Or (CCY(0) + VY(0) <= 1) Then
VY(0) = -VY(0)
Endif
If (CCX(1) + VX(1) >= XLIM) Or (CCX(1) + VX(1) <= 1) Then
VX(1) = -VX(1)
Enddif
If (CCY(1) + VY(1) >= YLIM) Or (CCY(1) + VY(1) <= 1) Then
VY(1) = -VY(1)
Endif
CCX(0) = CCX(0) + VX(0)
CCY(0) = CCY(0) + VY(0)
CCX(1) = CCX(1) + VX(1)
CCY(1) = CCY(1) + VY(1)
Delay 0.2
ShowPage
Next i
' Finish with the DrawingArea object
End
(Result)
時計の針
昔、何かのパソコン雑誌でこの問題を BASIC で解く記事
があって読んだ記憶があるんですよね。私が読んでた雑誌
というと『Oh!MZ』か、ゲーム誌になる前の『テクノポリ
ス』だと思うんですが。算数とか数学で習った知識をアル
ゴリズムにして BASIC にするという、教育的でありながら
フレンドリーでフランクで若い読者に向けて親切ないい記
事だな、という印象で覚えていました。
気になってネットで調べたら解答をいろいろと取り揃え
てるサイトがあった。履修で言えば中学生で習う話とのこ
とです。そう書かれていた某知恵袋では、一元一階方程式
で解いてました。未知数である角を X とした場合、長針が
一周する間に、短針は・・・って感じで解くなら確かに中
学生だなあ。
代わりに小学生期では、そういう状態になるのは一日に
何回あるでしょう、みたいに問われてたかな。なんか時計
のキットみたいなのをグリグリいじって確認したような気
がする。
あと他のサイトではさらっと数式で出してる解答もあれ
ば Excel で表にして出したのもありバラエティがある。こ
こでは、精度を出す方針にする。まずは秒単位、次に 1/100
秒まで。原理的にはもっと精度を出せるんですが、とりあ
えずそこまで。
プログラムの原理に納得した方は他の組み合わせにも
チャレンジしてください。それもやってみたら、次は時計
であることではなく、他の問題に応用できないか考えてく
ださい。応用の仕方がわかると面白くなります。
ループが多いと時間がかかる
↓
効率のいい探索方法
↓
180 に一番近い数値を表示する
↓
桁(Gear)を切り替えて収束させていく
↓
グラフィクスに残すと楽しい
(X11-BASIC)
' clocklinex.bas
' 両側から範囲を狭めていく方法
' 時計の針と目盛りをグラフィカルに図示
' 解の配列
Dim lDeg(12)
Dim sDeg(12)
Count = 0
' 針の初期位置
lInit = 0
sInit = 0
lArow1 = 0
lArow2 = 0
sArow1 = 0
sArow2 = 0
' 1速
Gear = 1
dShot = 360 / 12 / 12
dLong = 360 / 12
' Loop
While sInit < 360
While lInit < 720
lArow2 = lArow1 + dLong
sArow2 = sArow1 + dShot
'
Critical Point の判定
Judge = (180 - (lArow2 - sArow2)) * (180 - (lArow1 - sArow1))
'
Print Judge Using "######.###", (180 - (lArow2 - sArow2)) Using
"###.###", (180 - (lArow1 - sArow1)) Using "###.###", "Gear"; Gear
If Judge <= 0 Then
Print Judge Using "######.###", (180 - (lArow2 - sArow2))
Using "###.###", (180 - (lArow1 - sArow1)) Using "###.###", "Gear";
Gear
Break
Endif
'
次への準備
lArow1 = lArow2
sArow1 = sArow2
Wend
' シフトチェンジ
If Gear <= 1 Then
Gear = 2
dShot = 360 / 12 / 12 / 60
dLong = 360 / 12 / 60
Else If Gear = 2 Then
Gear = 3
dShot = 360 / 12 / 12 / 60 / 60
dLong = 360 / 12 / 60 / 60
Else If Gear = 3 Then
Gear = 4
dShot = 360 / 12 / 12 / 60 / 60 / 100
dLong = 360 / 12 / 60 / 60 / 100
Else
'
角度=>時計表記へ
hh = int(sArow1 * 12 / 360)
mm = int(lArow1 * 60 / 360)
ss = int(((lArow1 * 60 / 360) - int(lArow1 * 60 / 360)) * 60)
dd = ((((lArow1 * 60 / 360) - int(lArow1 * 60 / 360)) * 60) -
int(((lArow1 * 60 / 360) - int(lArow1 * 60 / 360)) * 60)) * 100
If lArow1 > 360 Then
mm = int((lArow1 - 360) * 60 / 360)
Endif
sDeg(Count) = sArow1
lDeg(Count) = lArow1
Count = Count + 1
Print hh Using "##"; ":"; mm Using "##"; ":"; ss Using "##";
".";dd Using "###", "short="; sArow1 Using "###.#", "long="; lArow1
Using "###.#"
Print
Gear = 1
dShot = 360 / 12 / 12
dLong = 360 / 12
'
長針を 0 に初期化、短針も時の位置にセット
lInit = 0
lArow1 = 0
lArow2 = 0
sInit = sInit + 360 / 12
sArow1 = sInit
sArow2 = sInit
Endif
Wend
Print "-Fin: "; sArow2; " [deg]", lArow2; " [deg]"
' グラフィクス
' 画面設定
ShowPage
Pause 1
Get_Geometry 1, bx, by, Width, Height
If Height > 320
' big screen
brafan = Height / 5
inpfac = 0.75
inphf = 0.8
depth = 6
density = 5
Else
' small screen
brafan = Width / 3.2
inpfac = 1
inphf = 1
depth = 4
density = 3
Endif
Print "-Width,Height = "; Width; ","; Height
Clearw
'
CenterX = Width / 2
CenterY = Height / 2
LongLine = Min(Width, Height) / 2
ShotLine = LongLine * 0.8
dc = 64000 / 12
' 目盛り描画
' Print "- Mark Draw"
' Print "mXpos", "mYpos"
For i = 0 To (Count - 1)
Grau = Get_Color(64000, 64000, 64000)
Color Grau
mXpos = int(CenterX + LongLine * sin(2 * i * pi / 12))
mYpos = int(CenterY - LongLine * cos(2 * i * pi / 12))
Circle mXpos, mYpos, 5
tm$ = Str$(i)
Deftext 0,0.2,0.2,0
Ltext mXpos, mYpos, tm$
Print mXpos, mYpos
Next i
' 針描画
' Print "- Arow Draw"
' Print "CenterX", "CenterY", "lXpos", "lYpos", "sXpos", "sYpos"
For i = 0 To (Count - 1)
Grau = Get_Color(dc * i, dc * (Count - i), 64000)
Color Grau
lXpos = int(CenterX + LongLine * sin(lDeg(i) * pi / 180))
lYpos = int(CenterY - LongLine * cos(lDeg(i) * pi / 180))
Line CenterX, CenterY, lXpos, lYpos
sXpos = int(CenterX + ShotLine * sin(sDeg(i) * pi / 180))
sYpos = int(CenterY - ShotLine * cos(sDeg(i) * pi / 180))
Line CenterX, CenterY, sXpos, sYpos
Print CenterX, CenterY, lXpos, lYpos, sXpos, sYpos
Next i
' グラフィクス後処理
ShowPage
Stop
'Pause 10
'Quit
End
(Result)
holy@mint ~ $ xbasic clockline5x.bas
0:32:43. 64 short= 16.4 long=196.4
1:38:10. 91 short= 49.1 long=229.1
2:43:38. 18 short= 81.8 long=261.8
3:49: 5. 45 short=114.5 long=294.5
4:54:32. 73 short=147.3 long=327.3
5:59:59.100 short=180.0 long=360.0
7: 5:27. 27 short=212.7 long=392.7
8:10:54. 55 short=245.5 long=425.5
9:16:21. 82 short=278.2 long=458.2
10:21:49.
9 short=310.9 long=490.9
11:27:16. 36 short=343.6 long=523.6
12:32:43. 64 short=376.4 long=556.4
-Fin: 360 [deg] 0 [deg]
GUI の制御
X11-BASIC にも GUI 関係の部品があります。ATARI-ST の
GEM 環境を継承してるんだと思うんです。なんとなくレトロ
な、古きよきコンピュータの味わいがあって私は好きです。
ただし、グラフィクス命令の延長で作られているので日
本語の対応はされていません。また昨今の GUI コンポーネ
ントを使った Visual プログラミングのような IDE があるわ
けでもありません。逆にシンプルで単一のファイルの中で
コードを書けます。タッチスクリーンが主流たるインター
フェイスの Android 端末なら、プルダウンメニューやポッ
プアップメニュー(リスト)など応用できると思います。
これらの部品は、リソース・コンストラクション・セッ
ト(RCS)というツールを使って作成されるとのこと。RSC の
詳しいことは公式マニュアルを参照してください。
GUI 部品を使う前には座標系の定義が必要です。しかし通
常、自動的に初期位置を決めてくれます。自分でカスタマ
イズすることもできますが、自動で決めてくれることで、
使用してる環境の画面のアスペクト比やシステムフォント
が違う場合でも、同じような操作感を得ることができます。
ダイアログボックス
ダイアログボックスはユーザからの入力によく使われま
す。Alert や FileSelect は、ダイアログボックスの典型で
す。
Form_do()関数は、ダイアログボックスのもっとも単純な
使い方です。単純に Exit や Touchexit のあるオブジェクト
ツリーを構築するには、Form_do()1 を呼びだせばいいです。
命令:Alert
シンプルな Alert ボックスを表示させます。
書式:Alert <type>, <message-string>,
<default-button>, <button-string>, <num-var> [,
<string-var>]
説明:ユーザの入力を問い合わせたりするアラートボックス
を表示します。
<type> アラートシンボルを選びます。0=none, 1="!", 2="?", 3="stop"で
す。
<message-string> メインとなる文です。一行は’|’というシンボルで分
割されます。編集可能なフィールドは Chr$(27)で始まります。’|’までが
編集可能になります。
<button-string> ボタンの中の文字列です。’|’で分けて書きます。
<default-button> リターンキーを押したらハイライトになるボタンになり
ます。
<num-var> この変数は選ばれたボタンの数値を設定します。
<string-var> これはユーザが設定できるテキストインプットの文字列変数
です。このフィールドは Chr$(13)で分割します。
(X11-BASIC)
' alertes1x.bas
Alert 3, "This file is write protected._You can only read or delete
it.", 1, "OK|DELETE|CANCEL", sel
Quit
End
(X11-BASIC)
' alertes2x.bas
' ALERT No.1
Alert 1, "Pick a|button", 1, "Left|Right", a
' ALERT No.2
Alert 0, "You pressed|Button" + STR$(a), 0, "OK", a
' Example of editable fields
i = 1
name$ = "TEST01"
posx$ = "N54.50.32.3"
t$ = "Edit waypoint:||Name:" + chr$(27) + name$ + "|"
t$ = t$ + "Position: " + chr$(27) + posx$ + "|"
Alert 0, t$, 1, "OK|UPDATE|DELETE|CANCEL", a, f$
While Len(f$)
Wort_Sep f$, CHR$(13), 0, a$, f$
Print "Field"; i; ": ", a$
Inc i
Wend
Quit
End
命令としてではなく、関数として返り値を得る手もあり
ます。
関数:Form_Alert()
書式:<num-result> = Form_Alert(<default-button>,
<string$>)
説明:アラートボタンを表示させます。Form_Alert は選択し
たボタンの番号を返します。
default button デフォルトではボタンなし(0=none)です。
string$ この文字列はアラートボックスのメッセージになります。
ここで大括弧記号は文字列の一部になります。例えば、
"$[$i$]$$[$Message$]$$[$Buttons$]
みたいな感じになります。小文字 i はアラートシンボルの
番号で整数です。
(X11-BASIC)
' alertes3x.bas
~Form_Alert(1, "[0][This is my message!][OK]")
Quit
End
命令:FileSelect
これでパスやファイルを指定するのがすごく楽になりま
す。デフォルト値を設定しておくことで、いちいちキー
ボードから入力する手間が省けます。
書式:FileSelect <title$>, <path$>, <default$>,
<string-variable>
説明:ファイルセレクトボックスを開きます。
<title$> ファイルセレクトボックスのタイトルを短めに入れます。例えば
「Select a .DOC file to open ...」という感じ。
<path$> もしこれを指定しなければデフォルトが指定されます。パス名は、
(UNIX にはないですが)ドライブの指定、コロン、パス、ファイルマスクなど
の情報が完全に含めて下さい。ファイルマスクというのは「*」(アスタリス
ク)で表現されるワイルドカードキャラクタのことです。
<default$> ファイルセレクト箇所に表示されるファイル名です。""とする
とデフォルトファイル名なしになります。
<string-variable> FileSelect はパスを含む選択したファイル名の文字列
を返します。その文字列を返す変数です。CANCEL を選択すると空白文字列が
変数に代入されます。
例を実行すると、変数 file$にパスとファイル名が代入されます。
(X11-BASIC)
' fselectx.bas
FileSelect "Load File", "./*.bas", "input.dat", file$
Print file$
Quit
End
(Result)
関数:ListSelect()
書式:num = ListSelect(title$, list$())
説明:ListSelect()はグラフィカルなリスト選択を表示し
ます。そのリストはユーザが定義する任意の配列 list$()か
らなります。返す値は配列の添字になります。また何のア
イテムも選択されないときは-1 を返します。
(X11-BASIC)
' listselectx.bas
Dim list$(4)
title$ = "List A to D"
list$(0) = "<Element A>"
list$(1) = "<Element B>"
list$(2) = "<Element C>"
list$(3) = "<Element D>"
num = ListSelect(title$, list$())
Print "You selected List No."; num
End
(Result)
メニュー
プログラムのオプションをメニューを用いることによっ
て選択できるようにしているアプリケーションが多いと思
います。X11-BASIC では独自にポップアップメニューとド
ロップダウンリストボックスが使用できます。ここに示す
例は、簡単なドロップダウンメニューの取扱いについてで
す。
命令:Menu
書式:Menu
説明:メニュー選択アクションを動作させます。このコマ
ンドは Event に位置づけられる命令です。使用する前に、
Menudef 命令で定義しておく必要があります。イベントに類
するため、Menu は普通ループの中で用いられます。
(例)
Menudef field$(), menuaction
Do
Pause 0.05
Menu
Loop
End
Procedure menuaction(k)
...
Return
命令:Menudef
書式:Menudef array$(), <procname>
説明:メニューの中から選んだ項目の数値を<procname>で
定義するプロシージャへ渡します。
この命令は array$()の文字列からなるメニューヘッダを
読みます。それらのヘッダは、メニュータイトルとメ
ニュー項目からなります。空白文字""はメニュー文字列の
終端を意味します。
<procname> メニューエントリを選択するとどう動かすかを制御するサブプ
ロシージャを指示します。
(例)
' menudef160303x.bas
field$() = ["INFO"," Menutest ","","FILE"," new"," open ...","
save","\
save as ...","--------------"," print","--------------","
Quit","",""]
Menudef field$(), menuaction
Do
Pause 0.05
Menu
Loop
End
Procedure menuaction(k)
Print "MENU selected "; k; " contents: "; field$(k)
If field$(k) = " Quit" Then
Quit
Endif
Return
命令:Menukill
書式:Menukill
説明:Menudef によって定義された Menu に関する決め事を
忘れ去ります。
命令:Menuset
書式:Menuset n,x
説明:メニューエントリ n の数値 x を変更します。
x=0
x=1
x=2
x=3
x=4
’ ’ normal, reset marker ’(HOCH)’
’(HOCH)’ set marker
’=’ set menu-point non selectable
’ ’ set menu-point selectable
check the menu entry ’-’ permanent non selectable
サンプルプログラム
これら GUI 関係の命令を集大成したサンプルプログラム
を示します。こんな画面が表示されるはずです。この画面
はトップダウンメニューの[Info]を選んで、そのプルダウ
ンメニュー[What This]を選ぶと表示されるダイアログボッ
クスです。
(Result)
(X11-BASIC)
' menux.bas
' Test-program for Drop-Down-Menus
Dim field$(50), slist$(1)
cFlag = 0 ! チェックマークの On/Off
qFlag = 0
' OS の設定
If Unix? < 0 Then
HomeDir$ = "/home/holy/"
Else If Win32? < 0 Then
HomeDir$ = "c:\My Document\owner\"
Else If Android? < 0 Then
HomeDir$ = "/storage/emulated/0/"
Else
HomeDir$ = ""
Endif
' グラフィクス画面設定
Openw 1
Pause 0.5
Get_Geometry 1, bx, by, Width, Height
If Height > 320 Then
' big screen
brafan = Height / 5
inpfac = 0.75
inphf = 0.8
depth = 6
density = 5
Else
' small screen
brafan = Width / 3.2
inpfac = 1
inphf = 1
depth = 4
density = 3
Endif
Clearw
Grau = Get_Color(32000, 32000, 32000)
Color Grau
Pbox 0, 0, Width, Height
' メニュー項目のセットと宣言
For i = 0 To 50
Read field$(i)
Exit If field$(i) = "***"
Next i
field$(i) = "" ! Data 文の最後の文字列"***"を空白に置き換える
Menudef field$(), MenuAction
' ループ
Repeat
Delay
Menu
0.05
Until (qFlag > 0)
Closew
Quit
End
' 選択したメニューのアクション内容
Procedure MenuAction(k)
Local button
If field$(k) = "
Quit" Then
qFlag = 1
Else If field$(k) = "
What This"
button = Form_Alert(1, "[0][--- What This
---||menu160307x.bas|Test-program for Drop-Down-Menus][ OK ]")
Print "Button Flag:"; button
Else If field$(k) = "
FileSelect "Open
Open"
File", HomeDir$ + "*.bas", "*.bas", file$
Print "Select Open File Name : "; file$
Else If field$(k) = "
FileSelect "Open
Save As"
File", HomeDir$ + "*.*", "output.dat", file$
Print "Select Save File Name : "; file$
Else If field$(k) = "
List"
slist$() = ["Dead", "Alive"]
num = ListSelect("Select List", slist$())
If num < 0 Then
Print "You pressed Cancel Button"
Text 10, 50, "You pressed Cancel Button"
Else
Print "List No."; num; " = "; slist$(num)
Endif
Else If field$(k) = "
Button"
Alert 0, "Choose " + Chr$(27) + "any Action", 1,
"OK|UPDATE|DELETE|CANCEL", a, f$
Print "a = "; a
Print "f$ = "; f$
Else If field$(k) = "
Help"
Alert 0, "You pressed|Help Button", 0, "OK", a
Print "a = "; a
Else If field$(k) = "
Online Help"
cFlag = not cFlag
Menuset k, 4 * abs(cFlag)
Endif
Return
' EndProcedure
' メニュー項目
Data "Info", "
What This", ""
Data "File", "
New", "
Open", "
Save", "
As","--------------", "
Quit", ""
Data "Edit", "
Cut", "
Copy", "
Data "Tool", "
List", "
Button", ""
Data "Help", "
Help", "
Online Help", ""
Data "***"
Paste", ""
Save
参考文献
・Microsoft BASIC 習熟者のための Full BASIC 入門
・白石 和夫、(仮称)十進 BASIC による JIS Full BASIC 入門の手引き、
1999.1.18
・From the Software Design Gallery、第 1 回『パソコン・プログラミング
言語の歴史(1) - 行番号』
・StarSuite 7 Office Suite、A Sun ONE Software Offering Basic プログ
ラマ向けガイド、2003, Revision A
あとがき
筆者はプログラミングなどについてのブログを書いてい
ます。この本の内容は、そのブログに少しずつ書き溜めて
きた X11-BASIC に関する導入部をまとめたものです。
検索エンジンで X11-BASIC を検索すると、この言語には
わりとユーザはいるし、ワークグループもあるんだなあと
思います。世界的な視野から見れば、この X11-BASIC とい
う環境は、それほどマイナーではないんですね。しかし、
日本で X11-BASIC について書かれたウェブサイトは少なく、
シンタックスについて解説した方がまだない状態でした。
それで英語の文献を読みつつ、稚拙ながら翻訳した文を書
き溜めた、自分用のマニュアルというのが実際のところで
す。
本書では BASIC 言語としての基礎部分までにとどめまし
た。理由は、KDP の推奨として電子書籍のファイルサイズを
1MByte 以下にとどめた方が良い、というご指導のためです。
おそらくダウンロードにかかる通信時間、料金の兼ね合い
なんでしょう。それでも内容のボリュームとして、そのへ
んで区切ってよかったと思います。
ブログの記事には次のステップとして、いろんな分野へ
の応用プログラムを掲載しています。続きの気になる方は
そちらサイトをご覧になってください。
最後ですが、これだけ良くできたプログラミング言語を
無料で提供してくれてる Markus Hoffmann 氏と愉快な仲間
たちへ、ありがとうと言わせていただきます。この環境が
無料ってのはホントすごいことですよ!
それと私より、若い人特に学生さん伝えておこうと思い
ます。別に、プログラミングでなくてもいいから、ハード
ウェア工作でも音楽でも CG でもいいんです。この道のこと
に関しては、オレ。結構イケるんだぜ、みたいな熱中でき
るモノをなにか持ってください。
2016/05/06
ブログ「牛と戯れた日々を想って」
http://acc-holy.cocolog-nifty.com/blog/
このマニュアルの著作権は放棄しませんが、転載は好き
なようにしてください。このマニュアルよりももっとよく
できたものが出来るのならそれに越したことはないと思い
ます。”すでにあるソースは有効に利用する”というのは
プログラマの良い伝統です。みんなが幸せ。
付録
シェル的使い方
電卓気分で使える PC で動く言語として十進(仮称)BASIC
を推してるんですが、それじゃ X11-BASIC を使うと便利な
ことは何かと問われたら、こういう使いかたを推します。
X11-BASIC プログラムを記述したソースファイルの先頭に、
X11-BASIC インタプリタがあるパスを記述して、
#! /usr/bin/xbasic
Print "yes"
Quit
End
のようなコードを保存(例えば test.bas とか)。
ターミナルで先ほどの行を追加したファイルに実行権を
加えます。
chmod +x test.bas
ターミナルのプロンプトで
./test.bas
とすると
holy@901:~$ ./test.bas
yes
holy@901:~$
のように実行されます。通常、
xbasic test.bas
のようにしますが、ヘッダに「#! [path]」を加えると上の
ような使い方も可能というわけです。
これはシェルスクリプトに実行権を与えて使うのと同じ
ことです。当然、そのように bash や csh から呼び出すこと
もできます。
Android の場合は、デスクトップに X11-BASIC のショート
カットを作成してインタプリタを起動することができます。
そのときもコードの終わりに quit の一行を加えておけば、
処理が終了したら X11-BASIC インタプリタも閉じるように
するようにできます。Android ショートカットの場合は、
ヘッダの「#!」はいらないようですね。
文字列処理する場合、日本語が使えない点で、X11-BASIC
は使いづらい感がどうしてもあります。けれどスクリプト
を使いたい状況、例えば毎日実行する定形化した繰り返し
作業なんかでは便利です。シェルで動く各種スクリプトと
連携をとるのが簡単という点で使い甲斐があると思います。
起動オプションの使い方
X11-BASIC インタプリタを起動するさいに、起動オプショ
ンをいくつか指定することができます。次の起動オプショ
ンが用意されています。
xbasic <filename> [input.bas]という filename のプログラムを実行します
-l リードオンリーで実行しない
-e <command> BASIC の命令を実行します
--eval <expression> expression で表された式を計算します
--daemon デーモンモードで実行します
-h --help ヘルプを表示します
--help <topic> topic のヘルプを表示します
-version バージョン等の情報を表示します
例:
xbasic testme.bas
xbasic -l dontrunme.bas
xbasic -e 'ALERT
1,"Hello
!",1,"
OK
",b'
xbasic --eval 1+3-4*3
xbasic --help "*nl*"
デーモン的使い方
コマンドラインオプションの-daemon は(ターミナルで接
続することなしで)デーモンモードでインタプリタを実行さ
せます。そのため入力についてのプロンプトが返ってきま
せん。このモードはバックグラウンドで X11-BASIC プログ
ラムを実行させたいときに有用でしょう。
例:X11-BASIC インタプリタで TCP ソケットポート番号 1371 でユーザを作成
して実行するには
- /etc/inetd.conf での設定
xbasic stream tcp nowait xbasic /usr/sbin/tcpd /bin/xbasic --daemon
- /etc/services での設定
xbasic1371/tcp
この例はデーモンステーションについてということに注
意してください。あなたのシステムのセキュリティホール
を作る原因にもなるので X11-BASIC を本来こういう使い方
はしません。
コンパイラの使い方
xbc コンパイラの使い方を説明します。これを使えば、
X11-BASIC インタプリタよりも 10 倍早くなるとのことです。
それと、インタプリタがない環境へも単独の実行ファイル
で渡すことができます。
・Linux 版
UNIX や Linux での、X11 グラフィクスエンジンとして SDL
ライブラリ(Simple Directmedia Layer、略して SDL)を使っ
ています。ないしはグラフィックなしとして扱われます。
SDL との関係を図に張り付けます。
この図は Wikipedia の SDL の項目から持ってきたもので
す。この図で言う所の"Application"層が X11-BASIC インタ
プリタにあたります。SDL について詳しいわけではないんで
すが、Windows や Android とのクロスプラットホームが実現
してるのはこのおかげが大きいんでしょう。
X11-BASIC インストールで make した後、make を実行した
ディレクトリ直下に x11basic.a と libx11basic.so.(ver)が
出来ていると思います。それらを、/usr/lib 以下にをコ
ピーします。
make を実行したディレクトリ直下に xbc も出来てますの
で、そこにソースファイルをコピーして、
xbc [ソースファイル名]
と入力すればコンパイルできます。出力ファイルは、[ソー
スファイル名].o という中間ファイルと b.out という実行
ファイルができます。パスを通すとか、エイリアスを設定
するとか工夫してもいいですし、コンパイルの実行まで
シェルで組んでしまってもいいですね。いろいろ工夫のし
ようがあると思います。
xbc の使い方は、ヘルプで見ることができます。
xbc --help
X11-Basic Compiler V.1.22 (c) Markus Hoffmann 2002-2013
X11-BASIC Version: 1.22 16.07.2015 12:51:12 xxxx 1.22
Usage: xbc [options] file...
Options:
-h, --help Display this information
--dynamic link with shared library libx11basic.so
--static link with static library (default)
-b only precompile
-c precompile and compile, but do not link
-l produce linkable object file (no executable)
-L <path> use path as library path (default: /usr/lib)
-C keep comments
--bytecode produce a bytecode file
-bytecode produce a bytecode file
--virtualm use virtual machine framework instead of
psydo-interpreter
-virtualm use virtual machine framework instead of
psydo-interpreter
--pseudo pseudo-compile
-shared produce shared object file
--win32 produce Windows .exe file
-win32 produce Windows .exe file
-o <file> Place the output into <file>
・Windows 版
MS-Windows 版も、SDL のサポートを受けています。SDL が
ない場合はグラフィックスなしモードになります。心配し
なくても X11-BASIC の ZIP パッケージには、SDL.DLL が入っ
てるのでそのまま解凍すればいいです。他の PC に持って
行って使うときにはすべきですけどね。
コンパイルは、ZIP ファイルを解凍したフォルダ(SDL.dll
がある)に BASIC プログラムのソースファイルをコピーして、
コマンドプロンプトで
xbc [ファイル名]
と入力すればコンパイルできます。
コンパイルの途中で、コンパイルの仕方、出力ファイル
名、コンパイルした後に実行するかどうか、聞いてきます。
コンパイルの仕方の選択肢は次のようになります。
1.スタンドアローンの exe ファイルを作成します。
2.C 言語に変換してから tcc コンパイラを使います。
3.バイトコードだけ出力します。
4.見掛け上のコンパイル。tcc を使ってください。
X11-BASIC だけなら「1」の選択肢を取るしかありません。
他の選択肢を選ぶにはそれ相応のツールをインストールし
ておく必要があります。
この後は、exe ファイルの名前を指定します。
最後にコンパイルしたらそのまま実行するかどうか聞か
れます。
これで Windows の実行ファイルができたと思います。
私はこのレトロというかモンドコンピュータ的なウィン
ドウが好きです。X11-BASIC の FileSelect 命令とか Menu 命
令で作る GUI のスタイルがこうなので、ATARI ST で使われ
たウィンドウ環境がこういうスタイルだったのだと当時を
しのばれます。今から見ると味わい深いですよね。
・Android 版
/bas ディレクトリ以下にプログラムソースファイルがあ
れば、メニューから Load して Compile すれば、拡張子
「.b」というファイルができます。
Android のガジェットに、このショートカットを画面に登
録するツールがあるので、それで画面上にアイコンを作れ
ばいいと思います。
Quick Reference
1.予約された変数名
すでに予約済みの変数があります。これらは普通の変数
として使えないキーワードです。うっかりこの名前を使う
ことで、エラーになることがあります。そういうときは、
LET 命令を使ってみてください。ふつう変数名の終わりはコ
マンド名とは違うものです。
int ANDROID? Android OS なら-1。それ以外なら 0。
int COLS テキストターミナルの行数
int CRSCOL 現在テキストカーソルがある行の位置
int CRSLIN 現在テキストカーソルがある列の位置
flt CTIMER CPU システム時計(秒)
int FALSE 最後に発生したエラー番号
int ERR 常数:0
int GPS? GPS 機能が使えれば TRUE。そうでなければ 0。
flt GPS_ALT GPS(Altitude m)
flt GPS_LAT GPS(latitude deg)
flt GPS_LON GPS(longitude deg)
int MOUSEK マウスボタン状態
int MOUSES Shift,Alt,Ctrl,Caps キーの状態
int MOUSEX マウス座標 x
int MOUSEY マウス座標 y
int PC プログラムカウンタ
flt PI 円周率。常数:3.14159265359...
int ROWS テキストターミナルの列数
int SENSOR? センサが使用可能か(TRUE)
int SP スタックポインタ
int STIMER システム内時計
flt TIMER Unix システム時計(float)
int TRUE 常数:-1
int UNIX? UNIX(Linux, BSD)なら-1。それ以外なら 0。
int WIN32? MS-Windows 32bit なら-1。それ以外なら 0。
DATE$ 本日の日付
FILEEVENT$ ファイルにイベントがあったか
INKEY$ キーボードバッファ
TERMINALNAME$ 端末名称
TIME$ 現在の時間
TRACE$ 現在トレース中のプログラムの行数
2.Conditions
状態の表現は、FALSE の場合は 0、TRUE の場合は-1 と決
められています。これらの状態を論理演算 AND, OR, XOR 等
で演算することもできます。
3.Numbers and Constants
数値の初期値には、0x という 16 進数が入ります。文字列
の初期値は空白""です。配列は [ , , ; , , ; , , ] のよ
うな形式です。
4.Operators
演算子は次のように定義されており、上の方ほど優先さ
れます。
0. () (括弧)
1. ^ (累乗)
2. * / (乗算, 除算)
3. \ (modulo)
4. - + (減算, 加算)
5. MOD DIV (modulus, ...)
6. < > = <> <= >= (比較演算子)
7. AND OR XOR NOT EQV IMP (倫理演算子)
5.Abbreviations
インタプリタの対話式ダイレクトモードではコマンドを
省略形で指示できます。例えば q を入力したら QUIT と解釈
してくれるとかです。
また次のような略記をダイレクトモードでもプログラム
コードでも使えます。
’ REM
? PRINT
@ GOSUB
~ VOID
! 行末に加えるコメント
& EVAL / indirect command
6.Interpreter Commands
CLEAR すべての変数を初期化します。
CONT STOP した後に入力すると続きを実行します。
DUMP 使ってる変数をとにかくリストアップする
DUMP "@" 関数やプロシージャをリストアップする
DUMP ":" ラベルがあればリストアップする
DUMP "#" 開いてるファイルをリストアップする
DUMP "K" list of implemented commands
DUMP "F" list of internal functions
ECHO ON/OFF TRON/TROFF と同じ
EDIT プログラムを編集するためにデフォルトのエディタを呼び出します
HELP <expr> 短いヘルプを出力します。
LIST [s,e] (s 行目から e 行目まで)プログラムリストを表示します。
LOAD file$ プログラムを読み込みます。
NEW すべての変数の値を初期化して停止します。
PLIST formatted listing
PROGRAM options set title and compiler options
PSAVE a$ writes the reformatted BASIC-program into file a$
QUIT X11-BASIC インタプリタの終了
REM comment コメント
RUN プログラムの実行
STOP プログラムの中断
SAVE [file$] BASIC プログラムのファイルへの書き出し
TROFF トレースモードをオフします。
TRON デバッグ用トレースモードをオンします。
VERSION X11-Basic のバージョンと日付
XLOAD コンテクストメニューからプログラムを読み込みます
XRUN コンテクストメニューからプログラムを読み込んで実行します
7.Flow Control Commands
AFTER n,procedure n 秒後にサブプロシージャ procedure を実行します。
BREAK EXIT IF が TRUE のときと同じ動作をします
CASE const 条件分岐。SELECT、DEFAULT、ENDSELECT 等も参照のこと。
CHAIN bas$ 他のプログラムを起動します
CONTINUE STOP した後に入力すると続きを実行します。
DEFAULT 条件分岐で使います。SELECT、CASE、ENDSELECT も参照のこと。
DEFFN 行に続く数式の関数を定義します。
DO * LOOP ループします。
DOWNTO IF * ELSE * ENDIF を参照
FOR ... DOWNTO IF * ELSE * ENDIF を参照
ELSE 条件分岐。If 構文の IF、ENDIF を参照のこと。
END プログラムの終了。インタラクティブモードに復帰します。
ENDFUNCTION 関数の終わり。FUNCTION を参照のこと。
ENDIF 条件分岐。If 構文の IF、ELSE を参照のこと。
ENDSELECT 条件分岐で使います。SELECT、CASE、DEFAULT も参照のこと。
EVERY n,procedure n 秒毎にプロシージャを実行します。
EXIT IF a 状態 a が真(TRUE)ならループを抜け出します。
FOR * NEXT ループを制御する構文です。
FUNCTION * ENDFUNC 関数の開始箇所から終了箇所までを意味します。
GOSUB proc(...) サブルーチンを呼び出します。
GOTO label label へジャンプします。
IF * ELSE * ENDIF 条件分岐
LOOP DO * LOOP を参照
NEXT FOR * NEXT を参照
ON BREAK GOSUB proc ブレークしたら飛んでいくプロシージャの行き先
ON ERROR GOSUB proc エラーが起きたら飛んでいくプロシージャの行き先
ON * GOSUB proc1,... 値によって飛んでいくサブルーチンを割り振る
ON * GOTO label1,... 値によって飛んでいくラベルを割り振る
REPEAT REPEAT * UNTIL というループ構文です。
RESUME エラーが起きても待機状態でいます
RETURN PROCEDURE の終了
SELECT expr SELECT * CASE * DEFAULT * ENDSELECT を参照
UNTIL exp REPEAT * UNTIL というループ構文です。
SPAWN procedure Spawn new thread
8.Console Input/Output Commands
BEEP TTY/コンソールにて音を鳴らします。1 で On、0 で Off。
BELL BEEP と同じ。
CLS テキストスクリーンを初期化します。
FLUSH バッファをはき出します
FORM_INPUT t$ 初期値として文字列を代入
HOME テキストカーソルをホームポジションに動かします。
INPUT [#n,]["text";] var 変数に値や文字列を入力します。
LINEINPUT [#n,]t$ channel/ole/console から一行読み込みます。
LOCATE row,column テキストコンソール上 column、row にカーソルを移しま
す。
PRINT a;b$ コンソールへ出力
PRINT AT(x,y); テキストカーソルを x 列,y 行に表示します
PRINT COLOR(x,y); テキストの色を変更します
PRINT TAB(x); テキストカーソルを x 列に移します
PRINT SPC(x); テキストカーソルを x 列に移します
PRINT a USING f$ フォーマットにしたがって数値を出力します
PUTBACK a put back a char to console
9.File Input/Output Commands
BGET #f,a,n read n bytes from file #f to address a
BLOAD f$,a[,l] reads entire file (given by name) to address a
BPUT #f,a,n writes n bytes from address a to file/channel f
BSAVE f$,a,l saves l bytes in memory at address a to file f$
CHDIR path$ ワーキングディレクトリのパス path$を変えます。
CHMOD file$,m ファイルのパーミッションを変更
CLOSE [[#]n] ファイル I/O のチャンネルやリンクを閉じます。
FLUSH [#n] ファイルへバッファをはき出します
KILL file$ ファイルの削除
MAP maps a file into memory
UNMAP unmaps memory
MKDIR path$ ディレクトリの作成
OPEN m$,#n,file$ 入出力可能なファイルまたはソケットを開きます
OUT #n,a out byte a to channel n
PRINT #n; ファイルやチャンネルに出力します
PUTBACK [#n,]a put back a char to channel/file/console
RELSEEK #n,d Place filepointer on new relative position
RENAME file$,dst$ ファイルのリネームもしくは移動
RMDIR path$ 空のディレクトリを削除
SEEK #n,d ファイルのポインタを相対的に d だけ移動します
TOUCH #n ファイルのタイムスタンプ変更
WATCH file$ monitor file changes
10.Variable Manipulation Commands
ABSOLUTE x,adr% Assigns the address to the variable x.
ARRAYCOPY dst(),src() 配列 dst()に配列 src()をコピー
ARRAYFILL a(),b 配列を値で埋めます
CLR a,b,c(),f$ ここでは a=0;b=0;c()=[];f$=""となります。
DEC var var=var-1 と同意。
DIM 配列の宣言をします。
ERASE a()[,...] 配列を消します
INC a 変数 a だけ増やします。
LET a=b 代入する命令です。
LOCAL var[,...] プロシージャや関数内で使うローカル変数を宣言します。
SORT a(),n[,b()] 配列をソート
SWAP a,b 変数の中身を交換
VAR vars declare arguments to be passed "by reference"
11.Memory Manipulation Commands
ABSOLUTE x,adr% Assigns the address to the variable x.
BMOVE q,z,n copies a block of n bytes from address q to z
DPOKE adr,word write short int word to adr
FREE adr% Frees a previously allocated memory block.
LPOKE adr,long writes long int value to pointer adr
MFREE adr% Frees a previously allocated memory block.
MSYNC adr%,l flushes changes map memory back to disk
POKE adr,byte write byte to pointer adr
SHM_DETACH adr% detaches the shared memory segment
SHM_FREE adr% frees the shared memory segment
12.Math commands
ADD 変数 b に変数 a を加えます。
DEC var var=var-1 と同じ。ただしこっちの方が速い
DIV a,b a=a/b と同じ。ただし、こっちの方が速い
FFT a(),i 一次元配列の高速フーリエ変換
FIT x(),y()[,yerr()],n,func(x,a,b,c,...) fits function to data
FIT_LINEAR x(),y()[,[xerr(),]yerr()],n,a,b[,siga,sigb,chi2,q] linear
regression with errors
FIT_POLY x(),y(),dy(),n%,a(),m% fit a polynom to datapoints
INC var var=var+1 と同じ。ただしこっちの方が速い
MUL a,b a=a*b と同じ。ただしこっちの方が速い
SORT a(),n[,b()] sorts n values of a() to incrementing order
SUB a,b a=a-b と同じ。ただしこっちの方が速い
13.Other Commands
CALL adr[,par,...] EXEC を参照
CONNECT #n,t$[,i%] connect a channel
DATA 1,"Hallo",... 後に書いた文字や数値をデータとして扱います。
DELAY sec sec だけ待機します。PAUSE と同義。
ERROR n エラー番号 n を実行します。
EVAL t$ X11-BASIC の命令を含む t$を実行します。
EXEC adr[,var,...] ポインタ adr の C 言語のサブルーチンを呼び出します。
GET_LOCATION ,,,,,,, 端末の位置を返します
GPS ON/OFF GPS デバイスを On/Off
LINK #n,t$ load shared object file t$
UNLINK #n unload shared object file
MERGE f$ Merges bas-file to actual program code
NOP 操作も動作もしません
NOOP 操作も動作もしません
PAUSE sec sec 秒待機します
PIPE #l,#k links two file channels
PLAYSOUND c,s$ WAV サンプルを奏でます
PLAYSOUNDFILE file$ 音楽ファイルを奏でます
PROCEDURE proc(p1,...) プロシージャの先頭
RANDOMIZE [seed] 乱数生成の種を設定
READ var DATA 命令を順に読みます
RECEIVE #n,t$ ソケットからのメッセージを返します
RESTORE [label] READ 命令のポインタをセットします。label で指示できま
す。
RETURN expr FUNCTION の終わりに expr を返します
RSRC_LOAD file$ GEM rsc-File (ATARI ST)を読み込みます
RSRC_FREE GEM rsc-File (frees)を読み込みます
SEND #n,t$ ソケットへメッセージを送ります
SENSOR ON/OFF SENSOR スイッチの On/Off
SETENV t$=a$ a$の値を環境変数 t$に代入します
SOUND freq 内臓スピーカーから音を出します
SPLIT t$,d$,mode,a$,b$ 文字列 t$をデリミタ d$で分けて a$と b$に代入しま
す
SHELL t$ t$に書かれたシェルコマンドを実行します
SPEAK t$ t$に書かれた文字列をしゃべらせます
SYSTEM t$ t$に書かれたシェルのコマンドを実行します。
UNLINK #n un-links shared object #n
VOID a calculates expression a and discard result
WAVE c,f, 音楽シンセサイザを制御します
WORT_SEP SPLIT と同じ
14.Graphic commands
14.1.Drawing and painting
BOUNDARY f 境界の On/Off
BOX x1,y1,x2,y2 枠の描画
CIRCLE x,y,r,, 円の描画
CLIP ,,,,, clipping function
COLOR f[,b] 前面(背面)のカラー設定
COPYAREA ,,,,, 画面上の矩形領域をコピー
CURVE ,,,,,,, cubic Bezier-curve
DEFFILL c,a,b 内部を埋めるスタイルとパターン設定
DEFLINE a,b 線幅や線種の設定
DEFMARK c,a,g set color, size, type (POLYMARK)
DEFMOUSE i マウスカーソルの種類設定
DEFTEXT c,s,r,g ltext によるテキストのプロパティ設定
DRAW [[x1,y1] TO] x2,y2 描線
ELLIPSE x,y,a,b[,a1,a2] 楕円の描画
FILL x,y flood fill
GET x,y,w,h,g$ 領域のパタンをビットマップとして g$に取得
GPRINT グラフィックウィンドウへ文字列を表示
GRAPHMODE mode グラフィックモードの設定
LINE x1,y1,x2,y2 描線
LTEXT x,y,t$ 描線によるテキスト
PBOX x1,y1,x2,y2 中身も埋まったボックス
PCIRCLE x,y,r[,a1,a2] 中身も埋まった円
PELLIPSE x,y,a,b[,a1,a2]中身も埋まった楕円
PLOT x,y 点描
POLYLINE n,x(),y() 配列 x(),y()による多角形
POLYFILL n,x(),y() 中身も埋まった多角形
POLYMARK n,x(),y() draw polygon points
PRBOX x1,y1,x2,y2 中身も埋まった丸めボックス
PUT x,y,g$ g$のビットマップを貼り付け
PUT_BITMAP t$,i,i,i,i map bitmap
RBOX x1,y1,x2,y2 丸めボックスを描画
SCOPE a(),typ,ys,yo fast plot of data a()
SCOPE y(),x(),typ,ys,yo,xs,xo fast 2D plot of data
SETFONT f$ ビットマップフォントの設定
SETMOUSE x,y マウスカーソルの設定
SGET screen$ グラフィックを screen$へキャプチャ
SPUT screen$ screen$のビットマップをウィンドウへ貼り付け
TEXT x,y,t$ テキストを描画(bitmap font)
14.2.Screen/Window commands
CLEARW [#n] グラフィックウィンドウの初期化
CLOSEW [#n] グラフィックウィンドウを閉じる
FULLW n フルスクリーンのウィンドウを開く
GET_GEOMETRY ,,,, グラフィックウィンドウのサイズを返す
GET_SCREENSIZE ,,,, スクリーンのサイズを返す
INFOW n,t$ ウィンドウの情報を設定
MOVEW n,x,y グラフィックウィンドウを移動
OPENW n グラフィックウィンドウを開く
ROOTWINDOW スクリーンの背景を描画
NOROOTWINDOW switch back to normal output
SAVESCREEN file$ スクリーンのビットマップをファイルへ保存
SAVEWINDOW file$ ウィンドウのビットマップをファイルへ保存
SCREEN n スクリーンモードの選択
SHOWPAGE 直近まで行われたグラフィック操作を反映する
SIZEW n,w,h グラフィックウィンドウのサイズ
TITLEW n,t$ グラフィックウィンドウのタイトル
TOPW n グラフィックウィンドウを前面に表示する
USEWINDOW #n direct graphics output to window n
VSYNC SHOWPAGE と同じ
14.3.GUI/User input commands
ALERT a,b$,c,d$,var[,ret$] ユーザ入力を待機する Alert/Infobox を表示す
る
EVENT ,,,,,,,, イベントが起きるまで待機
FILESELECT tit$,path$,dflt$,f$ ファイル選択ボックスを表示
HIDEM マウスカーソルを隠す
KEYEVENT a,b キーが押されるまで待機
LISTSELECT tit$,list$() リスト選択ボックスを表示
MENUDEF m$(),proc 配列 m$()からメニュータイトルやアイテムを読む
MENUKILL メニューの消去
MENUSET n,x change menu-point #n with value x
MENU STOP メニューのスイッチを Off する
ONMENU execute the menu and
MENU メニューイベントを待機
MOUSE x,y,k マウス位置と状態の取得
MOUSEEVENT ,,, マウスイベントを待機
MOTIONEVENT ,,, マウスの動作を待機
OBJC_ADD t%,o%,c% オブジェクトツリーに追加
OBJC_DELETE t%,o% オブジェクトツリーから削除
RSRC_LOAD file$ ATARI の GUI GEM のリソースをロード
RSRC_FREE ATARI の GUI GEM のリソースを解法
SHOWM マウスカーソルを表示
15.File Input/Output functions
d%=DEVICE(file$) ファイルのデバイス番号を返します
b=EOF(#n) ファイルの終わりに達したら TRUE を返します
b=EXIST(fname$) fname$というファイルが存在すれば TRUE を返します
a=FREEFILE() Returns first free filenumber or -1
a$=FSFIRST$(path$,,) ファイルシステムにある最初のファイルを探します
a$=FSNEXT$() 次にあるファイルを探します
c=INP(#n) チャンネルやファイルからバイト数を読みます
c=INP?(#n) 読むことのできるバイト数か
a=INP&(#n) チャンネルやファイルから 1word(2 Bytes)読みます
i=INP%(#n) チャンネルやファイルから 1long(4 Bytes)読みます
t$=INPUT$(#n,num) ファイルまたはチャンネル n から num バイト読みます
ret=IOCTL(#n,d%,) チャンネルやファイルの設定を返します
t$=LINEINPUT$(#n) ファイルまたはチャンネル n から 1 行読みます
p=LOC(#n) ファイルポジションインディケータを返します
l=LOF(#n) ファイルの長さ(全文字数)を返します
l%=SIZE(file$) ファイルのサイズを返します
t$=TERMINALNAME$(#n) ターミナル接続したデバイス#n の名前を返します
16.Variable/String Manipulation functions
adr%=ARRPTR(b()) pointer to array descriptors
a=ASC(t$) 文字列の最初の文字の ASCII コードを返す
b$=BIN$(a[,n]) バイナリを文字列に変換
t$=CHR$(a) 文字列を ASCII コードへ変換
a$=DECLOSE$(t$) removes enclosing characters from string
a=DIM?(a()) 配列 a()の要素数を返します
a$=ENCLOSE$(t$[,p$]) encloses a string
f=GLOB(a$,b$[,flags]) 文字列 a$がパタン b$に合致したら TRUE を返します
t$=HEX$(a[,n]) a を 16 進数にして返す
t$=INLINE$(a$) 6 ビット ASCII コードから 8-bit バイナリに変換
a=INSTR(s1$,s2$[,n]) s1$に s2$が含まれるか
a=TALLY(t$,s$) t$のなかにある s$の数を返す
b%=INT(a) 整数へ変換する
t$=LEFT$(a$[,n]) 文字列 a$を左から n 文字返す
t$=LEFTOF$(a$,b$) 文字列 a$をパタン b$で分割して左側を返します
l=LEN(t$) 文字列の長さを返す
u$=LOWER$(t$) t$のテキストを小文字に変換
l=LTEXTLEN(t$) テキストのサイズを返す
m$=MID$(t$,s[,l]) 文字列 t$の左から s 文字目から l バイトだけ返します
t$=MKA$(a()) convert a whole array into a string
t$=MKI$(i) convert integer to 2-byte string
t$=MKL$(i) convert integer to 4-byte string
t$=MKF$(a) convert float to 4 byte string
t$=MKD$(a) convert float to 8 byte string
o$=OCT$(d,n) convert integer d to string with octal number
t$=REPLACE$(a$,s$,r$) a$にある s$を r$に書き換えます
t$=REVERSE$(a$) 文字列を反転して返します
t$=RIGHT$(a$[,n]) 文字列 a$の右から n 文字を返す
t$=RIGHTOF$(a$,b$) a$を b$で分割した右側を返します
a=RINSTR(s1$,s2$[,n]) s1$の右側から s2$のある位置を返します
t$=SPACE$(i) i 個のスペースを返します
t$=STR$(a[,b,c]) 数値を文字列に変換
t$=STRING$(i,w$) 文字列 w$を i 個コピーする
u$=TRIM$(t$) 文字列 t$の空白を除去する
u$=XTRIM$(t$) 文字列 t$の空白を除去する
u$=UCASE$(t$) 文字列 t$を大文字に変換する
u$=UPPER$(t$) 文字列 t$を大文字に変換する
u$=USING$(a,f$) 数値 a の表示形式を整形
a=VAL(t$) ASCII 文字列を数値に変換します。
i=VAL?(t$) returns number of chars which are part of a number
adr%=VARPTR(v) returns pointer to variable
u$=WORD$(b$,n) 文字列 b$の第 n 文字目を返します
e=WORT_SEP(t$,d$,m,a$,b$) splits t$ into parts
17.Data compression and coding functions
b$=ARID$(a$) order-0 adaptive arithmetic decoding
b$=ARIE$(a$) order-0 adaptive arithmetic encoding
b$=BWTD$(a$) inverse Burrows-Wheeler transform
b$=BWTE$(a$) Burrows-Wheeler transform
c$=COMPRESS$(a$) 文字列を圧縮します
c$=UNCOMPRESS$(a$) 文字列を解凍します
c%=CRC(t$[,oc]) 32 bit checksum
e$=ENCRYPT$(t$,key$) encrypts a message
t$=DECRYPT$(e$,key$) decrypts a message
b$=MTFD$(a$) Move To Front decoding
b$=MTFE$(a$) Move To Front encoding
b()=CVA(a$) returns array reconstructed from the string
b%=CVI(a$) convert 2-byte string to integer
b%=CVL(a$) convert 4-byte string to integer
b=CVS(a$) convert 4-byte string to float
b=CVF(a$) convert 4-byte string to float
b=CVD(a$) convert 8-byte string to double
t$=INLINE$(a$) 6-bit ASCII to 8-bit binary conversion
t$=REVERSE$(a$) return the reverses of a string
b$=RLD$(a$) run length decoding
b$=RLE$(a$) run length encoding
18.Memory Manipulation functions
adr%=ARRPTR(b()) pointer to array descriptors
i%=DPEEK(adr%) read word from pointer adr
b%=LPEEK(adr%) reads long (4 Bytes) from address
adr%=MALLOC(n%) allocates size bytes of memory
adr%=MSHRINK(adr%,n%) reduces the size of a storage area
d%=PEEK(a%) reads Byte from address a
adr%=REALLOC(oadr%,n%) changes the size of a storage area
adr%=SHM_ATTACH(id) attaches the shared memory segment
id=SHM_MALLOC(size,key) returns the identifier of the shared memory
segment p.506
adr%=SYM_ADR(#n,s$) return pointer to symbol from shared object file
adr%=VARPTR(v) returns pointer to variable
19.Logic functions
c%=AND(a%,b%) 論理計算 c=(a AND b)
c%=OR(a%,b%) 論理計算 c=(a OR b)
c%=XOR(a%,b%) 論理計算 c=(a XOR b)
c%=EQV(a%,b%) 論理計算 c=(a EQV b)
c%=IMP(a%,b%) 論理計算 c=(a IMP b)
b%=BCHG(x%,bit%) x のビットを 0 と 1 を反転
b%=BCLR(x%,bit%) x のビットを 0 に
b%=BSET(x%,bit%) x のビットを 1 に
b%=BTST(x%,bit%) x のビットが 1 なら-1 を返す
b%=BYTE(x%) same as b=x AND 255
b%=CARD(x%) same as b=x AND 0xffff
b%=WORD(x%) same as b=x AND 0xffff
b%=EVEN(d) d が奇数なら TRUE
b%=ODD(d) d が偶数なら TRUE
b%=GRAY(a) Gray code. if a<0: inverse Gray code
b%=SHL(a) ビットを左へシフトする
b%=SHR(a) ビットを右へシフトする
b%=SWAP(a) Swaps High and Low words of a
20.Math functions
The math function library contains a comprehensive
set of mathematics functions, including:
trigonometric 三角関数
hyperbolic ハイパブリック関数
logarithmic (底が e である場合と 10 である場合)
exponential (底が e である場合と 10 である場合)
miscellaneous (平方根、累乗、etc.)
数学関数のいくつかはベクトルや行列で定義されてます。
b=ABS(a) 絶対値 b = |a|
c=ADD(a,b) 加算 c = a + b
b=CBRT(a) 三平方 b = 3 √ a
a=CEIL(b) truncate number
a=CINT(b) truncate number (note: differs from INT() !)
z=COMBIN(n,k) z = (n−k)!·k!
c=DIV(a,b) 除算 c = a/b
b()=FFT(a()[,f%]) 高速フーリエ変換
a=FIX(b) round number to integer
a=FLOOR(b) round number down to integer
b=FRAC(a) a の非整数部(小数点以下の数)
y=GAMMA(x) gamma function y = Γ(x)
y=LGAMMA(x) logarithm of gamma function y = |lnΓ(x)|
a=HYPOT(x,y) a = x 2 + y 2
b=INT(a) 整数化。小数点以下切り捨て
b()=INV(a()) 正方行列の逆行列を計算
i=SGN(a) 正負の符号とゼロ
b=SQR(a) 平方 b = √a
b=SQRT(a) 平方 b = √a
b=TRUNC(a) truncate number
b=LN(a) 自然対数
b=LOG(a) 自然対数(底が e)
b=LOG10(a) 底が 10 の対数
b=LOGB(x) 底が 2 の対数
b=LOG1P(x) b = log(1 + x) accurate near zero
c=MOD(a,b) c=(a MOD b)と同じ
c=MUL(a,b) 乗算 c = a · b
b=EXP(a) exponential function b = e x (e to the x)
b=EXPM1(a) exponential function minus 1 b = e x − 1
b=FACT(a) 階乗 b = a!
a=PRED(x) returns the preceding integer of x
a=SUCC(x) returns the next higher integer
b()=SOLVE(a(),x()) solve linear equation system
z=VARIAT(n,k) number of permutations of n elements
20.1.Angles
角度は引数も返り値も共にラジアンです。
b=RAD(a) デグリー(度)をラジアンへ変換
b=DEG(a) ラジアンをデグリー(度)へ変換
6.20.2. Trigonometric functions
b=SIN(a) 正弦関数
b=COS(a) 余弦関数
b=TAN(a) タンジェント
b=ASIN(a) アークサイン
b=ACOS(a) アークコサイン
b=ATAN(a) アークタンジェント
b=ATN(a) アークタンジェント
b=ATAN2(a,c) extended arc-tangent
b=SINH(a) ハイパブリックサイン
b=COSH(a) ハイパブリックコサイン
b=TANH(a) ハイパブリックタンジェント
b=ASINH(a) ハイパブリックアークサイン
b=ACOSH(a) ハイパブリックアークコサイン
b=ATANH(a) ハイパブリックアークタンジェント
20.3.Random numbers
a=GASDEV(dummy) ガウス分布に基づいた乱数
a=RAND(dummy) 整数の乱数
a=RANDOM(n) 0 から n までの整数の乱数
a=RND(dummy) 0 から 1 までの乱数
a=SRAND(seed) 乱数のシードを設定。RANDOMIZE と同じ。
21.System functions
ret%=CALL(adr%[,par]) マシン語コードまたは C 言語のサブルーチンを呼び
出す
t$=ENV$(n$) 環境変数 n$の値を読みます
t$=ERR$(i) エラーメッセージ
ret=EXEC(adr[,var]) EXEC を参照。整数を返します。
i%=FORK() creates a child process
d$=JULDATE$(a) Julian day
a=JULIAN(date$) date$ by Julian day a
a$=PARAM$(i) i’th word from the commandline
t$=PRG$(i) program line
a=SENSOR(i) get the value from the i th sensor
t$=SYSTEM$(n$) n$で書かれたシェルのコマンドを実行して文字列に返しま
す。
t$=UNIXTIME$(i) TIMER から time$を得る
d$=UNIXDATE$(i) TIMER から date$を得る
22.Graphic functions
c=COLOR_RGB(r,g,b[,a]) rgb(a)値を与えることで色を得る
a=EVENT?(mask%) ペンディング中のグラフィクスイベントがあれば TRUE を返
す
a=FORM_ALERT(n,t$) デフォルトでボタン n のあるメッセージボックスを表示
~FORM_CENTER(adr%,x,y,w,h) centers the object tree on screen
a=FORM_DIAL(,,,,,,,,) complex function for screen preparation
a=FORM_DO(i) do dialog
c=GET_COLOR(r,g,b) rgb(a)値を与えることで色を得る
d=OBJC_DRAW(,,,,) draw object tree
ob=OBJC_FIND(tree,x,y) return object number by coordinates
a=OBJC_OFFSET(t%,o,x,y) calculate absolute object coordinates
c=POINT(x,y) returns color of pixel of graphic in window
c=PTST(x,y) returns color of pixel of graphic in window
a=RSRC_GADDR(typ,nr) get pointer to object tree
23.Other functions
a=EVAL(t$) evaluate expression contained in t$
m=MAX(a,b,c,...) 最大値を返す
m=MAX(f()) not implemented yet
m=MIN(a,b,c,...) 最小値を返す
m=MIN(array()) not implemented yet
m=MIN(function()) not implemented yet