C言語関係掲示板

過去ログ

No.551.全角のみの検索で違った文字が出る

[戻る] [ホームページ]
No.4880

全角のみの検索で違った文字が出る。
投稿者---sim(2003/02/01 03:12:04)


ファイルから1行読み込み検索対象の単語があればその行をファイルに出力するプログラムを作成してます。
ファイルの構成はすべてシフトJISの全角になっています。

特定の単語で検索を行うとファイル内には無い文字がヒットされることがあります。
「燕」で検索を行ったら燕が無いのにかかわらず表示されてしまいます。

燕の文字コードが「898d」だから、検索対象の文字の2バイト目と次に来る1バイト目で検索に引っかかるのでしょうか?
それを考えて文字を進めるところをいじってもみたのですがどうにもなりませんでした^^;
よろしければアドバイスをお願いします。

char strtxt[80], wan[80];
int wp,tp,i;
/*ファイルの読み込み*/
while((fgets(strtxt,TXTLEN,fp_in)) != NULL){
     /*ファイルと単語のポインタの初期化*/
     wp=0;tp=0;
     /*単語が見つかるかテキストに単語が見つからなかったら終了*/
     while((wan[wp] != '\0') && (strtxt[tp]) != '\0'){
          /*検索単語のと読み込んだファイルが一致しているかどうか*/
          if(wan[wp] == strtxt[tp]){
               /*見つかったらポインタを1つ進める*/
               wp++;
               tp++;
               }else{
               /*見つからなかったら単語ポインタを最初に戻し、テキストポインタを1つ進める*/
                    tp = tp - wp +1;
                    wp = 0;
               }
           }
           /*単語が見つかっていたらその行をファイルに出力*/
           if(wan[wp] == '\0'){
                fprintf(fp_out"%s",strtxt);
                
           }
      }
}


処理的にはstrstr()と同じ処理をさせているつもりです。
ためしにstrstr()を使って書き直しましたが同じ現象がでます。


No.4881

Re:全角のみの検索で違った文字が出る。
投稿者---sim(2003/02/01 03:15:05)


すみません、環境を書き忘れていました。

OS:win2000
コンパイラ:BCC(Borland C++ Compiler 5.5)


No.4887

Re:全角のみの検索で違った文字が出る。
投稿者---カンナ(2003/02/01 10:59:57)
http://hana.sakura.ne.jp/~elfin/k/


 御推察の通りです。

 対応策としては、見つからなかったときにテキストポインタを1つ進める
のではなく1文字進める必要があります。
 お使いの環境では通常Shift-JISが用いられています。その場合まず
テキストポインタを単語ポインタ分戻し、それからその1バイト目が2バイト
文字の1バイト目にあたるかどうかを判定します。あたっていたら2つ進め、
あたっていなかったら1つ進めます。2バイト文字の1バイト目にあたる範囲は
0x81〜0x9Fおよび0xE0〜0xEFです。したがって見つからなかった場合の
elseブロックの中は以下のようになります。

/*見つからなかったら単語ポインタを最初に戻し、テキストポインタを1文字分進める*/
unsigned char ch;
tp -= wp;
wp= 0;

ch = strtxt[tp];
if ( 0x81 <= ch && ch <= 0x9F || 
     0xE0 <= ch && ch <= 0xEF ){
    tp+=2;
}else{
    tp+=1;
}
 EUCの場合なら2バイト文字の1バイト目の範囲がA1〜FEになります。
 JISの場合はこのやり方では判定できません。2バイト文字の開始や終了
を表す制御コードを適切に処理する必要があります。

No.4907

解決しました。ありがとうございました。
投稿者---sim(2003/02/01 21:18:52)


カンナさん、レスありがとうございました。
おかげさまで解決しました。

>その場合まず
>テキストポインタを単語ポインタ分戻し、それからその1バイト目が2バイト
>文字の1バイト目にあたるかどうかを判定します。あたっていたら2つ進め、
>あたっていなかったら1つ進めます。2バイト文字の1バイト目にあたる範囲は
> 0x81〜0x9Fおよび0xE0〜0xEFです。
2バイト文字の1バイト目のチェックをする事がまったく気がつきませんでした^^;
よくよく考えてみたら、1バイト目の範囲と2バイト目の範囲は違ってくるんですよね・・・。
まだまだ勉強不足でした。

> EUCの場合なら2バイト文字の1バイト目の範囲がA1〜FEになります。
> JISの場合はこのやり方では判定できません。2バイト文字の開始や終了
>を表す制御コードを適切に処理する必要があります。
他のコードの事も教えていただきありがとうございました。
今後拡張を行うときの参考にさせていただきます。