1. 程式人生 > >一個簡單的C++實現有理數類的例子

一個簡單的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;
}