我正在尝试编写一个程序来模拟霍夫曼编码和解码。为了做到这一点,我需要在一个文本文件中序列化一个二进制树,这样我就可以稍后再次读取它并重建树(在解码huffman文件时)。
然而,在我的函数(readBinaryTree)读取文件(它是递归的)之后,程序就会停止执行。我以前从未见过这种情况。
这是代码:
if (!decode) {
.
.
.
//alot of stuff here
.
.
.
}
else if (decode) {
std::ifstream keyFile("hufftreekey.txt");
Node* HuffTree = NULL;
std::cout << "PRE!" << std::endl;
readBinaryTree(HuffTree, keyFile); //THIS FUNCTION EXECUTES, BUT NOTHING AFTER IT DOES
std::cout << "POST!" << std::endl;
std::map<char, std::string> codes = buildCodes(HuffTree);
std::ofstream outFile;
outFile.open ("mobydick_decoded.txt.huff");
char c;
std::ifstream input( argv[ 1 ] );
while (input >> std::noskipws >> c) {
if (codes.find(c) != codes.end()) {
std::string huffcode = codes[c];
outFile << huffcode;
}
else{
std::cout << "ERROR!" << std::endl;
}
}
outFile.close();
}
终端中的输出是"PRE!",但它从不打印"POST!"。我没有收到任何错误消息,没有抛出异常,只是从不打印,调用函数后也不会执行任何操作。
这就是功能:
void readBinaryTree(Node* root, std::ifstream &fin){
std::string s_val;
char val;
std::getline(fin, s_val);
val = s_val[0];
if(val == '#')
return;
else if(val == '_') {
root = new Node();
if (root == NULL) {
std::cout << "MEMORY ALLOC FAILURE!" << std::endl;
}
root->content = '_';
readBinaryTree(root->leftChild, fin);
readBinaryTree(root->rightChild, fin);
}
else {
root = new Node();
if (root == NULL) {
std::cout << "MEMORY ALLOC FAILURE!" << std::endl;
}
root->content = val;
readBinaryTree(root->leftChild, fin);
readBinaryTree(root->rightChild, fin);
}
}
这不是一个无限循环的问题,程序完成了,但在readBinaryTree函数被调用
您不是在构建一个二叉树。你正在像漏雨的筛子一样泄漏记忆,然后执行未定义的行为来雪上加霜。
更改此项:
void readBinaryTree(Node* root, std::ifstream &fin)
到此:
void readBinaryTree(Node*& root, std::ifstream &fin)
// see addition here ====^
尝试通过引用(或地址)传递指针,看看会发生什么。
在C++中,如果new失败,它将不会使指定的指针为NULL。它将抛出一个std::bad_alloc
异常。我的猜测是root = new Node();
失败了,引发了一个异常,但C++没有发现catch(在C++中调用try{...}Catch{...}
进行异常处理)。根据C++标准,所有未捕获的异常都会导致程序立即终止。因此,打印了"PRE!",但没有打印"POST!"。如果您真的想使用if(ROOT == NULL)
来检查动态内存分配是否成功,请使用placement new,如:
root = new (nothrow) node();
nothrow描述符确保new不会抛出异常,并且在失败时始终返回NULL。
我希望我的解释能有所帮助。