编译原理:中缀表达式求值

编译器中的表达式求值问题实验

#define _CRT_SECURE_NO_WARNINGS

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

typedef char* ElementType;
typedef struct SNode* PtrToSNode;
struct SNode {
	ElementType Data;
	PtrToSNode Next;
};
typedef PtrToSNode Stack;

Stack CreateStack(void);//创建一个栈
int IsEmpty_Stack(Stack);//判断栈是否为空
void Push(Stack, ElementType);//将元素放入栈中
ElementType Pop(Stack);//将元素从栈顶拿出
ElementType GetStackTop(Stack);//查看栈顶元素
int Arith(char*);
ElementType* CreateExpS(char*);
int IsNumber(ElementType);
int Compare(ElementType, ElementType);
int ChToNum(ElementType);
ElementType NumToCh(int);
int Math(int, ElementType, int);
int FindValue(ElementType);

int main(void)
{
	char* Expression;
	int Ans;

	Expression = (char*)malloc(sizeof(char)*100);
	scanf("%s", Expression);
	Ans = Arith(Expression);
	printf("%d", Ans);

	return 0;
}

int Arith(char* Expression)
{
	ElementType* ExpS;
	Stack OpS;
	Stack NumS;
	int Front;
	int Rear;
	int Ans;
	ElementType Op;
	int Index = 0;

	OpS = CreateStack();
	NumS = CreateStack();
	ExpS = CreateExpS(Expression);
	Push(OpS, ExpS[Index]);//将表达式栈顶#放入字符栈中
	Index++;
	do {
		if(IsNumber(ExpS[Index]))//如果当前表达式元为数字
			Push(NumS,ExpS[Index++]);//则将该元入数栈
		else {//若是字符
			if (Compare(ExpS[Index], GetStackTop(OpS))==-1) {//当符号的级别大于符栈顶符号
				Push(OpS, ExpS[Index]);//则将当前符号入符栈
				Index++;//指向下一个表达式元,继续判断
			}
			else if (Compare(ExpS[Index], GetStackTop(OpS))==1) {//当符号级别小于符栈顶符号
				Rear = ChToNum(Pop(NumS));//则可以开始计算
				Front = ChToNum(Pop(NumS));
				Op = Pop(OpS);
				Ans = Math(Front, Op, Rear);//数栈顶部两个数按照符栈顶符号运算
				Push(NumS, NumToCh(Ans));//将运算结果重新放入数栈
			}
			if (Compare(ExpS[Index], GetStackTop(OpS))==0) {//当符号级别等于符栈顶的符号
				Pop(OpS);//则应当将符栈顶出栈,往往是符栈顶是(,#,当前符号是),#
				Index++;
			}
		}
	} while (!IsEmpty_Stack(OpS));

	return ChToNum(Pop(NumS));
}
ElementType* CreateExpS(char* Expression)
{
	int index = 0;
	int i;
	int j;
	char* Element;//栈中存储的是一个字符串
	i = 0;
	j = 1;
	ElementType* ExpS;
	
	ExpS = (ElementType*)malloc(sizeof(ElementType) * 100);
	Element = (char*)malloc(sizeof(char) * 2);
	Element[0] = '#';
	Element[1] = '\0';
	ExpS[index++] = Element;//将#先放入表达式
	if (Expression[i] == '-') {//如果表达式第一个元是负数
		Element = (char*)malloc(sizeof(char) * 10);
		Element[0] = '-';
		i++;
		for (; '0' <= Expression[i] && Expression[i] <= '9'; i++)//将整个负数取出
			Element[j++] = Expression[i];
		Element[j] = '\0';
		ExpS[index++] = Element;
	}
	while (Expression[i] != '\0') {//当输入的表达式未处理完则继续循环
		//当负数存在于表达式非首位位置时,则一定会出现(-相连续的情况
		if (Expression[i] == '(' && Expression[i + 1] == '-') {//(-则当前是一个负数
			Element = (char*)malloc(sizeof(char) * 10);
			j = 1;
			Element[0] = '-';
			for (i += 2; '0' <= Expression[i] && Expression[i] <= '9'; i++)
				Element[j++] = Expression[i];
			i ++;
			Element[j] = '\0';
			ExpS[index++] = Element;
		}
		else if (Expression[i] <= '0' || '9' <= Expression[i]) {//当前为符号
			Element = (char*)malloc(sizeof(char) * 2);
			Element[0] = Expression[i];
			Element[1] = '\0';
			i++;
			ExpS[index++] = Element;
		}
		else {//当前为正整数
			j = 0;
			Element = (char*)malloc(sizeof(char) * 10);
			for (; '0' <= Expression[i] && Expression[i] <= '9'; i++)
				Element[j++] = Expression[i];
			Element[j] = '\0';
			ExpS[index++] = Element;
		}
	}
	Element = (char*)malloc(sizeof(char) * 2);
	Element[0] = '#';
	Element[1] = '\0';
	ExpS[index++] = Element;

	return ExpS;
}
int IsNumber(ElementType Exp)//是否为数字
{
	if (('0' <= Exp[1] && Exp[1] <= '9') || ('0' <= Exp[0] && Exp[0] <= '9'))
		return 1;
	else
		return 0;
}
int Compare(ElementType ExpTop, ElementType OpTop)//将表达式栈顶符和符栈顶符按表比较
{
	int ExpN;
	int OpN;

	ExpN = FindValue(ExpTop);//将表达式栈顶符转化为下标
	OpN = FindValue(OpTop);//将符栈顶转化为下标
	int Map[7][7] = {//1为大于,-1为小于,0是等于
		{1,1,-1,-1,-1,1,1},
		{1,1,-1,-1,-1,1,1},
		{1,1,1,1,-1,1,1},
		{1,1,1,1,-1,1,1},
		{-1,-1,-1,-1,-1,0,0},
		{1,1,1,1,0,1,1},
		{-1,-1,-1,-1,-1,0,0} };

	return Map[OpN][ExpN];
}
//用于解决栈中只存字符串的问题
int ChToNum(ElementType Num)//将字符串转化为数字
{
	int N = 0;
	int i = 0;
	int Op = 1;

	if (Num[0] == '-') {
		Op = -1;
		i++;
	}

	for (; Num[i] != '\0'; i++)
		N = N * 10 + Num[i] - '0';

	return N * Op;
}
//用于将计算结果重新放入数栈中
ElementType NumToCh(int Str)//将数字转化为字符串
{
	ElementType N;
	Stack S;
	char* String;
	ElementType Ch;
	int i = 0;

	String = (char*)malloc(sizeof(char) * 10);
	if (Str < 0) {//如果为负数,则字符串钱应当还有-
		Str = -Str;
		String[i++] = '-';
	}
	S = CreateStack();
	while (Str != 0) {//将数字一个一个取出,入栈(因为每次取个位,取出顺序是倒的)
		N = (char*)malloc(sizeof(char) * 2);
		N[0] = '0'+ Str % 10;
		N[1] = '\0';
		Push(S, N);
		Str /= 10;
	}
	while (!IsEmpty_Stack(S)) {
		Ch = Pop(S);
		String[i++] = Ch[0];
	}
	String[i] = '\0';

	return String;
}
int Math(int Front, ElementType Op, int Rear)//根据运算符计算
{
	switch (Op[0])
	{
	case '+': return Front + Rear;
	case '-': return Front - Rear;
	case '*': return Front * Rear;
	case '/': return Front / Rear;
	case '(': return -1;
	case ')': return -1;
	case '#': return -1;
	default:
		return -1;
	}
}

