1 / 17
文档名称:

C语言课程设计输入一个表达式,输出其结果.pdf

格式:pdf   大小:728KB   页数:17页
下载后只包含 1 个 PDF 格式的文档,没有任何的图纸或源代码,查看文件列表

如果您已付费下载过本站文档,您可以点这里二次下载

分享

预览

C语言课程设计输入一个表达式,输出其结果.pdf

上传人:小sjj 2022/12/2 文件大小:728 KB

下载得到文件列表

C语言课程设计输入一个表达式,输出其结果.pdf

文档介绍

文档介绍:该【C语言课程设计输入一个表达式,输出其结果 】是由【小sjj】上传分享,文档一共【17】页,该文档可以免费在线阅读,需要了解更多关于【C语言课程设计输入一个表达式,输出其结果 】的内容,可以使用淘豆网的站内搜索功能,选择自己适合的文档,以下文字是截取该文章内的部分文字,如需要获得完整电子版,请下载此文档到您的设备,方便您编辑和打印。:.
课程设计报告
课程名称C语言程序设计
课题名称输入一个表达式,输出其结果
专业通信工程
班级通信1101
学号27
姓名皮锋
指导教师罗雅博彭祯曹燚
2012年6月29日:.
湖南工程学院
课程设计任务书
课程名称
C语言程序设计
课题
输入一个表达式,输出其结果
专业班级通信1101
学生姓名皮锋
学号27
指导老师罗雅博彭祯曹燚
审批
任务书下达日期2012年6月15日
任务完成日期2012年6月29日
:.
一、设计思想
两种算法首先都要建立两个栈,一个是存放操作数的数栈OdStack,一个是存放运算符
的符栈OpStack。数栈采用double型的用来存放浮点数,符栈采用char型的用来存放运算
符,由于考虑到运算符有优先级的问题,所以事先做了一个Type用来存储运算符的优先级。
栈建立好了之后做栈的相关操作,初始化栈,入栈,出栈,看栈顶。其中入栈要判满,出栈
和看栈顶要判空。
中缀转后缀再计算的算法。
此算法的基本思路是先将中缀表达式转换成后缀表达式,之后再利用后缀表达式的算法
对表达式进行计算。
首先,用一个char数组将中缀表达式读入,对数组中的每一个元素进行处理,区分哪
些是数,哪些是运算符。如果是数元素(或小数点元素),则依次存入用来存储后缀表达式
的char数组,直到一个整合数存完之后用空格将其与后面的元素分开。如果是运算符元素,
则根据当前运算符的优先级和栈里面的运算符的优先级进行处理。如果栈内元素的优先级小
于当前元素的优先级或者栈内为空,则将当前运算符入栈;如果栈内元素的优先级大于等于
当前元素的,则依次将出栈元素存入后缀表达式,并用空格将其与后面的元素分开,直到栈
内元素的优先级小或者栈内为空。对于左括号来说,无条件进栈,并只在有右括号出现的时
候才有可能出栈。对于右括号来说,无条件让栈内元素出栈,直到左括号出栈。依次将每个
元素进行处理直到中缀表达式索引完毕。至此,已经实现了将中缀表达式转换成了后缀表达
式,在数组的最后加上结束符以便下一步的调用。
第二步,读出后缀表达式并进行计算。如果索引到空格则将索引标志后推1位。之后要
先对char型的数字元素进行整合,从后缀表达式中依次取出数字元素(连同小数点)存入
一个新的char型数组,直到一整个数取完后通过atof函数将char型转换成浮点型存入数栈,
并将新数组初始化用来存储下一个数。如果是索引到运算符,则在数栈中出栈两个数字与当
前运算符进行运算,先出栈的数字放在运算符后面,后出栈的数字放在运算符的前面,将运
算以后的结果再次存入数栈。依次进行计算直到后缀表达式索引完毕。此时对栈内剩余元素
进行操作。每在符栈出栈一个运算符,就从数栈出栈两个数进行计算,算法同上,将运算以
后的结果再次存入数栈。循环操作直到符栈栈空,此时数栈出栈元素即为最后结果。
:.
二、算法流程图
中缀转后缀再计算的算法分两个流程,第一步是中缀表达式转换成后缀表达式;
图1中缀转后缀算法流程图
:.
第二步是将后缀表达式进行计算输出。
:.

