〜 テキスト 〜
全角英数を半角に変換

HSPの文字コードはシフトJISです。
シフトJISの半角英字Aは65、Bは66、Cは67…Zは90が割り振られています。 また、小文字半角aは97、bは98、cは99…zは122が割り振られています。 一方の全角英字Aは24706、Bは24962、Cは25218…Zは31106です。 全角小文字は33154から始まり、bは33410、cは33666…zは39554となってます。 一見すると、全角はバラバラのように思えますが、256ずつ規則的に増えて行っています。 これは2バイト文字の上位バイト(下から数えて9ビット目)が1ずつ増えて行っているためです。 数値も同様に、半角が0は49、1は50、2は51…9は57となっているのに対し、 全角0は20610、1は20866、2は21122…9は22658となっています。 この法則さえ分かってしまえば、変換することは容易です。 全角から半角への変換は、そのままのサイズか元のサイズより小さくなるだけですから、 元の変数サイズと同じサイズだけ確保しておけば問題ないでしょう(編集しない場合)。 API関数LCMapStringを用いて変換したい方は、コチラを利用してみてください。

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

getvarsize 変数
変数指定変数のサイズがstatにセットされる。

hankaku 書込先変数, 読込元変数, タイプ
書込先変数変換したテキストを代入する文字列型の変数を指定する。
statに-1(範囲外)、0(半角)、1(全角1バイト目)、2(全角2バイト目)のいずれかがセットされる。
内部でwordchk命令とgetvarsize命令を使用しているため、
hankaku命令の前にwordchk命令とgetvarsize命令を定義すること!
読込元変数変換したい文字列型の変数を指定する。
タイプ変換タイプ(0:半角へ変換 1:全角へ変換)を指定する。

 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
#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 getvarsize val
	mref pval, 1024             // PVAL構造体
	mref stt, 64                // stat
	stt = 4
	repeat 4, 2
		if pval.cnt = 0 : break
		stt = stt * pval.cnt
	loop
	return

#deffunc hankaku val, val
	mref rstr, 24 : mref string, 25
	strlen i, string
	sample = "09AZaz"       // 全角変換対象の代表
	sa = 31, 31, 32               // 全角と半角のコード差(数値, 英大字, 英小字)
	getvarsize rstr : size = stat // 保存先変数サイズを取得
	memset rstr, , size
	repeat i
		wordchk string, cnt
		if (stat = -1) || (type < 0) || (type > 1) {
			break
		} else {
			strlen i, rstr
			if i + stat + 1 >= size : break // オーバーフロー防止
			// 対象文字が全角
			if stat {
			  wpeek chk, string, cnt
			  repeat 3
			    // 変換対象範囲内なら変換
			    wpeek compare, sample, cnt * 4 : wpeek compare.1, sample, cnt * 4 + 2
			    if (chk >= compare) && (chk <= compare.1) {
			      poke rstr, i, (chk >> 8) - sa.cnt
			      chk = -1 // 変換したことを示すフラグ
			      break
			    }
			  loop
			  // 未変換なら、元の文字列を送る
			  if chk ! -1 : wpoke rstr, i, chk
			  // 2バイト進める
			  continue cnt + 2
			// 対象文字が半角
			} else {
			  peek chk, string, cnt
			  poke rstr, i, chk
			}
		}
	loop
	return
#global

	sdim data, 128, 2 // 代入先変数は大きめに確保しておくこと!
	data = "ABCabc012あいうABCabc012わをんxyz890XYZXYZ890xyz"
	mes "元の文字列 " + data
	hankaku data.1, data.0 // 半角英数へ
	mes "半角へ変換 " + data.1
	stop

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

結果 = hankaku(変数, タイプ)
結果取り出した文字列の格納先を指定する。
内部でwordchk命令を使用しているため、hankaku命令の前にwordchk命令を定義すること!
変数変換対象の文字列が格納されている変数を指定する。
タイプ変換タイプ(0:半角へ変換 1:全角へ変換)を指定する。

 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
#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 hankaku var string, local rstr, local sample, local sa
	sdim rstr, (2 - (type = 0)) * strlen(string) // 0:元のサイズ分を確保 1:元のサイズの2倍分を確保
	sample = "09AZaz"                      // 全角変換対象の代表
	sa = 31, 31, 32                              // 全角と半角のコード差(数値, 英大字, 英小字)
	repeat strlen(string)
		if wordchk(string, cnt) = -1 || type < 0 || type > 1 {
			break
		} else {
			// 対象文字が全角
			if stat {
			  chk = wpeek(string, cnt)
			  repeat length(sa)
			    // 変換対象範囲内なら変換
			    if chk >= wpeek(sample, cnt * 4) && chk <= wpeek(sample, cnt * 4 + 2) {
			      poke rstr, strlen(rstr), (chk >> 8) - sa.cnt
			      chk = -1 // 変換したことを示すフラグ
			      break
			    }
			  loop
			  // 未変換なら、元の文字列を送る
			  if chk ! -1 : wpoke rstr, strlen(rstr), chk
			  // 2バイト進める
			  continue cnt + 2
			// 対象文字が半角
			} else {
			  poke rstr, strlen(rstr), peek(string, cnt)
			}
		}
	loop
	return rstr
#global

	sdim data, 128
	data = "ABCabc012あいうABCabc012わをんxyz890XYZXYZ890xyz"
	mes "元の文字列 " + data
	mes "半角へ変換 " + hankaku(data) // 半角英数へ