C++第9周(春)项目3 - 分数类

课程首页在:http://blog.csdn.net/sxhelijian/article/details/11890759,内有完整教学方案及资源链接

【项目3】在第8周项目3基础上
(1)定义分数的一目运算+和-,分别代表分数取正和求反,将“按位取反运算符”~重载为分数的求倒数运算。
(2)定义分数类中<<和>>运算符重载,实现分数的输入输出,改造原程序中对运算结果显示方式,使程序读起来更自然。

参考解答:

#include <iostream>
#include <Cmath>
using namespace std;
class CFraction
{
private:
    int nume;  // 分子
    int deno;  // 分母
public:
    CFraction(int nu=0,int de=1):nume(nu),deno(de) {}
    void simplify();

    //输入输出的重载
    friend istream &operator>>(istream &in,CFraction &x);
    friend ostream &operator<<(ostream &out,CFraction x);

    CFraction operator+(const CFraction &c);  //两个分数相加,结果要化简
    CFraction operator-(const CFraction &c);  //两个分数相减,结果要化简
    CFraction operator*(const CFraction &c);  //两个分数相乘,结果要化简
    CFraction operator/(const CFraction &c);  //两个分数相除,结果要化简
    CFraction operator+();  //取正一目运算
    CFraction operator-();  //取反一目运算
    CFraction operator~();  //取倒数一目运算
    bool operator>(const CFraction &c);
    bool operator<(const CFraction &c);
    bool operator==(const CFraction &c);
    bool operator!=(const CFraction &c);
    bool operator>=(const CFraction &c);
    bool operator<=(const CFraction &c);
};

// 分数化简
void CFraction::simplify()
{
    int m,n,r;
    n=fabs(deno);
    m=fabs(nume);
    while(r=m%n)  // 求m,n的最大公约数
    {
        m=n;
        n=r;
    }
    deno/=n;     // 化简
    nume/=n;
    if (deno<0)  // 将分母转化为正数
    {
        deno=-deno;
        nume=-nume;
    }
}

// 重载输入运算符>>
istream &operator>>(istream &in,CFraction &x)
{
    char ch;
    while(1)
    {
        cin>>x.nume>>ch>>x.deno;
        if (x.deno==0)
            cerr<<"分母为0, 请重新输入\n";
        else if(ch!='/')
            cerr<<"格式错误(形如m/n)! 请重新输入\n";
        else
            break;
    }
    return cin;
}

// 重载输出运算符<<
ostream &operator<<(ostream &out,CFraction x)
{
    cout<<x.nume<<'/'<<x.deno;
    return cout;
}

// 分数相加
CFraction CFraction::operator+(const CFraction &c)
{
    CFraction t;
    t.nume=nume*c.deno+c.nume*deno;
    t.deno=deno*c.deno;
    t.simplify();
    return t;
}

// 分数相减
CFraction CFraction:: operator-(const CFraction &c)
{
    CFraction t;
    t.nume=nume*c.deno-c.nume*deno;
    t.deno=deno*c.deno;
    t.simplify();
    return t;
}

// 分数相乘
CFraction CFraction:: operator*(const CFraction &c)
{
    CFraction t;
    t.nume=nume*c.nume;
    t.deno=deno*c.deno;
    t.simplify();
    return t;
}

// 分数相除
CFraction CFraction:: operator/(const CFraction &c)
{
    CFraction t;
    if (!c.nume) return *this;   //除法无效(除数为)时,这种情况需要考虑,但这种处理仍不算合理
    t.nume=nume*c.deno;
    t.deno=deno*c.nume;
    t.simplify();
    return t;
}

// 分数取正号
CFraction CFraction:: operator+()
{
    return *this;
}

// 分数取负号
CFraction CFraction:: operator-()
{
    CFraction x;
    x.nume=-nume;
    x.deno=deno;
    return x;
}

// 分数取倒数
CFraction CFraction:: operator~()
{
    CFraction x;
    x.nume=deno;
    x.deno=nume;   //未对原分子为0的情况进行处理
    if(x.deno<0)   //保证负分数的负号在分子上
    {
        x.deno=-x.deno;
        x.nume=-x.nume;
    }
    return x;
}

// 分数比较大小
bool CFraction::operator>(const CFraction &c)
{
    int this_nume,c_nume,common_deno;
    this_nume=nume*c.deno;        // 计算分数通分后的分子,同分母为deno*c.deno
    c_nume=c.nume*deno;
    common_deno=deno*c.deno;
    if ((this_nume-c_nume)*common_deno>0) return true;
    return false;
}

// 分数比较大小
bool CFraction::operator<(const CFraction &c)
{
    int this_nume,c_nume,common_deno;
    this_nume=nume*c.deno;
    c_nume=c.nume*deno;
    common_deno=deno*c.deno;
    if ((this_nume-c_nume)*common_deno<0) return true;
    return false;
}

// 分数比较大小
bool CFraction::operator==(const CFraction &c)
{
    if (*this!=c) return false;
    return true;
}

// 分数比较大小
bool CFraction::operator!=(const CFraction &c)
{
    if (*this>c || *this<c) return true;
    return false;
}

// 分数比较大小
bool CFraction::operator>=(const CFraction &c)
{
    if (*this<c) return false;
    return true;
}

// 分数比较大小
bool CFraction::operator<=(const CFraction &c)
{
    if (*this>c) return false;
    return true;
}

