- ベストアンサー
C言語について教えてください。
数日前に「http://okwave.jp/qa4903738.html」で質問させてもらった者です。 前回、寝起きでボケてるうちに回答を締め切ってしまって、 回答してくださった方との対話ができていませんでした。 すみません。 今回は前回の指摘された部分を含めて回答を戴きたく投稿させてもらいます。 質問内容はほぼ変わりありません。 CSVファイルの内容をfreadで読み込み、strtokを使わずにbuffに格納した後、 buffから1文字ずつbuff2へコピーさせていって、コンマがきたら数字、 改行がきたら名前と判別して、自作関数に渡して表示させたいです。 あと、fgetsは使わないようにしたいです。 CSVファイルの内容は 『11,名前1(改行) 15,名前2(改行) 18,名前3』 といった感じです。 ----------------------------------------------- #define _CRT_SECURE_NO_DEPRECATE 1 #include <stdio.h> #include <string.h> #include <stdlib.h> #define NUM 256 struct kou { short nenrei; char namae[30]; }; void pri(struct kou o) { printf("%d\n%s\n",o.nenrei,o.namae); } int main(void) { FILE *fp; // ファイルポインタ char buff1[NUM] = {0}; char buff2[NUM] = {0}; char *fname = "text1.csv"; // ファイル名を指定 int n = 0; struct kou p; fp = fopen(fname, "r"); if(fp == NULL) { printf("%sファイルをオープンできませんでした。\n",fname); return 1; } fread(buff1, 1, NUM, fp); // ここでファイルの内容が全てbuffに入る。 // printf("%s\n",buff1); // buff1にファイルの内容が書き込まれているか確認する。 while((buff2[n] = buff1[n]) != NULL) // buff2[0]からbuff1の中が終わるまで一文字ずつコピーしていく。 { if(buff2[n] == ',') // buff2に格納されていく中にコンマがきたら以下の作業を行う。 { p.nenrei = atoi(buff2); // char型からshort型への変換し、p.iAgeに入れていく。 } if(buff2[n] == '\n') { strcpy(p.namae,buff2); // p.namaeにbuff2をコピー。 pri(&p); } n++; } fclose(fp); printf("ファイルをクローズしました。\n"); return 0; } ----------------------------------------------- 前回指摘されたwhileの条件式ですが、 まだchar型とポインタを比べてることになっているので正しくないんですよね? 正直、どうすればいいかわかりません。 あと、今のままでは名前3の後が改行ではないので表示されることないですよね・・・。 どうすれば表示されるようになるでしょうか。 これも前回言われましたが while内の1つ目のif文の所で、カンマを処理したので次に取り込むbuff2への書き込み位置の変更というのもわかりません。 カンマが来た時点でbuff2[n]のnは2になっているんですよね? ということはbuff2[3]からまた読み込めたらいいということですよね? 厚かましくも立て続けに質問してしまって申し訳ありませんが回答を戴けたらありがたく思います。 宜しくお願いします。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
>NULLと\0は今のところ同じものと考える その回答を真に受けてはいけません。 「今のところ」同じものと考えるならば、 「いつになったら」別のものと考えられるようになるのでしょうか。 NULLはポインタ、'\0'は整数型定数で、 両者は「いつでも」全く別物です。
その他の回答 (3)
- SilverThaw
- ベストアンサー率32% (260/806)
No.1です >返答ありがとうございます。 >NULLじゃなくて『\0』ってやるべきだったんですね。 >同じものだと勘違いしていました。 NULLと「\0」は厳密には違いますが、今は同じものだと考えてください。 問題はその前です。 質問文及びソース上は「NULL」を入れている部分がなく、 また、fread()もfgets()などと違い終端にNULLを入れる関数ではないためです。 fread()は第二引数のサイズを第三引数の回数分だけ第一引数に読み、読み込めた回数を戻り値として返します。 質問の問題では、1ByteずつNUM回、buffにデータを読み込みます。 ……と、書いていますが、実際には >char buff1[NUM] = {0}; のために、終端はNULLと扱われますが、実際にはNULLと「0」は同値ではありません。 問題はここちらの方ですね。 >while((buff2[n] = buff1[n]) != NULL) この場合、NULLと比較する左辺の値は「buff2[n]」でも「buff1[n]」でもありません。 「(buff2[n] = buff1[n])」が実行された結果、すなわち正常に代入された「真」が比較対象となります。 「真」は「0以外」の値とるため、while()文は無限ループとなります。 >freadを使って処理するのが課題ということで ……学校の課題ですか?
お礼
補足のコメントに「~ですが、~ですが」と2回続けてしまってましたね。 自分のコメントを何度も読み返すべきでした。 課題の方ですが、なんとかできました。 アドバイスありがとうございました。
補足
再びの返答ありがとうございます。 NULLと\0は今のところ同じものと考えると while((buff2[n] = buff1[n]) != '\0') とやってもよろしくない感じですか? buff1のnの最後に入ってる(?)『\0』がbuff2にコピーされた時、比較対象の'\0'と同じになったのでループが終了する(whileの条件式が'\0'でない場合繰り返すなので)という考えでも間違っているんでしょうか。 >……学校の課題ですか? そうですね。まだ始まったばかりなのですが、始めにプリントを渡されて徐々に授業でやっていくみたいなんですが、1度や2度の説明で理解できるかわからないので、何度も読み返すことのできるこの場で質問させていただきました。
- asuncion
- ベストアンサー率33% (2127/6289)
>あと、fgetsは使わないようにしたいです。 freadにこだわる意味がよくわからないです。 1行ずつ処理したいのでしょうから、素直にfgetsを使うのが楽だと思いますが、いかがでしょうか? 今は、CSVファイルの大きさが >#define NUM 256 で定義した範囲に収まっているから特に問題なさそうです。 しかし、CSVファイルがもっと大きいサイズを持つとき、 freadで読むと、とにかく256バイトでぶった切ります。 そうすると、例えば名前の途中で別々のデータになったりして、 つなぎ合わせるのがめんどうになると思います。 ファイルの1行が固定長であれば、freadを使う意味はあります。
お礼
お世話になります。 fgetsを使ったほうが楽とおっしゃっていたので、 「fgetsが出来なくてfreadで出来るか!」 という勢いでfgetsを使って挑戦してみました。 やはりこちらでもカンマを処理した後の次に取り込むbuff2への書き込み位置の変更に悩みましたが、変数を増やしてmemcpyを使うことによって出来ました。 この勢いでfreadでも出来たらなと思います。 ありがとうございました。
補足
前回に引き続き返答していただきありがとうございます。 freadを使って処理するのが課題ということで今回はfgetsを使えないのです。 毎度ためになるお話ありがとうございます。
- SilverThaw
- ベストアンサー率32% (260/806)
>まだchar型とポインタを比べてることになっているので正しくないんですよね? >正直、どうすればいいかわかりません。 回答の前に、 何処からNULLで終端を確認しなければいけないと判断したか教えてください。 >あと、今のままでは名前3の後が改行ではないので表示されることないですよね・・・。 >どうすれば表示されるようになるでしょうか。 少なくとも、今の処理ですべてを行うことは無理でしょう。 まず、「全体の長さ」か「ファイル終端」を判断するための方法から検討する必要があります。 >これも前回言われましたが while内の1つ目のif文の所で、カンマを処理したので次に取り込むbuff2への書き込み位置の変更というのもわかりません。 バッファのある位置に、カンマが入っているのであれば、同じ位置に改行コードが入っていることはあり得ないので、次から確認すべきという意味でしょう。
お礼
課題の方ですが、なんとかできました。 2度の返答ありがとうございました。
補足
返答ありがとうございます。 NULLじゃなくて『\0』ってやるべきだったんですね。 同じものだと勘違いしていました。 まだ学び始めて日が浅いもので…迷惑かけます。
お礼
度重なる質問に答えていただきありがとうございました。 課題はなんとかできました。 今後のためのお言葉とアドバイスありがとうございました。
補足
返答ありがとうございます。 では、 while((buff2[n] = buff1[n]) != '\0') という部分は比較対象として合ってると考えていいってことなんですよね?