テキスト操作1
今までにテキストの連結や演算は行えていましたが、
逆である、既存のテキストの一部を取り出したり、編集することは出来ませんでした。
今回はそのやり方について説明します。

サイズ = strlen(調査対象変数)
サイズ取得した変数のバイト数。
調査対象変数サイズを調査する文字列型変数を指定する。
名前は、STRingLENgthからきていると思われます。 strlen関数は変数内のテキストサイズ(厳密にはNULLまでのバイト数)を返す関数です。 HSPの仕様として、テキスト操作命令の大半はこのNULLまでをテキストデータとして処理し、 NULLを間に挟んでいる場合はNULL以降のデータは読み取れないようになっています。 NULLとは以前にも触れたことのあるように、文字であって文字ではない制御文字の一種。 主に「存在しない無の状態」を表し、ASCIIコードは0番です。(ASCIIコードは後述参照。) 通常のテキストデータであれば、末端に文字列の終わりを示すNULLが1つ付けられるだけですが、 例えば画像や音楽ファイル等のバイナリデータには、テキストで言うところのあらゆる制御文字が入ります。 当然、NULL文字も複数入っているかもしれません。 このバイナリデータはテキストとして読み込んだり、編集することは通常ないでしょうが、 例えば、バイナリエディタというバイナリデータを編集するツールをHSPで作成する場合、 NULLまでしか処理できないこれらの命令・関数では特殊なやり方をしなければなりません。 そういう意味では不便といえば不便なのですが、 そのような処理をする必要がある割合は、しない割合に比べて圧倒的に低いので、 「NULLまでしか処理しない」ということを取り決めておいた方がやりやすくなります。 NULLまでしか処理しないというのは、テキスト処理速度の面で大きな意味を持っています。 例えば、1GBものテキストデータをクリアして表示する場合、 先頭にNULLを設定するだけで全てのデータが存在しないことを意味しますので、 メモリ上の全てのテキストをクリアするよりも圧倒的に速く処理できます。 そのような経緯で仕様になったのではないかと思われます。 文字数ではなくバイト数なので、ひらがなや漢字などの2バイト文字は2とカウントされます。
 1
 2
 3
	sdim s, 16
	s = "abcあいう"
	mes "変数s「" + s + "」には" + strlen(s) + "バイト入っています。"
次に、テキストの指定部分を取り出す(コピーする)関数を紹介します。
取得テキスト = strmid(取出元変数, 開始インデクス, 取出サイズ)
取得テキスト取出元変数から取出した文字列。
取出元変数対象の文字列型変数。
開始インデクス先頭を0としたバイト単位の開始位置。
取出サイズ開始インデクスから実際に取出す、バイト単位のサイズ。
strmid関数は、第1パラメータに対象の変数を指定し、第2パラメータで指定する位置から、 第3パラメータで指定するバイト数分の文字列を返す関数です。 第2パラメータの開始位置は、先頭を0として「全体サイズ−1」までのいずれかを指定することで、 その位置から抽出することになります。 −1(マイナス値)を指定すると、末端の文字から第3パラメータに指定したサイズ分を抽出します。 例えば「ultimate」と入った変数の開始位置を−1に、サイズを4とすると、「mate」となります。 開始位置が全体のサイズより大きい値を指定したり、 取出しサイズを同様に全体サイズ以上指定しても、エラーにはならず、最大サイズまでが取出されます。 取出しサイズにマイナスを指定してもエラーにはならず、空文字を返します。 2バイト文字を含んでいる時、2バイト文字の2バイトから検索開始したり、 2バイト文字の1バイト目までを検索対称にしていると、見覚えのない文字が取得されます。 全てが2バイト文字なら、偶数バイト位置から取得を始めて、偶数バイトを取出すことで問題ありませんが、 1バイト2バイトそれぞれを混合させていると厄介です。 回避策についてはもう少し先の章で扱いますのでしばらくお待ちください。
 1
 2
 3
 4
 5
 6
	s = "abcdefghijklmnopqrstuvwxyz"
	mes "1:" + strmid(s, 10, 10)
	mes "2:" + strmid(s, -1, 10)
	mes "3:" + strmid(s, 10, 99)
	mes "4:" + strmid(s, 99, 10)
	mes "5:" + strmid(s, 10, -1)
