多项式类的设计与实现(MFC)

更新时间:2024-06-10 12:10:02 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

题目: 班级: 姓名: 学号: 日期:

课 程 设 计 任 务 书

学院 学生姓名 设计题目 内容及要求: 专业 学号 多项式类的设计与实现 开发多项式类Polynomial,多项式的每一项用链表的结点表示,每项包含一个系数和一个指数。例如:2x的指数为4,系数为2。请开发一个完整的Polynomial类,包括构造函数、析构函数以及“get”函数(读取值)和“set”函数(设置值)。该类还要提供以下重载的运算符: (1) 重载加法运算符+,将两个多项式相加。 (2) 重载加法运算符-,将两个多项式相减。 (3) 重载赋值运算符=,将一个多项式赋给另外一个多项式。 (4) 重载加法运算符*,将两个多项式相乘。 (5) 编写一个主函数测试多项式类的上述功能。 4进度安排: 第17周:分析题目,查阅课题相关资料,进行类设计、算法设计; 第18周:程序的设计、调试与实现; 第19周:程序测试与分析,撰写课程设计报告,进行答辩验收。 指导教师(签字): 年 月 日

学院院长(签字) 年 月 日

目 录

1 需求分析 ..................................................................................... - 1 - 2 算法基本原理 ............................................................................. - 1 - 3 类设计......................................................................................... - 2 - 4 详细设计 ..................................................................................... - 2 -

4.1 类的接口设计..................................................................................................- 2 - 4.2 类的实现..........................................................................................................- 3 - 4.3 主函数设计....................................................................................................- 12 -

5 DOS界面程序运行结果及分析 ................................................. - 14 -

5.1 程序运行结果................................................................................................- 14 - 5.2运行结果分析 ................................................................................................- 15 -

6 基于MFC的图形界面程序开发 ............................................... - 15 -

6.1 基于MFC的图形界面程序设计 .................................................................- 15 - 6.2 程序测试........................................................................................................- 27 - 6.3 MFC程序编写总结 .......................................................................................- 29 -

7 参考文献 ................................................................................... - 29 -

1 需求分析

(1) 开发多项式类Polynomial,多项式的每一项用链表的结点表示,每项包含一个系数和一个指数。例如:2x4的指数为4,系数为2。请开发一个完整的Polynomial类,包括构造函数、析构函数以及“get”函数(读取值)和“set”函数(设置值)。

(2)多项式的定义:n个单项式的代数和叫多项式。 (3)程序测试数据: P1:2x+3x^2+2x^4+3x^2 P2:3x^2+2x^3

(1)

2 算法基本原理

设有2个多项式p1,p2

P1:2x+3x^2+2x^4+3x^2 P2:3x^2+2x^3

实现多项式p1和p2的计算,关键是对p1和p2的指数和系数进行加减生的操作,我们可以先编辑一个基类Polynominal。通过链表和重载运算符的方法来实现。 (1)多项式即个个单项式的和,我们可以把一个多项式分解成一项一项来看,每一项用链表的一个节点表示,每个节点包括一个单项式的系数、指数和指向该节点类型的一个指针。

(2)用Polynominal创建对象p1、p2、p3,通过调用Create(c1,e1,size1)函数来构建多项式。

(3)通过重载+、-、*以及=运算符,对多项式进行操作。 (4)通过p1.Print()来显示结果。

- 1 -

3 类设计

从上面的算法分析可以看到,本设计面临的计算问题的关键是多项式运算。可以定义一个多项式类Polynominal。

(1)该类包括私有数据成员Node *head,Node是构造的节点类型的结构体,包括系数、指数和指向该节点类型的一个指针。

(2)成员函数包括Polynominal()//构造函数, Polynominal(const Polynominal &)//拷贝构造函数,~Polynominal()//析构函数Node* get(int e);//读取指数为e的项,返回其指针,void set(double c,int e);//设置指数为e的项的系数为c, void Create(double *c,int *e,int n);//创建多项式,friend Polynominal operator +(Polynominal a,Polynominal b);//重载+运算符,friend Polynominal operator -(Polynominal a,Polynominal b);//重载-运算符,friend Polynominal operator *(Polynominal a,Polynominal b);//重载*运算符,friend ostream& operator<<(ostream&

