关于C++链表类文件的写入与读取,出现-858993460

llllllllllx 2015-03-18 10:43:22
#include <iostream>
#include <string>
#include <fstream>
#include <cstdlib>
#include <list>
#include <algorithm>
#include <ctime>

using namespace std;

class Stu
{
private:
int num;
int grade;
string name;
string sex;
string birth;
string profession;
string adress;
public:
Stu(){}
~Stu(){}

void SetStu(int nnum, int ngrade, string nname, string nsex, string nbirth, string nprofession, string nadress)
{
num = nnum;
grade = ngrade;
name = nname;
sex = nsex;
birth = nbirth;
profession = nprofession;
adress = nadress;
}

int GetNum()
{
return num;
}
int GetGrade()
{
return grade;
}
string GetName()
{
return name;
}
string GetSex()
{
return sex;
}
string GetAdress()
{
return adress;
}
string GetProfession()
{
return profession;
}
string GetBirth()
{
return birth;
}
friend class List;
};

struct Node
{
Stu data;
Node *next;
};

class List
{
private:
Node *head;
public:
friend class Stu;
List(){ head = NULL; }
void AddList();
void DelList();
void ShowList();
void SaveList();
void LoadList();
void Search();
Node* GetHead(){ return head; }
};

void List::ShowList()
{
Node *current = head;
if (head == NULL)
{
cout << "没有学生信息!" << endl;
}
while (current!=NULL)
{
cout << current->data.GetNum();
cout << current->data.GetName();
cout << current->data.GetSex();
cout << current->data.GetBirth();
cout << current->data.GetProfession();
cout << current->data.GetGrade();
cout << current->data.GetAdress();
current = current->next;
cout << endl;
}
}

void List::AddList()
{

int n;
cout << "请输入新建学生个数:";
cin >> n;
Stu *ptr1 = new Stu[n];
Node *ptr2 = new Node[n];
int nnum, ngrade;
for (int i = 0; i<n; i++)
{
string nname, nsex, nbirth, nprofession, nadress;
Node *p, *s;
cout << "请输入学生姓名:";
cin >> nname;
cout << endl << "请输入学生学号:";
cin >> nnum;
cout << endl << "请输入学生性别:";
cin >> nsex;
cout << endl << "请输入学生英语成绩:";
cin >> ngrade;
cout << endl << "请输入学生生日:";
cin >> nbirth;
cout << endl << "请输入学生专业:";
cin >> nprofession;
cout << endl << "请输入学生住址:";
cin >> nadress;
ptr1[i].SetStu(nnum, ngrade, nname, nsex, nbirth, nprofession, nadress);
ptr2[i].data = ptr1[i];
s = (Node*)new(Node);
s->data = ptr1[i];
p = head;
if (head == NULL)
{
head = s;
s->next = NULL;
}
else
{
while (p->next!=NULL)
{
p = p->next;
}
{
p->next = s;
s->next = NULL;
}
}
}
delete[] ptr1;
delete[] ptr2;

}

void List::DelList()
{
int dnum;
cout << "请输入要删除学生的编号" << endl;
cin >> dnum;
Node *p, *q;
p = head;
if (p == NULL)
{
return;
}
if (p->data.num == dnum)
{
head = p->next;
delete p;
}
else
{
while (p->data.num != dnum&&p->next != NULL)
{
q = p;
p = p->next;
if (p->data.num == dnum)
{
q->next = p->next;
delete p;
}
}
}
}

void List::SaveList()
{
ofstream fList("Stu.txt", ios::out);
Node *p = head;
while (p)
{
fList << p->data.GetNum() << p->data.GetName() << p->data.GetSex() << p->data.GetGrade() << p->data.GetProfession() << p->data.GetAdress() << p->data.GetBirth();
p = p->next;

}
}

void List::LoadList()
{

ifstream fList("Stu.txt", ios::in);
if (!fList)
{
cerr << "open error!" << endl;
abort();
}
while (!fList.eof())
{
int tnum;
int tgrade;
string tname;
string tsex;
string tbirth;
string tprofession;
string tadress;
Node *p, *q;
if (head == NULL)
{

p = new Node();
fList >> tnum >> tname >>tsex >> tgrade >> tprofession >> tadress >> tbirth;
p->data.SetStu(tnum, tgrade, tname, tsex, tbirth, tprofession, tadress);
head = p;
head->next = NULL;
}
else
{
q = head;
p = new Node();
fList >> tnum >> tname >> tsex >> tgrade >> tprofession >> tadress >> tbirth;
p->data.SetStu(tnum, tgrade, tname, tsex, tbirth, tprofession, tadress);
while (q->next != NULL)
{
q = q->next;
}
q->next = p;
p->next = NULL;
}
}

}


