鱼C论坛

 找回密码
 立即注册
查看: 1561|回复: 3

[已解决]C++关于使用链表实现大数求和的问题

[复制链接]
发表于 2019-4-23 11:05:33 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
具体是这样的,我编写了两个大数存储的类用于计算斐波那契数列,并设置了两个大数变量h1 h2 分别赋值1 但是在重载了+=之后发现在一次循环里用h1 += &h2完全没有问题,但是接着用h2 += &h1时候就会莫名的抛异常退出,异常是:terminate called after throwing an instance of
下面附上代码
  1. #include <iostream>
  2. #include <conio.h>
  3. #include "hugeNumber.h"
  4. #include <cstdlib>
  5. using namespace std;

  6. int main()
  7. {



  8.    hugeNumber h1;
  9.    hugeNumber h2;
  10.    h1.add_Node_in_list(1);
  11.    h2.add_Node_in_list(1);




  12.    for(int i = 0;i < 1000;i++)
  13.    {
  14.        h1 += &h2;
  15.        h2 += &h1;
  16.        system("pause");
  17.        cout<<i+1<<"-"<<h1.Tostring()<<i+2<<h2.Tostring()<<endl;


  18.    }


  19.     /*
  20.     unsigned int nFibonacci[1000];
  21.     nFibonacci[0] = 1;
  22.     nFibonacci[1] = 1;
  23.     cout<<"1."<<nFibonacci[0]<<endl;
  24.     cout<<"2."<<nFibonacci[1]<<endl;
  25.     for(int i = 2;i < 1000;i++)
  26.     {
  27.         nFibonacci[i] = nFibonacci[i-1]+nFibonacci[i-2];
  28.         cout<<i+1<<"."<<nFibonacci[i]<<endl;
  29.         getch();
  30.     }
  31.     */
  32.     return 0;
  33. }
复制代码

类的定义:
  1. #ifndef HUGENUMBER_H
  2. #define HUGENUMBER_H
  3. #define max_num 0xffffffff
  4. #include <iostream>
  5. using namespace std;
  6. class hgNumNode
  7. {
  8.    public:
  9.      unsigned int value32;//存储32位无符号整形
  10.      hgNumNode* next;//链表指针
  11.      hgNumNode(unsigned int values){this->value32 = values;this->next=nullptr;}
  12.      virtual ~hgNumNode(){};//尽量给缺省实现的虚函数加上函数体否则可能会出现undefined reference to `vtable for
  13. };

  14. class hugeNumber
  15. {
  16.     public:
  17.         hugeNumber();
  18.         virtual ~hugeNumber();
  19.         hgNumNode* hgHead;//链表头节点
  20.         int length;//链表长度
  21.         hgNumNode* hgLast;//链表尾节点
  22.         bool add_Node_in_list(unsigned int values);//添加一个新节点到链表中
  23.         void cleanList();//清空链表
  24.         void reset_self(unsigned int values);//清空链表并重设第一个节点的值
  25.         void remove_zero_end();//删除值为0的节点
  26.         void remove_zero_end(hgNumNode* parent);
  27.         void operator +=(hugeNumber* afterNum);//重载+=
  28.         string Tostring();
  29.         string Tostring(hgNumNode* heads);

  30.     protected:

  31.     private:
  32. };

  33. #endif // HUGENUMBER_H
复制代码

