c/c++ 表达式求值

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

[问题描述]
一个算术表达式是由操作数(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) 只能处理一位数的加、减、乘、除表达式计算(可带括号)


 

相关文章
|
4月前
|
程序员 编译器 C++
【实战指南】C++ lambda表达式使用总结
Lambda表达式是C++11引入的特性,简洁灵活,可作为匿名函数使用,支持捕获变量,提升代码可读性与开发效率。本文详解其基本用法与捕获机制。
176 48
|
7月前
|
编译器 C++ 容器
【c++11】c++11新特性(上)(列表初始化、右值引用和移动语义、类的新默认成员函数、lambda表达式)
C++11为C++带来了革命性变化,引入了列表初始化、右值引用、移动语义、类的新默认成员函数和lambda表达式等特性。列表初始化统一了对象初始化方式,initializer_list简化了容器多元素初始化;右值引用和移动语义优化了资源管理,减少拷贝开销;类新增移动构造和移动赋值函数提升性能;lambda表达式提供匿名函数对象,增强代码简洁性和灵活性。这些特性共同推动了现代C++编程的发展,提升了开发效率与程序性能。
281 12
|
12月前
|
算法 编译器 C++
【C++11】lambda表达式
C++11 引入了 Lambda 表达式,这是一种定义匿名函数的方式,极大提升了代码的简洁性和可维护性。本文详细介绍了 Lambda 表达式的语法、捕获机制及应用场景,包括在标准算法、排序和事件回调中的使用,以及高级特性如捕获 `this` 指针和可变 Lambda 表达式。通过这些内容,读者可以全面掌握 Lambda 表达式,提升 C++ 编程技能。
522 3
|
C++ 算法
c++中 lambda 表达式 解析
c++中 lambda 表达式 解析
170 0
c++中 lambda 表达式 解析
|
算法 编译器 程序员
C++ 11新特性之Lambda表达式
C++ 11新特性之Lambda表达式
102 0
|
算法 编译器 C++
C++一分钟之—Lambda表达式初探
【6月更文挑战第22天】C++的Lambda表达式是匿名函数的快捷方式,增强函数式编程能力。基本语法:`[capture](params) -&gt; ret_type { body }`。例如,简单的加法lambda:`[](int a, int b) { return a + b; }`。Lambda可用于捕获外部变量(值/引用),作为函数参数,如在`std::sort`中定制比较。注意点包括正确使用捕获列表、`mutable`关键字和返回类型推导。通过实践和理解这些概念,可以写出更简洁高效的C++代码。
261 13
|
安全 编译器 C++
C++一分钟之-泛型Lambda表达式
【7月更文挑战第16天】C++14引入泛型lambda,允许lambda接受任意类型参数,如`[](auto a, auto b) { return a + b; }`。但这也带来类型推导失败、隐式转换和模板参数推导等问题。要避免这些问题,可以明确类型约束、限制隐式转换或显式指定模板参数。示例中,`safeAdd` lambda使用`static_assert`确保只对算术类型执行,展示了一种安全使用泛型lambda的方法。
199 1
C++语言的lambda表达式
C++从函数对象到lambda表达式以及操作参数化
|
C++
C++一分钟之-理解C++的运算符与表达式
【6月更文挑战第18C++的运算符和表达式构成了编程的基础,涉及数学计算、逻辑判断、对象操作和内存管理。算术、关系、逻辑、位、赋值运算符各有用途,如`+`、`-`做加减,`==`、`!=`做比较。理解运算符优先级和结合律至关重要。常见错误包括优先级混淆、整数除法截断、逻辑运算符误用和位运算误解。解决策略包括明确优先级、确保浮点数除法、正确使用逻辑运算符和谨慎进行位运算。通过实例代码学习,如 `(a &gt; b) ? &quot;greater&quot; : &quot;not greater&quot;`,能够帮助更好地理解和应用这些概念。掌握这些基础知识是编写高效、清晰C++代码的关键。
150 3
|
C语言 C++ 容器
c++primer plus 6 读书笔记 第五章 循环和关系表达式
c++primer plus 6 读书笔记 第五章 循环和关系表达式

热门文章

最新文章