C++面向对象程序设计习题1:分数相加

C++面向对象程序设计习题1:分数相加

自从学习了C++面向对象编程相关基础语法后,苦于没有相应的习题来练习,偶然遇到了大佬华师数据学院·王嘉宁分享的50道习题,比较基础,但是确实会给我这样的初学者一个可以简单上手的机会。

接下来我打算用这个暑假的时间来完成一共50道题目的解答,当然会参考大佬给出的解答,但是更多的会加入自己的一些想法,为了自己立的flag不会倒,我会把所有的代码及时分享出来,有空闲也会详细说明一些语法,希望与大家共勉。

下面是第一题:分数相加

/*
 * 实现分数相加
 * 分子分母均为无符号整数
 * 单独有一位char类型的成员表示正负号
 */


#ifndef _FRACT_HPP_
#define _FRACT_HPP_

#include <iostream>

using uint_t = unsigned int;

class Fract
{
private:
    uint_t fenzi, fenmu; // 分子分母均为正数表示
    char sign; // 正负号,默认为'+'

    uint_t gcd(uint_t, uint_t) const; // 最大公约数
    uint_t lcm(uint_t, uint_t) const; // 最小公倍数
public:
    explicit Fract(uint_t a = 0, uint_t b = 1, char s = '+'); // 构造函数参数默认值写入函数声明中,且使用explicit禁用复制初始化
    
    void add(const Fract&);
    void sub(const Fract&);
    Fract operator+(const Fract&) const;
    Fract operator-(const Fract&) const;
    void show() const;
};

// 构造函数,检查分子分母是否最简
Fract::Fract(uint_t a, uint_t b, char s) : fenzi(a), fenmu(b), sign(s)
{
    uint_t init_gcd = gcd(fenzi, fenmu);
    // 将分子分母化为最简
    if (init_gcd != 0) {
        fenzi = fenzi / init_gcd;
        fenmu = fenmu / init_gcd;
    }
}

// 最大公约数
uint_t Fract::gcd(uint_t m, uint_t n) const
{
    uint_t k = m < n ? m : n;
    for (; k > 0; --k) {
        if (m % k == 0 && n % k == 0) {
            break;
        }
    }
    return k;
}

// 最小公倍数: 两数相乘后除以最大公约数
uint_t Fract::lcm(uint_t m, uint_t n) const
{
    return m * n / gcd(m, n);
}

// 分数加法
void Fract::add(const Fract& x)
{
    uint_t init_lcm = lcm(this->fenmu, x.fenmu);

    int temp_fenzi;
    // 如果x符号为-,则分子相减
    if (x.sign == '+') {
        temp_fenzi = this->fenzi * init_lcm / this->fenmu + x.fenzi * init_lcm / x.fenmu;
    } else {
        temp_fenzi = this->fenzi * init_lcm / this->fenmu - x.fenzi * init_lcm / x.fenmu;
    }

    if (temp_fenzi < 0) {
        // 结果为-,则修改符号为-
        this->fenzi = temp_fenzi * -1;
        this->sign = '-';
    } else {
        this->fenzi = temp_fenzi;
        this->sign = '+';
    }
    
    this->fenmu = init_lcm;
    
    // 将分子分母化为最简
    uint_t init_gcd = gcd(fenzi, fenmu);
    if (init_gcd != 0) {
        fenzi = fenzi / init_gcd;
        fenmu = fenmu / init_gcd;
    }
}

// 分数减法
void Fract::sub(const Fract& x)
{
    char s = x.sign == '+' ? '-' : '+'; // 获取x的相反符号
    Fract y(x.fenzi, x.fenmu, s);
    this->add(y);
}

// 运算符+重载
Fract Fract::operator+(const Fract& x) const
{
    Fract z(this->fenzi, this->fenmu, this->sign);
    z.add(x);
    return z;
}

// 运算符-重载
Fract Fract::operator-(const Fract& x) const
{
    Fract z(this->fenzi, this->fenmu, this->sign);
    z.sub(x);
    return z;
}

// 分数显示
void Fract::show() const
{
    char s = this->sign == '+' ? ' ':'-';
    if (fenzi % fenmu == 0) {
        std::cout << s << fenzi / fenmu << std::endl;
    } else {
        std::cout << s << this->fenzi << '/' << this->fenmu << std::endl;
    }
}



#endif


/*
// 测试
#include "Fract.hpp"
#include <iostream>

using namespace std;

int main()
{
    Fract a(1, 5), b(7, 8, '-');
    a.show();
    b.show();
    // 分数加法
    Fract c = a + b;
    c.show();
    // 分数减法
    c = a - b;
    c.show();
    return 0;
}
 */
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力攀爬的小白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值