c语言:表达式求值实现(包含加减乘除括号)

这道题不难,但是当你认真去编代码的时候,还是要考虑好多细节,所以不能只停留在看懂的层面上,不去实践你永远不知道你到底掌握了没有,加油!

之前的表达式求值不包括括号运算,现将改进后的代码和源代码粘在上面,便于以后的复习。

一.不包括括号运算

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string>
#include<math.h>
#define STACK_INIT_SIZE 100
using namespace std;
typedef struct
{
    char date[STACK_INIT_SIZE];
    int top;
}OptrStack;     //操作符结构体    

typedef struct
{
    double date[STACK_INIT_SIZE];
    int top;
}OpndStack;     //操作数结构体    

//操作符相关操作
OptrStack *Init_OptrStack();    //置栈空
int Empty_OptrStack(OptrStack *s);//判空栈
int Push_OptrStack(OptrStack *s, char x);//入栈(注意:判断栈是否已满)
char Pop_OptrStack(OptrStack *s, char x);//出栈(注意:判断栈是否已空)
char GetTop_OptrStack(OptrStack *s, char x);//取栈顶元素,先判空  

//操作数相关操作
OpndStack *Init_OpndStack();//置栈空
int Empty_OpndStack(OpndStack *t);//判空栈
int  Push_OpndStack(OpndStack *t, double y);//入栈(注意:判断栈是否已满)
double Pop_OpndStack(OpndStack *t, double y);//出栈(注意:判断栈是否已空)
double GetTop_OpndStack(OpndStack *t, double y);//取栈顶元素  

//表达式求值函数
void Error(char *s);                  //错误处理函数
int Judge_optr(char ch);              //用于判断字符ch是否是运算符
int Operate(int a, int b, char top);  //用于计算当前的值,并将该值返回
void Jsbds_operate(char str[]);        //读入一个简单算术表达式的值  

//操作符函数实现部分
OptrStack *Init_OptrStack()
{
    OptrStack *s;
    s = (OptrStack *)malloc(sizeof(OptrStack));
    s->top = -1;
    return s;
}
int Empty_OptrStack(OptrStack *s)//判空栈
{
    if (s->top != -1)
        return 1;
    else
        return 0;
}
int  Push_OptrStack(OptrStack *s, char x)//入栈(注意:判断栈是否已满)
{
    if (s->top == (STACK_INIT_SIZE - 1))
    {
        return 0;
    }
    else
        s->date[++s->top] = x;
    return 1;  

}
char Pop_OptrStack(OptrStack *s, char x)//出栈(注意:判断栈是否已空)
{
    if (!Empty_OptrStack(s))
    {
        return 0;
    }
    else
    x = s->date[s->top];
    s->top--;
    return x;
}
char GetTop_OptrStack(OptrStack *s, char x)//取栈顶元素,先判空
{
    if (!Empty_OptrStack(s))
    {
        return 0;
    }
    else
        x = s->date[s->top];
    return x;
}
//操作数函数实现部分
OpndStack *Init_OpndStack()//置栈空
{
    OpndStack *t;
    t = (OpndStack*)malloc(sizeof(OpndStack));
    t->top = -1;
    return t;
}
int Empty_OpndStack(OpndStack *t)//判空栈
{
    if (t->top != -1)
        return 1;
    else
        return 0;
}
int  Push_OpndStack(OpndStack *t, double y)//入栈(注意:判断栈是否已满)
{
    if (t->top == (STACK_INIT_SIZE - 1))
    {
        return 0;
    }
    else
        t->date[++t->top] = y;
    return 1;
}
double Pop_OpndStack(OpndStack *t, double y)//出栈(注意:判断栈是否已空)
{
    if (!Empty_OpndStack(t))
    {
        return 0;
    }
    else
    y = t->date[t->top];
    t->top--;
    return y;
}
double GetTop_OpndStack(OpndStack *t, double y)//取栈顶元素
{
    if (!Empty_OpndStack(t))
    {
        return 0;
    }
    y = t->date[t->top];
    return y;
}  

