2022/5/29 第五次大作业 OurString, SuperInt

Problem 1 OurString

本题相当于string类的设计,注意内存的分配与删除,还有越界的问题即可,在此不做过多赘述。

不知道为什么,不用strncpy而是用strcpy的话它会提示有内存泄漏的可能性。但是按照qt提示使用strlcpy却提示没有这个函数,在visual studio里面试过,也没有。最后只能使用strncpy还要手动补零。

 

Problem 1 SuperInt

题目要求使用linked list(链表)来进行大整数的运算。

 

  首先,使用list<int>储存每一位数字,另外单独定义一个int类型的sign来表示正负号。

  题目要求至少重载 + 和 * ,而符号不同的加法又可以转化成减法,加上强迫症,所以我把加减乘除都重载了。

  经过分析,两个数的加减法都可以缩小到 “正数 + 正数” 和 “大的正数 - 小的正数” 两种情况,所以只需要针对这两种情况进行计算。而由于减法和除法的需要,我重载了">"、"=="还有">="三个比较运算符,不过它们不会考虑符号,只比较绝对值的大小。

 

下面是代码

  1 /*
  2  * File: superint.h
  3  * --------------
  4  * This interface exports the SuperInt class, which makes it possible to
  5  * represent nonnegative integers of arbitrary magnitude
  6  * on Assignment #5.
  7  * [TODO: extend the documentation]
  8  */
  9 
 10 #ifndef _superint_h
 11 #define _superint_h
 12 
 13 #include <string>
 14 #include <iostream>
 15 #include <list>
 16 
 17 using namespace std;
 18 
 19 enum SIGN{pos = 1, neg = -1};
 20 
 21 /*
 22  * Implementation notes: SuperInt data structure
 23  * -------------------------------------------
 24  * The SuperInt data structure stores the digits in the number in
 25  * a linked list in which the digits appear in reverse order with
 26  * respect to the items in the list.  Thus, the number 1729 would
 27  * be stored in a list like this:
 28  *
 29  *     start
 30  *    +-----+    +-----+    +-----+    +-----+    +-----+
 31  *    |  o--+--->|  9  |  ->|  2  |  ->|  7  |  ->|  1  |
 32  *    +-----+    +-----+ /  +-----+ /  +-----+ /  +-----+
 33  *               |  o--+-   |  o--+-   |  o--+-   | NULL|
 34  *               +-----+    +-----+    +-----+    +-----+
 35  *
 36  * The sign of the entire number is stored in a separate instance
 37  * variable, which is -1 for negative numbers and +1 otherwise.
 38  * Leading zeros are not stored in the number, which means that
 39  * the representation for zero is an empty list.
 40  */
 41 
 42 class SuperInt {
 43 
 44 public:
 45 
 46     /*
 47      * Constructor: SuperInt
 48      * -----------------------
 49      * Usage: SuperInteger bi;
 50      * Constructs a new big integer with default style;
 51      */
 52    SuperInt();
 53     /*
 54      * Constructor: SuperInt
 55      * -----------------------
 56      * Usage: SuperInteger si1(si2);
 57      * Constructs a new super integer whose value is a copy of another super integer.
 58      */
 59    SuperInt(const SuperInt& s2);
 60    /*
 61     * Constructor: SuperInt
 62     * Usage: SuperInt sup(str);
 63     * -----------------------
 64     * Creates a new SuperInt from a string of decimal digits,
 65     * which may begin with a minus sign to indicate a negative value.
 66     */
 67   SuperInt(const char* s);
 68     /*
 69      * Constructor: SuperInt
 70      * Usage: SuperInt sup(s);
 71      * -----------------------
 72      * Creates a new SuperInt from a const string of decimal digits,
 73      * which may begin with a minus sign to indicate a negative value.
 74      */
 75    SuperInt(std::string str);
 76      /*
 77       * Constructor: SuperInt
 78       * Usage: SuperInt sup(long);
 79       * -----------------------
 80       * Creates a new SuperInt from a decimal long integer,
 81       * which may begin with a minus sign to indicate a negative value.
 82       */
 83     SuperInt(long n);
 84 /*
 85  * Destructor: ~SuperInt
 86  * -------------------
 87  * Frees the memory used by a SuperInt when it goes out of scope.
 88  */
 89     ~SuperInt();
 90 /*
 91  * Method: toString
 92  * Usage: string str = superint.toString();
 93  * --------------------------------------
 94  * Converts a SuperInt object to the corresponding string.
 95  */
 96     std::string toString() const;
 97 
 98 
 99     friend SuperInt operator+(const SuperInt& s1, const SuperInt& s2);
100     friend SuperInt operator-(const SuperInt& s1, const SuperInt& s2);
101     friend SuperInt operator*(const SuperInt& s1, const SuperInt& s2);
102     friend SuperInt operator/(const SuperInt& s1, const SuperInt& s2);
103 
104     friend bool operator>(const SuperInt& s1, const SuperInt& s2);
105     friend bool operator==(const SuperInt& s1, const SuperInt& s2);
106     friend bool operator>=(const SuperInt& s1, const SuperInt& s2);
107 
108     SuperInt& operator=(const SuperInt& s2);
109     friend ostream & operator<<(ostream &os, const SuperInt& s);
110     SuperInt abs();
111 
112 
113 
114 private:
115     list<int> lst;   //本体
116     int sign = pos;   //符号位
117 
118     void removeZero();  //去掉首位的0
119     void carryPosSuperInt();   //进位函数
120 };
121 
122 #endif
superint.h

 

  1 /*
  2  * File: superint.cpp
  3  * ----------------
  4  * This file implements the superint.h interface
  5  * on Assignment #5.
  6  * [TODO: extend the documentation]
  7  */
  8 
  9 #include <cctype>
 10 #include <string>
 11 #include<cstring>
 12 #include<iostream>
 13 #include<vector>
 14 #include "superint.h"
 15 #include "error.h"
 16 using namespace std;
 17 
 18 /*
 19  * Implementation notes: SuperInt data structure
 20  * -------------------------------------------
 21  * The SuperInt data structure stores the digits in the number in
 22  * a linked list in which the digits appear in reverse order with
 23  * respect to the items in the list.  Thus, the number 1729 would
 24  * be stored in a list like this:
 25  *
 26  *     start
 27  *    +-----+    +-----+    +-----+    +-----+    +-----+
 28  *    |  o--+--->|  9  |  ->|  2  |  ->|  7  |  ->|  1  |
 29  *    +-----+    +-----+ /  +-----+ /  +-----+ /  +-----+
 30  *               |  o--+-   |  o--+-   |  o--+-   | NULL|
 31  *               +-----+    +-----+    +-----+    +-----+
 32  *
 33  * The sign of the entire number is stored in a separate instance
 34  * variable, which is -1 for negative numbers and +1 otherwise.
 35  * Leading zeros are not stored in the number, which means that
 36  * the representation for zero is an empty list.
 37  */
 38 
 39 SuperInt::SuperInt()
 40 {
 41     sign = pos;
 42 }
 43 
 44 SuperInt::SuperInt(const SuperInt& s2)  //深拷贝
 45 {
 46     this->sign = s2.sign;
 47     for(int i: s2.lst){
 48         this->lst.push_back(i);
 49     }
 50     removeZero();
 51 }
 52 
 53  SuperInt::SuperInt(const char* s)  //从最高位开始插
 54 {
 55     int i = 0;
 56     if(s[0] == '-'){
 57         i = 1;
 58         sign = neg;
 59     }
 60     for(; i < strlen(s); i++){
 61         lst.push_front(s[i] - '0');
 62     }
 63     lst.push_back(0);   //如果是空字符串,赋0
 64     removeZero();   //防止非个位数前面有0
 65 }
 66 
 67 SuperInt::SuperInt(string str)  //从最高位开始插
 68 {
 69     if(str[0] == '-'){
 70         sign = neg;
 71         str = str.substr(1);
 72     }
 73     for(char ch: str){
 74         lst.push_front(ch);
 75     }
 76     lst.push_back(0);   //如果是空字符串,赋0
 77     removeZero();   //防止非个位数前面有0
 78 }
 79 
 80 SuperInt::SuperInt(long n)  //从个位开始插
 81 {
 82     if(n < 0){
 83         sign = neg;
 84         n *= -1;
 85     }
 86     while(n >= 10){
 87         lst.push_back(n % 10);
 88         n /= 10;
 89     }
 90     lst.push_back(n);
 91 }
 92 
 93 SuperInt::~SuperInt()   //默认析构
 94 {
 95     lst.clear();
 96 }
 97 
 98 
 99 string SuperInt::toString() const
