让我首先说我没有访问调试器的权限,我正在使用Nano作为我的编辑器
目前,用我的计算器,我的头撞在砖墙上(分段错误)。我试着通过我的指示来发现我的问题是什么,但我缺乏经验/知识,这只会让我走到这一步。让我解释一下到目前为止在我的程序中起作用的是什么。目前,我可以将十六进制数字存储在链表中,并将它们相加。问题出在我的乘法上。不知怎的,leftNode在乘法方法的中途变成了NULL,抛出了一个分段错误。我想知道leftNode在什么时候变成NULL?
乘法方法:
LList Calculator::multiply(LList& left, LList& right) {
LList prodSum;
listnode *leftNode = (left.next());
int zeros = 0;
for(;;) {
if(leftNode == NULL) break;
int lval = leftNode->data;
LList curList;
for(int i = 0; i < zeros; i++) {
curList.insertTail(0);
}
right.reset();
listnode *rightNode = (right.next());
int carry = 0;
while(rightNode != NULL) {
int rval = rightNode->data;
int product = lval * rval + carry;
carry = product / 16;
product %= 16;
curList.insertTail(product);
rightNode = (right.next());
}
while(carry) {
curList.insertTail(carry % 16);
carry /= 16;
}
prodSum = *add(prodSum, curList);
leftNode = (left.next()); // eventually causes a segmentation fault
leftNode->data << endl;
++zeros;
}
return prodSum;
}
与乘法相关的类:
class listnode {
public:
element data;
listnode * next;
};
class LList {
private:
listnode * head;
listnode * tail;
listnode * view;
public:
LList();
~LList();
void read();
listnode* next();
void reset();
void print();
void insertTail(element val);
void clean();
element deleteHead();
};
class Calculator {
public:
Calculator();
//inline LList* add(LList& left, LList& right); works
inline LList multiply(LList& left, LList& right);
};
Calculator::Calculator() {
};
与遍历节点相关的其他方法:
listnode* LList::next() {
listnode* temp = view;
if(temp != NULL)
view = view->next;
if(view == NULL) {
}
return temp;
};
void LList::reset() {
view = head;
}
LList::LList(){
head = NULL;
view = NULL;
};
void LList::insertTail(element val) {
listnode * temp;
temp = new listnode;
temp -> data = val;
temp -> next = NULL;
if(head == NULL) {
head = temp;
view = head;
}
else
tail -> next = temp;
tail = temp;
};
void LList::clean() {
while(head != NULL)
deleteHead();
};
element LList::deleteHead() {
listnode * temp;
temp = head;
head = head -> next;
delete temp;
return temp -> data;
};
LList::~LList(){
delete head;
};
又是我。
在您标记的行之后出现一个异常:// eventually causes a segmentation fault
,似乎有一个部分形成的行用于将leftNode->data
发送到cout
,但在通过左侧节点的最后一次迭代中,leftNode = (left.next());
会将leftNode
设置为NULL,因此此处的取消引用可能会导致故障。
另一个问题是,没有为LList定义复制构造函数或赋值运算符,因此此行:prodSum = *add(prodSum, curList);
将为prodSum提供一组列表节点,这些节点将立即删除。
然而,LList的析构函数似乎只删除了头部节点,而不是整个列表,所以有一个无效和有效的抓包在进行
此外,multiply返回prodSum,因此缺少复制构造函数将导致类似的情况发生。
我正在包含您的代码的一个版本,该版本似乎可以工作。我不得不制作我自己的add
函数,只是因为我在这里看不到它。
我让析构函数删除了LList的所有节点。
我标记了默认的复制构造函数和赋值运算符=delete
,因为默认的实现做了错误的事情。
为了按值传递LList对象,我添加了一个移动构造函数和一个移动赋值运算符。这些将分配的节点从一个对象传递到另一个对象,并且只允许一个对象保留一组节点,因此您不必担心双重破坏。
#include <iostream>
#include <string>
typedef int element;
class listnode {
public:
element data;
listnode * next;
};
class LList {
listnode *head, *tail, *view;
public:
LList() { head = view = tail = NULL; }
LList(LList&& src) : head(src.head), tail(src.tail), view(src.view) { src.head = src.tail = src.view = nullptr; }
LList(const LList&) = delete;
~LList() { clean(); }
LList& operator = (LList&& src) {
clean();
/* OK here */
head = src.head;
tail = src.tail;
view = src.view;
src.head = src.tail = src.view = nullptr;
return *this;
}
LList& operator = (const LList&) = delete;
listnode* next() {
listnode* temp = view;
if(temp) view = view->next;
return temp;
}
void reset() { view = head; }
void print();
void insertTail(element val) {
listnode* temp = new listnode;
temp->data = val;
temp->next = NULL;
if(!head) { view = head = temp; }
else { tail->next = temp; }
tail = temp;
}
void clean() { while(head) deleteHead(); }
element deleteHead() {
listnode* temp = head;
head = head->next;
const element data = temp->data;
delete temp;
return data;
}
};
LList add(LList& left, LList& right) {
LList sum;
int carry = 0;
left.reset();
right.reset();
for(;;) {
const listnode* leftNode = left.next();
const listnode* rightNode = right.next();
if(!leftNode && !rightNode) break;
if(leftNode) carry += leftNode->data;
if(rightNode) carry += rightNode->data;
sum.insertTail(carry % 16);
carry /= 16;
}
if(carry) sum.insertTail(carry);
return sum;
}
LList multiply(LList& left, LList& right) {
LList prodSum;
listnode *leftNode = left.next();
int zeros = 0;
for(;;) {
if(!leftNode) break;
int lval = leftNode->data;
LList curList;
for(int i = 0; i < zeros; i++) {
curList.insertTail(0);
}
right.reset();
listnode *rightNode = right.next();
int carry = 0;
while(rightNode) {
int rval = rightNode->data;
int product = lval * rval + carry;
carry = product / 16;
product %= 16;
curList.insertTail(product);
rightNode = right.next();
}
while(carry) {
curList.insertTail(carry % 16);
carry /= 16;
}
prodSum = add(prodSum, curList);
leftNode = left.next(); // eventually causes a segmentation fault
//std::cout << leftNode->data << std::endl;
++zeros;
}
return prodSum;
}
LList string_to_list(std::string hex_string) {
LList list;
for(size_t i=hex_string.length()-1; i+1; --i) {
char c = hex_string[i] | 0x20;
if (c >= '0' && c <= '9') list.insertTail(c - '0');
else if(c >= 'a' && c <= 'f') list.insertTail(c - 'a' + 10);
}
return list;
}
std::string list_to_string(LList& list) {
std::string hex_string;
list.reset();
for(;;) {
listnode* node = list.next();
if(!node) return hex_string;
static const char digits[] = "0123456789abcdef";
hex_string = digits[node->data] + hex_string;
}
}
int main() {
//LList list = string_to_list("1234aBcd");
//std::string s = list_to_string(list);
//std::cout << s << 'n';
LList left = string_to_list("111");
LList right = string_to_list("333");
LList prod = multiply(left, right);
std::cout << list_to_string(prod) << 'n';
}