这几天一直在写表达式求值,但是蛋疼的是老出错,最后没办法只好重写,好不容易终于写出来了,哎 纪念一下
。
表达式求值的实现:
使用栈结构:1.顺序栈 2.链栈
顺序栈的结构为
typedef struct
{
SElemType *base; //这个指向栈低
SElemType *Top; //这个指向栈顶元素的下一个空位置
int stacksize; //顺序栈的大小,栈当前的最大容量
}SqStack;
需要实现的函数
1.构造一个空栈S
InitStack(SqStack &S)
2.吧元素压入栈中插入元素e进入栈顶
Push(Sqstack &S , SElemType e)
3.得到栈顶元素,返回数据类型
SElemType GetTop(SqStack &S)
4.吧元素从栈顶删除,并返回元素值
SElemType Pop(SqStack &S)
5.判断是字符还是数值
int In(char c)
6.比较字符栈的栈顶字符和当前字符的优先级
如果当前优先级高那压入栈中,否则先进行计算
Precede(char c1 , char c2)
7.进行计算的函数,判断是应该进行什么计算的函数
Operate(int a , char theta , int b)
8.关键算法函数
EvaluateExpression()
最先开始用的链栈结构写的,结果各种乱起八糟的错误,实在写不下去了,只好重写!
//功能:表达式求值
//时间:2014年4月23日16:22:24
//作者:cutter_point
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
//首先得有一个栈,存放运算符
//链栈
typedef struct LStack1
{
char c; //存放运算符
struct LStack1 *next;
}*PLStack1;
typedef struct LStack2
{
double i; //存放表达式的数据值
struct LStack2 *next;
}*PLStack2;
/************栈函数****************/
//创建一个空链栈,这种写两遍好累啊,能用模板么?
void InitStack(PLStack1 &S)
{
S=NULL;
}
void InitStack(PLStack2 &S)
{
S=NULL;
}
//Push压入字符元素
void Push1(PLStack1 &S , char c)
{
PLStack1 p;
p=(PLStack1)malloc(sizeof(LStack1));
p->c=c;
p->next=NULL;
S->next=p;
S=p;
}
void Push2(PLStack2 &S , double i)
{
PLStack2 p;
p=(PLStack2)malloc(sizeof(LStack2));
p->i=i;
p->next=S;
S=p;
}
//Pop弹出字符元素
char Pop1(PLStack1 &S , char c)
{
PLStack1 p;
c=S->c;
p=S;
S=S->next;
free(p);
return c; //把c的值返回出去,因为这是局部变量
}
double Pop2(PLStack2 &S , double i)
{
PLStack2 p;
i=S->i;
p=S;
S=S->next;
free(p);
//cout<<"这个数值是:"<<i<<endl;
return i; //把c的值返回出去,因为这是局部变量
}
//各种函数
//取得栈顶元素,字符栈
char GetTop1(PLStack1 &S)
{
return S->c;
}
double GetTop2(PLStack2 &S) //这个算是重载了吧!
{
return S->i;
}
//判断是运算的字符
int In(char c)
{
int i=0;
switch(c)
{
case '+': case '-': case '*': case '/':
case '(': case ')': case '#':
i++;
break;
}
return i;
}
//Precede函数的使用,判断优先级的大小
char Precede(char c1 , char c2)
{
char c3;
if(c1 == '+' || c1 == '-')
{
switch(c2) //判断+和'+','-'的优先级,前面是+号,c2是后面出现的
{
case '+': case '-': case ')': case '#':
c3='>';break;
case '*': case '/': case '(':
c3='<';break;
default :
cout<<"喊你一声逗比,你可敢应1?"<<endl;break;
}
}else if(c1 == '*' || c1 == '/')
{
switch(c2) //判断+和'*','/'的优先级,前面是+号,c2是后面出现的
{
case '+': case '-': case ')': case '#': case '*': case '/':
c3='>';break;
case '(':
c3='<';break;
default :
cout<<"喊你一声逗比,你可敢应2?"<<endl;break;
}
}else if(c1 == '(')
{
switch(c2) //判断+和'('的优先级,前面是+号,c2是后面出现的
{
case '+': case '-': case '(': case '*': case '/':
c3='<';break;
case ')':
c3='=';break;
default :
cout<<"喊你一声逗比,你可敢应3?"<<endl;break;
}
}else if(c1 == ')') //判断‘)’和其他符号的优先级
{
if(c2 != '(')
{
c3='>';
}
}else if(c1 == '#') //判断‘#’和其他符号的优先级
{
if(c2 != '(')
{
if(c2 == '#')
c3='=';
else
c3='<';
}
}
return c3; //返回c1和c2比较的优先级结果
}
//Operate为进行二元运算a θb进行运算
double Operate(double a , char theta , double b)
{
double count;
switch(theta)
{
case '+': count=a+b; break;
case '-': count=a-b; break;
case '*': count=a*b; break;
case '/': count=a/b; break;
}
return count;
}
//这两个定义成全局的,因为好多函数要用到
PLStack1 OPTR;
PLStack2 OPND;
//核心算法,算术表达式求值的算符优先算法,OPTR和OPND分别是运算符栈和运算数栈
double EvaluateExpression()
{
char c[40]; //这是为了获得重键盘输入的数值
char x,theta,k; //x用来后面Pop1存放字符,theta是后面操作字符,k用来存放GetTop取到的字符
double a=0,b=0,d=0;
int i=0;
cout<<"输入表达试!!"<<endl;
//输入字符并存放到数组中
gets(c);
InitStack(OPTR);
Push1(OPTR , '#'); //栈低是一个‘#’标示已经没有元素了
InitStack(OPND);
k=GetTop1(OPTR); //吧栈顶字符取出
while((c[i] !='#') || k != '#') //今天先到这吧 2014年4月23日21:04:09 2014年5月1日11:57:03循环有问题!!
//while(i == -1)
{
cout<<k<<"xxxxxxxxxxxxxxxxxx"<<endl;
if(In(c[i]) != 0) //判断是否是字符,不是则压入OPND栈
{
//cout<<"第 "<<i<<" 个数值是:"<<c[i]<<" 栈顶字符是:"<<k<<endl;
double j;
char *p;
p=&c[i];
j=atof(p); //把字符转换成数值
Push2(OPND , j); //压入栈
i++;
}
else
{
switch(Precede(GetTop1(OPTR) , c[i])) //Precede用来判定它的优先级
{
case '<': //栈顶元素优先权低
Push1(OPTR , c[i]);
//c = getchar(); //得到下一个字符
i++;
break;
case '=': //脱括号
Pop1(OPTR , x);
// c = getchar();
i++;
break;
case '>':
theta=Pop1(OPTR , theta); //取出符号准备计算
b=Pop2(OPND , b);
a=Pop2(OPND , a);
Push2(OPND , Operate(a , theta , b));
//这里不能写i++,因为这里是要计算,但是还是要用到当前字符和下一个比较2014年5月3日11:17:45
break;
}//switch
}//else
k=GetTop1(OPTR); //取出栈顶字符以便循环判断
}//while
return GetTop2(OPND);
}
void main()
{
cout<<"结果是:"<<EvaluateExpression()<<endl;;
}
//第三次调试开始 2014年5月1日16:30:20
//决定这个程序写作完全失败!!!!2014年5月1日18:27:54
//重新调试,因为重写了之后,估计知道错误在那了 2014年5月3日11:16:39
//好吧我承认我天真了,还是调试不成功!!!2014年5月3日11:19:12
写了这个之后完全没想法了,赶紧开始新的吧!,从新开始的事太蛋疼了。。。。。
/*
* 功能:表达式求值
* 时间:2014年5月1日19:09:18
* 作者:cutter_point
*/
#include <stdio.h>
#include<stdlib.h>
#include<iostream>
#define STACK_INIT_SIZE 10 //用来设置栈的初始大小
using namespace std;
//栈的数据结构
//字符栈
typedef struct StackChar
{
char *base; //指向栈顶元素的下一个位置
char *top; //指向栈底元素
int stacksize; //栈当前可使用的最大容量
}*SCLink;
//数值栈
typedef struct StackInt
{
int *base; //指向栈顶元素的下一个位置
int *top; //指向栈底元素
int stacksize; //栈当前可使用的最大容量
}*SILink;
//设置全局变量,定义两个栈
StackChar OPTR;
StackInt OPND;
/**********************************************************************/
//栈函数
void InitStackChar(StackChar &S) //初始化一个栈
{
S.base=(char *)malloc(STACK_INIT_SIZE*sizeof(char));
S.top=S.base; //空栈头和尾指针地址相同
S.stacksize = STACK_INIT_SIZE; //设置初始大小
}//InitStackChar
void InitStackInt(StackInt &S)
{
S.base=(int *)malloc(STACK_INIT_SIZE*sizeof(int));
S.top=S.base; //空栈头和尾指针地址相同
S.stacksize = STACK_INIT_SIZE; //设置初始大小
}//InitStackInt
/**********************************************************************/
void PushChar(StackChar &S , char e) //插入元素e进入栈
{
//插入之前先判断空间是否够用
if(S.top-S.base >= S.stacksize)//栈满了
{
S.base=(char *)realloc(S.base , (S.stacksize + STACK_INIT_SIZE)*sizeof(char));
S.top=S.base+S.stacksize;
S.stacksize +=STACK_INIT_SIZE; //刷新数据
}
*S.top=e;
S.top++;
}//PushChar
void PushInt(StackInt &S , int e)
{
//插入之前先判断空间是否够用
if(S.top-S.base >= S.stacksize)//栈满了
{
S.base=(int *)realloc(S.base , (S.stacksize + STACK_INIT_SIZE)*sizeof(int));
S.top=S.base+S.stacksize;
S.stacksize +=STACK_INIT_SIZE; //刷新数据
}
*S.top=e;
S.top++;
}//PushInt
/**********************************************************************/
char PopChar(StackChar &S) //删除栈顶元素,取出元素
{
char e;
//如果栈不为空则删除S的栈顶元素,并返回删除的值
if(S.base != S.top)
{
e = *(S.top-1);
S.top--;
}
return e;
}//PopChar
int PopInt(StackInt &S)
{
int e;
//如果栈不为空则删除S的栈顶元素,并返回删除的值
if(S.base != S.top)
{
e = *(S.top-1);
S.top--;
}
return e;
}//PopInt
/**********************************************************************/
char GetTopChar(StackChar &S)
{
char e;
//若栈不为空,则返回S的栈顶元素
if(S.base != S.top)
{
e = *(S.top-1); //记住这里S.top指向的是栈顶元素的下一个地址
}
return e;
}//GetTopChar
int GetTopInt(StackInt &S)
{
int e;
//若栈不为空,则返回S的栈顶元素
if(S.base != S.top)
{
e = *(S.top-1); //记住这里S.top指向的是栈顶元素的下一个地址
}
return e;
}//GetTopInt
/**********************************************************************/
//判断函数,是不是字符,不是字符则进入int栈
int In(char c)
{
//判断是运算的字符
int i=0;
switch(c)
{
case '+': case '-': case '*': case '/':
case '(': case ')': case '#':
i++;
break;
}
return i;
}
char Precede(char c1 , char c2) //比较两个字符的优先级 今天就先到这2014年5月1日20:06:36
{
char e; //用来返回判定的结果
switch(c1)
{
case '+': case '-':
switch(c2)
{
case '+': case '-': case ')': case '#':
e='>';
break;
case '*': case '/': case '(':
e='<';
break;
default:
printf("\n");
printf("8888888888888888888888888888888888888888888\n");
printf("88 88\n");
printf("88 88\n");
printf("88 ①cutter_point制作,盗版不究!! 88\n");
printf("88 88\n");
printf("88 88\n");
printf("8888888888888888888888888888888888888888888\n");
break;
}//switch(c2) + -
break;
case '*': case '/':
switch(c2)
{
case '+': case '-': case '*': case '/': case ')': case '#':
e='>';
break;
case '(':
e='<';
break;
default:
printf("\n");
printf("8888888888888888888888888888888888888888888\n");
printf("88 88\n");
printf("88 88\n");
printf("88 ②cutter_point制作,盗版不究!! 88\n");
printf("88 88\n");
printf("88 88\n");
printf("8888888888888888888888888888888888888888888\n");
break;
}//switch(c2) * /
break;
case '(':
switch(c2)
{
case '+': case '-': case '*': case '/': case '(':
e='<';
break;
case ')':
e='=';
break;
default:
printf("\n");
printf("8888888888888888888888888888888888888888888\n");
printf("88 88\n");
printf("88 88\n");
printf("88 ③cutter_point制作,盗版不究!! 88\n");
printf("88 88\n");
printf("88 88\n");
printf("8888888888888888888888888888888888888888888\n");
break;
}//switch(c2) (
break;
case ')':
switch(c2)
{
case '+': case '-': case '*': case '/': case ')': case '#':
e='>';
break;
default:
printf("\n");
printf("8888888888888888888888888888888888888888888\n");
printf("88 88\n");
printf("88 88\n");
printf("88 ④可爱cutter_point制作,盗版不究!!88\n");
printf("88 88\n");
printf("88 88\n");
printf("8888888888888888888888888888888888888888888\n");
break;
}//switch(c2) ')'
break;
case '#':
switch(c2)
{
case '+': case '-': case '*': case '/': case '(': case '#':
e='<';
break;
default:
printf("\n");
printf("8888888888888888888888888888888888888888888\n");
printf("88 88\n");
printf("88 88\n");
printf("88 ⑤可爱cutter_point制作,盗版不究!!88\n");
printf("88 88\n");
printf("88 88\n");
printf("8888888888888888888888888888888888888888888\n");
break;
}//switch(c2) '#'
break;
default:
printf("\n");
printf("8888888888888888888888888888888888888888888\n");
printf("88 88\n");
printf("88 88\n");
printf("88 ⑥蛋疼的排版,伤不起!!!! 88\n");
printf("88 88\n");
printf("88 88\n");
printf("8888888888888888888888888888888888888888888\n");
break;
}//switch(c1)
return e; //返回比较结果
}
int Operate(int a , char theta , int b) //进行计算,判断应该进行那种计算
{
switch(theta)
{
case '+':
return a+b;
break;
case '-':
return a-b;
break;
case '*':
return a*b;
break;
case '/':
return a/b;
break;
default:
printf("程序太难,排版不易,且排且珍惜!\n");
}
}
/**********************************************************************/
int EvaluateExpression() //表达式求值,关键算法函数
{
//算术表达式求值的算符优先算法。设OPTR和OPND分别为运算符栈和运算数栈,
InitStackChar(OPTR); //初始化顺序栈
InitStackInt(OPND); //同上
char c[2*STACK_INIT_SIZE],k,theta; //就是20的空间STACK_INIT_SIZE是 10,k用来接受PopChar消除括号弹出来的,theta用来接受用来计算弹出的符号
int i=0,j=0,a,b; //用来计数数组中到了第几个元素了,a,b是后面Pop弹出来计算的,i,j用来指示数组轮转到那了
PushChar(OPTR , '#'); //栈低先用'#'占据
printf("输入表达式:");
gets(c); //把得到的数据存入到数组中
printf("表达式是:");
//输出数组C中的值,看是否已经全部输入
while(c[j-1] != '#')
{
printf("%c",c[j]);
j++;
}
printf("\n");
// printf("why you are so 犀利?\n");
while(c[i] != '#' || GetTopChar(OPTR) != '#')
{
if(In(c[i]) == 0) //不是运算符则进栈
{
int j; //用来存放吧字符转换成的数字
char *temp;
temp=&c[i];
j=(int)atof(temp); //把字符转换成数值atof(*p)是吧字符转化成浮点型数据
// j=c[i]-'0'; //数字与0的距离就是他的数字,ASCII码
// printf("%d\n",j);
PushInt(OPND , j);
i++; //取下一个字符
}
else
{
switch(Precede(GetTopChar(OPTR) , c[i]))
{
case '<':
PushChar(OPTR , c[i]);
i++; //取下一个字符
break;
case '=': //消除括号
k=PopChar(OPTR);
i++; //取下一个字符
break;
case '>':
theta=PopChar(OPTR);
b=PopInt(OPND);
a=PopInt(OPND);
// printf("!!!%d\n",Operate(a,theta,b));
PushInt(OPND , Operate(a , theta , b));
break;
}//switch
}//else
}//while
return GetTopInt(OPND);
}//EvaluateExpresssion
/**********************************************************************/
int main( )
{
printf("结果是:%d\n",EvaluateExpression()); //基本完成时间2014年5月2日12:14:40 程序待调试
return 0;
}
//今天调试发现错误点,i++放错位置了,导致while循环老错 2014年5月3日11:04:48
//调试结束,程序完成!
//出自严蔚敏的数据结构算法3_4,表达式求值 2014年5月3日11:10:21
第一次写博客!!
哈哈,我这个人不太会说话,有什么得罪的地方,你来咬我啊!!