0

各行に2つの列があり、最初の列がテール頂点で、2番目の列がヘッド頂点であるテキストファイルを読み取って、有向グラフを作成しようとしています。現在、コードが機能するかどうかをテストするために、グラフにデータを入力して印刷しようとしています。

ノードを挿入するたびにグラフを印刷しています。グラフの印刷は、3番目のノード「4」を挿入するまでは問題なく機能します。その後、最初のノードが1から0に変わります。理由はわかりません。ノードポインタをエッジに格納するのは良い考えではないかと思います。私はすでに「ノード」ベクトルにノード情報を持っているので、それを複製したくないので、それを行っています。

入力テストファイル:

1 2
4 5

私のデータ構造は次のとおりです。ノード:ノードIDとブール変数ノードを保持しますダーティエッジ:テールノードとヘッドノードへのポインターを保持しますグラフ:すべてのノードとエッジのベクトルを保持します

出力:

Pushing :1
print called
Nodes are:
1

Pushing :2
print called
Nodes are:
1
2

Pushing :4
print called
0(0) --> 2(0)     // Problem this should have been 1(0) --> 2(0)
Nodes are:
1
2
4



#include <iostream>
#include <vector>
#include <fstream>
#include <string>
#include <sstream>

using namespace std;

class node {
public:
    node() {}
    node(int _nodeId, bool dirty);
    int nodeId;
    bool dirty;
    void operator=(node rhs);
    bool operator==(node rhs);
};

class edge {
public:
    edge(node *_startNode, node *_endNode): startNode(_startNode), endNode(_endNode) {}
    node *startNode, *endNode;
};



node :: node(int _nodeId, bool _dirty) {
    nodeId = _nodeId;
    dirty = _dirty;
}

void node :: operator=(node rhs) {
    this->dirty = rhs.dirty;
    this->nodeId = rhs.nodeId;
}

bool node :: operator==(node rhs) {
    if (this->nodeId == rhs.nodeId) {
        return true;
    }
    return false;
}



class graph {
public:
    void print();
    void addEdge(node startNode, node endNode);
    void addNode(node n);
    void dfs(node s);
private:
    vector<edge> edges;
    vector<node> nodes;
};

void graph :: addNode(node n) {
    // only add this node if it does not exist in the graph
    if (find(nodes.begin(), nodes.end(), n) == nodes.end()) {
        //print();
        cout <<  "Pushing :"<<n.nodeId<<endl;
        nodes.push_back(n);
    }
    print();
    cout << endl;
}

void graph :: dfs(node s) {
    // Search node s and mark it as dirty


}
void graph :: print() {
    cout << "print called\n";
    vector<edge>::iterator itr = edges.begin();
    while (itr != edges.end()) {
        cout << itr->startNode->nodeId << "("<< itr->startNode->dirty<<") --> ";
        cout << itr->endNode->nodeId << "("<< itr->endNode->dirty<<")"<<endl;
        ++itr;
    }

    cout << "Nodes are:\n";
    for (int i=0; i< nodes.size(); ++i) {
        cout << nodes.at(i).nodeId << endl;
    }
}

void graph :: addEdge(node startNode, node endNode) {
    vector<node>::iterator itrStartNode;
    itrStartNode = find(nodes.begin(), nodes.end(), startNode);
    vector<node>::iterator itrEndNode;
    itrEndNode = find(nodes.begin(), nodes.end(), endNode);
    edge e(&(*itrStartNode), &(*itrEndNode));
    edges.push_back(e);
}


int main(int argc, char *argv[]) {
    graph g;
    // Read the file here
    ifstream file;
    file.open("test.txt", ios::in);
    string line;
    while (getline(file, line)) {
        int startNodeId, endNodeId;
        istringstream is(line);
        is >> startNodeId >> endNodeId;
        node startNode(startNodeId, false);
        node endNode(endNodeId, false);
        g.addNode(startNode);
        g.addNode(endNode);
        g.addEdge(startNode, endNode);
    }
    file.close();
    g.print();
    return 0;
}
4

1 に答える 1

2

一時変数を作成しています。例:

        node startNode(startNodeId, false);
        node endNode(endNodeId, false);

    edge e(&(*itrStartNode), &(*itrEndNode));

一時インスタンスへのポインタをコンテナに保存します

    edge e(&(*itrStartNode), &(*itrEndNode));
    edges.push_back(e);

それらのインスタンスが作成されたローカルスコープ(whileループまたはaddEdgeメソッド)を終了すると、それらのインスタンスを格納しているスタックメモリは、他の場所で使用するためにプログラムによって取り戻されます。ただし、ポインタは引き続き有効なメモリアドレス(プログラムによって取得されたかどうかに関係なく)を指しているため、有効に見えるデータを指している可能性があります。それがおそらく起こっていることです。つまり、有効に見えるが正しくない頂点が表示されている理由です。

演算子を使用してnew、ループと関数のローカルスコープを超えて存続するインスタンスを作成し、それらを(を介してdelete)適切にクリーンアップします。

于 2013-03-03T19:43:31.063 に答える