算术表达式的求值(去年的课设之一 )

算术表达式的求值
[问题描述]
  一个算术表达式是由操作数(operand)、运算符(operator)和界限符(delimiter)组成的。假设操作数是正实数,运算符只含加减乘除等四种运算符,界限符有左右括号和表达式起始、结束符“#”,如:#(7+15)*(23-28/4)#。引入表达式起始、结束符是为了方便。编程利用“运算符优先法”求算术表达式的值。
[基本要求]
(1) 从键盘或文件读入一个合法的算术表达式,输出正确的结果。
(2) 显示输入序列和栈的变化过程。
(3) 考虑算法的健壮性,当表达式错误时,要给出错误原因的提示。
上一篇实现交互式
简单算术表达式的求值(待更新功能,暂无解析)
需要的头文件


#include <fstream>
#include<string>
#include<cmath>
#include<iostream>
using namespace std;

需要用到的结构:2个栈

//操作符
typedef struct CStackNode {
	char data;
	struct CStackNode *next;
} CStackNode, *CLinkStack;
bool Init(CLinkStack &cL) {
	cL = NULL;
	return true;
}
//入栈
bool Push(CLinkStack &L, char e) {
	CLinkStack temp = new CStackNode;
	temp->data = e;
	temp->next = L;
	L = temp;
	return true;
}
//出栈
bool Pop(CLinkStack &L, char  & e) {
	if (!L) return false;
	e = L->data;
	CLinkStack temp = L;
	L = L->next;
	delete temp;
	return  true;
}
//取顶
char getTop(CLinkStack L) {
	if (L) return L->data;
	else return false;
}
//判空
bool StackEmpty(CLinkStack L) {
	if (!L) return true;
	else return false;
}
//清空
bool clearAll(CLinkStack L) {
	char e;
	while (!StackEmpty(L)) {
		Pop(L, e);
	}
	return true;
}
//遍历
void GetAll(CLinkStack S) {// 递归遍历,分治法
	if (S == NULL) {
		return;
	}
	else {
		cout << S->data << " ";
		GetAll(S->next);
	}
}
//数字
typedef struct IStackNode {
	double data;
	struct IStackNode *next;
} IStackNode, *ILinkStack;
bool Init(ILinkStack & cL) {
	cL = NULL;
	return true;
}
bool Push(ILinkStack &L, double e) {
	ILinkStack temp = new IStackNode;
	temp->data = e;
	temp->next = L;
	L = temp;
	return true;
}
bool Pop(ILinkStack &L, double & e) {
	if (!L) return false;
	e = L->data;
	ILinkStack temp = L;
	L = L->next;
	delete temp;
	return  true;
}
double getTop(ILinkStack L) {
	if (L) return L->data;
	else return false;
}
bool StackEmpty(ILinkStack L) {
	if (!L) return true;
	else return false;
}
bool clearAll(ILinkStack L) {
	double e;
	while (!StackEmpty(L)) {
		Pop(L, e);
	}
	return true;
}
void GetAll(ILinkStack S) {// 递归遍历,分治法
	if (S == NULL) {
		return;
	}
	else {
		cout << S->data << " ";
		GetAll(S->next);
	}
}

//判断符号是否为规定的操作符
bool In(char c) {
	// if (c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == ')' || c == '#'||c=='.'||c=='('||c==')')
	if (c >=  '0' &&c <= 9 + '0')
		return false;
	else
		return true;
}
//判断字符
bool TrueIn(char c) {
	if (c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == ')' || c == '#' || c == '.')
		return true;
	else
		return false;
}

