〜 テキスト 〜
文字数指定版のstrmid命令,getstr命令

Windows版HSP標準文字コードはシフトJISですので、使用文字により半角全角が混合します。
HSPに標準の文字列操作命令が幾つも用意されていますが、
パラメータに指定する文字位置・文字数はいずれもバイト単位であり、利用者に入力してもらったテキスト、
またはファイルから読み込んだテキストの一部を操作する時は、判別する必要があります。
X文字目からY文字取り出したり、検索したい方の為に参考スクリプトを書いてみました。
使い方は標準の物と同じで、異なるのはバイト単位の位置・数が文字数に変わっただけです。
	

wordchk 対象変数, 位置
対象変数判別したい文字列の入った変数を指定する。
statに-1(範囲外)、0(半角)、1(全角)のいずれかがセットされる。
位置指定変数の位置をバイト単位で指定する。

bytechk 対象変数, 位置
対象変数判別したい文字列の入った変数を指定する。
statに-1(範囲外)、0(半角)、1(全角1バイト目)、2(全角2バイト目)のいずれかがセットされる。
内部でwordchk命令を使用しているため、bytechk命令の前にwordchk命令を定義すること!
位置指定変数の位置をバイト単位で指定する。

strmid2 読出先変数, 取出元変数, インデクス, 文字数
読出先変数取り出した文字列を格納する変数を指定する。
内部でwordchk命令を使用しているため、strmid2命令の前にwordchk命令を定義すること!
取出元変数取り出す元の文字列が格納されている変数を指定する。
インデクス取り出し始めのインデクスを指定する。
文字数取り出す文字数を指定する。

getstr2 読出先変数, 取出元変数, インデクス, 区切りコード
読出先変数取り出した文字列を格納する変数を指定する。
内部でwordchk命令を使用しているため、getstr2命令の前にwordchk命令を定義すること!
取出元変数取り出す元の文字列が格納されている変数を指定する。
インデクス取り出し始めのインデクスを指定する。
区切りコード区切りキャラクタのASCIIコードを指定する。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#module
#deffunc wordchk val, int
	mref txt, 24 : mref ichi, 1
	mref stt, 64
	peek chk, txt, ichi
	if chk = 0 : stt = -1 : return						// 範囲外
	if (chk > 128 & (chk < 160)) | (chk > 223) : stt = 1 : else : stt = 0	// 1byte=0 2byte=1
	return

#deffunc bytechk val, int
	mref s, 24 : mref p, 1
	mref stt, 64
	// 対象コードをチェックする
	wordchk s, p
	code = stat
	if code = -1 : return // 範囲外
	// 対象コードより前を確認
	repeat , 1
		wordchk s, p - cnt
		// 全てをチェックし終わったか、1バイト文字が来た
		if (stat = -1) || (stat = 0) {
			if code = 0 {
			  // 1バイト領域になったのが奇数回なら半角、偶数回なら全角2バイト目
			  if cnt \ 2 = 1 : stt = 0 : else : stt = 2
			} else {
			  // 1バイト領域になったのが奇数回なら全角1バイト目、偶数回なら全角2バイト目
			  if cnt \ 2 = 1 : stt = 1 : else : stt = 2
			}
			break
		}
	loop
	return

#deffunc strmid2 val, val, int, int
	mref result, 24 : mref txt, 25 : mref start, 2 : mref len, 3
	if start >= 0 {
		// 開始,終了位置を取得
		i = 0						// 要素カウンタ
		j = 0, 0					// 開始位置, 終了位置
		k = start, len					// 比較用開始位置, 比較用終了位置
		repeat 2
			repeat , j
			  if j.i >= k.i : j.i = cnt : break	// 指定位置まで来たらブレイク
			  wordchk txt, cnt
			  if stat = -1 : j.i = cnt : break	// 範囲外
			  j.i++
			  if stat : continue cnt + 2		// 全角文字は2バイト進める
			loop
			i++
		loop
		// データ取り出し
		strmid result, txt, j.0, j.1 - j.0
	} else {
		strlen i, txt					// 後ろから調べる為にテキストサイズ取得
		j = 0						// 文字数カウンタ
		repeat i, 1
			bytechk txt, i - cnt
			if (stat = -1) || j >= len {		// 指定位置まで来たらブレイク
			  k = i - cnt + 1			// 開始位置を決定
			  break
			}
			j++
			if stat = 2 : continue cnt + 2
		loop
		strmid result, txt, k, i - k
	}
	return

#deffunc getstr2 val, val, int, int
	mref result, 24 : mref txt, 25 : mref start, 2 : mref code, 3
	// 開始位置を取得
	i = 0
	repeat
		wordchk txt, cnt
		if stat = -1 : i = cnt : break
		i++
		if i > start : i = cnt : break
		if stat = 1 : continue cnt + 2
	loop
	// 指定コードまでを抜き出す
	getstr result, txt, i, code
	return
