用栈完成算数表达式的计算

完成算数表达式的计算如(2+13)(10-8/(1+1*3))

代码

#include <bits/stdc++.h>
#include <windows.h>
using namespace std;
string s="(2+1*3)*(10-8/(1+1*3))";
char opx[10]={'+','-','*','/','(',')','\0'};//哪些运算符 
int opn[265];//运算符对应的数字 
char priority[10][10]={//上一个运算符和现在运算符的优先顺序。'='是要消除配对的括号。 
    {'>', '>', '<', '<', '<', '>','>'},
    {'>', '>', '<', '<', '<', '>','>'},
    {'>', '>', '>', '>', '<', '>','>'},
    {'>', '>', '>', '>', '<', '>','>'},
    {'<', '<', '<', '<', '<', '=',' '},
    {'<', '<', '<', '<', '=', ' ',' '}, 
    {'<', '<', '<', '<', '<', '<','='}
};
void optonum(){//实现符号和数字的对应 
	for(int i=0;i<7;i++)opn[opx[i]]=i;
	for(int i=0;i<7;i++)cout<<opx[i]<<"\t";cout<<endl;
	for(int i=0;i<7;i++)cout<<opn[opx[i]]<<"\t";cout<<endl;
}
vector<int> d;//"运算数"栈。先进后出 
vector<int> op;//运算符队列,优先级底的先放进栈。 
int cal(int d1,int opx,int d2){//二元运算 
	switch(opx){
		case 0:return d1+d2;break;
		case 1:return d1-d2;break;
		case 2:return d1*d2;break;
		case 3:return d1/d2;break;
	}
}
void view(int x,char c){//观察"运算数"和运算符栈 
	cout<<"算式:"<<s<<"\t数:"<<x<<"\t字符:"<<c<<endl;
	cout<<"运算符:";for(vector<int>::iterator i=op.begin();i!=op.end();i++)cout<<"\t"<<opx[*i];cout<<"|"<<endl;
	cout<<"运算数:";for(vector<int>::iterator i=d.begin();i!=d.end();i++)cout<<"\t"<<*i;cout<<"|"<<endl;
	//system("pause");
}
int main(){
	optonum();//完成运算符号和数字的转换 
	int num=0,//输入的数字 
		opx1,opx2,//当前运算符和上一个运算符 
		num1,num2;//前后两个运算数
	op.push_back(opn['\0']);//率先放进一个"字符串结束标记",以判断完成运算 
	for(int i=0;i<=s.length();i++){//遍历算式每个字符 
		view(num,s[i]);//观察到了哪个字符,运算数栈和运算符栈 
		if(isdigit(s[i]))num=num*10+s[i]-'0';//该位置是数字,有可能是多为数字 
		else{//运算符 
			if(isdigit(s[i-1])){
				d.push_back(num);num=0;
			}//该字符不是数字,而且前一个是数字,就可以把数字放进运算数队列 
			opx2=opn[s[i]];//把字符转换成"运算数字" 
			while(!op.empty()){//有运算符就循环 
				opx1=op.back();//前一个运算符 
				cout<<"运算符:\t"<<opx[opx1]<<"和"<<opx[opx2]<<"\t"; 
				if(priority[opx1][opx2]=='>'){//进行上一个优先的运算 
					op.pop_back();//消除运算的符号 
					num2=d.back();d.pop_back();//前后两个运算数 
					num1=d.back();d.pop_back();//第二取出的是第一个运算符 
					int ans=cal(num1,opx1,num2);
					cout<<"算式___________:"<<num1<<" "<<opx[opx1]<<" "<<num2<<endl;
					d.push_back(ans);//运算结果放进栈 
					cout<<num1<<" "<<opx[opx1]<<" "<<num2<<"=结果:"<<ans<<endl;
				}else if(priority[opx1][opx2]=='<'){//优先级低,放进队列 
					op.push_back(opx2);
					cout<<"推迟计算!"<<endl;
					break;
				}else if(priority[opx1][opx2]=='='){//括号配对,消除括号 
					op.pop_back();
					cout<<"消括号!"<<endl;
					break;
				}
			}
		}
	}
	cout<<"结果:"<<d.back();
	return 0;
}

程序推进数据

