您的位置:首页 > 编程语言 > C语言/C++

基于链表的学生成绩管理系统——C++二进制文件读写string对象时出现的错误

2016-10-17 11:05 639 查看
昨天晚上做C++的大作业,没错,就是经典的学生成绩管理系统。编译通过,一切正常。运行时,系统中输入其他命令(像insert啊,search啊,count啊blabala…)都能正常运行,但是输入exit命令退出系统时就出错。可以判断,是最后退出时,我的链表类析构时出现了问题。

错误的提示信息有两条如下:

_Mycont CXX0030: Error: expression cannot be evaluated
_Myfirstiter CXX0030: Error: expression cannot be evaluated


出错的位置定位如下图所示:



上网搜索后发现是读写二进制文件的锅。我的链表节点里含有string对象,而string对象里包含指针。每次打开程序构造链表时会从二进制文件读取上次保存的信息,那么这个指针也会被读进来,但是这个指针已经失效了,它指向的地址在这次运行时并没有申请,所以析构对象时,去释放它指向的地址是非法的。

链表节点的部分代码:

class StuNode
{
friend class StuList;

std::string name_; //string对象
int number_;
std::string sex_; //string对象
...
StuNode *next_;

public:
....
}


写入二进制文件的load()函数(在链表构造函数中调用):

void StuList::save()
{
FILE* pFile = fopen("save.dat", "wb");

for(StuNode *ptr = head_->next_;ptr!=NULL;ptr=ptr->next_)
{
fwrite(ptr,sizeof(StuNode),1,pFile);//这里虽然将链表的指针也写进了文件,但是读文件重新建立链表时,指针将被新申请的地址替代,不会出错
}

fclose(pFile);
}


这个问题我想到的解决方法:

1.使用字符串类型时用C风格的char *。

2.仍然使用string类,写入二进制文件时不将每个节点作为一个单元写入,当遇到string对象时,只将字符串读出,对象中的其他内容不读。注意,这样的话load()函数也要对应修改。

这里采用第二种方法。

void StuList::save()//为了防止保存指针,逐一保存数据域中各项
{
FILE* pFile = fopen("save.dat", "wb");

for(StuNode *ptr = head_->next_;ptr!=NULL;ptr=ptr->next_)
{
//遇到string对象保存字符串大小和字符串内容
std::string::size_type strsize=ptr->name_.size();
fwrite(&strsize,sizeof(strsize),1,pFile);
for(std::string::iterator it=ptr->name_.begin();
it!=ptr->name_.end();it++)
{
fwrite(&(*it),sizeof(char),1,pFile);
}

fwrite(&(ptr->number_),sizeof(int),1,pFile);
fwrite(&(ptr->birthday_),sizeof(Date),1,pFile);
... ...
}

fclose(pFile);
}


读取string对象时先读字符串大小,用一临时char型变量ch逐个读取字母,string::push_back(ch)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息