其他分享
首页 > 其他分享> > 《计算机软件技术实习》之简单计算器的实现

《计算机软件技术实习》之简单计算器的实现

作者:互联网

《计算机软件技术实习》之简单计算器的实现

实验要求:

  1. 学习图形界面的设计,利用 MFC 应用程序(Java swing 或 QT 框架,或 C#)创建基于对话框的应用程序,添加按钮、编辑框等控件;
  2. 能通过设计的按钮控件输入并实现简单算术运算,要求表达式在编辑框中显示,能将运算结果,输出在编辑框内显示;并保存历史的表达式运算记录。
  3. 也能够实现混合运算的算术表达式求解,算术表达式中包括加、减、乘、除、括号等运算符;并且能够识别括号,优先级正确。
    实验准备:
    1.1算术表达式求值 :参与运算的数据(即操作数)可以为整数或实数,运算符(即操作符)为+、-、、/(加、减、乘、除)等二元操作符,包括圆括号;
    如 :5
    6+10-25=15
    6+(5-4/2)*3=15
    运算规则:
    先乘除,后加减,从左到右计算,先括号内,后括号外;
    表达式的三种表示法特点:
    1)操作数之间的相对次序不变;
    2)运算符的相对次序不同;
    3)后缀表达式中已考虑了运算符的优先级,没有括号,只有操作数和运算符。
    这一次我所运用到的方法是:方法二:双栈算符优先级法。
    双栈算符优先级法为了实现表达式求值,需要设置两个栈:
    一个是运算符栈OP,用于寄存运算符;
    另一个成为操作数栈OPND用于寄存运算数和运算结果。
    算法的关键是判断运算符的优先级。
    如果操作符的优先级比较高就直接入OP栈,如果优先级较低的话,需要先将OPND栈顶的两个操作数提取出来进行运算,然后将结果再一次入栈。遇到右括号需要运算,弹出OP栈直到左括号的所有操作数,然后将结果存到栈中。
    核心思想就是这样,具体算法如下所示:(大部分C++语言我已经将核心思想注释过了)
    比较优先级函数:
int priority(int state, char a){
		int rank;
		switch (a) {
		case '+':
		case '-':
			rank = 1;//+,-优先级为1。 
			break;
		case '*':
		case '/':
			rank = 2;//*,/优先级为2。 
			break;
		case '(':// 保证“(”直接入栈 ,也不会干扰其他运算符判断。 
			if (state == 0)
				rank = 3;
			else
				rank = 0;
			break;
		case '#':
			rank = 0;//#表示结束。 
			break;
		default:
			break;
		}
		return rank;
	}//priority函数主要来判断栈里面运算符的优先级。 

计算表达式函数:

double calculate(char op, double num1, double num2)
	{
		double anwser;
		switch (op) {
		case '+':
			anwser = num1 + num2;
			break;
		case '-':
			anwser = num1 - num2;
			break;
		case '*':
			anwser = num1 * num2;
			break;
		case '/':
			anwser = num1 / num2;
			break;
		default:
			break;
		}
		return anwser;
	}//calculate函数主要是实现两个数字的运算(包括加减乘除),以op来读取OP栈里面的运算符。 
读入表达式并且计算的出结果的函数:

```cpp

```cpp
double result(string s,int a,int &sign) {
	stack<char> OP;//定义OP栈来存放操作运算符。 
	stack<double> OPND;//定义OPND来存放需要运算的数字(包括小数)。
	OP.push('#');//先在运算符的栈之中放入一个中止运算符。 
	OPND.push(0);
	string num;//用来保存一个完整的运算数字。 
	for (int i = 0; i<a; i++) {//读取整个s字符串。	
		if ((s[i] == '+' || s[i] == '-' || s[i] == '*' || s[i] == '/') && (s[i + 1] == '+' || s[i + 1] == '-' || s[i + 1] == '*' || s[i + 1] == '/'))
		{
			sign = 0;
			break;
		}
		if (s[i] == '/' && s[i + 1] == '0')
		{
			sign = 0;
		}
		if (isdigit(s[i])) {//判断是否为0到9的数字。 
			while (isdigit(s[i]) || s[i] == '.') {
				num.push_back(s[i]);//判断输入小数点之后,在末尾增加一个小数点。 
				i++;//继续后移一位,读入小数点后面的部分。 
			}
			double a = atof(num.c_str());//把上面读取出来的整个数字字符串转化为双精度类型的数字赋值给a。 
			OPND.push(a);// 将a这个数字放入OPND的栈之中。 
			num.clear();//清除num中的数字。 
			i--;//后移一位。 
		}
		else if (s[i] == '+' || s[i] == '-' || s[i] == '*' || s[i] == '/' || s[i] == '(') {
			if (s[i] == '(') {
				if (s[i + 1] == '-')
					OPND.push(0);
			};
			if (priority(0, s[i]) > priority(1, OP.top()))//比较字符串s中的运算符优先级和OP栈中的优先级,大则入栈。 
				OP.push(s[i]);
			else {
				while (priority(0, s[i]) <= priority(1, OP.top())) {
					char temp = OP.top();//定义temp保存OP栈顶运算符。 
					OP.pop();//弹出栈顶 
					double op2 = OPND.top();//将OPND栈顶的数字赋值给op2(由于先进后出原则,必须赋值给op2保证运算顺序)。
					OPND.pop();//弹出栈顶 
					double op1 = OPND.top();//取出OPND当前栈顶的数字,进行下一步的运算。
					OPND.pop(); //弹出栈顶 
					OPND.push(calculate(temp, op1, op2));//将计算结果入栈。 
				}
				OP.push(s[i]);
			}
		}
		else if (s[i] == ')') {
			while (OP.top() != '(') {//取出操作,直到将取出OP栈中的“(”为止。 
				char temp = OP.top();
				OP.pop();
				double op2 = OPND.top();
				OPND.pop();
				double op1 = OPND.top();
				OPND.pop();
				OPND.push(calculate(temp, op1, op2));
			}
			OP.pop();//弹出“)” ,结束。 
		}//上面的操作已经判断过优先级,所以括号里的数字可以直接计算,无需重复判断。
	}
	while (OP.top() != '#') {
		char temp = OP.top();
		OP.pop();
		double op2 = OPND.top();
		OPND.pop();
		double op1 = OPND.top();
		OPND.pop();
		OPND.push(calculate(temp, op1, op2));
	}//将栈中的运算符全部取出来,计算完成全部表达式,将值再一次放回OPND栈中。 
       return OPND.top();
	;//此时结果OPND栈顶的结果就是整个表达式的结果。 
}

`
需要判断是否符合表达式的规范,并且要让输出的结果有小数输出double类型,没有小数输出int类型。所以我设置了一个sign标识符来便于识别整个表达式是否符合标准,如果sign为1;说明符合可以输出,sign为0的话说明输入表达式有误。具体实现如下所示:

int main(){
	double b;
	string s;
	int a,SIGN=1;//标志位首先置为1
	cin>>s;
	a=s.length();
    b=result(s,a,SIGN);
	if(SIGN==1)
	cout<<b<<endl;
	if(SIGN==0)//判断条件不符合正确表达式会把标志置为0.
	cout<<"Error!Please enter the correct expression."<<endl;
}

这是C++的完整实现,我会在下一篇blog之中将讲述基于MFC的C++代码具体学习以及实现。
我所参考的资料为:CSDN上的yujunseu原创博客。链接如下:https://blog.csdn.net/yj3254/article/details/43705713?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.control

标签:计算机软件,double,top,OPND,运算符,计算器,实习,优先级,OP
来源: https://blog.csdn.net/qq_48063427/article/details/110651942