类的实现:
  1. #include "hugeNumber.h"
  2. #include <cstdio>

  3. hugeNumber::hugeNumber()
  4. {
  5.     this->hgHead = nullptr;
  6.     this->length = 0;
  7.     this->hgLast = nullptr;
  8. }

  9. hugeNumber::~hugeNumber()
  10. {
  11.     cleanList();
  12. }

  13. bool hugeNumber::add_Node_in_list(unsigned int values)
  14. {
  15.     hgNumNode* addNode = new hgNumNode(values);
  16.     if(this->length == 0)
  17.     {
  18.         this->hgHead =addNode;
  19.         this->hgLast =addNode;
  20.         this->length= 1;
  21.         return true;
  22.     }
  23.     this->hgLast->next=addNode;
  24.     this->hgLast = addNode;
  25.     this->length++;
  26.     return true;
  27. }

  28. void hugeNumber::cleanList()
  29. {
  30.     hgNumNode* delNode = this->hgHead;
  31.     while(delNode != nullptr)//不能再对象析构中调用delete删除相同对象,这样会导致无限调用析构的死循环递归
  32.     {
  33.          delete delNode;
  34.          delNode = delNode->next;
  35.     }
  36.     this->length = 0;
  37.     this->hgHead = nullptr;
  38.     this->hgLast = nullptr;


  39. }

  40. void hugeNumber::reset_self(unsigned int tar)
  41. {
  42.     cleanList();
  43.     hgNumNode* newNode= new hgNumNode(tar);
  44.     this->hgHead = newNode;
  45.     this->hgLast = newNode;
  46.     this->length++;
  47. }
  48. void hugeNumber::remove_zero_end()
  49. {
  50.     if(this->hgHead == nullptr)
  51.         return;
  52.     remove_zero_end(this->hgHead);

  53. }

  54. void hugeNumber::remove_zero_end(hgNumNode* parent)
  55. {
  56.     if(parent == nullptr)
  57.         return;
  58.     else
  59.         remove_zero_end(parent->next);
  60.     if(parent->value32 == 0)
  61.     {
  62.         delete parent;
  63.         parent= nullptr;
  64.         this->length--;
  65.     }


  66. }

  67. void hugeNumber::operator+=(hugeNumber* afterNum)
  68. {
  69.     cout<<"begin"<<endl;
  70.     if(this->length == afterNum->length)
  71.     {
  72.         this->add_Node_in_list(0);

  73.     }
  74.     else if(this->length < afterNum->length)
  75.     {
  76.         for(int i = this->length;i < afterNum->length;i++)
  77.             this->add_Node_in_list(0);

  78.     }
  79.     this->add_Node_in_list(0);
  80.     this->add_Node_in_list(0);

  81.     hgNumNode* h1 = this->hgHead;
  82.     hgNumNode* h2 = afterNum->hgHead;

  83.     while(true)
  84.     {
  85.         if(h1 == nullptr)
  86.             break;
  87.         if(h2 == nullptr)
  88.             break;
  89.         if(max_num - h1->value32 < h2->value32)
  90.             h1->next->value32+=1;
  91.         h1->value32 += h2->value32;
  92.         cout<<"now-values-"<<h1->value32<<endl;
  93.         h1 = h1->next;
  94.         h2 = h2->next;
  95.         remove_zero_end();


  96.     }
  97.     cout<<"end"<<endl;

  98. }

  99. string hugeNumber::Tostring()
  100. {
  101.     if(this->hgHead == nullptr)
  102.         return "0";

  103.     string ret = "0x"+Tostring(this->hgHead);
  104.     return ret;
  105. }

  106. string hugeNumber::Tostring(hgNumNode* heads)
  107. {
  108.     string ret ="-";
  109.     if(heads->next != nullptr)
  110.     {
  111.         ret+=Tostring(heads->next);
  112.     }
  113.     char temp[10];
  114.     sprintf(temp,"%08x",heads->value32);
  115.     ret.append(temp);
  116.     return ret;
  117. }
复制代码
最佳答案
2019-4-23 12:34:37
调试代码比自己写代码累多了。。。
先说我找出来的问题吧

  1. void hugeNumber::reset_self(unsigned int tar)
  2. {
  3.     cleanList();
  4.     hgNumNode* newNode= new hgNumNode(tar);
  5.     this->hgHead = newNode;
  6.     this->hgLast = newNode;
  7.     this->length++;
  8. }
  9. void hugeNumber::remove_zero_end()
  10. {
  11.     if(this->hgHead == nullptr)
  12.         return;
  13.     remove_zero_end(this->hgHead);

  14. }
