C++ 十六进制计算器乘法

标签 c++ calculator multiplication

我遇到问题,我的乘法方法只处理一行,目前没有前进到下一行。 add 函数工作正常,我能够更新当前的十六进制数,但出于某种原因,我只能使用一行乘法。

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 的最后一位——而是保存在 curList 的开头下一个右数循环。这可能是有意的,但我认为它不会总是以正确的数字位置结束(但也许我在这一点上错了——我没有对可能性进行太多思考)。

为了调试您的问题,我不得不复制您的代码,填写缺失的部分并修复错误。此外,还有一些风格问题,它们不是真正的错误或错误,但众所周知会引发问题。所以这里是我对我的测试版本所做的更改:

  • LList 包含一个有状态的迭代器(view),使用 next()reset() 访问。将来,您的代码的多个部分可能希望同时迭代同一个 LList,但它们将无法共享 LList 对象持有的单个迭代状态。迭代器对象解决了这个问题。

  • 在“用户”代码中使用原始指针:如果可能,应避免指针操作,或将其限制在“库”代码中——例如在 LList 对象中。无需在计算器类内部处理指针。

  • 变量应在其使用所需的最内层范围内声明。代码的第一个问题,即 rightNode 从前一个循环中携带一个值,如果遵循这个样式点,就不会发生。

  • 无需在函数末尾保留术语 vector (addList) 以求和。我的版本将运行总和作为名为 prodSumLList

这是我的代码版本,包括我自己的 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';
}

关于C++ 十六进制计算器乘法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36961466/

相关文章:

c++ - c++11 中是否有 shared_memory_object 的替代品

c++ - 这会导致内存泄漏吗

C++ ifstream 跳过数据

c++ - 简单类的 LNK2019 错误

java - 使用 JOptionPane 创建乘法表

c - 乘以和增加战俘

c++ - 如何在 C++ 中获取整数的位长度?

python - 在 eval [Python 3.4.2] 中使用用户定义的变量/函数?

java - 引用通过方法分配的按钮的名称

python - 如果我将元素放入括号中,则乘法为零(python)