続いて、文字列内の特定文字列を検索する関数を紹介します。
インデクス = instr(検索対象変数, 開始インデクス, 検索文字列)
インデクス取得した位置。
検索対象変数検索元の文字列型変数を指定する。
開始インデクス先頭を0としたバイト単位の検索開始位置を指定する。
検索文字列検索する文字列を指定する。
第1パラメータに検索を行う文字列型変数を指定し、 第2パラメータにバイト単位の開始位置を、第3パラメータに実際に検索する文字列を指定することで、 開始位置を0としたインデクスを返します。見つからなかった場合は−1を返します。 文字列の先頭からのインデクスではなく、開始位置からのインデクスを返す点に注意してください。 例えば「ultimate」と入った変数の開始位置を1(lから)に、検索文字列が「mat」なら、3を返します。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
	sdim p3, 16
	p1 = "This site is Hot Soup Processor Beginner's Club."
	pos  50,  50 : mes "検索する文字列"
	pos 200,  50 : input p3, 100
	pos 350,  50 : button "検索", *search
	pos  50, 100 : mes "下記の文字列から検索を行います。"
	color 255
	pos  50, 120 : mes p1
	stop

*search
	p2 = 0 // 開始位置を先頭に設定する
	repeat
		i = instr(p1, p2, p3) // 指定位置から検索する
		if i = -1 : dialog "見つかりませんでした。" : break
		dialog "先頭から" + (p2 + i) + "バイト目に発見しました。\n引き続き検索しますか?", 2
		if stat = 7 : break
		p2 += i + 1 // 次回の開始位置を「今回+1」に設定する
	loop
半角・全角文字が混合している変数を検索する場合は注意が必要です。 例えば、全角「」の2バイト目を見るとASCIIコードが97となっており、 ASCIIコード97というのは、半角「a」と同じです。 変数に全角「」を含んでいて、半角「a」を検索すると該当してしまう場合がありうるのです。 正しく検索すれば問題はないのですが、全角文字の2バイト目(先頭から1バイト目)を基準として検索すると、 テキスト内に半角「a」を含んでいなくても−1を返さずに0が返ります。 対象の文字が半角文字なのか全角文字の2バイト目(先頭から1バイト目)なのかの判断は次章以降で。
 1
 2
	a="ABC"
	mes instr(a, 3, "a") // 半角小文字の「a」はないので−1となるはず…