复制代码

删除后,尾节点的next指针没有置nullptr,且hgLast指针没有修改,
最小的修改方案:
  1. void hugeNumber::remove_zero_end()
  2. {
  3.         if (this->hgHead == nullptr)
  4.                 return;
  5.         remove_zero_end(this->hgHead,this->hgLast);
  6.         this->hgLast->next = nullptr;
  7. }

  8. bool hugeNumber::remove_zero_end(hgNumNode* parent,hgNumNode*& lastpointer)
  9. {
  10.         if (parent == nullptr) {
  11.                 lastpointer = nullptr;
  12.                 return true;
  13.         }
  14.         else {
  15.                 if (remove_zero_end(parent->next, lastpointer)) {
  16.                         lastpointer = parent;
  17.                 }
  18.         }
  19.                
  20.        
  21.         if (parent->value32 == 0)
  22.         {
  23.                 delete parent;
  24.                 parent = nullptr;
  25.                 this->length--;
  26.                 return true;
  27.         }
  28.         return false;
  29. }
复制代码


还有
  1. void hugeNumber::cleanList()
  2. {
  3.     hgNumNode* delNode = this->hgHead;
  4.     while(delNode != nullptr)//不能再对象析构中调用delete删除相同对象,这样会导致无限调用析构的死循环递归
  5.     {
  6.          delete delNode;
  7.          delNode = delNode->next;
  8.     }
  9.     this->length = 0;
  10.     this->hgHead = nullptr;
  11.     this->hgLast = nullptr;


  12. }
复制代码

delete delNode后,再调用delNode会出现错误,建议改成
  1. void hugeNumber::cleanList()
  2. {
  3.         hgNumNode* delNode = this->hgHead;
  4.         while (delNode != nullptr)//不能再对象析构中调用delete删除相同对象,这样会导致无限调用析构的死循环递归
  5.         {
  6.                 hgNumNode* next = delNode->next;
  7.                 delete delNode;
  8.                 delNode = next;
  9.         }
  10.         this->length = 0;
  11.         this->hgHead = nullptr;
  12.         this->hgLast = nullptr;


  13. }
复制代码


仍然有错误,我重新实现个大数类吧0 0,
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2019-4-23 12:34:37 | 显示全部楼层    本楼为最佳答案   
调试代码比自己写代码累多了。。。
先说我找出来的问题吧

  1. void hugeNumber::reset_self(unsigned int tar)
  2. {
  3.     cleanList();
  4.     hgNumNode* newNode= new hgNumNode(tar);
  5.     this->hgHead = newNode;
  6.     this->hgLast = newNode;
  7.     this->length++;
  8. }
  9. void hugeNumber::remove_zero_end()
  10. {
  11.     if(this->hgHead == nullptr)
  12.         return;
  13.     remove_zero_end(this->hgHead);

  14. }
复制代码

删除后,尾节点的next指针没有置nullptr,且hgLast指针没有修改,
最小的修改方案:
  1. void hugeNumber::remove_zero_end()
  2. {
  3.         if (this->hgHead == nullptr)
  4.                 return;
  5.         remove_zero_end(this->hgHead,this->hgLast);
  6.         this->hgLast->next = nullptr;
  7. }

  8. bool hugeNumber::remove_zero_end(hgNumNode* parent,hgNumNode*& lastpointer)
  9. {
  10.         if (parent == nullptr) {
  11.                 lastpointer = nullptr;
  12.                 return true;
  13.         }
  14.         else {
  15.                 if (remove_zero_end(parent->next, lastpointer)) {
  16.                         lastpointer = parent;
  17.                 }
  18.         }
  19.                
  20.        
  21.         if (parent->value32 == 0)
  22.         {
  23.                 delete parent;
  24.                 parent = nullptr;
  25.                 this->length--;
  26.                 return true;
  27.         }
  28.         return false;
  29. }