//表达式求值函数实现
void Error(char *s)   //错误处理函数
{
    std::cout << s << endl;
    exit(1);
}
int Judge_optr(char top)//用于判断字符ch是否是运算符
{
    int x;
    //cout << top << "test" << endl;
    switch (top)
    {
    case '+':
    case '-':
        x = 1; break;
    case '*':
    case '/':
        x = 2; break;
    }
    return x;
}
double Operate(double b, double a, char top)  //用于计算当前的值,并将该值返回
{
    double c = 0;
    switch (top)
    {
    case '+':
        c = b + a;
        break;
    case '-':
        c = b - a;
        break;
    case '*':
        c = b * a;
        break;
    case '/':
        if (a == 0)
        {
            printf("分母为零!\n");
            return 0;
        }
        else
            c = b / a;
        break;
    default:
        printf("输入的字符非法!\n");
        break;
    }
    return c;
}
void Jsbds_operate(char str[])             //读入一个简单算术表达式,并将计算结果返回到主函数
{
    OptrStack *optr = Init_OptrStack();     //初始化操作符栈
    OpndStack *opnd = Init_OpndStack();     //初始化操作数栈
    int i, j;                               //i,j为循环变量,a,b接收从操作数栈中出栈的元素
    double f;                               //接收将字符数转换为浮点数的值
    double a = 0;
    double b = 0;
    double c = 0;
    char d[100];                           //储存字符串中连续的‘数’
    char top = 0;                          //接收从操作符栈中出栈的元素
    for (i = 0; str[i]; i++)               //将字符串中的元素按顺序入到栈中
    {
        switch (str[i])
        {
        case '+':
        case '-':
            /*先判断当前运算符与操作符栈栈顶元素的优先级,如果高于栈顶元素,则入栈;
            小于栈顶元素,则从操作数栈中依次出两个数,并将操作符栈中栈顶元素出栈,
            再将从操作数栈中出的两个数,按从操作符栈栈中出的运算符运算,
            并将结果压入操作数栈中,再将当前的操作符压入操作符栈中。*/
            if (!Empty_OptrStack(optr))  //当操作符栈为空的时候压栈保存
            {
                Push_OptrStack(optr, str[i]);
            }
            else
            {
                a = Pop_OpndStack(opnd, a); //接收从操作数栈中出栈的元素
                b = Pop_OpndStack(opnd, b); //接收从操作数栈中出栈的元素
                top = Pop_OptrStack(optr, top);//接收从操作符栈中出栈的元素
                c = Operate(b, a, top);
                Push_OpndStack(opnd, c);
                //将计算后的值压入操作数栈中
                Push_OptrStack(optr, str[i]);
            }
            break;
        case '*':
        case '/':
            if ((!Empty_OptrStack(optr))||(Judge_optr(str[i]) > Judge_optr(GetTop_OptrStack(optr, top))))
            { //当操作符栈为空或者该操作符的优先级大于栈顶元素的优先级是入栈保存
                Push_OptrStack(optr, str[i]);
            }
            else
            {
                a = Pop_OpndStack(opnd, a);//接收从操作数栈中出栈的元素
                b = Pop_OpndStack(opnd, b);//接收从操作数栈中出栈的元素
                top = Pop_OptrStack(optr, top);//接收从操作符栈中出栈的元素
                c = Operate(b, a, top);
                Push_OpndStack(opnd, c);
                //将计算后的值压入操作数栈中
                Push_OptrStack(optr, str[i]);
            }
        case '\0':
            break;
        default:
            j = 0;
            do
            {
                d[j++] = str[i];
                i++;
            } while (str[i] >= '0' && str[i] <= '9');  //可存入一个或多个数字字符
            d[j] = '\0';                  //将输入的连续多个数字字符拼成了字符串
            i--;
            f = atof(d);                //调用库函数atoi()将字符数转换为浮点数
            Push_OpndStack(opnd, f);    //将转换后的数压入操作数栈中
            break;
        }
    }
    while (Empty_OptrStack(optr))  //当操作符栈不为空的时候执行
    {
        a = Pop_OpndStack(opnd, a);//接收从操作数栈中出栈的元素
        b = Pop_OpndStack(opnd, b);//接收从操作数栈中出栈的元素
        top = Pop_OptrStack(optr, top);//接收从操作符栈中出栈的元素
        c = Operate(b, a, top);
        Push_OpndStack(opnd, c);
        //将计算后的值压入操作数栈中
    }
    cout << "该表达式的计算结果为:";
    std::cout << GetTop_OpndStack(opnd, c) << endl;//将操作数栈中的元素(即表达式的最终结果)打印出来
}  