//判断优先级
char Precede(char a, char b) {//按照表规定
	switch (a) {
	case '+':
	{
		switch (b) {
		case '+':return '>';
		case '-':return '>';
		case '*':return '<';
		case '/':return '<';
		case '(':return '<';
		case ')':return '>';
		case '#':return '>';
		}
	}
	break;
	case '-':
	{
		switch (b) {
		case '+':return '>';
		case '-':return '>';
		case '*':return '<';
		case '/':return '<';
		case '(':return '<';
		case ')':return '>';
		case '#':return '>';
		}
	}
	break;
	case '*':
	{
		switch (b) {
		case '+':return '>';
		case '-':return '>';
		case '*':return '>';
		case '/':return '>';
		case '(':return '<';
		case ')':return '>';
		case '#':return '>';
		}
	}
	break;
	case '/':
	{
		switch (b) {
		case '+':return '>';
		case '-':return '>';
		case '*':return '>';
		case '/':return '>';
		case '(':return '<';
		case ')':return '>';
		case '#':return '>';
		}
	}
	break;
	case '(':
	{
		switch (b) {
		case '+':return '<';
		case '-':return '<';
		case '*':return '<';
		case '/':return '<';
		case '(':return '<';
		case ')':return '=';
			//	case '#':return ' ';
		}
	}
	break;
	case ')':
	{
		switch (b) {
		case '+':return '>';
		case '-':return '>';
		case '*':return '>';
		case '/':return '>';
			//	case '(':return ' ';
		case ')':return '>';
		case '#':return '>';
		}
	}
	break;
	case '#':
	{
		switch (b) {
		case '+':return '<';
		case '-':return '<';
		case '*':return '<';
		case '/':return '<';
		case '(':return '<';
			//	case ')':return ' ';
		case '#':return '=';
		}
	}
	break;
	}
}

//计算
double Operate(double a, char c, double b) {
	switch (c) {
	case '+': return (a + b); break;
	case '-':return (a - b); break;
	case '*':return (a*b);	break;
	case '/':return (a / b);	break;
	}
}
//匹配重点
double EvaluateExpression(char data[])
{
	CLinkStack optr;//操作符栈
	Init(optr);
	ILinkStack opnd;//数字栈
	Init(opnd);
	char ch, theta;
	int mark = 0;
	int mark_weishu = 0;//小数部分标志
	int pointOccurTime = 0;
	int currentPos = 0;
	ch = data[currentPos++];//ch = getchar();
	while (ch != '#')
	{
		return -1;
	}
	Push(optr, ch);//'#'表示起始点
	//遍历符号栈结果
	cout << "符号栈中的结果" << ends;
	GetAll(optr);
	cout << endl;
	ch = data[currentPos++];// ch = getchar();
	double a, b;
	int numberTime = 0;
L:while (ch != '#' || getTop(optr) != '#') //表达式没有扫描完毕或OPTR栈定元素不为#
{
	if (ch != '\n') {
		if (!In(ch))
		{//输入数字,只对整数操作
			if (numberTime && mark == 0)//二位数或更多位数
			{//不是第一位且前一位也为数字
				double e;
				Pop(opnd, e);
				b = e * 10 + (ch - '0');
				Push(opnd, b);
				ch = data[currentPos++];	// ch = getchar();
			}
			else if (numberTime &&  mark == 1)
			{//不是第一位且前一位不为数字,小数部分
				double e, numbertemp;
				Pop(opnd, e);
				numbertemp = (ch - '0');
				++mark_weishu;
				b = e + numbertemp * pow(10, (mark_weishu)*(-1));
				Push(opnd, b);
				ch = data[currentPos++];//	ch = getchar();
			}
			else {//第一位整数
				int n = ch - '0';
				Push(opnd, n);
				ch = data[currentPos++];	//	ch = getchar();
				numberTime = 1;
			}
			//遍历数字栈结果
			cout << "数字栈中的结果" << ends;
			GetAll(opnd); cout << endl;
		}
		else //字符
		{
			if (TrueIn(ch)) {//使用正确的符号
				if (numberTime != 0 && ch == '.') {
					pointOccurTime += 1;
					if (pointOccurTime < 2) {
						mark = 1;
						ch = data[currentPos++];// cin >> ch;
						goto L;
					}
					else
						goto L2;
				}
				else
				{
					//先考虑匹配问题
					switch (getTop(optr))
					{
						case '#': {
							if (ch != '('&&ch != '#'&&ch != '+'&&ch != '-'&&ch != '*'&&ch != '/')
								goto L0;
							break;
						}
						case '(': {
							if (ch != '+'&&ch != '-'&&ch != '*'&&ch != '/'&&ch != ')'&&ch!='(' )
								goto L0;
							break;
						}
						case ')': {
							if (ch != '#'&&ch != '+'&&ch != '-'&&ch != '*'&&ch != '/')
								goto L0;
							break;
						}
						case '+': {
							if (ch != '#'&&ch != '+'&&ch != '-'&&ch != '*'&&ch != '/'&&ch!='(')
								goto L0;
							break;
						}
						case '-': {
							if (ch != '#'&&ch != '+'&&ch != '-'&&ch != '*'&&ch != '/'&&ch != '(')
								goto L0;
							break;
						}
						case '*': {
							if (ch != '#'&&ch != '+'&&ch != '-'&&ch != '*'&&ch != '/'&&ch != '(')
								goto L0;
							break;
						}
						case '/': {
							if (ch != '#'&&ch != '+'&&ch != '-'&&ch != '*'&&ch != '/'&&ch != '(')
								goto L0;
							break;
						}
					}
					//正式比较运算顺序
					numberTime = 0;
					pointOccurTime = 0;
					mark = 0;
					mark_weishu = 0;
					switch (Precede(getTop(optr), ch))
					{
						case '<'://后面的大,压入
						{
							Push(optr, ch);
							//遍历符号栈结果
							cout << "符号栈中的结果" << ends;
							GetAll(optr);
							cout << endl;
							//遍历数字栈结果
							cout << "数字栈中的结果" << ends;
							GetAll(opnd); cout << endl;
							ch = data[currentPos++];//cin >> ch; 
							break;
						}
						case '>'://后面的小,输入前面的结果
						{
							if (!StackEmpty(opnd) && !StackEmpty(opnd->next)) {
								Pop(optr, theta);
								Pop(opnd, a);
								Pop(opnd, b);
								Push(opnd, Operate(b, theta, a));// b operate a的结果
								//遍历符号栈结果
								cout << "符号栈中的结果" << ends;
								GetAll(optr);
								cout << endl;
								//遍历数字栈结果
								cout << "数字栈中的结果" << ends;
								GetAll(opnd); cout << endl;
							}
							else
								goto L0;
							break;
						}
						case '=':Pop(optr, ch); 
							ch = data[currentPos++];//cin >> ch; 
							break;
					}
					//考虑到有3个书上没规定,但是会影响的顺序
					if ((getTop(optr) == '('&&ch == '#') || (getTop(optr) == ')'&&ch == '(') || (getTop(optr) == '#'&&ch == ')'))
						goto L0;
					//遍历符号栈结果
					cout << "符号栈中的结果" << ends;
					GetAll(optr);
					cout << endl;
				}
			}
			else
				goto L1;//没用使用正确的符号格式就返回-2
		}
	}
	else {//遇到换行符号
	ch = data[currentPos++];//	ch = getchar();
		goto L;
	}
}
  return getTop(opnd);
L0:  return -1;//符号匹配不对
L1:  return -2;//符号类型不对
L2:  return -3;//输入了多余的小数点
}

