gpt4 book ai didi

c++ - c++ 中重新定义的 << 运算符的奇数输出

转载 作者:行者123 更新时间:2023-11-28 01:09:41 24 4
gpt4 key购买 nike

我有一个运行时错误,我这辈子都无法解决。我的程序几乎完成了我想要的,但是有一些损坏的字符打印为乱码。该程序应该接收一个代表森林的文本文件,构建森林,然后遍历森林以将其打印出来。树可以任意大,每个节点可以有任意多个子节点。森林在文本文件中表示如下:

a  
b
c
d
e
z
f
g
h
i
j

并且将转换为以下两棵树的森林:

    a     
/ \
b d
/ / \
c e z

f
/ \
g i
/ /
h j

代码中被注释掉的行是我测试时遗留下来的,以确保文件被正确读取并且我创建的节点被正确标记和指向。

我的代码如下:

(文件节点.h)

#ifndef NODE_H
#define NODE_H


template<typename NODETYPE> class Forest;

template<typename NODETYPE> class ForestNode
{
friend class Forest<NODETYPE>;

public:
ForestNode();

NODETYPE getTag() const;
ForestNode<NODETYPE> * getLeftChild() const;
ForestNode<NODETYPE> * getSibling() const;
void setTag(NODETYPE);
void setLeftChild(ForestNode<NODETYPE>*);
void setSibling(ForestNode<NODETYPE>*);
private:
NODETYPE tag;
ForestNode<NODETYPE> * leftChild;
ForestNode<NODETYPE> * sibling;
};

template<typename NODETYPE> ForestNode<NODETYPE>::ForestNode()
: tag(0), leftChild(NULL), sibling(NULL)
{

}

template<typename NODETYPE> NODETYPE ForestNode<NODETYPE>::getTag() const
{
return tag;
}

template<typename NODETYPE> ForestNode<NODETYPE>* ForestNode<NODETYPE>::getLeftChild() const
{
return leftChild;
}

template<typename NODETYPE> ForestNode<NODETYPE>* ForestNode<NODETYPE>::getSibling() const
{
return sibling;
}

template<typename NODETYPE> void ForestNode<NODETYPE>::setTag(NODETYPE info)
{
this->tag = info;
}
template<typename NODETYPE> void ForestNode<NODETYPE>::setLeftChild(ForestNode<NODETYPE>* info)
{
leftChild = info;
}
template<typename NODETYPE> void ForestNode<NODETYPE>::setSibling(ForestNode<NODETYPE>* info)
{
sibling = info;
}


#endif // NODE_H

(文件forest.h)

#ifndef FOREST_H
#define FOREST_H

#include <iostream>
#include <cstdlib>
#include <string>
#include "node.h"

using namespace std;

template<typename NODETYPE> class Forest
{


template<NODETYPE> friend ostream& operator<<(ostream& output, const Forest<NODETYPE>& f1);

template<NODETYPE> friend void outputHelper(ostream& output, const ForestNode<NODETYPE>& currentNode, int depth);

friend void inputHelper(istream& file, int previousDepth, ForestNode<char*>& previousNode, ForestNode<char*>* *nodeArray, int& nodeCount);

friend istream& operator>>(istream& file, Forest<char*>& f1);

public:

Forest();
Forest( const Forest& otherForest);
void nodes(int&) const;

ForestNode<NODETYPE> * root;

};

template<typename NODETYPE>ostream& operator<<(ostream& output, const Forest<NODETYPE>& f1)
{
int depth = 0;

output << f1.root->getTag();
outputHelper(output, f1.root, depth);

return output;
}

void outputHelper(ostream& output, const ForestNode<char*> *currentNode, int depth)
{
for(int i = 0; i < depth; i++)
{
output << ' ' << ' ';
}

output << currentNode->getTag();
output << endl;

if(currentNode->getLeftChild() != NULL)
{
outputHelper(output, currentNode->getLeftChild(), depth+1);
}

if(currentNode->getSibling() != NULL)
{
outputHelper(output, currentNode->getSibling(), depth);
}

}


