计算器表达式求值源码
学习完C语言,数据结构,为了加深对知识的理解,就写了一个这样的一个小程序。
本程序是控制台程序,开发环境为Linux,但把代码Copy下来到Windows也可以运行。
先说一下本程序的设计思路,首先是用两个栈来存放数据和符号(数据栈和符号栈)。
算法(重点):
数字:数字无条件入栈
符号:
判断符号栈是否为空,如果为空,则无条件入栈
如果不为空,
当前符号如果为右括号:
一直去弹符号栈,直到弹出第一个左括号。
当前符号如果不为右括号:
判读栈顶元素是不是左括号
栈顶不是左括号
当前符号优先级 <= 栈顶元素的优先级,则计算。(出栈一个符号,出两个数字,先出栈的数字是右操作数,后出栈的数字是左操作数)
当前符号优先级 > 栈顶元素的优先级,符号入栈。
栈顶是左括号
当前符号无条件入栈
循环结束:
判断符号栈是否为空,如果为空,则数据栈的栈顶元素,就是最后的结果。
如果不空,一直计算,直到符号栈为空。
下面直接上代码:
#include <stdio.h> #include <string.h> #include <stdlib.h> //数据_结构体 struct stack_data{ double arr[100]; int top; }; //操作符_结构体 struct stack_op{ char str[100]; int top; }; //创建数据栈 struct stack_data* create_data(); //创建符号栈 struct stack_op* create_op(); //入栈 void push_data(struct stack_data* s_d,double data); //入栈 void push_op(struct stack_op* s_o,char c); //出栈 double pop_data(struct stack_data* s_d); //出栈 char pop_op(struct stack_op* s_o); //判断是否为满 int is_full_data(struct stack_data* s_d); //判断是否为满 int is_full_op(struct stack_op* s_o); //判断是否为空 int is_empty_data(struct stack_data* s_d); //判断是否为空 int is_empty_op(struct stack_op* s_o); //销毁 void destroy_data(struct stack_data* s_d); //销毁 void destroy_op(struct stack_op* s_o); //计算 double compute(char c,double a,double b); //判断优先级 int judge(char c); main(int argc,char **argv){ struct stack_data* sd=create_data(); struct stack_op* so=create_op(); char str[200]; char *p; gets(str); for(p=str;*p;p++){ if(*p>='0'&&*p<='9'){ push_data(sd,atof(p)); while(*p>='0'&&*p<='9'){ p++; } if(*p=='.'){ p=p+1; while(*p>='0'&&*p<='9')p++; } p--; }else{ if(is_empty_op(so)||*p=='('){ push_op(so,*p); continue; }else{ if(*p==')'){ while(so->str[so->top-1]!='('){ char b1=pop_op(so); double a1=pop_data(sd); double a2=pop_data(sd); push_data(sd,compute(b1,a1,a2)); } pop_op(so); }else{ if(so->str[so->top-1]!='('){ if(judge(*p)<=judge(so->str[so->top-1])){ char b2=pop_op(so); double a3=pop_data(sd); double a4=pop_data(sd); push_data(sd,compute(b2,a3,a4)); p--; continue; }else{ push_op(so,*p); } }else{ push_op(so,*p); } } } } } while(is_empty_op(so)==0){ char b3=pop_op(so); double a5=pop_data(sd); double a6=pop_data(sd); push_data(sd,compute(b3,a5,a6)); } while(is_empty_data(sd)==0){ printf("%f ",pop_data(sd)); } destroy_data(sd); sd=NULL; destroy_op(so); so=NULL; return 0; } //创建数据栈 struct stack_data* create_data(){ struct stack_data* s=malloc(sizeof(*s)); memset(s,0,sizeof(*s)); s->top=0; } //创建符号栈 struct stack_op* create_op(){ struct stack_op* s=malloc(sizeof(*s)); memset(s,0,sizeof(*s)); s->top=0; } //入栈 void push_data(struct stack_data* s_d,double data){ s_d->arr[s_d->top]=data; s_d->top+=1; } //入栈 void push_op(struct stack_op* s_o,char c){ s_o->str[s_o->top]=c; s_o->top+=1; } //出栈 double pop_data(struct stack_data* s_d){ s_d->top-=1; double data=s_d->arr[s_d->top]; return data; } //出栈 char pop_op(struct stack_op* s_o){ s_o->top-=1; char c=s_o->str[s_o->top]; return c; } //判断是否为满 int is_full_data(struct stack_data* s_d){ if(s_d->top==100) return 1; return 0; } //判断是否为满 int is_full_op(struct stack_op* s_o){ if(s_o->top==100) return 1; return 0; } //判断是否为空 int is_empty_data(struct stack_data* s_d){ if(s_d->top==0) return 1; return 0; } //判断是否为空 int is_empty_op(struct stack_op* s_o){ if(s_o->top==0) return 1; return 0; } //销毁 void destroy_data(struct stack_data* s_d){ free(s_d); s_d=NULL; } //销毁 void destroy_op(struct stack_op* s_o){ free(s_o); s_o=NULL; } //计算 double compute(char c,double a,double b){ if(c=='+')return b+a; if(c=='-')return b-a; if(c=='*')return b*a; if(c=='/')return b/a; } //判断优先级 int judge(char c){ if(c=='+'||c=='-') return -1; if(c=='*'||c=='/') return 0; }
这是初级版本,只能算加减乘除和带括号的表达式,支持小数,以后会更新。
希望和大家多交流,分享。