zoukankan      html  css  js  c++  java
  • c/c++ 表达式求值

    表达式求值

    [问题描述]
    一个算术表达式是由操作数(operand)、运算符(operator)和界限符(delimiter)组成的。假设操作数是正整数,运算符只含加减乘除等四种运算符,界限符有左右括号和表达式起始、结束符“#”,如:#(7+15)*(23-28/4)#。引入表达式起始、结束符是为了方便。编程利用“算符优先法”求算术表达式的值。

    [基本要求]
    (1) 从键盘读入一个合法的算术表达式,输出正确的结果。
    (2) 显示输入序列和栈的变化过程。

    [选作内容]
    (1) 扩充运算符集合。
    (2) 引入变量操作数。
    (3) 操作数类型扩充到实数。

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <conio.h>
    
    #define TRUE 1
    #define FALSE 0
    #define Stack_Size 50
    
    char ops[7]={'+','-','*','/','(',')','#'};  /*运算符数组*/
    
    int  cmp[7][7]={{2,2,1,1,1,2,2},    /*用来进行比较运算符优先级的矩阵,3代表'=',2代表'>',1代表'<',0代表不可比*/
                    {2,2,1,1,1,2,2},
                    {2,2,2,2,1,2,2},
                    {2,2,2,2,1,2,2},
                    {1,1,1,1,1,3,0},
                    {2,2,2,2,0,2,2},
                    {1,1,1,1,1,0,3}};
    
    typedef struct
    { 
    	char elem[Stack_Size];
    	int top;
    }SeqStack;     /*运算符栈的定义*/
    
    typedef struct
    {
    	int elem[Stack_Size];
    	int top;
    }nSeqStack;   /* 运算数栈的定义*/
    
    
    void InitStack(SeqStack *S)   /*初始化运算符栈*/
    {
    	S->top =-1;
    }
    
    void InitStackn(nSeqStack *S)   /*初始化运算数栈*/
    {
    	S->top =-1;
    }
    
    int IsEmpty(SeqStack *S)    /*判断栈S为空栈时返回值为真,反之为假*/
    {
    	return(S->top==-1?TRUE:FALSE);
    }
    
    int IsEmptyn(nSeqStack *S)    /*判断栈S为空栈时返回值为真,反之为假*/
    {
    	return(S->top==-1?TRUE:FALSE);
    }
    
    /*判栈满*/
    int IsFull(SeqStack *S)	    /*判断栈S为满栈时返回值为真,反之为假*/
    {
    	return(S->top==Stack_Size-1?TRUE:FALSE);
    }
    
    int IsFulln(nSeqStack *S)	    /*判断栈S为满栈时返回值为真,反之为假*/
    {
    	return(S->top==Stack_Size-1?TRUE:FALSE);
    }
    
    int Push(SeqStack *S, char x)   /*运算符栈入栈函数*/
    {
    	if (S->top==Stack_Size-1)
    	{
    		printf("Stack is full!
    ");
    		return FALSE;
    	}
    	else
    	{
    		S->top++;
    		S->elem[S->top]=x;
    		return TRUE;
    	}
    }
    
    int Pushn(nSeqStack *S, int x)   /*运算数栈入栈函数*/
    {
    	if (S->top==Stack_Size-1)
    	{
    		printf("Stack is full!
    ");
    		return FALSE;
    	}
    	else
    	{
    		S->top++;
    		S->elem[S->top]=x;
    		return TRUE;
    	}
    }
     
    int Pop(SeqStack *S, char *x)    /*运算符栈出栈函数*/
    {
    	if (S->top==-1)
    	{
    		printf("运算符栈空!
    ");
    		return FALSE;
    	}
    	else
    	{
    		*x=S->elem[S->top];
    		S->top--;
    		return TRUE;
    	}
    }
     
    int Popn(nSeqStack *S, int *x)    /*运算数栈出栈函数*/
    {
    	if (S->top==-1)
    	{
    		printf("运算符栈空!
    ");
    		return FALSE;
    	}
    	else
    	{
    		*x=S->elem[S->top];
    		S->top--;
    		return TRUE;
    	}
    }
    
    char GetTop(SeqStack *S)    /*运算符栈取栈顶元素函数*/     
    {
    	if (S->top ==-1)
    	{
    		printf("运算符栈为空!
    ");
    		return FALSE;
    	}
    	else
    	{
    		return (S->elem[S->top]);
    	}
    }
    
    int GetTopn(nSeqStack *S)    /*运算数栈取栈顶元素函数*/     
    {
    	if (S->top ==-1)
    	{
    		printf("运算符栈为空!
    ");
    		return FALSE;
    	}
    	else
    	{
    		return (S->elem[S->top]);
    	}
    }
    
    
    int Isoperator(char ch)        /*判断输入字符是否为运算符函数,是返回TRUE,不是返回FALSE*/
    {
    	int i;
    	for (i=0;i<7;i++)
    	{
    		if(ch==ops[i])
    			return TRUE;
    	}
    	return FALSE;
    }
    
    /*
    int isvariable(char ch)
    { if (ch>='a'&&ch<='z')
          return true;
       else 
    	   return false;
    }*/
    
    
    char Compare(char ch1, char ch2)   /*比较运算符优先级函数*/
    {
    	int i,m,n;
    	char pri;
    	int priority;
    	for(i=0;i<7;i++)              /*找到相比较的两个运算符在比较矩阵里的相对位置*/
    	{
    		if(ch1==ops[i])	
    			m=i;
    		if (ch2==ops[i])
    			n=i;
    	}
    
    	priority = cmp[m][n];
    	switch(priority)
    	{
    	case 1:
    		pri='<';
    		break;
    	case 2:
    		pri='>';
    		break;
    	case 3:
    		pri='=';
    		break;
    	case 0:
    		pri='$';
    		printf("表达式错误!
    ");
    		break;
    	}
    	return pri;
    }
    	
    int Execute(int a, char op, int b)    /*运算函数*/
    {
    	int result;
    	switch(op)
    	{
    	case '+':
    		result=a+b;
    		break;
    	case '-':
    		result=a-b;
    		break;
    	case '*':
    		result=a*b;
    		break;
    	case '/':
    		result=a/b;
    		break;
    	}
        return result;
    }
    
    int ExpEvaluation() 
    /*读入一个简单算术表达式并计算其值。optr和operand分别为运算符栈和运算数栈,OPS为运算符集合*/
    {
    	int a,b,v,temp;
    	char ch,op;
    	char *str;
    	int i=0;
    	
    	SeqStack optr;
    	nSeqStack operand;
    
    	InitStack(&optr);
    	InitStackn(&operand);
    	Push(&optr,'#');
    	printf("请输入表达式(以#结束):
    ");            /*表达式输入*/
    	str =(char *)malloc(50*sizeof(char));
    	gets(str);
    
    	ch=str[i];
    	i++;
    	while(ch!='#'||GetTop(&optr)!='#')
    	{ 
    		if(!Isoperator(ch))
    		{
    			temp=ch-'0';    /*将字符转换为十进制数*/
    			ch=str[i];
    			i++;
    			while(!Isoperator(ch))
    			{
    				temp=temp*10 + ch-'0'; /*将逐个读入运算数的各位转化为十进制数*/
    				ch=str[i];
    				i++;
    			}
    			Pushn(&operand,temp);
    		}
    		else
    		{
    			switch(Compare(GetTop(&optr),ch))
    			{
    			case '<':
    				Push(&optr,ch); 
    				ch=str[i];
    				i++;
    				break;
    			case '=':
    				Pop(&optr,&op);
    				ch=str[i];
    				i++;
    				break;
    			case '>':
    				Pop(&optr,&op);
    				Popn(&operand,&b);
    				Popn(&operand,&a);
    				v=Execute(a,op,b);  /* 对a和b进行op运算 */
    				Pushn(&operand,v);
    				break;
    			}
    		}		
    	}
    	v=GetTopn(&operand);
    	return v;
    }
    
    void main()                               /*主函数*/
    {
    	int result;
    	result=ExpEvaluation();
    	printf("
    表达式结果是%d
    ",result);
    }	
    
    
    
    
    
    
    


     

    下面这个是在网上找的:

    用 C++ 实现的加、减、乘、除表达式计算
    
    前些日子面试一个开发工作,考官出了这么一笔试题目,要我写出实现过程, 思量半天,终于
    用 C++ 完成,现将代码贴出,与诸同道共分享。
    
    // 头文件 Calc.h
    #ifndef __CALC_H__
    #define __CALC_H__
    #include <stack>
    #define ascii_int(x) (x >= 0x30 && x <= 0x39) ? (x - 0x30) : (x)
    const int GREATER =  1;
    const int EQUAL   =  0;
    const int LESS    = -1;
    class Calculate {
    public:
      int  evaluteExpr(char *exp);
    private:
      int  getLevel(char ch);
      bool isOperator(char ch);
      int  compareOpteratorLevel(char inputChar, char optrStackTop);
      int  calc(int num1, int num2, char op);
      void evaluate(char ch);
    private:
      std::stack<int>  _opnd_stack;
      std::stack<char> _optr_stack;
      static char _optr[];
      static int  _level[];
    };
    #endif
    
    
    // 头文件的实现代码 Calc.cxx
    #include "Calc.h"
    char Calculate::_optr[] = {'#', '(', '+', '-', '*', '/', ')'};
    int Calculate::_level[] = { 0,   1,   2,   2,   3,   3,   4 };
    // Get current operator level for calculating
    int Calculate::getLevel(char ch) {
      for (int i = 0; *(_optr+i) != ''; ++i) 
        if (*(_optr+i) == ch) 
          return *(_level+i);
    }
    // Calculate the operands
    int Calculate::calc(int num1, int num2, char op) {
      switch (op) 
        {
        case '+':
          return num1 + num2;
        case '-':
          return num1 - num2;
        case '*':
          return num1 * num2;
        case '/':
          return num1 / num2;
        }
    }
    // judge inputing character is operator or not
    bool Calculate::isOperator(char ch) {
      for (char *p = _optr; *p != ''; ++p)
        if (*p == ch) 
          return true;
      return false;
    }
    // Compare level of input operator and the top operator of operator stack
    int Calculate::compareOpteratorLevel(char inputChar, char optrStackTop) {
    //   if (inputChar == '(' && optrStackTop == ')') 
    //     return EQUAL;
    //   else 
      if (inputChar == '(')
        return GREATER;
      if (inputChar == ')' && optrStackTop == '(') 
        return EQUAL;
      else if (inputChar == ')') 
        return LESS;
      if (inputChar == '#' && optrStackTop == '#') 
        return EQUAL;
    //   else if (inputChar == '#')
    //     return LESS;
      return (getLevel(inputChar) > getLevel(optrStackTop)) ? GREATER : LESS;
    }
    // Evaluate value while inputing operators
    void Calculate::evaluate(char ch) {
      char op;
      int num, result;
      if (!isOperator(ch)) {
        _opnd_stack.push(ascii_int(ch));
        return ;
      }
      switch (compareOpteratorLevel(ch, _optr_stack.top())) 
        {
        case GREATER :
          _optr_stack.push(ch);
          break;
        case EQUAL :
          _optr_stack.pop();
          break;
        case LESS :
          num = _opnd_stack.top();
          _opnd_stack.pop();
          result = _opnd_stack.top();
          _opnd_stack.pop();
          op = _optr_stack.top();
          _optr_stack.pop();
          result = calc(result, num, op);
          _opnd_stack.push(result);
          evaluate(ch);
          break;
        }
    }
    // Evaluate user specified expression
    int Calculate::evaluteExpr(char *exp) {
      _optr_stack.push('#');
      for (char *p =exp; *p != ''; ++p )
        evaluate(*p);
      int result = _opnd_stack.top();
      _opnd_stack.pop();
      return result;
    }
    
    
    // 测试代码 calc_test.cxx
    #include <iostream>
    #include "Calc.h"
    using namespace std;
    int main(void) {
      Calculate *calc = new Calculate();
      cout << "1+3*(4+7) = " 
           << calc->evaluteExpr("1+3*(4+7)#") 
           << endl;
      cout << "((1+2)) = " 
           << calc->evaluteExpr("((1+2))#") 
           << endl;
      cout << "3*8+9/7-5-9+(1-9)/4 = " 
           << calc->evaluteExpr("3*8+9/7-5-9+(1-9)/4#") 
           << endl;
      cout << "(6-7)*(5+9) = " 
           << calc->evaluteExpr("(6-7)*(5+9)#") 
           << endl;
      cout << "0*8+0/6-9+(7-1) = " 
           << calc->evaluteExpr("0*8+0/6-9+(7-1)#") 
           << endl;
      delete calc;
    }
    
    用 MinGW/G++ 3.4.5 编译如下: 
      g++  -o test.exe  Calc.cxx  Calc_test.cxx
    
    作为一个演示算法够了, 但代码还是有一些缺点:
       (1) 只能处理一位数的加、减、乘、除表达式计算(可带括号)


     

  • 相关阅读:
    Tcp/IP协议详讲
    LoadRunner生成测试报告
    Lombok Requires Annotation Processing
    js数组、对象、数组中套对象等的“复制”(不改变原来的值)的方法,
    一篇文章学完Mysql
    element中<el-input输入值后不变
    JS判断输入值是否为正整数等
    el-input类型为number时禁止输入e和.
    element-ui升级
    ndroid Studio 连接自己搭建的服务器 需要admin 的帐号的问题 SSH Password Login,please enter password for user git@git.
  • 原文地址:https://www.cnblogs.com/wuyida/p/6301417.html
Copyright © 2011-2022 走看看