【发布时间】:2015-10-14 04:50:22
【问题描述】:
我仍然遇到一个问题,该问题在与模板和基于链接列表的堆栈一起使用的类分配中不断出现。我经常遇到分段错误,我一生都无法理解为什么。
main() 请求一个值来确定玩游戏的磁盘数量,它调用set_Discs(),将“x”附加到字符串对象tmp_str 以表示游戏的磁盘。然后将该字符串对象推入堆栈rod[0](第一根杆),然后循环返回。我每次通过循环调用cout 来打印顶部堆栈对象作为测试并且它可以工作,因此我可以成功存储字符串对象。然而,在调用下一个函数 print_Game() 时,它会执行 for 循环的第一次迭代(打印第一行)并再次崩溃。
int main() {
TowerHanoi game;
size_t disc_in;
//How many discs to be used
cout << "Welcome to Towers of Hanoi!"<< "Please enter how many discs you want to play with: " << endl;
cin >> disc_in;
game.set_Discs(disc_in);
game.print_Game();
//Ask for source and target rod
return EXIT_SUCCESS;
}
set_Discs() 函数:
void TowerHanoi::set_Discs(size_t disc) {
//cout << "test: " << rod[0].top() << endl;
discs = disc;
while (disc > 0) {
string tmp_str;
for (size_t i=0; i<disc; i++) {
tmp_str.append("x");
}
disc--;
rod[0].push(tmp_str);
cout << "test: " << rod[0].top() << endl;
}
}
函数print_Game() 是最近的一个合乎逻辑的尝试,如果它不好并且工作不足,请原谅我。循环添加间距,然后打印top 字符串对象,然后调用pop()(在LinkedList.template 中调用removeFromHead())以使下一个字符串对象成为下一次循环的顶部对象,依此类推.参考addToHead()。
void TowerHanoi::print_Game() {
size_t spaces = discs;
string topLen = rod[0].top();
string xString;
cout << "top length: " << topLen.length() << endl;
for (size_t a=0; a<discs;a++) {
LStack<string> rodCopy = rod[0];
cout << "==="; //3 spaces
for (size_t i=0; i<spaces-topLen.length();i++) { //add to xString
xString.append("=");
}
cout << "===" << xString << rod[0].top() << xString << endl;
rod[0].pop();
spaces--;
}
}
来自 LStack.template 的一些相关代码(这是 Stack):
//push
template <typename Obj>
void LStack<Obj>::push(Obj& head_in) {
list->addToHead(head_in);
used++;
}
//pop
template <typename Obj>
Obj LStack<Obj>::pop() {
used--;
return list->removeFromHead();
}
//top
template <typename Obj>
const Obj& LStack<Obj>::top() {
return list->list_getHead();
}
LinkedList.template中的相关代码:
template <typename Item>
void LinkedList<Item>::addToHead(Item& entry) {
node<Item>* temp = head;
head = new node<Item>();
head->set_data(entry);
head->set_link(temp);
}
template <typename Item>
const Item& LinkedList<Item>::removeFromHead() {
node<Item>* head_copy = head; //create a copy of head
head->set_data(head_copy->link()); //set head's data to the previous object
return head_copy->data(); //return head's original data
}
节点模板:
template <typename Object>
void node<Object>::set_data(const Object& new_data){
word = new_data;
}
template <typename Object>
void node<Object>::set_link(node<Object>* new_link){
next= new_link;
}
template <typename Object>
void node<Object>::set_previous(node<Object>* new_prev) {
previous = new_prev;
}
template <typename Object>
const Object& node<Object>::data() const{ //return the word
return word;
}
template <typename Object>
const Object& node<Object>::link() const { //return next node (const function)
return next->data();
}
template <typename Object>
const Object& node<Object>::back() const { //return previous node (const)
return previous->data();
}
【问题讨论】:
-
“rod”的声明是什么样子的?
-
这些方法都是静态的吗?没有
new运营商? -
LStack<std::string> rod[2];网络。在addToHead()中复制了head 后,声明head = new node<Item>;这是根据另一个人Paul 的建议。 -
@CameronO'Reilly
head->set_data(head_copy->link());应该会产生编译错误。如果您尝试通过head->set_link(head_copy->link());或head->set_data(head_copy->data());来“修复”它,您将拥有一个什么都不做然后返回顶部项目的函数。 (人们会期望在该函数中看到对head和delete的修改。) -
另一个潜在的问题是复制整个列表,例如
LStack<string> rodCopy = rod[0];。当涉及到指针时,您必须非常小心地制作原始堆栈的深层副本。否则,您在销毁列表时会遇到问题,例如一个节点似乎是两个列表的成员。 (您还没有显示复制或销毁堆栈的代码)。
标签: c++ string class templates