什么样的Rational类实现算是优雅?
在我看来它应该符合以下几个特点
1.符合面向对象的封装特性,数据隐藏(因为只有一个类,没有考虑封装和多态)。
2.声明与实现相分离,接口清晰,自然,既有足够的基本功能又不冗余。
3.代码简洁清晰
4.最好不加注释就能看懂,变量名,方法名能够见名知义
5.do not repeat yourself,不要做重复的工作
6.出错时抛出异常,中止程序,而不是将错误掩盖在内部实现之中,埋下隐患。
下面的这个Rational实现我认为是比较优雅的,它符合上面的5个特点
1.public ,private展示了其数据隐藏特点,分子,分母类的使用者不可访问
2.提供了加减乘除相反数倒数相等的基本操作,而且重载了+,-,*,/操作符,使用时可以更加清晰自然
3.每个方法的实现 本身就不复杂,gcd函数的实现更是非常简洁
4.方法名,分子分母基本能够见名知义
5.减法用加上相反数来实现,除法用乘以倒数来实现,能够体现这一点
6.分母为零时,分子为零求倒数时抛出异常
#ifndef Rational_
#define Rational_
#include "myException.h"
#include<iostream>
using namespace std;
class Rational{
public:
Rational(int x, int y);//传入分子分母构造分数
Rational(string s);//从字符串构造分数
Rational nega();//相反数
Rational reci();//倒数
bool isEqual(Rational that);
Rational add(Rational that);//加法
Rational sub(Rational that);//减法
Rational mul(Rational that);//乘法
Rational div(Rational that);//除法
void Output(ostream &out)const;//输出方法
int getNumer(){return numer;}
int getDenom(){return denom;}
private:
int numer;//分子
int denom;//分母
int gcd(int a, int b) const { return (b==0) ? a : gcd(b, a % b); }//最大公约数
};
#endif // Rational_define
#include "rational.h"
#include "myException.h"
#include<cstdlib>
using namespace std;
Rational::Rational(int x, int y){//传入分子分母构造分数
if(y==0) throw new illegalDenominatorValue();
numer = x;
denom = y;
}
//从字符串构造分数
Rational::Rational(string s){
int pos = s.find('/',0);
if(pos <= 0 || pos >= s.length()-1) throw new illegalInputExpression();
numer = atoi( s.substr(0,pos).c_str() );
denom = atoi( s.substr(pos+1,s.length()-pos-1).c_str() );
if(denom == 0 ) throw new illegalDenominatorValue();
}
//相反数
Rational Rational::nega(){
return Rational(-numer, denom);
}
//倒数
Rational Rational::reci(){
if(numer == 0) throw new NoReciprocal();
return Rational(denom,numer);
}
//相等
bool Rational::isEqual(Rational that){
return numer * that.denom == denom * that.numer;
}
//加法
Rational Rational::add(Rational that){
return Rational(numer * that.denom + denom * that.numer,denom * that.denom);
}
//减法
Rational Rational::sub(Rational that){
return add(that.nega());
}
//乘法
Rational Rational::mul(Rational that){
return Rational(numer * that.numer, denom * that.denom);
}
//除法
Rational Rational::div(Rational that){
return mul(that.reci());
}
//输出
void Rational::Output(ostream &out)const{
int c = gcd(numer,denom);
// int c = 1;
out<<numer/c<<"/"<<denom/c;
}
//输出操作符重载
ostream& operator<<(ostream& out, const Rational& r){
r.Output(out);
return out;
}
//操作符重载
Rational operator +(Rational a, Rational b){
return a.add(b);
}
Rational operator -(Rational a, Rational b){
return a.sub(b);
}
Rational operator *(Rational a, Rational b){
return a.mul(b);
}
Rational operator /(Rational a, Rational b){
return a.div(b);
}
myException.h
// exception classes for various error types
#ifndef myExceptions_
#define myExceptions_
#include <string>
#include<iostream>
using namespace std;
// illegal Denominator value
class illegalDenominatorValue
{
public:
illegalDenominatorValue(string theMessage = "Denominator must be nonezero!"){
message = theMessage;
}
void outputMessage() {cout << message << endl;}
private:
string message;
};
// illegal input Expression
class illegalInputExpression
{
public:
illegalInputExpression(string theMessage = "Illegal input Expression"){
message = theMessage;
}
void outputMessage() {cout << message << endl;}
private:
string message;
};
//倒数
class NoReciprocal
{
public:
NoReciprocal(string theMessage = "No Reciprocal with numerator=0"){
message = theMessage;
}
void outputMessage() {cout << message << endl;}
private:
string message;
};
#endif
test.cpp
#include "rational.h"
#include "Rational.cpp"
using namespace std;
int main(){
Rational a(1,2);
Rational b("1/4");
//Rational c("1/0");
//Rational c("1/");
cout<<"a = \t"<< a <<endl;
cout<<"b = \t"<< b <<endl;
cout<<"-a = \t"<< a.nega()<<endl;
cout<<"1/b =\t"<< b.reci()<<endl;
cout<<"a.add(b) =\t"<< a.add(b)<<endl;
cout<<"a.sub(b) =\t"<< a.sub(b)<<endl;
cout<<"a.mul(b) =\t"<< a.mul(b)<<endl;
cout<<"a.div(b) =\t"<< a.div(b)<<endl;
cout<<"a+b =\t"<< a+b<<endl;
cout<<"a-b =\t"<< a-b<<endl;
cout<<"a*b =\t"<< a*b<<endl;
cout<<"a/c =\t"<< a/b<<endl;
return 0;
}
作为一个例子,我们来看如何使用这个类解决“求解形如a/b x+ c/d = e/f的一元一次分式方程”的问题
#include "rational.h"
#include "Rational.cpp"
using namespace std;
int main(){
while(1){
cout << "输入方程:形如a/b x + d/c = f/e"<<endl;
char Arr[50];
cin.getline(Arr, 50);
string equation(Arr);
// cout << equation <<endl;
// a/b x + d/c = f/e
int pos_x = equation.find('x',0);
int pos_p = equation.find('+',0);
int pos_e = equation.find('=',0);
Rational coe( equation.substr(0,pos_x) );// a/b
Rational b( equation.substr(pos_p+1,pos_e - pos_p) );// d/c
Rational c( equation.substr(pos_e+1,equation.length()-pos_e) );// f/e
// cout<<"coe = "<<coe<<endl;
// cout<<"b = "<<b<<endl;
// cout<<"c = "<<c<<endl;
if(coe.getNumer() == 0 && b.isEqual(c)) cout<<"x ∈ Q"<<endl;
else if(coe.getNumer() == 0 && !b.isEqual(c)) cout<<"无解"<<endl;
else cout<<"解得 x = "<<(c-b)/coe<<endl<<endl;
system("pause");
system("cls");
}
}代码如下
main.cpp
#include "rational.h"
#include "Rational.cpp"
using namespace std;
int main(){
while(1){
cout << "输入方程:形如a/b x + d/c = f/e"<<endl;
char Arr[50];
cin.getline(Arr, 50);
string equation(Arr);
// cout << equation <<endl;
// a/b x + d/c = f/e
int pos_x = equation.find('x',0);
int pos_p = equation.find('+',0);
int pos_e = equation.find('=',0);
Rational coe( equation.substr(0,pos_x) );// a/b
Rational b( equation.substr(pos_p+1,pos_e - pos_p) );// d/c
Rational c( equation.substr(pos_e+1,equation.length()-pos_e) );// f/e
// cout<<"coe = "<<coe<<endl;
// cout<<"b = "<<b<<endl;
// cout<<"c = "<<c<<endl;
if(coe.getNumer() == 0 && b.isEqual(c)) cout<<"x ∈ Q"<<endl;
else if(coe.getNumer() == 0 && !b.isEqual(c)) cout<<"无解"<<endl;
else cout<<"解得 x = "<<(c-b)/coe<<endl<<endl;
system("pause");
system("cls");
}
}版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/giantpoplar/article/details/47374179