科学计算器设计.docx
《科学计算器设计.docx》由会员分享,可在线阅读,更多相关《科学计算器设计.docx(18页珍藏版)》请在冰豆网上搜索。
科学计算器设计
科学计算器设计(C语言版)
学校:
学院:
计算机信息工程学院
语言
平台:
作者:
日期:
一、背景和目的
计算器是现代日常生活中使用较为频繁的工具之一,常用的计算器有简易版和科学计算器两种模式.简易版的计算器不支持表达式运算,每次只能输入一个数据或者运算符来计算,而科学计算器除了容纳简易版计算器的功能外,还支持表达式运算,用户可以输入一个合法的算术表达式来得到所需的结果。
常用的算术表达式有三种,前缀表达式,中缀表达式和后缀表达式。
中缀表达式:
我们平时书写的表达式就是中缀表达式,形如(a+b)*(c+d),事实上是运算表达式形成的树的中序遍历,特点是用括号来描述优先级。
后缀表达式:
也叫逆波兰表达式,事实上是算数表达式形成的树的后序遍历.中缀表达式(a+b)*(c+d)的后缀表达式是ab+cd+*,它的特点就是遇到运算符就立刻进行运算。
前缀表达式:
算数表达式形成的树的前序遍历。
日常所书写的是中缀表达式,但是计算机内部是用后缀表达式计算,所以此程序的用户使用中缀表达式作为输入,程序将中缀表达式转化为后缀表达式后再进行运算并输出结果。
由于今后工作将使用C语言进行开发,而C语言是一个功能强大并且很灵活的语言,为复习和巩固C编程,故决定用C语言编写一个科学计算器。
本次开发采用C语言,以面对过程思想进行开发,使用的数据结构有队列和栈。
二、模块设计
本次开发,使用的控制台输入,并直接在控制台输出。
科学计算器的功能组件如下:
中缀表达式转后缀表达式
trans_expr()
输入表达式
input_expr()
当读到数字直接送至输出队列中
当读到运算符T时
a:
将栈中所有优先级高于或等于T的运算符弹出,送至输出队列
b:
T进栈
读到左括号时总是将它压入栈中
读到右括号时,将靠近栈顶的第一个左括号上面的运算符依次全部弹出,送至输出队列,再丢弃左括号
计算后缀表达式
calcu_expr()
建立一个栈
从左到右读后缀表达式,读到数字就将它压入栈S中,读到运算符则从栈中依次弹出两个数X和Y,然后以“X运算符Y”的形式计算出结果,再将结果压入栈S
如果后缀表达式未读完,就重复上述过程,最后输出栈顶数值则为结束
输出结果
转换成功
Y
N
三、详细设计
宏:
#defineTEST//表示测试阶段
#defineMAX_SIZE100//表达式长度
#defineLBRACKET0//左括号
#defineRBRACKET1//右括号
#defineADD2//加
#defineSUB3//减
#defineMUL4//乘
#defineDIV5//乘
#defineINT6//整数
#defineDOUBLE7//浮点数
数据结构:
表达式节点
structExprNode{
intn;//表达式节点类型
doublep;//表达式节点数据
};
中缀表达式:
structExprNodeinfixExpr[MAX_SIZE];
intinfixLen;
后缀表达式:
structExprNodesuffixExpr[MAX_SIZE];
intsuffixLen;
后缀转换栈:
inttransStack[MAX_SIZE];
inttransTop;
后缀表达式运算栈:
structExprNodecalcuStack[MAX_SIZE];
intcalcuTop;
函数过程:
__inlineintget_char(char*c)
缓冲变量无字符则读入字符
读入成功返回0,否者返回—1
intinput_expr(void)
读入表达式
若输入非法字符则返回-1,否则返回0
intpri(inta,intb)
优先级计算
若a优先于b则返回—1,否则返回0
inttrans_expr(void)
中缀表达式转换为后缀表达式
括号不匹配返回-1,否则返回0
__inlineintmaxn(inta,intb)
求最大值
structExprNodecalcu(structExprNode*a,structExprNode*b,intc)
计算a和b做c运算的结果
intcalcu_expr(void)
计算后缀表达式
表达式计算失败返回—1,否则为0
voidshow(void)
输出运算结果
代码:
#includeh〉
//#defineTEST//表示测试阶段
#defineMAX_SIZE100//表达式长度
#defineLBRACKET0//左括号
#defineRBRACKET1//右括号
#defineADD2//加
#defineSUB3//减
#defineMUL4//乘
#defineDIV5//乘
#defineINT6//整数
#defineDOUBLE7//浮点数
structExprNode{
intn;//表达式节点类型
doublep;//表达式节点数据
};
structExprNodeinfixExpr[MAX_SIZE];//中缀表达式
intinfixLen;
structExprNodesuffixExpr[MAX_SIZE];//后缀表达式
intsuffixLen;
inttransStack[MAX_SIZE];//后缀转换栈
inttransTop;
structExprNodecalcuStack[MAX_SIZE];//后缀表达式运算栈
intcalcuTop;
//缓冲变量无字符则读入字符
//读入成功返回0,否者返回—1
__inlineintget_char(char*c)
{
if(*c=='\0')returnscanf(”%c",c);
return0;
}
//读入表达式
//若输入非法字符则返回-1,否则返回0
intinput_expr(void)
{
charc=0;
intflag=0,error=0,s,i;
infixLen=0;
while(get_char(&c)!
=-1)
{
switch(c)
{
case’\n’:
flag=—1;break;
case'(’:
infixExpr[infixLen++].n=LBRACKET;c=0;break;
case')':
infixExpr[infixLen++].n=RBRACKET;c=0;break;
case'+’:
infixExpr[infixLen++]。
n=ADD;c=0;break;
case'-’:
infixExpr[infixLen++]。
n=SUB;c=0;break;
case’*':
infixExpr[infixLen++]。
n=MUL;c=0;break;
case’/':
infixExpr[infixLen++].n=DIV;c=0;break;
default:
if(c>=’0’&&c<='9'||c==’。
’)
{
if(c!
=’。
’)
{
infixExpr[infixLen]。
n=INT;
infixExpr[infixLen]。
p=c—'0';
s=0;
}
else
{
infixExpr[infixLen]。
n=DOUBLE;
infixExpr[infixLen]。
p=0;
s=1;
}
c=0;
while(get_char(&c)!
=—1)
{
if(c〉='0’&&c<='9’)
{
infixExpr[infixLen]。
p=infixExpr[infixLen].p*10+(c—'0’);
if(s)s++;
c=0;
}
elseif(c==’。
')
{
if(s)
{
error=-1;
}
else
{
infixExpr[infixLen].n=DOUBLE;
s++;
}
c=0;
}
elsebreak;
}
if(infixExpr[infixLen].n==DOUBLE)
{
for(i=1;i〈s;i++)
{
infixExpr[infixLen]。
p/=10;
}
}
infixLen++;
}
else
{
error=-1;
c=0;
}
break;
}
if(flag)break;
};
returnerror;
}
//优先级计算
//若a优先于b则返回—1,否则返回0
intpri(inta,intb)
{
intc[2],p[2],i;
c[0]=a;c[1]=b;
for(i=0;i〈2;i++)
{
switch(c[i])
{
caseLBRACKET:
p[i]=0;break;
caseADD:
caseSUB:
p[i]=1;break;
caseMUL:
caseDIV:
p[i]=2;break;
}
}
if(p[0]>=p[1])
{
return—1;
}
return0;
}
//中缀表达式转换为后缀表达式
//括号不匹配返回—1,否则返回0
inttrans_expr(void)
{
inti,error=0,flag;
suffixLen=0;
transTop=0;
for(i=0;i〈infixLen;i++)
{
if(infixExpr[i]。
n>=INT)//当读到数字直接送至输出队列中
{
suffixExpr[suffixLen++]=infixExpr[i];
}
elseif(infixExpr[i].n〉RBRACKET)//当读入运算符时
{
//将栈中所有优先级高于或等于T的运算符弹出,送至输出队列
while(transTop>0)
{
if(pri(transStack[transTop-1],infixExpr[i].n))
{
suffixExpr[suffixLen++].n=transStack[-—transTop];
}
elsebreak;
}
//再把运算符入栈
transStack[transTop++]=infixExpr[i]。
n;
}
elseif(infixExpr[i].n==LBRACKET)//读到左括号时总是将它压入栈中
{
transStack[transTop++]=infixExpr[i].n;
}
else//读到右括号时
{
flag=—1;
//将靠近栈顶的第一个左括号上面的运算符依次全部弹出,送至输出队列
while(transTop〉0)
{
if(transStack[transTop-1]==LBRACKET)
{
flag=0;
break;
}
suffixExpr[suffixLen++].n=transStack[——transTop];
}
//再丢弃左括号
if(flag)error=—1;
elsetransTop--;
}
}
while(transTop〉0)
{
if(transStack[transTop—1]==LBRACKET)
{
error=—1;
}
suffixExpr[suffixLen++].n=transStack[—-transTop];
}
//在测试阶段输出后缀表达式
#ifdefTEST
for(i=0;i{
switch(suffixExpr[i]。
n)
{
caseADD:
printf("+”);break;
caseSUB:
printf("-”);break;
caseMUL:
printf("*”);break;
caseDIV:
printf(”/”);break;
caseINT:
flag=suffixExpr[i]。
p;printf(”%d”,flag);break;
caseDOUBLE:
printf(”%lf”,suffixExpr[i]。
p);break;
}
}
#endif
returnerror;
}
//求最大值
__inlineintmaxn(inta,intb)
{
if(a>=b)returna;
returnb;
}
//计算a和b做c运算的结果
structExprNodecalcu(structExprNode*a,structExprNode*b,intc)
{
structExprNoder;
inti,j;
r.n=maxn(a—〉n,b->n);
switch(c)
{
caseADD:
r.p=(a-〉p)+(b->p);break;
caseSUB:
r.p=(a—>p)-(b—>p);break;
caseMUL:
r。
p=(a—〉p)*(b—>p);break;
caseDIV:
r.p=(a->p)/(b->p);
if(r。
n==INT)
{
i=a-〉p;
j=b->p;
if(i%j)r。
n=DOUBLE;
}
break;
}
returnr;
}
//计算后缀表达式
//表达式计算失败返回—1,否则为0
intcalcu_expr(void)
{
inti,j,error=0;
structExprNodea[2],r;
calcuTop=0;
for(i=0;i〈suffixLen&&!
error;i++)
{
if(suffixExpr[i]。
n〉=INT)//读到数字就将它压入栈S中
{
calcuStack[calcuTop++]=suffixExpr[i];
}
else//读到运算符
{
//从栈中依次弹出两个数X和Y
for(j=0;j〈2;j++)
{
if(calcuTop)a[j]=calcuStack[--calcuTop];
elseerror=—1;
}
//以”X运算符Y”的形式计算出结果,再将结果压入栈S
if(!
error)
{
calcuStack[calcuTop++]=calcu(&a[1],&a[0],suffixExpr[i].n);
}
}
}
if(calcuTop!
=1)error=—1;
returnerror;
}
//输出运算结果
voidshow(void)
{
inti,n;
#ifndefTEST
for(i=0;i〈suffixLen;i++)
{
switch(infixExpr[i]。
n)
{
caseLBRACKET:
printf(”(”);break;
caseRBRACKET:
printf(”)");break;
caseADD:
printf("+”);break;
caseSUB:
printf("-”);break;
caseMUL:
printf(”*”);break;
caseDIV:
printf("/”);break;
caseINT:
n=infixExpr[i]。
p;printf(”%d",n);break;
caseDOUBLE:
printf(”%lf”,infixExpr[i].p);break;
}
}
#endif
if(calcuStack[0]。
n==INT)
{
n=calcuStack[0].p;
printf(”=%d\n”,n);
}
else
{
printf("=%lf\n",calcuStack[0].p);
}
}
intmain(intargc,charargv[])
{
do
{
if(input_expr())
{
printf(”请输入正确的表达式!
\n");
continue;
}
if(trans_expr()!
=—1&&calcu_expr()!
=-1)
{
show();
}
else
{
printf("请输入正确的表达式!
\n");
}
}while
(1);
return0;
}