一个非常简单的计算器。不过还算是第一个自己写出来的一个还能算点样的小东西吧。 #include<iostream> #include<string> using namespace std; #define maxsize 512 struct seqstack { char data[maxsize]; int top; }; struct seq { double data[maxsize]; int top; }; void SetNull(seqstack *s) { s->top=-1; } void Setnull(seq *s) { s->top=-1; } void Push(seqstack *s,char x) { s->top++; s->data[s->top]=x; } void push(seq *s,double x) { s->top++; s->data[s->top]=x; } char Pop(seqstack *s) { s->top--; return s->data[s->top+1]; } double pop(seq *s) { s->top--; return s->data[s->top+1]; } char GetTop(seqstack *s) { return s->data[s->top]; } int Precedence(char sign) { switch(sign) { case '+': case '-': return 1; case '*': case '/': return 2; case '^': case '%': return 3; case '(': case '@': default: return 0; } } void Change(char* s1,char* s2) /*将s1所指的中缀表达式转换为s2所指的后缀表达式*/ { seqstack T; /*运算符栈*/ int i=0,j=0; /*用于记录扫描s1和s2中相应字符的位置*/ char ch; /*保存当前扫描到的字符*/ SetNull(&T); /*将运算符栈置空(初始化)*/ Push(&T,'@'); /*将栈底存放‘@’字符,并且这个字符具有最低的优先级 0*/ ch=s1[i]; /*将ch存入s1中的第一个字符*/ while(ch!='/0') /*开始进入转换*/ { if(ch==' ') /*如果遇到ch为空格,则不进行任何处理,直接跳过*/ ch=s1[++i]; /*继续扫描下一个字符*/ else if(ch=='(') /*如遇到左括号,直接进运算符栈*/ { Push(&T,ch); ch=s1[++i]; } else if(ch==')') /*如遇到右括号,将运算符栈中‘(’上面的运算符依次出栈并以此写入到s2串当中去*/ { while(GetTop(&T)!='(') s2[j++]=Pop(&T); Pop(&T); /*将运算符栈中的左括号出栈*/ ch=s1[++i]; } else if(ch=='+' || ch=='-' ||ch=='*' ||ch=='/' ||ch=='^'||ch=='%') /*如遇到四则运算符、乘方符号、百分号,则使存在运算符栈栈顶的不低于ch的优先级的运算符依次出栈并且写入到s2中*/ { char w=GetTop(&T); /*用w获取当前运算符栈栈顶的运算符*/ while(Precedence(w)>=Precedence(ch)) { s2[j++]=w; /*若w的优先级大于等于ch的优先级,则将w直接写入s2中*/ Pop(&T); /*由于w只是获取栈顶元素,而没有取出,所以需要将w所对应的栈顶元素出栈*/ w=GetTop(&T); /*让w继续获得栈顶元素,继续下一轮比较*/ } Push(&T,ch); /*将ch写入到运算符栈中*/ ch=s1[++i]; } else { while((ch>='0' && ch<='9')||ch=='.') /*如果ch为数字或者小数点,则将数值中的每一位依次写入到s2串中*/ { s2[j++]=ch; ch=s1[++i]; } s2[j++]=' '; /*在放入s2串中的每个数值后面接着放入一个空格字符*/ } } ch=Pop(&T); /*把运算符栈中剩下的字符依次出栈并写入到s2串中去*/ while(ch!='@') { s2[j++]=ch; ch=Pop(&T); } s2[j++]='/0'; /*在后缀表达式的最后写入‘/0’结束符*/ } double Cal(char* str) /*计算str所指的后缀表达式的值*/ { seq S; /*定义保存操作数和中间计算结果的栈,元素类型为double类型*/ double x,y; int i=0; Setnull(&S); /*将栈清空(初始化)*/ while(str[i]!='/0') /*进行对后缀表达式的处理*/ { if(str[i]==' ') /*如果遇到空格字符,则直接continue跳过*/ { i++; continue; } else if(str[i]=='+') /*如遇到加号,则做栈顶两元素的加法,结果存到x当中*/ { x=pop(&S)+pop(&S); i++; } else if(str[i]=='-') /*如遇到减号,则做栈顶两元素的减法,结果存到x当中*/ { x=pop(&S); /*弹出减数*/ x=pop(&S)-x; /*弹出被减数并作减法*/ i++; } else if(str[i]=='*') /*如遇到乘号,则做栈顶两元素的乘法*/ { x=pop(&S)*pop(&S); i++; } else if(str[i]=='/') /*如遇到除号,则做栈顶两元素的*/ { x=pop(&S); /*弹出除数*/ x=pop(&S)/x; /*弹出被除数并作除法*/ i++; } else if(str[i]=='^') /*如遇到乘方符号,则做栈顶元素与自己相乘*/ { x=pop(&S); /*弹出栈顶元素*/ x=x*x; /*做乘方运算*/ i++; } else if(str[i]=='%') /*如遇到百分号,则做栈顶元素除以100的运算*/ x=pop(&S); if(x!=0.0) x=pop(&S)/x; i++; } else /*若扫描到的是浮点数字符串,则进行如下转换,转换成相应的浮点数*/ { x=0.0; /*用x保存扫描到的整数部分的值*/ while(str[i]>=48 && str[i]<=57) { x=x*10+str[i]-48; i++; } if(str[i]=='.') /*利用y保存扫描到的小数部分的值*/ { double j=10.0; /*用j作为相应小数位的权值*/ i++; y=0.0; while(str[i]>=48 &&str[i]<=57) { y=y+(str[i]-48)/j; i++; j*=10; } x+=y; /*把小数部分合并到整数部分x中去*/ } } push(&S,x); /*将转换完成或进行相应运算后得到的浮点数进栈*/ } x=pop(&S); /*将最后的运算结果出栈*/ return x; /*返回运算结果的数值*/ } void CMyDlg::OnOK() /*计算按钮相应函数*/ { UpdateData(true); /*将用户输入在控件上的中缀表达式存入到字符串当中去*/ seqstack *p; /*定义顺序栈,接收用户输入的表达式*/ char a[1000]; /*定义字符串,用于存储转换后的后缀表达式*/ p=new seqstack; strcpy(p->data,m_output); Change(p->data,a); double e; e=Cal(a); CString str; str.Format("%f",e); /*将算得的浮点数转换成浮点数字符串*/ m_result=str; UpdateData(false); /*将结果显示到控件上将显示在控件上的字符串清空*/ m_output=""; /*将显示在控件上的字符串清空*/