split命令を追加してみる

IRC

23:10	f_the_darudaru	perlの my( $a,$b,$c ) = split( /,/ , $data); 見たいな記述の導入を検討師弟t抱けると幸いです(鬼
	f_the_darudaru	他人事だからいえることを堂々と、血も涙も無い感じで・・・!!
23:12	fujidig	わー><
	f_the_darudaru	でも、この記述は、初心者niha大変な武器になると思うのですよ
23:13	fujidig	多重代入はRubyにもあるから知ってますんですけど、配列オブジェクト(値)がないと駄目じゃないですかねえ
	As	ひとつのモジュールに、現在作成されているモジュール型変数の数を取得する関数を導入してほしいですw
23:14	f_the_darudaru	フウム
	elfizm	C++でいう静的メンバで解決できそう?
23:15	fujidig	modinitでcount++してmodtermでcount--とか。
	f_the_darudaru	むしろ、splitの命令で、split( "分割する記号" , 受け取る変数1,受け取る変数2,受け取る変数3,....)mitaina
	f_the_darudaru	見たいな書き方ならできるかも?
	As	>>modinitでcount++してmodtermでcount--とか。 
23:16	As	その手があったか!!orz
	fujidig	うん、それなら出来そうだねえ。<split( "分割する記号" , 受け取る変数1,受け取る変数2,受け取る変数3,....)
	f_the_darudaru	おっと、元データが抜けた(笑
	elfizm	www
23:17	fujidig	strfでHSP初の可変長の関数を作ったばっかりだしw
	f_the_darudaru	可変長引数関数が出来たのなら、難しくは無い話ですな。
23:18	f_the_darudaru	時折、掲示板でも「noteloadで読み込んだデータを分割したい」とかあるので、良いかもしれません。
23:20	fujidig	配列変数で受け取る方が汎用性がある気がするんだけれど、、「一つ一つ別の変数で受け取る命令はあるのになんで配列で受け取る命令はないんだよ」ってなりそうな気も
23:21	f_the_darudaru	フム
	f_the_darudaru	では二通り(鬼
23:22	fujidig	うぎゃー

ということがあったので作ってみました。

diff -Naru openhsp.orig/hsp3/hsp3int.cpp openhsp/hsp3/hsp3int.cpp
--- openhsp.orig/hsp3/hsp3int.cpp	Fri Apr 04 22:21:34 2008
+++ openhsp/hsp3/hsp3int.cpp	Tue Apr 15 09:36:18 2008
@@ -511,6 +511,59 @@
 		note.ResumeLineDirect();
 		break;
 		}
+	case 0x2a:								// split
+		{
+		PVal *pval;
+		int aptr;
+		char *sptr;
+		char *sep;
+		char *newsptr;
+		int size;
+		int sep_len;
+		int n;
+		int is_last = 0;
+		
+		sptr = code_getvptr( &pval, &size );
+		if ( pval->flag != HSPVAR_FLAG_STR ) throw HSPERR_TYPE_MISMATCH;
+		sep = code_gets();
+		sep_len = strlen( sep );
+		
+		pval = NULL;
+		n = 0;
+		while (1) {
+			n ++;
+			newsptr = strstr2( sptr, sep );
+			if ( !is_last && *exinfo->npexflg & EXFLG_1 ) {
+				// 分割結果の数が格納する変数より多ければ最後の変数に配列で格納していく
+				// ただし最後の要素が a.2 のように要素指定があればそれ以降は全く格納しない
+				if ( aptr != 0 ) pval = NULL;
+				is_last = 1;
+				aptr = 0;
+			}
+			if ( is_last ) {
+				aptr ++;
+				if ( pval != NULL && aptr >= pval->len[1] ) {
+					if ( pval->len[2] != 0 ) throw HSPVAR_ERROR_ARRAYOVER;
+					HspVarCoreReDim( pval, 1, aptr+1 );
+				}
+			} else {
+				aptr = code_getva( &pval );
+			}
+			if ( pval != NULL ) {
+				code_setva( pval, aptr, HSPVAR_FLAG_STR, sptr );
+			}
+			if ( newsptr == NULL ) {
+				// 格納する変数の数が分割できた数より多ければ残った変数それぞれに空文字列を格納する
+				while( ( *exinfo->npexflg & EXFLG_1 ) == 0 ) {
+					aptr = code_getva( &pval );
+					code_setva( pval, aptr, HSPVAR_FLAG_STR, "" );
+				}
+				break;
+			}
+			if ( pval != NULL ) {
+				pval->offset = aptr;
+				((char *)HspVarCorePtr(pval))[newsptr - sptr] = '\0';
+			}
+			sptr = newsptr + sep_len;
+		}
+		ctx->stat = n;
+		break;
+		}
 
 	case 0x27:								// randomize
 #ifdef HSPWIN
diff -Naru openhsp.orig/hspcmp/hspcmd.cpp openhsp/hspcmp/hspcmd.cpp
--- openhsp.orig/hspcmp/hspcmd.cpp	Sat Mar 29 22:12:56 2008
+++ openhsp/hspcmp/hspcmd.cpp	Tue Apr 15 09:33:06 2008
@@ -97,6 +97,7 @@
 	"$027 8 randomize",				// (changed on ver3.0)
 	"$028 8 noteunsel",				// (changed on ver3.0)
 	"$029 8 noteget",				// (changed on ver2.55)
+	"$02a 8 split",                 // (3.2)
 
 	//	enhanced command (ver2.2)
 
OpenHSP
Copyright (C) 1997-2008, Onion Software/onitama, all rights reserved.
This software is provided by the copyright holders and contributors "as is" and
any express or implied warranties, including, but not limited to, the implied
warranties of merchantability and fitness for a particular purpose are disclaimed.

使い方

第一引数に元データ変数、第二引数にセパレータ文字列、第三引数以降に結果が入る変数を指定します。 stat にいくつ分割できたかが返ります。

buf = "tarou:18:male"
split buf, ":", name, age, sex
mes name
mes age
mes sex
mes stat
第三引数を指定せずにいくつ分割できたかだけをもらう
buf = "よそはよそ、うちはうち。そよそよ。ご飯をよそいなさい。"
split buf, "よそ"
mes buf
mes "上の文章に「よそ」は何個あるかな?"
mes "答えは"+(stat - 1)+"個"

文字列中に指定した文字列がいくつあるか数えることができます。

分割できた数の方が結果の変数の数より大きければ一番後ろに指定した変数に配列として入っていきます。
buf = "tarou:18:male"
split buf, ":", results
repeat stat
	mes results.cnt
loop