HSPで関数や局所変数を使いたい |
今となっては、HSP Ver3が主流となり、HSP Ver2.61は使われなくなりつつあると思います。本講座でも、今後はVer3のみの対応と したいと思います。
以下のような表現も、Ver3に合わせたいと思います。
C言語を学ばれた方の中には、「HSPでも関数や局所変数が使えたらいいのになあ」と思う方もいるかと思います。HSPにもそれと 似たようなものがあります。
1.ユーザー定義命令 |
戻り値のない関数、つまり命令を作りたい時には#deffunc命令を使います。
goto *Main #deffunc test mes "これはテストです" return *Main test
これで、「これはテストです」と表示する、testという命令ができました。#deffuncの後ろに命令名、最後にreturnを付けます。
C言語の場合は、必ずmainという名前の関数から実行されます。Windowsプログラミングでは、必ずWinMainという関数から実行
されます。上に何が書いてあろうともです。HSPの場合は、必ず1行目から始まります。そのため、goto文でtest命令の
定義部を飛ばしてやる必要があるのです。
「#deffunc」は実際に命令を使う位置より前に置いても、後に置いてもかまいません。
test stop #deffunc test mes "これはテストです" return
stopがないとその下の部分まで実行されてしまうのは、gosub文によるサブルーチンと同じです。
このプログラムは、gosub文による以下のサブルーチンと同じ働きです。
gosub *test stop *test mes "これはテストです" return
ユーザー定義命令には、引数を指定することができます。
#deffunc 新規命令の名前 引数の型1 引数名1, 引数の型2 引数名2,……
goto *Main #deffunc nedan str sinamono, int tanka mes sinamono + "は" + tanka + "円" + "です" return *Main nedan "ガム", 100
"ガム"がsinamonoに、100がtankaに渡されます。引数の型には、整数型int、文字列型str、実数型double等があります。
gosub文だといちいち
sinamono = "ガム"
tanka = 100
としてからサブルーチンを呼ばなければならないので、この方がすっきりします。
なお、関数(命令)定義時に使用される引数を仮引数、関数(命令)を実際に使用する時に渡される引数を実引数といいます。上の 場合だとsinamono、tankaが仮引数、"ガム"、100が実引数です。
goto *Main #deffunc increment int a a=a+1 mes a return *Main increment 10
これはエラーになります。HSPの場合仮引数はあくまでも値を受け取るための器であって、変数ではないので、中で値を変えることは
できません。
もちろん
goto *Main #deffunc increment int a mes a+1 ;仮引数に足し算する return *Main increment 10や
goto *Main #deffunc increment int a mes a+1 return *Main x=10 increment x+2 ;実引数に計算式を指定するといった書き方はできます。
なお、特殊な型として引数の型にvarを指定すると、中で値を変えられるようになりますが、参照渡しという少し難しい概念が必要 となりますので、後で必要になった時に解説します。
2.ユーザー定義関数 |
戻り値がある関数を作りたい時には#defcfunc命令を使います。
#defcfunc 新規関数の名前 引数の型1 引数名1, 引数の型2 引数名2,……
戻り値の型は指定しません。
goto *Main #defcfunc half int a return a/2 *Main mes half(10)
戻り値をreturnの後ろに書きます。これは、引数の半分の値を返す関数です。関数を呼ぶ場合は引数をカッコで囲む必要が あります(引数がまったくない場合も「関数名()」として関数を呼ぶ必要があります)。なお、mes half(5)とした場合aがint型なので a/2もint型となり、答は2になります。戻り値をdouble型にしたい場合は
goto *Main #defcfunc half int a return double(a)/2 *Main mes half(5)
とする等、ユーザー側で工夫が必要です。
条件によって返す値を変えたい場合は、以下のようにします。
goto *Main #defcfunc guusuu int a if a\2==0 { return "偶数" } else { return "奇数" } *Main mes "10は" + guusuu(10) + "です" mes "5は" + guusuu(5) + "です"
3.モジュール定義命令 |
HSPで局所変数を使うには#module、#globalというモジュール定義命令を使います。
#deffunc〜return、#defcfunc〜returnを#module、#globalではさんでやることによって、その命令、関数内の変数は局所変数と
なります。
;1〜10の3乗を計算 goto *Main #module #defcfunc sanjyou int a answer=1 for i,0,3,1 answer=answer*a next return answer #global *Main for i,1,11,1 mes sanjyou(i) next
関数sanjyou内の変数 i と、外の変数 i は名前は同じですがまったくの別物として扱われます。
goto *Main #module #defcfunc increment int a return a+1 #global *Main a=10 mes increment(a)
このようにすると、#defcfuncで定義されている仮引数aは、increment関数内でしか有効ではないため、関数を呼び出す側の実引数の 変数と名前が同じでも問題ありません。
グローバル変数(関数、命令の外にある変数)を関数、命令の中から参照するには、変数名に"@"をつけます。
;円の面積を求めます goto *Main #module #defcfunc menseki double hankei return hankei*hankei*pi@ #global *Main pi=3.14159 ; 円周率 mes menseki(10.0)
今回の説明の詳細は、hspprog.htmにあります。hspprog.htmはHSPをインストールしたフォルダのdoclibフォルダにあります。
ひとくちメモ: |
・関数とは |
C言語を知らない方のための補足です。 学校で学んだ関数は、このような形をしたものでした。 y=f (x) プログラミングでも同じです。xを引数、yを戻り値と呼びます。正確には、関数 f が返した戻り値をyに入れているのです。 f の代わりにsanjyouとか、mensekiといった名前をつけているわけです。 つまり関数とは、引数xを受け取って、それを元になんらかの処理をし、計算結果を戻り値として返すものです。 y=f (x1, x2, ……) プログラミングの場合は、このように引数が複数の場合が多いです。 引数がまったくない場合もあります。あるいは、戻り値がない場合もあります。引数も戻り値もまったくない場合もあります。C言語では すべて関数としています。 mes half(10)と書くと、まずhalf(10)が実行され、その戻り値がmesへの引数となります。 HSPでもVer3で関数の考えが導入され、いくつかの命令語が関数y=f (x)の形になりました。HSP Ver2.61まではf y,xという形をして いました。つまり戻り値もまた引数に含まれ、あくまでも命令語であるという扱いでした。 |
・局所変数とは |
その関数(命令)の中でしか有効でない変数を局所変数といいます。C言語風に言えば、関数内で宣言された際に作成(メモリ内に
その変数のための領域が確保される)され、関数の終了とともに破棄される(メモリ内から消える)のです。 HSPの場合少し仕様が違っていて、関数を呼ぶたびに作成されたり破棄されたりしません。変数は保持されています。(C言語でいえば、 staticをつけて宣言した変数です。なお、特殊な型として引数の型にlocalを指定すると、関数が呼ばれると同時に作成され、関数の 終了とともに破棄されます。) しかし、関数の外側からは参照できない点は同じです(厳密には参照する方法があります)。 もっとも重要な点は、関数の外側に同じ名前の変数があっても、気にしなくていいという点です。gosub文によるサブルーチンの説明を した際に、メインルーチンで使われる変数名と同じ名前を使うなとは言いませんが、メインルーチンの変数をおかしくしてしまわない ように気をつけてくださいということを書きました。それを気にしなくていいのです。 |