• 検索結果がありません。

LIST

プロシージャは次の 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,"-");"_ ";str$

(int(b/a*100),3,3);"% ]";

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 " a@main.before: "; a @Test1()

Print " a@main.after: "; a Quit

End

Procedure Test1() Local a

Print " a@sub.before: "; a a = 2

Print " a@sub.after: "; a Return

End

(Result)

a@main.before: 1 a@sub.before: 1 a@sub.after: 2 a@main.after: 1

(GAMBAS)

' Gambas module file Public Sub Main() Dim a As Integer a = 1

Print " a@main.before: "; a Test1()

Print " a@main.after: "; a Stop

End

Sub Test1()

Dim a As Integer

Print " a@sub.before: "; a a = 2

Print " a@sub.after: "; a End

(Result)

a@main.before: 1 a@sub.before: 0 a@sub.after: 2 a@main.after: 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