我遇到的问题是我的乘法方法只处理一行,它目前没有前进到下一行。添加功能正常工作,我能够更新当前的十六进制数,但由于某种原因,我只能获得一行乘法。
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);
}
答案 0 :(得分:1)
while(rightNode != NULL)
的第一次评估使用rightNode
的未初始化值,当您运行程序时,该值恰好为非NULL。在此检查之后,在取消引用之前,rightNode
被设置为right.next()
的有效节点指针值。但是对于下一个左边的数字,右边节点仍然是前一个循环的NULL,因为它在right.reset()
之后没有更新,所以对于第一个之后的每个数字,while(rightNode != NULL)
始终以rightNode设置为NULL开始,所以跳过第一个循环之后的所有循环。
一旦修复,将暴露另一个错误:在右数字循环内的curList中添加零,因此每当处理右数位时都会添加零。相反,在左数字循环中创建curList之后,应在右数字循环之前添加零。
还有另一个错误(我认为) - 在右数字循环结束后,任何进位值都不会添加到curList
的最后一位 - 而是在下一个右边开始保存-digit循环。这可能是有意的,但我不认为它总是会以正确的数字位置结束(但也许我在这一点上错了 - 我没有太多考虑可能性)。
为了调试您的问题,我不得不复制您的代码,填写缺少的部分并修复错误。此外,还有一些风格问题不是实际的错误或错误,但已知会促进问题。以下是我对我的测试版本所做的更改:
LList包含使用view
和next()
访问的有状态迭代器(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';
}