この記事はC言語演習問題集の問題の回答です。まだ問題読んでないという方は下記記事の「日本語って難しい!マルチバイト文字をC言語で扱ってみよう」をぜひ見てから読んでください。

解答例
#include <stdio.h>
#include <string.h>
int main(void){
char input[256];
char target[256] = "人";
unsigned int inputLen;
unsigned int targetLen;
int i, j;
int num;
printf("日本語を入力してください:");
scanf("%s", input);
inputLen = strlen(input);
targetLen = strlen(target);
printf("inputLen = %d, targetLen = %d\n", inputLen, targetLen);
for(i = 0; i < inputLen; i++){
printf("%c", input[i]);
}
printf("\n");
for(j = 0; j < targetLen; j++){
printf("%c", target[j]);
}
printf("\n");
num = 0;
for(i = 0; i < inputLen - targetLen + 1; i++){
j = 0;
if(input[i] == target[0]){
for(j = 0; j < targetLen; j++){
if(input[i + j] != target[j]){
break;
}
}
if(j == targetLen){
num++;
}
}
}
if(num > 0){
printf("「%s」を%d回発見!\n", target, num);
} else {
printf("「%s:なし!\n", target);
}
return 0;
}
表示例
スポンサーリンク
解説
今回は文字列を扱ってみました。結構C言語の参考書って、1バイトで扱える英語のみを扱って終わり!というパターンが多いのですが、ここでは日本語を扱ってみています。日本語は文字の種類が多いので1バイトでは表現しきれず、複数バイトを用いて表現されています。わたしも実際に何バイト使用しているかは知らなかったのですが、実際に試してみたら1文字3バイト使用しているようでした(これは環境によるかも)。
それではプログラムを追いながらポイントを見ていきましょう。
char target[256] = "人";
printf("日本語を入力してください:");
scanf("%s", input);
inputLen = strlen(input);
targetLen = strlen(target);
inputとtargetの両方に日本語が入力されます。表示例で使用した例だとinputは「日本人アメリカ人大阪人」で普通に考えれば11文字です。targetは「人」にしていますので3文字のはずです。しかし表示例ではそれぞれ33文字、3文字であると出力されています。
これは上で説明したように日本語が1文字3バイトで扱われ、strlen関数が1文字1バイトであることを前提として計算しているからです。
英語と日本語の文字列はchar配列内で下記のように格納されることになります。char型の配列は1要素が1バイトでありますが、1文字分とは限らないというのがこの問題のポイントです。
なので、日本語のある文字が含まれているかを確認するためには1バイト分だけでなく3バイト分調べてやる必要があります。
for(i = 0; i < inputLen - targetLen + 1; i++){
j = 0;
if(input[i] == target[0]){
for(j = 0; j < targetLen; j++){
if(input[i + j] != target[j]){
break;
}
}
if(j == targetLen){
num++;
}
}
}
targetLenが3なのでchar型の要素を3つ分調べてやれば3バイト分確認したことになります。3バイト分連続して同じデータが格納されていれば同じ文字が含まれると判断してnumをインクリメントしています。
ちなみに日本語文字列を扱う変数の型としてwchar_tなども存在します。今回は日本語文字がマルチバイト文字であることを実感してもらうためにchar型を使用しましたが、実践ではwchar_tを使用する方が直感的に分かりやすいプログラムが作成できると思います。
独り言
正直自分も日本語を扱うプログラムは初めて書きました。もしかしたらこうやるのかも・・・・!と思ってやってみたら思った通りに動いてくれたので問題文にしてみました。文字列扱うのってC言語では実は結構難しいしバグりやすい部分だと思います。それを日本語でやるとさらに難しいですね・・・。