• 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++控制台程序的可以应用,MFC工程可以直接忽略)。

    #include<algorithm>
    #include<iostream>
    using namespace std;
    typedef long long ll;
    bool flag = 0;
    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, -10000000); }//构造函数,建立空链表
    	Polynomial(Polynomial&R);//复制构造函数
    	int maxOrder();//计算最大阶数
    	Term* find_place(int e);
    	bool inser_order(double c, int e);
    	Term*getHead()const { return first; };//取得单链表的头指针
    										  //~Polynomial();
    
    };
    
    Polynomial x, y;
    Term* Term::InsertAfter(double c, int e)
    {
    
    	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;
    }
    //寻找需要插入的位置,由inser_order(double c, int e)调用
    Term* Polynomial::find_place(int e)
    {
    	Term* current = first;
    	while (current->link!=NULL&&current->link->exp<e)
    	{
    		current = current->link;
    	}
    	return current;
    }
    //插入,保持递增单链表
    bool Polynomial::inser_order(double c, int e)
    {
    	Term*current = find_place(e);
    	Term*temp=NULL;
    //if (current == NULL) { AfxMessageBox(_T("插入出错!")); return false; }
    	Term* newnode= new Term(c, e, temp);
    	if (newnode == NULL) { AfxMessageBox(_T("插入出错!")); return false; }
    	newnode->link = current->link;
    	current->link = newnode;
    	return true;
    }
    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;
    }
    
    

    接下来实现计算器按钮的实现,下面是按钮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;
    	//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);
    		//输入,尾插法建立多项式
    	//	if (flag)
    	//rear = rear->InsertAfter(c, e);
    		if (!flag)x.inser_order(c, e);
    		else y.inser_order(c, e);
    		//	rear->InsertAfter(c, e, y.first);
    	//	else rear = rear->InsertAfter(c, e,x.first);
    		//  else rear->InsertAfter(c, e, x.first);
    	}
    	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);
    

    欢迎大家纠正错误,完整代码见GitHub链接,主要是了解MFC框架即可。

    不疯魔不成活
  • 相关阅读:
    初步学习pg_control文件之四
    初步学习pg_control文件之三
    初步学习pg_control文件之二
    初步认识pg_control文件之一
    Slony-I的 RemoteWorker重试调查
    对Slony-I中wait on的理解
    超高逼格Log日志打印
    实现列表二级展开/收起/选择
    贝塞尔曲线实现购物车飞入效果
    乐鑫esp8266的 基于Nonos移植红外线1883,实现遥控器控制
  • 原文地址:https://www.cnblogs.com/gzr2018/p/9972883.html
Copyright © 2020-2023  润新知