C++ 利用顺序栈实现简单四则运算计算器

实验课的作业,要求是用顺序栈实现可以四则运算的计算器,大概的要求就是用户输入一行中缀表达式,编写程序让计算机将中缀转为易于计算的后缀表达式,在将后缀表达式的结果计算出来

注意这里只支持十位数以内的数字运算,作业ddl来不及不想搞了,但是上网参考了一下别人的代码十位数以上的也不难,之后有时间再改进。刚开始敲的时候直接参考了清华大学出版社殷人昆那版的《数据结构》中的顺序栈和Calculator模板类,问题太多了改错改了一堆,postfix函数也不是适用的,所以在调试的时候花的时间比我预计的多出很多........发出来纪念一下

SeqStack.h

#pragma once
#include <iostream>
using namespace std;
#include <assert.h>
const int stackIncreament = 10;  //栈溢出时扩展空间的增量

template<class T>
class SeqStack {
public:
	SeqStack() { elements = 0; top = -1; maxSize = 0; }
	SeqStack(int sz = 50); //构造函数
	~SeqStack() { delete[] elements; } //析构
	void Push(const T& x);  //如果栈满了就要溢出处理,否则就入栈到栈顶
	T Pop(); //退出栈的元素通过引用型参数x返回
	T getTop(); //获取栈顶元素的值
	bool IsEmpty()const { return(top == -1) ? true : false; }
	bool IsFull()const { return(top == maxSize - 1) ? true : false; }                                   
	int getSize()const { return top + 1; } //返回栈中元素个数
	void MakeEmpty() { top = -1; } //清空栈的内容
private:
	T* elements;   //存放栈中元素的栈数组
	int top;    //栈顶指针
	int maxSize;   //栈的最大容量
	void overflowProcess(); //栈的溢出处理
};

template<class T>
SeqStack<T>::SeqStack(int sz) :top(-1), maxSize(sz) { //先执行初始化列表
	elements = new T[maxSize];
	if (elements==nullptr) {
		cout << "栈存储空间分配失败!" << endl; exit(1);
	}
}

template<class T>
void SeqStack<T>::overflowProcess() {  //私有函数:扩充栈存储空间
	T* newArray = new T[maxSize + stackIncreament];
	if (newArray = nullptr) { cout << "存储分配失败!" << endl; exit(1); }
	for (int i = 0; i <= top; i++)
		newArray[i] = elements[i];  //逐个将栈内原有元素放入新的
	maxSize = maxSize + stackIncreament; //更新最大容量
	delete[] elements; //删掉旧的
	elements = newArray; //给新的正名
}

template<class T>
void SeqStack<T>::Push(const T& x) {
	if (IsFull() == true) { cout << "栈满,自动扩充容量!" << endl; overflowProcess(); }//栈满就做溢出处理
	elements[++top] = x; //栈顶指针先加1再放进栈
	cout << "元素 " << x << " 成功推入栈顶" << endl;
}

template<class T>
T SeqStack<T>::Pop() {
	if (IsEmpty() == true) { cout << "栈为空!" << endl; return false; }
	T x = elements[top--]; //先存出数据再让指针退1
	return x;
}

template<class T>
T SeqStack<T>::getTop() {
	if (IsEmpty() == true)return false;
	T x;
	x = elements[top];
	return x;
}

calculate.h

#pragma once
#include <cmath>
#include <string>
#include "SeqStack.h"
#include <iostream>
using namespace std;

//模拟一个简单的计算器,对从键盘读入的中缀表达式先转化为后缀表达式再求值
template<class T>
class Calculator {
public:
	Calculator(int sz) :s(sz) { }//给顺序栈开辟了空间
	void postfix(string mid_str);  //中缀转后缀
	void Run();  //执行表达式运算
	void Clear();
private:
	char RPN_ch[100];
	SeqStack<T> s; //因为我们计算器是针对后缀表达式的,所以这个栈中存放的必须是后缀表达式
	void AddOperand(T& value); //进操作数栈
	bool Get2Operands(T& left, T& right);//从栈中退出两个操作数
	void DoOperator(char op); //形成运算指令进行计算
};

template<class T>
void Calculator<T>::DoOperator(char op) {
	T left, right, value; //取两个操作数,根据操作符op形成运算指令并计算
	bool result;
	result = Get2Operands(left, right);  //取两个操作数
	if (result == true)  //操作数取成功了就开始计算并将结果Push进栈
	switch (op) {
	case'+':value = left + right; s.Push(value); break;
	case'-':value = left - right; s.Push(value); break;
	case'*':value = left * right; s.Push(value); break;
	case'/':if (right == 0.0) { //检查:除数不能为零
		cerr << "Divide by 0!" << endl; Clear();  //报错清栈
	}
		   else { value = left / right; s.Push(value); } break;
	} //else Clear();  //取数不成功,result==false
	if (result != true) {
		cout << "取数不成功,无法进行下一步运算!" << endl; Clear();
	}
}

template<class T>
bool Calculator<T>::Get2Operands(T& left, T& right) {
	if (s.IsEmpty() == true)
	{
		cerr << "缺少右操作数!" << endl; return false; //栈空,报错
	}
	else right=s.Pop(); //取出右操作数
	if (s.IsEmpty() == true)
	{
		cerr << "缺少左操作数!" << endl;  
		return false;
	}
	else left=s.Pop();
	return true; //代表成功祛除了两个操作数
}

template<class T>
void Calculator<T>::AddOperand(T& value) {
	s.Push(value); //将操作数的值Push进操作数栈
}

