实验内容:利用表达式求值思想,完成简易计算器的开发。
实验要求:
stack是存放数字的栈,opstack是存放运算符的栈。
判断栈是否为空,EmptyTOS的值为-1。
int isEmpety(stack s){
return s->top == EmptyTOS;
}
创建一个存放数字的栈。MaxSize的值为100,即这个栈最多能容纳100个
数字。
stack createStack(){
stack s;
s = (Stack*)malloc(sizeof(Stack));
if(s == NULL)
printf("out of space!");
s->operand = (double*)malloc(sizeof(double)*MaxSize);
if(s->operand == NULL)
printf("out of space!");
makeEmpety(s);
s->size = MaxSize;
return s;
}
使栈为空。本质上就是改变栈顶的位置,若栈里原先有数据,再次存放就
会覆盖。
void makeEmpety(stack s){
s->top = EmptyTOS;
}
将数字放入栈。先判断这个栈是否为满,若满,则不放入;反之,放入。
void push(double x , stack s){
if(isFull(s))//top在判断时自增
printf("Full stack!");
else
s->operand[s->top] = x;
}
弹出栈顶的元素。即改变栈顶位置,继续入栈就会覆盖。
void pop(stack s){
if(isEmpety(s))
printf("Empty stack!");
else
s->top--;//下次输入就覆盖掉
}
获得栈顶的元素。
double top(stack s){
if(!isEmpety(s))
return s->operand[s->top];
printf("Empty stack!!!");
return 0;
}
判断栈是否为满。
int isFull(stack s){
return s->top++ == s->size;
}
以上是关于栈的相关函数,这里我只列举了数字栈的函数,但其实符号栈
也是大同小异,各位朋友可以自行改写。以下则是讲解计算器功能逻辑的相关函
数。
实现加减乘除计算操作的函数。
double operate(double a,double b,char c){
double result;
switch(c){
case '+':
result = a+b;
break;
case '-':
result = b-a;
break;
case '*':
result = a*b;
break;
case '/':
if(a == 0){
setCheck(-1);
}
else
result = b/a;
break;
}
return result;
}
比较一串表达式中运算符号的优先级。例如:乘除优先于加减,括号优先于
其他,同级别运算符左边优先于右边。
char compare(char c1,char c2){
if(c1=='+'){
switch(c2){
case '+': return '>';break;
case '-': return '>';break;
case '*': return '<';break;
case '/': return '<';break;
case '(': return '<';break;
case ')': return '>';break;
case '#': return '>';break;
}
}
else if(c1=='-'){
switch(c2){
case '+': return '>';break;
case '-': return '>';break;
case '*': return '<';break;
case '/': return '<';break;
case '(': return '<';break;
case ')': return '>';break;
case '#': return '>';break;
}
}
else if(c1=='*'){
switch(c2){
case '+': return '>';break;
case '-': return '>';break;
case '*': return '>';break;
case '/': return '>';break;
case '(': return '<';break;
case ')': return '>';break;
case '#': return '>';break;
}
}
else if(c1=='/'){
switch(c2){
case '+': return '>';break;
case '-': return '>';break;
case '*': return '>';break;
case '/': return '>';break;
case '(': return '<';break;
case ')': return '>';break;
case '#': return '>';break;
}
}
else if(c1=='('){
switch(c2){
case '+': return '<';break;
case '-': return '<';break;
case '*': return '<';break;
case '/': return '<';break;
case '(': return '<';break;
case ')': return '=';break;
case '#': return '!';break;
}
}
else if(c1==')'){
switch(c2){
case '+': return '>';break;
case '-': return '>';break;
case '*': return '>';break;
case '/': return '>';break;
case '(': return '!';break;
case ')': return '>';break;
case '#': return '>';break;
}
}
else if(c1=='#'){
switch(c2){
case '+': return '<';break;
case '-': return '<';break;
case '*': return '<';break;
case '/': return '<';break;
case '(': return '<';break;
case ')': return '!';break;
case '#': return '=';break;
}
}
}
判断输入的是否是运算符。
bool input(char a){
if(a =='+' || a =='-' || a =='*' || a =='/' || a =='(' || a ==')' || a =='#')
return true;
else
return false;
}
对输入的表达式进行计算。
首先将表达式转换为字符串,对每个字符依次进行判断,若是数字,则入
数字栈;若是运算符,则入符号栈。temp作为临时变量,代表当前字符。然后
比较符号栈栈顶的符号与当前符号的运算优先级。若栈顶运算符先级更高,直接
计算,即从数字栈弹出栈顶的两个元素,再从符号栈中弹出栈顶元素,利用
operate()函数计算,将计算结果放入数字栈栈顶;若栈顶运算符优先级更低,
将当前temp代表的运算符入栈,继续向下读取字符串;若栈顶运算符优先级与
当前运算符相同,则弹出符号栈栈顶运算符。
double evaluate(QString qs,stack s,opstack ops){
int pos = 0,n = qs.length();
double in,a,b;
QString num = "";
char temp,c;
while(pos < n){
temp = qs.at(pos).toLatin1();
if(input(temp)==false){
num.append(temp);
pos++;
}
else {
if(num != ""){
in = num.toDouble();
num = "";
push(in,s);
}
switch(compare(ops->operatoR[ops->top],temp)){
case '<':
pos++;
push2(temp,ops);
break;
case '=':
pos++;
pop2(ops);
break;
case '>':
a = topAndPop(s);
b = topAndPop(s);
c = top2(ops);
pop2(ops);
push(operate(a,b,c),s);
break;
}
}
}
return top(s);
}
简单的一个运算表达式。
我在github上做的开源。