我遇到的问题是我的乘法方法仅处理一行,而当前没有前进到下一行。加法功能正常工作,并且我能够更新当前的十六进制数,但是由于某些原因,我只能让一行乘法工作。

Example input:
111# * 333# = 333
123# * 123# = 369

这是有问题的代码:
    LList* Calculator::multiply(LList& left, LList& right) {
    int product, carry = 0, lval = 0, rval = 0, zeros = 0;
    bool calculating = true;
    listnode *leftNode;
    vector <LList*> addList;
    listnode *rightNode;
    LList* newHex;
    while(calculating) {

        leftNode = left.next();
        if(leftNode == NULL) {
            break;
        }
        else {
            lval = leftNode->data;
        }


        //leftNode = left.next();
        right.reset();

        if(leftNode == NULL) {
            calculating = false;
            if(carry != 0) {
                //newHex->insertTail(carry);
            }
            lval = 0;
            break;
        }

        LList* curList = new LList;
        addList.push_back(curList);

        while(rightNode != NULL) {

            // Add however zeros we need for
            // each entry based on the zero counter
            for(int i = 0; i < zeros; i++) {
                curList->insertTail(0);
            }

            rightNode = right.next();


            if(rightNode == NULL) {

            }
            else {
            rval = rightNode->data;

            product = lval * rval + carry;
            carry = 0;
            if(product >= 16) {
                carry = (product / 16);
                product = (product % 16);
            }
            curList->insertTail(product);
            }
        }
        zeros++;


    }

    Calculator calc;
    LList* temp;
    // Add up everything in the addList
    for(int i = 0; i < addList.size() - 1; i++) {
        if(temp == NULL)
            temp = calc.add(*addList[i], *addList[i+1]);
        else
            temp = calc.add(*addList[i+1], *temp);
    }

    newHex = temp;

    // Delete it
    for(int i = 0; i < addList.size(); i++) {

    }

    return newHex;
};

这是下一个方法:
listnode* LList::next() {
    listnode* temp = view;
    if(temp != NULL)
        view = view->next;

    if(view == NULL) {
    }
    return temp;
};

补充计划:
#include <iostream>
#include <vector>
#include <stdlib.h>
#include <string>
using namespace std;
#undef NULL
const int NULL = 0;
const char SENTINEL = '#';
typedef int element;

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);
        inline LList* multiply(LList& left, LList& right);
};

Calculator::Calculator() {

};

LList* Calculator::add(LList& left, LList& right) {
    int sum, carry = 0, lval = 0, rval = 0;
    bool calculating = true;
    listnode *leftNode;
    listnode *rightNode;
    LList* newHex = new LList;
    while(calculating) {
        leftNode = left.next();
        rightNode = right.next();

        if(leftNode == NULL) {
            lval = 0;
        }
        else
            lval = leftNode->data;

        if(rightNode == NULL) {
            rval = 0;
        }
        else
            rval = rightNode->data;


        if(leftNode == NULL && rightNode == NULL) {
            calculating = false;
            if(carry != 0) {
                newHex->insertTail(carry);
            }
            break;
        }

        sum = lval + rval + carry;
        carry = 0;
        if(sum >= 16) {
            carry = 1;
            sum -= 16;
        }

        newHex->insertTail(sum);

    }

    return newHex;
};


LList* Calculator::multiply(LList& left, LList& right) {
    int product, carry = 0, lval = 0, rval = 0, zeros = 0;
    bool calculating = true;
    listnode *leftNode;
    vector <LList*> addList;
    listnode *rightNode;
    LList* newHex;
    while(calculating) {

        leftNode = left.next();
        if(leftNode == NULL) {
            break;
        }
        else {
            lval = leftNode->data;
        }


        //leftNode = left.next();
        right.reset();

        if(leftNode == NULL) {
            calculating = false;
            if(carry != 0) {
                //newHex->insertTail(carry);
            }
            lval = 0;
            break;
        }

        LList* curList = new LList;
        addList.push_back(curList);

        while(rightNode != NULL) {

            // Add however zeros we need for
            // each entry based on the zero counter
            for(int i = 0; i < zeros; i++) {
                curList->insertTail(0);
            }

            rightNode = right.next();


            if(rightNode == NULL) {

            }
            else {
            rval = rightNode->data;

            product = lval * rval + carry;
            carry = 0;
            if(product >= 16) {
                carry = (product / 16);
                product = (product % 16);
            }
            curList->insertTail(product);
            }
        }
        zeros++;


    }



    Calculator calc;
    LList* temp;
    // Add up everything in the addList
    for(int i = 0; i < addList.size() - 1; i++) {
        if(temp == NULL)
            temp = calc.add(*addList[i], *addList[i+1]);
        else
            temp = calc.add(*addList[i+1], *temp);
    }

    newHex = temp;

    // Delete it
    for(int i = 0; i < addList.size(); i++) {

    }

    return newHex;
};

