IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C语言-用栈实现表达式求值 -> 正文阅读

[C++知识库]C语言-用栈实现表达式求值

目录

目的描述:

算法的基本思想:

错误点:

完整代码:

1.输入输出

2.栈操作函数包(数组堆栈.h)

3.实现表达式求值函数包(表达式求值.c)

4.测试输出:


目的描述:

算符优先算法要实现的是,根据运算优先关系来对一个表达式求值,假如说要计算:

4+2*3-10/5

运算的顺序例如:

4+2*3-10/5? =? 4+6-10/5? =? 10-10/5? =? 10-2? =? 8 (开始不是很理解的话可以继续往下看)

算法的基本思想:

为实现算符优先算法,可以使用两个工作栈。一个称做?OPTR,用以寄存运算符;另一个称做?OPND,用以寄存操作数或运算结果。

(1)首先置操作数栈为空栈,表达式起始符“#”为运算符栈的栈底元素;
(2) 依次读人表达式中每个字符,若是操作数则进?OPND栈,若是运算符则和OPTR?栈的栈顶运算符比较优先权后作相应操作,直至整个表达式求值完毕(即?OPTR栈的栈顶元素和当前读人的字符均为“#”)

(3)在这里分别定义了两套对栈进行基本操作的函数,只有函数名改变其他均相同。这样做的原因是,在对寄存运算符时,需要字符栈;而寄存操作数或运算结果时,字符栈无法满足多位数的操作,所以这里采用数字栈(后来看到了另一位作者的文章,两个栈都采用数字栈也可以实现,并且会大大减少代码数量,原理就是在存放操作符的时候,将会转化成ASCII码的形式存入栈中)

(4)这里是两个最近的运算符的优先级关系表:(用来参考着写计算算符优先级的函数)

?(空白的地方是不可能存在的合法运算符关系,可忽略)

(5)通过利用对栈的基本操作函数,对两个栈进行操作,按步骤分解可以参考下表

?

错误点:

(记录一下自己遇到的错误)

(1)就是关于在寄存操作数或运算结果时开始没有考虑到有多位数的情况,我对多位数的处理是,设定了一个flag判断,如果连续getchar()得到的都是数字,就令flag=1;如果遇到了运算符,就令flag=0。

(2)在计算每一步结果的函数 Operate(double a, char theta, double b)里,当这是的操作是’-‘或者’/‘时,要注意a,b的顺序,因为栈的特点是LIFO(last in first out),所以除数和被除数,减数和被减数就会颠倒过来,要记得写成反的。

(3)记得判断输入getchar()为换行符’\n'时要跳出循环的判断。

完整代码:

1.输入输出

输入:一个只含有‘+’,‘-’,‘/’,‘*’,‘#’运算符和数字的运算表达式,中间没有空格,结尾以#结束

输出:一个整数计算结果

2.栈操作函数包(数组堆栈.h)

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
typedef char Elemtype1;//提供给存储运算符的栈使用
typedef double Elemtype2;//提供给存储操作数的栈使用

typedef struct {
	Elemtype1 *data;
	int top;//栈顶指针,这里用int类型表示指针的下标
	int stacksize;
} SqStack1;
Elemtype1 Pop1(SqStack1 *s);

typedef struct {
	Elemtype2 *data;
	int top;//栈顶指针,这里用int类型表示指针的下标
	int stacksize;
} SqStack2;
Elemtype2 Pop2(SqStack2 *s);

SqStack1 InitStack1() {//空栈构造函数
	SqStack1 s;
	s.data = (Elemtype1 *)malloc(STACK_INIT_SIZE * sizeof(Elemtype1));
	s.top = -1; //表示栈空
	s.stacksize = STACK_INIT_SIZE;
	if (s.data != NULL)
	{}
	else
		printf("Init error!\n");
	return s;
}

void DestroyStack1(SqStack1 *s) {//销毁栈函数
	free(s->data);
}

int StackEmpty1(SqStack1 *s) {//判断是否为空栈,是返回1,否 返回0
	if (s->top == -1)
		return 1;
	else
		return 0;
}

void ClearStack1(SqStack1 *s) {//清除栈
	while (StackEmpty1(s) != 1) {
		Pop1(s);
	}
}

void Push1(SqStack1 *s, Elemtype1 e) {//添加元素入栈
	if (s->top >= s->stacksize) {
		s->data = (Elemtype1 *)malloc((STACK_INIT_SIZE + STACKINCREMENT) * sizeof(Elemtype1));
		s->stacksize += STACKINCREMENT;
		if (s->data != NULL) {}
		else
			printf("Push error!\n");
	} else {
		s->top++;
		s->data[s->top] = e;
	}
}

Elemtype1 Pop1(SqStack1 *s) {//删除栈顶元素并返回其值,否则返回ERROR
	if (StackEmpty1(s) != 1 && s->top >= 0) {
		Elemtype1 e = s->data[s->top];
		s->top--;
		return e;
	}
	printf("Pop error!\n");
}

int StackLength1(SqStack1 *s) {//返回栈的长度
	int len = 0, temp = s->top;
	while (temp >= 0) {
		len++;
		temp--;
	}
	return len;
}

Elemtype1 GetTop1(SqStack1 *s) {//返回栈顶元素
	if (StackEmpty1(s) != 1) {
		return s->data[s->top];
	} else
		printf("GetTop error!\n");
}

int StackTraverse1(SqStack1 *s) {//从栈底向栈顶访问每个元素
	if (StackEmpty1(s) == 1) {
		printf("栈为空!\n");
		return 0;
	}
	int temp = 0;
	while (temp <= s->top) {
		printf("%c ", s->data[temp]);
		temp++;
	}
	return 1;
}

//以下是对第二组堆栈操作的定义*************************************************
SqStack2 InitStack2() {//空栈构造函数
	SqStack2 s;
	s.data = (Elemtype2 *)malloc(STACK_INIT_SIZE * sizeof(Elemtype2));
	s.top = -1; //表示栈空
	s.stacksize = STACK_INIT_SIZE;
	if (s.data != NULL)
	{}
	else
		printf("Init error!\n");
	return s;
}

void DestroyStack2(SqStack2 *s) {//销毁栈函数
	free(s->data);
}

int StackEmpty2(SqStack2 *s) {//判断是否为空栈,是返回1,否 返回0
	if (s->top == -1)
		return 1;
	else
		return 0;
}

void ClearStack2(SqStack2 *s) {//清除栈
	while (StackEmpty2(s) != 1) {
		Pop2(s);
	}
}

void Push2(SqStack2 *s, Elemtype2 e) {//添加元素入栈
	if (s->top >= s->stacksize) {
		s->data = (Elemtype2 *)malloc((STACK_INIT_SIZE + STACKINCREMENT) * sizeof(Elemtype2));
		s->stacksize += STACKINCREMENT;
		if (s->data != NULL) {}
		else
			printf("Push error!\n");
	} else {
		s->top++;
		s->data[s->top] = e;
	}
}

Elemtype2 Pop2(SqStack2 *s) {//删除栈顶元素并返回其值,否则返回ERROR
	if (StackEmpty2(s) != 1 && s->top >= 0) {
		Elemtype2 e = s->data[s->top];
		s->top--;
		return e;
	}
	printf("Pop error!\n");
}

int StackLength2(SqStack2 *s) {//返回栈的长度
	int len = 0, temp = s->top;
	while (temp >= 0) {
		len++;
		temp--;
	}
	return len;
}

Elemtype2 GetTop2(SqStack2 *s) {//返回栈顶元素
	if (StackEmpty2(s) != 1) {
		return s->data[s->top];
	} else
		printf("GetTop error!\n");
}

int StackTraverse2(SqStack2 *s) {//从栈底向栈顶访问每个元素
	if (StackEmpty2(s) == 1) {
		printf("栈为空!\n");
		return 0;
	}
	int temp = 0;
	while (temp <= s->top) {
		printf("%c ", s->data[temp]);
		temp++;
	}
	return 1;
}

3.实现表达式求值函数包(表达式求值.c)

#include "数组堆栈.h"
double EvaluateExpression();
int isAccepted(char);
char Precede(char, char);
double Operate(double a, char theta, double b);

int main() {
	printf("请输入一个表达式:");
	double result;
	result = EvaluateExpression();
	printf("表达式的计算结果是:%0.f", result);
	return 0;
}

int flag = 0; //如果在操作数栈有连续数字的输入,则设flag=1标记,用于多位数的计算
double EvaluateExpression() {
	SqStack1 OPTR;
	SqStack2 OPND;
	char e, theta;
	double a, b;
	e = getchar();
	OPTR = InitStack1(); //运算符栈
	Push1(&OPTR, '#');
	OPND = InitStack2(); //操作数或运算结果栈
	while (GetTop1(&OPTR) != '#' || e != '#') {
		if (e == '\n')
			break;
		if (isAccepted(e) == 1) { //如果字符是数字
			e = e - '0';
			if (flag == 1) { //是多位数
				double temp = Pop2(&OPND);
				temp = temp * 10 + e;
				Push2(&OPND, temp);
			} else {
				Push2(&OPND, e);
				flag = 1;
			}
			e = getchar();
		} else {
			flag = 0;
			switch (Precede(GetTop1(&OPTR), e)) {
				case '<'://栈顶元素优先级低,压入栈
					Push1(&OPTR, e);
					e = getchar();
					break;
				case '>'://新运算符优先级低,将前一个运算符弹出进行计算
					a = Pop2(&OPND);
					theta = Pop1(&OPTR);
					b = Pop2(&OPND); //abc
					//将计算结果再次压入运算结果栈
					Push2(&OPND, Operate(a, theta, b));
					//注意这里不用再重新获取e的值
					break;
				case '=':
					Pop1(&OPTR);//将剩下的一半括号弹出
					e = getchar();
					break;
			}
		}
	}
	return GetTop2(&OPND);//返回计算结果

}

int isAccepted(char e) { //如果字符是数字,返回1;字符是运算符,返回2;否则返回0
	char number[15] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
	char calculate[15] = {'+', '-', '(', ')', '*', '#', '/'};
	for (int i = 0; i <= 9; i++) {
		if (number[i] == e)
			return 1;
	}
	for (int i = 0; i <= 6; i++) {
		if (calculate[i] == e)
			return 2;
	}
	return 0;
}

char Precede(char a, char b) {
	if (b == '+' || b == '-') {
		if (a == '(' || a == '#')
			return '<';
		else
			return '>';
	} else if (b == '*' || b == '/') {
		if (a == '*' || a == '/' || a == ')')
			return '>';
		else
			return '<';
	} else if (b == '(')
		return '<';
	else if (b == ')') {
		if (a != '(')
			return '>';
		else
			return '=';
	} else if (b == '#') {
		if (a != '#')
			return '>';
		else
			return '=';
	}

}

double Operate(double a, char theta, double b) {
	if (b == 0) {
		printf("Conflicts with calculation rules!\n");
		return;
	}
	if (theta == '+')
		return a + b;
	else if (theta == '-')
		return b - a;//因为栈先弹出减数,所以要交换顺序
	else if (theta == '*')
		return a * b;
	else if (theta == '/')
		return b / a;//因为栈先弹出除数,所以要交换顺序
}

4.测试输出:

有错误欢迎指正喔!!\\(^-^)//

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-07-04 22:37:15  更:2022-07-04 22:37:54 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/12 5:17:13-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码