这个问题和利用变量接收输出数据导致最后一行重复输出的原理是一样的,问题都在feof函数的身上!
忘记原理的同学们请仔细看一下关于变量重复输出的博客,在这里就不讲那么详细了,C/C++用变量访问输出文件,出现最后一条数据重复输出两次的原因解析
他们的问题都是feof造成了最后一行的错误输出,不同之处就是,链表会使得多出的那一行为乱七八糟的数据,而变量则是与是一条数据一样的重复输出。
上代码:
while(!feof(fp))
{
p=new mNode;//生成新结点
fread(&(p->data),sizeof(Member),1,fp);//将数据从文件中读取
r->next=p;
p->next=NULL;
//插入结点到表尾
r=p;//指向新的尾结点
}
p = L->next;
printf("\n\tID\t姓名\t性别\t关系\t联系电话\n");
while(p!=NULL)
{
printf("\t%d",p->data.ID);//输出ID
printf("\t%s",p->data.Name);//输出姓名
printf("\t%s",p->data.Gender);//输出性别
printf("\t%s",p->data.List);//输出关系
printf("\t%s\n",p->data.Tel);//输出联系电话
p = p->next;//将p指向下一条数据
}
输出结果:
原因:
最后一行乱码是因为feof的读取,文件结束,但是feof无法判断,他就没有读取任何东西,但是开辟了一个新链表空间出来在链表最后.
不同的是变量是存储了上一次的数据,但是链表是新来的,刚开辟的新空间,所以里面是磁盘某段数据,因此采用变量接受输出数据会出现的是,重复输出,而链表是输出一堆乱七八糟的数据。
解决:
- 是feof函数的错误判断导致链表多开辟一块空间,只要像变量重复输出的解决方法一样——在开辟链表空间之前,加一个if判断一下文件指针是否到达文件末尾即可,如下:
while(!feof(fp))
{
Member str;//临时变量
if(fread(&str,sizeof(Member),1,fp))//判断文件指针是否到达文件末尾,就是看是否还能读出数据
{
p=new mNode;//生成新结点
p->data=str;
r->next=p;
p->next=NULL;
//插入结点到表尾
r=p;//指向新的尾结点
}
else
break;
}
p = L->next;
printf("\n\tID\t姓名\t性别\t关系\t联系电话\n");
while(p!=NULL)
{
printf("\t%d",p->data.ID);//输出ID
printf("\t%s",p->data.Name);//输出姓名
printf("\t%s",p->data.Gender);//输出性别
printf("\t%s",p->data.List);//输出关系
printf("\t%s\n",p->data.Tel);//输出联系电话
p = p->next;//将p指向下一条数据
}
- 既然开辟了多一个的链表空间,只要阻止最后一条数据的输出即可:
while(!feof(fp))
{
p=new mNode;//生成新结点
fread(&(p->data),sizeof(Member),1,fp);//将数据从文件中读取
r->next=p;
p->next=NULL;
//插入结点到表尾
r=p;//指向新的尾结点
}
p = L->next;
printf("\n\tID\t姓名\t性别\t关系\t联系电话\n");
while(p->next!=NULL)//防止最后一句的输出
{
printf("\t%d",p->data.ID);//输出ID
printf("\t%s",p->data.Name);//输出姓名
printf("\t%s",p->data.Gender);//输出性别
printf("\t%s",p->data.List);//输出关系
printf("\t%s\n",p->data.Tel);//输出联系电话
p = p->next;//将p指向下一条数据
}
正确输出结果:
注意:秉承降低空间复杂度的需求,建议使用第一种方法~