四则运算表达式求值(可以计算小数和带括号)

本文介绍了一种计算带括号的小学算术四则运算表达式的算法,包括使用堆栈存储数字和符号,通过优先级比较进行计算,以及处理小数和负数的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


若有疑问,请联系simonsliu9@gmail.com,一定尽快回复

求一个可以带括号的小学算术四则运算表达式的值

input

一行,一个四则运算表达式。’*‘表示乘法,’/'表示除法
输入样例1:
3.4
输入样例2:
7+8.3
输入样例3:
3 + 4.5 ∗ ( 7 + 2 ) ∗ ( 3 ) ∗ ( ( 3 + 4 ) ∗ ( 2 + 3.5 ) / ( 4 + 5 ) ) − 34 ∗ ( 7 − ( 2 + 3 ) ) 3+4.5*(7+2)*(3)*((3+4)*(2+3.5)/(4+5))-34*(7-(2+3)) 3+4.5(7+2)(3)((3+4)(2+3.5)/(4+5))34(7(2+3))

output

一行,该表达式的值,保留小数点后面两位
输出样例1:
3.40
输出样例2:
15.30
输出样例3:
454.75

主要实现功能

  1. 判断左括号
  2. 判断有括号
  3. 判断数字,有小数需要判断
  4. 判断符号,计算
  5. 不断弹出计算

实现过程

头文件导入

会用到stack来对数字和符号进行存储,也会用到string

#include<iostream>
#include<cstdio>
#include<stack>
#include<cstring>
using namespace std;
定义全局变量

需要的全局变量:
用来存储表达式的字符数组s,保存每一个数字的用作中间变量字符数组temp
符号栈opt,数字栈item

const int maxn = 1000; // 常量
char s[maxn], temp[maxn];
// 一个用于保存表达式,一个用于保存数字从字符数组转化成double变量的中间变量
stack<char> opt;//符号栈
stack<double> item;//数字栈
主要功能函数
  1. 将字符数组转化成数字 double str2double(char s[])
    这个函数一般是将temp中保存的字符数组形式的数字转化成double类型,考虑了小数点
double str2double(char s[]) {
	int len = strlen(s);
	double sum1 = 0;
	double sum2 = 0;
	bool flag = false;
	for (int i = 0; i < len; i++) {
		if (s[i] == '.') {
			flag = true;
			break;
		}
		sum1 = sum1 * 10 + s[i] - '0';
	}
	if (flag) {
		for (int i = len - 1; i >= 0; i--) {
			if (s[i] == '.') break;
			sum2 = (sum2 + s[i] - '0') / 10.0;
		}
	}
	return sum1 + sum2;
}
  1. 运算符优先级比较函数int priority(char ch)
int priority(char ch) {
	if (ch == '*' || ch == '/') return 2;
	if (ch == '+' || ch == '-') return 1;
	return 0;
}
  1. 计算函数void cal()
void cal() {
	double x = item.top(); 
	item.pop();
	double y = item.top(); 
	item.pop();
	switch (opt.top()) {
	case '+': y += x; break;
	case '-': y -= x; break;
	case '*': y *= x; break;
	case '/': y /= x; break;
	}
	item.push(y);
	opt.pop();
}
  1. 主函数
int main() {
	scanf("%s", s); // 输入字符串
	int len = strlen(s); // 字符串长度
	int cnt = 0; // 中间变量temp的游标
	int i = 0;   // 对字符串进行遍历的右边
	bool flag = false; // 对开头字符是负号的处理flag
	// 如果开头是负号,则flag=true,然后表达式遍历游标i+1
	if (s[i] == '-') flag = true, i = 1; 
	// 开始遍历表达式
	while (i < len) {
	    // 如果为左括号,则进栈,游标后移
		if (s[i] == '(') opt.push(s[i]),i++;
		// 如果为右括号,则计算括号中的值
		else if (s[i] == ')') {
			while (opt.top() != '(') cal();
			opt.pop();
			i++;
		}
		// 如果为数字或者小数点
		else if (s[i] <= '9' && s[i] >= '0' || s[i] == '.') {
		    // 不断的循环,把一个数存入中间变量temp中,然后temp的游标后移,i也后移
			while (s[i] <= '9' && s[i] >= '0' || s[i] == '.') temp[cnt++] = s[i++];
			// 给中间变量的末尾加一个‘0’,意思表示结尾,便于str2double中计算temp的长度
			temp[cnt] = 0;
			// 将temp转化为对应的浮点数,然后存入数字栈item中,考虑是否为负数
			if (flag) item.push(-str2double(temp)), flag = false;
			else item.push(str2double(temp));
			// 然后temp的游标归零,便于下一次存储数字
			cnt = 0;
		}
		// 如果为计算符号
		else {
		    // 符号栈opt不为空,同时游标指向的符号的优先级小于栈顶符号优先级,则进行计算
			while (!opt.empty() && priority(s[i]) < priority(opt.top())) cal();
			// 把当前符号压栈,因为当前符号比栈顶符号优先级大,所以不能拿栈顶符号进行计算
			opt.push(s[i]);
			i++;
		}
	}
	// 这种情况,是里面的优先级计算顺序已经调整好,直接进行计算
	while (!opt.empty()) cal();
	printf("%.2lf\n", item.top());
	return 0;
}

