#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include"stack.h"
#include"genlib.h"
#include"simpio.h"
void calcul(stackADT S);//计算器主程序
static void Help(void);//显示帮助函数
int privilege(char a);//显示运算优先级
stackADT alf;
int main(){
stackADT operandStack;
string line;
char ch;//用来输入提示命令符
operandStack = NewStack();//创建一个新的栈 ,用来存储需要计算的数字,先进后出
printf("-------------------------------------------------------------------------------\n");
printf("Welcome To our OWN calculator!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
printf("-------------------------------------------------------------------------------\n");
printf("|our own calculator have a strong support of mathmatics, if you first use this|\n|calculator, you'd beter read the help message first!!! |\n");
printf("| |\n");
printf("|Q-Quit the program |\n");
printf("|H-Display the help message |\n");
printf("|D-goto the calculator |\n");
printf("-------------------------------------------------------------------------------\n");
scanf("%c",&ch);//输入命令
getchar();//用来存储回车符,经常用在输入一个字符之后
//程序主历程,用来判断用户想要做些什么
while(ch!='Q'){
if(ch=='Q'){
return 0;break;
}
if(ch=='H'){
Help();
scanf("%c",&ch);
getchar();
continue;
}
calcul(operandStack);
getchar();
}
}
/*用来进行计算器运算的主程序*/
void calcul(stackADT S){
double lhs, rhs, result;//因为我们计算通常是两个数进行计算,所以使用lhs和rhs表示我们计算的两个数,result表示两个数计算的结果
double num;
char *op=malloc(sizeof(char)*40);//输入一行算数表达式,用字符串变量存储 (包含运算符和运算数字)
char opera[20];//用来存储我们现在的 运算符(事实上这个也可以看成是一个栈)
// char tmp;//中间变量,无用处
int i=0,j=0,top=0;//中间变量,top事实上是一个存储运算符的栈的最顶端
printf("please input the line\n");
scanf("%s",op);//输入我们的算术表达式
//tmp = op[i];
while(op[i]!='='&&op[i]!='\n'){//当我们不是等于号的时候进行运算
//tmp = op[i];
if(op[i]=='+'||op[i]=='-'||op[i]=='*'||op[i]=='/'||op[i]=='s'||op[i]=='%'||op[i]=='^'||op[i]=='c'||op[i]=='('||op[i]==')'){
while(privilege(opera[top-1])>=privilege(op[i])&&opera[top-1]!='('){//计算优先级,当我们下一个运算符比上一个运算符优先级低的时候,对前面两个数进行计算
lhs=Pop(S);//找到我们已经压到栈里面的两个数,取出运算符进行计算
rhs=Pop(S);
switch(opera[top-1]){//通过运算符看看我们需要进行什么运算 ,每次运算将结果重新压入到栈里面
case '+':result=rhs+lhs;Push(S,result);top--;break;
case '-':result=rhs-lhs;Push(S,result);top--;break;
case '*':result=rhs*lhs;Push(S,result);top--;break;
case '/':result=rhs/lhs;Push(S,result);top--;break;
case '%':result=(int)rhs%(int)lhs;Push(S,result);top--;break;
case '^':result=pow(rhs,lhs);Push(S,result);top--;break;
case 's':result=sin(lhs);Push(S,rhs);Push(S,result);top--;break;
case 'c':result=cos(lhs);Push(S,rhs);Push(S,result);top--;break;
case '(':Push(S,rhs);Push(S,lhs);break;
case ')':Push(S,rhs);Push(S,lhs);top--;//当我们遇到'('的时候,我们什么都不需要做,当我们遇到’)‘的时候,要把之前一直到’(‘中间的数据都计算掉
while(opera[top-1]!='('){
lhs=Pop(S);
rhs=Pop(S);
switch(opera[top-1]){
case '+':result=rhs+lhs;Push(S,result);top--;break;
case '-':result=rhs-lhs;Push(S,result);top--;break;
case '*':result=rhs*lhs;Push(S,result);top--;break;
case '/':result=rhs/lhs;Push(S,result);top--;break;
case '%':result=(int)rhs%(int)lhs;Push(S,result);top--;break;
case '^':result=pow(rhs,lhs);Push(S,result);top--;break;
case 's':result=sin(lhs);Push(S,rhs);Push(S,result);top--;break;
case 'c':result=cos(lhs);Push(S,rhs);Push(S,result);top--;break;
}
}
top--;
break;
}
}
/*当我们遇到’)‘运算符的时候,是直接计算前面的运算的,所以我们会多出()一共两个符号,所以在这里我们要去除掉,
比如我们计算(3+s2)*4+5的时候,遇到)时,直接计算s2+3,然后就跳出循环了,此时栈里面还有()*+符号,我们要把括号去掉*/
if(opera[top-1]==')'){
top-=2;
}
//当我们遇到运算符的时候先压入到栈里面
opera[top]=op[i];
top++;
}
//将数据压入到栈里面
else if(('0'<=op[i]&&op[i]<='9')||op[i]=='.'){
num = 0; j = 1;
while(('0'<=op[i]&&op[i]<='9')||op[i]=='.'){
if(op[i]!='.'&&j <= 1){
num=num*10+(op[i]-'0');
i++;
}
else{
if(op[i]=='.'){
i++;
num+=(op[i]-'0')/pow(10,j);
i++;j++;
}
else{
num+=(op[i]-'0')/pow(10,j);
i++;j++;
}
}
}
Push(S,num);
i--;
}
i++;
}
//把剩余的数据消化掉,因为栈里面很可能还有数据没有计算
while(top > 0){
lhs=Pop(S);
rhs=Pop(S);
switch(opera[top-1]){
case '+':result=rhs+lhs;Push(S,result);top--;break;
case '-':result=rhs-lhs;Push(S,result);top--;break;
case '*':result=rhs*lhs;Push(S,result);top--;break;
case '/':result=rhs/lhs;Push(S,result);top--;break;
case '%':result=(int)rhs%(int)lhs;Push(S,result);top--;break;
case '^':result=pow(rhs,lhs);Push(S,result);top--;break;
case 's':result=sin(lhs);Push(S,rhs);Push(S,result);top--;break;
case 'c':result=cos(lhs);Push(S,rhs);Push(S,result);top--;break;
case '(':Push(S,rhs);Push(S,lhs);break;
case ')':Push(S,rhs);Push(S,lhs);top--;
while(opera[top-1]!='('){
lhs=Pop(S);
rhs=Pop(S);
switch(opera[top-1]){
case '+':result=rhs+lhs;Push(S,result);top--;break;
case '-':result=rhs-lhs;Push(S,result);top--;break;
case '*':result=rhs*lhs;Push(S,result);top--;break;
case '/':result=rhs/lhs;Push(S,result);top--;break;
case '%':result=(int)rhs%(int)lhs;Push(S,result);top--;break;
case '^':result=pow(rhs,lhs);Push(S,result);top--;break;
case 's':result=sin(lhs);Push(S,rhs);Push(S,result);top--;break;
case 'c':result=cos(lhs);Push(S,rhs);Push(S,result);top--;break;
}
}
top--;
break;
}
}
result=Pop(S);
printf("%lf\n",result);
}
static void Help(void){
printf("-------------------------------------------------------------------------------\n");
printf("you can input '+' '-' '*' '/' '%' '^' 's'as sin and 'c'as cos\n");
printf("EXAMPLE: 2+3^3-3/4*3%3+s(3+c3)= DON'T FORGET THE SIGNAL '='\n");
printf("Q-Quit the problem\n");
printf("H-Display help message\n");
printf("C-clear the calculator stack\n");
printf("D-goto the calculator\n");
printf("-------------------------------------------------------------------------------\n");
}
int privilege(char a){
switch(a){
case '+':
case '-':return 1;break;
case '*':
case '/':
case '%':return 2;break;
case '^':
case 's':
case 'c':return 3;break;
case '(':return 4;break;
case ')':return 0;break;
default :return 0; break;
}
}