|
|
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
何かいい方法とかないですか?
|
|
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
|
|
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
でも、これもダメっぽいです。。。
しかもソースもぐちゃぐちゃに・・・。
|
|
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消費してるからですね
|
|
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さん、色々教えていただきましてありがとうございますね!
文字列処理はちょっとミスると混乱しますね--;
ではでは解決にいたしますね。
どうもでした。
|
|