面向对象程序设计-15-运算符重载应用

声明

题解包含以下内容:

  • (相对)高级的 C++ 模板及语法技巧
  • 仅适用于 C++20 标准的代码
  • 强烈的个人代码风格和 Modern C++ 范式追求
  • 泛滥的标准库函数

换句话说就是(相较于其他公开题解)更低的查重率和更高的使用门槛;请酌情使用。

【id:81】【20分】A. 三维坐标点的平移(运算符重载)

题目描述

定义一个三维点Point类,利用友元函数重载"++“和”–"运算符,并区分这两种运算符的前置和后置运算。

lab15-A-1

要求如下:

  1. 实现Point类;
  2. 编写main函数,初始化1个Point对象,将这个对象++或–后赋给另外一个对象,并输出计算后对象的坐标信息。

输入

第1行:输入三个int类型的值,分别为一个Point对象p1的x,y,z坐标。

输出

第1行:Point对象p1后置++之后的坐标信息输出。
第2行:Point对象p1后置++操作后赋给另外一个Point对象p2的坐标信息。
第3行开始,依次输出前置++,后置–,前置–运算的坐标信息,输出格式与后置++一样。
即:
p2=p1++;
第1行输出p1
第2行输出p2

p1恢复原值
p2=++p1;
第3行输出p1
第4行输出p2

p1恢复原值
p2=p1–;
第5行输出p1
第6行输出p2

p1恢复原值
p2=–p1;
第7行输出p1
第8行输出p2

样例

输入样例1输出样例1
10 20 30x=11 y=21 z=31
x=10 y=20 z=30
x=11 y=21 z=31
x=11 y=21 z=31
x=9 y=19 z=29
x=10 y=20 z=30
x=9 y=19 z=29
x=9 y=19 z=29

提示

原值是最初输入的数值

第1行是p1后置++后,再输出
第2行是p1恢复原值,接着p1后置++同时复制给p2,p2输出
第3、4行是p1恢复原值,p1前置++同时输出,然后p1再输出
第5、6行是p1恢复原值,p1后置–后,再输出,接着输出一次原值
第7、8行是p1恢复原值,p1前置–同时输出,然后p1再输出

Answer

#include<bits/stdc++.h>
using namespace std;

class Point {
  int x, y, z;

public:
  constexpr Point( int xx = 0, int yy = 0, int zz = 0 ) noexcept
    : x { xx }, y { yy }, z { zz } {}
  friend constexpr Point operator++( Point& p ) noexcept {
    ++p.x; ++p.y; ++p.z;
    return p;
  }
  friend constexpr Point operator++( Point& p, int ) noexcept {
    Point tmp = p;
    ++p.x; ++p.y; ++p.z;
    return tmp;
  }
  friend constexpr Point operator--( Point & p ) noexcept {
    --p.x; --p.y; --p.z;
    return p;
  }
  friend constexpr Point operator--( Point &p, int ) noexcept {
    Point tmp = p;
    --p.x; --p.y; --p.z;
    return tmp;
  }
  void show() const {
    cout << "x=" << x << " y=" << y << " z=" << z << endl;
  }
  friend istream& operator>>( istream& is, Point& p ) {
    return is >> p.x >> p.y >> p.z;
  }
};

int main()
{
  Point p1, p2;
  cin >> p1;
  const Point p1_bk = p1;

  p1++; p1.show();
  (p2 = (p1 = p1_bk)++).show();

  (++(p1 = p1_bk)).show();
  (p2 = ++(p1 = p1_bk)).show();

  (p1 = p1_bk)--; p1.show();
  (p2 = (p1 = p1_bk)--).show();

  (--(p1 = p1_bk)).show();
  (p2 = --(p1 = p1_bk)).show();
}

不会出题就别几把出,这什么破题?话都说不明白。

还有正常人会用友元重载自增运算符?垃圾题目真给你烂完了。


【id:191】【20分】B. 货币加减(运算符重载)

题目描述

