C++十六进制计算器乘法
C++ Hexadecimal 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程序:
#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
的最后一位——相反,它会被保存到下一个右数字循环的开始。这可能是故意的,但我不认为它总是会出现在正确的数字位置(但也许我在这一点上错了——我没有太多考虑这种可能性)。
为了调试你的问题,我不得不复制你的代码,填充缺失的部分并修复错误。此外,还有一些风格问题,它们不是实际的错误或bug,但已知会引发问题。以下是我对测试版本所做的更改:
-
LList包含一个用
next()
和reset()
访问的有状态迭代器(view
)。将来,代码的多个部分可能希望同时对同一LList进行迭代,但它们将无法共享LList对象所拥有的单个迭代状态。迭代器对象解决了这个问题。 -
在"用户"代码中使用原始指针:如果可能的话,应该避免指针操作,或者将指针操作限制在"库"代码中——就像在LList对象中一样。不需要处理Calculator类内部的指针。
-
变量应在其使用所需的最内部范围内声明。如果遵循这个样式点,代码的第一个问题,即
rightNode
携带了上一个循环中的值,就不可能发生。 -
不需要保留项的向量(
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';
}
- 如何在openssl-ecc中获取十六进制格式的私钥
- 如何将包含epoch时间的十六进制字符串转换为time_t
- 将字符指针十六进制转换为字符串并保存在文本文件C++中
- 如何将一个ostringstream十六进制字符串字符对转换为单个unit8t等价的二进制值
- 如何在C++中用std::cout正确显示带十六进制的字符串文本
- 通过错误处理,在C++中可靠地获得用户十六进制输入
- 为什么mpfr_printf与十六进制浮点(%a转换说明符)的printf不同
- 在 std::无符号字符的向量处存储 int 的十六进制表示形式
- 指向存储在字符串 c++ 中的十六进制
- 读取文件中所有可能的十六进制 16 字节序列并打印每个序列
- C ++如何使用UTF8十六进制代码打印UTF8符号?
- 如何将字节数组元素替换为修改的十六进制 ASCII 符号?
- 如何在C++中将十六进制字符串转换为文本数据
- 使用 sprintf 将十六进制0xAABBCC转换为字符串"AA:BB:CC"
- 绝对编码器十六进制输入
- 为什么C++总是显示十六进制内存地址,而不仅仅是整数?
- 用于加法和减法的十六进制计算器
- C++十六进制计算器乘法
- 分段错误c++十六进制计算器
- C++十六进制计算器运行时错误