listnode* LList::next() {
    listnode* temp = view;
    if(temp != NULL)
        view = view->next;

    if(view == NULL) {
    }
    return temp;
};

void LList::reset() {
    view = head;
}


LList::LList(){
    /*
    next:
    This is used to set the linked
    list to NULL.
    */
    head = NULL;
    view = NULL;
};


void LList::print() {
    listnode * temp;
    int i = 0;
    string printValues;
    temp = head;
    while(temp != NULL) {
        int var = temp -> data;
        char character = ' ';
        if(i % 3 == 0 && i != 0)
            printValues += ',';
        i++;
        if(var > 9 && var < 16) {
            character = static_cast <char>(var + 65 - 10);
        };
        if (var <= 9 && var >= 0) {
            character = static_cast <char>(var + 48);
        };
        if (var > 96 && var < 103) {
            character = static_cast <char>(var + 97 + 10);
        };

        printValues += character;
        temp = temp -> next;

    }
    string tempValues;
    for(int i = printValues.length() - 1; i >= 0; i--)
        tempValues += printValues[i];
    cout << tempValues;
    cout << endl;
};

 void LList::read() {
    string userval;
    int i;
    bool parsing = true;
    char curval;
    vector <int> values;
    clean();
    while(parsing) {
        cin >> userval;
        for(unsigned int i = 0; i < userval.length(); i++) {
            curval = userval[i];
            if(curval >= 48 && curval <= 57)
                values.push_back(static_cast <int>(curval -
            48));

            if(curval >= 65 && curval <= 70)
                values.push_back(static_cast <int>(curval -
            65 + 10));

            if(curval >= 97 && curval <= 102)
                values.push_back(static_cast <int>(curval -
            97 + 10));

            if(curval == ' ')
                break;

            if(curval == SENTINEL) {
                parsing = false;
                break;
            }
        }
    }
    for(int i = values.size() -1; i >= 0; i--) {
        insertTail(values[i]);
    }
};

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();
};

void validCommands() {
    cout << "Valid commands are:" << endl;
    cout << "  e enter  enter the current ";
    cout << "hexadecimal ";
    cout << "number from the keyboard" << endl;
    cout << "  a add        add a new hexadecimal ";
    cout << "number to the current hex. number" << endl;
    cout << "  m multiply   ";
    cout << "multiply a new hexadecimal number ";
    cout << "by the current hex. number" << endl;
    cout << "  h help   show this help menu" << endl;
    cout << "  q quit   quit the program" << endl << endl;
};

element LList::deleteHead() {
    listnode * temp;
    temp = head;
    head = head -> next;
    delete temp;
    return temp -> data;
};

LList::~LList(){
    delete head;
};

int main() {
    LList L, add,multiply;
    Calculator calc;
    L.insertTail(0);
    char option;
    bool run;
    cout << "Hexadecimal Calculator, Ver 1.0.0 \n";



    do {
        /*
    This do while is used to continuosly run the
    program until the user decides to end.
    */
    cout << "Current Hexadecimal number is: ";
    L.print();
    cout << endl;

    cout << "Command (h for help): ";
    cin >> option;

    cout << endl << endl;
        switch(option) {
            case 'e' :
                cout << "Enter a hexadecimal number ";
                cout << "followed by #: ";
                L.read();
                cout << endl << "Entering completed.";
                cout << endl << endl;
            break;
            case 'a' :
                cout << "Adding a new hexadecimal number ";
                cout << "to the current hex. number" << endl;
                cout << endl;
                cout << "Enter a hexadecimal ";
                cout << "number, follow by #: ";
                add.read();
                cout << endl << "Addition completed.";
                cout << endl;
                L = *calc.add(L, add);
                cout << endl;
                break;
            case 'm' :
                cout << "Multiplying a new hexadecimal ";
                cout << "number ";
                cout << "to the current hex. number" << endl;
                cout << endl;
                cout << "Enter a hexadecimal ";
                cout << "number, follow by #: ";
                multiply.read();
                cout << endl << "Multiplication completed.";
                cout << endl;
                L = *calc.multiply(L, multiply);
                cout << endl;
                break;
            case 'h' : validCommands();
            break;
            case 'q' : run = false;
            break;
        };
    } while (run);
        exit(0);

}

最佳答案

while(rightNode != NULL)的第一个评估使用rightNode的未初始化值,当您运行程序时,该值恰巧为非NULL。在此检查之后,在取消引用之前,rightNode被设置为right.next()中的有效节点指针值。但是对于下一个左数位,rightnode在上一个循环中仍为NULL,因为它在right.reset()之后不会更新,因此对于第一个数字之后的每个数字,while(rightNode != NULL)总是从rightNode设置为NULL开始,因此第一个数字之后的所有循环都是跳过了。

一旦解决此问题,就会暴露出另一个错误:在右数字循环内的curList中添加零,因此,每当处理右数字时都将添加零。而是应在左数字循环内创建curList之后,在右数字循环前添加零。

