使用c ++通过文件存储和检索链表

时间:2012-09-21 01:18:48

标签: c++ file linked-list store

我已经创建了一个使用c ++存储和检索链表的程序,但不幸的是我的程序没有正确检索数据并返回代码0xC0000005。我的计划有什么问题?我是初学者。

//C++ code
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <cstring>
#include <ctime>

using namespace std;

struct link
{
    link(int dat, link *nxt): data(dat), another(nxt)
    {
    }
    int data;
    link *another;
};

struct list
{
    link *first;
    ~list();
    list();
    void addnew();
    void displl();
}list;

list::list()
{
    fstream datafile;
    datafile.open("datafile", ios::in | ios::app);
    datafile.seekg(0, ios::end);
    int eb = datafile.tellg();
    if(!eb)
    {
        first = NULL;
        return;
    }
    datafile.seekg(0, ios::beg);
    link *head, *current, *preceding;
    head = preceding = current = NULL;
    while(eb)
    {
        if(!current)
        {
            datafile.read((char *)&current, sizeof(link));
            current->another = NULL;
            head = current;
        }
        preceding = current;
        datafile.read((char *)&current->another, sizeof(link));
        current = current->another;
        current->another = NULL;
        preceding->another = current;
        eb--;
    }
    first = head;
}

void list::addnew()
{
    srand(time(0) + rand());
    first = new link(rand()%10, first);
}

void list::displl()
{
    link *current;
    cout << endl << " - ";
    for(current = first; current; current = current->another)
        cout << current->data << " - ";
    cout << endl;
}

list::~list()
{
    fstream datafile;
    datafile.open("datafile", ios::out | ios::app);
    link *temp;
    while(first != NULL)
    {
        temp = first;
        first = first->another;
        datafile.write((char *)&temp, sizeof(link));
        delete temp;
    }
    first = NULL;
}

int main()
{
    list.addnew();
    list.addnew();
    list.addnew();
    list.displl();
    system("pause");
    return 0;
}

2 个答案:

答案 0 :(得分:0)

由于非法内存访问而导致0xC0000005错误,因为您正在程序中执行指针操作。因为您没有提供完整的代码,所以您可能正在进行非法操作,例如不在程序的其他部分初始化指针。

答案 1 :(得分:0)

正如Beta已经指出的那样,尝试阅读链接时会发生访问冲突:

     ...
datafile.read((char *)&current, sizeof(link));
     ...

“current”是一个指针,使用“&amp;” operator on it给出了一个指针,指向变量本身占用的内存(在堆栈的某个地方)。因此,代码尝试将一些链接大小的垃圾数据块读入此指针 - 但这不会导致访问冲突。当“current”被取消引用并用于写入它指向的“链接”对象的成员时,会发生异常:

current->another = NULL;

从数据文件加载的值来自类似错误的序列化代码 - 没有保存“链接”数据。所有文件都包含来自堆上分配的“链接”对象的旧内存地址 - 这些地址无效,因为它们的内存是在以前的程序会话中分配的。

成功序列化对象的字节图像如下所示:

datafile.write(reinterpret_cast<const char*>(temp), sizeof(*temp));

但是“链接”对象不是普通的旧数据 - 在您销毁此链接对象后,它包含的指针将无效。因此,加载列表必须包括为每个链接分配内存(如“addnew”)。

您可能只想从头开始走列表,并保存每个链接的有效负载数据,如下所示:

datafile.write(reinterpret_cast<const char*>(&temp->data), sizeof(temp->data));

然后,要加载列表,请为每个节点将有效负载读入临时变量:

datafile.read(reinterpret_cast<char*>(&temp_data), sizeof(temp_data));

如果此操作成功,请分配并构造堆“link”对象并将其连接到上一个节点:

next_tail = new link(temp_data, 0);
tail->another = next_tail;
tail = next_tail;