• ベストアンサー

入力文字と配列がわからない><

文字列と配列がよくわかりません・・・。 以下のプログラムで「おく」と入力すると ・ ィ と表示されます・・・。 何がおかしいのでしょうか; int main(){   char a[4];   scanf("%s", a);   printf("a[0] = %c \na[1] = %c \n", a[0], a[1]); }

質問者が選んだベストアンサー

  • ベストアンサー
  • jacta
  • ベストアンサー率26% (845/3158)
回答No.5

まず、かな・漢字のような多バイト文字を使うときは、必ず使用されている環境を書くようにしてください。そうでないと、ほとんどの人は、勝手に環境を推測して回答してしまうので、自分の環境に適用できるかどうか分からない情報が得られてしまいます。 というわけで、私はなるべく厳密な書き方をします。 多バイト文字をcharの配列に格納するためには、MB_CUR_MAX×文字数+1バイトが格納できる配列を用意しなければなりません。しかし、MB_CUR_MAXは必ずしも定数式ではありません。(C99を使っているのでない限り)可変長配列は使えません(宣言時の配列の要素数には定数式しか使えない)ので、MB_CUR_MAXは使えません。そこで、代替手段としてMB_LEN_MAXを使います。 char a[MB_LEN_MAX*2 + 1]; 次に、printfで出力する場合ですが、多バイト文字から文字を取り出すには、その文字を構成するバイト数を調べなければなりません。多バイト文字を構成するバイト数を調べるにはmblen関数を使います。 しかし、mblen関数を用いて文字の構成バイト数が分かったとしても、それだけでは文字を取り出すことができません。ISO-2022-JPのように、シフトシーケンスに依存する文字コードの場合があるからです。これに対応する一般的な方法はありませんが、mbstowcs関数でいったんワイド文字列に直してから、ワイド文字1文字ずつをwctomb関数で多バイト文字に直すのが一番移植性が高いと思います。 そして、多バイト文字列の比較ですが、これについてはstrcmp関数で十分かと思いますが、部分文字列を比較する場合は、話が全く違ってきますので要注意です。 以上、非常に小難しい話になってしまいましたが、環境を特定できれば、もっと簡単にすることができます(ただし、移植性は失われますが)。

すると、全ての回答が全文表示されます。

その他の回答 (4)

  • akanekor
  • ベストアンサー率52% (102/194)
回答No.4

文字列比較は strcmp使います。 http://www.bohyoh.com/CandCPP/C/Library/strcmp.html if(strcmp(a, "ひゃく万")==0) { 処理; }

すると、全ての回答が全文表示されます。
  • PG_RankB
  • ベストアンサー率40% (12/30)
回答No.3

全角文字=2バイト 半角文字=1バイト です。 C言語ではその文字列がどこで終わるかは、ヌル文字と言う文字の場所で判断しています。 ヌル文字をしまうためにも、1バイトを使用しますので、「おく」の場合、全角なので、 2バイト * 2 + 1バイト = 5バイト必要です。 a[4]・・・× a[5]・・・○ 半角文字の場合、入力文字数+1バイト。 全角文字の場合、入力文字数*2+1バイト。 最低限これだけの領域を確保すると言う事になりますので、注意して下さい。 実際は、どの程度の長さの文字列が来るか分からないので、a[80]や、a[256]など、多めにサイズを取るか、5バイトなら絶対にそれ以上の文字数で書き込みが無いよう、処理に工夫をするのが普通です。

dra2jp
質問者

補足

ご回答ありがとうございます! char a[100]; scanf("%s", a); //「ひゃく万」を入力 if(a=='ひゃく万'){ 処理; } ではうまくいかないのですが、条件分岐はどうしたらいいのでしょうか?

すると、全ての回答が全文表示されます。
  • qwertyf
  • ベストアンサー率51% (14/27)
回答No.2

期待している結果は「お」と「く」がそれぞれ表示される、というものでしょうが、 ひらがなや漢字は全角文字(=2バイト文字)なので、 a[0]とa[1]は一緒に出力しないと化けます。 printf( "%c%c\n", a[0], a[1] ); といった感じです。 つまり、a[0]とa[1]の2つの要素で「お」が構成され、 a[2],a[3]の2つの要素で「く」が構成されます。 よって、a[0]だけ、とか a[2]だけを出力しても正しく表示されません。 余談ですが、文字列は最後に必ずヌル文字(\0)が入りますので、 a[4] だけじゃオーバーフローします。もっと余分に(a[1000]くらい)確保したほうがいいです。

dra2jp
質問者

補足

ありがとうございます!なるほど!そうなのですね。ではその入力した文字列を条件分岐させるにはどうしたらよいのでしょうか? char a[100]; scanf("%s", a); //「ひゃく万」を入力 if(a=='ひゃく万'){ 処理; } ではうまくいきません・・・。

すると、全ての回答が全文表示されます。
  • akanekor
  • ベストアンサー率52% (102/194)
回答No.1

「おく」 みたいな、全角文字は2バイト文字です。 で、charの領域は1個、1バイトです。 なので、「お」一文字だけで、a[0],a[1]の二つ分の領域を必要とします。 また、%cは、一バイト分のchar文字を表示する命令なので、 a[0]で、「お」文字の先頭一バイトのデータ、a[1]で「お」文字の後方一バイトのデータ表示になり そんな答えが返ってきます。 (例外として、ユニコード使うと、通常の半角文字も2バイト使うようになります。) 後、a[4]で領域とっていますが、「おく」だけで4バイトの領域使ってしまうため、 今のままだと、NULL文字一個分、領域破壊が起きていますよ。 最低、a[5]じゃないといけません。

すると、全ての回答が全文表示されます。

関連するQ&A