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

来源:互联网 发布:疯狂java讲义 豆瓣 编辑:程序博客网 时间:2024/06/14 23:09

昨天晚上做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)。

0 0
原创粉丝点击