次に、検索開始位置から特定文字までの文字列を取得する命令を紹介します。
getstr 保持変数, 取得元変数, インデクス, 区切り文字コード
保持変数取得したテキストを保持する変数を指定する。
取得元変数取得する対象の文字列型変数を指定する。
インデクス先頭を0として、取得開始位置をバイト単位で指定する。
区切り文字コード1バイトのデリミタをASCIIコードで指定する。
strmid関数の終了条件が文字数ではなく特定文字」に変わった形式の命令です。 getstr命令は、strmid関数とほぼ同じであるにもかかわらず、 なぜ関数ではなく「取得先の変数を指定するタイプの命令」なのでしょうか…? 同じ様に関数に出来そうですが、内部仕様がどうなっているのか知らないので何とも言えません。 さて、上に書いたように、strmid関数とほぼ同じでパラメータの設定の仕方も似ています。 取得を行うものですが、関数ではなく命令なので、第1パラメータは取得先の変数を指定します。 第2パラメータに抽出を行うテキストが入った変数を指定し、 第3パラメータは先頭を0バイト目とした、バイト数単位の開始位置を、 第4パラメータに1バイトの文字コードを指定します。 ASCIIコードはご存知でしょうか? ASCIIコードとは、アメリカの規格団体であるANSIが定めた「文字コードの体系」のことで、 NULL等の制御コードや数字・記号・アルファベット等、1バイトで128種類定義されています。 1バイトは最大で256パターン扱えるので、 定義されてない残りの128は国や企業が定めても良いことなっており、 日本では、この拡張領域に半角カナや、全角文字の先頭コードとして規格化しました。 文字とコードはバラバラに設定されているわけではなく、ある一定の法則に従っています。 「各文字がどのコードになるのか」は、ANSIの割り当てた制御文字以外の一覧を下記に載せておきます。
コード表0123456789
30  空白!"#$%&'
40()*+,-./01
5023456789:;
60<=>?@ABCDE
70FGHIJKLMNO
80PQRSTUVWXY
90Z[\]^_`abc
100defghijklm
110nopqrstuvw
120xyz{|}~   
最上段に0〜9、左端列に10刻みで30〜120が書いてあります。 この表の見方は、縦横の交わるところが、その文字のコードであることを示しています。 「¥」を例にすると、左端列は90、最上段は2、つまり「¥」は92であるということを示しています。 getstr命令を含む幾つかの命令や関数では、パラメータにASCIIコードを指定させる様になっていますが、 スクリプトにコードをそのまま書くと、後から見た時に何であったか判別しにくくなります。 HSPでは文字列の要領で、開始と終了に半角アポストロフィ「'」を配置することで、 置いた文字を文字コードとして扱うことが出来るようになりますが、 全角文字を指定しても自分の予想していた思い通りの数字は取得できないかもしれません。
1
	mes '\\' // ¥等は通常テキスト同様にエスケープすること!
getstr命令に話を戻しまして、第4パラメータは上記の方法を使う等して指定してください。 尚、getstr命令を使用して何らかのテキストが取得出来たら、 取得したテキストのバイト数+終了コード(NULL)分がシステム変数strsizeにセットされます。
 1
 2
 3
	txt = "HSPBC-Author:Ultimate/Satoshi"
	getstr get, txt, instr(txt, , ":") + 1, '/' // 「:」の次から「/」までを取り出す
	mes "取得サイズ:" + strsize + "\n取得テキスト:" + get
続いて、以前にTipsで同様の機能を実現していましたが、 HSP3.2から新しく標準命令として使えるようになったテキスト分割命令を紹介します。
split 分割元変数, 区切り文字列, 分割先変数…
分割元変数分割対象のテキストが格納された変数を指定する。
区切り文字列分割対象の区切りテキストを指定する。
分割先変数…分割した文字列の格納先変数を指定する。
分割数分変数を指定することで各変数にセット可能。
分割数よりも指定変数が少ない場合は配列変数として各要素にセットする。
getstr命令は区切り文字までのテキスト1個を取得するのに対し、 split命令は区切り文字列に分割して「区切り文字列数+1個」を取得するもの。 getstr命令と違って文字コードではなく、1バイト文字限定ではなくて文字列で指定可能です。 分割先変数パラメータは「split data, ",", csv1, csv2, csv3, csv4」のように複数個指定しますが、 4つに分割できるものでも「split data, ",", csv1, csv2」のように指定することも可能です。 この場合、csv1は通常変数のまま1つ目の分割テキスト、 後方の変数が配列になり、csv2.0に2つ目、csv2.1に3つ目、csv2.2に4つ目の分割テキストが入ります。
 1
 2
 3
 4
 5
	v = "分割先に指定した変数の個数よりも\n分割元変数の分割個数が多い場合は\n分割先を配列にして\n要素0から順に格納します"
	split v, "\n", ary
	foreach ary
		mes strf("%d. ", cnt) + ary.cnt
	loop
最後に、コチラも以前にTipsで同様の機能を実現していましたが、 HSP3.2から新しく標準命令として使えるようになった不要文字除去関数を紹介します。
受取先 = strtrim(除去対象変数, 除去タイプ, 除去文字コード)
受取先除去後テキストの受取先を指定する。
除去対象変数除去対象のテキストが格納された変数を指定する。
除去タイプ除去タイプ(0:両端, 1:左端, 2:右端, 3:全箇所対象)を指定する。
除去文字コード除去対象文字をASCIIコードで指定する。
strtrim関数は、String'sTrimmingの略で、文字列内の特定文字をトリミング(=除去)するというもの。 除去タイプには除去対象の位置を指定します。 0または省略すると、除去対象文字が両端に付いている場合に除去されます。 1を指定すると、除去対象文字がテキスト先頭に付いている場合に除去されます。 2を指定すると、除去対象文字がテキスト最後方に付いている場合に除去されます。 3を指定すると、位置に関係なくテキスト内に含まれている除去対象文字が除去されます。 除去文字コードはgetstr命令の区切り文字パラメータと同様に文字コードで指定しなければなりませんが、 strtrim関数は65535、つまり2バイト値までの範囲で指定可能となっているので、 半角文字コードだけでなく、全角文字コードも指定できます。 ただ、現時点では2バイト文字コードを取得する命令・関数を紹介していないので、 今回のサンプルでは半角文字を使って除去するようにしています。 3・4行目に同じ処理が書かれており、4行目をコメントアウトしているのは、 使用しているHSPのバージョンによって変えて欲しいからです。 HSP3.1以前のstrf関数は書式フォーマットに1つしか指定できませんので、 3行目の書き方をすればエラーになって動作させることが出来ません。 3行目をコメントアウトして、4行目のコメントを表示させるように変更してください。
 1
 2
 3
 4
 5
	hspbc = " Hot Soup Processor Beginner's Club "
	repeat 4
		mes strf("type=%d [%s]", cnt, strtrim(hspbc, cnt))   // HSP3.2以降用
//		mes "type=" + cnt + " [" + strtrim(hspbc, cnt) + "]" // HSP3.1以前用
	loop
以上でテキスト操作命令を終了します。 この他にもテキスト操作命令はありますが、若干タイプが異なるので30章で説明します。