}
return0;
}
流程图如图如下:
2、匹配函数(pipei)
本函数从主函数接收所输入的字符数组,从第一个开始对字符逐个扫描。
遇到左括号时,将左括号进栈,遇到右括号时将当前栈顶元素出栈。
直到所有元素扫描完成后,若栈内无元素则括号是匹配的,否则就是不匹配的。
流程图如下:
3、后缀表达式转换trans(数值串用数组储存并用#隔开,运算符用栈)
先按运算符的优先级设定其计算的先后顺序,用结构体储存。
在表达式括号匹配的情况下,仍然从头开始扫描,栈顶元素初始为“=”,对字符串的各字符逐个扫描,遇到运算符就将其与栈顶运算符优先级进行比较,若小于栈顶运算符优先级,则将该运算符进栈。
若相等则退栈。
若大于,则退栈并将该运算符放到后缀表达式中。
如果扫描到的是数字,则将其直接进栈并用“#”隔开,直到最后,将栈内所有元素均放入后缀字符串poltexp中
流程图如下:
4、对后缀表达式进行计算compvalue(char*p)
数据存储:
栈,用来存储计算机过程值和结果的算法仍然是要逐个扫描分别将前两个数字转化成数值后将其进栈,当读取到运算符时,对当前栈最顶端的两个数进行该运算符的运算,并把结果放入栈顶为下次计算提供数据,直到后缀表达式扫描结束时将栈顶元素值返回。
流程图如下:
3.调试分析
问题一:
多次计算错误
在代码初步编完并初次运行后,对于第一个表达是可以正常计算,但对于以后的各个表达式计算的结果皆不正确,仔细翻看代码后发现,原来在存储表达式的字符串在第一次输入后没有清空对以后各次计算造成了误差,因此只需在主函数中,在每次计算结束后,用memset函数把定义的字符串清空即可。
问题二:
指数运算指数的指数错误
在测试指数计算时对于指数的指数计算错误,结果仍为一阶指数的值。
首先认定错误出现在指数运算的定义中,查看后发现在对指数计算取完数值后没有将栈顶指针加一,这将导致在下一次指数运算时取的数值仍是当前栈顶元素的值。
因此,只需将栈顶元素指针减一即可,修改完后的代码为:
case'^':
a=st.data[st.top];
st.top--;
b=st.data[st.top];
st.top--;
st.data[++st.top]=pow(b,a);
break;
问题三:
对于正负数的判断
为了能使计算时正负数能够被识别,即+3+5或-2+3都能够正确计算,在测试时查看后缀表达式即可发现只需在取负的数字前加上0即可达到正负数的计算的目的。
对于正负数的判断又分两种情况,即表达式的开头或括号内的开头。
因此,就要对表达式开头和括号内开头的字符进行判断,添加后的代码为;
{
/*************对正数和负数处理***********/
if(*exp=='-'||*exp=='+')
{
exp--;
if((*exp=='(')||postexp[0]=='\0')
{
postexp[i++]='0';
postexp[i++]='#';
exp++;
}
elseexp++;
}
4.总结与体会
本次程序设计由赵靖老师指导、组长带领我们完成的,前后历时三个星期,我们三人接到命题后讨论决定分别做主程序main.cpp和子程序trans、compvalue。
最后组合并不断调试,发现了很多漏洞和问题,我们一一分析并解决,同时为计算器扩展了很多功能,而很多问题都是我们在一起讨论总结出来的,这我们认识到一人计短,二人计长,不管人与人的编程能力有多大的区别,但是只要有较好的编程思想和算法,一样可以为整个团队解决问题。
这次课程设计提高我们了分析和解决问题的能力,也让我们认识到了团队合作的重要性。
5、代码清单
1.匹配函数:
intpipei(charexp[])
{
inti=0;
chare;
sqstack*st;
initstack(st);
while(exp[i]!
='\0')
{
if(exp[i]=='(')//为左括号时进栈
push(st,exp[i]);
elseif
(exp[i]==')')//为右括号时
{
if(Gettop(st,e)==1)
{
if(e!
='(')
return0;//括号不匹配时返回
elsepop(st,e);//将栈顶元素出栈
}
elsereturn(0);
}
i++;//继续处理其他字符
}
if(st->top==-1)return
(1);//栈为空时
elsereturn(0);
}
2.后缀表达式转换函数:
voidtrans(char*exp,charpostexp[])//中缀转后缀
{
struct
{
chardata[maxsize];//存放运算符
inttop;//栈指针
}op;//运算符栈
inti=0;//i为后缀表达式的标号
op.top=-1;
op.top++;
op.data[op.top]='=';//将=进栈
while(*exp!
='\0')
{
if(!
Inop(*exp))//不是运算符时即为数字时
{
while((*exp>='0'&&*exp<='9')||*exp=='.')
{
postexp[i++]=*exp;//为数字时存放在后缀表达式里
exp++;
}
postexp[i++]='#';//数值串结束
}
else
{
/*************对正数和负数处理***********/
if(*exp=='-'||*exp=='+')
{
exp--;
if((*exp=='(')||postexp[0]=='\0')
{
postexp[i++]='0';
postexp[i++]='#';
exp++;
}
elseexp++;
}
switch(Precede(op.data[op.top],*exp))
{
case-1:
//op运算级低于exp
op.top++;
op.data[op.top]=*exp;
exp++;
break;
case0:
op.top--;
exp++;
break;
case1:
postexp[i++]=op.data[op.top];
op.top--;
break;
}
}
}
while(op.data[op.top]!
='=')
{
postexp[i++]=op.data[op.top];
op.top--;
}
postexp[i]='\0';
}
3.表达式计算:
/***********计算后缀表达式值*************/
floatcompvalue(char*postexp)
{
struct
{
doubledata[maxsize];//计算的结果
inttop;//栈指针
}st;//定义数值栈
doubled,a,b,c,f;//中间变量
intpoint=0,zhi=1,jiech=1;
st.top=-1;
st.data[st.top]=0;
while(*postexp!
='\0')//后缀不为空时扫描表达式
{
switch(*postexp)//判断后缀式字符
{
case'+':
a=st.data[st.top];//取数值a
st.top--;
b=st.data[st.top];
//cout<<"b="<
st.top--;
c=a+b;
st.top++;
st.data[st.top]=c;//将结果进栈
break;
case'-':
a=st.data[st.top];
st.top--;
b=st.data[st.top];
st.top--;
c=b-a;
st.top++;
st.data[st.top]=c;
break;
case'*':
a=st.data[st.top];
st.top--;
b=st.data[st.top];
st.top--;
c=b*a;
st.top++;
st.data[st.top]=c;
break;
case'/':
a=st.data[st.top];
st.top--;
b=st.data[st.top];
st.top--;
if(a!
=0)//判断除以零无意义
{
c=b/a;
st.top++;
st.data[st.top]=c;
}
else
{
cout<<"\n\t除零错误!
\n"<exit(0);
}
break;
case'!
':
a=st.data[st.top];
for(intj=1;j<=a;j++)
jiech=jiech*j;
st.data[st.top]=jiech;
break;
case'^':
a=st.data[st.top];
st.top--;
b=st.data[st.top];
st.top--;
st.data[++st.top]=pow(b,a);
break;
default:
//后缀字符为数字
d=0;
f=0;
while((*postexp>='0'&&*postexp<='9')||*postexp=='.')//处理连续数字字符
{
if(*postexp=='.')
{
point=1;
postexp++;
}
else;
if(point==0)
{
d=10*d+*postexp-'0';//将字符转为数字
postexp++;
}
else
{
//printf("%d\t",pow(10,zhi));
f=f+(*postexp-'0')/pow(10,zhi);
zhi++;
postexp++;
}
}
point=0;//下一个数要重新验证
zhi=1;
st.top++;
st.data[st.top]=d+f;//将结果进栈
break;
}
postexp++;
}
return(st.data[st.top]);
}
评语:
成绩:
签名:
年月日