zoukankan      html  css  js  c++  java
  • 作业4-运算符重载

    1.MyString

    补足MyString类,使程序输出指定结果

     1 //补足MyString类,使程序输出指定结果 
     2 #include <iostream>
     3 #include <string>
     4 #include <cstring>
     5 using namespace std;
     6 class MyString {
     7     char * p;
     8 public:
     9     MyString(const char * s) {
    10         if( s) {
    11             p = new char[strlen(s) + 1];
    12             strcpy(p,s);
    13         }
    14         else
    15             p = NULL;
    16 
    17     }
    18     ~MyString() { if(p) delete [] p; } 
    19 // 在此处补充你的代码
    20     MyString(const MyString & s){ //初始化的时候p肯定就是NULL 
    21         if(s.p==NULL) p = NULL;
    22         else{
    23             p = new char[strlen(s.p) + 1];
    24             strcpy(p,s.p);
    25         }
    26     } 
    27     void Copy(const char * s){
    28             if(p) delete [] p; //一定要先删掉!! 
    29             if(s){
    30                 p = new char[strlen(s) + 1];
    31                 strcpy(p,s);
    32             }
    33             else p = NULL;     
    34     } 
    35     MyString & operator = (const char * s){//返回值要是引用,是为了处理连等情况 
    36         if(p) delete [] p;
    37         if(s){
    38             p = new char[strlen(s)+1];
    39             strcpy(p ,s);
    40             return *this;
    41         } 
    42     
    43     } 
    44     MyString & operator = (const MyString & s){ //需要是深拷贝 
    45         if(p) delete [] p;
    46         p = new char[strlen(s.p)+1]; //为什么非要new? 
    47         strcpy(p, s.p);
    48         return * this; 
    49     } 
    50     friend ostream & operator<<(ostream & o, const MyString & s){ //必须得是友元才能访问私有对象,友元函数可以写在类里面 
    51         o << s.p ; //但是p是私有成员,所以要搞成友元 
    52         return o; //返回cout的引用 
    53     } 
    54 };
    55 
    56 int main()
    57 {
    58     char w1[200],w2[100];
    59     while( cin >> w1 >> w2) {
    60         MyString s1(w1),s2 = s1; //需要自己写一个复制函数 
    61         MyString s3(NULL);
    62         s3.Copy(w1);
    63         cout << s1 << "," << s2 << "," << s3 << endl;
    64 
    65         s2 = w2; //需要重载=号 
    66         s3 = s2;
    67         s1 = s3;
    68         cout << s1 << "," << s2 << "," << s3 << endl;
    69         
    70     }
    71 }

    备注:应该先观察main函数,发现有几个要点:

    1.要自己写一个复制构造函数,确保s2=s1是深拷贝(我最后就是这一步忘记了导致RE,因为浅拷贝会在s2=w2时使s1指向的MyString也修改,这样之后就会有问题)

    2.写一个Copy函数(这个函数不需要有返回值),函数体和复制构造函数差不多,要注意的是,复制构造函数是在初始化时被调用,所以不需要delete原有的p,但copy时一定要删掉本来p指向的内存空间。然后就是注意深拷贝的写法,要先new出来一个空间,然后用strcpy把字符串粘过去

    3.重载=号,参数为字符串指针,对应的是s2=w2那一行,和复制构造函数的写法也很像,但要注意返回值是*this,还要注意一下函数头是怎么写的

    4.重载=号,参数为MyString类(的引用),对应66行s3=s2。

    5.重载流插入运算符<<。这个函数是全局函数,但是因为是MyString类的友元,这道题又是个程序填空题,所以就把它写在类里面。

    ps.我的这几个函数写的都不是很严谨,因为就只考虑了题目要求。按理说应该每个函数都先判断一下s是不是为空,再执行复制操作,否则是没有strlen(s)的;另外就是要考虑s=s这种情况,应该加一句if(this==&s) return *this。虽然这道题里没有涉及,我就没写。

    2.看上去好坑的运算符重载

     1 /*输入
     2 多组数据,每组一行,整数n
     3 输出
     4 对每组数据,输出一行,包括两个整数, n-5和n - 8
     5 */ 
     6 #include <iostream> 
     7 using namespace std;
     8 class MyInt 
     9 { 
    10     int nVal; 
    11     public: 
    12     MyInt( int n) { nVal = n ;}
    13 // 在此处补充你的代码
    14     MyInt & operator-(const int n){ //这里比较特殊,需要-等同于-=。 
    15         nVal-=n;
    16         return *this;
    17     } 
    18     operator int(){ //重载类型转换运算符!! 
    19         return nVal;
    20     } 
    21 }; 
    22 int Inc(int n) {
    23     return n + 1;
    24 }
    25 int main () { 
    26     int n;
    27     while(cin >>n) {
    28         MyInt objInt(n); 
    29         objInt-2-1-3; 
    30         cout << Inc(objInt); //这里需要重载类型转换运算符  
    31         cout <<","; 
    32         objInt-2-1; 
    33         cout << Inc(objInt) << endl;
    34     }
    35     return 0;
    36 }

    备注:这道题需要重载减号和类型转换运算符

    其中减号的重载比较特殊,返回值需要是引用,因为-相当于-=。一般情况下返回值是对象就可以。

    类型转换运算符的写法要注意!!

    3.惊呆!point竟然能这样输入输出

     1 /*输入
     2 多组数据,每组两个整数
     3 输出
     4 对每组数据,输出一行,就是输入的两个整数
     5 */ 
     6 #include <iostream> 
     7 using namespace std;
     8 class Point { 
     9     private: 
    10         int x; 
    11         int y; 
    12     public: 
    13         Point() { };
    14 // 在此处补充你的代码
    15         friend istream & operator>> (istream & is, Point & p){ //这里point不能是const啊!! 
    16             is>>p.x>>p.y;
    17             return is;
    18         }
    19         friend ostream & operator<< (ostream & o,const Point & p){
    20             o<<p.x<<","<<p.y;
    21             return o;
    22         }
    23 }; 
    24 int main() 
    25 { 
    26      Point p;
    27      while(cin >> p) {
    28          cout << p << endl;
    29      }
    30     return 0;
    31 }

    备注:这道题要注意的就是流提取的参数肯定不能是const啊……不然怎么输入,我太蠢了。其实记运算符重载怎么写的要点就在于函数名是operator和你要重载的那个运算符。然后流提取和流插入比较特殊,要记住返回值和参数都需要是引用。 

    4.[]的重载

    /*写一个二维数组类 Array2,使得下面程序的输出结果是:
    0,1,2,3,
    4,5,6,7,
    8,9,10,11,
    next
    0,1,2,3,
    4,5,6,7,
    8,9,10,11,
    */
    #include <iostream>
    #include <cstring>
    using namespace std;
    
    class Array2 {
    // 在此处补充你的代码
        private:
            int x, y;
            int *p; //用一个一维数组来存 
        public:
            Array2(int xx, int yy):x(xx), y(yy){p = new int[xx*yy];} //构造函数里new了就要记得写析构函数!! 
            Array2(){
                x = 0; y = 0; p = NULL;
            } 
            ~Array2(){
                if(p) delete []p;
            } 
            int * operator[](int i){ //[]的重载需要是一个指针,这样才能访问p[i][j]  
            //注意[]其实有两个参数!!!只有第一个参数为Array2的时候才会调用,这就是为什么第二个中括号是正常访问数组下标! 
                return (p+i*y); 
            } 
            int operator()(int i, int j){
                return p[i*y+j];
            }
            Array2 & operator=(const Array2 & a){
                if(p) delete[]p;
                x = a.x; y = a.y;
                p = new int[x*y]; //注意一定是中括号!! 
                memcpy(p, a.p, sizeof(int)*x*y); //注意memcpy的使用!
                return *this; 
            } 
    };
    
    int main() {
        Array2 a(3,4); //构造函数 
        int i,j;
        for(  i = 0;i < 3; ++i )
            for(  j = 0; j < 4; j ++ )
                a[i][j] = i * 4 + j; //要重载中括号 
        for(  i = 0;i < 3; ++i ) {
            for(  j = 0; j < 4; j ++ ) {
                cout << a(i,j) << ","; //重载小括号 
            }
            cout << endl;
        }
        cout << "next" << endl;
        Array2 b;     b = a;  //重载等于号 
        for(  i = 0;i < 3; ++i ) {
            for(  j = 0; j < 4; j ++ ) {
                cout << b[i][j] << ",";
            }
            cout << endl;
        }
        return 0;
    }

    备注:这道题一个是要注意别忘了写析构函数!!!二是比较神奇的一个地方,用一个一维数组存二维数组,然后重载中括号。为什么可以实现只重载第一个中括号呢?我问了助教才知道orz因为[]这个运算符实际有两个参数,一个是[]前面的a,一个是[]里面的i,只有在a是Array2这个新类型时,才会调用重载;那么第一个中括号已经调用了重载,返回值是一个指针,对于第二个中括号来说,两个参数就是 int* 和 int,就是正常的数组下标,就不会调用重载了!!

    还有就是我最后犯了一个错误,p = new int[x*y]一定是中括号!!有一个无良程序写成了小括号,我查了一下发现小括号是指把这个整型初始化成了x*y,这显然不对!

     5.别叫,这个大整数已经很简化了!

      1 #include <iostream> 
      2 #include <cstring> 
      3 #include <cstdlib> 
      4 #include <cstdio> 
      5 using namespace std;
      6 const int MAX = 110; 
      7 class CHugeInt {
      8 // 在此处补充你的代码
      9     char s[200];
     10 public:
     11     void reverse(char *a){
     12         int i = 0, j = strlen(a)-1;
     13         while(i < j){
     14             swap(a[i], a[j]);//原来真有这个神奇函数?
     15             i++; 
     16             j--;
     17         }
     18     }    
     19     CHugeInt(char *a){
     20         memset(s, 0, sizeof(s)); //先清零!
     21         strcpy(s, a);
     22         reverse(s); 
     23     }
     24     CHugeInt(int a){
     25         memset(s, 0, sizeof(s)); //先清零!
     26         int tmp = 0;
     27         if(a == 0) s[0] = '0'; //一定要加上这行!!否则如果a是0,CHugeInt里就没有数了! 
     28         else{
     29             while(a > 0){
     30                 s[tmp] = '0'+a%10;
     31                 tmp++;
     32                 a/=10;
     33         } //还可以用一个函数sprintf(s,"%d",n); 
     34         }
     35     }
     36     CHugeInt operator+(const CHugeInt &a){
     37         CHugeInt ans(0);
     38         if(a.s[0]=='0'&&strlen(a.s)==1) //特判0 
     39             return *this;
     40         if(s[0]=='0'&&strlen(s)==1){
     41             strcpy(ans.s,a.s);
     42             return ans;
     43         }
     44         int j = 0; //进位 
     45         int len = max(strlen(s), strlen(a.s));
     46         for(int i = 0; i < len; i++){
     47             int x = 0; 
     48             int a1 = max(s[i]-'0',0);//防止是s[i]==0的情况
     49             int a2 = max(a.s[i]-'0',0);
     50             x = a1+a2+j; 
     51             j = x/10;
     52             x%=10;
     53             ans.s[i] = '0'+x;
     54         }
     55         if(j!=0)
     56             ans.s[len]=j+'0';
     57         return ans;
     58     } 
     59     CHugeInt operator +(int n) {
     60         return *this + CHugeInt(n);
     61     }
     62     CHugeInt operator +=(int n){
     63         *this = *this + n;
     64         return *this;
     65     } 
     66     friend CHugeInt operator +(int n, CHugeInt &num) { //转成了上一类。这需要是一个全局函数。运算符重载为友元函数 
     67         return num + n;
     68     }
     69     friend ostream& operator<<(ostream & o, const CHugeInt& num){ //ostream这个参数就正经地写成const别瞎写orz 
     70         for(int i = strlen(num.s)-1; i >= 0; i--)
     71             o<<num.s[i];
     72         return o;
     73     }
     74     CHugeInt operator++(){//前置形式 
     75         *this = *this + 1;
     76         return *this; 
     77     }
     78     CHugeInt operator++(int){ //后置形式 
     79         CHugeInt record(*this);
     80         *this = *this + 1;
     81         return record;
     82     } 
     83 };
     84 int  main() 
     85 { 
     86     char s[210];
     87     int n;
     88 
     89     while (cin >> s >> n) {
     90         CHugeInt a(s);
     91         CHugeInt b(n);
     92         cout << a + b << endl;
     93         cout << n + a << endl;
     94         cout << a + n << endl;
     95         b += n;
     96         cout  << ++ b << endl;
     97         cout << b++ << endl;
     98         cout << b << endl;
     99     }
    100     return 0;
    101 }

    备注:

     这道题还是又硬核又有趣的。首先就是高精度运算大整数都要倒着写,然后要先写一个reverse函数,C++标准库里居然真的有swap这个函数!!太神奇了吧。构造函数里就先倒过来存起来,但一定要注意清零!!还有就是因为我是手动把整型转成字符串的,一定要注意0这种情况的特判!就像在运算时也要注意避免出现0-‘0’这种情况的出现。还有就是为了满足加法交换律+号要重载好几次,但都可以巧妙地转换成写好的第一类哈哈哈。还有就是自增运算符的重载注意一下,前置(成员函数)没有参数,后置有一个没用的参数orz

  • 相关阅读:
    删除Tomcat服务及其它注意
    下拉菜单被js图片挡住
    There are no resources that can be added or removed from the server
    Mysql存中文值乱码
    myeclipse的项目导入到eclipse下,com.sun.org.apache.commons.beanutils.BeanUtils不能导入
    No enclosing instance of type E is accessible. Must qualify the allocation with an enclosing
    winServer2003除默认端口外的其他端口只能本地访问,关闭防火墙即可
    Oracle 11.2.0.3 on windows 2008 r2
    windows2008 r2 卸载GI
    初始化参数(Initialization Parameter)知识合集 based on 11g
  • 原文地址:https://www.cnblogs.com/fangziyuan/p/12468924.html
Copyright © 2011-2022 走看看