作业帮 > 综合 > 作业

4.计算表达式的值求用C++类做的代码

来源:学生作业帮 编辑:搜搜考试网作业帮 分类:综合作业 时间:2024/04/24 17:16:49
4.计算表达式的值求用C++类做的代码
对于给定的一个表达式,表达式中可以包括常数、算术运行符(“+”、“-”、“*”、“/”)和括号,编写程序计算表达式的值.
基本要求:从键盘输入一个正确的中缀表达式,将中缀表达式转换为对应的后缀表达式,计算后缀表达式的值.
测试数据:任意选取一个符合题目要求的表达式.
提高要求:(1)对于表达式中的简单错误,能够给出提示;
(2)不仅提示错误,也能给出错误信息
(3)表达式中可以包括单个字母表示的变量
(4)能够处理多种操作符
(5)实现包含简单运算的计算器
(6)实现一个包含简单运算和函数运算的计算器
4.计算表达式的值求用C++类做的代码
#include <iostream>
#include <vector>
using namespace std;

bool isoperator(char op);\x09\x09\x09\x09\x09\x09  // 判断是否为运算符
int priority(char op);\x09\x09\x09\x09\x09\x09  \x09  // 求运算符优先级
void postfix(char pre[] , char post[],int &n);    // 把中缀表达式转换为后缀表达式
double read_number(char str[],int *i);\x09\x09\x09  // 将数字字符串转变成相应的数字
double postfix_value(char post[]);\x09\x09\x09\x09  // 由后缀表达式字符串计算相应的中值表达式的值\x09

template <class ElemType> class MyStack
{
public:
\x09const static  int MAXSIZE =100;
\x09ElemType data[MAXSIZE];
\x09int top;

public:
\x09void init();\x09\x09\x09// 初始化栈
\x09bool empty();\x09\x09\x09// 判断栈是否为空
\x09ElemType gettop();\x09    // 读取栈顶元素(不出栈)
\x09void push(ElemType x);\x09// 进栈
\x09ElemType pop();\x09\x09\x09// 出栈
};

template<class T> void MyStack<T>::init()
{
\x09this->top = 0;
}

template<class T> bool MyStack<T>::empty()
{
\x09return this->top == 0? true : false;
}

template<class T> T MyStack<T>::gettop()
{
\x09if(empty())
\x09{
\x09\x09cout << "栈为空!\n";
\x09\x09exit(1);
\x09}
\x09return this->data[this->top-1];
}

template<class T> void MyStack<T>::push(T x)
{
\x09if(this->top == MAXSIZE)
\x09{
\x09\x09cout << "栈已满!\n";
\x09\x09exit(1);
\x09}
\x09this->data[this->top] =x;
\x09this->top ++;
}

template<class T> T MyStack<T>::pop()
{
\x09if(this->empty())
\x09{
\x09\x09cout << "栈为空! \n";
\x09\x09exit(1);
\x09}

\x09T e =this->data[this->top-1];
\x09this->top --;
\x09return e;
}

int main()
{
\x09MyStack<int> stack ;
\x09stack.init();

\x09//char pre[] ="22/(5*2+1)#";
\x09char exp[100];
\x09cout << "输入表达式(中缀,以#结束):";
\x09cin >> exp;

\x09char post[100] ;
\x09//cout <<"中缀表达式为:"<< pre << endl;

\x09int n =0;\x09\x09\x09// 返回后缀表达式的长度
\x09postfix(exp,post,n);
\x09cout <<"后缀表达式为:";
\x09for( int i =0 ;i < n ;i++)
\x09\x09cout << post[i] ;

\x09cout << "\n由后缀表达式计算出的数值结果:  ";
\x09cout << postfix_value(post) << endl;

\x09system("pause");
\x09return 0;
}

bool isoperator(char op)
{
\x09switch(op)
\x09{
\x09case '+':
\x09case '-':
\x09case '*':
\x09case '/':
\x09\x09return 1;
\x09default : 
\x09\x09return 0;
\x09}
}

int priority(char op)
{
\x09switch(op)
\x09{
\x09case '#':
\x09\x09return -1;
\x09case '(':
\x09\x09return 0;
\x09case '+':
\x09case '-':
\x09\x09return 1;
\x09case '*':
\x09case '/':
\x09\x09return 2;
\x09default :
\x09\x09return -1;
\x09}
}

