链表与文件的读取与保存有关问题,求大神帮看看,给跪了

链表与文件的读取与保存问题,求大神帮看看,给跪了
void save(struct goods *head)
{ struct goods *p1;
FILE *fp;
p1 = head;

fp=fopen("date.txt","w");
while (p1!=NULL)
{
fprintf(fp,"%d %s %d %d\n",p1->ID,p1->name,p1->price,p1->count);
p1 = p1->next;
}
fclose(fp);
printf("保存成功\n");


}
struct goods *readInfo()
{
struct goods *p1,*p2,*head;
FILE *fp;
int flag;
n=0;
fp = fopen("date.txt","r");
while ((fp=fopen("date.txt","r"))==NULL)
{
printf("加载文件失败");

}





head = NULL;
p1 = p2 = (struct goods *)malloc(sizeof(struct goods));
flag = fscanf(fp,"%d %s %d %d\n",&p1->ID,p1->name,&p1->price,&p1->count);

while(!feof(fp)){
n = n+1;
if( n == 1 )
{
head = p1;
}
else{
p2->next = p1;
}
p2 = p1 ;
p1 = (struct goods *)malloc(sizeof(struct goods));
fscanf(fp,"%d %s %d %d\n",&p1->ID,p1->name,&p1->price,&p1->count);

};
fclose(fp);
p2->next = NULL;
free(p1);
save(head);
return head;
}

现在问题是每次读取都少了一行,打断点看,是读取的时候每次少读取一行,各位大神帮看看为什么每次都会少读取一组数据呢。
------解决思路----------------------
修改如下:

void save(struct goods *head)
{
struct goods *p1;
FILE *fp;
p1 = head;

fp = fopen("date.txt", "w");
while (p1 != NULL)
{
fprintf(fp, "%d %s %d %d\n", p1->ID, p1->name, p1->price, p1->count);
p1 = p1->next;
}
fclose(fp);
printf("保存成功\n");
}
struct goods *readInfo()
{
struct goods *p1, *p2, *head;
FILE *fp;
int flag;
n = 0;
while ((fp = fopen("date.txt", "r")) == NULL)
{
printf("加载文件失败");
}
head = NULL;
while(1)
{
p1 = (struct goods *)malloc(sizeof(struct goods));
if (4 != fscanf(fp, "%d %s %d %d\n", &p1->ID, p1->name, &p1->price, &p1->count)) break;
n = n + 1;
if (n == 1)
{
head = p1;
}
else 
{
p2->next = p1;
}
p2 = p1;
};
fclose(fp);
p2->next = NULL;
free(p1);
save(head);
return head;
}

------解决思路----------------------
不要使用
while (条件)
更不要使用
while (组合条件)
要使用
while (1) {
 if (条件1) break;
 //...
 if (条件2) continue;
 //...
 if (条件3) return;
 //...
}
因为前两种写法在语言表达意思的层面上有二义性,只有第三种才忠实反映了程序流的实际情况。
典型如:
下面两段的语义都是当文件未结束时读字符
while (!feof(f)) {
 a=fgetc(f);
 //...
 b=fgetc(f);//可能此时已经feof了!
 //...
}
而这样写就没有问题:
while (1) {
 a=fgetc(f);
 if (feof(f)) break;
 //...
 b=fgetc(f);
 if (feof(f)) break;
 //...
}
类似的例子还可以举很多。