os,

const

Polynominal&

a);Polynominal&

operator

=(Polynominal a);//重载=运算符,void Print(ostream& os = cout) const;//显示函数 void Copy(const Polynominal &a)//复制函数

对以上进行总结,该程序只包含一个类即Polynomina,对多项式的所有操作都抽象在该类中。

4 详细设计

程序主要分为三个部分:类声明、类实现、主函数。

4.1 类的接口设计

//类的声明 class Polynominal { public:

Polynominal(){ head=0; }//构造函数

Polynominal(const Polynominal &);//拷贝构造函数 ~Polynominal() {

- 2 -

Node *q,*p; p=head;

while (p)//删除链表 {

q=p->next; if (p) delete p; p=q; }

head=NULL; }

Node* get(int e);//读取指数为e的项,返回其指针 void set(double c,int e);//设置指数为e的项的系数为c void Create(double *c,int *e,int n);//创建多项式

friend Polynominal operator +(Polynominal a,Polynominal b);//重载+运算符 friend Polynominal operator -(Polynominal a,Polynominal b);//重载-运算符 friend Polynominal operator *(Polynominal a,Polynominal b);//重载*运算符 friend ostream& operator<<(ostream& os, const Polynominal& a); Polynominal& operator =(Polynominal a);//重载=运算符 void Print(ostream& os = cout) const; void Copy(const Polynominal &a);

void Addr(){cout<<\链表头指针值为:\private:

Node *head;//链表头指针 };

在程序中,声明了个个运算符的重载,通过Node* get(int e);读取指数为e的项,返回其指针,通过void set(double c,int e)设置指数为e的项的系数为c,多项式的的系数、指数以及指针全部采用了动态内存分配技术,这些工作都是由构造函数和Create()函数完成,它们的清理工作在析构函数中完成。

4.2 类的实现

//类实现

#include #include

- 3 -

#include #define MAXSIZE 15 struct Node//链表结点 {

int exp;//指数 double coef;//系数 Node *next; };

void Polynominal::Copy(const Polynominal &a) { //复制对象(公用函数) Node *t,*s,*p; p=a.head;s=head=0; while(p) {

t=new Node; if (head==0) head=t; t->coef=p->coef; t->exp=p->exp; p=p->next; if(s) s->next=t; s=t; }

if (s) s->next=0; }

Polynominal::Polynominal(const Polynominal& a)//复制构造函数 { Copy(a); }

void Polynominal::Create(double *c,int *e,int n)//创建多项式 { if (n<1)

cout<<\错误:要创建多项式的项数必须大于零。\\n\ else {

- 4 -

head=new Node;//创建头结点 head->coef=c[0]; head->exp=e[0]; Node *q,*p=head; for (int i=1;i

q=new Node; q->coef=c[i]; q->exp=e[i]; p->next=q; p=q; } p->next=0; } }

Node* Polynominal::get(int e)//读取指数为e的项 {

Node *p=head; while (p) {

if (p->exp==e) return p; p=p->next; }

return p;//没有找到,返回空指针 }

void Polynominal::set(double c,int e)//将指数为e系数为c的项加入多项式(原多项式无指数为e的项)

