表达式转换-中缀转后缀表达式后计算-数据结构与算法

文章目录


问题

一个计算中缀表达式的算法题

40分,其余六个测试点都显示"read(ASCII 13)"
我的代码现在一直只能过第1、6、7、8这四个测试集,
查看测试集显示错误信息:
“Wrong Answer.wrong answer On line 1 column 25, read (ASCII 13), expected +.”

题目链接表达式转换-洛谷

我查了(ASCII 13)是回车键,但是我又能过四个测试集,为什么输出会有回车键的问题呢?

谁能救救我啊?万分感谢!

下面是我的代码(可能有点乱,抱歉):

/*long long
1)输入数字是单个数字
2)输入没有负数 */
#include<iostream>
#include<cstdio>
#include<stack>
using namespace std;
const int max0 = 500;
stack<char> s;		//计算后缀表达式用 
long long get_num();						//从栈中返回一个整型数字 
bool compare_sign(char big, char small);	//比较两个(四则运算符)运算符的优先级 
void change(char str[]);					//给新转化出来的后缀表达式 操作数 加分隔符'.'
void out_bds(char str[], int i, stack<char> ss);//输出中间产物表达式
int main() {
	char a[max0]{};			//后缀表达式 
	int ac(0);				//迭代a
	stack<char> sign;		//符号栈
	char m[max0]{};			//待处理的中缀表达式
	char ch(0);
	for(int i = 0; i < max0; ++i){
		ch = getchar();
		if(ch == '\n') break;
		m[i] = ch; } 
	//--------------------一、中缀表达式转后缀表达式 
	for(int i = 0; i < max0 && m[i] != '\0'; i++) {		//读取中缀表达式并开始转换 
		if('0' <= m[i] && m[i] <= '9') {				//遇到操作数,直接加入后缀表达式 
			a[ac++] = m[i]; }
		else if(m[i] != '(' && m[i] != ')') {	 
			while(!sign.empty() && compare_sign(sign.top(), m[i])) { 
				a[ac++] = sign.top();					//遇到运算符,出栈优先级不小于它的运算符加入表达式,直到栈空或遇到'('
				sign.pop(); }
			sign.push(m[i]); }							//然后自己入栈 
		else if(m[i] == '(') {
			sign.push(m[i]); }
		else if(m[i] == ')') {							//遇到')',出栈加入表达式直到'(' 
			while(sign.top() != '(') {
				a[ac++] = sign.top();
				sign.pop(); }
			sign.pop(); }}
	while(!sign.empty()) {		//出栈所有剩余运算符 
		a[ac++] = sign.top();
		sign.pop(); }
	change(a);
	out_bds(a, 0, s);
	//--------------------二、计算后缀表达式 
	char t(0); ac = 0;		
	while(true) {
		t = a[ac++];					//入栈 
		if(t == '@') {s.pop();break;}
		s.push(t);
		if(t == '+' || t == '-' || t == '*' || t == '/' || t == '^') {	//见运算符
			s.pop();				//出栈运算符
			long long d(0), b(0);	//出栈两个数字为int型
			s.pop(); d = get_num();
			s.pop(); b = get_num();
			long long result(1);	//计算
			if(t == '+') result = b + d;
			else if(t == '-') result = b - d;
			else if(t == '*') result = b * d;
			else if(t == '/') result = b / d;
			else if(t == '^') {
				for(int i = 0; i < d; ++i)
					result *= b; }
			if(result < 0) {s.push('0'); result = -result;}
			stack<char> c;			//结果转为char型再入栈
			if(result == 0) {s.push('0');}
			while(result != 0) {
				c.push((char)(result % 10 + '0'));
				result /= 10; }
			while(!c.empty()) {
				s.push(c.top());
				c.pop(); }
			s.push('.');
			out_bds(a, ac, s); }}
	return 0; }
//----------------------------------------
//只考虑了表达式转换过程中可能发生的优先级比较 
bool compare_sign(char big, char small) {
	if(big == '+' || big == '-') {
		if(small == '+' || small == '-') return true; }
	else if(big == '*' || big == '/' || big == '^') {
		if(small != '(' && small != '^') return true; }
	return false; }
//----------------------------------------
//从char型栈中读取出一个int型操作数 
long long get_num() {
	long long sum(0);
	char t(0);
	for(long long i = 1; s.top() != '.'; i *= 10) {		//i也是必须开long long的 
		t = s.top();
		sum += (long long)(s.top() - '0') * i;
		s.pop();
		if(s.empty()) break; }
	if(t == '0') sum = -sum;
	return sum; }