void menu()
{
cout << endl;
cout << "\t\t***********************************************" << endl;
cout << "\t\t** **" << endl;
cout << "\t\t** 学生信息管理系统主菜单 **" << endl;
cout << "\t\t** **" << endl;
cout << "\t\t** 1. 新增学生信息 **" << endl;
cout << "\t\t** 2. 删除学生信息 **" << endl;
cout << "\t\t** 3. 导入学生信息 **" << endl;
cout << "\t\t** 4. 学生信息搜索(按姓名) **" << endl;
cout << "\t\t** 5. 学生信息统计 **" << endl;
cout << "\t\t** 6. 按英语成绩排序 **" << endl;
cout << "\t\t** 7. 学生信息保存 **" << endl;
cout << "\t\t** 8. 显示学生信息 **" << endl;
cout << "\t\t** 0. 退出 **" << endl;
cout << "\t\t** **" << endl;
cout << "\t\t***********************************************" << endl;
cout << endl;
}

void domain()//主菜单函数实现
{
List S;
while (1)
{
system("cls");
menu();
cout << "请选择数字编号1~8" << endl;
int i1;
cin >> i1;
while (!(i1 >= 0 && i1 <= 8))
{
cout << "输入有误请重新输入" << endl;
cin >> i1;
}
switch (i1)
{
case 1:S.AddList(); break;
case 2:S.DelList(); break;
case 3:S.LoadList(); break;
//case 4:S.Search(); break;
//case 5:Sl.Statistic(); break;
//case 7:Sl.Sort(); break;
case 7:S.SaveList(); break;
case 8:S.ShowList(); break;
case 0:cout << "系统退出" << endl; exit(0);
default:break;
}
cout << "是否返回主菜单? Y/N" << endl;
string p;
cin >> p;
if (p == "n" || p == "N")
{
cout << "系统退出" << endl;
exit(0);
}
getchar();

}

}


int main()
{
menu();
domain();
return 0;
}
...全文
478 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
llllllllllx 2015-03-20
  • 打赏
  • 举报
回复
引用 11 楼 sublimepan 的回复:
加打印信息看看吧,代码里导入操作,在调用load函数前先把链表内容打印出来,然后每读取一组数据后都把链表内容打印出来,看究竟哪里出错了。
你好我经过单步执行操作发现,那个while多循环了一次,然后而且都是在最后一个节点多循环了一次。难道while (!fList.eof())有错误。参考其他代码都是这样写的。我不清楚现在我该怎么改了,虽然我已经知道了问题所在。但是什么原因还是不懂,也不懂怎么修改。
llllllllllx 2015-03-20
  • 打赏
  • 举报
回复
引用 10 楼 zhao4zhong1 的回复:
代码功能归根结底不是别人帮自己看或讲解或注释出来的;而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒:再牛×的老师也无法代替学生自己领悟和上厕所! 单步调试和设断点调试(VS IDE中编译连接通过以后,按F10或F11键单步执行,按Shift+F11退出当前函数;在某行按F9设断点后按F5执行停在该断点处。)是程序员必须掌握的技能之一。
你好,我觉得你说的很有道理,之前我没有按照你说的那样调试代码只是自己读靠逻辑分析,用了断点和单步操作。思路更加清晰了,但是我看了一下程序运行情况。while (!fList.eof()),在我读完所有数据的时候,这个判定没有生效。而是又执行了一次while里面的语句之后才跳出while的。参考其他代码,都是根据这个语句来判定是否读完文件的。我现在已经知道了问题所在。但是解决方法与具体原因还想请教一下其他有经验的人。很感谢你。之前都没用过断点单步执行等操作。
赵4老师 2015-03-20
  • 打赏
  • 举报
回复
不要使用
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;
 //...
}
类似的例子还可以举很多。
llllllllllx 2015-03-20
  • 打赏
  • 举报
回复
经过我不断的查找资料,终于找到了跟我一样的问题。最终解决的这个问题~这里给大家贴出原因和解决办法。
llllllllllx 2015-03-19
  • 打赏
  • 举报
回复
void List::SaveList()
{
ofstream fList("Stu.txt", ios::out);
Node *p = head;
while (p)
{
fList << p->data.GetNum() << " " << p->data.GetName() << " " << p->data.GetSex() << " " << p->data.GetGrade() << " " << p->data.GetProfession() << " " << p->data.GetAdress() << " " << p->data.GetBirth() << " ";
p = p->next;

}
}

