表达式求值
第一次使用Markdown编辑器不太习惯,写了很多版本的表达式求值有并且有Java的。但是就觉得这一个还不错。
表达式求值主要就是主要考虑运算符的优先级,“+-”属于同一级别,”%/属于同一级别我自定义了一个函数判断
static int precedence(char ch)
{
switch (ch) {
case '+': return 1;
case '-': return 1;
case '*': return 2;
case '/': return 2;
case '%': return 2;
default:
break;
}
return 0;
}
运算操当栈顶的运算符优先级大于等于当前运算符,就取出数据栈的两个数据和运算符栈的运算符进行运算
//运算操作
static int stack_count(stack<double> *num, stack<char> *op)
{
char oper= op->top();op->pop();//取出运算符
//取出两个数据进行运算
if (num->size()<2) { return -1; }//如果数据栈的数据少于两个说明出错
double num1 = num->top();num->pop();
double num2 = num->top();num->pop();
int s = 0;
switch(oper)
{
case '+': num->push(num2+num1);break;
case '-': num->push(num2-num1);break;
case '*': num->push(num2*num1);break;
case '/': num->push(num2/num1);break;
case '%': num->push((int)num2 % (int)num1);break;
default:s = -1;break;
}
return s;
}
主函数就是将输入的表达式进行传入到运算函数里面进行运算,我的是将输入的表达式存储到一个string类里面然后,遍历str的每个字符进行操作
static int oper_expre(string str)
{
char *op = { "+-*/%" };
char *left = { "({[" };
char *right = { ")]}" };
stack<double> OPND;//存放数据
stack<char> OPTR; //存放运算符
for (string::iterator it = str.begin();it != str.end();it++)
{
if (*it == ' ') { continue; } //跳过空字符
else if (strchr(op, *it) != NULL)
{
while (!OPTR.empty() && precedence(OPTR.top()) >= precedence(*it))
{
if (stack_count(&OPND, &OPTR) == -1)
{
return -1;
}
}
OPTR.push(*it);
}
else if (strchr(left, *it) != NULL)//处理左括号
{
OPTR.push(*it);
}
else if (strchr(right, *it) != NULL)//处理右括号
{
while (strchr(left, OPTR.top()) == NULL)
{
if (stack_count(&OPND, &OPTR) == -1)
{
return -1;
}
}
OPTR.pop();
}
else if (*it >= '0'&&*it <= '9')//处理数据
{
string num;
while (*it >= '0'&&*it <= '9' || *it == '.')
{
num += *it;
it++;
if (it == str.end()) { break; }
}
it--;
stringstream sir(num);
double d;
sir >> d;
OPND.push(d);
}
else
{
return -1;
}
}
while (!OPTR.empty())
{
if (stack_count(&OPND, &OPTR) == -1)
{
return -1;
}
}
if (OPND.empty()) { return -1; }//如果为空说明输入有问题
cout << OPND.top() << endl;
return 1;
}
这里是所有代码 程序缺点是不能进行负数的运算 大家可以自行优化下
#include<iterator>
#include<iostream>
#include<stack>
#include<string>
#include<string.h>
#include<sstream>
using namespace std;
//运算符优先级判断
static int precedence(char ch)
{
switch (ch) {
case '+': return 1;
case '-': return 1;
case '*': return 2;
case '/': return 2;
case '%': return 2;
default:
break;
}
return 0;
}
//运算操作
static int stack_count(stack<double> *num, stack<char> *op)
{
char oper= op->top();op->pop();//取出运算符
//取出两个数据进行运算
if (num->size()<2) { return -1; }//如果数据栈的数据少于两个说明出错
double num1 = num->top();num->pop();
double num2 = num->top();num->pop();
int s = 0;
switch(oper)
{
case '+': num->push(num2+num1);break;
case '-': num->push(num2-num1);break;
case '*': num->push(num2*num1);break;
case '/': num->push(num2/num1);break;
case '%': num->push((int)num2 % (int)num1);break;
default:s = -1;break;
}
return s;
}
static int oper_expre(string str)
{
char *op = { "+-*/%" };
char *left = { "({[" };
char *right = { ")]}" };
stack<double> OPND;//存放数据
stack<char> OPTR; //存放运算符
for (string::iterator it = str.begin();it != str.end();it++)
{
if (*it == ' ') { continue; } //跳过空字符
else if (strchr(op, *it) != NULL)
{
while (!OPTR.empty() && precedence(OPTR.top()) >= precedence(*it))
{
if (stack_count(&OPND, &OPTR) == -1)
{
return -1;
}
}
OPTR.push(*it);
}
else if (strchr(left, *it) != NULL)//处理左括号
{
OPTR.push(*it);
}
else if (strchr(right, *it) != NULL)//处理右括号
{
while (strchr(left, OPTR.top()) == NULL)
{
if (stack_count(&OPND, &OPTR) == -1)
{
return -1;
}
}
OPTR.pop();
}
else if (*it >= '0'&&*it <= '9')//处理数据
{
string num;
while (*it >= '0'&&*it <= '9' || *it == '.')
{
num += *it;
it++;
if (it == str.end()) { break; }
}
it--;
stringstream sir(num);
double d;
sir >> d;
OPND.push(d);
}
else
{
return -1;
}
}
while (!OPTR.empty())
{
if (stack_count(&OPND, &OPTR) == -1)
{
return -1;
}
}
if (OPND.empty()) { return -1; }//如果为空说明输入有问题
cout << OPND.top() << endl;
return 1;
}
int main()
{
string str;
while(cin>>str)
{
if (oper_expre(str) == -1)//处理格式是否正确
{
cout << "输入格式不正确请重新输入" << endl;
}
}
return 0;
}