ポク太郎です。
プログラム中、変数定義が面倒な際にフィールドデータを作ります。フィールドデータとは以下のようなもの。
フィールドデータ…カンマ等で区切ったデータ:tarou,hanako,jirou,pokutaro
このように整理しておくと変数を減らせます。昔触った環境に便利な関数があったのでそれを移植します。
関数の仕様は
以下の関数を作成しようとしています。
フィールドデータ:txt=tarou,hanako,jirou,pokutaro
があったときに、
N=nthc(txt,”,”)とすると、4を返す関数(フィールドの数)
T=nthf(txt,”,”,3)とすると、“jirou”を返す関数(フィールドの3番目)
あまりに巨大なフィールドを渡すとスピードが出ませんが、UWSCで鬼計算はしないと思いますので。
C言語のstrstr関数を移植
準備としてC言語のstring.hからstrstr関数を移植。これから作る自作関数中から呼び出して使用します。
C言語strstr関数仕様:引数txt中から引数schを検索し、schより後ろの文字列を返す関数。
FUNCTION strstr(txt,sch)
//txt中にschが無い、txtよりschが長い場合""空白が返される
r=""
FOR i=1 TO LENGTH(txt)
search=COPY(txt,i,LENGTH(sch))
IF (search=sch)
r=COPY(txt,i)
BREAK
ENDIF
NEXT
RESULT=r
FEND
1,12行目 | 1 12 |
FUNCTION strstr(txt,sch) FEND |
strstr(txt,sch)関数宣言 引数txt中からschを検索し、schより後ろの文字列を返す関数。(C言語仕様) |
||
3行目 | 3 | r=““ |
戻り値として使用する変数rの初期化。 | ||
4,10行目 | 4 10 |
FOR i=1 TO LENGTH(txt) NEXT |
引数txtを1番目から(文字数)番目までスキャンするためのループ。 | ||
5行目 | 5 | search=COPY(txt,i,LENGTH(sch)) |
変数searchにi番目から(引数schの文字数)個を取り出して代入。 COPY(DT,N1,N2):DTのN1番目の文字からN2個の文字列を返すUWSC標準関数。 |
||
6~9行目 | 6 7 8 9 |
IF (search=sch) r=COPY(txt,i) BREAK ENDIF |
もし5行目で代入したsearchと引数schが等しいなら、 変数rに引数txtのi番目から引数txtの最後までを代入。(UWSCのCOPY関数は第3引数を省略すると最後までとなる) BREAKはループを出ろというUWSCの命令。 |
||
11行目 | 11 | RESULT=r |
関数の戻り値として変数rを返す。 |
フィールドの数を返すnthc関数
ループ命令を使ってフィールドの中身をスキャンするので、フィールドの数をすぐに得られるようにします。その数を返すのがnthc関数。
FUNCTION nthc(txt,spr)
n=1
s=txt
IF strstr(s,spr)=""
n=0
ELSE
WHILE (0=0)
s=strstr(s,spr)
s=COPY(s,LENGTH(spr)+1)
n=n+1
IF strstr(s,spr)=""
BREAK
ENDIF
WEND
ENDIF
RESULT=n
FEND
1,17行目 | 1 17 |
FUNCTION nthc(txt,spr) FEND |
nthc(txt,spr)関数宣言: 引数txt(フィールドデータ)に引数spr(セパレータ)で区切られたフィールドがいくつあるかを返す関数。 |
||
2,3行目 | 2 3 |
n=1 s=txt |
使用する変数の初期化。 変数nはフィールドの数を数えるのに使用。 変数sはフィールドデータを調べるための文字列として使用。 |
||
4,6,15行目 | 4 6 15 |
IF strstr(s,spr)=““ ELSE ENDIF |
条件分岐。フィールドデータにセパレータが含まれてないかどうかを調べる。 | ||
5行目 | 5 | n=0 |
○⇒(フィールドデータにセパレータが含まれてない) 変数nに0を代入し、16行目へ。 |
||
7,11~14行目 | 7 11 12 13 14 |
WHILE (0=0) IF strstr(s,spr)=““ BREAK ENDIF WEND |
×⇒(フィールドデータにセパレータが含まれている) 8~10行目のループへと突入。 ループ条件を0=0としてあるので、常に成り立ち無限ループとなるが、(WHILE (1)と書く人が多いかも。) BREAK条件を、strstr関数を実行した結果変数sが空白となったとき、として制御する。(8行目を通るたびに変数sは削られていくことに注目。) |
||
8~10行目 | 8 9 10 |
s=strstr(s,spr) s=COPY(s,LENGTH(spr)+1) n=n+1 |
この部分を通るたびに1つ後のセパレータの次のデータを先頭に持ってくるためのルーチン。 変数sにstrstr関数の戻り値を代入。 8行目を通るたびに変数sはセパレータを先頭とする文字列に置き換わっていく。 9行目で変数sの先頭にあるセパレータ部分を取り除く。(UWSCのCOPY関数は第3引数を省略すると最後までとなる) 10行目の変数nはフィールドの数をなのでここでインクリメント。 |
||
16行目 | 16 | RESULT=n |
関数の戻り値として変数nを返す。 |
指定したフィールドのデータを返すnthf関数
実際にフィールドデータを取り出すnthf関数。引数として区切りの文字とn番目を渡します。
FUNCTION nthf(txt,spr,n)
i=0
tmp=""
nlast=nthc(txt,spr)
r=""
IF (n<1)
ELSEIF (txt="")
ELSEIF (strstr(txt,spr)="")
ELSEIF (n>nlast)
ELSE
s=txt
WHILE (0=0)
tmp=s
s=strstr(s,spr)
i=i+1
IF (i=n)
n1=LENGTH(tmp)
n2=LENGTH(s)
r=COPY(tmp,1,n1-n2)
BREAK
ELSE
s=COPY(s,LENGTH(spr)+1)
ENDIF
IF s=""
BREAK
ENDIF
WEND
ENDIF
RESULT=r
FEND
1,30行目 | 1 30 |
FUNCTION nthf(txt,spr,n) FEND |
nthf(txt,spr,n)関数宣言: 引数spr(セパレータ)で区切られた引数txt(フィールドデータ)から引数n番目のデータを返す関数。 |
||
2~5行目 | 2 3 4 5 |
i=0 tmp=““ nlast=nthc(txt,spr) r=““ |
使用する変数の初期化。 変数iはフィールドの数を数えるのに使用。 変数tmpは変数sを退避するため一時的に使用。 変数nlastはフィールドデータの数を代入。 変数rは関数の戻り値を記憶しておくために使用。初期値として空白を入れておく。 |
||
6~10,28行目 | 6 7 8 9 10 28 |
IF (n<1) ELSEIF (txt=““) ELSEIF (strstr(txt,spr)=““) ELSEIF (n>nlast) ELSE ENDIF |
条件分岐いろいろ:面倒なので最初に弾ける条件は弾いてしまいます。 5行目で変数rに空白を代入してあるので弾かれた条件ではそのまま29行目で空白を関数の引数として返します。 6行目: 0番目が指定された ⇒戻り値に空白返す。 7行目: フィールドデータとして空白が渡された ⇒戻り値に空白返す。 8行目: フィールドデータ中にセパレータが含まれてなかった ⇒戻り値に空白返す。 9行目: フィールドの数より大きなnを指定された ⇒戻り値に空白返す。 ×⇒(上記すべて成り立たなかった) 11~27行目を実行。 |
||
11行目 | 11 | s=txt |
使用する変数の初期化。 変数sはフィールドデータを調べるための文字列として使用。初期値は引数txt。 |
||
12,24~27行目 | 12 24 25 26 27 |
WHILE (0=0) IF s=““ BREAK ENDIF WEND |
nthc関数の7,11~14行目と同じ条件のループ。(14行目を通るたびに変数sは削られていくことに注目。) | ||
13~15行目 | 13 14 15 |
tmp=s s=strstr(s,spr) i=i+1 |
13行目: 変数tmpに変数sを一時的に退避。 14行目: 変数sにstrstr関数の戻り値を代入。 通るたびに変数sはセパレータを先頭とする文字列に置き換わっていく。 15行目: 変数iはフィールドの数をなのでここでインクリメント。 |
||
16~23行目 | 16 17 18 19 20 21 22 23 |
IF (i=n) n1=LENGTH(tmp) n2=LENGTH(s) r=COPY(tmp,1,n1–n2) BREAK ELSE s=COPY(s,LENGTH(spr)+1) ENDIF |
条件:もしフィールドの数を数えている変数iと引数として指定された引数nが同じなら、(目的のデータが見つかったなら) ○⇒ 17行目: 退避していた変数tmpの文字数を変数n1に代入。 18行目: 現在の変数sの文字数を変数n2に代入。 19行目: 変数rに目的のフィールドの文字列を代入。 (退避していた変数tmpの1文字目から(n1-n2)個がそれに相当します。) 20行目:見つかったのでループを抜ける。 ×⇒ 22行目: 変数sの(セパレータの文字数+1)番目からの最後までを変数sに代入。 (先頭にあったセパレータを取り除いたものを変数sとして再度13行目のループ先頭へ戻る。) (UWSCのCOPY関数は第3引数を省略すると最後までとなる) |
||
29行目 | 29 | RESULT=r |
関数の戻り値として変数rを返す。 |
フィールドデータを扱う関数動作確認
動作確認プログラムがこちら。
PRINT "nthc kotae ="+nthc("abc[]defghi[]jklm[]nop","[]")
PRINT "nthc kotae ="+nthc("[]defghi[]jklm[]nop","[]")
PRINT "nthc kotae ="+nthc("abc[]defghi[]jklm[]","[]")
PRINT "---------------------------"
FOR i=-1 TO 5
PRINT "nthf kotae "+i+"="+nthf("abc[]defghi[]jklm[]nop","[]",i)
NEXT
PRINT "---------------------------"
FOR i=-1 TO 5
PRINT "nthf kotae "+i+"="+nthf("[]defghi[]jklm[]","[]",i)
NEXT
1~3行目 | 1 2 3 |
PRINT “nthc kotae =“+nthc(“abc[]defghi[]jklm[]nop“,“[]“) PRINT “nthc kotae =“+nthc(“[]defghi[]jklm[]nop“,“[]“) PRINT “nthc kotae =“+nthc(“abc[]defghi[]jklm[]“,“[]“) |
nthc関数の動作確認です。 セパレータとして”[]“(2文字)を渡したときに、先頭と終端がセパレータではない、先頭がセパレータでである、終端がセパレータであるフィールドデータを渡して正常にカウントするか確認します。 |
||
5~7行目 | 5 6 7 |
FOR i=–1 TO 5 PRINT “nthf kotae “+i+“=“+nthf(“abc[]defghi[]jklm[]nop“,“[]“,i) NEXT |
nthf関数の動作確認です。 先頭・終端がセパレータでないフィールドデータを与えたときの挙動を確認します。(n番目の指定は-1~5までやってみます。) |
||
9~11行目 | 9 10 11 |
FOR i=–1 TO 5 PRINT “nthf kotae “+i+“=“+nthf(“[]defghi[]jklm[]“,“[]“,i) NEXT |
nthf関数の動作確認(変則なフィールドデータ)です。 先頭・終端がセパレータであるフィールドデータを与えたときの挙動を確認します。(n番目の指定は-1~5までやってみます。) |
||
4,8行目 | 4 8 |
PRINT “–––––––––––––––––––––––––––“ PRINT “–––––––––––––––––––––––––––“ |
結果を見やすくするための区切りを表示。 |
結果は、
nthc kotae =4 nthc kotae =4 nthc kotae =4 --------------------------- nthf kotae -1= nthf kotae 0= nthf kotae 1=abc nthf kotae 2=defghi nthf kotae 3=jklm nthf kotae 4=nop nthf kotae 5= --------------------------- nthf kotae -1= nthf kotae 0= nthf kotae 1= nthf kotae 2=defghi nthf kotae 3=jklm nthf kotae 4= nthf kotae 5=
一応思い通りの仕様の動きができました。
文字列操作あれこれMID、LEFT、RIGHT、LEN | 文字列中に指定ワードあるなし判定関数 | 現在のタイムスタンプ文字列を返す関数 | カンマ等で区切られたフィールドデータを扱う関数 |
本記事の内容は以下でした。
○フィールドデータの数を返す関数
○フィールドデータの数を返す関数
戻値(int)=nthc(txt,spr)
○指定されたフィールドデータを返す関数
戻値(str)=nthf(txt,spr,n)
コメント