void List::LoadList()
{
int tnum;
int tgrade;
string tname;
string tsex;
string tbirth;
string tprofession;
string tadress;
ifstream fList("Stu.txt", ios::in);
if (!fList)
{
cerr << "open error!" << endl;
abort();
}
while (!fList.eof())
{

Node *p, *q;
if (head == NULL)
{

p = new Node();
fList >> tnum >> tname >> tsex >> tgrade >> tprofession >> tadress >> tbirth;
p->data.SetStu(tnum, tgrade, tname, tsex, tbirth, tprofession, tadress);
head = p;
head->next = NULL;
}
q = head;
p = new Node();
fList >> tnum >> tname >> tsex >> tgrade >> tprofession >> tadress >> tbirth;
p->data.SetStu(tnum, tgrade, tname, tsex, tbirth, tprofession, tadress);
while (q->next != NULL)
{
q = q->next;
}
q->next = p;
p->next = NULL;
}


经过楼上的解答,这是修改过后的代码。楼下贴出运行结果。
llllllllllx 2015-03-19
  • 打赏
  • 举报
回复
引用 4 楼 sublimepan 的回复:
检查你读取的文件,各个数据是否分隔开了
我按你说的做了隔开了,读取的数据又出现了新的问题。你能不能在帮我看一下。我楼下贴新代码和图。
赵4老师 2015-03-19
  • 打赏
  • 举报
回复
代码功能归根结底不是别人帮自己看或讲解或注释出来的;而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒:再牛×的老师也无法代替学生自己领悟和上厕所! 单步调试和设断点调试(VS IDE中编译连接通过以后,按F10或F11键单步执行,按Shift+F11退出当前函数;在某行按F9设断点后按F5执行停在该断点处。)是程序员必须掌握的技能之一。
llllllllllx 2015-03-19
  • 打赏
  • 举报
回复
引用 8 楼 sublimepan 的回复:
你导入信息时,需要保留之前的数据吗?如果不需要,先将链表清空吧。如果需要,只导入再显示,测试一下,应该能正常显示的。
你好,就是我上面的导入操作是在关闭程序重启程序后的操作。我分析了一晚上也没有分析出什么逻辑错误,真的很痛不知道你能不能帮我解决一下。
sublimepan 2015-03-19
  • 打赏
  • 举报
回复
加打印信息看看吧,代码里导入操作,在调用load函数前先把链表内容打印出来,然后每读取一组数据后都把链表内容打印出来,看究竟哪里出错了。
sublimepan 2015-03-19
  • 打赏
  • 举报
回复
你导入信息时,需要保留之前的数据吗?如果不需要,先将链表清空吧。如果需要,只导入再显示,测试一下,应该能正常显示的。
llllllllllx 2015-03-19
  • 打赏
  • 举报
回复
将个数据通过空格分割后再次读取的时候不会出现神秘代码了。但是随之而来了又有新的问题。多读取了一个节点。不是ShowList()函数的错误,那个函数没有问题。应该还是读取文件的问题。可是为什么会多个数据呢。


然后文件里的是 1 1 1 1 1 1 1 2 2 2 2 2 2 2

求教!
sublimepan 2015-03-18
  • 打赏
  • 举报
回复
检查你读取的文件,各个数据是否分隔开了
llllllllllx 2015-03-18
  • 打赏
  • 举报
回复
读取文件是load()函数怎么修改啊,快到上交时间了。
llllllllllx 2015-03-18
  • 打赏
  • 举报
回复
我写入文件是正确的,这里我学号姓名之类的全是1 1 1 1 1 2 2 2之类的文件截图
然后 进行读取函数时
llllllllllx 2015-03-18
  • 打赏
  • 举报
回复
这是C++专周的一个作业,学生管理系统。因为还没有写完,就把写了一半的代码放了上来。在文件读写的地方发生了问题。文件读写的函数是
void List::SaveList()
{
	ofstream fList("Stu.txt", ios::out);
	Node *p = head;
	while (p)
	{
		fList << p->data.GetNum() << p->data.GetName() << p->data.GetSex() << p->data.GetGrade() << p->data.GetProfession() << p->data.GetAdress() << p->data.GetBirth();
		p = p->next;

	}
}

void List::LoadList()
{

	ifstream fList("Stu.txt", ios::in);
	if (!fList)
	{
		cerr << "open error!" << endl;
		abort();
	}
	while (!fList.eof())
	{
		int tnum;
		int tgrade;
		string tname;
		string tsex;
		string tbirth;
		string tprofession;
		string tadress;
		Node *p, *q;
		if (head == NULL)
		{

			p = new Node();
			fList >> tnum >> tname >>tsex >> tgrade >> tprofession >> tadress >> tbirth;
			p->data.SetStu(tnum, tgrade, tname, tsex, tbirth, tprofession, tadress);
			head = p;
			head->next = NULL;
		}
		else
		{
			q = head;
			p = new Node();
			fList >> tnum >> tname >> tsex >> tgrade >> tprofession >> tadress >> tbirth;
			p->data.SetStu(tnum, tgrade, tname, tsex, tbirth, tprofession, tadress);
			while (q->next != NULL)
			{
				q = q->next;
			}
			q->next = p;
			p->next = NULL;
		}
	}

}
因为怕你们有疑问就把我的半成品全放上来了。希望你们可以自己运行一下我不知道该怎么修改。C++老师很坑爹。当时也没有听太懂,还是要靠自己问。

64,637

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