定义CMoney类,包含元、角、分三个数据成员,友元函数重载‘+’、‘-’,实现货币的加减运算(假设a-b中a的金额始终大于等于b的金额),

重载输入及输出,实现货币的输入,输出

读入最初的货币值,对其不断进行加、减操作,输出结果。

可根据需要,为CMoney类添加构造函数或其它成员函数。

输入

测试次数

每组测试数据格式如下:

第一行,初始货币:元 角 分

第二行开始,每行一个操作:add 元 角 分(加)、minus 元 角 分(减)、stop(结束)

输出

对每组测试数据,输出操作终止后的货币金额,具体输出格式见样例。

样例

输入样例1输出样例1
2
0 0 0
add 48 9 0
minus 0 5 3
add 18 6 8
add 12 1 2
stop
10 2 5
add 5 8 0
add 32 1 2
minus 10 5 9
minus 37 5 8
stop
79元1角7分
0元0角0分

Answer

#include <bits/stdc++.h>
using namespace std;

class CMoney {
  int yuan, jiao, fen;

public:
  explicit CMoney( int y = 0, int j = 0, int f = 0 )
    : yuan { y }, jiao { j }, fen { f } {}
  friend CMoney operator+( const CMoney& a, const CMoney& b ) {
    const auto tmp = (a.fen + a.jiao * 10 + a.yuan * 100) + (b.fen + b.jiao * 10 + b.yuan * 100);
    return CMoney( tmp / 100, tmp / 10 % 10, tmp % 10 );
  }
  friend CMoney operator-( const CMoney& a, const CMoney& b ) {
    const auto tmp = (a.fen + a.jiao * 10 + a.yuan * 100) - (b.fen + b.jiao * 10 + b.yuan * 100);
    return CMoney( tmp / 100, tmp / 10 % 10, tmp % 10 );
  }
  friend istream& operator>>( istream& is, CMoney& m ) {
    return is >> m.yuan >> m.jiao >> m.fen;
  }
  friend ostream& operator<<( ostream& os, const CMoney& m ) {
    return os << m.yuan << "元" << m.jiao << "角" << m.fen << "分";
  }
};

int main()
{
#ifdef _WIN32
  system( "chcp 65001" );
#endif

  size_t t {}; cin >> t;
  while ( t-- ) {
    CMoney cash; cin >> cash;
    string order;
    while ( (cin >> order) && order != "stop" ) {
      if ( order == "add" ) {
        CMoney add; cin >> add;
        cash = cash + add;
      } else if ( order == "minus" ) {
        CMoney sub; cin >> sub;
        cash = cash - sub;
      }
    }
    cout << cash << endl;
  }
}

【id:93】【20分】C. 时钟调整(运算符前后增量)

题目描述

假定一个时钟包含时、分、秒三个属性,取值范围分别为0~11,0~59,0~59,具体要求如下:

1、用一元运算符++,并且是前增量的方法,实现时钟的调快操作。例如要把时钟调快5秒,则执行5次” ++<对象> “ 的操作

2、用一元运算符–,并且是后增量的方法,实现时钟的调慢操作。例如要把时钟调慢10秒,则执行10次” <对象>-- “的操作

3、用构造函数的方法实现时钟对象的初始化,用输出函数实现时钟信息的输出

clock和time是系统内部函数,所以不要用来做类名或者其他

输入

第一行输入时钟的当前时间时、分、秒

第二行输入t表示有t个示例

第三行输入t个整数x,如果x为正整数,则表示执行调快操作,使用重载运算符++;如果x为负整数,则表示执行调慢操作,使用重载运算符–

每次的调快或调慢操作都是承接上一次调整后的结果进行,例如先调快10秒,再调慢2秒,那么调慢2秒是接着调快10秒后的结果进行的

输出

每行输出每个时钟调整操作后的时分秒

样例

输入样例1输出样例1
11 58 46
4
5 70 -22 -55
11:58:51
0:0:1
11:59:39
11:58:44

Answer

#include <bits/stdc++.h>
using namespace std;

