资源描述
《高级语言程序设计》
课程设计报告
课题名称: 多功能计算器
电子信息学院
2015年 07 月 14 日
目 录
1 课程设计目的与要求 1
2 问题描述 2
3 总体设计 3
3.1功能分析 3
1)以菜单方式工作 3
2)整数的加、减、乘、除 3
3)实数的加、减、乘、除 3
4)分数的计算。 3
5)复数的加、减、乘、除 3
6)一元多项式加、减 3
3.2 系统使用的主要函数 3
3.3 系统使用的主要数据结构 4
4 详细设计 6
4.1程序总体结构图 6
4.2 程序流程图 8
5 功能测试 12
5.1.系统主界面 12
5.2整数和实数的加减乘除界面 12
5.3分数的计算的界面 13
5.4复数的加减乘除的界面 13
5.5一元多项式的加减的界面 14
6程序设计调试情况分析 15
7 课程设计小结 16
参考文献 17
附录 系统源程序 17
课程设计题目:多功能计算器
1 课程设计目的与要求
高级语言程序设计是本科工科类各专业的重要基础课,课程以影响深远的、传统的、面向过程的优秀编程语言C语言为基础,学习程序设计的基本概念和方法,通过本门课程学习,应使同学掌握高级语言的基本原理,熟练掌握程序设计的基础知识、基本概念;掌握程序设计的思想和编程技巧。
课程设计是在学生已经具备了使用C语言编写简单的应用程序的能力,为使学生对C语言有更全面的理解,进一步提高运用C语言编程解决实际问题的能力,通过提出算法、指定输入输出来设计一个解决方案。经过该实践环节,培养学生的探索精神和创新能力。通过答辩训练学生的综合表达能力。
参加本课程设计的学生,应当认真完成本课程设计的全部过程。并以最终课程设计成果来证明其独立完成各种实际任务的能力。从而反映出理解和运用本课程知识的水平和能力。具体如下:
(1)数据组织方面尽量使用到:数组、链表、结构体、文件;
(2)程序结构方面做到函数调用,尽量采用指针运算;
(3)代码编写规范,形成良好的编程习惯;
(4)程序须有一定的健壮性和必要的提示信息,考虑问题的多种可能和边界数据。
(5)课设完成须进行答辩,提交课设报告电子稿、装订的打印稿。课设报告内容包括以下几个方面:
l 程序的总体设计和算法分析。
l 程序流程图、函数说明
l 源程序代码清单
l 测试数据和测试过程记录
l 遇到的问题及解决方法分析
l 课程设计小结
2 问题描述
多功能计算器以菜单方式工作,包含了整数和实数的加减乘除、分数的计算、复数的加减乘除以及一元多项式的加减等功能。
多功能计算器中的数据存放在文件中,提供文件的输入、输出等操作,这样可以很方便的读取文件,和保存信息,这样能让信息更好的被利用。
要实现以菜单方式工作的功能,则提供显示操作,将结构体中的数据依次读出。其中,显示的是其他功能的选项,即整数的加减乘除、实数的加减乘除、分数的计算、复数的加减乘除和一元多项式的加减。
要实现整数的加减乘除就需要借用相应的计算,所以只需要设置好相关的加、减、乘、除的计算方式就可计算。当然,也要设定输入的是整数。
要实现实数的加减乘除的方式大体和整数的加减乘除一样。
要实现分数计算的功能,就要先定义分数,分数的定义可以看成是两个数之比。当然,分数可以是负数形式的,我们就可以把它看成是一个正数和一个负数的比值。另外,分数的运算结果要是最简形式的。
关于复数的加减乘除,则是通过抽象数据类型定义和构造二元组进行的。进而进行加减乘除的运算。
要进行一元多项式的加减,则运用链表声明语句,建立带表头结构的单链线性表进而运算。
3 总体设计
3.1功能分析
系统要求实现计算器的最基本功能,包括数据的录入、处理、输出等。对于多功能计算器而言,其数据的处理包括输入数据之间的运算关系,数据处理时的先后顺序以及数据结果的输出。
系统达到的功能如下:
1)以菜单方式工作
2)整数的加、减、乘、除
3)实数的加、减、乘、除
4)分数的计算。将分数定义为两个整数之比,如:1/2,3/4,24/48,64/2等;分数也可以是负数,如-1/2,15/-24;分数运算结果要是最简化的,如:4/-8,应表示成等价的-1/2。
5)复数的加、减、乘、除
6)一元多项式加、减
3.2 系统使用的主要函数
void JJFYS() /*实数和整数加减乘除法运算的函数*/
void FenS() /*分数运算的函数*/
void FuS() /*复数运算的函数*/
void YiD() /*一元多项式运算的函数*/
void match(char expected) /*检查字符匹配的函数*/
void ComplexNumberOutput(fushu c) /*输出运算结果*/
void CreatePolyn(PolynList L,int n) /*指数系数一对一对输入*/
void PolynTraverse(PolynList L,void(*vi)(ElemType, ElemType)) // 初始条件:单链表L已存在
// 操作结果: 依次对L的每个数据元素调用函数vi().一旦vi()失败,则操作失败
void visit(ElemType c, ElemType e) /*ListTraverse()调用的函数(类型要一致)*/
void write() /*写入文件*/
void read() /*从文件中读出运算结果*/
3.3 系统使用的主要数据结构
利用类型定义符定义结构体:
typedef struct result;
char menu(void)
{ char ch;
return(ch);
}
char token[61]; /*存放表达式字符串的数组*/
和
typedef struct fushu//抽象数据类型定义
{
float real;//数据对象
float image;
}fushu;
和
typedef struct PolynNode{
int coef; // 系数
int expn; // 指数
struct PolynNode *next;
}PolynNode,*PolynList;
double result;
FILE *data=fopen("61590_4.dat","at");
4 详细设计
4.1程序总体结构图
多功能计算器系统
整数的加减乘除
实数的加减乘除
分数的计算
复数的加减乘除
一元多项式的加减
图4-1 主控模块
子模块:
整数加法
整数乘法
整数的加减乘除
整数减法
整数除法
图4-2整数的加减乘除模块
实数加法
实数乘法
实数的加减乘除
实数减法
实数除法
图4-3实数的加减乘除模块
分数的计算
分数的定义
分数除法
分数乘法
分数减法
分数加法
分数最简化结果
图4-4分数的计算模块
复数加法cost()
复数减法
复数的加减乘除
复数除法
复数乘法
图4-5复数的计算模块
一元多项式的加减
输入并建立多项式
输出多项式
两个多项式相减,输出差多项式
两个多项式相加,输出和多项式
图4-6 一元多项式的加减模块
4.2 程序流程图
多功能计算器系统理系统
菜单
实数加减乘除
整数加减乘除
分数计算w()
复数加减乘除
一元多项式加减
结束
1
2
3
4
5
主控模块流程图:
图4-7主控模块流程图
整数的加减乘除模块
输入所要求和的整数
将输入的整数相除
能否找到所需要的选项
将输入的整数相加
将输入的整数相减
将输入的整数相乘
结束
子模块流程图:
N
Y
图4-8 整数的加减乘除流程图
复数的加减乘除模块
构造二元组
N
能否找到所需要的选项
Y
复数的除法
复数的乘法
复数的减法
复数的加法
输出结果
图4-11复数的加减乘除流程图
输出运算结果
结束
输入指令,选择退出或继续
建立链表数组 链表链表
输入数据
输入各项指令,进行操作
输出多项式
按项的幂排序
两式相加得出和
两式相减得出差
开始
退出
继续
图4-12 一元多项式的加减流程图
5 功能测试
5.1.系统主界面
多功能计算器系统运行后的界面如图5-1所示。
图5-1系统主界面
5.2整数和实数的加减乘除界面
输入数字及运算符号,键入回车,系统进行运算,得到如图5-2的界面。
图5-2整数或实数的加减乘除的界面
5.3分数的计算的界面
先输入1,2,3,4选择菜单,再分别输入分子分母进行计算,输入0退出系统,得到如图5-3的运行结果。
图5-3分数的计算的界面
5.4复数的加减乘除的界面
先输入实部和虚部,再输入1,2,3,4选择功能,输入0,退出系统,得到如图5-4的界面。
图5-4复数的加减乘除的界面
5.5一元多项式的加减的界面
根据提示输入数据,得到如图5-5的界面。
图5-5一元多项式加减的界面
6程序设计调试情况分析
(1)缺少变量定义,定义位置不正确,过分重视分号的重要性
问题内容: 在for、if、while语句中画蛇添足加分号,有些变量未经定义就开始使用。
问题分析:由于该程序相对来讲稍有些长,前后有些变量不容易联系起来,平时看书不仔细、不太注意,把一些简单的基础知识搞混或忘记
解决方法:但是在错误信息的提示下一般还是很容易找到。不过需要注意的是在定义的时候有些函数使用同样的变量名而表示不同的作用,因而使用要很小心,定义及定义的位置要特别留意。为减少这样的错误我后来还是用不同的变量名来表示,结果引起的那些错误解决了
7 课程设计小结
C语言是一种通用性较强的语言,通过这次C语言的课程设计,我认识到学好计算机要重视实践操作,不仅仅是学习C语言,还是其它的语言,以及其它的计算机方面的知识都要重在实践,所以后在学习过程中,我会更加重视实践操作,使自己更好地学习计算机的各类知识。在实际设计的过程中,需要耐心和细心。通过逐渐熟悉,对程序中出现问题能够较快地找到问题所在,并找到解决的方法。在整个设计过程中,逐渐形成了一种谨慎的对待科学的态度
尽管我们已经学习了《C程序设计》,对老师所讲的知识也有了一些认识,但是正所谓“纸上谈兵终觉浅,觉知此事要躬行。”理论知识学完之后,一定的实践还是很有必要的,所以在本学期课程设计是很及时、很必要的。这样不仅能加深我们对程序设计的掌握,而且还及时、真正的做到了学以致用。在本次课程设计中,我学到了主要是以下几点:基本功要过硬,不能马虎经常犯犯小错误;提高自己找错纠错能力,通常错误总是那几种,多练习就熟练了;要善于查找资料提高自己的资料查询能力,要善于利用网络来获得知识,获得帮助。开始着手程序设计时,有些功能感觉无从下手,都不知道要干什么。这些问题只要找到相关的资料就会得到提示从而理解所要解决问题的大致方向。有了明确的目的,就可以发挥自己的头脑来完成它了;要善于思考。程序中有些实现难点和最初完成程序时免不了的许多不足就需要自己根据代码认真思考来解决。只有这样才能纠正程序的不足并使其更加人性化。
这次课程设计虽然经历了很多波折,也曾让自己苦恼好久,但是让我学到了很多,不仅是巩固了先前学的程序设计知识,而且也培养了我的动手能力,更令我的创造性思维得到拓展。希望今后类似这样课程设计、类似这样的锻炼机会能更多些!
小组成员分工
组长:何驰 负责子程序编程模块,工作量 50 %
组员:张红兵 负责程序调试模块 工作量 25%
丁斌 负责课程设计报告撰写模块 工作量 25%
参考文献
[1] 吉顺如主编.《C程序设计教程与实验》 清华大学出版社
[2] 黄逵中主编.《C语言实例教程》中国电力出版社2004.9
[3] 王为青 张圣亮编著. 《C语言实战105例》 人民邮电出版社,2007
[4] 王金鹏 肖进杰 编著 《C语言设计进阶与实例解析》 清华大学出版社 2011.4
附录 系统源程序
16
#include<stdlib.h>
#include<stdio.h>
#include<malloc.h>
#include<ctype.h>
#define TUB 5
FILE*fp;
struct result
{
float JJFYS;
int FenS;
float FuS;
int YiD;
}s[TUB]={0,0,0,0,0};
typedef struct result;
char menu(void)
{
char ch;
printf("------------------------------------------\n");
printf("\n Management For Caculator's Result\n");
printf("1 JJFYS result\n");
printf("2 FenS result\n");
printf("3 FuS result\n");
printf("4 YiD result\n");
printf("w Write to a File \n");
printf("r Read from a File \n");
printf("0 Exit\n ");
printf("Please Input your choice:");
printf("-------------------------------------------\n");
scanf(" %c",&ch);
return(ch);
}
void JJFYS()
{
char token[61]; /*存放表达式字符串的数组*/
int n=0;
void error(void) /*报告错误函数*/
{
printf("ERROR!\n");
exit(1);
}
void match(char expected) /*检查字符匹配的函数*/
{
if(token[n]==expected)
token[++n]=getchar();
else error();
}
double term(void); /*计算乘除的函数*/
double factor(void); /*处理括号和数字的函数*/
double exp(void) /*计算加减的函数*/
{
double temp=term();
while((token[n]=='+')||(token[n]=='-'))
switch(token[n])
{
case'+':match('+');
temp+=term();
break;
case'-':match('-');
temp-=term();
break;
}
return temp;
}
double term(void)
{
double div;
double temp=factor();
while((token[n]=='*')||(token[n]=='/'))
switch(token[n])
{
case'*':match('*');
temp*=factor();
break;
case'/':match('/');
div=factor();
if(div==0) /*处理除数为零的情况*/
{
printf("The divisor is zero!\n");
exit(1);
}
temp/=div;
break;
}
return temp;
}
double factor(void)
{
double temp;
char number[61];
int i=0;
if(token[n]=='(')
{
match('(');
temp=exp();
match(')');
}
else if(isdigit(token[n])||token[n]=='.')
{
while(isdigit(token[n])||token[n]=='.') /*将字符串转换为浮点数*/
{
number[i++]=token[n++];
token[n]=getchar();
}
number[i]='\0';
temp=atof(number);
}
else error();
return temp;
}
main()
{
double result;
FILE *data=fopen("61590_4.dat","at");
if(data==NULL)
data=fopen("61590_4.dat","wt");
if(data==NULL)
return 0;
token[n]=getchar();
result=exp();
if(token[n]=='\n')
{
token[n]='\0';
printf("%s=%g\n",token,result); fprintf(data,"%s=%g\n",token,result);
}
else error();
fclose(data);
return 0;
getch();
}
}
void FenS()
{
int fm,f;
int tf(int a,int b,int m,int n)
{
int i,s;
for(i=b>n?b:n;;i++)
{
if(i%b==0&&i%n==0)
break;
}
fm=i;
if(f)
s=(i/b*a+i/n*m);
else
s=(i/b*a-i/n*m);
return s;
}
int hj(int t,int s)
{
int i;
for(i=t<s?t:s;i>=1;i--)
{
if(t%i==0&&s%i==0)
{
t/=i;
s/=i;
}
}
fm=s;
return t;
}
main()
{
int a,b,m,n,t,s,fz,r,c,ff=0;
char k;
printf("------------------------------------------\n");
printf(" [1] 加法 [2] 减法\n");
printf(" [3] 乘法 [4] 除法\n");
printf(" [0] 退出\n");
printf("------------------------------------------\n");
do{
printf("请输入你选择的菜(0--4):");
k1:
scanf("%d",&c);
if(c<0||c>4)
{ printf("菜单中没有本选项,请重新输入!");
fflush(stdin);
goto k1;
getchar();
}
printf("请输入第一个分数的分子和分母:");
scanf("%d %d",&a,&b);
printf("请输入第二个分数的分子和分母:");
scanf("%d %d",&m,&n);
switch(c)
{
case 0:return 0;break;
case 1:f=1;t=tf(a,b,m,n);s=fm;k='+';break;
case 2:f=0;t=tf(a,b,m,n);s=fm;k='-';break;
case 3:t=a*m;s=b*n;k='*';break;
case 4:t=a*n;s=b*m;k='/';break;
}
fz=hj(t,s);
printf("%d/%d%c%d/%d=%d/%d\n",a,b,k,m,n,fz,fm);
}while(1);
}
void FuS()
{
typedef struct fushu//抽象数据类型义
{
float real;//数据对象
float image;
}fushu;
fushu ComplexNumberInput(float a,float b)//构造二元组
{
fushu c;
c.real=a;//实部
c.image=b;//虚部
return(c);
}
fushu ComplexNumberAdd(fushu c1,fushu c2)//求和运算
{
fushu sum;
sum.real=c1.real+c2.real;
sum.image=c1.image+c2.image;
return (sum);
}
fushu ComplexNumberSub(fushu c1,fushu c2)//求差运算
{
fushu sub;
sub.real=c1.real-c2.real;
sub.image=c1.image-c2.image;
return (sub);
}
fushu ComplexNumberMul(fushu c1,fushu c2)//求积运算
{
fushu Mul; Mul.real=c1.real*c2.real-c1.image*c2.image; Mul.image=c1.real*c2.image+c1.image*c2.real;
return (Mul);
}
fushu ComplexNumberDiv(fushu c1,fushu c2)//求商运算
{
fushu div;
float d1,d2,d3,d4;
d1=c1.real*c2.real+c1.image*c2.image;
d2=c2.real*c2.real+c2.image*c2.image;
d3=c1.image*c2.real-c1.real*c2.image;
d4=c2.real*c2.real+c2.image*c2.image;
if(d2!=0&&d4!=0)
{
div.real=d1/d2;
div.image=d3/d4;
return(div);
}
else
{
div.real=0;
div.image=0;
return(div);
}
}
void ComplexNumberOutput(fushu c)//输出运算结果
{
if(c.real==0.0&&c.image==0.0)
printf("0\n");
if(c.real==0.0&&c.image!=0.0)
printf("%fi\n",c.image);
if(c.real!=0.0&&c.image==0.0)
printf("%f\n",c.real);
if(c.real!=0.0&&c.image!=0.0)
printf("%f+(%fi)\n",c.real,c.image);
}
void main()//主函数
{
int choice;
int k;
float a1,a2,b1,b2;
struct fushu c1,c2,sum,sub,mult,div;
printf("欢迎进行复数的基本代数运算\n");
printf("1: 复数加法运算\n");
printf("2: 复数减法运算\n");
printf("3: 复数乘法运算\n");
printf("4: 复数除法运算\n");
printf("0: 推出系统\n");
printf("请分别输入第一个复数的实部和虚部: ");
scanf("%f%f",&a1,&b1);
c1 = ComplexNumberInput(a1,b1);
printf("第一个复数为: ");
ComplexNumberOutput(c1);
printf("请分别输入第二个复数的实部和虚部: ");
scanf("%f%f",&a2,&b2);
c2 = ComplexNumberInput(a2,b2);
printf("第二个复数为: ");
ComplexNumberOutput(c2);
for(;;)
{
printf("请输入你选择的功能: ");
scanf("%d",&choice);
switch(choice)
{
case 0:exit(0); break;
case 1:sum = ComplexNumberAdd(c1,c2);
printf("求和后结果为: ");
ComplexNumberOutput(sum); break;
case 2:sub = ComplexNumberSub(c1,c2);
printf("求差后结果为: ");
ComplexNumberOutput(sub); break;
case 3:mult = ComplexNumberMul(c1,c2);
printf("求积后结果为: ");
ComplexNumberOutput(mult ); break;
case 4:div=ComplexNumberDiv(c1,c2);
if(div.real!=0&&div.image!=0)
{
printf("求商后结果: ");
ComplexNumberOutput(div); break;
}
else
{ printf("除零错误,请重新输入第二个复数;\n");
k=0;
exit(k);
}
}
}
}
}
void YiD()
{
typedef int ElemType;
/*单项链表的声明*/
typedef struct PolynNode{
int coef; // 系数
int expn; // 指数
struct PolynNode *next;
}PolynNode,*PolynList; /*正位序(插在表尾)输入n个元素的值,建立带表头结构的单链线性表*/
/*指数系数一对一对输入*/
void CreatePolyn(PolynList L,int n)
{
int i;
PolynList p,q;
L=(PolynList)malloc(sizeof(PolynNode)); // 生成头结点
L->next=NULL;
q=L;
printf("成对输入%d个数据\n",n);
for(i=1;i<=n;i++)
{ p=(PolynList)malloc(sizeof(PolynNode));
scanf("%d%d",&p->coef,&p->expn); //指数和系数成对输入
q->next=p;
q=q->next;
}
p->next=NULL;
}
// 初始条件:单链表L已存在
// 操作结果: 依次对L的每个数据元素调用函数vi().一旦vi()失败,则操作失败
void PolynTraverse(PolynList L,void(*vi)(ElemType, ElemType))
{
PolynList p=L->next;
while(p)
{
vi(p->coef, p->expn);
if(p->next)
{
printf(" + "); //“+”号的输出,最后一项后面没有“+”
}
p=p->next;
}
printf("\n");
}
/*ListTraverse()调用的函数(类型要一致)*/
void visit(ElemType c, ElemType e)
{
if(c != 0)
{
printf("%dX^%d",c,e); //格式化输出多项式每一项
}
}
/* 多项式相加,原理:归并 */
/* 参数:两个已经存在的多项式 */
/* 返回值:归并后新的多项式的头结点 */
PolynList MergeList(PolynList La, PolynList Lb)
{
PolynList pa, pb, pc, Lc;
pa = La->next;
pb = Lb->next;
Lc = pc = La; // 用La的头结点作为Lc的头结点
while(pa&&pb)
{
if(pa->expn < pb->expn)
{
pc->next = pa; //如果指数不相等,pc指针连上指数小的结点,
pc = pa;
pa = pa->next; //指向该结点的指针后移
}
else if (pa ->expn > pb->expn )
{
pc->next = pb; //pc指针连上指数小的结点,
pc = pb;
pb = pb->next; //指向该结点的指针后移
}
else //(pa ->expn = pb->expn )
{
pa->coef = pa->coef + pb->coef; //指数相等时,系数相加
pc->next = pa;
pc = pa;
pa = pa->next; //两指针都往后移
pb = pb->next;
}
}
pc->next = pa ? pa:pb; // 插入剩余段
return Lc;
}
void main()
{
PolynList ha,hb,hc;
printf("非递减输入多项式ha, ");
CreatePolyn(ha,5); // 正位序输入n个元素的值
printf("非递减输入多项式hb, ");
CreatePolyn(hb,5); // 正位序输入n个元素的值
printf("多项式ha :");
PolynTraverse(ha, visit);
printf("\n");
printf("多项式hb :");
PolynTraverse(hb, visit);
printf("\n");
hc = MergeList(ha,hb
展开阅读全文