//\x09 把中缀表达式转换为后缀表达式,返回后缀表达式的长度(包括空格)
void postfix(char pre[] ,char post[],int &n)
{
\x09int i = 0 ,j=0;
\x09MyStack<char> stack;
\x09stack.init();\x09\x09// 初始化存储操作符的栈

\x09stack.push('#');\x09// 首先把结束标志‘#’放入栈底

\x09while(pre[i]!='#')
\x09{
\x09\x09if((pre[i]>='0' && pre[i] <='9')||pre[i] =='.') // 遇到数字和小数点直接写入后缀表达式
\x09\x09{
\x09\x09\x09post[j++] = pre[i];
\x09\x09\x09n++;
\x09\x09}
\x09\x09else if (pre[i]=='(')\x09// 遇到“(”不用比较直接入栈
\x09\x09\x09stack.push(pre[i]);
\x09\x09else if(pre[i] ==')')  // 遇到右括号将其对应左括号后的操作符(操作符栈中的)全部写入后缀表达式
\x09\x09{
\x09\x09\x09while(stack.gettop()!='(')
\x09\x09\x09{
\x09\x09\x09\x09post[j++] = stack.pop();
\x09\x09\x09\x09n++;
\x09\x09\x09}
\x09\x09\x09stack.pop(); // 将“(”出栈,后缀表达式中不含小括号
\x09\x09}
\x09\x09else if (isoperator(pre[i]))
\x09\x09{
\x09\x09\x09post[j++] = ' '; // 用空格分开操作数(
\x09\x09\x09n++;
\x09\x09\x09while(priority(pre[i]) <= priority(stack.gettop())) 
\x09\x09\x09{
\x09\x09\x09\x09// 当前的操作符小于等于栈顶操作符的优先级时,将栈顶操作符写入到后缀表达式,重复此过程
\x09\x09\x09\x09post[j++] = stack.pop();
\x09\x09\x09\x09n++;
\x09\x09\x09}

\x09\x09\x09stack.push(pre[i]);\x09// 当前操作符优先级大于栈顶操作符的优先级,将该操作符入栈
\x09\x09}

\x09\x09i++;
\x09}
\x09while(stack.top) // 将所有的操作符加入后缀表达式
\x09{
\x09\x09post[j++] = stack.pop();
\x09\x09n++;
\x09}
}

double read_number(char str[],int *i)
{
\x09double x=0.0;
\x09int k = 0;
\x09while(str[*i] >='0' && str[*i]<='9')  // 处理整数部分
\x09{
\x09\x09x = x*10+(str[*i]-'0');
\x09\x09(*i)++;
\x09}

\x09if(str[*i]=='.') // 处理小数部分
\x09{
\x09\x09(*i)++;
\x09\x09while(str[*i] >= '0'&&str[*i] <='9')
\x09\x09{
\x09\x09\x09x = x * 10 + (str[*i]-'0');
\x09\x09\x09(*i)++;
\x09\x09\x09k++;
\x09\x09}
\x09}
\x09while(k!=0)
\x09{
\x09\x09x /= 10.0;
\x09\x09k--;
\x09}

\x09return x;
}

double postfix_value(char post[])
{
\x09MyStack<double> stack;\x09// 操作数栈
\x09stack.init();

\x09int i=0 ;
\x09double x1,x2;

\x09while(post[i] !='#')
\x09{
\x09\x09if(post[i] >='0' && post[i] <='9')
\x09\x09\x09stack.push(read_number(post,&i));
\x09\x09else if(post[i] == ' ')
\x09\x09\x09i++;
\x09\x09else if (post[i] =='+')
\x09\x09{
\x09\x09\x09x2 = stack.pop();
\x09\x09\x09x1 = stack.pop();
\x09\x09\x09stack.push(x1+x2);
\x09\x09\x09i++;
\x09\x09}
\x09\x09else if (post[i] =='-')
\x09\x09{
\x09\x09\x09x2 = stack.pop();
\x09\x09\x09x1 = stack.pop();
\x09\x09\x09stack.push(x1-x2);
\x09\x09\x09i++;
\x09\x09}
\x09\x09else if (post[i] =='*')
\x09\x09{
\x09\x09\x09x2 = stack.pop();
\x09\x09\x09x1 = stack.pop();
\x09\x09\x09stack.push(x1*x2);
\x09\x09\x09i++;
\x09\x09}
\x09\x09else if (post[i] =='/')
\x09\x09{
\x09\x09\x09x2 = stack.pop();
\x09\x09\x09x1 = stack.pop();
\x09\x09\x09stack.push(x1/x2);
\x09\x09\x09i++;
\x09\x09}
\x09}
\x09return stack.gettop();
}
再问: 负数的怎么处理呢,谢谢
再答: char exp[100] ;
 \x09int z=0;
\x09 for(int i =0;i<100;i++){
 \x09\x09if(i==0 && a[0] == '-'){
\x09\x09 \x09exp[0]='(';
\x09\x09 \x09exp[1]='0';
\x09\x09 \x09exp[2]=a[0];
\x09\x09 \x09exp[3]=a[1];
\x09\x09 \x09exp[4]=')';
\x09\x09 \x09i++;
\x09\x09 \x09z= 5;
\x09\x09 }else if(a[i]=='-' && (a[i-1] == '+')|(a[i-1] == '-')|(a[i-1] == '*')|(a[i-1] == '/')){
 \x09\x09\x09exp[z]='(';
 \x09\x09\x09exp[z+1]='0';
\x09\x09 \x09exp[z+2]=a[i];
\x09\x09 \x09exp[z+3]=a[i+1];
\x09\x09 \x09exp[z+4]=')';
 \x09\x09\x09i++;
 \x09\x09\x09z+=5;
 \x09\x09}else{
\x09\x09 \x09exp[z]=a[i];
\x09\x09 \x09z++;
\x09\x09 }
 \x09}将输入的字符窜变成-3+6*-5  ---> (0-3)+6*(0-5)
 \x09这是取巧的办法,谁让你只有5分啊,你赚大发了,5分没人做的