みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

ソースを観てくれませんか。

こんにちは。C言語で書きました。
関数内でCSVファイルからデータを読み取り、そのデータをリストに入れて、先頭を指すポインタをmain内に返すと言う作業をさせたくて書いたソースです。なぜ無限ループするのか分かりません。
どなたか教えていただけませんか?
以下ソース

#include <stdio.h>
#include <stdlib.h>

struct account{
int ID;
char Sname[50];
char Fname[50];
char Adress[100];
int Sex;
int Age;
char Group[100];
struct account *next;
};

struct account *Rfile(char *FileName,struct account *top);

int main(void)
{
char FileName[FILENAME_MAX];
struct account *top,*q;
top = NULL;

printf("読み込むファイルの名前を入力してください>>>");
scanf("%s",FileName);

q = Rfile(FileName,top);

return 0;

}

struct account *Rfile(char *FileName,struct account *top)
{
FILE *fp;
char filename[FILENAME_MAX];
int ret;

struct account *new;
new = (struct account *) malloc(sizeof(struct account));
new->next = NULL;


strcpy(filename,FileName);

if( (fp = fopen( filename,"r")) == NULL)
{
printf("ファイルが見つかりません。>>>%s\n",filename);
//exit(EXIT_FILURE);
}
while( (ret = fscanf( fp, "%d,%[^,],%[^,],%[^,],%d,%d,%[^,]", &(new->ID), new->Sname, new->Fname, new->Adress, &(new->Sex), &(new->Age), new->Group ) ) != EOF )//ファイルの最後でないなら
{
printf("%d,%s,%s,%s,%d,%d,%s",new->ID,new->Sname,new->Fname,new->Adress,new->Sex,new->Age,new->Group);

if(top != NULL){
while(top->next != NULL){
top = top->next;
}
top = new;
}
else{//top == NULL
top = new;
}

new = NULL;

new = (struct account *) malloc(sizeof(struct account));
new->next = NULL;

}

fclose(fp);

return top;

}

投稿日時 - 2011-06-22 00:00:30

QNo.6826714

困ってます

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

まず、他の場所のロジックは確認していません。その点はご了承を。


fscanfの仕様だと、「0個以上の読み込みに成功/残りは変換フォーマットと不一致」のときはEOFではなく成功した個数が返ります。そして、次は読み込みが成功した後から始まるので、だいたいは続いて不一致となります。

例えば、この例なら
最初の%dに対して、入力が数字でなかった
→戻り値 は 0(!=EOF)
→次のfscanfは上の「数字でなかった」ところから始まる
→やはり最初の%dで不一致
→戻り値 は 0(!=EOF)
→次のfscanfは上の「数字でなかった」ところから始まる
以下永遠に続く

となります。
どっかで、カンマの数が違うとかがあるのではないでしょうか
あるいは、このやり方では"で括った中身を別扱いしてくれないので、"AAA,BBB"などとあったら"AAAとBBB"に別れてしまいます。

EOFによる終了チェックだけではなく、全部読めているかの確認も必要です

投稿日時 - 2011-06-22 01:16:18

お礼

ご指摘のようにカンマ不足でした。
なんとか完成までこぎつけられました!
ありがとうございました!

投稿日時 - 2011-06-22 07:32:35

ANo.1

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(3)

ANo.3

入門者のようだから、(f)scanf のメモリ破壊や、スペースが含まれているファイル名が指定できないのは放置するね。

「"%d,%[^,],%[^,],%[^,],%d,%d,%[^,]"」

最後の %[^,] って次の行の数字まで読み込んでるような気がするけど大丈夫かな?


あと、引数の top は NULL だから渡してもいみないよ。
あと、top って名前付けてるけど、last になってるとおもう。


はじめに c やらせて、崖に突き落とすと、今後の学習でなにか有利なのかなぁ~。なぞ。

投稿日時 - 2011-06-22 06:40:55

お礼

ありがとうございました。指摘されたことをもとにして改良し無事に完成することができました。本当に助かりました!ありがとうございました。

投稿日時 - 2011-06-22 07:28:57

ANo.2

無限ループとは関係ありませんが, #1 で指摘されたところを直しても期待したリンクリストはできません.

投稿日時 - 2011-06-22 01:31:28

お礼

改良してなんとかできました!
アドバイスありがとうございました。

投稿日時 - 2011-06-22 07:30:52

あなたにオススメの質問