int main()
{
    char str[100];
    std::cout << "请输入算术表达式(功能:+,-,*,/)" << endl;
    cin >> str;
    Jsbds_operate(str);
    return 0;
}  

二.包括括号运算(粘贴修改部分)

int Judge_optr(char top)//用于判断字符ch是否是运算符
{
	int x;
	//cout << top << "test" << endl;
	switch (top)
	{
	case '(':
		x = 0; break;
	case '+':
	case '-':
		x = 1; break;
	case '*':
	case '/':
		x = 2; break;
	case ')':
		x = 3; break;
	}
	return x;
}
double Operate(double b, double a, char top)  //用于计算当前的值,并将该值返回
{
	double c = 0;
	switch (top)
	{
	case '+':
		c = b + a;
		break;
	case '-':
		c = b - a;
		break;
	case '*':
		c = b * a;
		break;
	case '/':
		if (a == 0)
		{
			printf("分母为零!\n");
			return 0;
		}
		else
			c = b / a;
		break;
	default:
		printf("输入的字符非法!\n");
		break;
	}
	return c;
}
void Jsbds_operate(char str[])             //读入一个简单算术表达式,并将计算结果返回到主函数
{
	OptrStack *optr = Init_OptrStack();     //初始化操作符栈
	OpndStack *opnd = Init_OpndStack();     //初始化操作数栈
	int i, j;                               //i,j为循环变量,a,b接收从操作数栈中出栈的元素
	double f;                               //接收将字符数转换为浮点数的值
	double a = 0;
	double b = 0;
	double c = 0;
	char d[100];                           //储存字符串中连续的‘数’
	char top = 0;                          //接收从操作符栈中出栈的元素
	for (i = 0; str[i]; i++)               //将字符串中的元素按顺序入到栈中
	{
		switch (str[i])
		{
		case '(':
		case '+':
		case '-':
			/*先判断当前运算符与操作符栈栈顶元素的优先级,如果高于栈顶元素,则入栈;
			小于栈顶元素,则从操作数栈中依次出两个数,并将操作符栈中栈顶元素出栈,
			再将从操作数栈中出的两个数,按从操作符栈栈中出的运算符运算,
			并将结果压入操作数栈中,再将当前的操作符压入操作符栈中。*/
			if ((!Empty_OptrStack(optr)) || (Judge_optr(str[i]) > Judge_optr(GetTop_OptrStack(optr, top)))||(str[i]=='('))  //当操作符栈为空的时候压栈保存
			{
				Push_OptrStack(optr, str[i]);
			}
			else
			{
				a = Pop_OpndStack(opnd, a); //接收从操作数栈中出栈的元素
				b = Pop_OpndStack(opnd, b); //接收从操作数栈中出栈的元素
				top = Pop_OptrStack(optr, top);//接收从操作符栈中出栈的元素
				c = Operate(b, a, top);
				Push_OpndStack(opnd, c);
				//将计算后的值压入操作数栈中
				Push_OptrStack(optr, str[i]);
			}
			break;
		case '*':
		case '/':
			if ((!Empty_OptrStack(optr)) || (Judge_optr(str[i]) > Judge_optr(GetTop_OptrStack(optr, top))) || (str[i] == '('))
			{ //当操作符栈为空或者该操作符的优先级大于栈顶元素的优先级是入栈保存
				Push_OptrStack(optr, str[i]);
			}
			else
			{
				a = Pop_OpndStack(opnd, a);//接收从操作数栈中出栈的元素
				b = Pop_OpndStack(opnd, b);//接收从操作数栈中出栈的元素
				top = Pop_OptrStack(optr, top);//接收从操作符栈中出栈的元素
				c = Operate(b, a, top);
				Push_OpndStack(opnd, c);
				//将计算后的值压入操作数栈中
				Push_OptrStack(optr, str[i]);
			}
			break;
		case ')':
			Push_OptrStack(optr, str[i]);
			break;
		case '\0':
			break;
		default:
			j = 0;
			do
			{
				d[j++] = str[i];
				i++;
			} while (str[i] >= '0' && str[i] <= '9');  //可存入一个或多个数字字符
			d[j] = '\0';                  //将输入的连续多个数字字符拼成了字符串
			i--;
			f = atof(d);                //调用库函数atoi()将字符数转换为浮点数
			Push_OpndStack(opnd, f);    //将转换后的数压入操作数栈中
			break;
		}
	}
	while (Empty_OptrStack(optr))  //当操作符栈不为空的时候执行
	{
		if ((GetTop_OptrStack(optr, top) == ')') || (GetTop_OptrStack(optr, top) == '('))
		{
		top=Pop_OptrStack(optr, top);
		}
		else
		{
			a = Pop_OpndStack(opnd, a);//接收从操作数栈中出栈的元素
			b = Pop_OpndStack(opnd, b);//接收从操作数栈中出栈的元素
			top = Pop_OptrStack(optr, top);//接收从操作符栈中出栈的元素
			c = Operate(b, a, top);
			Push_OpndStack(opnd, c);
			//将计算后的值压入操作数栈中
		}
	}
	cout << "该表达式的计算结果为:";
	std::cout << GetTop_OpndStack(opnd, c) << endl;//将操作数栈中的元素(即表达式的最终结果)打印出来
}
时间: 2024-12-07 23:49:33

