c++实现计算器功能

576 阅读3分钟

大作业题目:高性能计算器    

使用C++语言设计一个高性能计算器,具有以下功能:     (1)基本功能(80分)(i)在控制台下输入一个表达式,例如,输入 3+5*4,可以按输入的表达式中的运算符优先级进行处理,得到23。(ii)在控制台上输入一个表达式,例如,输入1+(3+5)*4,可以按输入的表达式中的括号和运算符串的优先级进行处理,得到33。(iii)设计的计算器可实现实数(含整数)的加、减、乘、除、乘方和开方运算。

(2)拓展功能(20分)(i)设计的计算器可实现复数的加、减、乘、除运算;(ii)设计的计算器可实现无穷精度的整数的加、减、乘、除、求模运算(提示,使用结构体)。

代码如下:

#include <iostream>
#include <stack>
#include <math.h>

using namespace std;

//核心函数,将表达式的每个字符都进行入栈操作
double inStack();   
void caluNum(stack<char>& signC, stack<double>& num);  //用来计算加减乘除, 结果放在数字栈顶
void factorial(stack<double>& num);   //用来计算阶乘
int printprioNum(char priNum);   //用来计算操作符的优先级

int main() {
	double result;   //最后的结果

	cout << "请输入表达式:\n";
	result = inStack();   //将缓冲区的操作符和数字压入栈 

	cout << "结果是:\n" << result;

	return 0;
}

double inStack() {
	//定义一个符号栈--用来存储符号
	stack<char> signC;
	//定义一个数字栈--用来存储数字
	stack<double> num;

	char signOne;
	double num_;

	while (1) {
		//cin.peek()返回的是表达式中的每一个字符对应的ASCLL表的值,
		//通过ASCLL表的值可以对数字进行筛选出来,将数字进行入栈
		if (cin.peek() >= '0' && cin.peek() <= '9') {  //判断下一个是否是数字
			//遇到数字忽略,继续输入
			cin >> num_;
			//num_打印的是数字
			cout << num_ << endl;
			//数字直接入数字栈
			num.push(num_);   
		}
		else {
			//如果不是数字,那输入的一定是运算符
			cin >> signOne;
			if (signOne == '=') {
				//如果符号栈不空,表明计算还未完成,就一直要计算
				while (!signC.empty()) caluNum(signC, num);
				//如果是等号且符号栈顶为空,表明已经计算出最终的结果了,就返回数字栈顶元素--也就是最终的结果
				return num.top();  
			}
			//如果是!就阶乘
			else if (signOne == '!') factorial(num);
			//如果符号是左括号或符号栈为空直接压入符号栈,因为括号优先级最大,应该要把括号里面的值
			else if (signOne == '(' || signC.empty()) signC.push(signOne);
			//如果是右括号,则while循环判断符号栈顶元素是否为左括号,如果是左括号就表示()完整的截取到了
			//这时候我们要计算完整括号里面的值,因为括号优先级是最大的。
			else if (signOne == ')') {  
				while (signC.top() != '(') caluNum(signC, num);
				//计算完成后左括号出栈
				signC.pop();  
			}
			//针对于括号除外的其他运算符的优先级,我们采用符号返回的数字大小来决定优先级的大小
			//如果栈顶符号的优先级大于等于当前符号优先级的话,进入while循环
			else if (printprioNum(signC.top()) >= printprioNum(signOne)) {  
				while (signC.top() != '(') {
					//计算结果压入数字栈,取出当前栈顶
					caluNum(signC, num);   
					//当符号栈为空或者待压入的符号优先级比符号栈顶元素高就跳出
					if (signC.empty() || printprioNum(signC.top()) < printprioNum(signOne)) {
						cout <<"当符号栈为空或者待压入的符号优先级高就跳出" << endl;
						break;
					}
				}
				//压入当前符号
				signC.push(signOne);  
			}
			else {
				//否则就压入符号栈
				signC.push(signOne);
			}
		}
	}
}

void caluNum(stack<char>& signC, stack<double>& num) {
	double a, b;

	//针对于负数参与运算的处理
	if (signC.top() == '-') {
		a = num.top(); 
		num.pop();
		signC.pop();   //取出负号
		if (!num.empty()) {
			if (signC.empty() || num.size() == signC.size())
				//如果前面还有数字,就压入+,即变成加负值
				signC.push('+');  
		}
		num.push(-a);  //压入负值
	}
	else {
		a = num.top();
		num.pop();
		b = num.top(); 
		num.pop();

		cout << "a:"<<a << endl;
		cout <<"b:" << b << endl;

		if (signC.top() == '+') num.push(b + a);
		else if (signC.top() == '*') num.push(b * a);
		else if (signC.top() == '/') num.push(b / a);
		else if (signC.top() == '^') num.push(pow(b, a));
		else if (signC.top() == '√') num.push(sqrt(a));

		signC.pop();
	}
}

void factorial(stack<double>& num) {
	int a = static_cast<int>(num.top()); num.pop();
	int result = 1;

	for (int i = 1; i <= a; i++) result *= i;

	num.push(static_cast<double>(result));
}

//放回优先级,优先级高的先运算
int printprioNum(char priNum) {
	//根据传入的符号,返回符号的优先级数字,数字高表示符号的优先级也就越高
	if (priNum == '(') return 0;
	else if (priNum == '+' || priNum == '-') return 1;
	else if (priNum == '*' || priNum == '/') return 2;
	//乘方的优先级在当前运算中是最高的
	else if (priNum == '^') return 3;
}