template<class T>
void Calculator<T>::Run() {
	T newOperand;  //用来存运算操作数
	int i = 0;
	while (RPN_ch[i] != '=') {
		switch (RPN_ch[i]) {
		case'+':case'-':case'*':case'/':
			DoOperator(RPN_ch[i]); break;  //如果是操作符,那就可以执行计算
		default:
			cin.putback(RPN_ch[i]); //将字符放回输入流
			cin >> newOperand;  //重新从输入流中读操作数
			AddOperand(newOperand); //将操作数放入栈中
			break;
		}
		i++;
	}
	T result=s.getTop();
	cout << "表达式运算结果为:" << result<< endl;
}

template<class T>
void Calculator<T>::Clear() {
	s.MakeEmpty();  //清栈
}


//栈内优先级 
int isp(char op) {
	int priority = 0;
	if (op == '#') {
		priority = 0;
	}
	else if (op == '(') {
		priority = 1;
	}
	else if (op == ')') {
		priority = 6;
	}
	else if (op == '+' || op == '-') {
		priority = 3;
	}
	else if (op == '*' || op == '/') {
		priority = 5;
	}
	return priority;
}

//栈外优先级
int icp(char op) {
	int priority = 0;
	if (op == '#') {
		priority = 0;
	}
	else if (op == '(') {
		priority = 6;
	}
	else if (op == ')') {
		priority = 1;
	}
	else if (op == '+' || op == '-') {
		priority = 2;
	}
	else if (op == '*' || op == '/') {
		priority = 4;
	}
	return priority;
}

//中缀表达式转成后缀表达式
template<class T>
void Calculator<T>::postfix(string mid_str) {
	SeqStack<char> s1(100);   //转换时操作符的辅助栈
  	//开始 
	s1.Push('#');
	int j = 0;
	for (int i = 0; i <(mid_str.size()); i++) {
		if (mid_str[i] >= '0' && mid_str[i] <= '9') {
			RPN_ch[j++]= mid_str[i];
		}
		else {  //如果不是0~9操作数
			int op_icp = icp(mid_str[i]);

			if (isp(s1.getTop()) > op_icp) {  //拿操作符辅助栈栈顶元素来与之比较
					RPN_ch[j++] = s1.getTop();//因为一直是操作完自加j++,所以最后直接给[j]上的赋‘=’就好
					s1.Pop();
					s1.Push(mid_str[i]);
			}
			else if (isp(s1.getTop()) < op_icp) {
				s1.Push(mid_str[i]);
			}
			else if (isp(s1.getTop()) == op_icp) {
				s1.Pop();
			}
		}
	}
	//将余下操作符栈中元素放入RPN数组
	while (!s1.IsEmpty()) {  
		if (s1.getTop() != '#') {
			RPN_ch[j++]= s1.getTop();
			s1.Pop();
		}
		else {
			s1.Pop();
		}
	 }
	RPN_ch[j] = '=';
	cout << "转化后的后缀表达式为:";
	for (int k = 0; k <= j; k++) {
		cout << RPN_ch[k];
	}cout << endl;
}

main.cpp

#include "SeqStack.h"
#include "Calculate.h"
#include <string>
#include <iostream>
using namespace std;

/*
* 测试样例:
* 2
* 10
* 5*9+3-1
* 7+2*5
*/
void main()
{
	int i;
	cout << "请输入要计算的表达式行数:" << endl;
	cin >> i;
	cout << "请输入存放表达式的顺序栈最大容量:" << endl;
	int sz; cin >> sz;
	Calculator<double> newCal(sz);
	string mid_str;
	for(int j=0;j<i;j++)
	{
		cout << "请输入第"<<j+1<<"条中缀算术表达式:" << endl;
		cin >> mid_str;
		newCal.postfix(mid_str);  //输入中缀并将将中缀转换成后缀 
		newCal.Run();
	}
	return;
}

可以直接跑,但也可能还有问题,欢迎建议。

  • 4
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的 C 语言程序,可以实现混合四则运算: ```c #include <stdio.h> #include <stdlib.h> #include <time.h> int main() { int num1, num2, num3, num4, result; char op1, op2, op3; srand(time(NULL)); // 初始化随机数生成器 num1 = rand() % 101; // 生成第一个随机数 num2 = rand() % 101; // 生成第二个随机数 num3 = rand() % 101; // 生成第三个随机数 num4 = rand() % 101; // 生成第四个随机数 op1 = "+-*/"[rand() % 4]; // 生成第一个运算符 op2 = "+-*/"[rand() % 4]; // 生成第二个运算符 op3 = "+-*/"[rand() % 4]; // 生成第三个运算符 // 计算结果 if (op1 == '+') { result = num1 + num2; } else if (op1 == '-') { result = num1 - num2; } else if (op1 == '*') { result = num1 * num2; } else { result = num1 / num2; } if (op2 == '+') { result += num3; } else if (op2 == '-') { result -= num3; } else if (op2 == '*') { result *= num3; } else { result /= num3; } if (op3 == '+') { result += num4; } else if (op3 == '-') { result -= num4; } else if (op3 == '*') { result *= num4; } else { result /= num4; } // 输出题目和答案 printf("%d %c %d %c %d %c %d = %d\n", num1, op1, num2, op2, num3, op3, num4, result); return 0; } ``` 这个程序会生成四个随机数和三个随机运算符,然后计算表达式的值,并输出题目和答案。运行多次可以得到不同的题目。需要注意的是,这个程序可能会生成除数为零的表达式,需要在实际使用时进行判断和处理。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值