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
© Copyright 2024 Paperzz