基於鏈表的學生成績管理系統——C++二進制文件讀寫string對象時出現的錯誤

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章