class Clock {
  int hour, minute, second;

public:
  Clock( int hh, int mm, int ss )
    : hour { hh }, minute { mm }, second { ss } {}
  Clock() : Clock( {}, {}, {} ) {}
  Clock& operator++() noexcept {
    ++second;
    if ( second == 60 ) {
      second = 0;
      ++minute;
      if ( minute == 60 ) {
        minute = 0;
        ++hour;
      }
    }
    hour %= 12;
    return *this;
  }
  Clock operator--( int ) noexcept {
    Clock before = *this;
    --second;
    if ( second == -1 ) {
      second = 59;
      --minute;
      if ( minute == -1 ) {
        minute = 59;
        --hour;
      }
    }
    hour = hour == -1 ? 11 : hour;
    return before;
  }
  friend istream& operator>>( istream& is, Clock& ck ) {
    return is >> ck.hour >> ck.minute >> ck.second;
  }
  friend ostream& operator<<( ostream& os, const Clock& ck ) {
    return os << ck.hour << ":" << ck.minute << ":" << ck.second;
  }
};

int main()
{
  Clock ck; cin >> ck;
  size_t t; cin >> t;
  while ( t-- ) {
    int x; cin >> x;
    if ( x > 0 )
      while ( x-- )
        ++ck;
    else while ( x++ )
      ck--;
    cout << ck << endl;
  }
}

【id:190】【20分】D. X的放大与缩小(运算符重载)

题目描述

X字母可以放大和缩小,变为n行X(n=1,3,5,7,9,…,21)。例如,3行x图案如下:

lab15-D-1

现假设一个n行(n>0,奇数)X图案,遥控器可以控制X图案的放大与缩小。遥控器有5个按键,1)show,显示当前X图案;2)show++, 显示当前X图案,再放大图案,n+2;3)++show,先放大图案,n+2,再显示图案;4)show–,显示当前X图案,再缩小图案,n-2;5)–show,先缩小图案,n-2,再显示图案。假设X图案的放大和缩小在1-21之间。n=1时,缩小不起作用,n=21时,放大不起作用。

用类CXGraph表示X图案及其放大、缩小、显示。主函数模拟遥控器,代码如下,不可修改。请补充CXGraph类的定义和实现。

int main()
{
    int t, n;
    string command;
    cin >> n;
    CXGraph xGraph(n);
    cin >> t;
    while (t--)
    {
        cin >> command;
        if (command == "show++")
        {
            cout << xGraph++ << endl;
        }
        else if(command == "++show")
        {
            cout << ++xGraph << endl;
        }
        else if (command == "show--")
        {
            cout << xGraph-- << endl;
        }
        else if (command == "--show")
        {
            cout << --xGraph << endl;
        }
        else if (command == "show")
        {
            cout << xGraph << endl;
        }
    }
    return 0;
}

输入

第一行n,大于0的奇数,X图案的初始大小。

第二行,操作次数

每个操作一行,为show、show++、show–、–show、++show之一,具体操作含义见题目。

输出

对每个操作,输出对应的X图案。

样例

输入样例1输出样例1
3
5
show
show++
show++
++show
--show
XXX
 X
XXX

XXX
 X
XXX

XXXXX
 XXX
  X
 XXX
XXXXX

XXXXXXXXX
 XXXXXXX
  XXXXX
   XXX
    X
   XXX
  XXXXX
 XXXXXXX
XXXXXXXXX

XXXXXXX
 XXXXX
  XXX
   X
  XXX
 XXXXX
XXXXXXX

Markdown 用的 HTML 标签不能和带文本编辑的 OJ 相比,将就着看就行,也不是不能用。

Answer

#include <bits/stdc++.h>
using namespace std;

