1. 程式人生 > >MFC實現一元稀疏多項式運算器

MFC實現一元稀疏多項式運算器

MFC實現一元稀疏多項式運算器

基本要求

  • 輸入並建立兩個多項式
  • 多項式a與b相加,建立和多項式c
  • 多項式a與b相減,建立差多項式d
  • 輸出多項式a, b, c, d。輸出格式:比如多項式a為:A(x)=c1xe1+ c2xe2+…+ cmxem,其中,ci和ei分別為第i項的係數和指數,且各項按指數的升冪排列,即0≤e1<e2<…<em

    首先看一下我介面,較為粗糙,實現計算器介面(個人感覺手動輸入更為方便,但實習的拓展要求是計算器的模擬介面Orz)

    這個可以自己新增一個頭檔案,用於多項式的類定義,下面的過載>> <<屬於多餘的,如果單純C++控制檯程式的可以應用。

#include<algorithm>
#include<iostream>
using namespace std;
typedef long long ll;
struct Term
{
    double coef;//係數
    int exp;//指數
    Term* link;
    Term(double c, int e, Term* next = NULL)
    {
        coef = c; exp = e; link = next;
    }
    Term*InsertAfter(double c, int e);
    friend ostream& operator <<(ostream&, const Term&);
};
class Polynomial//多項式類定義
{

public:
    Term * first;
    friend ostream&operator<<(ostream&, const Polynomial&);
    friend istream&operator>>(istream&, Polynomial&);
    friend  Polynomial operator+(Polynomial&, Polynomial&);
    friend  Polynomial operator-(Polynomial&, Polynomial&);
    Polynomial() { first = new Term(0, -1); }//建構函式,建立空連結串列
    Polynomial(Polynomial&R);//複製建構函式
    int maxOrder();//計算最大階數
    Term*getHead()const { return first; };//取得單鏈表的頭指標
                                          //~Polynomial();


};

Term* Term::InsertAfter(double c, int e)
{
    //當前有this指標指示的項後面加一項
    link = new Term(c, e, link);
    return link;
}
ostream& operator<<(ostream& out, const Term&x)
{
    if (x.coef == 0.0)return out;
    out << x.coef;
    switch (x.exp)
    {
    case 0:break;
    case 1:out << "X"; break;
    default:out << "X" << x.exp;
        break;
    }
    return out;
}
Polynomial::Polynomial(Polynomial&R)
{
    //複製建構函式
    first = new Term(0, -1);
    Term *destptrr = first, *srcptr = R.getHead()->link;
    while (srcptr != NULL)
    {
        destptrr->InsertAfter(srcptr->coef, srcptr->exp);
        srcptr = srcptr->link;
        destptrr = destptrr->link;
    }
}
int Polynomial::maxOrder()
{
    //升序排序計算最大階數,即為最後一項
    Term*current = first;
    while (current->link != NULL)
    {
        current = current->link;
    }
    return current->exp;
}
istream& operator>>(istream&in, Polynomial& x)
{
    //輸入,尾插法建立多項式
    Term* rear = x.getHead(); double c; int e;
    while (true)
    {
        cout << "input a term(c,exp)" << endl;
        in >> c >> e;
        if (e < 0)break;
        rear = rear->InsertAfter(c, e);
    }
    return in;
}
ostream& operator<<(ostream &out, Polynomial&x) {
    Term*current = x.getHead()->link;//頭指標為空,不輸出
    cout << "多項式:" << endl;
    bool h = true;
    while (current != NULL)
    {
        if (h == false && current->coef > 0)out << "+";
        h = false;
        out << *current;
        current = current->link;
    }
    out << endl;
    return out;
}
Polynomial operator+(Polynomial&A, Polynomial&B)
{
    Term*pa, *pb, *pc, *p; double temp;
    Polynomial C; pc = C.first;
    pa = A.getHead()->link; pb = B.getHead()->link;
    while (pa != NULL && pb != NULL)
    {
        if (pa->exp == pb->exp)
        {
            temp = pa->coef + pb->coef;
            if (fabs(temp) > 0.0001)
                pc = pc->InsertAfter(temp, pa->exp);
            pa = pa->link; pb = pb->link;
        }
        else if (pa->exp < pb->exp) {
            pc = pc->InsertAfter(pa->coef, pa->exp);
            pa = pa->link;
        }
        else {
            pc = pc->InsertAfter(pb->coef, pb->exp);
            pb = pb->link;
        }
    }
    if (pa != NULL)p = pa;
    else p = pb;
    while (p != NULL)
    {
        pc = pc->InsertAfter(p->coef, p->exp);
        p = p->link;
    }
    return C;
}
Polynomial operator-(Polynomial&A, Polynomial&B)
{
    Term*pa, *pb, *pc, *p; double temp;
    Polynomial C; pc = C.first;
    pa = A.getHead()->link; pb = B.getHead()->link;
    while (pa != NULL && pb != NULL)
    {
        if (pa->exp == pb->exp)
        {
            temp = pa->coef-pb->coef;
            if (fabs(temp) > 0.0001)
                pc = pc->InsertAfter(temp, pa->exp);
            pa = pa->link; pb = pb->link;
        }
        else if (pa->exp < pb->exp) {
            pc = pc->InsertAfter(pa->coef, pa->exp);
            pa = pa->link;
        }
        else {
            pc = pc->InsertAfter(pb->coef*(-1), pb->exp);
            pb = pb->link;
        }
    }
    bool flag = true;
    if (pa != NULL)p = pa;
    else {
        p = pb; flag = false;
    }
    while (p != NULL)
    {
        if(flag)
        pc = pc->InsertAfter(p->coef, p->exp);
        else    pc = pc->InsertAfter(p->coef*(-1), p->exp);
        p = p->link;
    }
    return C;
}
Polynomial x, y;

