![](/img/trans.png)
[英]How can I implement a constexpr N-way set_union (deduplicated merge)
[英]How to get a child in an n-way tree?
我有一個使用std :: vector實現的n路樹。 Node類僅包含指向根元素的指針,而Link類具有指向其自身的std :: vector指針。 創建鏈接時,我要為每個鏈接命名,但是當我嘗試使用鏈接名稱在此樹中定位節點時,卻遇到了分段錯誤。 我也意識到我的函數GetLink()不執行任何錯誤檢查,我嘗試了幾件事,但是它們沒有用,因此,如果可能的話,在這種情況下如何實現的任何建議將不勝感激。 這是我的代碼:
// in node.h
class Node {
public:
// constructors
// fuctions
private:
Link *root;
};
// in link.h
class Link {
public:
//EDIT: added vector initialization in the constructor
Link() : my_links(0) { }
// some functions
// EDIT: example of making the tree
bool Load(token) {
// parsing code based on token
else if (strcmp (temp, "link") == 0)
{
Link* lnk = new Link ();
lnk->Load (token);
lnk->Init ();
AddChild (lnk);
lnk->m_parent = this;
}
// some more parsing code
}
void Link::AddChild (Link* pChild)
{
my_links.push_back(pChild);
}
Link* Link::GetLink(char* str) // this is the function that is the problem.
{
if (strcmp(name, str) == 0)
{
return this;
}
for (int i=0; i < (int) my_links.size(); i++)
{
//Edit: added check for NULL ptr
if (my_links[i] == NULL)
{
fprintf (stderr, "\n\t Couldn't find link\n\n");
break;
}
//Edit: typo corrected
return my_links[i]->GetLink(str);
}
}
private:
char name[256];
Link* m_parent;
std::vector<Link*> my_links;
};
// in main.cpp
static Node* node;
static Link* link;
main()
{
char *str = "link_3";
link = node->GetLink(str);
printf("\n found link: %s", link->GetName());
retrun 0;
}
編輯:將早期的代碼重寫為MCVE
#include <cstdio>
#include <vector>
#include <cstring>
class Link {
public:
//EDIT: added vector initialization in the constructor
Link() : my_links(0)
{
m_parent = NULL;
}
void SetParent(Link* pParent)
{
m_parent = pParent;
}
// EDIT: example of making the tree
bool Load(char *str)
{
unsigned int len;
Link* lnk = new Link ();
len = strlen(str);
strcpy(name, str);
lnk->SetParent(this);
AddChild (lnk);
return true;
}
void AddChild (Link* pChild)
{
my_links.push_back(pChild);
}
Link* GetLink(char* str) // this is the function that is the problem.
{
if (strcmp(name, str) == 0)
{
return this;
}
for (int i=0; i < (int) my_links.size(); i++)
{
//Edit: added check for NULL ptr
if (my_links[i] == NULL)
{
fprintf (stderr, "\n\t Couldn't find link\n\n");
break;
}
//Edit: typo corrected
return my_links[i]->GetLink(str);
}
fprintf(stderr, "\n\t Cannot get link\n\n");
return 0;
}
char* GetName()
{
return name;
}
private:
char name[256];
Link* m_parent;
std::vector<Link*> my_links;
};
class Node {
public:
Node()
{
root = NULL;
}
bool Load (char *str)
{
unsigned int len;
root = new Link(); // here is where the error occurs
len = strlen(str);
strcpy(name, str);
return true;
}
void AddChild (char *str)
{
root->Load(str);
}
Link* GetRoot()
{
return root;
}
private:
char name[256];
Link *root;
};
static Node* node;
static Link* lnk;
int main()
{
node->Load((char*)"I am root");
node->AddChild((char*)"I am child 1");
node->AddChild((char*)"I am child 2");
node->AddChild((char*)"I am child 3");
char *str = (char*)"I am child 2";
lnk = node->GetRoot()->GetLink(str);
printf("\n found link: %s", lnk->GetName());
return 0;
}
我現在在VS2010的第77行上得到的錯誤是Node類中的“ root = new Link()”,Load()函數為:
Unhandled exception at 0x012e1bbe in nWayTree.exe: 0xC0000005: Access violation writing location 0x00000100.
在MCVE中收到錯誤的原因是,您從未實例化node
,因此, node->Load((char*)"I am root");
取消引用未初始化的指針,導致未定義的行為。 實際上,當您的程序試圖寫入希望“ root”成員變量存在的內存位置時,您會遇到訪問沖突。 您可以通過編寫來解決此問題
static Node* node = new Node();
但是,即使更正了此錯誤,您的MCVE仍然存在語義錯誤。 每次調用node->AddChild
,都不會添加另一個子節點,而是重命名節點,並為node的root
成員變量分配一個新的默認構造鏈接(無名稱)。 同樣,您的GetLink()函數不會遞歸地在所有子節點上調用GetLink()(如果有的話),而只會在第一個子節點上調用GetLink(),然后無條件返回結果(循環在一次執行)。
另外,Node,Link和root之間的區別對我也不是很清楚。 這是我假設要實現的目標,並且要盡可能少地增加c ++(與您的示例相比):
#include <cstdio>
#include <vector>
#include <cstring>
class Node {
private:
char m_name[256];
Node* m_parent;
std::vector<Node*> my_links;
public:
//EDIT: added vector initialization in the constructor
Node(const char* name, Node* parent=nullptr) : m_parent(parent), my_links() {
strcpy(m_name, name);
}
void AddChild(const char* childname) {
my_links.push_back(new Node(childname,this));
}
Node* GetNode(const char* str) {
if (strcmp(m_name, str) == 0) {
return this;
}
for (size_t i = 0; i < my_links.size(); i++)
{
Node* t = my_links[i]->GetNode(str);
if (t != NULL) return t;
}
return NULL;
}
char* GetName() {
return m_name;
}
};
Node root((const char*)"I am root");
int main()
{
root.AddChild("I am child 1");
root.AddChild("I am child 2");
root.AddChild("I am child 3");
const char *str1 = "I am child 2";
const char *str2 = "I am child 1 of child 2 of root";
root.GetNode(str1)->AddChild(str2);
Node* node = root.GetNode(str2);
if (node == NULL) {
printf("Link not found");
} else
{
printf("\n found link: %s", node->GetName());
}
}
這是“現代c ++樣式”版本(不聲稱它是特別好的版本):
編輯:我剛剛意識到您正在使用VS2010,它將無法編譯以下示例,因為它使用了某些c ++ 11和c ++ 14(當前的c ++標准)功能。 但是,您可以使用VS2013的免費版本來構建它,並且應該能夠使用g ++和clang ++的任何最新版本來構建它(不過,您必須添加標記'-std = c ++ 14'或類似標記)。
#include <iostream>
#include <vector>
#include <string>
#include <memory>
using namespace std;
class Node {
private:
string m_name;
Node* m_parent;
vector<unique_ptr<Node>> my_links;
public:
Node(const string& name, Node* parent = nullptr) :
m_name(name),
m_parent(parent),
my_links()
{}
void AddChild(const string& childname) {
my_links.push_back(make_unique<Node>(childname, this));
}
Node* GetNode(const string& str) {
if (m_name == str) {
return this;
}
for (auto& e:my_links)
{
Node* t = e->GetNode(str);
if (t != nullptr) return t;
}
return nullptr;
}
string GetName() {
return m_name;
}
};
Node root("I am root");
int main()
{
root.AddChild("I am child 1");
root.AddChild("I am child 2");
root.AddChild("I am child 3");
string str1("I am child 2");
string str2("I am child 1 of child 2 of root");
root.GetNode(str1)->AddChild(str2);
Node* node = root.GetNode(str2);
if (node == nullptr) {
cout <<"Link not found";
} else {
cout << "found link: "<< node->GetName();
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.