100 {
101    string str = "";
102 
103    for(int i: lst){
104        char ch = i + '0';
105        str = ch + str;  //高位加在左边
106    }
107    if(sign == neg){ //带负号的话加上去
108        str = '-' + str;
109    }
110    if(str == "") str = "0"; //保险起见,加了这个
111    return str;
112 }
113 
114 SuperInt SuperInt::abs(){   //取绝对值
115     if(sign == pos){
116         return *this;
117     }
118     SuperInt s2;
119     s2 = *this;
120     s2.sign = pos;
121     return s2;
122 }
123 
124 SuperInt operator+(const SuperInt& s1, const SuperInt& s2){
125     SuperInt s3;
126 
127     //若二者存在负数
128     if(s1.sign == neg && s2.sign != neg){  //负数加正数
129         SuperInt s4(s1);
130         s4.sign = pos;
131         return s2 - s4;
132     }
133     else if(s1.sign != neg && s2.sign == neg){  //正数加负数
134         SuperInt s4(s2);
135         s4.sign = pos;
136         return s1 - s4;
137     }
138     else if(s1.sign == neg && s2.sign == neg){
139         s3.sign = neg;  //两个负数相加
140     }
141 
142 
143     list<int>::const_iterator s1_it = s1.lst.begin();
144     list<int>::const_iterator s2_it = s2.lst.begin();
145 
146     while(s1_it != s1.lst.end() &&
147           s2_it != s2.lst.end()){
148         int thisNum = *s1_it + *s2_it;    //该位上的和
149         s3.lst.push_back(thisNum);  //不管进位,就插
150         s1_it++;
151         s2_it++;
152     }
153     //到此,二者至少有一个为end()
154 
155     if(s1_it != s1.lst.end()){   //看看是哪个先到end()
156         while(s1_it != s1.lst.end()){
157             s3.lst.push_back(*s1_it);
158             s1_it++;
159         }
160     }
161     else{   //包含都到end()和s2到end()的情况
162         while(s2_it != s2.lst.end()){
163             s3.lst.push_back(*s2_it);
164             s2_it++;
165         }
166     }//得到没有进位的s3
167 
168     //s3开始进位
169     s3.carryPosSuperInt();
170     return s3;  //因为不可能出现首位为0的情况,所以不需要除0
171 }
172 
173 SuperInt operator-(const SuperInt& s1, const SuperInt& s2){
174     SuperInt s3;
175 
176     if(s1.sign == neg && s2.sign == pos){//负数减正数
177         SuperInt s4(s2);
178         s4.sign = neg;
179         return s1 + s4; //转化成两个负数相加
180     }
181     else if(s1.sign == neg && s2.sign != pos){    //负数减负数
182         SuperInt s4(s2);
183         s4.sign = pos;
184         return s4 + s1; //转化为正数加负数
185     }
186     else if(s1.sign == pos && s2.sign == neg){    //正数减负数
187         SuperInt s4(s2);
188         s4.sign = pos;
189         return s1 + s4; //转化为两个正数相加
190     }
191 
192     if(s2 > s1){    //如果被减数比减数小
193         s3 = s2 - s1;
194         s3.sign = neg;  //符号为负
195         return s3;
196     }
197 
198     //只负责正(大)数减正数(小)
199     list<int>::const_iterator s1_it = s1.lst.begin();   //从个位开始
200     list<int>::const_iterator s2_it = s2.lst.begin();
201 
202     while(s1_it != s1.lst.end() &&
203           s2_it != s2.lst.end()){
204         int thisNum = *s1_it - *s2_it;    //该位上的差
205         s3.lst.push_back(thisNum);  //不管进位,就插
206         s1_it++;
207         s2_it++;
208     }
209     //到此,二者至少有一个为end()
210 
211     if(s1_it != s1.lst.end()){   //看看是哪个先到end()
212         while(s1_it != s1.lst.end()){
213             s3.lst.push_back(*s1_it);
214             s1_it++;
215         }
216     }
217     else{   //包含都到end()和s2到end()的情况
218         while(s2_it != s2.lst.end()){
219             s3.lst.push_back(*s2_it);
220             s2_it++;
221         }
222     }//得到没有进位的s3
223 
224     //s3开始进位
225     list<int>::iterator s3_it = s3.lst.begin();
226     while(s3_it != s3.lst.end()){
227         if(*s3_it >= 0){    //不需要进位
228             s3_it++;
229             continue;
230         }
231         else{
232             (*s3_it) += 10; //最多对高一位的数直接造成影响
233 
234             s3_it++;
235             (*s3_it) -= 1;  //退位
236         }
237     }
238     s3.removeZero();
239     return s3;
240 }
241 
242 SuperInt operator*(const SuperInt& s1, const SuperInt& s2){
243      SuperInt s3;
244     //首先对符号进行操作
245     s3.sign = s1.sign * s2.sign;
246 
247     //数字的部分
248     int carries = 0;
249     for(list<int>::const_iterator s1_it = s1.lst.begin(); s1_it !=s1.lst.end(); s1_it++){
250         SuperInt s;
251         for(list<int>::const_iterator s2_it = s2.lst.begin(); s2_it !=s2.lst.end(); s2_it++){
252             s.lst.push_back((*s1_it) * (*s2_it));   //模拟竖式乘法
253         }
254         s.carryPosSuperInt();   //可以最后再进位,但是防止出现超过int范围的情况
255         for(int i = 0; i < carries; i++){
256             s.lst.push_front(0);    //补位
257         }
258 
259         s3 = s3 + s;
260         carries++;
261     }
262 
263     s3.carryPosSuperInt();//保险起见,加一个
264 //    s3.removeZero();//保险起见,加一个
265 
266     return s3;
267 }
268 
269 SuperInt operator/(const SuperInt& s1, const SuperInt& s2){//除法
270     SuperInt result("0");
271     result.sign = s1.sign * s2.sign;
272     SuperInt s(s1);
273     while(s >= s2){
274         result = result + 1;
275         s = s - s2;
276     }
277     return result;
278 }
279 
280 bool operator>(const SuperInt& s1, const SuperInt& s2){ //注意!!!仅比较数字部分!!!
281     if(s1.lst.size() > s2.lst.size()){
282         return true;
283     }
284     else if(s1.lst.size() == s2.lst.size()){
285         list<int>::const_iterator s1_it = s1.lst.end();
286         list<int>::const_iterator s2_it = s2.lst.end();
287         while(s1_it != s1.lst.begin()){
288             s1_it--;
289             s2_it--;
290             if(*s1_it > *s2_it){
291                 return true;
292             }
293         }
294         return false;
295     }
296     else{
297         return false;
298     }
299 
300 }
301 
302 bool operator==(const SuperInt& s1, const SuperInt& s2){    //注意!!!仅比较数字部分!!!
303     if(s1.lst.size() != s2.lst.size()){
304         return false;
305     }
306     list<int>::const_iterator s1_it = s1.lst.end();
307     list<int>::const_iterator s2_it = s2.lst.end();
308     while(s1_it != s1.lst.begin()){
309         s1_it--;
310         s2_it--;
311         if(*s1_it != *s2_it){
312             return false;
313         }
314     }
315     return true;
316 }
317 
318 bool operator>=(const SuperInt& s1, const SuperInt& s2){    //注意!!!仅比较数字部分!!!
319     return s1 > s2 || s1 == s2;
320 }
321 
322 SuperInt& SuperInt::operator = (const SuperInt& s2){
323     lst.clear();
324     this->sign = s2.sign;
325     for(int i: s2.lst){
326         this->lst.push_back(i);
327     }
328     return *this;
329 }
330 
331 ostream& operator << (ostream &os, const SuperInt& s){
332     os << s.toString();
333     return os;
334 }
335 
336 void SuperInt::removeZero(){    //去0,如果最高位上有0就除去
337     while(lst.back() == 0 && lst.size() > 1){  //最高位为0
338         lst.pop_back();
339     }
340 }
341 
342 void SuperInt::carryPosSuperInt(){ //进位,将lst中的每一个数字都化为小于10的数字,然后进位
343     int times;
344     list<int>::iterator it = lst.begin();
345     while(it != lst.end()){
346         times = 0;
347         if(*it < 10){    //不需要进位
348             it++;
349             continue;
350         }
351         else{
352             while(*it >= 10){   //算出进位数
353                 (*it) -= 10;
354                 times++;
355             }
356 
357             it++;   //进位
358             if(it == lst.end()){
359                 lst.push_back(times);
360             }
361             else{
362                 (*it) += times;
363             }
364         }
365     }
366 
367 }
superint.cpp

 

 

目前存在的疑问:

  1.当superint类直接和数字相加减时,它不会报错,是不是因为重载了这些符号后,它会自动调用构造函数生成一个临时的superint变量再进行运算,所以才不会出错呢?

posted @ 2022-05-29 16:57  WangKeWei172  阅读(183)  评论(0)    收藏  举报