+ - * / ( )
0 1 2 3 4 5 6
算式:(2+13)(10-8/(1+13)) 数:0 字符:(
运算符: |
运算数:|
运算符: 和( 推迟计算!
算式:(2+1
3)(10-8/(1+13)) 数:0 字符:2
运算符: (|
运算数:|
算式:(2+13)(10-8/(1+13)) 数:2 字符:+
运算符: (|
运算数:|
运算符: (和+ 推迟计算!
算式:(2+1
3)(10-8/(1+13)) 数:0 字符:1
运算符: ( +|
运算数: 2|
算式:(2+13)(10-8/(1+13)) 数:1 字符:
运算符: ( +|
运算数: 2|
运算符: +和
推迟计算!
算式:(2+13)(10-8/(1+13)) 数:0 字符:3
运算符: ( + |
运算数: 2 1|
算式:(2+1
3)
(10-8/(1+13)) 数:3 字符:)
运算符: ( + |
运算数: 2 1|
运算符: 和) 算式___________:1 * 3
1 * 3=结果:3
运算符: +和) 算式___________:2 + 3
2 + 3=结果:5
运算符: (和) 消括号!
算式:(2+1
3)
(10-8/(1+1
3)) 数:0 字符:

运算符: |
运算数: 5|
运算符: 和* 推迟计算!
算式:(2+13)(10-8/(1+13)) 数:0 字符:(
运算符: |
运算数: 5|
运算符: 和( 推迟计算!
算式:(2+1
3)
(10-8/(1+1
3)) 数:0 字符:1
运算符: * (|
运算数: 5|
算式:(2+13)(10-8/(1+13)) 数:1 字符:0
运算符: * (|
运算数: 5|
算式:(2+1
3)(10-8/(1+13)) 数:10 字符:-
运算符: * (|
运算数: 5|
运算符: (和- 推迟计算!
算式:(2+13)(10-8/(1+13)) 数:0 字符:8
运算符: * ( -|
运算数: 5 10|
算式:(2+1
3)(10-8/(1+13)) 数:8 字符:/
运算符: * ( -|
运算数: 5 10|
运算符: -和/ 推迟计算!
算式:(2+13)(10-8/(1+13)) 数:0 字符:(
运算符: * ( - /|
运算数: 5 10 8|
运算符: /和( 推迟计算!
算式:(2+1
3)(10-8/(1+13)) 数:0 字符:1
运算符: * ( - / (|
运算数: 5 10 8|
算式:(2+13)(10-8/(1+13)) 数:1 字符:+
运算符: * ( - / (|
运算数: 5 10 8|
运算符: (和+ 推迟计算!
算式:(2+1
3)(10-8/(1+13)) 数:0 字符:1
运算符: * ( - / ( +|
运算数: 5 10 8 1|
算式:(2+13)(10-8/(1+13)) 数:1 字符:
运算符: * ( - / ( +|
运算数: 5 10 8 1|
运算符: +和* 推迟计算!
算式:(2+13)(10-8/(1+13)) 数:0 字符:3
运算符: * ( - / ( + |
运算数: 5 10 8 1 1|
算式:(2+1
3)
(10-8/(1+13)) 数:3 字符:)
运算符: * ( - / ( + |
运算数: 5 10 8 1 1|
运算符: 和) 算式___________:1 * 3
1 * 3=结果:3
运算符: +和) 算式___________:1 + 3
1 + 3=结果:4
运算符: (和) 消括号!
算式:(2+1
3)
(10-8/(1+1
3)) 数:0 字符:)
运算符: * ( - /|
运算数: 5 10 8 4|
运算符: /和) 算式___________:8 / 4
8 / 4=结果:2
运算符: -和) 算式___________:10 - 2
10 - 2=结果:8
运算符: (和) 消括号!
算式:(2+13)(10-8/(1+1*3)) 数:0 字符:
运算符: *|
运算数: 5 8|
运算符: *和 算式___________:5 * 8
5 * 8=结果:40
运算符: 和 消括号!
结果:40

几个点

  • 遇到非数字字符,如果前一个是数字字符,就把num放进队列
  • 右括号前所有算式都要算完
在C语言中,利用顺序(数组实现)计算简单的算术表达式通常涉及前缀(prefix)表示法或者逆波兰表示法(RPN,也称后缀表示法)。这里是一个基于逆波兰表示法的简单示例: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_STACK_SIZE 100 int is_digit(char c) { return ('0' <= c && c <= '9'); } int pop(stack_t *s) { if (s->top == -1) { return INT_MIN; } int top_val = s->data[s->top]; s->top--; return top_val; } void push(stack_t *s, int val) { if (s->top >= MAX_STACK_SIZE - 1) { printf("Stack overflow.\n"); return; } s->data[++s->top] = val; } int eval_rpn(const char *tokens) { stack_t s = { -1 }; const char *token = tokens; while (*token != '\0') { if (is_digit(*token)) { int num = 0; while (is_digit(*++token)) { num = num * 10 + *token - '0'; } push(&s, num); } else { int op2 = pop(&s); int op1 = pop(&s); switch (*token++) { case '+': push(&s, op1 + op2); break; case '-': push(&s, op1 - op2); break; case '*': push(&s, op1 * op2); break; case '/': if (op2 != 0) push(&s, op1 / op2); else printf("Division by zero error.\n"); break; default: printf("Invalid operator.\n"); return INT_MIN; } } } return pop(&s); } int main() { char expression[] = "2 3 + 4 *"; int result = eval_rpn(expression); printf("Result of the expression: %d\n", result); return 0; } ``` 在这个代码中,我们首先检查字符是否为数字,如果是则读取直到遇到非数字字符,然后将整数值推入。遇到操作符时,从顶弹出两个操作数进行相应的运算,并把结果压回。最后顶剩余的就是表达式计算结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值