MFC實現一元稀疏多項式運算器
阿新 • • 發佈:2018-11-17
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&¤t->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);