第一篇:C++课程设计报告--矩阵乘法计算
C++课程设计报告
一、题目名称:矩阵乘法计算
二、难易等级: A级
三、对题目的分析和注释:
分析:
依次建立两个矩阵空间并按照矩阵乘法规则进行运算。(矩阵的乘法规则:
1、矩阵的乘法运算必须符合m*n的矩阵与n*s的矩阵相乘。
2、第一个矩阵的第i行的元素依次乘以第二个矩阵的第j列元素后结果相加组成生成矩阵第i行第j列元素。)
注释:
(1)设计一个矩阵类,将相应的函数和数据封装在类中,简化程序。
(2)修改程序结构,使程序可以反复执行,直至按键选择退出为止。
(3)本程序用数组表示5*5矩阵,将其改为根据输入矩阵的大小动态分配空间[m][n]来放置数据,其中m,n为用户可输入的任意整数。
(4)增加类的构造函数和成员函数,使得矩阵数据既可以用在对象初始化时赋值,也可以通过键盘赋值,还可以通过读取数据文件输入。
(5)用模板的形式改写矩阵数据类型,使得矩阵中的数据既可以是整型数据,也可以是浮点型数据,执行程序时,分别定义两个整型矩阵和两个浮点型矩阵进行乘法验证。
(6)完成矩阵的乘法运算,在运算之前判断这两个矩阵能否满足乘法运算的条件,若不满足,则给出提示信息。
四、所增加功能模块的设计
如果要说增加功能的话,自己编的程序里面不多,我只是按照题目要求,设计了一个矩阵类,同时用模板的形式改写矩阵数据类型和运算符的重载。
1、模板的使用
我使用了大量的模板,以T为模板参数,通过对T的不同类型的选择实现相应的运算处理。其中choose1()函数本是无参函数,为了方便模板化,给其赋以伪参数T,在执行时通过T的取值生成相应的函数模板。
template
switch(sjlx){
case 1:
{
choose1(1);
}break;
case 2:
{
choose1(0.0);
}break;
case 3:
{
choose1(1e-10);
}break;
default:cout<<“输入选择错误!!”< 2、矩阵类的构造 按照课本要求采用二级指针动态开辟内存空间,节省内存使用; 其中数据结构如下: Mat-->Mat[0]----->Mat[0][0] Mat[0][1] ……Mat[0][j] Mat[1]----->Mat[1][0] Mat[1][1] ……Mat[1][j] : : Mat[i]----->Mat[i][0] Mat[i][1] ……Mat[i][j] 实现构造的代码为: template Mat[i]=new T[nCol];} cout<<“请输入数据:n”;for(i=0;i for(j=0;j { cout<<“第[”< cin>>Mat[i][j]; } } 3、运算符的重载 要实现矩阵间的乘法运算,有必要对其运算符进行重载。而乘法运算符又要针对不同数据类型进行运算,所以我对运算符重载函数模板化。template mat3.Mat[i][j]=0; for(int k=0;k mat3.Mat[i][j]+=mat1.Mat[i][k]*mat2.Mat[k][j];} return mat3;} 五、设计中遇到的主要问题及解决办法 1、无法实现文件输入 主要原因是输入之前调用的是默认构造函数,只是简单赋值,并未开辟内存空间,后来调用带参构造函数就可以正常输入数据; 2、重载乘法运算的函数无法重载 经检查发现,由于重载的是友元函数,函数不存在this指针,因此必须显式地调用两个相乘的矩阵类。 六、设计中尚存的不足 1、功能还不够强大,只能做简单的矩阵乘法,我所期望的是能够做各种混合运算,具有强大处理功能的实用程序,希望在以后的深入学习中可以改进。 2、关于异常处理这方面,我觉得处理功能也不是很行,觉得还是应该建立全面的异常检测与异常处理机制。 七、对设计的感想和心得体会 经过这几周的上机编程,我体会颇多,学到了很多东西。我加强了对C++程序设计这门课程的认识,并且复习了自己上学期学习到的知识。这些都使我对计算机语言的学习有了更深入的认识。总之,通过这这几周的上机编程,我收获颇丰,相信会为自己以后的学习和工作带来很大的好处。像矩阵乘法计算问题这样的程序设计,经历了平时在课堂和考试中不会出现的问题和考验。而这些问题,这并不是我们平时只靠课本,就可以轻易解决的。所以,锻炼了我们挑战难题,学会用已掌握的知识去解决具体问题的能力,进一步培养了独立思考问题和解决问题的能力。当然,老师的指导和同学的帮助也是不可忽视的,他们给了我许多提示和帮助,教会了我编译复杂程序的方法。 实践出真知,做课程设计前,我的C++知识只是停留在理论水平,而且就算理论水平,也存在很多漏洞。有时,在做课题的时候,理论的漏洞冒了出来,我就只能在看着课本慢慢的再学习一遍,但有些东西还是没有搞懂,所以现在就又翻出课本,看着课本编程,也算是将旧的东西复习了一遍。同时,有的概念在编程过程中印象更加深刻。 成功=勤奋+合作。在课程设计这方面自己也花了好多时间,交流与合作在编程过程中给我很大的帮助,我得到了很多,每次看到解问题后大家的愉悦,我想大家应该与我一样收获很大吧。说真的,我挺喜欢这种讨论的氛围,它也让编程过程变得趣味横生,不再只是呆滞的盯着屏幕写程序。 对凡事都应当有毅力,不要中途放弃。在编程过程中,好几次遇到困难我都想再换一个别的程序或找同学拷一个程序,但我最终还是坚持下来了。永不言弃,你就一定会成功的。 磨刀不误砍柴工。在刚拿到任务时,书上的关键代码我也是看的一头雾水,后来我将上学期的课本认真研读一遍之后,感觉收获真的不少,接着编起程来就顺手好多了。 此次程序设计使我透彻地领悟到面向对象的程序设计的优点和强大生命力,特别是类和模板的使用,使程序的兼容性和扩展能力都大大加强,比如我们想要再做一个处理其他类型数据的矩阵的乘法计算,只需要添加一个相应的类型声明就可以利用模板迅速构造出来。 通过课程设计的训练,我进一步学习和掌握了对程序的设计和编写,从中体会到了面向对象程序设计的方便和巧妙。懂得了在进行编写一个程序之前,要有明确的目标和整体的设计思想。另外某些具体的细节内容也是相当的重要。这些宝贵的编程思想和从中摸索到的经验都是在编程的过程中获得的宝贵财富。这些经验对我以后的编程会有很大的帮助的,我要好好利用。 这次矩阵乘法计算问题课程设计让我充分认识到了自己的不足,认识到了动手能力的重要性。我会在以后的学习中更加努力锻炼自己,提高自己,让自己写出更好更完善的程序,为以后的编程打好基础! 数据结构 课程设计报告 设计题目: n维矩阵乘法:A B-1 专 业 计算机科学与技术 班 级 计本 学 生 学 号 指导教师 起止时间 2007.X.3-2007.X.11 学年第I 学期 一、具体任务 功能: 设计一个矩阵相乘的程序,首先从键盘输入两个矩阵a,b的内容,并输出两个矩阵,输出ab-1结果。 分步实施: 1.初步完成总体设计,搭好框架,确定人机对话的界面,确定函数个数; 2.完成最低要求:建立一个文件,可完成2维矩阵的情况; 3.进一步要求:通过键盘输入维数n。有兴趣的同学可以自己扩充系统功能。 要求: 1.界面友好,函数功能要划分好 2.总体设计应画一流程图 3.程序要加必要的注释 4.要提供程序测试方案 5.程序一定要经得起测试,宁可功能少一些,也要能运行起来,不能运行的程序是没有价值的。 二、软件环境 Microsoft Visual C++ 6.0 三、问题的需求分析 程序以二维数组作为矩阵的存储结构,通过键盘输入矩阵维数n,动态分配内存空间,创建n维矩阵。矩阵建立后再通过键盘输入矩阵的各个元素值;也可以通过文件读入矩阵的各项数据(维数及各元素值)。 当要对矩阵作进一步操作(A*B或A*B^(-1))时,先判断内存中是否已经有相关的数据存在,若还未有数据存在则提示用户先输入相关数据。 当要对矩阵进行求逆时,先利用矩阵可逆的充要条件:|A| != 0 判断矩阵是否可逆,若矩阵的行列式 |A| = = 0 则提示该矩阵为不可逆的;若 |A| !=0 则求其逆矩阵,并在终端显示其逆矩阵。 四、算法设计思想及流程图 1.抽象数据类型 ADT MatrixMulti{ 数据对象:D = {a(I,j)|i = 1,2,3,…,n;j = 1,2,…,n;a(i,j)∈ElemSet,n为矩阵维数} 数据关系: R = {Row,Col} Row = {| <= i <= n,1 <= j <= n-1} Col = {| <= i <= n-1,1 <= j <= n} 基本操作: Swap(&a,&b); 初始条件:记录a,b已存在。 操作结果:交换记录a,b的值。 CreateMatrix(n); 操作结果:创建n维矩阵,返回该矩阵。 Input(&M); 初始条件:矩阵M已存在。 操作结果:从终端读入矩阵M的各个元素值。 Print(&M) 初始条件:矩阵M已存在。 操作结果:在终端显示矩阵M的各个元素值。 ReadFromFile(); 操作结果:从文件读入矩阵的相关数据。 Menu_Select(); 操作结果:返回菜单选项。 MultMatrix(&M1,&M2,&R); 初始条件:矩阵M1,M2,R已存在。 操作结果:矩阵M1,M2作乘法运算,结果放在R中。 DinV(&M,&V); 初始条件:矩阵M,V已存在。 操作结果:求矩阵M的逆矩阵,结果放入矩阵V中。 MatrixDeterm(&M,n); 初始条件:矩阵M已存在。 操作结果:求矩阵M的行列式的值。 } ADT MatrixMulti 2.矩阵求逆算法设计思想 算法采用高斯-约旦法(全选主元)求逆,主要思想如下: 首先,对于k从0到n-1作如下几步: ① 从第k行、第k列开始的右下角子阵中选取绝对值最大的元素,并记住此元素所在的行号与列号,再通过行交换和列交换将它交换到主元素位置上。这一步称为全选主元。 ② 主元求倒:M(k,k) = / M(k,k) ③ M(k,j) = M(k,j) * M(k,k);j = 0,1,…,n-1;j != k ④ M(i,j) = M(i,j) – M(i,k) * M(k,j);i,j = 0,1,…,n-1;i,j!=k ⑤ M(i,k) = M(i,k) * M(k,k),i = 0,1…,n-1;i != k 最后,根据在全选主元过程中所记录的行、列交换的信息进行恢复,恢复原则如下: 在全选主元过程中,先交换的行(列)后进行恢复;原来的行(列)交换用列(行)交换来恢复。 3.矩阵行列式求值运算算法设计思想 利用行列式的性质:行列式等于它的任一行(列)各元素与其对应的代数余子式乘积,即 D = ∑a(i,k)*A(i,k) ; k = 1,2,…,n; D = ∑a(k,j)*A(k,j) ; k = 1,2,…,n; 再利用函数的递归调用法实现求其值。 4.各函数间的调用关系 Main() ReadFromFile() DinV() Swap () Print() Menu_Select() MatrixDeterm() CreateMatrix() MultMatrix() Input() 5.流程图 否 否 是 否 是 是 否 是 否 否 是 开始 switch(Menu_Select()) case 1: case 3: case 2: n 0 ? 是 输入矩阵维数n 输入矩阵A,B 输出矩阵维数n system(“pause”); 通过键盘输入需对哪个矩阵求逆,求出相应该的逆阵,并显示求得的逆阵system(“pause”);若矩阵不可逆则返回主菜单 case 4: R=A*B并显示矩阵R system(“pause”); case 5: 是 否 是 R=A*B^(-1)显示矩阵R system(“pause”);若B不可逆,则返回主菜单 case 6: 从指定文件中读入矩阵数据 case 0: exit(0); 结果 否 五、源代码 #include #include #include #include #include #include #define YES #define NO 0 typedef float ElemType; ElemType **A; //矩阵A ElemType **B; //矩阵B ElemType **R; //矩阵R,用于存放运算结果 ElemType **V; //矩阵V,存放逆矩阵 int n=0; //矩阵维数 int flag=-1; //标记 void swap(ElemType *a,ElemType *b) //交换记录a,b的值 { ElemType c; c=*a; *a=*b; *b=c; } ElemType **CreateMatrix(int n) //创建n维矩阵,返回该矩阵 { int i,j; ElemType **M; M = (ElemType **)malloc(sizeof(ElemType *)*n); if(M == NULL) exit(1); for(i=0;i { *(M+i) = (ElemType *)malloc(sizeof(ElemType)*n); for(j=0;j *(*(M+i)+j) = 0; } return M; } ElemType MatrixDeterm(ElemType **M,int n) /*递归法求n维矩阵行列式的值,返回运算结果*/ { int i,j,k,l,s; ElemType **T1; ElemType **T2; T1=CreateMatrix(n); T2=CreateMatrix(n); ElemType u; ElemType value=0; //运算结果 for(i=0;i { for(j=0;j { T1[i][j]=M[i][j]; T2[i][j]=M[i][j]; } } if(n==2) //若为2维矩阵,则直接运算并返回运算结果 { value=T2[0][0]*T2[1][1]-T2[0][1]*T2[1][0]; return value; } else { for(j=0;j //将矩阵的行列式以第一行展开 { u=T1[0][j]; for(i=1,l=0;i //求矩阵行列式的余子式M(0,j) { for(k=0,s=0;k { if(k==j) continue; else { T2[l][s]=T1[i][k]; s++; } } l++; } value=value+u*((int)pow(-1,j))*MatrixDeterm(T2,n-1); /*行列式等于某一行的各个元素与其代数余子式的乘积之和*/ } return value; } } int DinV(ElemType **M,ElemType **V) /*全选主元法求矩阵M的逆矩阵,结果存入矩阵V中*/ { int i,j,k; ElemType d; ElemType u; int *JS,*IS; JS=(int *)malloc(sizeof(int)*n); IS=(int *)malloc(sizeof(int)*n); u=MatrixDeterm(M,n); //返回矩阵A的行列式值 if(u==0) return -1; for(i=0;i for(j=0;j V[i][j]=M[i][j]; for(k=0;k { d=0; for(i=k;i //找出矩阵M从M[k][k]开始绝对值最大的元素 { for(j=k;j { if(fabs(V[i][j])>d) { d=fabs(V[i][j]); //d记录绝对值最大的元素的值 /*把绝对值最大的元素在数组中的行、列坐标分别存入IS[K],JS[K]*/ IS[k]=i; JS[k]=j; } } } if(d+1.0 == 1.0) return 0; //所有元素都为0 if(IS[k] != k) /*若绝对值最大的元素不在第k行,则将矩阵IS[K]行的元素与k行的元素相交换*/ for(j=0;j swap(&V[k][j],&V[IS[k]][j]); if(JS[k]!=k) /*若绝对值最大的元素不在第k列,则将矩阵JS[K]列的元素与k列的元素相交换*/ for(i=0;i swap(&V[i][k],&V[i][JS[k]]); V[k][k]=1/V[k][k]; //绝对值最大的元素求倒 for(j=0;j /*矩阵M第k行除元素M[k][k]本身外都乘以M[k][k]*/ if(j!=k) V[k][j]=V[k][j]*V[k][k]; for(i=0;i /*矩阵除第k行的所有元素与第k列的所有元素外,都拿本身减去M[i][k]*M[k][j],其中i,j为元素本身在矩阵的位置坐标*/ if(i!=k) for(j=0;j if(j!=k) V[i][j]=V[i][j]-V[i][k]*V[k][j]; for(i=0;i /*矩阵M第k列除元素M[k][k]本身外都乘以-M[k][k]*/ if(i!=k) V[i][k]=-V[i][k]*V[k][k]; } for(k=n-1;k>=0;k--) /*根据上面记录的行IS[k],列JS[k]信息恢复元素*/ { for(j=0;j if(JS[k]!=k) swap(&V[k][j],&V[JS[k]][j]); for(i=0;i if(IS[k]!=k) swap(&V[i][k],&V[i][IS[k]]); } free(IS); free(JS); return 0; } void MultMatrix(ElemType **M1,ElemType **M2,ElemType **R) /*矩阵M1乘M2 结果存入矩阵R*/ { int i,j,k; for(i=0;i { for(j=0;j { R[i][j]=0; } } for(i=0;i { for(j=0;j { for(k=0;k { R[i][j]=R[i][j]+M1[i][k]*M2[k][j]; } } } } void Input(ElemType **M) //输入矩阵M的各个元素值 { int i,j; char str[10]; char c='A'; if(flag==1) c='B'; system(“cls“); printf(“\n\n输入矩阵%c(%d*%d)\n“,c,n,n); for(i=0;i { for(j=0;j { scanf(“%f“,*(M+i)+j); } } flag=1; gets(str); //吸收多余的字符 } void Print(ElemType **M) //显示矩阵M的各个元素值 { int i,j; printf(“\t“); for(i=0;i { for(j=0;j { printf(“ %.3f“,M[i][j]); } puts(““); printf(“\t\t“); } } int Menu_Select() { char c; do{ system(“cls“); puts(“\t\t*************n维矩阵乘法器*************“); puts(“\t\t| 1.通过键盘输入各项数据 |“); puts(“\t\t| 2.显示矩阵A,B |“); puts(“\t\t| 3.矩阵求逆,并显示逆矩阵 |“); puts(“\t\t| 4.求矩阵运算A*B,并显示运算结果 |“); puts(“\t\t| 5.求矩阵运算A*B^(-1),并显示运算结果|“); puts(“\t\t| 6.从文件读入矩阵A,B与维数n |“); puts(“\t\t| 0.退出 |“); puts(“\t\t***************************************“); printf(“\t\t请选择(0-6):“); c=getchar(); }while(c<'0'||c>'6'); return (c-'0'); } void ReadFromFile() //从指定文件读入矩阵的维数及矩阵各元素的值 { int i,j; FILE *fp; if((fp=fopen(“tx.txt“,“r“))==NULL) { puts(“无法打开文件!!“); system(“pause“); exit(0); } fscanf(fp,“%d“,&n); //读入矩阵维数 A=CreateMatrix(n); //创建矩阵A B V R B=CreateMatrix(n); V=CreateMatrix(n); R=CreateMatrix(n); for(i=0;i //读入矩阵A { for(j=0;j { fscanf(fp,“%f“,&A[i][j]); } } for(i=0;i //读入矩阵A { for(j=0;j { fscanf(fp,“%f“,&B[i][j]); } } puts(“\n\n读文件成功“); fclose(fp); flag=1; } int main() { int i; char c,h; char str[10]; for(;;) { switch(Menu_Select()) { case 1: flag=-1; for(;;) { system(“cls“); printf(“\n\n\t矩阵维数n:“); scanf(“%d“,&n); gets(str); if(n>0) break; else { printf(“\n\t输入有误,请重新输入!\n“); puts(““); system(“pause“); } } A=CreateMatrix(n); B=CreateMatrix(n); V=CreateMatrix(n); R=CreateMatrix(n); Input(A); Input(B); break; case 2: system(“cls“); if(flag==-1) { puts(“\n\n\t不存在任何矩阵数据,请先输入数据“); system(“pause“); break; } puts(“\n“); printf(“\tA = “); Print(A); puts(“\n“); printf(“\tB = “); Print(B); puts(““); system(“pause“); break; case 3: system(“cls“); if(flag==-1) { puts(“\n\n\t不存在任何矩阵数据,请先输入数据“); system(“pause“); break; } for(;;) { printf(“\n\n\t输入需要求逆的矩阵(A/B):“); h=getchar(); c=getchar(); //h=getchar(); if(c=='A'||c=='a') { i=DinV(A,V); if(i==-1) { puts(“\n\n\t矩阵A的行列式等于0,不可逆!“); system(“pause“); break; } printf(“\tA = “); Print(A); puts(“\n“); printf(“A^(-1) = “); Print(V); puts(““); system(“pause“); break; } else if(c=='B'||c=='b') { i=DinV(B,V); if(i==-1) { puts(“\n\n\t矩阵B的行列式等于0,不可逆!“); system(“pause“); break; } printf(“\tB = “); Print(B); puts(“\n“); printf(“B^(-1) = “); Print(V); puts(““); system(“pause“); break; } else puts(“\n\n\t输入有误,请重新输入!\n“); } break; case 4: system(“cls“); if(flag==-1) { puts(“\n\n\t不存在任何矩阵数据,请先输入数据“); system(“pause“); break; } MultMatrix(A,B,R); printf(“\n\n\tA*B = “); Print(R); puts(““); system(“pause“); break; case 5: system(“cls“); if(flag==-1) { puts(“\n\n\t不存在任何矩阵数据,请先输入数据“); system(“pause“); break; } i=DinV(B,V); if(i==-1) { puts(“\n\n\t矩阵B的行列式等于0,不可逆!“); system(“pause“); break; } MultMatrix(A,V,R); printf(“\n\nA*B^(-1) = “); Print(R); puts(““); system(“pause“); break; case 6: system(“cls“); ReadFromFile(); puts(““); system(“pause“); break; case 0: puts(“\t\t正常退出“); exit(0); break; } } return 0; } 六、运行结果 1.主界面: 2.输入6,回车,从文本文件tx.txt中读入矩阵数据: 3.回车,回到主菜单界面;输入2回车,显示从文件读入的矩阵数据: 4.回车,回到主菜单界面;输入3回车,对指定矩阵求逆:(由于这里矩阵A是不可逆的,因此仅以矩阵B为例) 5.回车,回到主菜单界面;输入4回车,求矩阵运算A*B: 6.回车回到主菜单界面,输入5回车,求A*B^(-1)的值: 7.回车回到主菜单界面,输入0回车,退出程序;如果需要自定矩阵维数及各元素值,请利用主菜单里的1号功能自行输入数据,再进行以上几种运算操作。 七、收获及体会 通过这次课程设计,让我再次复习了线性代数里矩阵的相关知识,比如n维矩阵的求逆、矩阵可逆的充分必要条件(|A| != 0)、矩阵与矩阵的乘法运算、行列式求值方法等。同样的,还让我复习了大量C语言里有关数组的一些重要概念,比如多维数组的动态分配问题、数组与指针的关系等。 记得在这个学期新开设的单片机基础课上,吴涛老师曾多次强调,让我们一定要经常锻炼自己的编程能力,他常对我们说:“编程是思维的体操。”尽管我在这方面的能力 和实力非常得有限,也远远不及班上的其他同学,但我通过这次课程设计充分体会到了这句话的精华。 电脑程序作为人体大脑思维的延伸,程序的功能也会因为大脑思维的不断完善而变得更加强大,所以我决定今后要加强在这方面的锻炼和学习,以此来激励自己不断前进! 八、参考文献 《数据结构(C语言版)》 严蔚敏,吴伟民 编著 清华大学出版社 《C语言程序设计》 洪维恩 编著 中国铁道出版社 《C语言程序设计教程》 谭浩强 张基温 唐永炎 编著 高等教育出版社 《工程数学——线性代数 第四版》 同济大学应用数学系 编 高等教育出版社 计本 2007-12 题目:计算表达式的值 1、问题描述 对于给定的一个表达式,表达式中可以包括常数、算术运行符(“+”、“-”、“*”、“/”)和括号,编写程序计算表达式的值。 基本要求:从键盘输入一个正确的中缀表达式,将中缀表达式转换为对应的后缀表达式,计算后缀表达式的值。 提高要求:(1)对于表达式中的简单错误,能够给出提示; (2)不仅提示错误,也能给出错误信息(3)表达式中可以包括单个字母表示的变量(4)能够处理多种操作符(5)实现包含简单运算的计算器 (6)实现一个包含简单运算和函数运算的计算器。 2.需求分析 软件的基本功能:由键盘输入中缀表达式,程序可以将输入的中缀表达式转换成对应的后缀表达式,并计算后缀表达式的值。对于在输入时发生的简单错误,程序可以给出提示。本程序支持整数、小数、多种操作数的处理,可以计算含加、减、乘、除、运算符的表达式,并能判断表达式括号是否匹配。输入/输出形式:用户可以通过控制台,根据输入提示。输入形式: ①正确的不含字母变量的中缀表达式; ②含有简单错误的中缀表达式。 输出形式: ①对于正确的中缀表达式,可以输出其转化后的后缀表达式及表达式的计算结果; ②对于含有简单错误的中缀表达式,程序将自动输出错误提示,并给出错误信息。 测试数据要求:用户可以输入一个符合要求的中缀表达式,也可以输入一个包含简单错误的表达式。表达式中可以包括各种类型的常数以及小数等,操作符包括(+、-、*、/),同时表达式还可以包括各种括号。 3.概要设计 (1)抽象数据类型: 根据题目的要求,考虑用栈类型比较适合。ADT SeqStack Data 栈中元素具有相同类型及后进先出特性,相邻元素具有前驱和后继关系 Operation SeqStack 前置条件:栈不存在 输入:无 功能:栈的初始化 输出:无 后置条件:构造一个空栈 ~ SeqStack 前置条件:栈已存在输入:无 功能:销毁栈 输出:无 后置条件:释放栈所占用的存储空间 Push 前置条件:栈已存在 输入:元素值x 功能:在栈顶插入一个元素x 输出:如果插入不成功,抛出异常 后置条件:如果插入成功,栈顶增加了一个元素 Pop 前置条件:栈已存在输入:无 功能:删除栈顶元素 输出:如果删除成功,返回被删元素值,否则,抛出异常 后置条件:如果删除成功,栈顶减少了一个元素 GetTop 前置条件:栈已存在 输入:无 功能:读取当前的栈顶元素 输出:若栈不空,返回当前的栈顶元素值 后置条件:栈不变 Empty 前置条件:栈已存在输入:无 功能:判断栈是否为空 输出:如果栈为空,返回1;否则,返回0 后置条件:栈不变 End ADT 4.详细设计 (1)实现概要设计的数据类型: 采用顺序栈 const int StackSize = 50;template ~SeqStack();//析构函数 void Push(T x);//将元素x入栈 DataType Pop(); //将栈顶元素弹出 DataType GetTop();//取栈顶元素(并不删除) int Empty();//判断栈是否为空 private: DataType data[StackSize];//存放栈元素的数组 int top;//栈顶元素 };(2)主程序以及其它模块的算法描述: 这个函数主要调用了实现功能的各个函数。其步骤为:在用户没有选择退出时,先调用输入函数,输入中缀表达式;然后调用判断表达式,如果中缀表达式错误,则根据返回的值来输出错误提示,不再往下运算;如果中缀表达式正确,则将中缀表达式转换为后缀表达式,然后输出中缀表达式和转换后的后缀表达式;接着,再调用计算函数,计算后缀表达式的结果输出。最后是清屏函数。直至用户选择退出。 5、编码与调试分析 编码与调试过程中遇到的问题及解决办法: 【问题1】程序在判断表达式输入形式有误时,考虑情况不周全。解决办法:尽可能多的将表达式有误的情况考虑在内。以下为现已考虑到并解决的问题:①表达式中出现非数字或非运算符的其他字符; ②表达式中括号不匹配。 【问题2】给变量赋值时出现重定义问题。 解决办法:在定义暂存栈顶元素的变量t时,应该在函数外面定义,在函数里面给变量赋值时不能定义。【问题3】无法处理多位数和小数。 解决办法:在连续的操作数结束之后插入空格到后缀表达式中,以分隔操作数。 解决此问题的核心代码: int i,t=0;float sum=0;for(i=0;i if(a[i]=='.'){ } } t=i;break;if(t!=0){ } else { } return sum; 2.待解决问题: for(i=0;i } i++;for(;i } sum=(a[i]-'0')*pow(0.1,i-t)+sum;if(a[i]=='.')break;sum=(a[i]-'0')*pow(10,n-(n-t)-1-i)+sum;for(i=0;i 6、使用说明 进入菜单,根据提示进行选择。 7、测试结果 (1)含小数、多位数及括号的表达式显示结果: 8、自学知识 在课程设计过程中,特别是在代码编写和调试的过程中,自学了很多新的知识。例如atof()函数,包含于表头文件 #include 自学MFC。还有一个知识点是清屏函数,它也是包含于 9、课程设计心得体会 通过这次课程设计,增强了我的自信心。因为在这次课程设计中,我遇到了一些问题,但是都逐个得解决了,虽然有些问题请教了同学,但是从中学了很多东西,也学到了一些处理问题的方法。在能力上得到了一些提升。同时也养成了独立思考问题,以及和同学一起探索问题的良好习惯。当然,在课程设计过程中,有些细节的处理还是不够完美,需要完善的地方还有很多,还需要继续努力,尽量将程序完善。 在编写程序过程中,得到了部分同学的帮助,如:数据间的分隔问题,得到了***同学的帮助,将中缀表达式转换为后缀表达式的算法思想参考了《数据结构课程设计》(机械工业出版社),然后根据自己的理解,完成基本算法和细节处理,最后完成了转换函数的代码编写。 在将字符串转换为浮点型数字进行运算的思想主要参考了《程序设计引导及在线实践》这本书里面的一道程序,然后加以灵活运用,转换为自己的代码。当然,为此也掌握了一些新的知识。 清屏函数是在百度百科上获取的知识,也属于自学的新知识。 参考书 [1]《c++面向对象程序设计》 清华大学出版社 谭浩强著 [2]《数据结构(C++版)》清华大学出版社 王红梅、胡明、王涛著 大连科技学院 C++课程设计报告 题 目 稿件管理数据系统 小组成员 吕荣兴 学生姓名 吕荣兴 专业班级 信管10-1班 所在系部 信息科学系 指导教师 曾维佳 职称 讲师 目 录 一 题目...........................................................2 二 实验目的.......................................................2 三 实验内容.......................................................2 四 实验结果.......................................................5 五 体会...........................................................5 六 小组分工......................................................14 七 部分程序代码..................................................14 C++课程设计报告 一 题目 稿件数据管理系统 二 实验目的 稿件管理系统,即是一个帮助人们管理大量稿件信息的系统。其应包括以下几项基本的功能:1)将稿件的一些基本信息(如稿件的编号,稿件名,第一作者的名字,投稿的日期,作者的省份等等)录入到系统中; 2)显示信息,即将系统中所有的稿件信息全部显示出来,方便人们的查看; 3)删除信息功能,即可以将一些不需要或是错误的文件删除; 4)修改,即将一些错误的稿件信息更正; 5)查看,即可以查看系统中一些稿件的信息,而不需要将所有的信息都显示出来,可更精确的查询某一个稿件的信息,找到并显示出来; 6)统计,即按照稿件作者的省份将每个省投稿的总的篇数统计出来并从高到低排列显示; 7)添加信息,即在原有数据的基础上增加一组或多组稿件的信息; 8)将输入系统的稿件信息写入到指定的文件中,便于保存; 9)将已有文件中的稿件信息读入到系统中,便于查看; 10) 退出系统。 三 实验内容 1、系统描述 统计稿件管理数据,要求能用菜单实现如下功能: 1输入每件稿件的第一作者名字,稿件名称,投稿日期,作者的省份。2输入每件稿件的发表日期,审稿意见。3按作者的省份,从高到低排出每个省的总发表篇数。4根据用户要求输出某作者某月(从键盘输入作者名和月份)的所有稿件数据。5 根据用户输入,绘制稿件按省份的百分比饼图。 2、系统需求分析 1、对于稿件管理系统要有一个清晰的认识,要知道一篇稿件包含哪些信息,而且要了解其中具体有哪些数据及变量,这就需要做一些查询或者询问的工作。 2、对其变量定义时是用整型、浮点型、还是字符型,这些都是稿件类中必须要解决的问题。 3、要考虑函数成员的实现。 4、要考虑整个程序要用到那些语句及前后逻辑。 5、更重要的是,我们要明确该程序的目的:能够有把握程序总的方向。编写一个简单的稿件管理程序,帮助管理大量的稿件信息。要求利用类实现,数据采用文件输 入。稿件管理包括稿件信息的录入,添加,显示,查询,删除,修改等功能。 3、设计思想 我的总体思路是先定义一个稿件的结构体数组,用于储存稿件的各项信息,在定义了数组以后,接下来便是定义一些函数用于实现各项功能,最后定义主函数,并应用switch语句等调用定义过的各项子函数来实现该系统的各项功能。 明白了应该做的功能以后,接下来就是实现这些功能,编写出正确的稿件管理系统。在编写程序的时候,最关键的地方就是算法的设计,这一步,我想也该是整个课程设计中最困难的地方。算法设计好了,整个程序基本上就算是完成了一大半了。下面便是我在设计算法时的一些基本想法: 首先是定义一个结构体数组,用于存放稿件的一些基本信息:稿件编号Number,其类型为int型,稿件名M_Name,其为char型数组,作者名字Author,同样为char型数组,投稿时间Time,char型,作者省份Province,char型数组。、在定义好了结构体数组后,便是写一些用于实现各项功能的子函数。 功能函数1:稿件信息录入功能 定义信息录入函数Input(),首先是清除多余的数据,在判断适合以后,再交互输入稿件的各项信息,在输入完成以后利用get(x)将多余的输入清除。 功能函数2:显示所有稿件信息的功能 定义显示信息功能函数Display(),先是判断系统中是否有稿件的信息,如果没有,则输出提示“没有记录”,如果有稿件的信息,则输出"编号 名称 作者名字 投稿日期 作者省份"再在下面显示相关的稿件信息,包括稿件的编号,稿件的名称,第一作者的名字,投稿日期,作者的省份等等。显示稿件信息的时候用的是循环输入。显示后输出提示“按任意键继续”。 功能函数3:按作者的省份统计出各省发表高见的总篇数,先是定义几个int型变量i,a,sa,并赋给初始值0;以及各省的名称:如A省,char A;再使用for循环语句统计出各省所发表的稿件的总的篇数。在统计好了各省的投稿总篇数后再使用冒泡或是选择排序将其按照从高到低的顺序重新排列,并显示出来包括稿件的编号,稿件的名称,第一作者的名字,投稿日期,作者的省份等等。 功能函数4:查找信息 定义一个查找稿件的函数,并可以将找到的稿件信息显示出来,Search(),文件内容是,先是输入提示:“输入需要查找的稿件的编号”,接下来便是在在系统的已有数据中查找,如果没有相关的稿件信息,则输出提示:“对不起,无法找到该稿件的信息!”相应的,输入信息失败,然后返回。相反,如果找到了该稿件的信息,则逐个将该稿件的信息输出显示出来包括稿件的编号,稿件的名称,第一作者的名字,投稿日期,作者的省份等等。在查找稿件信息的时候,还可以根据稿件的名称,第一作者的名字,投稿日期,作者的省份等信息进行查找并将其删除。 功能函数5:插入信息功能 定义函数Insert(),其主要功能就是将一个已知的稿件信息添加到系统之中。该函数开始是用一个字符型数组char x[10]将多余的输入清除,然后再用交互输入的方法将稿件的各项信息逐个写入 系统之中,包括稿件的编号,稿件的名称,第一作者的名字,投稿日期,作者的省份等等。并输出提示“成功插入稿件信息!”。 功能函数6:修改信息功能 定义修改稿件信息函数Modify(),运行时,先是输入提示“输入需要修改的稿件的编号”,然后进行查找判断,若查找到了,则显示“编号 名称 作者名字 投稿日期 作者省份”,并在相应的位置将相应的稿件信息显示出来,显示出来以后的一步便是对该稿件的信息进行修改,先是将修改后的稿件信息逐个输入(交互输入),再将修改后的信息与原来的信息赋给原来的那组稿件,这样,一组稿件信息的修改便完成了。可以在显示稿件信息的功能函数里进行查看,看是否修改信息成功,最后,输出提示“稿件信息修改成功”。若没有找到相应的函数,则说明输入有误,系统中不存在所输入得稿件,并且输出提示“对不起,无该稿件的信息”。在查找稿件信息的时候,还可以根据稿件的名称,第一作者的名字,投稿日期,作者的省份等信息进行查找并将其删除。 功能函数7:信息删除功能 定义一个删除稿件信息的函数Delete(),输入提示“请输入需要删除的稿件的编号”,查找判断,如果没有找到相应的编号的稿件信息,则说明该系统中没有要查找的稿件信息,返回信息失败,输出提示“提示:对不起,无法找到该编号!”。 相反,如果找到了相应编号的稿件以及稿件的信息,以其后一位的稿件的各项相关的信息将其覆盖,即将其删除。并输出提示“已成功删除!”。 删除功能还可以根据稿件的名称,第一作者的名字,投稿日期,作者的省份等信息进行查找并将其删除。 功能函数8:将已知文件中的稿件信息读入到系统之中 定义读入数据函数Duru()。打开指定的文件“**.Txt”,再将该文件中的各个稿件信息以循环的方式读入到文件f1中,然后关闭文件f1.close。并显示“提示:读入数据成功,可选择【显示所有信息】查看”。 功能函数9:将系统中的稿件信息写入到指定的文件之中 定义写入文件函数Save()。打开文件f2,按循环方式将系统中的所有稿件信息写入到指定的文件之中。,在写入成功以后显示“提示:稿件信息已成功存入文件”。 在上面的这些功能函数定义好了以后,接下来的便是菜单函数Menu()和主函数void main()的编写设计。 1)编写菜单函数:实行逐行输入形成一个整体菜单的方法,用cout<<“ ”的方法将该稿件管理系统的基本功能显示出来,供使用者操作; 2)主函数void main()的编写: 使用switch语句,选择判断,在菜单函数中选择需要执行的相关函数,在主函数中调用相应的功能函数(子函数)来实现相应的功能,实现完一个功能后再跳出主函数,重新在菜单函数中选择相应的功能,再通过主函数中的选择判断调用相应的子函数来实现相应的功能。最后,选择功能“0” 退出该系统,并显示“谢谢您的使用!”。算法的设计到此结束。下面进行的便是上机调试。 四 实验结果 编写好稿件管理系统的源代码以后,在上机调试的过程中遇到了不少的错误,调试的时候也不是一两次就能通过的,主要的就是一些语法上的错误等,还有就是头文件的使用,有时候又,调试怎么都不能通过,但却怎样也找不到错误在哪里,结果,加了一个头文件,一切的问题迎刃而解;也有的时候,一处的一个小小的输入错误会导致后面一大片的错误,只要发现了并正确地修改,很多问题都会得到解决。在连续了两个星期的时间后,终于,我所编写的程序可以编译通过了,大部分功能也都能得以实现了。 在编写这个稿件程序管理系统时,我主要是运用了结构体数组,而没有用类,链表和指针等,因为我一直以来对这些东西都不是和懂,一开始以为这并没什么伪问题,但是,通过这两星期的课程设计课,我认识到了自己在学习专业课上的很多毛病,原来我连最最基本的一些的都不知道,不清楚,不能完全的、熟练地去掌握它们。通过这一次的学习,我认识到,时间不是让我们浪费在那些无聊的事情上,尽管这里是大学,不像高中那样,但是我们不能就此认为浪费时间就是理所当然的。我们应该将更多的时间花在一些有意义的事情上,一些可以增加我们的知识,开阔我们的眼界,增强我们身心健康的事情上。 调试成功后的主菜单显示如下: 如菜单中所示,共有0—9是个选项,分别对应了该稿件管理系统的十个相应的功能,选择相应的功能可以执行想要的一些功能。 功能一:稿件信息录入功能的测试结果:输入稿件的基本信息,其结果如下: 该功能可以连续输入,在写入一组稿件信息后还可以选择“y”继续写入更多的稿件信息,选择“n”则结束这项功能,进入主菜单,继续选择新的功能。 功能二:显示所有的稿件信息功能的测试结果,显示所有稿件的各项信息,其结果如下: 可以看出,该项功能可以将系统中所有的稿件信息一一显示出来,便于查看,在结果显示出来以后可以按任意键退出该功能回到主菜单进行新的功能选项; 功能三统计篇数的功能: 该功能可以按作者的省份将每个省的稿件发表总的篇数统计出来,并按照从高到低的顺序将其排列显示出来。 功能四:查找稿件信息功能的测试,其测试结果如下: 输入稿件的编号,便可将改建的所有信息一一显示出来,如稿件的编号,稿件名,作者名字,投稿日期,作者省份等等,显示后可按任意键退出该功能,回到主菜单进行下一功能的选择运用。 功能五:添加稿件信息功能的测试,其结果如下图所示: 选择功能5后,将出现提示:“插入一组稿件信息”,接下来可以根据提示信息将所要插入的稿件信息逐一录入系统,并可在功能2中显示出来看是否插入成功,按任意键同样可以退出该功能,进入主菜单重新进行新的任务; 功能六:信息修改功能的测试,其测试结果如下: 首先,找出需要修改的稿件信息,并将其显示出来,然后再进行修改功能,修改完成后可以按任意键退出该功能;同样,可以在功能2中检查是否修改成功; 功能七:删除文件功能的测试,其测试结果如下图所示: 稿件删除成功后,按任意键返回主菜单进行新的任务; 功能八:读入数据功能,其测试结果为: 读入文件后,按任意键回单主菜单,再在主菜单里选择功能2查看读入数据是否成功; 功能九:将系统中的稿件信息写入指定文件的功能的测试,其结果如下图所示: 功能0:即退出该系统,其显示如下: 安全退出系统。 五 体会 由于上课时没有认真听C++课程老师的讲解,学得相当糟糕,但要设计的又是一个较大的程序,便去请教老师。老师建议我们找一个模板,认真仔细地看,去理解它,看懂它,然后根据自己的实践内容适当修改,应该就没多大问题了。 老师的话给了我莫大的鼓励,但不自觉地滋生了傲慢的态度。只要有个模板不就行了嘛,小事一桩啊!但结果并非如此在后来的实践过程中,我还是碰到了许多麻烦。一个大程序都是环环相扣的,类的对象,函数的定义,变量的使用都是互相有联系的。我认为只要把模板略加改动,就能够完成这次作业了。这种投机取巧的想法让我很快尝到了苦头。程序编好后,执行时出现了许多错误,大多是定义的不规则,究其原因,我根本没看懂模板。还是仔细研究模板吧!我首先声明头文件,然后分别定义稿件数据类、稿件省份类,再是函数声明语句,主函数的定义(switch语句的应用)。接着,我浏览了成员函数,每个成员函数看起来并不很难,简单的输入输出(AddItem),指针取值(基本都涉及到了)还有交换变量的数据域(swap)。但对指针还是相当模糊的,不能透彻地理解它,在C++机试中就是因为不了解指针,导致相关的试题都不会做。看完每一个函数,心里算是有些程序雏形了。对于按省份给每个省的总发表篇数进行排序这一问题,刚开始真的不会弄,老师让我用一维数组,可还是不太明白。于是,我询问了周边同学。他们用了多重循环语句,并且调试成功了,听他们讲解后我便用了他们的方法。,与同学讨论向同学请教有时候也不失为一个好方法,一个人的智慧毕竟是不全面的,集体的力量才是强大的! 六 小组分工 程序设计 系统调试 吕荣兴 七 部分程序代码 #include int Number;//稿件编号 char M_Name[20];//稿件名称 char Author[20];//作者名字 char Time[20];//投稿日期 char Province[20];// 作何省份 }Manuscript;Manuscript Manus[100];/*结构体数组变量*/ int menu()/*菜单函数*/ { char c;do { system(“cls”);/*运行前清屏*/ cout<<“ n”;cout<<“ n”;cout<<“ n”;cout<<“ n”;cout<<“ n”;cout<<“ ************************************************************n”;cout<<“ ************************************************************n”;cout<<“ * ☆★☆★☆★☆★☆★☆稿件管理系统☆★☆★☆★☆★☆★☆ *n”;cout<<“ * * * *n”;cout<<“ * ★ 1-----------信息录入 2-----------显示信息 ★ *n”;cout<<“ * * * *n”;cout<<“ * ☆ 3-----------统计篇数 4-----------查找显示 ☆ *n”;cout<<“ * * * *n”;cout<<“ * ★ 5-----------添加信息 6-----------信息修改 ★ *n”;cout<<“ * * * *n”;cout<<“ * ☆ 7-----------删除信息 8-----------读入数据 ☆ *n”;cout<<“ * * * *n”;cout<<“ * ★ 9-----------写入文件 0-----------保存退出 ★ *n”;cout<<“ * * * *n”;cout<<“ * ★ ☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆ ★ *n”;cout<<“ * *n”;cout<<“ ************************************************************n”;cout<<“ * ★ ☆★☆★☆★ 按数字键选择相应程序 ★☆★☆★☆★☆ ★ *n”;cout<<“ ************************************************************n”< c=getchar();/*读入选择*/ } while(c<'0'||c>'9');return(c-'0');/*返回选择*/ } /////////****** 功能1 ************* 录*************************************************///////////////////// int Input(Manuscript Manus[],int n)/*录入信息*/ { int i=0;char sign,x[10];/*x[10]为清除多余的数据所用*/ while(sign!='n'&&sign!='N')/*判断*/ { cout<<“请输入稿件的编号:”;/*交互输入*/ cin>>Manus[n+i].Number;cout<<“请输入稿件的名称:”;cin>>Manus[n+i].M_Name;cout<<“请输入作者名字:”;cin>>Manus[n+i].Author;cout<<“请输入投稿日期:”;cin>>Manus[n+i].Time;cout<<“请输入作者省份:”;cin>>Manus[n+i].Province;gets(x);/*清除多余的输入*/ cout<<“=====>提示:继续写入?(Y/N)”;cin>>sign;/*输入判断*/ i++;} return(n+i);} /////////////////////////////////////////////////////////////////// 入信息 课程设计总结 经过一个学期对《C++程序设计》的学习,我学习到了基本的理论知识,了解到了C++语言程序设计的思想,这些知识都为我的课程实践和进一步的学习打下了坚实的基础。在为期近两周的C++课程设计中,我体会颇多,学到了很多东西。我加强了对C++程序设计这门课程的认识,并且复习了自己以前学习到的知识。这些都使得我对计算机语言的学习有了更深入的认识!总之,通过这次课程设计,我收获颇丰,相信会为自己以后的学习和工作带来很大的好处。像职工信息表这样的程序设计,经历了平时在课堂和考试中不会出现的问题和考验。而这些问题,这并不是我们平时只靠课本,就可以轻易解决的。所以,锻炼了我们挑战难题,学会用已掌握的知识去解决具体问题的能力,进一步培养了独立思考问题和解决问题的能力。特别是学会了在Visual C++中如何调试程序的方法。当然,老师的指导和同学的帮助也是不可忽视的,他们给了我许多提示和帮助,教会了我编译复杂程序的方法。 在老师和同学的帮助下,通过自己的努力,终于完成了这次职工信息表的简单课程设计。我经过这段时间的编程,对其中的艰辛,我是深有体会。从刚开始的选择程序、理解程序到后来的调试程序以及改进程序这个过程中,我遇到了各种各样的困难和挫折。但是我坚定信念,对自己充满了信心,想尽一切办法克服重重困难。 通过课程设计的训练,我进一步学习和掌握了对程序的设计和编写,从中体会到了面向对象程序设计的方便和巧妙。懂得了在进行编写一个程序之前,要有明确的目标和整体的设计思想。另外某些具体的细节内容也是相当的重要。这些宝贵的编程思想和从中摸索到的经验都是在编程的过程中获得的宝贵财富。这些经验对我以后的编程会有很大的帮助的,我要好好利用。 虽然这次课程设计是在参考程序的基础之上进行的,但是我觉得对自己是一个挑战和锻炼。我很欣慰自己能在程序中加入自己的想法和有关程序内容,也就是对它的程序改进了一番改进,并有创新。但是我感觉自己的创新还不够典型,总之还不是很满意。另外由于时间的紧迫和对知识的了解不够广泛,造成了系统中还存在许多不足,功能上还不够完善。以后我会继续努力,大胆创新,争取能编写出透射着自己思想的程序。这次课程设计让我充分认识到了自己的不足,认识到了动手能力的重要性。我会在以后的学习中更加努力锻炼自己,提高自己,让自己写出更好更完善的程序,为以后的编程打好基础! 总而言之,这次C++程序设计实践让我收获很大。 计算机科学与技术13-2班 2010年7月4日第二篇:数据结构课程设计报告n维矩阵乘法
第三篇:C++ 数据结构 课程设计报告 计算表达式
第四篇:C++课程设计实训报告
第五篇:c++课程设计总结