这次本来是老师布置的一个作业,老师提前把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;
}