,设计的程序每运行一次只能进行一次计算:
intmain()
{
printf("******欢迎进入小型计算器******\n请输入算术表达
式:");
charstr[N];
doubleresult;
scanf("%s",str);
result=Calu(str);
printf("输出计算结果:%f\n",result);
}
为了改进程序,我在主函数里加了一个循环:
intmain()
{
inta;
printf("******欢迎进入小型计算器******\n请输入算术表达
式:");
for(a=0;;a++)
{
charstr[N];
doubleresult;
scanf("%s",str);
result=Calu(str);
printf("输出计算结果:%f\n",result);
printf("〉〉");
}
}
,想什么时候退出计算就退出计算,我对程序又进行了改进,
输入字母e退出计算:
if(exp1[index1]=='(')
{
=exp1[index1];
=-1;
OpPush(&OpStack,&tempsign);
index1++;
}
else
{
if(exp1[index1]==')')
{
while(OpPeek(&OpStack).level!=-1):.
{
exp2[index2]=OpPop(&OpStack).Type;
index2++;
exp2[index2]='';
index2++;
}
OpPop(&OpStack);
index1++;
}
elseif(exp1[index1]=='e')/*
exit(0);
else
Error();
}

:.
:.

#include<>
#include<>
#include<>
#defineN100/*N为数栈和表达式数组容量*/
#defineM100/*M为符栈和其他数组容量*/
typedefstruct/*定义运算符类型,level为运算符等级*/
{
charType;
intlevel;
}Type;/*做一个Type用来存储运算符的优先级*/
typedefstruct/*定义存放操作数的数栈*/
{
doublestack[N];
inttop;
}OdStack;
typedefstruct/*定义存放运算符的符栈*/
{
Typestack[M];
inttop;
}OpStack;
voidInit_OdStack(OdStack*s)/*定义初始化数栈*/
{
(*s).top=0;
}//初始化栈顶,赋等级0值
voidOdPush(OdStack*s,doublen)/*进数栈*/
{
if((*s).top==N-1)/*如果栈满则报错退出程序*/
Error();
else
{
(*s).stack[(*s).top]=n;//将数栈中的值变为n
(*s).top++;//栈顶的值加1
}
}
doubleOdPop(OdStack*s)/*定义出数栈*/
{
if((*s).top==0)/*如果栈空则报错退出程序*/
Error();:.
else
{
(*s).top--;//栈顶的值减1
return(*s).stack[(*s).top];//返回数栈中的值
}
}
voidInit_OpStack(OpStack*s)/*定义初始化符栈*/
{
(*s).top=0;
}//初始化栈顶,赋等级0值
voidOpPush(OpStack*s,Type*sign)/*定义进符栈*/
{
if((*s).top==M-1)/*如果栈满则报错退出程序*/
Error();
else
{
(*s).stack[(*s).top]=*sign;
(*s).top++;//栈顶的值加1
}
}
TypeOpPop(OpStack*s)/*定义出符栈*/
{
if((*s).top==0)/*栈空则报错退出程序*/
Error();
else
{
(*s).top--;
return(*s).stack[(*s).top];//返回符栈的值
}
}
TypeOpPeek(OpStack*s)/*定义看符栈顶*/
{
Typeren;
if((*s).top==0)/*判栈空,空则赋等级0值*/
{
=0;//运算优先级为等级0值
returnren;
}
else
return(*s).stack[(*s).top-1];
}
intError()/*报错函数*/
{
printf("输入错误!\n");:.
exit(1);
}
intCom(chartempch)/*定义运算符等级*/
{
intlevel;/*给不同运算符定级*/
switch(tempch)
{
case'+':
case'-':level=1;break;
case'*':
case'/':level=2;break;//乘除优先加减
}
returnlevel;//返回运算符等级
}
doubleOper(doublea,doubleb,chartempch)/*定义运算过程*/
{
doubleren;
switch(tempch)/*对不同运算符执行运算并返回结果*/
{
case'+':ren=b+a;break;
case'-':ren=b-a;break;
case'*':ren=b*a;break;
case'/':ren=b/a;break;
}
returnren;
}
doubleCalu(char*exp1)//
{
OdStackOdStack;/*定义数栈*/
OpStackOpStack;/*定义符栈*/
Typetempsign;/*定义Type型运算符*/
charexp2[N],tempexp[M],tempch;/*定义后缀表达式数组exp2,整合
数组tempexp,tempch为运算符*/
intindex1,index2,tempindex;/*index1为主要索引,index2为次要索
引,tempindex为附加索引*/
doublenumber,a,b,c;/*number为整合数,a、b、c为运算
数*/
Init_OdStack(&OdStack);/*初始化数栈*/
Init_OpStack(&OpStack);/*初始化符栈*/
index1=0;/*初始化索引,附加索引*/
index2=0;
tempindex=0;
tempexp[0]='\0';/*初始化整合数组*/
while(exp1[index1]!='\0')/*处理初始表达式转化成后缀表达式*/:.
{
if((exp1[index1]>='0'&&exp1[index1]<='9'))/*处理数字元素*/
{
while((exp1[index1]>='0'&&exp1[index1]<='9')||
exp1[index1]=='.')
{
exp2[index2]=exp1[index1];/*连续的数字元素不分
开并依次存入后缀表达式*/
index2++;
index1++;
}
exp2[index2]='';/*结束后用空格将
其与后面的元素分开*/
index2++;
}
else//不是数字或小数点元素
{
if(exp1[index1]=='+'||exp1[index1]=='-'||exp1[index1]=='*'||exp1[index1]=='/')//
是运算符/*处理运算符元素
*/
{
=exp1[index1];
=Com();/*求运算符等
级*/
while(OpPeek(&OpStack).level>=)/*当栈
中符的等级大于当前等级时则取出符存入后缀表达式*/
{
exp2[index2]=OpPop(&OpStack).Type;
index2++;
exp2[index2]='';/*每两个运算
符之间用空格分开*/
index2++;
}
OpPush(&OpStack,&tempsign);/*结束后将当前运
算符入栈*/
index1++;
}
else
{
if(exp1[index1]=='(')/*如果是左括号则无条
件进栈*/
{
=exp1[index1];:.
=-1;/*进栈后等级为-1,以
便遇到右括号出栈*/
OpPush(&OpStack,&tempsign);
index1++;
}
else
{
if(exp1[index1]==')')/*右括号规则*/
{
while(OpPeek(&OpStack).level!=-1)/*遇到
右括号则不断出栈存入后缀表达式直到寻到左括号*/
{
exp2[index2]=OpPop(&OpStack).Type;
index2++;
exp2[index2]='';/*每两个运算符之间用
空格分开*/
index2++;
}
OpPop(&OpStack);/*直到遇到左括号将左
括号出栈*/
index1++;
}
elseif(exp1[index1]=='e')
exit(0);
else/*如果输入了非法
字符则报错退出程序*/
Error();
}
}
}
}
while(OpPeek(&OpStack).level!=0)/*原表达式结束后对栈进行
操作直到栈空*/
{
if(OpPeek(&OpStack).level==-1)/*如果有为用掉的左括号则
报错退出程序*/
Error();
exp2[index2]=OpPop(&OpStack).Type;
index2++;
exp2[index2]='';
index2++;
}
exp2[index2]='\0';/*最后结束后缀表达式*/
index1=0;/*索引归零,开始计:.
算结果*/
while(exp2[index1]!='\0')/*循环直到后
缀表达式结束*/
{
if((exp2[index1]>='0'&&exp2[index1]<='9'))/*整合数并
入栈*/
{
while((exp2[index1]>='0'&&exp2[index1]<='9')||
exp2[index1]=='.')/*用附加索引判断数的长度并整合入整合数组*/
{
tempexp[tempindex]=exp2[index1];
index1++;
tempindex++;
}
tempexp[tempindex]='\0';/*结束整合数组*/
if(tempexp[0]!='\0')/*如果整合数
组有值则转换成浮点型存入数栈*/
{
number=atof(tempexp);
OdPush(&OdStack,number);
tempexp[0]='\0';/*入栈后初始化整
合数组和附加索引以便下次整合*/
tempindex=0;
}
}
else
{
if(exp2[index1]=='')/*判断空格,有则跳
过*/
{
while(exp2[index1]=='')
index1++;
}
else
{
if(exp2[index1]=='+'||exp2[index1]=='-'||exp2[index1]=='*'||exp2[index1]=='/')/*
对加减乘除进行运算*/
{
a=OdPop(&OdStack);
b=OdPop(&OdStack);
tempch=(exp2[index1]);
c=Oper(a,b,tempch);
OdPush(&OdStack,c);/*将计算结:.
果放入数栈*/
index1++;
}
}
}
}
returnOdPop(&OdStack);/*弹出结果*/
}
intmain()
{
inta;
printf("******欢迎进入小型计算器******\n字母e结输入束计
算!\n请输入算术表达式:");
for(a=0;;a++)
{
charstr[N];/*定义数组以存储表达式*/
doubleresult;/*定义result以存储结
果*/
scanf("%s",str);
result=Calu(str);/*计算表达式并返回结
果值*/
printf("输出计算结果:%f\n",result);
printf("〉〉");
}
}

通过对本次程序的学****和编写,了解了关于电脑对计算表达式的计算过程,并且学会了
从中缀变成后缀的方法。在本次编写的时候遇到了不少问题和麻烦,通过对C语言的复****br/>和对算法的分析,最终也一一解决。也是这次的编写让我更加认识到算法的重要性和算法的
趣味性,特别是中缀转后缀如直接计算的差别体现了算法的发展历程和一个好的算法对于程
序的关键性。通过本次编写也意识到了清晰的程序结构对于以后的更新和更改都有很重要的
意义,方便的利用函数体来定义一些算法比直接在主函数中设置算法要好的多。更关键的是
了解到了栈的性质和用途,一些适当的问题使用栈不仅仅可以迎刃而解,有时还能够起到事
倍功半的效果。从栈的构建、定义到入栈、出栈、看栈顶等的操作编写,大幅度提高了个人
的编程能力,体会到了不同的结构在程序中所起到的不同的作用。同时也更加关注了程序的
容错机制和简介模式。
计算机与通信学院课程设计评分表:.
设计内容:C语言程序设计
项目评价
课程设计期间表现情况
课程设计内容完成情况
课程设计答辩成绩
课程设计报告完成质量
综合成绩
日期:2012年6月30

:.