class CXGraph {
  int n;

public:
  CXGraph( int nn )
    : n { nn } {}
  CXGraph& operator++() noexcept {
    if ( n < 21 )
      n += 2;
    return *this;
  }
  CXGraph operator++( int ) noexcept {
    CXGraph before = *this;
    this->operator++();
    return before;
  }
  CXGraph& operator--() noexcept {
    if ( n > 1 )
      n -= 2;
    return *this;
  }
  CXGraph operator--( int ) noexcept {
    CXGraph before = *this;
    this->operator--();
    return before;
  }
  friend ostream& operator<<( ostream& os, const CXGraph& g ) {
    string output;
    for ( int i = 0; i < g.n; i += 2 )
      output.append( i / 2, ' ' ).append( g.n - i, 'X' ).push_back( '\n' );
    for ( int i = g.n - 3; i >= 0; i -= 2 )
      output.append( i / 2, ' ' ).append( g.n - i, 'X' ).push_back( '\n' );
    return os << output;
  }
};

int main()
{
  int t, n;
  string command;
  cin >> n;
  CXGraph xGraph( n );
  cin >> t;
  while ( t-- ) {
    cin >> command;
    if ( command == "show++" ) {
      cout << xGraph++ << endl;
    } else if ( command == "++show" ) {
      cout << ++xGraph << endl;
    } else if ( command == "show--" ) {
      cout << xGraph-- << endl;
    } else if ( command == "--show" ) {
      cout << --xGraph << endl;
    } else if ( command == "show" ) {
      cout << xGraph << endl;
    }
  }
  return 0;
}

【id:188】【20分】E. 矩形关系(运算符重载)

题目描述

假设坐标采用二维平面坐标。

定义点类CPoint,包含属性x,y(整型)。方法有:带参构造函数,getX,getY分别返回点的x坐标,y坐标。

定义矩形类CRectangle,包含属性:矩形的左上角坐标leftPoint,右下角坐标rightPoint。类中方法有:

1)带参构造函数,初始化矩形的左上角、右下角

2)重载>运算符,参数为CPoint点对象,假设为p,若p在矩形内,返回true,否则返回false。

3)重载>运算符,第一个矩形若包含第二个矩形(部分边界可以相等),返回true,否则返回false。(要求该函数调用2)实现)

4)重载==运算符,判断两个矩形是否一致,返回true或false。

5)重载*运算符,判断两个矩形是否有重叠部分,返回true或false。

6)重载类型转换运算符,计算矩形的面积并返回,面积是整型。

7)重载<<运算符,输出矩形的两个角坐标,具体格式见样例。

输入2个矩形,计算面积,判断矩形的关系。主函数如下,不可修改。

int main()
{
    int t, x1, x2, y1, y2;
    cin >> t;
    while (t--)
    {
        // 矩形1的左上角、右下角
        cin >> x1 >> y1 >> x2 >> y2;
        CRectangle rect1(x1, y1, x2, y2);
        // 矩形2的左上角、右下角
        cin >> x1 >> y1 >> x2 >> y2;
        CRectangle rect2(x1, y1, x2, y2);
        // 输出矩形1的坐标及面积
        cout << "矩形1:" << rect1 << " " << (int)rect1 << endl;
        // 输出矩形2的坐标及面积
        cout << "矩形2:" << rect2 << " " << (int)rect2 << endl;
        if (rect1 == rect2)
        {
            cout << "矩形1和矩形2相等" << endl;
        }
        else if (rect2 > rect1)
        {
            cout << "矩形2包含矩形1" << endl;
        }
        else if (rect1 > rect2)
        {
            cout << "矩形1包含矩形2" << endl;
        }
        else if (rect1 * rect2)
        {
            cout << "矩形1和矩形2相交" << endl;
        }
        else
        {
            cout << "矩形1和矩形2不相交" << endl;
        }
        cout << endl;
    }
    return 0;
}

可根据需要,添加构造函数和析构函数。

输入

测试次数

每组测试数据如下:

矩形1的左上角、右下角坐标

矩形2的左上角、右下角坐标

输出

每组测试数据输出如下,中间以空行分隔:

矩形1的坐标和面积(具体格式见样例)

矩形2的坐标和面积(具体格式见样例)

