C语言下表达式的自动计算两种方式报告+源代码Word文档下载推荐.docx
《C语言下表达式的自动计算两种方式报告+源代码Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《C语言下表达式的自动计算两种方式报告+源代码Word文档下载推荐.docx(40页珍藏版)》请在冰点文库上搜索。
2.下面给出得到后缀表达式的算法流程图:
图2得到后缀表达式的算法流程图
图2是通过用户输入的表达式得到其后缀表达式的算法流程图,整体描述了得到后缀表达式的过程,但是还有一些细节并没有刻画出来。
其中,大方向有两个分支,就是判断进来的字符是否为数字,然后,当得知进来的字符不是数字时,又分成了两个分支,即判断该字符是否为运算操作符或是左括号,因为他们的操作基本类似;
第二分支就是进来的字符为右括号。
3.下面给出通过后缀表达式得到计算结果的算法流程图:
图3通过后缀表达式得到结果的算法流程图
图3是通过后缀表达式得到最终计算结果的算法流程图,其中,当整个后缀表达式遍历完成后,我们的数字栈中只会剩下一个Node元素,这个元素即为最终计算的结果。
4.下面给出一步直接计算表达式的算法流程图:
图4一步直接计算表达式得到结果的算法流程图
图4是一步直接计算表达式得到结果的算法流程图,其核心思想和得到后缀表达式基本类似,不同之处是,如果遍历过程中遇到了数字,将数字入数字栈,而当遇到操作符后,如果优先级小,那么直接从数字栈依次取出两个栈顶数字,进行计算,将计算的结果再次入数字栈。
三、源代码
下面给出计算表达式的原代码,两种方法写在了一个程序里面,其中有个GetHzbdsByExpr的方法,是得到后缀表达式的方法,有个GetResultByListNode的方法,是通过后缀表达式得到计算结果的方法,然后有个GetResultWithOneStep的方法,是一步直接计算结果的方法,都有注释标识。
源代码:
#include"
stdio.h"
conio.h"
string.h"
stdlib.h"
structNode*listNode[100];
/*定义一个长度为100的Node类型的数组,用来存放转换完成的后缀表达式*/
typedefstructNode/*定义Node类型的结构体,用来代表数字和操作符*/
{
charop;
/*操作符的字符*/
intlevel;
/*操作符的优先级*/
floatod;
/*数字的值*/
inttype;
/*Node的类型标识符*/
}Node;
voidinitNode(Node*nd,charc,intle,floatval,intty)/*初始化Node*/
nd->
op=c;
/*操作符的字符,赋值为传过来的字符*/
level=le;
/*操作符的优先级,赋值为传过来的优先级级别*/
od=val;
/*赋值为传过来的浮点数数值*/
type=ty;
/*赋值标识符*/
}
typedefstructMyStack/*定义一个栈的结构体,用来存放操作符和数字*/
Node*listNd[100];
/*定义一个长度为100的node类型的数组,用来当做栈*/
inttop;
/*栈顶索引*/
}MyStack;
voidinitMyStack(MyStack*ms)/*初始化栈*/
ms->
top=0;
/*初始化的时候栈顶指向0*/
intIsEmpty(MyStack*ms)/*判断栈是否为空*/
if(ms->
top==0)
return0;
/*0代表为空*/
return1;
voidPush(Node*nd,MyStack*ms)/*向ms栈中追加一个node类型的nd*/
listNd[ms->
top]=nd;
/*追加node*/
top++;
/*将栈顶索引指向下一项*/
Node*Pop(MyStack*ms)/*从ms栈中取出栈顶的node*/
top!
=0)/*如果栈不为空*/
{
top--;
/*将栈顶索引指向上一项*/
returnms->
top];
/*返回栈顶node*/
}
returnNULL;
/*如果栈为空,那么返回NULL*/
Node*Top(MyStack*ms)/*观察栈顶的node*/
inttop=ms->
top;
/*获得当前的栈顶索引*/
Node*topNode;
/*定义一个node*/
if(top!
=0)
topNode=ms->
listNd[top-1];
/*得到栈顶的Node*/
returntopNode;
/*返回栈顶Node*/
}
else
char*cutStr(char*expr,intbegin,intend)/*截取字符串的方法,从begin开始,截取到end*/
char*result=NULL;
/*定义截取到的结果字符数组*/
intresultCount=0;
/*要截取的字符串的长度*/
resultCount=end-begin+1;
/*截的末尾索引减去起始索引加1即为要截取的长度*/
result=(char*)malloc(sizeof(char)*resultCount+1);
/*多申请一个字节,用于存放结束句'
\0'
*/
if(result==NULL)/*如果没有开辟成功空间*/
printf("
Errormallocmemoryinfunction.\n"
);
/*打印开辟内存空间错误*/
strncpy(result,expr+begin,resultCount);
/*从expr+begin这个地址开始,截取resultCount个字符赋给result*/
result[resultCount]='
;
/*赋值结果字符数组的最后一位为‘\0’*/
returnresult;
voidGetHzbdsByExpr(char*expr)/*得到后缀表达式的方法*/
intindex=0,indexnow,tempindex=0,i=0,listIndex=0;
/*index-主索引;
indexnow-在截取字符串时代表当前索引值;
tempindex-副索引;
i-控制循环;
listIndex-后缀表达式的项编号*/
floattempn;
/*即时用的数字*/
charstr[100]={"
"
};
/*截取字符串时用到的临时存放字符的数字*/
char*c={"
/*主索引遍历时遍历到位置的字符*/
char*tempc={"
/*即时用的字符*/
structMyStack*opStack=(MyStack*)malloc(sizeof(MyStack));
/*定义一个操作符栈,并为之开辟空间*/
structNode*node=(Node*)malloc(sizeof(Node));
/*定义一个Node元素*/
initMyStack(opStack);
/*初始化操作符栈*/
listNode[0]=NULL;
/*清空存放后缀表达式的数组*/
while(index<
strlen(expr))/*主索引开始*/
structNode*tempNode=(Node*)malloc(sizeof(Node));
/*每次循环里面重新定义这些node*/
structNode*topNode=(Node*)malloc(sizeof(Node));
structNode*popNode=(Node*)malloc(sizeof(Node));
c=cutStr(expr,index,index);
/*得到当前索引位置的字符*/
if(*c>
='
0'
&
&
*c<
9'
)
str[0]=*c;
/*把这个字符加到str数组中*/
tempindex=0;
/*要截取的字符的长度*/
indexnow=index+1;
/*从主索引下一个开始继续遍历*/
tempc=cutStr(expr,indexnow,indexnow);
/*主索引的下一个字符*/
while(indexnow<
strlen(expr)&
((*tempc>
)&
(*tempc<
)||(*tempc=='
.'
)))
tempindex=tempindex+1;
/*满足条件,要截取的字符长度加1*/
indexnow=indexnow+1;
/*指向下一个字符*/
str[tempindex]=*tempc;
/*将这个字符追加到一个数组中*/
/*下一个字符*/
str[tempindex+1]='
/*遍历完一个数值之后,数组中数值的下一位赋值为‘0’*/
tempn=atof(&
str[0]);
/*将数组中的数值转成float类型的数字*/
initNode(tempNode,'
?
'
-100,tempn,1);
/*type=1代表node的类型为数字*/
listNode[listIndex]=tempNode;
/*将这个tempNode添加到后缀表达式的listNode中*/
listIndex++;
/*后缀表达式的数组长度加1,指向下一个空位*/
index=index+tempindex+1;
/*整个截取数值的工作结束,将主索引向后移动tempindex+1个位置*/
if(*c=='
+'
||*c=='
-'
initNode(tempNode,*c,1,-100,2);
/*1代表'
和'
的优先级,type=2代表node的类型为操作符,-100为随意赋值给od*/
if(IsEmpty(opStack)==0)
Push(tempNode,opStack);
/*如果字符栈为空,直接入栈*/
index++;
/*主索引自加*/
topNode=Top(opStack);
/*如果字符栈不为空,得到栈顶字符*/
while(IsEmpty(opStack)==1&
tempNode->
level<
=topNode->
level)
popNode=Pop(opStack);
/*如果目前的操作符的优先级小于栈顶操作符的优先级,就将栈顶操作符取出*/
listNode[listIndex]=popNode;
/*将取出的操作符node放入后缀表达式的数组中*/
/*继续观察栈顶操作符*/
/*后缀表达式数字加一位*/
/*当目前的操作符的优先级大于栈顶操作符的优先级时,将目前的操作符入操作符栈*/
*'
/'
%'
initNode(tempNode,*c,2,-100,2);
/*2代表'
、'
的优先级,比'
的优先级高*/
('
initNode(tempNode,*c,-1,-100,2);
/*左小括号的优先级为-1*/
/*左小括号直接入栈*/
)'
topNode=Top(opStack);
/*得到栈顶*/
while(IsEmpty(opStack)==1&
(topNode->
op!
='
))/*观察栈顶,如果栈顶不是左括号*/
/*取出栈顶*/
/*加到后缀表达式中*/
/*继续观察栈顶*/
Pop(opStack);
/*当工作完成后,栈顶一定是一个左括号,直接扔掉*/
['
initNode(tempNode,*c,-2,-100,2);
/*左中括号的优先级为-2*/
/*左中括号直接入栈*/
]'
{'
initNode(tempNode,*c,-3,-100,2);
/*左花括号的优先级为-3*/
/*左花括号直接入栈*/
}'
while(IsEmpty(opStack)==1)/*当遍历的工作做完之后,如果操作符栈不为空*/
popNode=Pop(opStack);
listNode[listIndex]=NULL;
/*当得到后缀表达式之后,将最后一个node的下一位赋空。
*/
Postfixexpressionis:
\n"
/*输出:
“后缀表达式为:
”*/
for(i=0;
i<
listIndex;
i++)
node=listNode[i];
/*遍历后缀表达式中的每一个node*/
if(node->
type==1)/*如果node的type=1,即node是数值,则输出node的数值*/
%.2f|"
node->
od);
type==2)/*如果node的type=2,即node是操作符,则输出node的字符*/
%c|"
op);
floatGetResultByListNode()/*通过后缀表达式得到结果的方法*/
floatresult=0;
/*定义最终计算的结果,用于方法返回*/
inti=0;
/*控制循环*/
floatoda=0,odb=0,odResult=0;
/*oda,odb-栈顶的两个数字,odResult-两个数字的计算结果*/
/*定义一个Node元素并开辟内存空间*/
structMyStack*odStack=(MyStack*)malloc(sizeof(MyStack));
/*定义数字栈并开辟空间*/
initMyStack(odStack);
/*初始化数字栈*/
listNode[i]!
=NULL;
i++)/*遍历后缀表达式中每一个node*/
/*得到第i个node*/
type==1)
Push(node,odStack);
/*如果node的类型是数值,那么入数栈*/
type==2)
structNode*odNode=(Node*)malloc(sizeof(Node));
charc=node->
op;
switch(c)/*判断操作符*/
{
case'
:
oda=Pop(odStack)->
od;
/*从栈顶取出一个数值作为加数*/
odb=Pop(odStack)->
/*再从栈顶取出一个数值为被加数*/
odResult=odb+oda;
/*计算两个数字*/
initNode(odNode,'
-100,odResult,1);
Push(odNode,odStack);
/*将计算结果再次入数栈*/
break;
/*从栈顶取出一个数值作为减数*/
/*再从栈顶取