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!\n");
		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!\n");
		return FALSE;
	}
	else
	{
		S->top++;
		S->elem[S->top]=x;
		return TRUE;
	}
}
 
int Pop(SeqStack *S, char *x)    /*运算符栈出栈函数*/
{
	if (S->top==-1)
	{
		printf("运算符栈空!\n");
		return FALSE;
	}
	else
	{
		*x=S->elem[S->top];
		S->top--;
		return TRUE;
	}
}
 
int Popn(nSeqStack *S, int *x)    /*运算数栈出栈函数*/
{
	if (S->top==-1)
	{
		printf("运算符栈空!\n");
		return FALSE;
	}
	else
	{
		*x=S->elem[S->top];
		S->top--;
		return TRUE;
	}
}

char GetTop(SeqStack *S)    /*运算符栈取栈顶元素函数*/     
{
	if (S->top ==-1)
	{
		printf("运算符栈为空!\n");
		return FALSE;
	}
	else
	{
		return (S->elem[S->top]);
	}
}

int GetTopn(nSeqStack *S)    /*运算数栈取栈顶元素函数*/     
{
	if (S->top ==-1)
	{
		printf("运算符栈为空!\n");
		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("表达式错误!\n");
		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("请输入表达式(以#结束):\n");            /*表达式输入*/
	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("\n表达式结果是%d\n",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) != '\0'; ++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 != '\0'; ++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 != '\0'; ++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) 只能处理一位数的加、减、乘、除表达式计算(可带括号)


 

posted on 2014-11-02 20:46  吴一达  阅读(575)  评论(0编辑  收藏  举报

导航