很久以前我就在想
学了这么久,却连常用的计算器程序都不会写,实在有点不好。
在学数据结构之前,凭空想过,不过真的不知道该咋写。
学栈的时候,老师讲了将中缀表达式转换为后缀表达式的方法,以及后缀表达式求值得问题,恍然大悟,也是感叹栈的神奇以及设计这种结构的人的强大。
实验就是做这个,顺带把代码贴上来吧。
中缀表达式转后缀表达式:
从始至尾遍历中缀表达式,如果是操作数,则直接输出到后缀表达式中;如果是左括号,则直接压栈;如果是右括号,则一直出栈到后缀表达式,直到遇到左括号,括号不输出;如果是运算符,需要将该运算符优先级和栈顶运算符优先级比较,只有在栈顶优先级低于将压栈运算符优先级时才压栈,否则出栈,继续比较栈顶和将压栈运算符,直到满足条件或栈空,则将该运算符压栈。
计算后缀表达式:
将中缀变后缀时,在读完一个操作数即将对操作符处理时向后缀表达式输出了一个定界符‘f’,以便在计算后缀表达式的时候区分隔操作数;
计算方法:遇到操作数,就将其压栈(先处理,将字符型转换为浮点型,用到了sscanf(str,"%f",&num),需要包含stdio.h头文件),遇到操作符,即出栈两个数a,b,将b操作符a压栈;重复,直到后缀表达式为空。
结果,输出出栈结果即可
main.cpp;
#include <iostream>
#include <cstring>
#include <stdio.h>
#include <cmath>
#include "STACK.h"
#define MAX_SIZE 100
using namespace std;
int getPriority(char ope) ;
//处理负号的问题,如把2^-2变化为2^(0-2) ; 处理左右括号不匹配问题,若缺失右括号,自动在字符串末尾加‘)’返回true
//如果左括号数小于右括号数,输入表达式错误,重新输入 ;
bool preProcess(char * str) ;
int main()
{
STACK <char> s ;
char middleStr[MAX_SIZE] ;
char suffixStr[MAX_SIZE] ;
int pos ;
cout <<"\t\txx计算器\n\t支持'+','-','*','/','^','%'\n\n" ;
while(cout <<"请输入表达式: \n\n")
{
cin >>middleStr ;
s.MakeNull() ;
strcpy(suffixStr,"") ;
if(!preProcess(middleStr) )
{
cout <<"\n输入表达式不正确,请重新输入。\n\n" ;
continue ;
}
pos = 0 ;
int len = strlen(middleStr) ;
for(int i = 0 ; i <len ; i++)
{
char temp = middleStr[i] ;
if((temp >= '0' && temp <='9')|| temp == '.' )
{
suffixStr[pos++] = temp ;
}
else if(temp == '(')
{
s.Push(temp) ;
}
else if(temp == ')')
{
//在之前加入定界符
suffixStr[pos++] = 'f' ;
while((temp= s.Pop() )!='(')
{
suffixStr[pos++] = temp ;
}
}
else
{
//数字和操作符的定界符
suffixStr[pos++]='f' ;
if(!s.isEmpty())
{
while(getPriority(s.Top())>=getPriority(temp))
{
suffixStr[pos++] = s.Pop() ;
}
s.Push(temp) ;
}
else
{
s.Push(temp) ;
}
}
}
suffixStr[pos++] = 'f' ;
while(!s.isEmpty())
{
suffixStr[pos++]=s.Pop() ;
}
suffixStr[pos] = '\0' ;
//cout <<suffixStr <<endl ;
//Calculate
STACK <float> cal ;
int len_suffix = strlen(suffixStr) ;
char strToNum[20] ;
strcpy(strToNum,"") ;
int strPos = 0 ;
for(int i = 0 ; i <len_suffix ; i++ )
{
char temp = suffixStr[i] ;
if((temp>='0'&&temp<='9')||temp == '.')
{
strToNum[strPos++] = temp ;
}
else if(temp == 'f')
{
if(strPos != 0)
{
strToNum[strPos] = '\0' ;
float num ;
sscanf(strToNum,"%f",&num) ;
cal.Push(num) ;
strcpy(strToNum,"") ;
strPos = 0 ;
}
}
else
{
float a = cal.Pop() ;
float b = cal.Pop() ;
switch(temp)
{
case '+' :
cal.Push(a+b) ;
break ;
case '-' :
cal.Push(b-a) ;
break ;
case '*' :
cal.Push(a*b) ;
break ;
case '/' :
cal.Push(b/a) ;
break ;
case '^':
cal.Push(pow(b,a)) ;
break ;
case '%' :
cal.Push((int)b%(int)a) ;
break ;
}
}
}
cout <<"计算结果为: "<<cal.Pop() <<endl <<endl;
}
return 0;
}
int getPriority(char ope)
{
char priority[13]="+-*/%^112223" ;
for(int i = 0 ; i < 6 ; i++)
{
if(ope == priority[i])
return priority[6+i] ;
}
//把‘(’的优先级定为-1
return -1 ;
}
bool preProcess(char * str)
{
int len = strlen (str) ;
for(int i = 0 ; i < len ; i++)
{
if(str[i] == '-'&&(i==0||!((str[i-1]>='0'&&str[i-1]<='9')||str[i-1]=='.')))
{
int j = i+1 ;
for( ; j <len&& ((str[j]>='0'&&str[j]<='9')||str[j]=='.'); j++) ;
for(int pos = len ; pos >= j ; pos--)
{
str[pos+3] = str[pos] ;
}
str[j+2] = ')' ;
for(int pos = j - 1 ;pos >= i ; pos--)
{
str[pos+2] = str[pos] ;
}
str[i+1] = '0' ;
str[i] = '(' ;
}
}
//字符串的长度可能已经变了!
len = strlen(str) ;
STACK <char> matchStore ;
int leftBracket = 0, rightBracket = 0 ;
for(int i = 0 ; i < len ; i++)
{
if(str[i] =='(' )
{
matchStore.Push(')') ;
leftBracket++ ;
}
if(str[i] == ')')
{
matchStore.Pop() ;
rightBracket++ ;
}
}
if(leftBracket<rightBracket)
return false ;
while(!matchStore.isEmpty())
str[len++]=matchStore.Pop() ;
str[len] = '\0' ;
return true ;
}
STACK.h
//用了类模版,比着书上写的
#ifndef STACK_H_INCLUDED
#define STACK_H_INCLUDED
template <typename T>
class STACK
{
private :
int max_size ;
int top ;
T* data ;
public :
STACK()
{
max_size = 100 ;
top = -1 ;
data = new T[max_size] ;
}
STACK(int n)
{
max_size = n ;
top = -1 ;
data = new T[max_size] ;
}
~STACK()
{
delete [] data ;
}
void MakeNull()
{
top = -1 ;
}
bool isEmpty()
{
if(top< 0)
return true ;
else
return false ;
}
T Top()
{
if(!isEmpty())
{
return data[top] ;
}
else
return NULL ;
}
T Pop()
{
if(!isEmpty())
{
T temp = Top() ;
top-- ;
return temp ;
}
else
return NULL ;
}
T Push(T x)
{
if(top>=max_size -1)
return NULL ;
else
{
data[++top] = x ;
return x ;
}
}
} ;
#endif // STACK_H_INCLUDED