HSPエラー7「配列の要素が無効です」

無料プログラミングツールHSPのエラーメッセージ「HSPエラー」。
 配列変数がらみで何かしらの問題が起こってる場合に表示されます。HSPエラーの番号は「7」。エディタ上のコンパイル実行では『配列の要素が無効です』のメッセージ。実行ファイルでのエラーメッセージは『内部エラーが発生しました(7)』。

配列変数は、整数値型のdim命令、文字列型のsdim命令を利用してスクリプト上で明示的に確保できます。HSP3から 実数値型(いわゆる小数点数値)としてddim命令も用意されてます。

命令の処理内容 1要素のサイズ
dim命令 整数値型の変数・配列変数の確保 4 バイト
sdim命令 文字列型の変数・配列変数の確保 64 バイト〜
ddim命令 [HSP 3.0〜] 実数値型の変数・配列変数の確保
(マクロ定義でdimtype命令に置き換え)
8 バイト
ldim命令 [HSP 3.2〜] ラベル型の変数・配列変数の確保
(マクロ定義でdimtype命令に置き換え)
4 バイト

配列変数についてはHSPリファレンス「プログラミングマニュアル1・基本仕様ガイド (hspprog.htm) 」の 「2.スクリプト記述の基本→配列変数 」の項目をチェックあれ。下はHSPにおける変数のベーシックコード。

	a = 100	// 整数値型変数

	b = "HSP講座"	// 文字列型変数

	c = 3.14	// 実数値型変数

整数値型配列変数と文字列型配列変数のサンプル例です。

;	整数値の表示 (HSP3)

//	「dim value, 7」の宣言に相当
	value = 0, 1, 2, 3, 4, 5, 6

;	要素数分だけ繰り返す
	foreach value
		mes value(cnt) * 10
	loop
;	曜日文字列の表示 (HSP3)

//	「sdim youbi, 64, 7」の宣言に相当
	youbi = "日", "月", "火", "水", "木", "金", "土"

	mes "曜日番号: "+gettime(2)
	mes "きょうは "+youbi.gettime(2)+" 曜日だよ〜ん。"

用意した配列変数の要素数を超えている

たとえば、下のように変数valueを要素数5で確保したとすると、変数「value.0〜value.4」の範囲を利用できる ことになります。「value.5」は存在しないためエラーです。

	dim value, 5

	mes value.5	// ← エラー

また、HSPは代入式で配列変数(1次元のみ)を確保できます。これは「dim kazu, 4」を宣言したのに相当し、 「kazu.0〜kazu.3」の範囲です。(いわゆる変数の自動バッファ確保機能が働く)

	kazu = 15, 20, 32, 46

	mes kazu.2
	mes kazu.6	// ← エラー

要素にありえないマイナス値が指定された場合もエラーです。

	kazu = 15, 20, 32, 46

	i = 3
	repeat
		mes kazu.i // ← ループ5回目でエラー
		i--
	loop

多次元配列変数(2次元〜4次元)は下みたいな感じでしょうか。とにかく要素数が溢れてないかチェック することをオススメします。

;	4次元
	dim value, 10, 10, 10, 10

//	要素のMax
	value.9.9.9.9 = 500

//	従来の書式
	mes value.9.9.9.9

//	HSP3よりサポートした書式 (コチラの方が分かりやすい)
	mes value(9, 9, 9, 9)

そもそも配列変数を確保してない

上では明示的に配列変数を確保するHSPのコード(dim命令・sdim命令、代入処理)が存在しますが、確保する処理 すら用意してない場合はエラーになります。

たとえば、下の「value」変数は要素0は自動的に確保されますが、要素1、2、・・・は存在すらしないためエラーです。

	mes value.0

	mes value.2	// エラー

変数の型が変わってしまってる

これはちょっとした盲点ですかいな。数値型、文字列型、実数値型の宣言を行った後に異なる型のものを 代入してしまうと、最初の宣言は実質的に無意味になります。(HSP3ではvartype関数を利用してスクリプト上 で変数の型をチェックできます)

//	数値型配列変数
	dim value, 5

//	文字列型で初期化してしまう
	value = "77"

	mes value.4	// ← エラー

上のような場合はint関数を利用して数値へと変換します。

//	実数値配列変数
	ddim value, 5

//	整数値型で初期化してしまう
	value = 1

	mes value.4	// ← エラー

HSP3の仕様である『計算する最初の項に合わせて、後の項が型変換されます』のため、上のような場合は小数点 数値を明示的に指定して、型が変わってしまわないようにします。(0.0を加算、1.0を乗算、double関数の利用)

その他

・ddim命令はhspdef.asファイルでマクロ定義されてるもの(実体はdimtype命令)なので、HSPスクリプトエディタ の[HSP]→[HSP拡張マクロを使用する]にチェックが入ってないと「エラー2(文法が間違っています)」です。

☆デバッグウィンドウを見よう

HSPスクリプトエディタに実装されてるデバッグウィンドウを活用しましょう。 変数タブで個々の変数の中身(状態、サイズ)をチェックできます。その際、下の[配列変数]オプションを有効に すれば、要素ごとの中身もチェックできます。

(番外編)文字列型配列変数の保存

文字列型の配列変数をbsave命令で保存しても1番目の要素しか出力されません。そのため、HSPには付属する 「hsp3util.as」モジュールにarraysave命令、arrayload命令というモジュール命令も用意されてます。この モジュール命令では要素の区切りとして改行処理を施してます。

ここでは、NULL文字($00)を区切りとしたものです。まずは出力サンプルコード。(いちおう超簡易的な暗号化処理も用意)

//	文字列型配列変数の出力保存 (by Kpan)

;	出力用データを格納するバッファの確保
;	(バッファオーバーフローしないよう要サイズ調整必須)
	sdim buf, 128

;	保存する配列変数
	string = "プログラミング", "HSP3", "配列変数", "保存すーるする"

	i = 0
	foreach string
;		文字列の書き出し
		poke buf, i, string.cnt
		i + strsize

;		NULL文字の書き出し
		poke buf, i, $00
		i++
	loop

;	暗号化
//	gosub *encode

;	保存
	bsave "hogehoge.bin", buf, i - 1
	mes "done ("+strsize+" バイト)"
	stop

*encode
	randomize 1234	// マジックナンバーとして任意の数値
	repeat i - 1
		poke buf, cnt, peek(buf, cnt) ^ rnd($100)
	loop

	return

そして、これを逆に読み込むサンプルコード。ファイルの存在有無は省略してます。

//	出力したファイルの読み込み (by Kpan)

;	取得した結果の文字列を代入する文字列型配列変数
;	(パフォーマンスを落としたくないなら要確保)
	sdim kekka, 64, 5

	notesel data
	noteload "hogehoge.bin"

;	複合化
//	gosub *decode

	i = 0
	repeat
;		ヘルプ説明にあるように「00というコード」で切り出し代入
		getstr kekka.cnt, data, i
		if strsize = 0 : break
		i + strsize + 1
	loop

;	取得結果の文字列表示
	foreach kekka
		mes kekka.cnt
	loop
	stop

*decode
	randomize 1234	// 指定したマジックナンバー
	repeat strsize
		poke data, cnt, peek(data, cnt) ^ rnd($100)
	loop

	return

キーワード de HSP

HSPミニ講座

★ Yahoo!経由用ページ : ファイル | フォルダ | メニュー | マウス | ウィンドウ | オブジェクト | 文字列 | システム | 関数 | sendmsg命令 | その他 | サイトマップ | リンク