C言語ケーススタディ 全角/半角混じり文字列内の文字検索




2014年10月より個人の方を対象に、Study C無料提供を開始しました。
C言語を勉強中の方は、学習・教育に最適なC言語インタープリタのStudy Cを使ってみてください(個人の方は無料です)。
大学・高専・高校などの教育機関での採用実績も多数あるロングセラー商品Study Cが、個人向けに無料提供を始めました。
インタープリタの手軽さに加え、ゲームや3Dタートルグラフィックで楽しく勉強したりと、C言語の学習を強力にサポートします。
ブロック崩しゲーム 3Dツリー クリスマスツリー
また、このようなボタンの用意されているページでは、掲載しているプログラムをStudy Cに直接ロードし実行したりすることができます。
Study Cにロードする Study Cにロードし編集する Study Cにロードし実行する
Study C無料利用についての詳細は、このページを参照してください。



 文字列内から文字検索は strchr() 関数で行うことができます。 しかし、全角文字が混じった文字列の場合、正しく検索できないことがあります。
 次のプログラムは、 strchr() 関数を使用して全角文字の混じった文字列の文字数をカウントしています。
main()
{
        char    *str = "漢字ABCあいう123";
        printf("===%s\n", strchr(str, 'C'));
}
Study Cをお使いの方は、コマンドラインに直接次のように入力して動作確認行うことができます。
C:\StudyC\MyProg>expr printf("===%s\n", strchr("漢字ABCあいう123", 'C'))
 実行結果として「===Cあいう123」と表示されます。また、コマンドラインで実行した結果は次のようになります。
===Cあいう123
<int>14 0xe
実行結果ですが、最初の行に printf() 関数が出力した文字列が表示され2行目(「<int>14 0xe」の部分)にprintf()関数が返してきた値が表示されます。 printf() 関数は表示した文字数を関数の返り値として返します。 最後の改行文字も含めた文字数です(0xeは、14の16進数表記です)。
上記のプログラム、コマンドラインの実行結果とも、正しく結果が表示されています。
ちなみに、strchr() 関数を使わずに同じような処理を行うプログラムは次のようになります。
main()
{
        char    *str = "漢字ABCあいう123";
        int     i1;
        for(i1 =0; ; i1++){
                if(str[i1] == '\0')
                        break;
		if(str[i1] == 'C'){
		        printf("===%s\n", str + i1);
			break;
		}
	}
}

 次に先ほどのプログラムの「漢字ABCあいう123"」の「漢字」の部分を「アイウ」に修正して実行してみてください。
main()
{
        char    *str = "アイウABCあいう123";
        printf("===%s\n", strchr(str, 'C'));
}
Study Cをお使いの方は、コマンドラインに直接次のように入力して動作を確認してください。 ↑カーソルキーを押せば前に入力した内容が呼び出されるので、「漢字」の部分を「アイウ」に修正してください。
expr printf("===%s\n", strchr("アイウABCあいう123", 'C'));
 実行結果として「===CウABCあいう123」と表示されます。また、コマンドラインで実行した結果は次のようになります。
===CウABCあいう123
<int>19 0x13
「===Cあいう123」という実行結果を期待されたと思います。
誤った結果が表示された理由は「イ」という文字が0x83と0x43の2バイトで構成されていて、2バイト目が「C」の0x43を同じコードのためです。 漢字コードの1バイト目は普通のASCII文字とは異なる領域ですが、2バイト目は領域が重複するために起こる現象です。
Study Cのエディタで「イ」の部分にカーソルを移動しCtrl+P、Ctrl+Cと入力するとウィンドウの上部に「83H : 43H」と文字コードが表示されます。 同じようにして他の文字コードも確認してみてください(「A」の位置では隣の文字「B」の文字コードとともに「41H : 42H」と表示されます)。
strchr() 関数は、日本語の文字列が含まれていることを考慮していないため正しく結果が得られません。 変わりに _mbschr()関数を使用すれば正しく実行されます。
main()
{
        char    *str = "アイウABCあいう123";
        printf("===%s\n", _mbschr(str, 'C'));
}
expr printf("===%s\n", _mbschr("アイウABCあいう123", 'C'));
どちらも正しい実行結果「===Cあいう123」が表示されたと思います。 _mbschr() 関数を使わずに同じような処理を行うプログラムは次のようになります。
main()
{
        char    *str = "アイウABCあいう123";
        int     i1;
        int count = 0;

        for(i1 =0;;){
                if(str[i1] == '\0')
                        break;
                if(_ismbblead(str[i1])){
                        if(str[i1+1] == '\0'){
                                break;
                        }
                        i1 += 2;
                        continue;
                }
		if(str[i1] == 'C'){
		        printf("===%s\n", str + i1);
			break;
		}
                i1++;
        }
}

【参照関数】
_mbschr
_ismbblead

【関連項目】
C言語ケーススタディ 全角文字の処理方法
C言語ケーススタディ 全角/半角混じり文字列の文字数