今さらながら全角2バイト目チェック方法No.15143
秀まるお2 さん 03/08/01 10:02
 
 今さらながらですが、ShiftJISの全角/半角混在文字列中の、特定位置が全角
文字の2バイト目かそうでないかを判定するアルゴリズムを改良しようと思いま
した。誰か詳しい人からコメントありましたらよろしくお願いします。

■今の処理:

BOOL IsKanji2( const char* psz, int x ) {
    if( x <= 0 ) return FALSE;
    if( !IsDBCSLeadByte( psz[x-1] ) ) {
        return FALSE;
    }
    const char*  pchTarget = psz + x;
    while( psz < pchTarget ) {
        if( IsDBCSLeadByte( *psz ) ) {
            psz += 2;
        } else {
            psz ++;
        }
    }
    if( psz == pchTarget ) {
        return FALSE;
    }
    return TRUE;
}

■新しく考えた処理:

BOOL IsKanji2( const char* psz, int x ) {
    if( x <= 0 ) {
        return FALSE;
    }
    int xStart = x;
    do {
        if( !IsDBCSLeadByte( psz[xStart-1] ) ) {
            break;
        }
        xStart --;
    } while( xStart > 0 );
    return (x - xStart) % 2;
}

[ ]
RE:15143 今さらながら全角2バイト目チェNo.15145
さん 03/08/01 16:02
 
> 今さらながらですが、ShiftJISの全角/半角混在文字列中の、特定位置が全角
>文字の2バイト目かそうでないかを判定するアルゴリズムを改良しようと思いま
>した。誰か詳しい人からコメントありましたらよろしくお願いします。

古いのと新しいのは同じ動作をしますね。
ただ、このコードだと全角第1バイトがTRUEで、それ以外(全角2バイト、半角、英数
字)はFALSEとなりますが。
実際、下の文字列は
  日本語テスト012テスト
次のような結果になります(+:TRUE,-:FALSE)
  +-+-+-+-+-+-------

趣味の問題ですが、私なら下みたいにコーディングします。
Window定義のTRUE,FALSEが1,0対応であるのに依存するのは危険だと思います(64BitW
indowsとかはその辺で問題が起きることもあるらしい)。
(psz != 0で、x > -&pszが仮定できるなら 最初の判定は省略できるので
ちょっとお得)

BOOL IsKanji2( const char* psz, int x ) {
    if( x <= 0 ) {
        return FALSE;
    }

    const char* pcEnd = psz + x;
    const char* pcPtr = pcEnd - 1;
    while( pcPtr >= psz ){
        if( !IsDBCSLeadByte( *pcPtr ) ) {
            break;
        }
        --pcPtr;
    };
    return ( (pcEnd - pcPtr) & 1 ) ? FALSE : TRUE;
}

[ ]
RE:15145 今さらながら全角2バイト目チェNo.15146
秀まるお2 さん 03/08/01 16:21
 
> ただ、このコードだと全角第1バイトがTRUEで、それ以外(全角2バイト、半角、英数
> 字)はFALSEとなりますが。
> 実際、下の文字列は
>   日本語テスト012テスト
> 次のような結果になります(+:TRUE,-:FALSE)
>   +-+-+-+-+-+-------

 そんなアホな…ということで、一応こちらでテストした所はちゃんと動作しま
したが、こちらのコードはアップロードした物と少し違うのでそれのせいやら?

    static char sz[] = "日本語テスト012テスト";
    static char af[100];
    int x = 0;
    while( sz[x] != '\0' ) {
        af[x] = IsKanji2( sz, x );
        x ++;
    }

 afは、010101010101000010101
 のようになりました。ちなみにですけど、僕の所ではコンパイル時に/Jオプシ
ョンを付けてまして、charはすべてunsignedです。でもそれは関係ないか。

 ま、どっちにしてもうちの所では正常動作してるのでよしとさせていたたきま
す。

 (既にHmJre.dllに入れてしまいました)

[ ]
RE:15146 今さらながら全角2バイト目チェNo.15147
さん 03/08/01 16:50
 
>> ただ、このコードだと全角第1バイトがTRUEで、それ以外(全角2バイト、半角、英数
>> 字)はFALSEとなりますが。
>> 実際、下の文字列は
>>   日本語テスト012テスト
>> 次のような結果になります(+:TRUE,-:FALSE)
>>   +-+-+-+-+-+-------
>
> そんなアホな…ということで、一応こちらでテストした所はちゃんと動作しま
>したが、こちらのコードはアップロードした物と少し違うのでそれのせいやら?
>
>    static char sz[] = "日本語テスト012テスト";
>    static char af[100];
>    int x = 0;
>    while( sz[x] != '\0' ) {
>        af[x] = IsKanji2( sz, x );
>        x ++;
>    }
>
> afは、010101010101000010101
> のようになりました。
うーんと上の例ではsz[0]を調べるにはIsKanji2( sz,1 )だと考えていました。IsKan
ji2(sz,0)であればおっしゃるとおりです。
それから忘れていましたが最後の"テスト"は半角でした。
多分、新しいほうが、ほとんどの場合ずっと早いはずですが、最悪は古いほうの2倍
かかりますね。

[ ]
RE:15147 今さらながら全角2バイト目チェNo.15148
秀まるお2 さん 03/08/01 17:02
 
> 多分、新しいほうが、ほとんどの場合ずっと早いはずですが、最悪は古いほうの2倍
> かかりますね。

 たしかにそういうケースもあるから、必ず速くなるとはいえないようで…。

 あと、秀丸内部ではUnicode文字についてもっとややこしい処理をしてるよう
なので、やはり秀丸内部は今まで通りってことにします。HmJreと鶴亀側だけに
採用します。

[ ]