复制代码


还有
  1. void hugeNumber::cleanList()
  2. {
  3.     hgNumNode* delNode = this->hgHead;
  4.     while(delNode != nullptr)//不能再对象析构中调用delete删除相同对象,这样会导致无限调用析构的死循环递归
  5.     {
  6.          delete delNode;
  7.          delNode = delNode->next;
  8.     }
  9.     this->length = 0;
  10.     this->hgHead = nullptr;
  11.     this->hgLast = nullptr;


  12. }
复制代码

delete delNode后,再调用delNode会出现错误,建议改成
  1. void hugeNumber::cleanList()
  2. {
  3.         hgNumNode* delNode = this->hgHead;
  4.         while (delNode != nullptr)//不能再对象析构中调用delete删除相同对象,这样会导致无限调用析构的死循环递归
  5.         {
  6.                 hgNumNode* next = delNode->next;
  7.                 delete delNode;
  8.                 delNode = next;
  9.         }
  10.         this->length = 0;
  11.         this->hgHead = nullptr;
  12.         this->hgLast = nullptr;


  13. }
复制代码


仍然有错误,我重新实现个大数类吧0 0,
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-4-23 14:17:37 | 显示全部楼层
Croper 发表于 2019-4-23 12:34
调试代码比自己写代码累多了。。。
先说我找出来的问题吧

非常感谢回答,我找到错误了,错误是函数 void remove_zero_end(); 在对hgHead节点值为0的处理有问题,会把它直接赋nullptr,之后的调用就出问题了,非常感谢您的答疑。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-4-23 14:41:35 | 显示全部楼层
  1. #ifndef HUGENUMBER_H
  2. #define HUGENUMBER_H
  3. #define max_num 0xffffffff

  4. #include <iostream>
  5. #include <sstream>
  6. #include <iomanip>

  7. class hugeNumber {
  8. private:
  9.         struct Node {
  10.                 unsigned int val;
  11.                 Node* pre;
  12.                 Node* next;
  13.                 Node(unsigned int val0=0) :pre(this), next(this), val(val0) {};

  14.                 Node* insert_back(unsigned val0 = 0);
  15.                 ~Node();
  16.         };

  17.         Node* _myhead;
  18.         int _mysize;

  19.         void remove_zero_end();
  20.         bool SumOverflow(unsigned int num1, unsigned int num2, unsigned int a);
  21. public:
  22.         hugeNumber();
  23.         hugeNumber(unsigned int val0);
  24.         hugeNumber(const hugeNumber&);
  25.         hugeNumber(hugeNumber&&);
  26.         ~hugeNumber();

  27.         int size() const;
  28.         void clear();

  29.         hugeNumber&  operator=(unsigned int val0);
  30.         hugeNumber& operator+=(const hugeNumber& num1);

  31.         std::string to_string() const;
  32. };