{

Node *q,*p,*t; t=new Node; t->coef=c; t->exp=e; if (head==0) {

- 5 -

head=t; head->next=0; return; }

if (e>head->exp) {

t->next=head; head=t;//插入头部 return; } p=head;

while (p && eexp) { q=p; p=p->next; } if (p) {

//新的项插入p所指结点前 t->next=p; q->next=t; }

else//插入尾部 {

q->next=t; t->next=0; } }

Polynominal operator +(Polynominal a,Polynominal b)//重载+运算符 {

Polynominal temp; Node *p,*q,*s,*t; double x;

s=new Node;temp.head=s;//先增加一个头结点

- 6 -

p=a.head; q=b.head; while (p && q) {

if (p->exp==q->exp) {

x=p->coef+q->coef; if (x!=0.0) {

t=new Node; t->exp=p->exp; t->coef=x; s->next=t; s=t; } p=p->next; q=q->next; } else {

t=new Node; if(p->exp>q->exp) {

t->coef=p->coef; t->exp=p->exp; p=p->next; } else {

t->coef=q->coef; t->exp=q->exp; q=q->next; }

s->next=t;

- 7 -

s=t; } }

if (q) p=q;//p恒指向余下的项 while (p) {

t=new Node; t->coef=p->coef; t->exp=p->exp; s->next=t; s=t; p=p->next; }

s->next=0; //链表尾标记 s=temp.head; temp.head=s->next;

delete s; //删除多余的头结点 return temp; }

Polynominal operator -(Polynominal a,Polynominal b)//重载-运算符 {

Polynominal temp; Node *p,*q,*s=0,*t;

//在此处添加代码,完成此函数(模仿上述重载\的函数) double x;

s=new Node;temp.head=s;//先增加一个头结点 p=a.head; q=b.head; while (p && q) {

if (p->exp==q->exp) {

x=p->coef-q->coef; if (x!=0.0)

- 8 -

{

t=new Node; t->exp=p->exp; t->coef=x; s->next=t; s=t; } p=p->next; q=q->next; } else {

t=new Node; if(p->exp>q->exp) {

t->coef=p->coef; t->exp=p->exp; p=p->next; } else {

t->coef=-q->coef; t->exp=q->exp; q=q->next; }

s->next=t; s=t; } }

if (q) p=q;//p恒指向余下的项 while (p) {

t=new Node; t->coef=p->coef;

- 9 -

t->exp=p->exp; s->next=t; s=t; p=p->next; }

s->next=0; //链表尾标记 s=temp.head; temp.head=s->next;

delete s; //删除多余的头结点 return temp; }

Polynominal operator *(Polynominal a,Polynominal b)//重载*运算符 {

Polynominal temp; Node *p,*q,*s; int e;double c; p=a.head; while (p) {

q=b.head; while (q) {

c=p->coef*q->coef; e=p->exp+q->exp;

s=temp.get(e);//查temp中有无指数为e的项 if (s)//temp中无指数为e的项 s->coef+=c;

else//temp中无指数为e的项 temp.set(c,e); q=q->next; } p=p->next; }

return temp;

- 10 -

}

ostream& operator<<(ostream& os, const Polynominal& a) {

a.Print(os); return os; }

Polynominal& Polynominal::operator =(Polynominal a)//重载=运算符 {

Node *s,*p; if (head)

{ //若原多项式存在,先撤消它 p=head; while (p) {

s=p->next; delete p; p=s; } } Copy(a); return *this; }

void Polynominal::Print(ostream& os) const//显示多项式 {

Node* p;int e; if (head) {

e=head->exp;

os<<\ if (e>1) os<<\

- 11 -

if (e==1) os<<\ } else {

os << \ return; } p=head->next; while (p) {

e=p->exp;

if (p->coef!=0.0)//系数非零 {

if (p->coef>0.0) os<<'+'<coef; else os<coef; if (e>1) os<<\ if (e==1) os<<\ } p=p->next; } os<

通过类的成员函数实现对多项式的运算,构造和析构函数主要是实现初始化以及销毁,其它函数则主要是实现功能。

4.3 主函数设计

//主函数 int main() {

int e1[MAXSIZE],e2[MAXSIZE],size2,size1,i; double c1[MAXSIZE],c2[MAXSIZE];

cout<<\多项式计算器------------\

- 12 -

cout<<\ 请输入多项式P1的项数:\cin>>size1;

