《C++语言基础》实践参考——分数类中的运算符重载(续)

简介: 返回:贺老师课程教学链接 项目要求【项目3-分数类中的运算符重载(续)】在分数类中的运算符重载基础上(1)定义分数的一目运算+和-,分别代表分数取正和求反,将“按位取反运算符”~重载为分数的求倒数运算。(2)定义分数类中<<和>>运算符重载,实现分数的输入输出,改造原程序中对运算结果显示方式,使程序读起来更自然。[参考解答]#include <iost

返回:贺老师课程教学链接 项目要求


【项目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;
}



目录
相关文章
|
11月前
|
存储 编译器 C++
【c++】类和对象(下)(取地址运算符重载、深究构造函数、类型转换、static修饰成员、友元、内部类、匿名对象)
本文介绍了C++中类和对象的高级特性,包括取地址运算符重载、构造函数的初始化列表、类型转换、static修饰成员、友元、内部类及匿名对象等内容。文章详细解释了每个概念的使用方法和注意事项,帮助读者深入了解C++面向对象编程的核心机制。
268 5
C++(十五) 运算符重载
C++中的运算符重载允许对已有运算符的功能进行重新定义,从而扩展语言功能、简化代码并提升效率。重载遵循特定语法,如 `friend 类名 operator 运算符(参数)`。重载时需注意不可新增或改变运算符数量、语义、优先级、结合性和返回类型。常见示例包括双目运算符 `+=` 和单目运算符 `-` 及 `++`。输入输出流运算符 `&lt;&lt;` 和 `&gt;&gt;` 也可重载。部分运算符只能作为成员函数重载。
|
存储 编译器 C++
【C++】:拷贝构造函数和赋值运算符重载
【C++】:拷贝构造函数和赋值运算符重载
172 1
|
自然语言处理 程序员 C++
C++基础知识(五:运算符重载)
运算符重载是C++中的一项强大特性,它允许程序员为自定义类型(如类或结构体)重新定义标准运算符的行为,使得这些运算符能够适用于自定义类型的操作。这样做可以增强代码的可读性和表达力,使得代码更接近自然语言,同时保持了面向对象编程的封装性。
137 0
|
编译器 C++
【C++】详解运算符重载,赋值运算符重载,++运算符重载
【C++】详解运算符重载,赋值运算符重载,++运算符重载
|
编译器 C++
【C++】类和对象③(类的默认成员函数:赋值运算符重载)
在C++中,运算符重载允许为用户定义的类型扩展运算符功能,但不能创建新运算符如`operator@`。重载的运算符必须至少有一个类类型参数,且不能改变内置类型运算符的含义。`.*::sizeof?`不可重载。赋值运算符`=`通常作为成员函数重载,确保封装性,如`Date`类的`operator==`。赋值运算符应返回引用并检查自我赋值。当未显式重载时,编译器提供默认实现,但这可能不足以处理资源管理。拷贝构造和赋值运算符在对象复制中有不同用途,需根据类需求定制实现。正确实现它们对避免数据错误和内存问题至关重要。接下来将探讨更多操作符重载和默认成员函数。
|
8月前
|
编译器 C++ 开发者
【C++篇】深度解析类与对象(下)
在上一篇博客中,我们学习了C++的基础类与对象概念,包括类的定义、对象的使用和构造函数的作用。在这一篇,我们将深入探讨C++类的一些重要特性,如构造函数的高级用法、类型转换、static成员、友元、内部类、匿名对象,以及对象拷贝优化等。这些内容可以帮助你更好地理解和应用面向对象编程的核心理念,提升代码的健壮性、灵活性和可维护性。
|
4月前
|
人工智能 机器人 编译器
c++模板初阶----函数模板与类模板
class 类模板名private://类内成员声明class Apublic:A(T val):a(val){}private:T a;return 0;运行结果:注意:类模板中的成员函数若是放在类外定义时,需要加模板参数列表。return 0;
95 0
|
4月前
|
存储 编译器 程序员
c++的类(附含explicit关键字,友元,内部类)
本文介绍了C++中类的核心概念与用法,涵盖封装、继承、多态三大特性。重点讲解了类的定义(`class`与`struct`)、访问限定符(`private`、`public`、`protected`)、类的作用域及成员函数的声明与定义分离。同时深入探讨了类的大小计算、`this`指针、默认成员函数(构造函数、析构函数、拷贝构造、赋值重载)以及运算符重载等内容。 文章还详细分析了`explicit`关键字的作用、静态成员(变量与函数)、友元(友元函数与友元类)的概念及其使用场景,并简要介绍了内部类的特性。
173 0