本题要求采用双链表实现无符号大数类,要求实现无符号大数类拷贝控制函数,要求支持无符号大数的加、减、比较、显示等运算,加、减结果必须返回无符号大数,便于进一步参加运算,不可存在内存泄漏。
不使用动态分配扣40%,存在内存泄漏最多扣20%,程序结构要合理,命名规范,程序结构不合理最多扣20%,课内上机没有完成扣20%。
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
class Unsigned_Big_Number{
public:
Unsigned_Big_Number(); //构造函数
~Unsigned_Big_Number(); //析构函数
// Unsigned_Big_Number & operator = (const Unsigned_Big_Number &rhs); //复制赋值
Unsigned_Big_Number & operator = (Unsigned_Big_Number && rhs) noexcept; //移动赋值
// Unsigned_Big_Number(const Unsigned_Big_Number &); //拷贝构造
Unsigned_Big_Number(Unsigned_Big_Number &&)noexcept; //移动构造
void read(); //读入数据
void display()const; //显示并换行
void display(int x)const; //重载,显示不换行
int compare(const Unsigned_Big_Number &rhs)const; //比较大小
void Compare_And_Display(const Unsigned_Big_Number &rhs); //比较大小后显示
Unsigned_Big_Number plus(const Unsigned_Big_Number &rhs); //加法
Unsigned_Big_Number subtraction(const Unsigned_Big_Number &rhs); //减法
private:
struct Node{
int data;
struct Node *pre;
struct Node *nxt;
}*m_pHead,*m_pTail;
int m_len; //链表长度
};
//构造函数
Unsigned_Big_Number::Unsigned_Big_Number(){
m_pHead = new Node;
m_pHead ->nxt =NULL;
}
//析构函数
Unsigned_Big_Number::~Unsigned_Big_Number(){
while(m_pHead){
Node *p=m_pHead;
m_pHead=p->nxt;
delete p;
}
}
//拷贝构造
//Unsigned_Big_Number::Unsigned_Big_Number(const Unsigned_Big_Number &rhs){
// m_pHead = new Node;
// Node *last = m_pHead;
// Node *p=rhs.m_pHead->nxt;
// while(p){
// Node*q = new Node;
// q->data = p->data;
// last->nxt =q;
// q->pre = last;
// last = q;
// p=p->nxt;
// }
// last->nxt=NULL;
//}
//复制赋值
//Unsigned_Big_Number&Unsigned_Big_Number::operator = (const Unsigned_Big_Number &rhs){
// Unsigned_Big_Number tmp(rhs);
// Node *t = m_pHead;
// m_pHead = tmp.m_pHead;
// tmp.m_pHead = t;
// return *this;
//}
//移动赋值
Unsigned_Big_Number & Unsigned_Big_Number::operator =(Unsigned_Big_Number &&rhs)noexcept{
Node *p = this->m_pHead;
this->m_pHead = rhs.m_pHead;
rhs.m_pHead=p;
p = this->m_pTail;
this->m_pTail = rhs.m_pTail;
rhs.m_pTail = p;
this->m_len = rhs.m_len;
return *this;
}
//移动构造函数
Unsigned_Big_Number::Unsigned_Big_Number(Unsigned_Big_Number &&rhs)noexcept{
m_pHead = rhs.m_pHead;
rhs.m_pHead = NULL;
}
//读入函数
void Unsigned_Big_Number::read(){
string s;
cin>>s;
Node *p=m_pHead;
int i =0;
while(s[i]!='\0'){
Node *q = new Node;
q->data=s[i]-'0';
p->nxt=q;
q->pre=p;
p=q;
i++;
}
m_pTail=p;
m_len=i;
}
//显示
void Unsigned_Big_Number::display()const{
Node *p = m_pHead->nxt;
for(int i=0;i<m_len;i++){
cout<<p->data;
p=p->nxt;
}
cout<<endl;
}
void Unsigned_Big_Number::display(int x)const{
Node *p = m_pHead->nxt;
for(int i=0;i<m_len;i++){
cout<<p->data;
p=p->nxt;
}
}
//比较函数,大于返回2,等于返回1,小于返回0;
int Unsigned_Big_Number::compare(const Unsigned_Big_Number &rhs)const{
if(m_len < rhs.m_len) return 0;
else if (m_len > rhs.m_len) return 2;
else{
Node *p1=m_pHead->nxt;
Node *p2=rhs.m_pHead->nxt;
int i=1;
while(i<m_len &&p1->data == p2->data){
p1=p1->nxt;
p2=p2->nxt;
i++;
}
if(p1->data>p2->data) return 2;
else if (p1->data<p2->data) return 0 ;
else return 1;
}
}
//比较并显示
void Unsigned_Big_Number::Compare_And_Display(const Unsigned_Big_Number &rhs){
display(1);
if (compare(rhs)==2) cout<<'>';
else if (compare(rhs)==1) cout<<'=';
else cout<<'<';
rhs.display();
}
Unsigned_Big_Number Unsigned_Big_Number::plus(const Unsigned_Big_Number &rhs){
Unsigned_Big_Number result;
Node *front = new Node;
Node *s=front; //为了和原来的链表具有一样的结构,最后释放这个空的尾结点;
Node *p=m_pTail;
Node *q=rhs.m_pTail;
int jw=0;
for(int i=0;i<min(m_len,rhs.m_len);i++){
Node *newnode = new Node;
newnode->data=(p->data+q->data+jw)%10;
jw=(p->data+q->data+jw)/10;
newnode->nxt=front;
front->pre=newnode;
front=newnode;
p=p->pre;
q=q->pre;
}
if(m_len>min(m_len,rhs.m_len)){
for (int i=0;i<m_len-min(m_len,rhs.m_len);i++){
Node *newnode = new Node;
newnode->data=(p->data+jw)%10;
jw=(p->data+jw)/10;
newnode->nxt=front;
front->pre=newnode;
front=newnode;
p=p->pre;
}
if(jw>0){
Node *newnode = new Node;
newnode->data=jw;
newnode->nxt=front;
front->pre=newnode;
front=newnode;
result.m_pHead->nxt=front;
front->pre= result.m_pHead;
result.m_len=m_len+1;
}
else{
result.m_pHead->nxt=front;
front->pre= result.m_pHead;
result.m_len=m_len;
}
}
else if(rhs.m_len>min(m_len,rhs.m_len)){
for (int i=0;i<rhs.m_len-min(m_len,rhs.m_len);i++){
Node *newnode = new Node;
newnode->data=(q->data+jw)%10;
jw=(q->data+jw)/10;
newnode->nxt=front;
front->pre=newnode;
front=newnode;
q=q->pre;
}
if(jw>0){
Node *newnode = new Node;
newnode->data=jw;
newnode->nxt=front;
front->pre=newnode;
front=newnode;
result.m_pHead->nxt=front;
front->pre= result.m_pHead;
result.m_len=rhs.m_len+1;
}
else{
result.m_pHead->nxt=front;
front->pre= result.m_pHead;
result.m_len=rhs.m_len;
}
}
else{
if(jw>0){
Node *newnode = new Node;
newnode->data=jw;
newnode->nxt=front;
front->pre=newnode;
front=newnode;
result.m_pHead->nxt=front;
front->pre= result.m_pHead;
result.m_len=rhs.m_len+1;
}
else{
result.m_pHead->nxt=front;
front->pre= result.m_pHead;
result.m_len=rhs.m_len;
}
}
result.m_pTail=s->pre;
s->pre->nxt = NULL;
delete s;
return result;
}
Unsigned_Big_Number Unsigned_Big_Number::subtraction(const Unsigned_Big_Number &rhs){
Unsigned_Big_Number result;
Node *front = new Node;
Node *s=front; //为了和原来的链表具有一样的结构,最后释放这个空的尾结点;
Node *p=m_pTail;
Node *q=rhs.m_pTail;
if(compare(rhs)==2){
for(int i=0;i<rhs.m_len;i++){
Node *newnode = new Node;
if(p->data<q->data){
newnode->data = p->data - q->data+10;
p->pre->data-=1;
}
else {newnode->data=p->data - q->data;}
p=p->pre;
q=q->pre;
front->pre=newnode;
newnode->nxt=front;
front=newnode;
}
for(int i=0;i<m_len-rhs.m_len;i++){
Node *newnode = new Node;
newnode->data=p->data;
p=p->pre;
front->pre=newnode;
newnode->nxt=front;
front=newnode;
}
//去除前导0
result.m_len=m_len;
Node *tmp=front;
while(front->data==0){
front=front->nxt;
delete tmp;
tmp = front;
result.m_len--;
}
}
else if(compare(rhs)==0){
for(int i=0;i<m_len;i++){
Node *newnode = new Node;
if(q->data<p->data){
newnode->data = q->data - p->data+10;
q->pre->data-=1;
}
else {newnode->data=q->data - p->data;}
p=p->pre;
q=q->pre;
front->pre=newnode;
newnode->nxt=front;
front=newnode;
}
for(int i=0;i<rhs.m_len-m_len;i++){
Node *newnode = new Node;
newnode->data=q->data;
q=q->pre;
front->pre=newnode;
newnode->nxt=front;
front=newnode;
}
//去除前导0
result.m_len=rhs.m_len;
Node *tmp=front;
while(front->data==0){
front=front->nxt;
delete tmp;
tmp = front;
result.m_len--;
}
}
else{
Node *newnode = new Node;
newnode->data=0;
front->pre=newnode;
newnode->nxt=front;
front=newnode;
result.m_len=1;
}
result.m_pHead->nxt=front;
front->pre=result.m_pHead;
result.m_pTail=s->pre;
s->pre->nxt=NULL;
delete s;
return result;
}
int main(){
Unsigned_Big_Number ubn1,ubn2,ubn3,ubn4,ubn5;
ubn1.read();
ubn2.read();
ubn1.display();
ubn2.display();
ubn1.Compare_And_Display(ubn2);
ubn3=ubn1.plus(ubn2);
Unsigned_Big_Number ubn6(ubn1.plus(ubn2));
ubn3.display();
ubn6.display();
ubn4=ubn1.subtraction(ubn2);
ubn4.display();
ubn5=ubn3.plus(ubn4);
ubn5.display();
}
一些知识点:
- 构造函数在类生成时会自动首先调用
- 析构函数在类消失时后自动调用来做扫尾处理
- 上面的加法函数里定义的s指针(指向尾结点)即使释放,其实那个内存的值还在,并没有去掉,释放了是为了说明可以重新写入数据,s是一个野指针,所以显示的时候尾结点的值依然会显示。所以要加上s的前面的后面是空的语句。
- 可以给显示函数加一个参数来重载这个函数,用来不换行显示。
- 用移动赋值重载=运算符,要将私有成员全部换过来,刚开始我就将头结点换过来,但是因为我定义的类里面有长度和尾指针,这两个量并没有给他们赋值。
- 以上代码并没有用到拷贝赋值,如果定义ubn6,并且想要使他等于ubn1,语句 ubn6=ubn1就要是使用复制赋值(重载=号),如果赋值方式为 ubn6(ubn1)这就要用到拷贝构造(上面的代码有问题,赋值赋值和拷贝构造都要把m_len 和 m_pTail 定义一下才行,懒得改了。。。)