矩形1和矩形2的关系(矩形1包含矩形2、矩形2包含矩形1、矩形2和矩形1相等、矩形1和矩形2相交、矩形1和矩形2不相交)

样例

输入样例1输出样例1
2
1 4 4 1
2 3 3 2
1 4 4 1
0 3 5 2
矩形1:1 4 4 1 9
矩形2:2 3 3 2 1
矩形1包含矩形2

矩形1:1 4 4 1 9
矩形2:0 3 5 2 5
矩形1和矩形2相交

Answer

#include <bits/stdc++.h>
using namespace std;

class CPoint {
  int x, y;

public:
  CPoint( int xx, int yy )
    : x { xx }, y { yy } {}
  CPoint() : CPoint( {}, {} ) {}
  int getX() const noexcept { return x; }
  int getY() const noexcept { return y; }
  bool operator==( const CPoint& p ) const noexcept {
    return x == p.x && y == p.y;
  }
  friend ostream& operator<<( ostream& os, const CPoint& point ) {
    return os << point.x << " " << point.y;
  }
};

class CRectangle {
  CPoint leftPoint, rightPoint;

public:
  CRectangle( CPoint left, CPoint right )
    : leftPoint { move( left ) }, rightPoint { move( right ) } {}
  CRectangle( int xx1, int yy1, int xx2, int yy2 ) : CRectangle( { xx1, yy1 }, { xx2, yy2 } ) {}
  bool operator>( const CPoint& p ) const noexcept {
    return
      leftPoint.getX() <= p.getX() && p.getX() <= rightPoint.getX() &&
      rightPoint.getY() <= p.getY() && p.getY() <= leftPoint.getY();
  }
  bool operator>( const CRectangle& r ) const noexcept {
    return operator>( r.leftPoint ) && operator>( r.rightPoint );
  }
  bool operator==( const CRectangle& r ) const noexcept {
    return r.leftPoint == leftPoint && r.rightPoint == rightPoint;
  }
  bool operator*( const CRectangle& r ) const noexcept {
    return
      rightPoint.getX() >= r.leftPoint.getX() && // this 的右下点要在 r 的左上点的右方
      rightPoint.getY() <= r.leftPoint.getY() && // this 的右下点要在 r 的左上点的下方
      r.rightPoint.getX() >= leftPoint.getX() && // this 的左上点要在 r 的右下点的左方
      r.rightPoint.getY() <= leftPoint.getY(); // this 的左上点要在 r 的右下点的上方
  }
  operator int() const noexcept {
    return abs( leftPoint.getX() - rightPoint.getX() ) * abs( leftPoint.getY() - rightPoint.getY() );
  }
  friend ostream& operator<<( ostream& os, const CRectangle& r ) {
    return os << r.leftPoint << " " << r.rightPoint;
  }
};

int main()
{
#ifdef _WIN32
  system( "chcp 65001" );
#endif

  int t, x1, x2, y1, y2;
  cin >> t;
  while ( t-- ) {
    // 矩形1的左上角、右下角
    cin >> x1 >> y1 >> x2 >> y2;
    CRectangle rect1( x1, y1, x2, y2 );
    // 矩形2的左上角、右下角
    cin >> x1 >> y1 >> x2 >> y2;
    CRectangle rect2( x1, y1, x2, y2 );
    // 输出矩形1的坐标及面积
    cout << "矩形1:" << rect1 << " " << (int)rect1 << endl;
    // 输出矩形2的坐标及面积
    cout << "矩形2:" << rect2 << " " << (int)rect2 << endl;
    if ( rect1 == rect2 ) {
      cout << "矩形1和矩形2相等" << endl;
    } else if ( rect2 > rect1 ) {
      cout << "矩形2包含矩形1" << endl;
    } else if ( rect1 > rect2 ) {
      cout << "矩形1包含矩形2" << endl;
    } else if ( rect1 * rect2 ) {
      cout << "矩形1和矩形2相交" << endl;
    } else {
      cout << "矩形1和矩形2不相交" << endl;
    }
    cout << endl;
  }
  return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值