Math++ 开发(2) - 分数类的编写

Math++ 开发(2) - 分数类的编写

知识点

class的使用
c++重载操作符:operator
this指针
qc的基本使用
.ui文件
默认参数的使用

今天的源码

fraction.cpp

#include "fraction.h"

Fraction::Fraction(int a, int b)
{
    if (b == 0)
    {
        return;
    }
    this->a = a;
    this->b = b;
}

Fraction Fraction::operator+(Fraction ot)
{
    int _up, _down;
    _down = this->b * ot.b;
    _up = this->a * ot.b + ot.a * this-> b;
    int cand = this->measure(_up, _down);
    return Fraction(_up / cand, _down / cand);
}

Fraction Fraction::operator-(Fraction ot)
{
    int _up, _down;
    _down = this->b * ot.b;
    _up = this->a * ot.b - ot.a * this-> b;
    int cand = this->measure(_up, _down);
    return Fraction(_up / cand, _down / cand);
}

Fraction Fraction::operator*(Fraction ot)
{
    int _up, _down;
    _up = this->a * ot.a;
    _down = this->b * ot.b;
    int cand = this->measure(_up, _down);
    return Fraction(_up / cand, _down / cand);
}

Fraction Fraction::operator/(Fraction ot)
{
    int _up, _down;
    _up = this->a * ot.b;
    _down = this->b * ot.a;
    int cand = this->measure(_up, _down);
    return Fraction(_up / cand, _down / cand);
}

int Fraction::measure(int x, int y)
{
    int z = y;
    while(x%y!=0)
    {
        z = x%y;
        x = y;
        y = z;
    }
    return z;
}

void Fraction::view(void)
{
    qDebug() << this->a << "/" << this->b << endl;
}

void Fraction::setA(int inp)
{
    this->a = inp;
}

void Fraction::setB(int inp)
{
    this->b = inp;
}

fraction.h

#ifndef FRACTION_H
#define FRACTION_H

#include <QDebug>

class Fraction
{
public:
    Fraction(int a=0, int b=1);
    Fraction operator+(Fraction ot);
    Fraction operator-(Fraction ot);
    Fraction operator*(Fraction ot);
    Fraction operator/(Fraction ot);
    void view(void);
    void setA(int inp);
    void setB(int inp);
    int a, b;
private:
    int measure(int x, int y);
};

#endif // FRACTION_H

过程详解

创建工程

qc - 文件 - 新建(ctrl+n)
弹出新建对话框
Math++ 开发(2) - 分数类的编写
这不有手就行
Math++ 开发(2) - 分数类的编写
这个qmake别去改它,
Math++ 开发(2) - 分数类的编写
Math++ 开发(2) - 分数类的编写
解释一下:class name是程序主类,暂且就叫MainWindow吧.
Base class:顾名思义,基类,也就是MainWindow要继承的类.
Header file:这个类的头文件
Source file:源文件
**最下面是重点:**那个复选框勾上.表示"从界面文件创建界面",也就是下面的mainwindow.ui,下面会做解释.
ok,下一步.
Math++ 开发(2) - 分数类的编写
这个不管他.
Math++ 开发(2) - 分数类的编写
这个建议都勾上,运行套件,编译用的.

最后,那个版本控制系统,加不加无所谓,最好加,我就用git,没毛病.

.ui文件解释

这玩意只能用qc解释,xml文档格式,用于储存"form",也就是所谓的"界面样式"
由于咱还是新手,不会纯代码编程,暂时用这个可视化的练练手吧…

(插个题外话,不是我瞎说,真的,用ui比纯代码快好多,特别是这种基本静态的界面)

主体编写

创建完后长这样:(因为是写完后才写的文章,所以嘛…)
Math++ 开发(2) - 分数类的编写
右键项目名称,(在文件栏里),add new…
Math++ 开发(2) - 分数类的编写
填一个类名:Fraction(分数)
多了两个文件:fraction.h和fraction.cpp(分别在HeadersSources里).
Math++ 开发(2) - 分数类的编写
我们先复习一下:C++中,头文件中放声明,源文件中放实现,所以,在fraction.cpp中编写了成员函数等之后,一定要在fraction.h中声明.

首先,因为要在类外访问,所以存放分母(a),分子(b)的变量应放在public中.

int a, b;