cout<<\ 请输入多项式P1的系数:\for(i=0;i

cout<<\ 请输入多项式p1的指数\for(i=0;i

cout<<\ 请输入多项式P2的项数:\cin>>size2;

cout<<\ 请输入多项式p2的系数\for(i=0;i

cout<<\ 请输入多项式p2的指数\ { }

Polynominal p1,p2,p3;

p1.Create(c1,e1,size1);//创建多项式p1 p2.Create(c2,e2,size2);//创建多项式p2 cout<<\多项式p1为\ p1.Print();

cout<

cout<

cin>>e2[i]; for(i=0;i>c2[i]; cin>>e1[i]; cin>>c1[i];

- 13 -

}

p3 = p1 + p2;

cout<<\多项式p1+p2为\显示多项式的和 p3 = p1 - p2;

cout<<\多项式p1-p2为\显示多项式的差 p3 = p1*p2;

cout<<\多项式p1*p2为\显示多项式的积 return 0;

在程序的主函数部分,对算法进行了验证。首先,输入了多项式的系数指数项数,接着定义三个对象p1,p2,p3,在定义过程中调用构造函数,进行初始化并动态分配了内存。调用Print()显示多项式,通过调用重载运算符实现操作,最后系统自动调用析构函数清理。

5 DOS界面程序运行结果及分析

5.1 程序运行结果

程序运行结果如图2所示。

- 14 -

图2 程序运行结果

通过计算对运行结果进行检测,经检测结果正确无误。

5.2运行结果分析

整个程序采用的是链表和动态内存分配方式。

将多项式的运算抽象到一个类Polynominal中,由该类生成三个对象p1,p2,,p3,同时由系统调用构造函数初始化,调用Creat()构造多项式,调用重载的运算符,实现加减乘的操作,由于涉及对象传值,调用拷贝构造函数。

6 基于MFC的图形界面程序开发

MFC的图形界面程序设计可在上述类设计的基础上进行改造,MFC的图形界面程序与DOS界面程序的主要不同点是:MFC图形界面程序与DOS界面程序的输入输出方式不同,DOS界面程序采用字符交互式实现数据输入输出,主要通过cin,cout等I/O流实现,而MFC的图形程序界面采用标准Windows窗口和控件实现输入输出,因此必须在MFC类的框架下加入上面所设计的矩阵和方程组类,并通过图形界面的输入输出改造来完成。

6.1 基于MFC的图形界面程序设计

(1)界面设计

首先在VC中建立MFC AppWizard(exe)工程,名称为一元稀疏多项式运算,并在向导的Step1中选择 Single document,即建立基于对话框的应用程序,如下图4~5所示。

- 15 -

图4 建立MFC AppWizard(exe)工程

图5 建立基于对话框的应用程序

将对话框资源中的默认对话框利用工具箱改造成如下界面,如图6所示。

- 16 -

图6 方程组求解程序界面设计

图6所示的界面中包含了3个Group Box(分组框),4个Static Text控件, 5个Button控件,和9个Edit Box控件,控件的基本信息列表如下表1所示。

表1 控件基本信息

控件类别 控件ID 控件Caption 项系数 项指数 Static Text IDC_STATIC 项系数 项指数 IDC_addmenber1 IDC_addmenber2 Botton IDC_add IDC_sub IDC_multiply IDC_EDIT1 IDC_EDIT4 添加 添加 加法运算 减法运算 乘法运算 - 17 -

说明 显示多项式p1 显示多项式p2 显示加法运算结果 显示减法运算结果 显示乘法运算结果 Edit Box IDC_EDIT7 IDC_EDIT8 IDC_EDIT9

况 况

q1=p1;q2=p2; h=k=new node; while(q1 && q2) { } if(q2)

k->next=q2; t=h; h=h->next;

if(q1->expn==q2->expn)//指数相同的情况 { }

else if(q1->expn>q2->expn)//第一项的指数比第二项指数大的情{ }

else if(q1->expnexpn)//第一项的指数比第二项指数小的情{ }

q1=q1->next; k=k->next; k->next=q2; t=q2->next; q2->next=q1; k=k->next; q2=t;

q1->coef=q1->coef+q2->coef; q1=q1->next; k=k->next; t=q2; q2=q2->next; delete t;

k->next=p1;

- 23 -

}

delete t; return h;

⑦ 编写乘法运算处理函数,具体代码如下: node *multiply(node *p1,node *p2) {

node *i,*j,*k,*s,*l,*m,*n;//乘法算法 i=p1; j=p2;

m=j;//保存j的头结点 k=f(0,0);

//保存k为头结点 {

j=m;

while(j)//乘法计算算法,并实现升序排序 {

l=f(0,0);//新计算结果保存在一个单独结点中,用于对之前生成的l->coef=(i->coef)*(j->coef); l->expn=(i->expn)+(j->expn);

;

s=k->next;//s用于对链表的遍历,n为s前驱 while(s) {

if(l->expn==s->expn) { }

else if(l->expnexpn) {

n->next=l; s->coef+=l->coef; delete l; break;

while(i)//创建乘法计算结果链表,形成头结点为k的链表

链表进行对比,形成升序排列

n=k

- 24 -

}

}

}

}

}

