中缀表达式转后缀表达式,并计算后缀表达式值

 中缀表达式:也就是一般的算术表达式,如"9+(3-1)*3+10/2这样的

后缀表达式:就是将运算符挪到操作数后面,但这样的挪动是有规则的,例如上式转换后缀表达式后是这样的:"9 3 1-4*+10 2/+"

中缀转后缀表达式规则:

从左到右遍历中缀表达式中的每一个·数字和符号:

1.如果是操作数就输出,成为后缀表达式的一部分

2.如果是运算符,先判定它与栈顶元素的优先级,如果栈顶元素优先级低比它低或相等,则入栈;

  如果优先级高于它,则出栈当前栈顶元素到后缀表达式中,直到栈顶元素优先级比它高(即便两者优先级相等,也出栈)

 然后在将此运算符进栈(如果出栈过程中遇到‘(’,停止出栈,将 此运算符进栈);

3.如果是‘(',直接进栈;

4.如果是‘)',将栈中元素出栈,放入后缀表达式中,直到遇到‘('为止,并且‘('也要被出栈,但不可以放入后缀表达式中,直接丢弃;


代码实现:

俺是先用一个字符串数组接收输入的中缀表达式,但是不能直接对这个字符数组直接转后缀 表达式,如果直接转,会发生多个操作数连在一起

无法区分的情况,例如这样"931-4*+10 2/+",9,3,1三个不同操作数连在一起成了一个操作数了, 为了避免这种状况,俺使用了一个指针数组,

将每个操作数从字符串数组中分离出来,并放在指针数组所指向的动态内存中,以此来将每个操作数区分开来,在将经过转换的表达式转换成

后缀表达式。

将字符串数组中的中缀表达式进行转换,防止操作数连在一起:

void checkInputConvert(char * infix, char ** opNum)
{
	int index1 = 0;
	int length = strlen(infix);
	for (int i = 0; i < length;)
	{
		char ch = infix[i];
		int index2 = 0;
		int charNum = 0;
		if (isNumber(ch))//判断是否是数字
		{
			
			charNum++;
			opNum[index1] = (char*)calloc(charNum + 1,sizeof(char));
			opNum[index1][index2++] = ch;
			while (isNumber(infix[i + charNum]))
			{
				charNum++;//统计单个操作数所包含的字符个数
				opNum[index1] = (char*)realloc(opNum[index1], sizeof(char)*(charNum + 1));
				opNum[index1][index2++] = infix[i + charNum - 1];
			}
 			i += charNum;
			opNum[index1++][index2] = '\0';//设置字符串结束符
			continue;//单个操作数已找完,跳出此次循环
		}

		if (isOperator(ch))//判断是否是操作符
		{
			opNum[index1] = (char*)calloc(2, sizeof(char));
			opNum[index1++][index2] = ch;
			i++;
			continue;
		}

		if (ch == '(' || ch == ')')
		{
			opNum[index1] = (char*)calloc(2, sizeof(char));
			opNum[index1++][index2] = ch;
			i++;
			continue;
		}
		printf("输入的数据有误,请重新输入!\n");
		exit(1);
	}
这其中还要用到其他判断函数,如下:

int isOperator(char ch)//判断是否是运算符
{
	char op[5] = "+-*/";
	for (int i = 0; i < 5; i++)
	{
		if (ch == op[i])
			return 1;
	}
	return 0;
}
int isNumber(char ch)
{
	if ((ch - '0') >= 0 && (ch - '0') <= 9)
		return 1;
	else
		return 0;
}

//比较优先级,ch未中缀表达式中的运算符,op为栈中的运算符或‘(’
//当op1的优先级小于op2的优先级时返回-1,大于时返回1,等于时返回0
int comparePrior(char op1, char op2)
{
	if (op1 == '+' || op1 == '-')
	{
		if (op2 == '*' || op2 == '/')
			return -1;
		if (op2 == '+' || op2 == '-')
			return 0;
	}

	if (op1 == '*' || op1 == '/')
	{
		if (op2 == '*' || op2 == '/')
			return 0;
		if (op2 == '+' || op2 == '-')
			return 1;
	}
	if (op2 == '(')
		return 1;
}

再将将转换后的中缀表达式,转换为后缀表达式:

void infixToPrefix(char ** infix,char** prefix )//中缀表达式转后缀
{
	stack<char> LS;
	int index1 = 0;//指向infix中的下标
	int index2 = 0;//指向prefix中的下标
	while (infix[index1] != NULL)
	{
			char ch = infix[index1][0];
			if (ch == '(')//左括号入栈
			{
				LS.push(ch);
				index1++;//指向下一个字符串
				continue;
			}
			if (isNumber(ch))//数字输出到temp中
			{
				int length = strlen(infix[index1]);
				prefix[index2] = (char*)calloc(length + 1, sizeof(char));//测定该操作数所包含字符个数,并分配空间
				prefix[index2][length] = '\0';
				strcpy(prefix[index2++], infix[index1++]);//将字符串拷贝过来

				continue;
			}
			if (isOperator(ch))//判断是不是操作符
			{
				if (LS.empty())//栈空不比较,直接入栈
				{
					LS.push(ch);
					index1++;
				}
				else
				{
					if (comparePrior(ch, LS.top()) >= 0)//优先级高直接入栈
					{
						LS.push(ch);
					}
					else//优先级低需要将栈中优先级比ch高或等于的全部出栈
					{//如果有多个操作符出栈,将会把这些操作符存在同同一指针指向的字符数组中
						int num = 0;//记录要出栈的操作符的个数
						char temp[100] = { 0 };//用来暂存出栈的存操作符
						temp[num++] = LS.top();
						LS.pop();
						while (!LS.empty() && comparePrior(ch, LS.top()) <= 0)
						{
							temp[num++] = LS.top();
							LS.pop();
						}
						LS.push(ch);//所有比ch优先级大于等于的操作符已经出栈完成,将ch入栈
						prefix[index2] = (char *)calloc(++num, sizeof(char));
						prefix[index2][--num] = '\0';
						strcpy(prefix[index2++], temp);
					}
					index1++;
				}
				continue;
			}
			if (ch == ')')
			{
				int num = 0;//记录要出栈的操作符的个数
				char temp[100] = { 0 };//用来暂存出栈的存操作符
				while (LS.top() != '(')
				{
					temp[num++] = LS.top();
					LS.pop();
				}
				LS.pop();//将‘(’出栈
				prefix[index2] = (char *)calloc(++num, sizeof(char));
				prefix[index2][--num] = '\0';
				strcpy(prefix[index2++], temp);
				index1++;
				continue;
			}
		}
		if (!LS.empty())
		{
			int num = 0;//记录要出栈的操作符的个数
			char temp[100] = { 0 };//用来暂存出栈的存操作符
			while (!LS.empty())//此时中缀表达式已扫完,若栈中有剩余操作符,全部弹出,追加到prefix中
			{
				temp[num++] = LS.top();
				LS.pop();
			}
			prefix[index2] = (char *)calloc(++num, sizeof(char));
			strcpy(prefix[index2], temp);

		}
}

此时中缀表达式已转换未后缀表达式,计算后缀表达式的值:

算法过程自己百度......

int calcPrefix(char ** prefix)//计算后缀表达式求值
{
	stack<double> LS;
	int index1 = 0;
	while (prefix[index1] != NULL)
	{
		int index2 = 0;
		char ch;
		if (isNumber(ch = prefix[index1][index2]))
		{
			double opNum = ch - '0';
			while ((ch = prefix[index1][++index2]) != '\0')
				opNum = opNum * 10 + (ch - '0');
			LS.push(opNum);
			index1++;
			continue;
		}

		flag:
		if (isOperator(ch = prefix[index1][index2]))
		{

			switch (ch)
			{
				case '+':
					{
						double opNum1 = LS.top();
						LS.pop();
						double opNum2 = LS.top();
						LS.pop();
						LS.push(opNum1 + opNum2);
						while ((ch = prefix[index1][++index2]) != '\0')
							goto flag;
						index1++;
						break;
					}
				case '-':
					{
						double opNum1 = LS.top();
						LS.pop();
						double opNum2 = LS.top();
						LS.pop();
						LS.push(opNum2 - opNum1);
						while ((ch = prefix[index1][++index2]) != '\0')
							goto flag;
						index1++;
						break;
					}
			case '*':
					{
						double opNum1 = LS.top();
						LS.pop();
						double opNum2 = LS.top();
						LS.pop();
						LS.push(opNum2 * opNum1);
						while ((ch = prefix[index1][++index2]) != '\0')
							goto flag;
						index1++;
						break;
					}
			case '/':
					{
						double opNum1 = LS.top();
						LS.pop();
						double opNum2 = LS.top();
						LS.pop();
						LS.push(opNum2 / opNum1);
						while ((ch = prefix[index1][++index2]) != '\0')
							goto flag;
						index1++;
						break;
					}
			}
			continue;
		}
	}
	return (LS.top());
}

最后就是主函数了:

#define  _CRT_SECURE_NO_WARNINGS
#include<stack>
#include<string.h>
#include<stdio.h>
using namespace::std;
int isOperator(char ch);//判断是否是运算符
int comparePrior(char op1,char op2);//比较优先级
int isNumber(char ch);
void infixToPrefix(char ** infix, char ** prefix);//中缀表达式转后缀
int calcPrefix(char ** prefix);//计算后缀表达式求值
void checkInputConvert(char * ch,char ** infix);//将输入的字符串转换为合理的中缀表达式
int main()
{
	
	while (1)
	{
		char ch[100] = "12+33-5*65/10+((343+34)*2)*3/4+34";
		char * infix[100] = { 0 };
		char * prefix[100] = { 0 };
		//printf("请输入要计算的表达式:\n");
		//scanf("%s", ch);
		printf("输入的中缀表达式为:%s\n", ch);
		checkInputConvert(ch, infix);
		char** p = infix;
		while (*p != NULL)
		{
			printf("%s", *p);
			p++;
		}
		infixToPrefix(infix, prefix);

		printf("\n%d\n",calcPrefix(prefix));
		system("pause");

	}
	return 0;
}

写的不好。。。。。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值