我认为还有另一个错误-右数位循环结束后,任何进位值都不会添加到curList的最后一位数字-而是将其保存为下一个右数位循环的开始。这可能是有意为之,但我不认为它总是会以正确的数字结尾(但在这一点上我可能是错的,我并未对各种可能性进行过多的思考)。

为了调试您的问题,我不得不复制您的代码,填写缺少的部分并修复错误。此外,还有一些样式问题,这些问题不是实际的错误或错误,但已知会引起问题。因此,这是我对测试版本进行的更改:

  • LList包含一个通过viewnext()访问的有状态迭代器(reset())。将来,您的代码的多个部分可能希望同时在同一LList上进行迭代,但是它们将无法共享LList对象持有的单个迭代状态。迭代器对象解决了这个问题。
  • 在“用户”代码中使用原始指针:如果可能,应避免使用指针操纵,或者将其限制为“库”代码-就像在LList对象中一样。无需在Calculator类内处理指针。
  • 变量应在其使用所需的最深范围内声明。如果遵循此样式点,则代码的第一个问题就不会发生,即rightNode从上一个循环中继承了一个值。
  • 无需保留项的 vector (addList)即可在函数末尾进行总结。我的版本保留了一个连续的总和作为名为LListprodSum

  • 这是我的代码版本,包括我自己的LList和Calculator::add,因为您没有使它们可用。请注意,此处LList与迭代器一起使用,而不是view成员。我的迭代器在其结束位置时可以被“取消引用”,并赋予零。这样做是为了方便起见,因为对于任何值,都隐含一个在最高位上方的无数高阶零字符串:
    #include <iostream>
    #include <string>
    #include <vector>
    
    struct listnode {
        int data;
        listnode *next;
        listnode(int data=0) : data(data), next(0) {}
    };
    
    class LList {
        listnode *head, *tail;  // head is least significant end
        void delNodes() {
            listnode* node = head;
            while(node) {
                listnode* todel = node;
                node = node->next;
                delete todel;
            }
            head = tail = 0;
        }
    public:
        LList() : head(0), tail(0) {}
        LList(std::string digits) : head(0), tail(0) {
            for(auto it = digits.rbegin(); it != digits.rend(); ++it) {
                if(*it >= '0' && *it <= '9') insertTail(*it - '0');
                else if(*it >= 'a' && *it <= 'f') insertTail(*it - 'a' + 10);
                else if(*it >= 'A' && *it <= 'F') insertTail(*it - 'A' + 10);
        }   }
        LList(const LList& src) : head(0), tail(0) {
            for(int data : src) { insertTail(data); }
        }
        ~LList() { delNodes(); }
        LList& operator = (const LList& src) {
            delNodes();
            for(int data : src) { insertTail(data); }
            return *this;
        }
        void insertTail(int value) {
            listnode *newnode = new listnode(value);
            if(!head) {
                head = tail = newnode;
            } else {
                tail->next = newnode;
                tail = newnode;
        }   }
        class iterator {
            friend LList;
            const listnode* node;
            iterator(const listnode* node) : node(node) {}
        public:
            iterator& operator ++ () { if(node) node = node->next; return *this; }
            int operator * () const { return node ? node->data : 0; }
            bool operator != (iterator iter) const { return iter.node != node; }
            bool operator == (iterator iter) const { return iter.node == node; }
        };
        iterator begin() const { return iterator(head); }
        iterator end()   const { return iterator(0); }
        std::string get_digits() const {
            static const char da[] = "0123456789abcdef";
            std::string digits;
            for(int d : *this) {
                digits = da[d] + digits;
            }
            return digits;
        }
    };
    
    LList add(const LList& left, const LList& right) {
        LList sum;
        auto liter = left.begin();
        auto riter = right.begin();
        int carry = 0;
        while(liter != left.end() || riter != right.end()) {
            int s = *liter + *riter + carry;
            carry = s / 16;
            sum.insertTail(s % 16);
            ++liter;
            ++riter;
        }
        if(carry) sum.insertTail(carry);
        return sum;
    }
    
    LList multiply(const LList& left, const LList& right) {
        LList prodSum;
        auto leftNode = left.begin();
        int zeros = 0;
        for(;;) {
            if(leftNode == left.end()) break;
            int lval = *leftNode;
            LList curList;
            for(int i = 0; i < zeros; i++) {
                curList.insertTail(0);
            }
            auto rightNode = right.begin();
            int carry = 0;
            while(rightNode != right.end()) {
                int rval = *rightNode;
                int product = lval * rval + carry;
                carry = product / 16;
                product %= 16;
                curList.insertTail(product);
                ++rightNode;
            }
            while(carry) {
                curList.insertTail(carry % 16);
                carry /= 16;
            }
            prodSum = add(prodSum, curList);
            ++leftNode;
            ++zeros;
        }
    
        return prodSum;
    }
    
    int main() {
        LList a("111");
        LList b("333");
        LList c = multiply(a, b);  // 36963
        std::cout << c.get_digits() << '\n';
    }
    

    09-07 23:50