一个简单的C++实现有理数类的例子

这次本来是老师布置的一个作业,老师提前把main.cpp给了我们,要求我们在头文件中定义并且实现一个有理数类,使得运行程序后输出的结果跟他给的一样。
main.cpp如下:

#include <stdio.h>
#include "Rational.h"
int main()
{
    Rational num1(1, 3), num2(3, 1), num3(2, 6);
    Rational result;
    result = num1 + num2;
    printf("%s + %s = %s\n", num1.value(), num2.value(), result.value());
    result = num1 * num2;
    printf("%s * %s = %s\n", num1.value(), num2.value(), result.value());
    printf("%s is%s equal to %s\n", num1.value(), (num1 == num2) ? " " : " not", num2.value());
    printf("%s is%s equal to %s\n", num1.value(), (num1 == num3) ? " " : " not", num3.value());
    system("pause");
    return 0;
}

分析可知需要定义两个构造函数,一个默认的构造函数,一个是带两个int类型参数的构造函数,并且还要重载三个操作符,分别是" + "," * "," == "。在实现的过程中最麻烦应该是value这个方法了,下面等会儿再说。
我们先来看main.cpp的代码。
Rational num1(1, 3), num2(3, 1), num3(2, 6);
Rational result;
第一行属于隐式的调用构造函数,第二行调用了默认构造函数(调用默认构造函数就只有这一种写法),还有一种显示的调用构造函数的方法,对于上面的代码可改写为:
Rational num1 = Rational(1,3), num2 = Rational(3,1), num3 = Rational(2,6);
Rational result;
继续往下看。对于printf函数,这儿涉及到一个知识点,如下图所示

所以我们在编写头文件中的value函数时需要明白该函数的返回值类型为char类型,注意!!!既不是string类型,也不是char类型。
在实现这个有理数类的时候,我们需要认识到两个点,其一需要实现化简操作,其二需要注意分母为负数时应该把负号传给分子(至于分母不能为0这个情况,在代码中操作对分母进行操作时加以限制即可)。我将这两个需要注意的问题都写到了narmalize()函数中,对于化简操作,先使用欧几里得算法求出最大公约数,然后分子分母同时除以它即可。
操作符重载后里面的实现方法没什么可说的,都是数学问题。
至于value函数,想让它返回值为char
类型比较麻烦。首先,一个分式由分子," / " ,分母这三部分组成,其中分子分母是整型," / "是一个运算符,最先想到的方法是使用C++的to_string()方法把分子跟分母转成字符串,然后直接使用" + "号将三个字符串连接起来,这样就可以使得整个分式变成一个字符串了。下面应该考虑将string类型转成char类型,在网上搜索后发现有两种方法:
data()和c_str(),然而把代码写好以后还没运行vs就报错,说返回值类型与函数类型不一致,仔细一看,原来使用上面两种方法的返回值都是const char
类型,const char跟char类型可是大大的不同啊,const限制了变量不可更改,所以又得进行一次const char到char的转换,只需新建一个字符指针数组,然后把const char*的内容拷贝即可,下面就是实现的代码。
对了,在运行时报了一个说strcpy是一个不安全的函数这个的错误,经过查询明白了,新版本的vs认为strcpy、scanf等函数不安全,建议使用strcpy_s()这个新函数,其用法跟原来的函数相差不大。还有一种解决该报错的方法,鼠标先选中"解决方案资源管理器"中的项目名,然后按照下面的步骤设置:
项目 ->属性 -> c/c++ -> 预处理器 -> 点击预处理器定义,编辑,加入_CRT_SECURE_NO_WARNINGS,即可。

下面是头文件的代码

#include<math.h>
#include<iostream>
#include<string>

class Rational
{
public:
    Rational();//默认构造函数
    Rational(int num, int denom);//自定义构造函数
    ~Rational();//析构函数
    Rational operator+(Rational rhs);//操作符重载
    Rational operator-(Rational rhs);
    Rational operator*(Rational rhs);
    int operator==(Rational rhs);
    char* value();

private:
    int numerator;//分子
    int denominator;//分母
    void normalize();//化简

};

Rational::Rational()
{
}

Rational::Rational(int num, int denom)
{
    numerator = num;
    denominator = denom;
    normalize();
}

Rational::~Rational()
{
}

void Rational::normalize()
{
    if (denominator < 0)
    {
        numerator = -numerator;
        denominator = -denominator;
    }
    //求出分子和分母的最大公约数,用欧几里得算法
    int a = abs(numerator);
    int b = abs(denominator);
    while (b>0)
    {
        int t = a%b;
        a = b;
        b = t;
    }
    numerator /= a;
    denominator /= a;
}

Rational Rational::operator+(Rational rhs)
{
    int a = numerator;
    int b = denominator;
    int c = rhs.numerator;
    int d = rhs.denominator;
    int e = a*d+ b*c;
    int f = b*d;
    return Rational(e, f);
}

Rational Rational::operator-(Rational rhs)
{
    rhs.numerator = -rhs.numerator;
    return operator+(rhs);
}

Rational Rational::operator*(Rational rhs)
{
    int a = numerator;
    int b = denominator;
    int c = rhs.numerator;
    int d = rhs.denominator;
    int e = a*c;
    int f = b*d;
    return Rational(e, f);
}

int Rational::operator==(Rational rhs)
{
    int a = numerator;
    int b = denominator;
    int c = rhs.numerator;
    int d = rhs.denominator;
    if (a / b == c / d) {
        return 1;
    }
    else
    {
        return 0;
    }
}

char* Rational::value() 
{
    std::string x;
    x = std::to_string(numerator)+ "/" + std::to_string(denominator);//转成string类型
        const char* p= x.c_str();//转成const char*类型
      char *m = new char[100];//转成char*类型
    strcpy_s(m, 101, p);//新版本的vs要求使用strcpy_s()函数
    return m;
}

猜你喜欢

转载自www.cnblogs.com/gabbywung/p/9954670.html