完整代码

#include<iostream>
#include<cstdio>
#include<stack>
#include<cstring>
using namespace std;

const int maxn = 1000;
char s[maxn], temp[maxn];
stack<char> opt;//符号栈
stack<double> item;//数字栈

double str2double(char s[]) {
	int len = strlen(s);
	double sum1 = 0;
	double sum2 = 0;
	bool flag = false;
	for (int i = 0; i < len; i++) {
		if (s[i] == '.') {
			flag = true;
			break;
		}
		sum1 = sum1 * 10 + s[i] - '0';
	}
	if (flag) {
		for (int i = len - 1; i >= 0; i--) {
			if (s[i] == '.') break;
			sum2 = (sum2 + s[i] - '0') / 10.0;
		}
	}
	return sum1 + sum2;
}
int priority(char ch) {
	if (ch == '*' || ch == '/') return 2;
	if (ch == '+' || ch == '-') return 1;
	return 0;
}
void cal() {
	double x = item.top(); item.pop();
	double y = item.top(); item.pop();
	switch (opt.top()) {
	case '+': y += x; break;
	case '-': y -= x; break;
	case '*': y *= x; break;
	case '/': y /= x; break;
	}
	item.push(y);
	opt.pop();
}
int main() {
	scanf("%s", s); // 输入字符串
	int len = strlen(s); // 字符串长度
	int cnt = 0; // 中间变量temp的游标
	int i = 0;   // 对字符串进行遍历的右边
	bool flag = false; // 对开头字符是负号的处理flag
	// 如果开头是负号,则flag=true,然后表达式遍历游标i+1
	if (s[i] == '-') flag = true, i = 1; 
	// 开始遍历表达式
	while (i < len) {
	    // 如果为左括号,则进栈,游标后移
		if (s[i] == '(') opt.push(s[i]),i++;
		// 如果为右括号,则计算括号中的值
		else if (s[i] == ')') {
			while (opt.top() != '(') cal();
			opt.pop();
			i++;
		}
		// 如果为数字或者小数点
		else if (s[i] <= '9' && s[i] >= '0' || s[i] == '.') {
		    // 不断的循环,把一个数存入中间变量temp中,然后temp的游标后移,i也后移
			while (s[i] <= '9' && s[i] >= '0' || s[i] == '.') temp[cnt++] = s[i++];
			// 给中间变量的末尾加一个‘0’,意思表示结尾,便于str2double中计算temp的长度
			temp[cnt] = 0;
			// 将temp转化为对应的浮点数,然后存入数字栈item中,考虑是否为负数
			if (flag) item.push(-str2double(temp)), flag = false;
			else item.push(str2double(temp));
			// 然后temp的游标归零,便于下一次存储数字
			cnt = 0;
		}
		// 如果为计算符号
		else {
		    // 符号栈opt不为空,同时游标指向的符号的优先级小于栈顶符号优先级,则进行计算
			while (!opt.empty() && priority(s[i]) < priority(opt.top())) cal();
			// 把当前符号压栈,因为当前符号比栈顶符号优先级大,所以不能拿栈顶符号进行计算
			opt.push(s[i]);
			i++;
		}
	}
	// 这种情况,是里面的优先级计算顺序已经调整好,直接进行计算
	while (!opt.empty()) cal();
	printf("%.2lf\n", item.top());
	return 0;
}
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值