[面试备忘]四则运算式求值

题目:四则运算表达式求之值。

  下面是程序化算法流程:

  1、建立运算符栈stackOperator用于运算符的存储,压入'\0'。

  2、预处理表达式,正、负号前加0(如果一个加号(减号)出现在最前面或左括号后面,则该加号(减号)为正负号) 。

  3、顺序扫描表达式,如果当前字符是数字(优先级为0的符号),则直接输出该数字;如果当前字符为运算符或括号(优先级不为0的符号),则判断第4点 。

  4、若当前运算符为'(',直接入栈;

  若为')',出栈并顺序输出运算符直到遇到第一个'(',遇到的第一个'('出栈但不输出;

  若为其它,比较stackOperator栈顶元素与当前元素的优先级:

  如果 栈顶元素运算符优先级 >= 当前元素的优先级,出栈并顺序输出运算符直到 栈顶元素优先级 < 当前元素优先级,然后当前元素入栈;

  如果 栈顶元素 < 当前元素,直接入栈。

  5、重复第3点直到表达式扫描完毕。

  6、顺序出栈并输出运算符直到栈顶元素为'\0'。

View Code
#include <cassert>
#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <stack>
#include <deque>

std::map<std::string, int> operatorPrior;

inline bool isNum(const char& ch)
{
return ch >= '0' && ch <= '9';
}

void initOperatorPrior()
{
//鍑轰笘鍖栧瓨鍌ㄨ繍绠楀簻浼樺厛绾х殑MAP瀵硅薄銆?
operatorPrior["#"] = -1;
operatorPrior["("] = 0;
operatorPrior["+"] = 1;
operatorPrior["-"] = 1;
operatorPrior["*"] = 2;
operatorPrior["/"] = 2;
}

void stringPreHandle(std::string& midNotation)
{
if ('+' == midNotation[0] || '-' == midNotation[0]) {
midNotation = std::string("0") + midNotation;
}
for (std::string::iterator index = midNotation.begin(); index < midNotation.end() - 1; ++index) {
if (*index == '(' && (*(index + 1) == '+' || *(index + 1) == '-')) {//鍦紙鍚庨潰绱ц窡+-鍙凤紝璇存槑鏄璐熷彿
midNotation.insert(index + 1, '0');
++index;
}
}
}

int stringToNum (const std::string& toCal) {
int result = 0;
for (std::size_t index = 0, base = 1; index != toCal.size(); ++index, base *= 10) {
result += (toCal[toCal.size() - index - 1] - '0') * base;
}
return result;
}

std::string numToString(int numb)
{
std::string result;
do {
result.insert(result.begin(), static_cast<char>('0' + numb % 10));
numb /= 10;
} while (numb != 0);
return result;
}

std::string getNumber(const std::string& toHandle, size_t startIndex, size_t& endIndex)
{
std::string destNum;
std::string::const_iterator startIterator = toHandle.begin() + startIndex;
std::string::const_iterator endterator = startIterator;
for (; endterator != toHandle.end(); ++endterator) {
if (isNum(*endterator)) {
destNum.insert(destNum.end(), *endterator);
} else {
break;
}
}
endIndex = startIndex + (endterator - startIterator);
return destNum;
}


void covertToPolishRevertNotation(const std::string& midNotation, std::deque<std::string>& revertPolishNotation)
{
std::string toConvert = midNotation;
stringPreHandle(toConvert);
std::stack<std::string> operatorStack;
operatorStack.push("#");
for (std::string::size_type index = 0; index < toConvert.size();) {
if (isNum(toConvert[index])) {
revertPolishNotation.push_back(getNumber(toConvert, index, index));
} else {
std::string pendingOP(1, toConvert[index]);
switch(toConvert[index]) {
case '+':
case '-':
case '*':
case '/':
while (operatorPrior[operatorStack.top()] >= operatorPrior[pendingOP]) {
revertPolishNotation.push_back(operatorStack.top());
operatorStack.pop();
}
operatorStack.push(pendingOP);
break;
case '(':
operatorStack.push(pendingOP);
break;
case ')':
while (operatorStack.top() != "(") {
revertPolishNotation.push_back(operatorStack.top());
operatorStack.pop();
}
operatorStack.pop();
break;
default:
assert(false);
}
++index;
}
}
while (operatorStack.top() != "#") {
revertPolishNotation.push_back(operatorStack.top());
operatorStack.pop();
}
}

int calculate(const std::string& toCal)
{

std::deque<std::string> reversePolishStack;
covertToPolishRevertNotation(toCal, reversePolishStack);
std::stack<std::string> numberStack;
while (reversePolishStack.size()) {
if (isNum(reversePolishStack.front()[0])) {
numberStack.push(reversePolishStack.front());
} else {
int numbB = stringToNum(numberStack.top());
numberStack.pop();
int numbA = stringToNum(numberStack.top());
numberStack.pop();
std::string op = reversePolishStack.front();
int tempResult = 0;
if (op == "+") {
tempResult = numbA + numbB;
} else if (op == "-") {
tempResult = numbA - numbB;
} else if (op == "*") {
tempResult = numbA * numbB;
} else if (op == "/") {
tempResult = numbA / numbB;
} else {
assert(false);
}
numberStack.push(numToString(tempResult));
}
reversePolishStack.pop_front();
}
return stringToNum(numberStack.top());
}

int main()
{
initOperatorPrior();
std::string midNotation("1*2*3*(4+5)*6*7");
std::cout << calculate(midNotation) << std::endl;
return 0;
}


此代码目前不能检测格式不正确的四则运算输入。

posted @ 2011-09-21 22:31  lifengzhong  阅读(216)  评论(0编辑  收藏  举报