HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2006
1112
猫太strmidのマルチバイト対応方法について7解決


猫太

リンク

2006/11/12(Sun) 11:41:17|NO.3414

こんにちは、お久しぶりです。
猫太です。

ちょっと困ったコトありまして、文字列関数のstrmidの改良版を自作関数を作っていまして、
そこで行き詰ってる部分があるんです。

どういう動きになってほしいかというと、strmidの第3パラメータで'1'と入力して、半角全角ごちゃ混ぜの変数から
全角半角問わず1文字だけ取ってきてほしいのです。
簡単な例として

a = "あaいeうiuえお" mes strmid(a,2,1)
で”い”を取ってきてほしいんです。

現在の状態です

#module #defcfunc MStrmid var buf, int Index, int i temp = strmid(buf,Index,i) if instr(buf,Index-1,temp) == -1{ temp = strmid(buf,Index,2) } return temp #global a = "あいうえoかきkukekoさし" repeat strlen(a) mes ""+cnt+"\t"+mstrmid(a,cnt,1) loop

何かいい方法とかないですか?



この記事に返信する


kz3

リンク

2006/11/12(Sun) 12:15:33|NO.3415

全角・半角を判別すればいいだけだと思います。

上記スクリプトで、何故「あ」だけが一文字取得できているのかというと instr() の第二パラメータが負数だとエラー(-1)を返すからです。

つまり一番最初に MStrmid() のパラメータを strmid() にそのまま与えただけでは、単に strmid() を呼び出すのと変わりないってことです。

この場合の MStrmid() は「何文字目から何文字の文字列を切り出す」というパラメータを「何バイト目から何バイトの文字列を切り出す」というパラメータに変換したものを strmid() に渡せばいいと思います。
(ラップ関数:http://quasiquote.org/hspwiki/HSP%cd%d1%b8%ec%bc%ad%c5%b5#H-sy1xq5)

「文字単位」から「バイト単位」に変換するのは文字列先頭から全角・半角を判別しながらバイト数をカウントしていけば出来ます。
Shift-JISコードならHSP付属ドキュメント「HSP3文字列のひみつ(中級者向け) (hsp3str.htm) 」に書いてあります。
ステップアップするにはいい機会でしょうから読んでみてはどうですか?



猫太

リンク

2006/11/12(Sun) 15:09:06|NO.3419

返信ありがとうございます。
文字列の秘密を読んで全角文字の判別方法をやってみて、うまく判別したのですが文字単位からバイト単位の変換が上手く出来ないといいますか、やり方がいまいちよくわかりません。
関係ないですが、strlenの文字数を返す改造版なら出来ました。

#module #defcfunc MStrlen var buf repeat if peek(buf,cnt) == 0 : break if (peek(buf,cnt) >= 129 && peek(buf,cnt) <= 159) || (peek(buf,cnt) >= 224 && peek(buf,cnt) <= 252){ in++ continue cnt+2 }else{ in++ continue cnt+1 } loop return in #global



kz3

リンク

2006/11/12(Sun) 16:54:20|NO.3425

>文字列の秘密を読んで全角文字の判別方法をやってみて、うまく判別したのですが
>文字単位からバイト単位の変換が上手く出来ないといいますか、
>やり方がいまいちよくわかりません。

それでは、スクリプトを示さなくてもアルゴリズムだけでコードに出来ますね。

#defcfunc MStrmid var buf, int Index, int i ; buf : 文字列が格納された変数 ; Index : 切り出しを開始するインデックス(文字単位) ; i : 切り出す文字数(文字単位)
(1). Index で指定された文字単位のインデックスが文字列先頭から何バイトなのか、を数える( バイト単位の切り出し開始インデックスを得る )

(2). (1)で得られたバイト単位のインデックスから i で指定された切り出す文字の数だけ、文字種類を判定しながら、切り出すバイト数を数える( 切り出すバイト数を得る )

(3). strmid( buf, (1), (2) ) でバイト単位の切り出しを行う。

というのが私の頭の中のアルゴリズムです。
あくまで参考に、他にもアルゴリズムはあるかも知れません。



猫太

リンク

2006/11/12(Sun) 17:29:49|NO.3428

なんか上手くいかないです。
とりあえず出来る限りやってみました。

#module #defcfunc MStrmid var buf, int Index, int i repeat if Index <= in : in = cnt : break if (peek(buf,cnt) >= 129 && peek(buf,cnt) <= 159) || (peek(buf,cnt) >= 224 && peek(buf,cnt) <= 252){ in++ continue cnt+2 }else{ in++ continue cnt+1 } loop repeat i if (peek(buf,in+cnt) >= 129 && peek(buf,in+cnt) <= 159) || (peek(buf,in+cnt) >= 224 && peek(buf,in+cnt) <= 252){ i2+2 continue cnt+2 }else{ i2++ continue cnt+1 } loop return strmid(buf,in,i2) #global

でも、これもダメっぽいです。。。
しかもソースもぐちゃぐちゃに・・・。



774

リンク

2006/11/12(Sun) 19:21:54|NO.3433

動かない原因は、
モジュール内で作られた(ローカル?)変数(上のソースだとin,i2)が
前に使った数値が入ったままでリセットされてないのと、
repeat i にしてるので

i2+2 continue cnt+2 }else{ i2++ continue cnt+1
でiを全角のときに2、半角のときに1消費してるからですね



KIMU

リンク

2006/11/13(Mon) 03:05:03|NO.3440

>しかもソースもぐちゃぐちゃに・・・。

見た目を整理してみる
基本的にはNO.3428のとやってる事は変わらない


#module #define ctype strtest(%1) ((((%1)>=129)&((%1)<=159))|(((%1)>=224)&((%1)<=252))) //MStrlen(p1,p2,p3) // p1=文字列型の変数名 // p2=文字数インデックス(バイト数ではない) // p3=機能切り替え 0=p1内の文字数を返す 1=p2のインデックスをバイト単位で返す //p2,p3を省略するとp3=0として動作 #defcfunc MStrlen var buf,int Index,int sw,local in repeat temp=peek(buf,cnt) if (temp=0) or ((Index<=in)*sw) {byte=cnt : break} in++ :continue cnt+strtest(temp)+1 loop if sw{return byte}else{return in} //MStrmid(p1,p2,p3) // p2,p3が文字数単位になったStrmid #defcfunc MStrmid var buf,int Index,int i,local in byte=MStrlen(buf,Index,1) repeat i temp=peek(buf,byte+in) if temp=0 {break} in+=strtest(temp)+1 loop return strmid(buf,byte,in) #global a = "あいうえoかきkukekoさし" repeat MStrlen(a) mes ""+cnt+"\t"+MStrmid(a,cnt,1) loop



猫太

リンク

2006/11/13(Mon) 07:27:34|NO.3444

おはようございます。
>動かない原因は、
>モジュール内で作られた(ローカル?)変数(上のソースだとin,i2)が
>前に使った数値が入ったままでリセットされてないのと、
>repeat i にしてるので

気づかなかったです・・・774さんありがとうです。
そしてKIMUさんわざわざ整理してくださいましてありがとうございます。
それとkz3さん、色々教えていただきましてありがとうございますね!

文字列処理はちょっとミスると混乱しますね--;
ではでは解決にいたしますね。
どうもでした。



ONION software Copyright 1997-2023(c) All rights reserved.