- ベストアンサー
日本語データを配列に収める方法
日本語(漢字含む)が書かれたファイルから、データを配列に収めるにはどうしたらいいのでしょうか?(長々とかかれていますがこれが主題です。後は読まずにこの文章に対してだけ答えてくださっても結構です。) ◆fgetc()で1文字ずつchar型の配列に収めていったのですが、その配列の内容を表示してみると、カタカナと「、」からなる意味不明の文字列が表示されてしまいました。表示は、%sで表示する方法と、%cで1文字ずつをループをつかって表示する方法の2通りの方法を試してみましたが、どっちもダメでした。なぜなんでしょうか???(ちなみに英字ならうまくいくのですが…) ない頭を使って考えてみたんですが、漢字のバイト数を2バイトと仮定すると、(そうではないものもあるらしいのですが…)char型の配列の要素1個あたり1バイトなので、要素1個には、漢字の情報の半分の情報量しか含まれていないからではないか、とおもったんですが、どうでしょうか? ◆しかし、fgetc()ではなく、fgets()で収めてみると、なぜかうまく表示されます(この場合、1行分だけですが)。前出の2つの方法の両方で。なぜなのでしょうか?????????? じゃあ、その方法でヤレバいいじゃん、といわれそうですがしかし、fgets()だと1行分配列に収めた後、さらに同じ配列にデータの続きを収めることができないからです。つまり、ファイルから1行分しか配列に収められないと…まぁ、何か方法はあると思いますが、いずれにしろスマートではなくなるのでは、と思うのです。 長くなってしまって、ごめんなさい。文章が下手で…(汗汗) どこか1部分に対する回答や、アドバイスでも結構ですので、よろしくお願いします。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
>…あっ、そうか!このdata[0]に格納されている2進数値列を%cで出力しようとしても、対応するcharacterが無いから何も表示されない、というコトなんですかね??? そういう考えでだいたいいいと思います。 正確には,漢字の半分のデータしかないので 何を出していいか分からない状態なので、 何も出ないという状態だと思います。 3byteの方も同様です。 例えば,「亜」をShift JISで表示するためには, 0x88 0x9fを送る必要がありますが、空白がはいると 0x88 0x20 0x9fが送られます。 0x88 0x20が漢字と解釈されますが、該当する文字は ありませんので、多分空白となるでしょう。 0x9fは半分なので表示できない・・となると思います。 ただ、こういう未定義のコードを出した場合どうなるかは、 場合によって違うかも知れません。 未定義ですから。
その他の回答 (4)
- terra5
- ベストアンサー率34% (574/1662)
>printf("%c",data[0]);でも、 1byteしか出力されません。 >printf("%c %c",data[0],data[1]);でも何も表示されないのに、 ' 'が2番目に出力されるので、3byte出力されます。 >printf("%c%c",data[0],data[1]); 2byte出力されます。 というわけで、同じ物が出ていないので結果が違うわけです。 これは元の配列が,intでもcharでも同じことです。 >日本語1文字につき、何が何でも2つの変数に入れなくてはならないのでしょうか? そんなことはありませんが、その方が説明も楽です(^^; 例えば,long intが4byteならShift JISなら二文字入れることが可能ですが, いろいろと環境に依存する問題も出てきそうなので, 面倒なので避けます(^^;;;
補足
回答ありがとうございました。 >' 'が2番目に出力されるので、3byte出力されます。 あ、そうか…スペースの存在を忘れていました。でもこの場合、 スペースしか表示されないんですよね。文字が何もでてこない… >>printf("%c",data[0]);でも、 >1byteしか出力されません。 ここなんです。1byte出力されるはずなのに何も表示されないのです… …あっ、そうか!このdata[0]に格納されている2進数値列を%cで出力しようとしても、対応するcharacterが無いから何も表示されない、というコトなんですかね???
- itohh
- ベストアンサー率45% (210/459)
こんにちは。itohhといいます。 記憶があいまいなのですが、 fgetc関数は、2バイト文字の場合、1バイト落としてしまいます。 それなので、文字化けしたようになります。 fopen関数をバイナリモードでオープンするといいかもしれません。 すみません、試していないので間違っているかもしれません。 fread関数でEOFになるまで読み込んでいくのは如何ですか? 例えば、 FILE *stream; char wRec[100]; char wBuf[1024]; int wCnt, numread; /* バイナリモードでファイルを開く */ if( (stream = fopen( "fread.out", "r+b" )) != NULL ) { wCnt = 0; memset( wBuf, 0x00, sizeof(wBuf) ); /* EOFになるまで読み込む */ while( !feof( stream ) ) { numread = fread( wRec, sizeof( char ), 100, stream ); memcpy( &wBuf[wCnt], wRec, numread ); wCnt += numread; } fclose( stream ); } 本来は、wBufは、ファイルのサイズを調査してファイルサイズ+1バイトのエリアを malloc関数で確保するべきだと思います。 det_mul2さんの環境がUNIXなのかWindowsなのか解らないのでファイルサイズを取得す る関数は省略しました。 また、エラー処理も省略していますので、それなりに行ってください。 ファイルサイズが解るのならば、 while文でループしないで numread = fread( wBuf, sizeof( char ), ファイルサイズ, stream ); でもOKです。
お礼
アドバイスありがとうございました。 昨日あきらめて、今日起きてちょっといじったら、うまくいきました。 小さなところを間違えていたようです…お騒がせしてすみませんでした。 それにしても、まだ解らないことがタックサンです。 日本語データを、char型の配列data[]にいれたとすると、 printf("%c",data[0]);でも、 printf("%c %c",data[0],data[1]);でも何も表示されないのに、 printf("%c%c",data[0],data[1]);ならちゃんと日本語が1文字表示されちゃうんですよね~2バイト文字を表示するには連続して表示しなければいけないというルールがあるのかな…??? int型の配列idata[]に同じデータを入れてみても、 printf("%c",idata[0]);でも、 printf("%c %c",idata[0],idata[1]);でも何も表示されないのに、 printf("%c%c",idata[0],idata[1]);ならちゃんと日本語が1文字表示されちゃうんですよね~。int型は2バイト以上あるはずなのに、、、 日本語1文字につき、何が何でも2つの変数に入れなくてはならないのでしょうか? >fopen関数をバイナリモードでオープンするといいかもしれません。 おっと、そんな別な方法もあるのですか。これは知りませんでした。まだまだ勉強が足りません。はやく、もっと自由自在にプログラミングができるようになりたいな~(独り言でした)
- terra5
- ベストアンサー率34% (574/1662)
この手の問題は処理系,環境,コンパイラ,実際のプログラムが無いと判断が難しいです。 自分で問題だと判断したところでなく,なるべく全体を、 何をしたいかを書いたほうがいいですよ。 全く関係の無いと思っていたところが,問題な場合もありますし。 fgetcで失敗するのは,プログラムに問題(バグ)があるような気がしますが,実際のソースコードがないと判断つきません。
お礼
アドバイスありがとうございました。 昨日あきらめて、今日起きてちょっといじったら、うまくいきました。 小さなところを間違えていたようです…お騒がせしてすみませんでした。 それにしても、まだ解らないことがタックサンです。 日本語データを、char型の配列data[]にいれたとすると、 printf("%c",data[0]);でも、 printf("%c %c",data[0],data[1]);でも何も表示されないのに、 printf("%c%c",data[0],data[1]);ならちゃんと日本語が1文字表示されちゃうんですよね~2バイト文字を表示するには連続して表示しなければいけないというルールがあるのかな…??? int型の配列idata[]に同じデータを入れてみても、 printf("%c",idata[0]);でも、 printf("%c %c",idata[0],idata[1]);でも何も表示されないのに、 printf("%c%c",idata[0],idata[1]);ならちゃんと日本語が1文字表示されちゃうんですよね~。int型は2バイト以上あるはずなのに、、、 日本語1文字につき、何が何でも2つの変数に入れなくてはならないのでしょうか?
- cherry_moon
- ベストアンサー率36% (37/102)
解決方法がわからないのでアドバイスです。すいません。 fgetc() だとだめで、fgets() ならうまくいくということは、 配列の中身も違うのではないでしょうか? while(*s){ printf("%02X ", *s); s++; } とかで、配列の中身を確認してみてはいかがでしょう? 2つの違いで何かわかるかもしれないですよ。
お礼
アドバイスありがとうございました。 昨日あきらめて、今日起きてちょっといじったら、うまくいきました。 小さなところを間違えていたようです…お騒がせしてすみませんでした。 それにしても、まだ解らないことがタックサンです。 日本語データを、char型の配列data[]にいれたとすると、 printf("%c",data[0]);でも、 printf("%c %c",data[0],data[1]);でも何も表示されないのに、 printf("%c%c",data[0],data[1]);ならちゃんと日本語が1文字表示されちゃうんですよね~2バイト文字を表示するには連続して表示しなければいけないというルールがあるのかな…??? int型の配列idata[]に同じデータを入れてみても、 printf("%c",idata[0]);でも、 printf("%c %c",idata[0],idata[1]);でも何も表示されないのに、 printf("%c%c",idata[0],idata[1]);ならちゃんと日本語が1文字表示されちゃうんですよね~。int型は2バイト以上あるはずなのに、、、 日本語1文字につき、何が何でも2つの変数に入れなくてはならないのでしょうか?
お礼
ありがとうございました。 ぼくの持っているCの本は、日本語についてあまり言及していないので全然解らなかったのです。(英字は1バイト。日本語は2バイトなんだけどね、くらいの説明) 今回、いろいろとわかってよかったです。ありがとうございました。