接下來實現計算器按鈕的實現,下面是按鈕1的相關程式碼,其他按鈕類似

void CPolynomialDlg::OnBnClickedButton1()
{
    UpdateData(true);//寫入
    CString str;
    mEdit.GetWindowTextW(str);//得到編輯框的文字
    str = str + _T("1");//CString後面加1
    mEdit.SetWindowTextW(str);//編輯框顯示更新內容
    UpdateData(false);
    // TODO: 在此新增控制元件通知處理程式程式碼
}

接下來是切換多項式的程式碼,並且讀入一個多項式。處理思路是一次讀入係數和指數,採取後插法實現單鏈表的建立。這裡用到CString到double和int的轉化,需要注意的是,轉double會出現一些後導0,影響美觀,需要去掉。我處理的麻煩了點,在大佬那知道了這個函式CString.Delete(CString.Getlength()-1,1),就懶得改了。


void CPolynomialDlg::OnBnClickedButtonnext()
{
    CString str;
    CString temp, temp1, temp2, temp3;
    mEdit.GetWindowTextW(str);
    double c = 0; int e = 0;
    int j;  int i;
    Term* rear;
//flag是標記,作為區分第一個和第二個多項式
    if (flag) rear = y.getHead();
    else rear = x.getHead();
    for (j = 0; j < str.GetLength(); j++)
    {
        temp = temp1 = temp2 = temp3 = "";
        if (str[j] == ' ')continue;
        c = 0; e = 0;
        while (str[j] != ' '&&j < str.GetLength()) { temp += str[j]; j++; }
        for (i = 0; i < temp.GetLength(); i++)
        {
            if (temp[i] != '.')temp1 += temp[i];
            else break;
        }
        c += _ttof(temp1);//CString轉double
        i++;
        for (i; i < temp.GetLength(); i++)
            temp2 += temp[i];
        if(c<0)
        c -= _ttof(temp2) / pow(10, temp2.GetLength());
        else c += _ttof(temp2) / pow(10, temp2.GetLength());
         while(str[j]==' ')j++;
        while (str[j] != ' '&&j < str.GetLength()) { temp3 += str[j]; j++; }
        e = _ttoi(temp3);
        //輸入,尾插法建立多項式
        rear = rear->InsertAfter(c, e);
    }
    if(!flag)
    AfxMessageBox(_T("第一個表示式建立完畢!"));
    else AfxMessageBox(_T("第二個表示式建立完畢!"));
    mEdit.SetWindowTextW(_T(""));
    flag = !flag;
    // TODO: 在此新增控制元件通知處理程式程式碼
}

關鍵就是計算函數了,也就是確定按鈕,這裡用到了下拉框選擇操作,用index判斷即可。最後作為CString輸出也有點格式優化,大家可以看一下。

void CPolynomialDlg::OnBnClickedOk()
{
    // TODO: 在此新增控制元件通知處理程式程式碼
    //CDialogEx::OnOK();
    CString temp;
    int index = combox.GetCurSel();
    //combox.GetLBText(index, temp);
    CString str;
    
        Polynomial C;
        if (index == 0)
        C = x + y;
        else 
            C = x-y;
        Term*current = C.getHead()->link;//頭指標為空,不輸出
    //  cout << "多項式:" << endl;
        bool h = true;
        while (current != NULL)
        {
            if (h == false && current->coef > 0)str+='+';
            h = false;
            //str+= *current;
            if (current->coef == 0.0)
                continue;
            CString strr, str0;
            if (current->coef == 1.0&&current->exp!=0);
            else
            {
                
                strr.Format(_T("%3f"), current->coef);
                int len = strr.GetLength();
                int i;
                for (i = len - 1; i >= 0; i--)
                {
               //小數點的處理
                    if (strr[i] == '0' || strr[i] == '.');
                    else break;
                }
                for (int j = 0; j <= i; j++)
                    str += strr[j];
            }
            switch (current->exp)//係數輸出,0,1單獨處理
            {
            case 0:break;
            case 1:str+="X"; break;
            default: {str += "X"; strr.Format(_T("%d"), current->exp); str += strr; }
                break;
            }
            current = current->link;
        }
        n_Edit.SetWindowTextW(str);
        
    
}

最後的就是釋放空間的按鈕,以便實現多次運算,這裡偷了個懶,一個小程式,就沒有delete了,最好還是順著單鏈表delete。

    // CDialogEx::OnCancel();
    n_Edit.SetWindowTextW(_T(""));//編輯框的清空
      x.first = new Term(0, -1);
      y.first = new Term(0, -1);

歡迎大家糾正錯誤