日本語(漢字含む)が書かれたファイルから、データを配列に収めるにはどうしたらいいのでしょうか?(長々とかかれていますがこれが主題です。後は読まずにこの文章に対してだけ答えてくださっても結構です。)
◆fgetc()で1文字ずつchar型の配列に収めていったのですが、その配列の内容を表示してみると、カタカナと「、」からなる意味不明の文字列が表示されてしまいました。表示は、%sで表示する方法と、%cで1文字ずつをループをつかって表示する方法の2通りの方法を試してみましたが、どっちもダメでした。なぜなんでしょうか???(ちなみに英字ならうまくいくのですが…)
ない頭を使って考えてみたんですが、漢字のバイト数を2バイトと仮定すると、(そうではないものもあるらしいのですが…)char型の配列の要素1個あたり1バイトなので、要素1個には、漢字の情報の半分の情報量しか含まれていないからではないか、とおもったんですが、どうでしょうか?
◆しかし、fgetc()ではなく、fgets()で収めてみると、なぜかうまく表示されます(この場合、1行分だけですが)。前出の2つの方法の両方で。なぜなのでしょうか??????????
じゃあ、その方法でヤレバいいじゃん、といわれそうですがしかし、fgets()だと1行分配列に収めた後、さらに同じ配列にデータの続きを収めることができないからです。つまり、ファイルから1行分しか配列に収められないと…まぁ、何か方法はあると思いますが、いずれにしろスマートではなくなるのでは、と思うのです。
長くなってしまって、ごめんなさい。文章が下手で…(汗汗)
どこか1部分に対する回答や、アドバイスでも結構ですので、よろしくお願いします。
No.1
- 回答日時:
解決方法がわからないのでアドバイスです。
すいません。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つの変数に入れなくてはならないのでしょうか?
No.2
- 回答日時:
この手の問題は処理系,環境,コンパイラ,実際のプログラムが無いと判断が難しいです。
自分で問題だと判断したところでなく,なるべく全体を、
何をしたいかを書いたほうがいいですよ。
全く関係の無いと思っていたところが,問題な場合もありますし。
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つの変数に入れなくてはならないのでしょうか?
No.3
- 回答日時:
こんにちは。
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関数をバイナリモードでオープンするといいかもしれません。
おっと、そんな別な方法もあるのですか。これは知りませんでした。まだまだ勉強が足りません。はやく、もっと自由自在にプログラミングができるようになりたいな~(独り言でした)
No.4
- 回答日時:
>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が無いから何も表示されない、というコトなんですかね???
No.5ベストアンサー
- 回答日時:
>…あっ、そうか!このdata[0]に格納されている2進数値列を%cで出力しようとしても、対応するcharacterが無いから何も表示されない、というコトなんですかね???
そういう考えでだいたいいいと思います。
正確には,漢字の半分のデータしかないので
何を出していいか分からない状態なので、
何も出ないという状態だと思います。
3byteの方も同様です。
例えば,「亜」をShift JISで表示するためには,
0x88 0x9fを送る必要がありますが、空白がはいると
0x88 0x20 0x9fが送られます。
0x88 0x20が漢字と解釈されますが、該当する文字は
ありませんので、多分空白となるでしょう。
0x9fは半分なので表示できない・・となると思います。
ただ、こういう未定義のコードを出した場合どうなるかは、
場合によって違うかも知れません。
未定義ですから。
ありがとうございました。
ぼくの持っているCの本は、日本語についてあまり言及していないので全然解らなかったのです。(英字は1バイト。日本語は2バイトなんだけどね、くらいの説明)
今回、いろいろとわかってよかったです。ありがとうございました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・人生のプチ美学を教えてください!!
- ・10秒目をつむったら…
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・【大喜利】【投稿~9/18】 おとぎ話『桃太郎』の知られざるエピソード
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C言語 配列の長さの上限
-
配列を使わずに、変数名を動的...
-
【速いブラインドタッチ】手を...
-
配列をEraseしてもメモリが開放...
-
C# Listを使わずに2次元配列の...
-
【C言語】配列の中に配列を入れ...
-
C言語 変換指定%sについてです。
-
unsigned char配列への入力の仕方
-
配列の重複削除について
-
C言語で特定列だけを抽出して配...
-
RGB値を画像(PNG・BMPJPEGなど)...
-
C# 配列の変数宣言について。
-
メモリの初期値
-
配列の参照渡しで型が一致しま...
-
複数の選択範囲の行番号を個別...
-
VB.NET 構造体の配列の検索機能...
-
VBでC言語のポインタみたい...
-
配列で格納したものをmsgboxで...
-
テキストファイルから文字列を...
-
VBAで配列からbmp画像を出力す...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C言語 配列の長さの上限
-
配列を使わずに、変数名を動的...
-
配列で格納したものをmsgboxで...
-
C# Listを使わずに2次元配列の...
-
C# 配列の変数宣言について。
-
先頭アドレスとは何ですか?
-
C言語で特定列だけを抽出して配...
-
配列の参照渡しで型が一致しま...
-
VBで構造体の配列を関数に渡す...
-
C++ vectorに配列をプッシュしたい
-
【速いブラインドタッチ】手を...
-
unsigned char配列への入力の仕方
-
配列をEraseしてもメモリが開放...
-
【C言語】配列の中に配列を入れ...
-
ExcelVBAで質問です。離れた二...
-
4勤2休のシフト作成
-
Functionの戻り値を2次元配列...
-
Redimした動的配列はEraseする...
-
配列を含む構造体の初期値について
-
複数の選択範囲の行番号を個別...
おすすめ情報