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

时间:2016-04-30 23:45:23

标签: c++ calculator multiplication

我遇到的问题是我的乘法方法只处理一行,它目前没有前进到下一行。添加功能正常工作,我能够更新当前的十六进制数,但由于某种原因,我只能获得一行乘法。

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

FUll PROGRAM:

#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);

}

1 个答案:

答案 0 :(得分:1)

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

一旦修复,将暴露另一个错误:在右数字循环内的curList中添加零,因此每当处理右数位时都会添加零。相反,在左数字循环中创建curList之后,应在右数字循环之前添加零。

还有另一个错误(我认为) - 在右数字循环结束后,任何进位值都不会添加到curList的最后一位 - 而是在下一个右边开始保存-digit循环。这可能是有意的,但我不认为它总是会以正确的数字位置结束(但也许我在这一点上错了 - 我没有太多考虑可能性)。

为了调试您的问题,我不得不复制您的代码,填写缺少的部分并修复错误。此外,还有一些风格问题不是实际的错误或错误,但已知会促进问题。以下是我对我的测试版本所做的更改:

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

  • 在“用户”代码中使用原始指针:如果可能,应避免使用指针操作,或限制为“库”代码 - 就像在LList对象中一样。不需要处理Calculator类中的指针。

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

  • 没有必要在函数结尾处保留一个向量(addList)的术语。我的版本将LList命名为prodSum

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