类构造函数:Fraction::Fraction(int a=0, int b=0);

Fraction::Fraction(int a, int b)
{
    if (b == 0)
    {
        return;
    }
    this->a = a;
    this->b = b;
}

这里注意:数学中,分母不为零,所以b==0时直接返回.
接下来两行:分别将传入参数放进定义好的整型变量中.

而在头文件中,我们则这样声明:

Fraction(int a=0, int b=1);

注意到了吗?我们只在头文件成员函数定义中给出了默认值,而源文件中则不用,也不能,不然会报:Math++ 开发(2) - 分数类的编写
重定义默认参数.

为了方便查看分数的状态,我们给出Fraction::view(void)

void Fraction::view(void)
{
    qDebug() << this->a << "/" << this->b;
}

QDebug是qt用于输出调试信息的,所以要包含头文件:

#include <QDebug>

要输出,则用插入操作符<<传给qDebug()

再定义两个设置函数

void Fraction::setA(int inp)
{
    this->a = inp;
}

void Fraction::setB(int inp)
{
    this->b = inp;
}

我们来测试一下.

//main.cpp
#include "mainwindow.h"
#include "fraction.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    //w.show();
    Fraction f1(12, 24);
    f1.view();
    Fraction f2(13, 43);
    f2.view();
    return a.exec();
}

ctrl+r运行,然后手动kill进程"mathplusplus.exe"得到如下:
Math++ 开发(2) - 分数类的编写
接下来;编写操作符重载.先来个简单点的,乘和除.(乘->上乘上,下乘下, 除->上乘下作上)

Fraction Fraction::operator*(Fraction ot)
{
    int _up, _down;
    _up = this->a * ot.a;
    _down = this->b * ot.b;
    int cand = this->measure(_up, _down);
    return Fraction(_up / cand, _down / cand);
}

Fraction Fraction::operator/(Fraction ot)
{
    int _up, _down;
    _up = this->a * ot.b;
    _down = this->b * ot.a;
    int cand = this->measure(_up, _down);
    return Fraction(_up / cand, _down / cand);
}

大概了解原理后,可以写出+和-:

Fraction Fraction::operator+(Fraction ot)
{
    int _up, _down;
    _down = this->b * ot.b;
    _up = this->a * ot.b + ot.a * this-> b;
    int cand = this->measure(_up, _down);
    return Fraction(_up / cand, _down / cand);
}

Fraction Fraction::operator-(Fraction ot)
{
    int _up, _down;
    _down = this->b * ot.b;
    _up = this->a * ot.b - ot.a * this-> b;
    int cand = this->measure(_up, _down);
    return Fraction(_up / cand, _down / cand);
}

测试一下:

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    //w.show();
    Fraction f1(1, 4);
    f1.view();
    Fraction f2(1, 3);
    f2.view();
    (f1 * f2).view();
    (f1 / f2).view();
    (f1 + f2).view();
    (f1 - f2).view();
    //return a.exec();
    return 0;
}
20:36:10: Starting D:\Program Files\Projects\build-mathplusplus-Desktop_Qt_5_9_9_MinGW_32bit-Debug\debug\mathplusplus.exe ...
1 / 4
1 / 3
1 / 12
3 / 4
7 / 12
1 / -12
20:36:10: D:\Program Files\Projects\build-mathplusplus-Desktop_Qt_5_9_9_MinGW_32bit-Debug\debug\mathplusplus.exe exited with code 0

差点忘了,还有一个重要的成员函数measure,最小公约数,用于约分.

int Fraction::measure(int x, int y)
{
    int z = y;
    while(x%y!=0)
    {
        z = x%y;
        x = y;
        y = z;
    }
    return z;
}

总结

今天我们编写了分数 类,为什么?

数学是严谨的,容不得半点马虎.

c++提供的double,float,都有精确度的问题,而且数学中的分数大多转换成小数无限循环,多次计算,然后取近似数,久而久之,精确度就像照相机"一米之外人畜不分",这显然不是我们想要的,所以就有了这个类.

项目是久而久之累积起来的,每一个组件,模块都要精心设计,精心编写.当我们认真对待每一句代码时,学习效果,作品,总能回报付出!

上一篇:1287. Element Appearing More Than 25% In Sorted Array


下一篇:求众数-摩尔投票法