我遇到问题,我的乘法方法只处理一行,目前没有前进到下一行。 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
) 以求和。我的版本将运行总和作为名为prodSum
的LList
。
这是我的代码版本,包括我自己的 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/