l->next=s; break;

else { }

n=n->next; s=s->next;

if(s==NULL) { } j=j->next;

n->next=l;

i=i->next;

return k->next;

⑧ 编写构造多项式具体代码如下: struct node {

node *f(int a,float b) {

node *p=new node; int expn; float coef; node *next;

};//结点结构体

- 25 -

p->coef=b; p->expn=a; p->next=NULL; return p;

}//创建结点

node *copy(node *p)//复制链表的函数 {

node *h,*d,*q,*k,*s;

h=f(0,0);//创建头结点,留空,为了能得到与新创建的结点对比的结点(即是k)的前驱

q=p; while(q) {

d=f(q->expn,q->coef);//创建新结点

s=h;k=s->next;//s是前驱,k是与d做比较的 while(k) { } if(!k)

if(k->expn==d->expn) { }

else if(k->expnexpn) { }

else if(k->expn>d->expn) { }

s->next=d; d->next=k; break; k=k->next; s=s->next;

k->coef+=d->coef;delete d;break;

- 26 -

}

}

{ } q=q->next;

s->next=d;

return h->next;

6.2 程序测试

运行程序后,首先出现的界面如图8所示。

图8 程序初始运行界面

单击添加按钮后,可将多项式在界面上显示出来,如图9所示。

- 27 -

图9 读入数据后的界面

单击加法运算、减法运算乘法运算按钮,实现求解并将解显示出来,如图10所示。

图10 求解后的界面

单击退出按钮后,程序能够正常实现退出。

- 28 -

6.3 MFC程序编写总结

MFC程序与DOS界面程序编写的最大不同是程序员需要将编程精力放在图形界面设计、图形界面输入输出以及界面元素和代码对应转换等问题上,而这些问题在DOS界面程序中是不存在的,因此,初学MFC的编程者会对此感到困难,然而,当你编写出一个基于Windows界面的程序时,所获得的满足程度远远大于简单的DOS界面程序,况且基于Windows的图形界面的程序设计已成为主流,作为程序员而言,是非学会不可的。

本次课程设计作为编写Windows程序的初步尝试,能够实现程序的主要功能,可以说是取得了成功,然而好的程序绝不仅仅是只有功能性这一个指标,本此编写的MFC程序虽然能实现所需功能,但从面向对象程序设计理念和图形界面设计要求来说,尚存在不足,主要包括以下几个方面。

(1)运行一次程序只能计算一对多项式不能重复计算 (2)输入的多项式过长不能正常显示

7 参考文献

[1]徐士良. C常用算法程序集. 北京:清华大学出版社,1995

[2]郑莉,董渊,张瑞丰. C++语言程序设计(第3版). 北京:清华大学出版社,2007 [3]钱能. C++程序设计教程(第二版). 北京:清华大学出版社,2007

[4]陈志泊,王春玲. 面向对象的程序设计语言—C++. 北京:人民邮电出版社,2002 [5]李庆扬,王能超,易大义. 数值分析. 湖北:华中理工大学出版社,1986

- 29 -

本文来源:https://www.bwwdw.com/article/trb6.html

Top