c语言:表达式求值实现(包含加减乘除括号)的相关文章

序列点在C语言表达式求值中的作用

摘要: 本文开创性地分析了序列点在C语言表达式求值中的作用:序列点左边的操作数要先于其右边的操作数求值.讨论了逗号操作符,.逻辑与操作符&&.逻辑或操作符||和条件操作符?:的问号处需要序列点的原因.举例分析了序列点在表达式求值中的作用. 关键字:序列点 表达式求值 C语言 C语言作为一种主流程序设计语言,许多编程语言如Java.C++.C#都借鉴了它的语法.C语言也是一种很适当的程序设计入门的教学语言,国内大专院校的许多专业都开设了这门课程并且大多将其作为第一门程序设计语言课程,同时C语

表达式求值:从“加减”到“带括号的加减乘除”的实践过程

本文乃Siliphen原创,转载请注明出处:http://blog.csdn.net/stevenkylelee ● 为什么想做一个表达式求值的程序 最近有一个需求,策划想设置游戏关卡的某些数值,这个数值不是一个常量,而是根据关卡的某些环境数据套上一个计算表达式算出来的.这个需求无法用excel拖表预计算出,因为关卡的环境数据只有在游戏中才能产生,在excel制表时,这些都是未知的.作为程序员,我可以把计算表达式硬编码在代码中,但这个做法有缺陷,如果策划要修改计算表达式的话,只能通过我修改程序并

数据结构算法C语言实现(八)--- 3.2栈的应用举例:迷宫求解与表达式求值

