C语言版科学计算器设计.docx
《C语言版科学计算器设计.docx》由会员分享,可在线阅读,更多相关《C语言版科学计算器设计.docx(16页珍藏版)》请在冰豆网上搜索。
![C语言版科学计算器设计.docx](https://file1.bdocx.com/fileroot1/2022-11/29/7e5282aa-bf39-447a-a690-9e56956403c3/7e5282aa-bf39-447a-a690-9e56956403c31.gif)
C语言版科学计算器设计
科学计算器设计(C语言版)
学校:
学院:
计算机信息工程学院
语言
平台:
作者:
日期:
一、背景和目的
计算器是现代日常生活中使用较为频繁的工具之一,常用的计算器有简易版和科学计算器两种模式。
简易版的计算器不支持表达式运算,每次只能输入一个数据或者运算符来计算,而科学计算器除了容纳简易版计算器的功能外,还支持表达式运算,用户可以输入一个合法的算术表达式来得到所需的结果。
常用的算术表达式有三种,前缀表达式,中缀表达式和后缀表达式。
中缀表达式:
我们平时书写的表达式就是中缀表达式,形如(a+b)*(c+d),事实上是运算表达式形成的树的中序遍历,特点是用括号来描述优先级。
后缀表达式:
也叫逆波兰表达式,事实上是算数表达式形成的树的后序遍历。
中缀表达式(a+b)*(c+d)的后缀表达式是ab+cd+*,它的特点就是遇到运算符就立刻进行运算。
前缀表达式:
算数表达式形成的树的前序遍历。
日常所书写的是中缀表达式,但是计算机内部是用后缀表达式计算,所以此程序的用户使用中缀表达式作为输入,程序将中缀表达式转化为后缀表达式后再进行运算并输出结果。
由于今后工作将使用C语言进行开发,而C语言是一个功能强大并且很灵活的语言,为复习和巩固C编程,故决定用C语言编写一个科学计算器。
本次开发采用C语言,以面对过程思想进行开发,使用的数据结构有队列和栈。
二、模块设计
本次开发,使用的控制台输入,并直接在控制台输出。
科学计算器的功能组件如下:
三、详细设计
宏:
#defineTESTﻩﻩﻩ//表示测试阶段
#defineMAX_SIZE 100//表达式长度
#defineLBRACKET0ﻩﻩ//左括号
#define RBRACKET1ﻩ//右括号
#defineADD2ﻩﻩ//加
#define SUB 3ﻩ//减
#defineMUL4ﻩ//乘
#define DIV5ﻩ//乘
#defineINT6ﻩﻩ//整数
#defineDOUBLE7ﻩﻩ//浮点数
数据结构:
表达式节点
structExprNode{
intn;ﻩ//表达式节点类型
doublep;ﻩ//表达式节点数据
};
中缀表达式:
structExprNodeinfixExpr[MAX_SIZE];
intinfixLen;
后缀表达式:
structExprNodesuffixExpr[MAX_SIZE];
intsuffixLen;
后缀转换栈:
inttransStack[MAX_SIZE];
inttransTop;
后缀表达式运算栈:
structExprNode calcuStack[MAX_SIZE];
intcalcuTop;
函数过程:
__inlineintget_char( char*c)
缓冲变量无字符则读入字符
读入成功返回0,否者返回-1
intinput_expr(void)
读入表达式
若输入非法字符则返回-1,否则返回0
intpri(int a,intb)
优先级计算
若a优先于b则返回-1,否则返回0
inttrans_expr(void)
中缀表达式转换为后缀表达式
括号不匹配返回-1,否则返回0
__inline int maxn(inta, intb )
求最大值
structExprNode calcu(structExprNode*a,struct ExprNode*b,intc )
计算a和b做c运算的结果
int calcu_expr(void)
计算后缀表达式
表达式计算失败返回-1,否则为0
ﻩ
voidshow(void)
输出运算结果
代码:
#include<stdio.h>
//#defineTESTﻩ//表示测试阶段
#defineMAX_SIZE100ﻩ//表达式长度
#defineLBRACKET0ﻩ//左括号
#defineRBRACKET 1ﻩ//右括号
#defineADD2ﻩﻩﻩ//加
#defineSUB 3ﻩ//减
#define MUL4ﻩ//乘
#define DIV5ﻩﻩ//乘
#defineINT 6ﻩﻩ//整数
#define DOUBLE 7ﻩ//浮点数
structExprNode{
intn;ﻩ//表达式节点类型
ﻩdoublep;ﻩ//表达式节点数据
};
structExprNodeinfixExpr[MAX_SIZE];//中缀表达式
intinfixLen;
structExprNodesuffixExpr[MAX_SIZE];ﻩ//后缀表达式
intsuffixLen;
inttransStack[MAX_SIZE];ﻩﻩ//后缀转换栈
inttransTop;
struct ExprNode calcuStack[MAX_SIZE];//后缀表达式运算栈
intcalcuTop;
//缓冲变量无字符则读入字符
//读入成功返回0,否者返回-1
__inlineintget_char(char *c)
{
if (*c=='\0')returnscanf("%c",c);
return0;
}
//读入表达式
//若输入非法字符则返回-1,否则返回0
intinput_expr(void )
{
ﻩchar c=0;
int flag= 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
ﻩ{
ﻩﻩﻩ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;
case MUL:
ﻩcaseDIV:
p[i] =2; break;
ﻩﻩ
ﻩﻩ}
ﻩ}
ﻩif( p[0]>= p[1])
{
ﻩreturn-1;
ﻩ}
ﻩreturn0;
}
//中缀表达式转换为后缀表达式
//括号不匹配返回-1,否则返回0
int trans_expr(void)
{
inti, error=0,flag;
ﻩsuffixLen=0;
transTop =0;
ﻩfor ( i =0;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;
ﻩ}
else if(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;
ﻩreturn b;
}
//计算a和b做c运算的结果
structExprNodecalcu( structExprNode*a, structExprNode*b,intc)
{
structExprNoder;
int i,j;
r.n=maxn(a->n,b->n);
ﻩswitch ( c)
ﻩ{
caseADD:
r.p= (a->p)+(b->p); break;
ﻩcase SUB:
r.p=(a->p)-(b->p);break;
caseMUL:
r.p= (a->p)*(b->p);break;
case DIV:
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;
struct ExprNodea[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;
ﻩreturn error;
}
//输出运算结果
voidshow(void )
{
ﻩint i,n;
#ifndefTEST
ﻩfor( i=0; i
ﻩ{
ﻩswitch(infixExpr[i].n)
ﻩ{
ﻩcaseLBRACKET:
printf( "( ");break;
ﻩcase RBRACKET:
printf( ")"); break;
ﻩcase ADD:
printf("+");break;
ﻩcaseSUB:
printf( "- ");break;
ﻩﻩcaseMUL:
printf("* "); break;
ﻩcaseDIV:
printf( "/"); break;
case INT:
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);
return 0;
}