int main()
{
    CFraction x,y,s;
    cout<<"输入x: ";
    cin>>x;
    cout<<"输入y: ";
    cin>>y;
    s=+x+y;
    cout<<"+x+y="<<s<<endl;
    s=x-y;
    cout<<"x-y="<<s<<endl;
    s=x*y;
    cout<<"x*y="<<s<<endl;
    s=x/y;
    cout<<"x/y="<<s<<endl;
    cout<<"-x="<<-x<<endl;
    cout<<"+x="<<+x<<endl;
    cout<<"x的倒数: "<<~x<<endl;

    cout<<x;
    if (x>y) cout<<"大于";
    if (x<y) cout<<"小于";
    if (x==y) cout<<"等于";
    cout<<y<<endl;
    return 0;
}
==================== 迂者 贺利坚 CSDN博客专栏=================
|== IT学子成长指导专栏 专栏文章的分类目录(不定期更新) ==|
|== C++ 课堂在线专栏  贺利坚课程教学链接(分课程年级) ==|
|== 我写的书——《逆袭大学——传给IT学子的正能量》    ==|
===== 为IT菜鸟起飞铺跑道,和学生一起享受快乐和激情的大学 =====
时间: 2024-08-01 15:49:40

C++第9周(春)项目3 - 分数类的相关文章

C++第8周(春)项目3 分数类中的运算符重载

课程首页在:http://blog.csdn.net/sxhelijian/article/details/11890759,内有完整教学方案及资源链接 [项目3-分数类中的运算符重载]实现分数类中的运算符重载,在分数类中可以完成分数的加减乘除(运算后再化简).比较(6种关系)的运算.可以以第5周项目2的代码为基础开始工作. class CFraction { private: int nume; // 分子 int deno; // 分母 public: //构造函数及运算符重载的函数声明 }

C++第5周(春)项目2 分数类的雏形

课程首页在:http://blog.csdn.net/sxhelijian/article/details/11890759,内有完整教学方案及资源链接 [项目2-分数类的雏形] C++中提供了多种基本的数据类型.实际上,这些远不能满足我们的需求,如复数(第10章的例子大多是处理虚数的),再如分数.我们可以自定义类支持这些数据类型. 本任务将设计一个简单的分数类,完成对分数的几个运算.一则巩固基于对象编程的方法,二则也为第10章做运算符重载等积累些感性认识. 分数类的声明为: class CFr

C++第3周(春)项目3 时间类

课程首页在:http://blog.csdn.net/sxhelijian/article/details/11890759,内有完整教学方案及资源链接 [项目3 - 时间类]阅读.运行程序后,按要求增加类的功能 #include <iostream> using namespace std; class Time { public: void set_time( ); void show_time( ); private: bool is_time(int, int, int); //这个成

C++第7周(春)项目4 友元类

课程首页在:http://blog.csdn.net/sxhelijian/article/details/11890759,内有完整教学方案及资源链接 [项目4-友元类] 定义下面两个类的成员函数(为体验友元类,实际上本例并不一定是一个好的设计,将两个类的合并为一个DateTime,日期.时间都处理更好) class Date; //对Date类的提前引用声明 class Time { public: Time(int,int,int); void add_a_second(Date &);

C++第11周(春)项目3 - 点类派生直线类

课程首页在:http://blog.csdn.net/sxhelijian/article/details/11890759,内有完整教学方案及资源链接 [项目3 - 点类派生直线类]定义点类Point,并以点类为基类,派生出直线类Line,从基类中继承的点的信息表示直线的中点.请阅读下面的代码,并将缺少的部分写出来. #include<iostream> #include<Cmath> using namespace std; class Point //定义坐标点类 { pub

C++第4周(春)项目2 三角形类2

课程首页在:http://blog.csdn.net/sxhelijian/article/details/11890759,内有完整教学方案及资源链接 [项目2 - 三角形类2]程序功能同项目1,main()函数如下,请重新定义Triangle类,其中逻辑特别简单的set和get成员函数,要处理为内置成员函数,直接在类内定义. int main() { Triangle tri1; //定义三角形类的一个实例(对象) double x,y,z; cout<<"请输入三角形的三边:&

C++第9周(春)项目1 - 复数类

课程首页在:http://blog.csdn.net/sxhelijian/article/details/11890759,内有完整教学方案及资源链接 [项目1]在第8周项目1基础上(1)再定义一目运算符 -,-c相当于0-c.(2)定义Complex类中的<<和>>运算符的重载,实现输入和输出,改造原程序中对运算结果显示方式,使程序读起来更自然. 参考解答: #include <iostream> using namespace std; class Complex

C++第9周(春)项目2 - Time类

课程首页在:http://blog.csdn.net/sxhelijian/article/details/11890759,内有完整教学方案及资源链接 [项目2]在第8周项目2基础上(1)定义对时间对象的自增和自减一目运算符 //一目运算符的重载 CTime operator++(int);//后置++,下一秒 CTime operator++();//前置++,下一秒,前置与后置返回值不一样 CTime operator--( int);//后置--,前一秒 CTime operator--

C++第5周(春)项目1 三角形类1

课程首页在:http://blog.csdn.net/sxhelijian/article/details/11890759,内有完整教学方案及资源链接 [项目1-三角形类的构造函数] 设计三角形类,通过增加构造函数,使对象在定义时能够进行初始化,可以由下面的类声明开始,需要自己实现相关的成员函数,以及增加要求的构造函数 class Triangle { public: double perimeter();//计算三角形的周长 double area();//计算并返回三角形的面积 void