C++ C++;十六进制乘法分段错误

C++ C++;十六进制乘法分段错误,c++,linked-list,segmentation-fault,calculator,C++,Linked List,Segmentation Fault,Calculator,首先让我说我没有调试器的访问权限,我使用Nano作为我的编辑器 目前,用我的计算器,我的头撞在砖墙上(分割错误)。我已经试着通过我的指示来发现我的问题是什么,但我缺乏经验/知识只是让我走了这么远。让我解释一下到目前为止我的程序中的工作原理。目前,我能够将十六进制数字存储在一个链表中,并将它们相加。这个问题来自于我的乘法方法。不知何故,在乘法方法的中途,leftNode变成了NULL,抛出了一个分段错误。我想知道leftNode在什么时候变为NULL 乘法方法: LList Calculator:

首先让我说我没有调试器的访问权限,我使用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;
};
与遍历节点相关的其他方法:

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;
};
又是我

在您标记的行之后出现一个异常:
//最终导致分段错误
,似乎有一个部分形成的行用于将
leftNode->data
发送到
cout
,但在通过left节点的最后一次迭代中,
leftNode=(left.next())
leftNode
设置为NULL,因此此处的解引用可能是导致故障的原因

另一个问题是没有为LList定义复制构造函数或赋值运算符,因此这一行:
prodSum=*add(prodSum,curList)
将为prodSum提供一组列表节点,这些节点将在之后立即删除

然而,LList的析构函数似乎只删除head节点,而不是整个列表,因此存在一个无效和有效的抓包

此外,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';
}
#包括
#包括
typedef int元素;
类listnode{
公众:
元素数据;
listnode*下一步;
};
类利斯特{
listnode*头、*尾、*视图;
公众:
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&)=删除;
~LList(){clean();}
LList&operator=(LList&src){
清洁();
/*好的*/
水头=src.head;
tail=src.tail;
view=src.view;
src.head=src.tail=src.view=nullptr;
归还*这个;
}
LList&运算符=(const-LList&)=删除;
listnode*next(){
listnode*temp=视图;
如果(临时)视图=视图->下一步;
返回温度;
}
void reset(){view=head;}
作废打印();
void insertTail(元素值){
listnode*temp=新listnode;
温度->数据=val;
temp->next=NULL;
如果(!head){view=head=temp;}
else{tail->next=temp;}
尾=温度;
}
void clean(){while(head)deleteHead();}
元素deleteHead(){
listnode*temp=头部;
头部=头部->下一步;
常量元素数据=临时->数据;
删除临时文件;
返回数据;
}
};
LList添加(LList和左、LList和右){
利斯特和;
整数进位=0;
左。重置();
对。重置();
对于(;;){
const listnode*leftNode=left.next();
const listnode*rightNode=right.next();
如果(!leftNode&!rightNode)中断;
if(leftNode)进位+=leftNode->数据;
如果(rightNode)进位+=rightNode->数据;
总和插入尾(进位%16);
进位/=16;
}
if(进位)和insertTail(进位);
回报金额;
}
李斯特乘法(李斯特与左、李斯特与右){
利斯特积;
listnode*leftNode=left.next();
整数零=0;
对于(;;){
如果(!leftNode)中断;
int lval=leftNode->data;
利斯特卷发师;
对于(int i=0;i<0;i++){
卷发器。插入尾(0);
}
对。重置();
listnode*rightNode=right.next();
整数进位=0;
while(右节点){
int rval=rightNode->data;
int product=lval*rval+carry;
进位=产品/16;
产品%=16;
卷发器.插入尾(产品);
rightNode=right.next();
}
while(携带){
卷发器。插入尾巴(携带%16);
进位/=16;
}
prodSum=add(prodSum,curList);
leftNode=left.next();//最终导致分段错误
//std::cout data='0'和&c='a'和&c data]+十六进制字符串;
}
}
int main(){
//list list=字符串到列表(“1234aBcd”);
//std::string s=列表到字符串(列表);

//什么问题?你的问题是什么?为什么我的乘法函数中出现分段错误?我没有调试器的访问权限——那么你要如何编写非琐碎的东西?你要“在头脑中”运行程序吗寻找错误?或者你希望第一次就把程序写得完美,而不需要调试它们吗?给自己找一个调试器。你不是已经问过了吗?@Xarotic,因为你至少有一个bug。创建一个bug的过程可能会帮你找到它;它肯定会引出一个更好的问题。我的救世主!谢谢