int FindValue(ElementType Op)
{
	switch (Op[0])
	{
	case '+': return 0;
	case '-': return 1;
	case '*': return 2;
	case '/': return 3;
	case '(': return 4;
	case ')': return 5;
	case '#': return 6;
	default:
		return -1;
	}
}
//以下为所用到的栈函数
Stack CreateStack(void)
{
	Stack S = (Stack)malloc(sizeof(struct SNode));

	S->Next = NULL;

	return S;
}

int IsEmpty_Stack(Stack S)
{
	return (S->Next == NULL);
}

void Push(Stack S, ElementType Sdata)
{
	PtrToSNode P;

	P = (PtrToSNode)malloc(sizeof(struct SNode));//创建新的栈结点
	P->Data = Sdata;
	P->Next = S->Next;//将栈顶链接在新栈顶后
	S->Next = P;//将新栈顶链接在栈头后
}

ElementType Pop(Stack S)
{
	if (IsEmpty_Stack(S)) {
		printf("The Stack is Empty.");

		return NULL;
	}
	else {
		PtrToSNode P;
		ElementType Sdata;

		P = S->Next;//找到栈顶结点
		Sdata = P->Data;//取出数据
		S->Next = P->Next;//栈头链接新的栈顶
		free(P);//释放原栈顶

		return Sdata;
	}
}

ElementType GetStackTop(Stack S)
{
	if (IsEmpty_Stack(S)) {
		printf("The Stack is empty.");

		return NULL;
	}
	else
		return S->Next->Data;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值