您的位置:首页 > 编程语言 > C语言/C++

四则混合运算C++代码(中缀表达式)

2012-02-29 19:02 411 查看
在复习算法的时候,栈的应用举例中有一项就是计算中缀表达式的四则混合运算。根据算法自己写了一下程序。

1、程序分为两块,一部分中缀转成后缀,一部分计算后缀。其中使用到了堆栈,我自己做了一个简单地模板栈。

2、中缀转后缀的程序,接受一个内涵中缀表达式的string,输出的是一个后缀表达式的string。中缀表达式的字符串校验自行解决,程序不负责。因为数字都是以字符的形式存在,因此一个完整的数字后面用一个“;”作为标识,以便计算式可以完整识别一个数字。

例如:输入"90+(3-1)*3+10/2 ”输出即为“90;3;1;- 3;*+10;2;/+”

3、计算后缀表达式的结果程序,接受一个后缀表达式的string,循环读取其中每一个字符,如果是数字即放到字符串strNum之中,直到遇到“;”即将strNum中记录的完整数字的字符串转换成浮点类型,使用std::atof()函数,然后入栈。遇到符号即取出栈顶两个元素计算,结果入栈。最后栈里的唯一数字即结果,return。

首先中缀表达式转换成后缀表达式:

///2月28日中缀表达式转换成后缀表达式
//输入中缀表达式字符串infix,转化后返回后缀表达式字符串postfix
//输出串中,每一个数字后面放置一个;作为标识。因为数字使用char表达,234即三个char,“;”标识数字结束。做好数字完结标识后,即写入输出字符串中。
//遇到符号,左括号直接入栈;右括号时,将栈顶符号逐个取出写入输出字符串中,直到遇见左括号;
//运算符需循环与栈顶符号优先级进行比较:如果小于或者等于,取出栈顶符号写入输出字符串中,如果是左括号,直接入栈,如果优先级高于栈顶符号,入栈。
std::string InfixToPostfix(std::string infix)
{
char current = 0;//读入的字符
std::string postfix;//写入后缀表达式的字符串

SqStack<char> mark;//符号入栈
InitStack(&mark);

std::map<char,int> priority;//运算符号优先级表
priority['+'] = 0;
priority['-'] = 0;
priority['*'] = 1;
priority['/'] = 1;

for(int i = 0;i<infix.length();++i)//逐个读取中缀表达式字符串中的字符
{
current =infix[i];
switch(current)
{
case '0':case '1':case '2':case '3':case '4':case '5':
case '6':case '7':case '8':case '9':case '.':
postfix.push_back(current);//如果是数字的话直接写入输出字符串。
break;
case '+':case '-':case '*':case '/':
if(infix[i-1] != ')') postfix.push_back(';');//如果运算符的前一项不是右括号即说明前一个数字输入完毕,用;标识前面几个字符组成一个数字。
if(!IsEmpty(mark))//如果符号栈非空,即比较目前符号与栈顶符号优先级,低于等于出栈,并写入输出字符串。
{
char tempTop;
GetTop(mark,tempTop);
while(tempTop != '(' && priority[current]<=priority[tempTop])
{
char tempOut;
Pop(&mark,&tempOut);
postfix.push_back(tempOut);
if(IsEmpty(mark))//如果栈为空,跳出while循环
break;
GetTop(mark,tempTop);
}
}
Push(&mark,current);//符号全部出栈或者遇到了'('或者大于栈顶符号的优先级,将新符号压入栈中。
break;
case '(':
Push(&mark,current);//左括号直接入栈
break;
case ')':
postfix.push_back(';');//右括号说明前方数字输入完成,标识一下。
char tempTop;
GetTop(mark,tempTop);
while(tempTop !='(')//直到栈顶元素是左括号才停止循环
{
char tempOut;
Pop(&mark,&tempOut);
postfix.push_back(tempOut);//出栈并写入输出字符串中。
GetTop(mark,tempTop);
}
char tempOut;
Pop(&mark,&tempOut);//直接将左括号出栈。
break;
default:
break;//忽略其他字符。
}
}
if(infix[infix.size()-1] != ')') postfix.push_back(';');//中缀表达式最后一个是数字需要加上;标识其是一个数字的结束,便于计算时统一识别数字结束。
while(!IsEmpty(mark))//如果栈非空,全部出栈并写入输出字符串。
{
char tempOut;
Pop(&mark,&tempOut);
postfix.push_back(tempOut);
}
return postfix;//返回后缀表达式。
}

然后计算后缀表达式:

///计算后缀表达式结果
//输入为后缀表达式s,逐个读取字符,如果是数字即放入存放当前数字的字符串中,遇到“;”即将此字符串转换为float,
//使用std::atof(),参数接受const char*类型,字符串需使用.c_str()转化。
//完成数字识别转化后入栈,遇到符号即取出栈顶的两个数字计算,结果入栈。
//栈中最后的元素即为结果。
float Compute(std::string s)
{
SqStack<float> waitForCompute;
SqStack<float>* ptWait = &waitForCompute;
InitStack<float>(ptWait);         //使用栈记录等待计算的数

std::string strNum;
float currNum = 0;

float temNum1 = 0;
float temNum2 = 0;
for(std::string::const_iterator i = s.begin();i<s.end();++i)
{
switch(*i)
{
case '0':case '1':case '2':case '3':case '4':case '5':
case '6':case '7':case '8':case '9':case '.':
strNum.push_back(*i);
break;
case '+':
Pop(ptWait,&temNum1);
Pop(ptWait,&temNum2);
Push(ptWait, temNum2 + temNum1);
break;
case '-':
Pop(ptWait,&temNum1);
Pop(ptWait,&temNum2);
Push(ptWait, temNum2 - temNum1);
break;
case '*':
Pop(ptWait,&temNum1);
Pop(ptWait,&temNum2);
Push(ptWait, temNum2 * temNum1);
break;
case '/':
Pop(ptWait,&temNum1);
Pop(ptWait,&temNum2);
Push(ptWait, temNum2 / temNum1);
break;
case ';':
currNum = std::atof(strNum.c_str());//字符串转换为浮点型。
strNum.clear();
Push(ptWait,currNum);
break;
}
}
Pop(ptWait,&currNum);
return currNum;

}


其中使用到了自定义的一个顺序栈:

const int MAXSIZE = 50;

template<class T> struct SqStack
{
T data[MAXSIZE];
int top;
};

template<class T> void InitStack(SqStack<T>* s);

template<class T>  void DestroyStack(SqStack<T>* s);

template<class T>  void ClearStack(SqStack<T>* s);

template<class T>  bool IsEmpty(SqStack<T> s);

template<class T>  void GetTop(SqStack<T> s,T& e);

template<class T>  void Push(SqStack<T>* s,T e);

template<class T>  void Pop(SqStack<T>* s, T* e);

template<class T>  int StackLength(SqStack<T> s);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: