0

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;
}
4

3 に答える 3

1

初心者向けの私のお気に入りのアドバイスは、小さくてシンプルに始めて、完全に機能するようにしてから、少しずつ複雑さを加えて、すべてのステップでテストすることです。ここには 3 つの独立した関数があります。基本的なリスト、リストへのランダムな値の割り当て、およびリストの読み取り/書き込みです。これらを個別に開発してから、それらを組み合わせる必要があります。どの部分が問題を引き起こしているのかわからないということは、それらを一度に書き込もうとしたことを示しています。(まぁ、それぞれの暗号が絡み合っていることもそれを物語っていますが)

最大の問題は、ファイル読み取りコードにあります (これは、すべての場所の既定のコンストラクタにあります)。初期化されていないメモリにデータを入れています:

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

それは、最初にカップを見つけずにホット コーヒーを注ぐようなものです。複雑な型で試す前に、charのような単純な型で読み取り/書き込みを行い、これを行わないように学習する必要があります。int次に、単一の で読み取り/書き込みを試みますlink。それからそれらの束で。

于 2012-09-21T03:03:27.767 に答える
0

ベータ版ですでに示したように、リンクを読み取ろうとするとアクセス違反が発生します。

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

「current」はポインタであり、「&」演算子を使用すると、変数自体(スタック上のどこか)が占めるメモリへのポインタが得られます。したがって、コードはリンクサイズのガベージデータのチャンクをこのポインタに読み込もうとしますが、これによってアクセス違反が発生することはありません。例外は、「current」が逆参照され、それが指す「link」オブジェクトのメンバーに書き込むために使用される場合に発生します。

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));

この操作が成功した場合は、ヒープ「リンク」オブジェクトを割り当てて作成し、それを前のノードに接続します。

next_tail = new link(temp_data, 0);
tail->another = next_tail;
tail = next_tail;
于 2012-09-21T04:36:03.523 に答える
0

プログラムでポインタ操作を行っているため、不正なメモリアクセス0xC0000005が原因でエラーが発生します。完全なコードを提供していないため、プログラムの他の部分でポインターを初期化しないなどの不正な操作を行っている可能性があります。

于 2012-09-21T01:41:10.837 に答える