#global

	string = "abあcdeいfうghえijklおmnoかpqきrstくuvwけこxyz"
	strmid2 gotten, string, 4, 5
	mes "元のテキスト     " + string
	mes "4文字目から5文字  " + gotten
	strmid2 gotten, string, -1, 7
	mes "後ろから7文字    " + gotten
	mes
	string = "あいう\\うえお\\かきく\\けこ"
	getstr2 gotten , string, 9, '\\'
	mes "元のテキスト     " + string
	mes "9文字目以降の'\\'まで " + gotten
	stop

結果 = wordchk(対象変数, 位置)
結果-1(範囲外)、0(半角)、1(全角)のいずれかがセットされる。
対象変数判別したい文字列の入った変数を指定する。
位置指定変数の位置をバイト単位で指定する。

結果 = bytechk(対象変数, 位置)
結果-1(範囲外)、0(半角)、1(全角1バイト目)、2(全角2バイト目)のいずれかがセットされる。
内部でwordchk命令を使用しているため、bytechk命令の前にwordchk命令を定義すること!
対象変数判別したい文字列の入った変数を指定する。
位置指定変数の位置をバイト単位で指定する。

結果 = strmid2(取出元変数, インデクス, 文字数)
結果取り出した文字列の格納先を指定する。
内部でwordchk命令を使用しているため、strmid2命令の前にwordchk命令を定義すること!
取出元変数取り出す元の文字列が格納されている変数を指定する。
インデクス取り出し始めのインデクスを指定する。
文字数取り出す文字数を指定する。

getstr2 読出先変数, 取出元変数, インデクス, 区切りコード
読出先変数取り出した文字列を格納する変数を指定する。
内部でwordchk命令を使用しているため、getstr2命令の前にwordchk命令を定義すること!
取出元変数取り出す元の文字列が格納されている変数を指定する。
インデクス取り出し始めのインデクスを指定する。
区切りコード区切りキャラクタのASCIIコードを指定する。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#module
#defcfunc wordchk var s, int ichi
	if ichi < 0 : return -1					// 範囲外
	chk = peek(s, ichi)
	if (chk > 128 & chk < 160) | chk > 223 : return 1	// 2byte=1
	if chk = 0 : return -1 : else : return 0		// 1byte=0 範囲外=-1

#defcfunc bytechk var txt, int p, local code, local stt
	// 対象コードをチェックする
	code = wordchk(txt, p)
	if code = -1 : return // 範囲外
	// 対象コードより前を確認
	repeat , 1
		stt = wordchk(txt, p - cnt)
		// 全てをチェックし終わったか、1バイト文字が来た
		if (stt = -1) | (stt = 0) {
			if code = 0 {
			  // 1バイト領域になったのが奇数回なら半角、偶数回なら全角2バイト目
			  if cnt \ 2 = 1 : stt = 0 : else : stt = 2
			} else {
			  // 1バイト領域になったのが奇数回なら全角1バイト目、偶数回なら全角2バイト目
			  if cnt \ 2 = 1 : stt = 1 : else : stt = 2
			}
			break
		}
	loop
	return stt

#defcfunc strmid2 var v, int start, int len, local i, local j, local k
	if start >= 0 {
		// 開始,終了位置を取得
		j = 0, 0						// 開始位置, 終了位置
		k = start, len						// 比較用開始位置, 比較用終了位置
		repeat 2
			repeat , j
			  if j.i >= k.i : j.i = cnt : break		// 指定位置まで来たらブレイク
			  if wordchk(v, cnt) = -1 : j.i = cnt : break	// 範囲外
			  j.i++
			  if stat : continue cnt + 2			// 全角文字は2バイト進める
			loop
			i++
		loop
		// データ取り出し
		return strmid(v, j.0, j.1 - j.0)
	} else {
		i = strlen(v)						// 後ろから調べる為に取得
		j = 0							// 文字数カウンタ
		repeat i, 1
			if (bytechk(v, i - cnt) = -1) || j >= len {	// 指定位置まで来たらブレイク
			  k = i - cnt + 1				// 開始位置を決定
			  break
			}
			j++
			if stat = 2 : continue cnt + 2
		loop
		// データ取り出し
		return strmid(v, k, i - k)
	}

#deffunc getstr2 var result, var v, int start, int ascii, local i
	// 開始位置を取得
	repeat
		if wordchk(v, cnt) = -1 : i = cnt : break
		i++
		if i > start : i = cnt : break
		if stat = 1 : continue cnt + 2
	loop
	// 指定コードまでを抜き出す
	getstr result, v, i, ascii
	return
#global

	string = "abあcdeいfうghえijklおmnoかpqきrstくuvwけこxyz"
	mes "元のテキスト     " + string
	mes "4文字目から5文字  " + strmid2(string, 4, 5)  // 通常のstrmid命令の場合「cdeい」
	mes "後ろから7文字    " + strmid2(string, -1, 7) // 通常のstrmid命令の場合「けこxyz」
	mes
	string = "あいう\\うえお\\かきく\\けこ"
	getstr2 gotten , string, 9, '\\'
	mes "元のテキスト     " + string
	mes "9文字目以降の'\\'まで " + gotten // 通常のgetstr命令の場合「えお」