//主函数
int main() {
	char data[100];
	const char *p;
	string line;
	fstream in("C:\\Users\\Lenovo\\Desktop\\data.txt", ios::in);
	//我放在电脑桌面上
	if (in) // 有该文件  
	{
L3:		while (getline(in, line)) // line中不包括每行的换行符  
		{
			cout << line << endl;
			p = line.c_str();
			int i;
			for (i = 0; i < line.length(); i++) {
				if (p[i] >= 0 && p[i] <= 127)//ASCILL码范围内
					data[i] = p[i];
				else {
					cout << "符号类型不对,请进行切换成英文格式的括号等检查工作" << endl;
					memset(data, '\0', sizeof(data));
					goto L3;
				}
			}
			data[i] = '\0';
			cout << "字符串信息" << ends;
			for (i = 0; i < line.length(); i++) {
				cout<<data[i];
			}cout << endl;
			double result = EvaluateExpression( data);
			if (result != -2 && result != -1 && result != -3) {
				if ((result - (int)result) != 0)
					printf("result=%lf\n", result);
				else
					cout << (int)result << endl;
			}
			else if (result == -1) {
				
				cout << "符号匹配不对,请进行符号匹配检查等工作" << endl;
				memset(data, '\0', sizeof(data));
				continue;
			}
			else if (result == -2) {
				
				memset(data, '\0', sizeof(data));
				cout << "符号类型不对,请进行切换成英文格式的括号等检查工作" << endl;
				continue;
			}
			else if (result == -3) {
			
				memset(data, '\0', sizeof(data));
				cout << "输入了多余的小数点,请进行检查工作" << endl;
				continue;
			}
			memset(data, '\0', sizeof(data));

		}
	}
	in.close();
	system("pause");
	return 0;
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

广大菜鸟

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

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

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

打赏作者

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

抵扣说明:

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

余额充值