复制代码

  1. #include "hugeNumber.h"

  2. inline hugeNumber::Node * hugeNumber::Node::insert_back(unsigned val0) {
  3.         Node* tmp = next;
  4.         next = new Node(val0);
  5.         next->pre = this;
  6.         next->next = tmp;
  7.         if (tmp != nullptr) {
  8.                 tmp->pre = next;
  9.         }

  10.         return next;
  11. }

  12. inline hugeNumber::Node::~Node() {
  13.         if (pre != nullptr) pre->next = next;
  14.         if (next != nullptr) next->pre = pre;
  15. }

  16. inline void hugeNumber::remove_zero_end() {
  17.         while (_myhead->pre != _myhead && _myhead->pre->val == 0) {
  18.                 delete _myhead->pre;
  19.                 _mysize--;
  20.         }
  21. }

  22. inline bool hugeNumber::SumOverflow(unsigned int num1, unsigned int num2, unsigned int a) {
  23.         if (a > 1) {
  24.                 std::cerr << "Error: illegal a";
  25.                 return false;
  26.         }

  27.         if (a == 0) {
  28.                 return max_num - num1 < num2;
  29.         }

  30.         if (num1 == max_num || num2 == max_num) return true;
  31.         return max_num - num1 < num2 + 1;
  32. }

  33. inline hugeNumber::hugeNumber() {
  34.         _myhead = new Node;
  35.         _mysize = 0;
  36. }

  37. inline hugeNumber::hugeNumber(unsigned int val0) :hugeNumber() {
  38.         if (val0 == 0) return;
  39.         _myhead->insert_back(val0);
  40.         _mysize = 1;
  41. }

  42. hugeNumber::hugeNumber(const hugeNumber & num0):hugeNumber()
  43. {
  44.         _mysize = num0._mysize;
  45.         for (Node *p = num0._myhead->pre; p != num0._myhead; p = p->pre) {
  46.                 _myhead->insert_back(p->val);
  47.         }
  48. }

  49. hugeNumber::hugeNumber(hugeNumber && num0)
  50. {
  51.         auto tmp = _myhead;
  52.         _myhead = num0._myhead;
  53.         num0._myhead = tmp;
  54. }

  55. inline hugeNumber::~hugeNumber() {
  56.         Node* p = _myhead->next;
  57.         while (p != _myhead) {
  58.                 Node* tmp = p->next;
  59.                 delete p;
  60.                 p = tmp;
  61.         }
  62.         delete _myhead;
  63. }

  64. inline int hugeNumber::size() const {
  65.         return _mysize;
  66. }

  67. inline void hugeNumber::clear() {
  68.         Node* p = _myhead->next;
  69.         while (p != _myhead) {
  70.                 Node* tmp = p->next;
  71.                 delete p;
  72.                 p = tmp;
  73.         }
  74.         _mysize = 0;
  75. }




  76. hugeNumber&  hugeNumber::operator=(unsigned int val0) {
  77.         clear();
  78.         if (val0 == 0) return *this;
  79.         _myhead->insert_back(val0);
  80.         _mysize = 1;
  81.         return *this;
  82. }

  83. hugeNumber& hugeNumber::operator+=(const hugeNumber& num1) {
  84.         unsigned int a = 0;
  85.         Node* p1 = _myhead->next, *p2 = num1._myhead->next;
  86.         while (p1 != _myhead || p2 != num1._myhead) {
  87.                 int next_a = SumOverflow(p1->val, p2->val, a);
  88.                 p1->val = p1->val + p2->val + a;
  89.                 a = next_a;

  90.                 p1 = p1->next;
  91.                 if (p2 != num1._myhead) {
  92.                         p2 = p2->next;
  93.                         if (p2 != num1._myhead && p1 == _myhead) {
  94.                                 p1 = _myhead->pre->insert_back(0);
  95.                                 ++_mysize;
  96.                         }
  97.                 }
  98.         }
  99.         if (a != 0) {
  100.                 _myhead->pre->insert_back(a);
  101.                 ++_mysize;
  102.         }

  103.         return *this;
  104. }

  105. inline std::string hugeNumber::to_string() const {
  106.         if (_mysize == 0) return "0x0(0)";
  107.         if (_mysize >1) {
  108.                 int a = 4;
  109.         }
  110.         std::stringstream hex, dec;
  111.         hex << std::setbase(16) << std::setw(8) << std::setfill('0');
  112.         Node* p = _myhead->pre;
  113.         while (p != _myhead) {
  114.                 hex << p->val;
  115.                 dec << "-" << p->val;
  116.                 p = p->pre;
  117.         }
  118.         std::string szhex = hex.str();
  119.         while (szhex[0] == '0') {
  120.                 szhex.erase(szhex.begin());
  121.         }
  122.         szhex = "0x" + szhex;

  123.         std::string szdec = dec.str();
  124.         szdec.erase(szdec.begin());

  125.         return szhex + "(" + szdec + ")";
  126. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-7-4 13:05

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表