简单算术表达式的求值(待更新功能,暂无解析)

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

先实现了交互式,后一篇博客实现这个任务
算术表达式的求值(去年的课设之一 )

#include"pch.h"

#include<cmath>
#include<iostream>
using namespace std;
//操作符
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 >= 1 + '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()
{
	CLinkStack optr;//操作符栈
	Init(optr);
	ILinkStack opnd;//数字栈
	Init(opnd);
	char ch, theta;
	int mark = 0;
	int mark_weishu = 0;//小数部分标志
	int pointOccurTime = 0;
	ch = getchar();
	while (ch != '#')
	{
		if (ch == '\n');   //空格符号
		else
		{
			cin.ignore(numeric_limits<streamsize>::max(), '\n');//清空输入缓存区
			cout << "Please begin with '#'" << endl;
		}
		ch = getchar();
	}
	Push(optr, ch);//'#'表示起始点
	//遍历符号栈结果
	cout << "符号栈中的结果" << ends;
	GetAll(optr);
	cout << endl;
	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 = 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 = getchar();
			}
			else {//第一位整数
				int n = ch - '0';
				Push(opnd, n);
				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;
						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 != ')')
							goto L0;
						break;
					}
					case ')': {
						if (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;
						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); 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 = getchar();
		goto L;
	}
}
  return getTop(opnd);
L0:  return -1;//符号匹配不对
L1:  return -2;//符号类型不对
L2:  return -3;//输入了多余的小数点

}
int main() {
	int choice = -1;
L3: while (choice != 0 && choice != 1) {//非0或非1
	cout << "请输入数字0或1,以决定是否继续程序:" << ends;
	while (!(cin >> choice))
	{
		cin.clear();
		while (cin.get() != '\n')
		{
			continue;
		}//跳过错误输入
		cout << "请输入数字0或1,以决定是否继续程序:" << ends;
	}
}
	while (choice == 1) {
		printf("请一次输入#(a operate b)#或#a operate b#的格式,请使用小括号代替其他括号\n");
		double result = EvaluateExpression();
		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) {
			cin.ignore(numeric_limits<streamsize>::max(), '\n');//清空输入缓存区
			cout << "符号匹配不对,请进行符号匹配检查等工作" << endl;
		}
		else if (result == -2) {
			cin.ignore(numeric_limits<streamsize>::max(), '\n');//清空输入缓存区
			cout << "符号类型不对,请进行切换成英文格式的括号等检查工作" << endl;
		}
		else if (result == -3) {
			cin.ignore(numeric_limits<streamsize>::max(), '\n');//清空输入缓存区
			cout << "输入了多余的小数点,请进行检查工作" << endl;
		}
		choice = -1;
		goto L3;
	}
	system("pause");
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

广大菜鸟

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

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

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

打赏作者

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

抵扣说明:

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

余额充值