//----------------------------------------
//从char型栈中读取出一个int型操作数;out_bds()的配套 
long long get_num(stack<char> &ss) {
	long long sum(0);
	char t(0);
	for(long long i = 1; ss.top() != '.'; i *= 10) 
	{	t = ss.top();
		sum += (long long)(ss.top() - '0') * i;
		ss.pop();
		if(ss.empty()) break; }
	if(t == '0') sum = -sum;
	return sum; }
//----------------------------------------
//给新转化出来的后缀表达式 操作数 加分隔符'.'
void change(char str[]) {
	char t[max0]{};
	int tc(0);
	for(int i = 0; str[i] != '\0'; i++) {
		if('0' <= str[i] && str[i] <= '9') {
			t[tc++] = str[i];
			t[tc++] = '.'; }
		else t[tc++] = str[i]; }
	for(int i = 0; t[i] != '\0'; i++) 
		str[i] = t[i];
	str[tc] = '@'; }		//表达式结束符
//----------------------------------------
//输出中间产物表达式,从str[i]开始;参数建立了一个副本栈,不担心原s改变 
void out_bds(char str[], int i, stack<char> ss) {
	stack<long long> t;			//中转站 
	while(ss.empty() == 0) {
		if(ss.top() == '.')
			ss.pop();
		t.push(get_num(ss)); }
	while(t.empty() == 0) {
		cout << t.top() << " ";
		t.pop(); }
	for( ; str[i] != '\0'; i++) {
		if(str[i] != '.' && str[i] != '@') 
			cout << str[i] << " "; }
	cout << endl; } 
/*
测试集
8-(3+2*6)/5+4
9+(9^8+(9^8+(9^8+(9^8))))
*/ 

程序运行:
运行结果

经验总结

  • 注意创建的数组大小,题目说输入字符串长度不超过100,但是表达式计算过程中的中间结果是可能超过100的。
  • 注意不要变量名冲突
  • 仔细审题,有些坑很细,如:计算过程总数字不超过231,但是可能等于,那int类型就不够了。
  • 如果重载了函数,修改其中一个时可能其它的也需要修改
  • 输出格式其实挺烦的,有时题目不会说很清楚,甚至就必须有行末空格。

🚀 个人主页:清风莫追
🔥 有问题欢迎指出,
🔥 希望能和大家一起加油,一起进步!

  • 25
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 20
    评论
中缀表达式后缀表达式算法可以分为两种,一种是使用栈来实现,另一种是使用逆波兰算法。这两种算法的目的都是将中缀表达式转换后缀表达式,以便于计算表达式的值。下面分别介绍这两种算法的内容和实现。 1. 使用栈实现中缀表达式后缀表达式算法: (1)从左到右遍历中缀表达式中的每个元素,如果是操作数,则直接输出;如果是操作符,则进行如下处理: (2)如果栈为空或者栈顶元素为左括号,则将操作符入栈。 (3)如果操作符的优先级大于栈顶元素的优先级,则将操作符入栈。 (4)否则,将栈顶元素弹出并输出,然后重复步骤(3)。 (5)如果遇到左括号,则将其入栈;如果遇到右括号,则将栈顶元素弹出并输出,直到遇到左括号为止。 (6)重复步骤(1)至(5),直到遍历完整个中缀表达式。 (7)如果栈中还有元素,则依次弹出并输出。 2. 使用逆波兰算法实现中缀表达式后缀表达式算法: (1)从左到右遍历中缀表达式中的每个元素,如果是操作数,则直接输出;如果是操作符,则进行如下处理: (2)如果操作符的优先级大于栈顶元素的优先级,则将操作符入栈。 (3)否则,将栈顶元素弹出并输出,然后重复步骤(2)。 (4)如果遇到左括号,则将其入栈;如果遇到右括号,则将栈中所有操作符弹出并输出,直到遇到左括号为止。 (5)重复步骤(1)至(4),直到遍历完整个中缀表达式。 (6)如果栈中还有元素,则依次弹出并输出。 这两种算法都可以将中缀表达式转换后缀表达式,以便于计算表达式的值。使用栈实现的算法比较简单易懂,逆波兰算法则更加高效,可以直接通过栈来计算后缀表达式的值,而不需要考虑运算符的优先级和结合性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

清风莫追

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值