void inputHelper(istream& file, int previousDepth, ForestNode<char*>* previousNode, ForestNode<char*> ** nodeArray, int& nodeCount)
{
int spaceCounter = 0;

while(file.peek() == ' ')
{
spaceCounter++;
file.ignore(1);
}


ForestNode<char*>* currentNode = new ForestNode<char*>();

char bar[100];
file.getline(bar, 100);
// cout << bar << endl;

currentNode->setTag(bar);
// cout << currentNode->getTag();

if(spaceCounter/2 < previousDepth)
{
for(int i = (spaceCounter/2)+1; i < nodeCount; i++)
{
nodeArray[i] = NULL;
}
}

cout << "array:";


for(int i = 0; i < spaceCounter/2; i++)
{
cout << nodeArray[i]->getTag();
}

// cout << endl;

// cout << spaceCounter/2 << ':';

if(spaceCounter/2 == previousDepth+1)
{
previousNode->setLeftChild(currentNode);
// cout << "i'm a child:" << previousNode->getLeftChild()->getTag() << " and my parent is:" << nodeArray[(spaceCounter/2)-1]->getTag();
nodeArray[spaceCounter/2] = currentNode;
}
else
{
if(!(nodeArray[spaceCounter/2] == NULL))
{
nodeArray[spaceCounter/2]->setSibling(currentNode);
// cout << "I'm a sibling:" << nodeArray[spaceCounter/2]->getSibling()->getTag() << " and my older sibling is:" << nodeArray[spaceCounter/2]->getTag();
nodeArray[spaceCounter/2] = currentNode;
}

}

// cout << endl;

// cout << currentNode->getTag();

if(!file.eof())
{
inputHelper(file, spaceCounter/2, currentNode, nodeArray, nodeCount);
}


}

istream& operator>>(istream& file, Forest<char*>& f1)
{
int charCount = 0;
int nodeCount = 0;

file.seekg(0, ios_base::end);

charCount = file.tellg();

file.seekg(0, ios_base::beg);

for(int i=0; i <= charCount; i++)
{
// cout << i << ':' << file.peek() << endl;
if(file.peek() == '\n')
{
nodeCount++;
}
file.seekg(i);
}

file.seekg(0, ios_base::beg);

nodeCount = nodeCount/2;
nodeCount = nodeCount + 1;

ForestNode<char*>* forestNodeArray[nodeCount];//holds pointers to last node of depth i

char bar[100];
file.getline(bar, 100);
cout << bar << endl;

ForestNode<char*>* foo = new ForestNode<char*>();
f1.root = foo;
f1.root->setTag(bar);

forestNodeArray[0] = f1.root;
inputHelper(file, 0, f1.root, forestNodeArray, nodeCount);

return file;
}

结束

(文件 main.h)

#include <iostream>
#include <fstream>
#include "forest.h"

using namespace std;

int main()
{
Forest<char*> forest;
filebuf fb;
fb.open ("forest1.txt",ios::in);
istream is(&fb);

is >> forest;

fb.close();

cout << forest;
}

我正在使用以下文本文件:

a
z
c
d
e
f
g
h
i
y
x
w
m
n
o
p
q
r
s
t

我的输出如下:

└@GƒtF
░≥9
c
d
e
f
g
h
i
Eⁿ(

L⌡(
m
n
o
p
q
r
s
t

进程返回 0 (0x0) 执行时间:0.092 秒按任意键继续。

如您所见,输出非常接近应有的结果,但是 ForestNodes 中包含的某些字符或标签已损坏,我终究无法弄清楚原因。任何帮助将不胜感激,我将把你视为人中之神。

最佳答案

据我所知,您的节点包含指向函数 inputHelper() 中的本地缓冲区 bar 的指针。当您在调用 setTag() 后立即打印 getTag() 的结果(注释掉)时,缓冲区仍然有效。但是,一旦函数返回,您的代码就会导致未定义的行为,因为您指的是堆栈中不再有效的某个位置。

您是否考虑过使用 std::string 而不是 char 缓冲区和 char*std::string 的自动内存管理和复制语义将解决您的问题。

编辑:输出乱码的原因是较低的堆栈帧被其他一些函数调用覆盖了。树中的 Deper 节点恰好是指距离较远且不太可能被覆盖的内存,这就是为什么它们的值可以正确输出的原因。

关于c++ - c++ 中重新定义的 << 运算符的奇数输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4064871/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com