一.简介 迷宫求解:类似图的DFS.具体的算法思路可以参考书上的50.51页,不过书上只说了粗略的算法,实现起来还是有很多细节需要注意.大多数只是给了个抽象的名字,甚至参数类型,返回值也没说的很清楚,所以很多需要自己揣摩.这也体现了算法和程序设计语言的特点,算法更侧重本质的描述,而任何编程语言都要照顾到实现的细节以及数据类型等语法方面的需求. 表达式求值: [编码中....] 二.头文件 迷宫求解: 1 //3_2_maze.h 2 /** 3 author:zhaoyu 4 email:[em

C/C++ 语言中的表达式求值

蛱酝缒 C/C++ 语言中的表达式求值

一起talk C栗子吧(第二十一回:C语言实例--表达式求值)

各位看官们,大家好,前几回中咱们说了堆栈的原理,并且举了实际的例子进行解说,这一回咱们说的例 子是:表达式求值.表达式求值和上一回中说的括号匹配一样,都使用了堆栈的原理,大家可以从例子中 看出来,所以我们把它们放在一起.闲话休提,言归正转.让我们一起talk C栗子吧! 看官们,我们在这里说的表达式为包含加,减,乘除的四则运算表达式.例如:1+2*3-4/5就是一个四则运 算表达式.这个表达式中,运算符在数字中间,所以我们叫它中缀表达式,这也是符合我们思维的一种表 现形式,不过,计算机就不理解中

Go 表达式求值器

示例:表达式求值器 本篇将创建简单算术表达式的一个求值器. 定义接口和类型 开始,先确定要使用一个接口 Expr 来代表这种语言的任意一个表达式.暂时没有任何方法,稍后再逐个添加: // Expr: 算术表达式 type Expr interface{} 我们的表达式语言将包括以下符号: 浮点数字面量 二元操作符:加减乘除(+.-.*.\/) 一元操作符:表示正数和负数的 -x 和 +x 函数调用:pow(x,y).sin(x) 和 sqrt(x) 变量:比如 x.pi,自己定义一个变量名称,每

栈的典型应用-表达式求值【转】

本文转载自:http://www.voidcn.com/blog/lub0807/article/p-1510616.html 栈的一个应用是求四则运算表达式的值,这里的表达式包含数字.加减乘除4种运算符,以及小括号. 由于输入是一个字符串,因此解决这个问题需要以下3个步骤: 1.输入字符串转化为中缀表达式: 2.中缀表达式转化为后缀表达式: 3.后缀表达式求值. 现在表达式为:9 + ( 3 - 1 )* 3 + 10 / 2 ,先看一下运行结果: 首先解释一下中缀表达式和后缀表达式的概念.所

11、蛤蟆的数据结构笔记之十一栈的应用之表达式求值实现

11.蛤蟆的数据结构笔记之十一栈的应用之表达式求值实现 本篇名言:"人生不售来回票,一旦动身,绝不能复返." 继续栈应用实现,这次是来看下表达式求值的栈实现. 欢迎转载,转载请标明出处: 1.  表达式求值 表达式求值是设计语言编译中的一个基本问题,它的实现是栈应用的又一个典型例子. 任何一个表达式都是由操作数(Operand).运算符(operator)和界限符(delimiter)组成. 操作数可以是常数也可以是变量或变量的标识符. 运算符可以分为算术运算符.关系运算符和逻辑运算符

栈的应用——表达式求值

表达式求值是程序设计语言编译中的一个基本问题,它的实现就是对“栈”的典型应用.本文针对表达式求值使用的是最简单直观的算法“算符优先法”. 本文给出两种方式来实现表达式求值,方式一直接利用中缀表达式求值,需要用到两个栈,操作数栈和操作符栈.首先置操作数栈为空栈, 操作符栈仅有“#”一个元素.依次读入表达式中的每个字符,若是操作数则进操作数栈,若是操作符则和操作符栈的栈顶运算符比较优先权作相应操作,直至整个表达式求值完毕.方式二首先把中缀表达式转换为后缀表达式并存储起来,然后利用读出的后缀表达式完成