这个是头文件的内容:
//栈操作基本表达式运算头文件
//创建人:mingming
//创建时间:2017.8.4
//最后修改时间:2017.8.4
#ifndef CACULATE_H
#define CACULATE_H
typedef double ElemType; //数字栈空间元素类型
typedef char ElemType2; //运算符栈空间元素类型
#define MAX_INIT_SIZE 20 //初始化的栈空间
#define NEW_SIZE 10 //每次新增的栈空间
#define MAX_BUFFER 10 //数字识别的缓冲区
//定义一个栈
typedef struct
{
ElemType *base;
ElemType *top;
int StackSize;
} sqStack;
bool InitStack(sqStack *s)
{
s->base = new ElemType[MAX_INIT_SIZE];
if(!s->base)
return false;
s->top = s->base;
s->StackSize = MAX_INIT_SIZE;
return true;
}
bool push(sqStack *s , ElemType e)
{
if((s->top - s->base) >= s->StackSize)
{
s->base = (ElemType *)realloc(s->base , ( NEW_SIZE + s->StackSize )* sizeof( ElemType ));
if( !s->base )
return false;
s->top = s->base + s->StackSize;
s->StackSize += NEW_SIZE;
}
*(s->top) = e;
s->top++;
return true;
}
bool pop(sqStack *s ,ElemType *e)
{
if(s->top == s->base)
return false;
s->top--;
*e = *s->top;
return true;
}
//求栈当前长度
int StackLen(sqStack s)
{
return ( s.top - s.base );
}
//对上面的各个方法进行重载
typedef struct
{
ElemType2 *base;
ElemType2 *top;
int StackSize;
} midStack;
bool InitStack(midStack *s)
{
s->base = new ElemType2[MAX_INIT_SIZE];
if(!s->base)
return false;
s->top = s->base;
s->StackSize = MAX_INIT_SIZE;
return true;
}
bool push(midStack *s , ElemType2 e)
{
if((s->top - s->base) >= s->StackSize)
{
s->base = (ElemType2 *)realloc(s->base , ( NEW_SIZE + s->StackSize )* sizeof( ElemType2 ));
if( !s->base )
return false;
s->top = s->base + s->StackSize;
s->StackSize += NEW_SIZE;
}
*(s->top) = e;
s->top++;
return true;
}
bool pop(midStack *s ,ElemType2 *e)
{
if(s->top == s->base)
return false;
s->top--;
*e = *s->top;
return true;
}
//求栈当前长度
int StackLen(midStack s)
{
return ( s.top - s.base );
}
#endif
这个是cpp文件的内容,用的时候要包含上面头文件#include<iostream>
#include<ctype.h>
#include"Caculate.h"
#define MAXBUFFER 50 //存放后缀表达式的最大缓冲区长度
//中缀表达式转换为后缀表达式
void MidtoLast(char *lastbuf)
{
std::cout << "请输入表达式!以#作为结束标志\n";
midStack stack;
InitStack(&stack); //操作符的栈初始化
int i=0;
char c;
char temp;
std::cin.get(c);
while( '#' != c ) //输入以#作为结束符
{
if( isdigit(c) || c=='.' ) //对读取到的数字处理,使得数字放在一起,并且一个数字后面有一个空格
{
while(isdigit(c) || c=='.')
{
lastbuf[i++] = c;
lastbuf[i] = ' ';
std::cin.get(c);
}
i++; //保护一个数字完了之后的空格不变
}
switch( c )
{
case '+': // + 只要前面有非括号运算符,就应该先出栈
if(stack.top == stack.base)
{
push( &stack , c );
}
else
{
do
{
pop( &stack , &temp );
if( '(' == temp )
{
push( &stack , temp );
}
else
{
lastbuf[i++] = temp;
lastbuf[i++] = ' ';
}
}while( '(' != temp && StackLen(stack));
push( &stack , c );
}
break;
case '-': // - 只要前面有非括号运算符,就应该先出栈
if(stack.top == stack.base)
{
push( &stack , c );
}
else
{
do
{
pop( &stack , &temp );
if( '(' == temp )
{
push( &stack , temp );
}
else
{
lastbuf[i++] = temp;
lastbuf[i++] = ' ';
}
}while( '(' != temp && StackLen(stack));
push( &stack , c );
}
break;
case '*': // * / 需要那顺序计算,谁在先,先算谁
if(stack.top == stack.base)
{
push( &stack , c );
}
else
{
pop( &stack , &temp );
if( '*'==temp || '/'==temp )
{
lastbuf[i++] = temp;
lastbuf[i++] = ' ';
}
else
{
push( &stack , temp );
}
push( &stack , c );
}
break;
case '/': // * / 需要那顺序计算,谁在先,先算谁
if(stack.top == stack.base)
{
push( &stack , c );
}
else
{
pop( &stack , &temp );
if( '*'==temp || '/'==temp )
{
lastbuf[i++] = temp;
lastbuf[i++] = ' ';
}
else
{
push( &stack , temp );
}
push( &stack , c );
}
break;
case '(':
push(&stack , c);
break;
case ')': //括号配对,知道碰见左括号
pop( &stack , &temp );
while( '(' != temp )
{
lastbuf[i++] = temp;
lastbuf[i++] = ' ';
pop( &stack , &temp );
}
break;
}
if( '#' != c) // 如果前面数字处理时已经读到了#,就不需要再读了
{
std::cin.get(c);
}
}
while( stack.top != stack.base ) //把栈里面没有用到的符号全部弹出来
{
pop( &stack , &lastbuf[i++] );
lastbuf[i++] = ' ';
}
lastbuf[i] = '\0'; //数组最后的结束符,防止内存泄漏
}
ElemType caculate(char *lastbuf)
{
sqStack s;
InitStack( &s );
int i = 0,bufcount=0;
double d,e;
char c , str[MAX_BUFFER];
c = lastbuf[bufcount++];
while(c != '\0')
{
while( isdigit(c) || c=='.') //数字处理,把连续的数字转换为一个double型
{
str[i++] = c;
str[i] = '\0';
if( i>=10 )
{
std::cout << "输入的数字位数过多!\n";
}
c = lastbuf[bufcount++];
if( ' '== c ) // 碰见空格说明一个数字完了
{
d = atof(str);
push( &s , d );
i = 0;
break;
}
}
switch( c )
{
case '+':
pop( &s , &e );
pop( &s , &d);
push(&s , d+e);
break;
case '-':
pop( &s , &e );
pop( &s , &d );
push(&s , d-e);
break;
case '*':
pop( &s , &e );
pop( &s , &d );
push(&s , d*e);
break;
case '/':
pop( &s , &e );
pop( &s , &d );
if( e != 0 )
{
push(&s , d/e);
}
else
{
std::cout << "除数为0,错误!\n";
return -1;
}
break;
}
c = lastbuf[bufcount++];
}
pop(&s , &d); //最终计算结果弹出到 d 中
return d;
}
int main()
{
char lastbuf[MAXBUFFER]; //后缀表达式缓冲区
MidtoLast(lastbuf); //中缀转后缀
std::cout << "运算结果为" << caculate(lastbuf) << std::endl;
return 0;
}
还有注意一下,甲鱼老师的中缀转换后缀有些问题,加减法 或者 乘除法 需要按照顺序求,就是说需要先判断站定是否有相同优先级或高优先级的运算符,如果有,就要先出栈,然后再进行压栈操作! |