逆波兰计算器的实现

话不多说先上代码供大佬们检查
#include"stdio.h"
#include"stdlib.h"
#include"memory.h"

#define MAXSIZE 100

typedef struct MStack
{
	char data[MAXSIZE];
	int top;
};

MStack *InitStack()
{
	MStack *ms;
	ms = (MStack*)malloc(sizeof(MStack));
	memset(ms->data, 0, MAXSIZE);
	ms->top = -1;
	return ms;
}

void PushStack(MStack *ms, char e)
{
	if (ms->top == MAXSIZE - 1)
	{
		printf("栈满溢出");
		return;
	}
	ms->data[++ms->top] = e;
}

void PopStack(MStack *ms, char *e)
{
	if (ms->top == -1)
	{
		printf("栈空!");
		return;
	}
	*e = ms->data[ms->top--];
}

int PriCal(char c)
{
	if (c == '-' || c == '+')return 1;
	if (c == '*' || c == '/')return 2;
	if (c == '(' || c == ')')return 3;
	return false;
}

int main()
{
	MStack *ms;
	MStack *msn;
	msn = InitStack();
	ms = InitStack();
	char above = 9;//保存上一次的输入值,检测输入算式是否合法
	char c;
	char num;
	int e;
	c = getchar();
	//以下是将普通中缀表达式改为后缀表达式
	while (1)
	{
		e = 0;
		//if (c == '\n')
		//{
			//if (!(above != ')' || (above <= '9' && above >= '0')))
			//{
			//	printf("输入算式有错,请检查后重新运行此程序!");
			//	return -1;
			//}
			//while (ms->top != -1)
			//{
			//	PopStack(ms, &c);
			//	PushStack(msn, c);
			//}
			//break;
		//}
		if (c <= '9' && c >= '0')
		{
			if (ms->top != -1)
			{
				if (above != '+' && above != '-' && above != '*' && above != '/' && above != '(')
				{
					printf("输入算式有错,请检查后重新运行此程序!");
					return -1;
				}
			}
			while (c <= '9' && c >= '0')
			{
				e = e * 10 + c - '0';
				above = c;
				c = getchar();
			}
			PushStack(msn, (char)(e + '0'));
		}
		if (c == '+' || c == '-' || c == '*' || c == '/')
		{
			if (!(above != ')' || (above <= '9' && above >= '0')))
			{
				printf("输入算式有错,请检查后重新运行此程序!");
				return -1;
			}
			if (ms->top == -1)
				PushStack(ms, c);
			else if (PriCal(ms->data[ms->top]) >= PriCal(c))
			{
				while (PriCal(ms->data[ms->top]) >= PriCal(c))
				{
					if (ms->data[ms->top] == '(')break;
					num = c;
					PopStack(ms, &num);
					PushStack(msn, num);
				}
				PushStack(ms, c);
			}
			else PushStack(ms, c);
		}
		if (c == '(' || c == ')')
		{
			if (c == '(')
			{
				if (above != '+' &&above != '-' &&above != '*' &&above != '/'&&ms->top != -1)
				{
					printf("输入算式有错,请检查后重新运行此程序!");
					return -1;
				}
				PushStack(ms, c);
			}
			if (c == ')')
			{
				if (above < '0' || above > '9')
				{
					printf("输入算式有错,请检查后重新运行此程序!");
					return -1;
				}
				while (c != '(')
				{
					PopStack(ms, &c);
					if (c != '(')
						PushStack(msn, c);
				}
			}
		}
		above = c;
		if (c == '\n')break;
		else c = getchar();
	}
	while (msn->top != -1)
	{
		PopStack(msn, &c);
		PushStack(ms, c);
	}
	/*PushStack(ms, '+');
	PushStack(ms, '/');
	PushStack(ms, '2');
	PushStack(ms, '8');
	PushStack(ms, '+');
	PushStack(ms, '*');
	PushStack(ms, '3');
	PushStack(ms, '-');
	PushStack(ms, '1');
	PushStack(ms, '3');
	PushStack(ms, '9');*/
	//以下是计算部分
	while (ms->top != -1)
	{
		if (ms->data[ms->top] <= '0' + 255 && ms->data[ms->top] >= '0')//原本数据范围是'0'-'9',如果要计算10以外则需要加大为'0'-'0'+255
		{
			PopStack(ms, &c);
			PushStack(msn, c);
		}
		if (ms->data[ms->top] == '+')
		{
			PopStack(ms, &c);
			PopStack(msn, &c);
			PopStack(msn, &num);
			num = (int)(num - '0') + (int)(c - '0') + '0';
			PushStack(msn, num);
		}
		if (ms->data[ms->top] == '-')
		{
			PopStack(ms, &c);
			PopStack(msn, &c);
			PopStack(msn, &num);
			num = (int)(num - '0') - (int)(c - '0') + '0';
			PushStack(msn, num);
		}
		if (ms->data[ms->top] == '/')
		{
			PopStack(ms, &c);
			PopStack(msn, &c);
			PopStack(msn, &num);
			num = (char)(int)(num - '0') / (int)(c - '0') + '0';
			PushStack(msn, num);
		}
		if (ms->data[ms->top] == '*')
		{
			PopStack(ms, &c);
			PopStack(msn, &c);
			PopStack(msn, &num);
			num = (int)(c - '0')*(int)(num - '0') + '0';
			PushStack(msn, num);
		}
	}
	printf("%d", msn->data[msn->top] - '0');
	return 0;
}

以上就是我的全部代码


逆波兰算法无非是中缀表达式转换为后缀表达式,然后通过后缀表达式求值。刚开始尝试的时候想法比较大一直想一次性实现,耽误我一天时间,后面分两个模块就实现挺快的  == 。

栈的基本操作没啥可以说的,那我们就不说了,先说说实现后缀表达式的计算这块,

while (ms->top != -1)
	{
		if (ms->data[ms->top] <= '9' && ms->data[ms->top] >= '0')//原本数据范围是'0'-'9',如果要计算10以外则需要加大为'0'-'0'+255
		{
			PopStack(ms, &c);
			PushStack(msn, c);
		}
		if (ms->data[ms->top] == '+')
		{
			PopStack(ms, &c);
			PopStack(msn, &c);
			PopStack(msn, &num);
			num = (int)(num - '0') + (int)(c - '0') + '0';
			PushStack(msn, num);
		}
		if (ms->data[ms->top] == '-')
		{
			PopStack(ms, &c);
			PopStack(msn, &c);
			PopStack(msn, &num);
			num = (int)(num - '0') - (int)(c - '0') + '0';
			PushStack(msn, num);
		}
		if (ms->data[ms->top] == '/')
		{
			PopStack(ms, &c);
			PopStack(msn, &c);
			PopStack(msn, &num);
			num = (char)(int)(num - '0') / (int)(c - '0') + '0';
			PushStack(msn, num);
		}
		if (ms->data[ms->top] == '*')
		{
			PopStack(ms, &c);
			PopStack(msn, &c);
			PopStack(msn, &num);
			num = (int)(c - '0')*(int)(num - '0') + '0';
			PushStack(msn, num);
		}
	}

此时数据只接受'0'-'9'的数字的加减法,一次次输入太麻烦我就一次性给输入为9 3 1 - 3 * + 8 2 / +;9是栈顶元素,这相当于计算9+(3-1)*3+8/2,结果算出来没有啥错误,这块是比较简单的。

	MStack *ms;
	MStack *msn;
	msn = InitStack();
	ms = InitStack();
	char above = 9;//保存上一次的输入值,检测输入算式是否合法
	char c;
	char num;
	int e;
	c = getchar();
	//以下是将普通中缀表达式改为后缀表达式
    while (1)
    {
        if (c == '\n')
        {
            while (ms->top != -1)
            {
                PopStack(ms, &c);
                PushStack(msn, c);
            }
            break;
        }
        if (c <= '9' && c >= '0')
            PushStack(msn, c);
        if (c == '+' || c == '-' || c == '*' || c == '/')
        {
            if (ms->top == -1)
                PushStack(ms, c);
            else if (PriCal(ms->data[ms->top]) >= PriCal(c))
            {
                while (PriCal(ms->data[ms->top]) >= PriCal(c))
                {
                    if (ms->data[ms->top] == '(')break;
                    num = c;
                    PopStack(ms, &num);
                    PushStack(msn, num);
                }
                PushStack(ms, c);
            }
            else PushStack(ms, c);
        }
        if (c == '(' || c == ')')
        {
            if (c == '(')PushStack(ms, c);
            if (c == ')')
            {
                while (c != '(')
                {
                    PopStack(ms, &c);
                    if(c != '(')
                        PushStack(msn, c);
                }
            }
        }
        c = getchar();
    }


我们现在实现了中后缀表达式转化,这儿关注的只是加减乘除的表达式转化,没怎么注意数字的,但是这样数字也差不多(如果只是单个字符的话)

我们给程序加个错误判断,above存储上一个输入的字符的值,如果我们这次输入为数字上次就必须是左括号或者操作符其它判断类似。但是如果栈内数据为空还需要单独判断。

同时再加个小小的操作让数据能处理非单个字符的运算

    MStack *ms;
    MStack *msn;
    msn = InitStack();
    ms = InitStack();
    char above = 9;//保存上一次的输入值,检测输入算式是否合法
    char c;
    char num;
    int e;
    c = getchar();
    //以下是将普通中缀表达式改为后缀表达式
    while (1)
    {
        e = 0;
        //if (c == '\n')
        //{
            //if (!(above != ')' || (above <= '9' && above >= '0')))
            //{
            //    printf("输入算式有错,请检查后重新运行此程序!");
            //    return -1;
            //}
            //while (ms->top != -1)
            //{
            //    PopStack(ms, &c);
            //    PushStack(msn, c);
            //}
            //break;
        //}
        if (c <= '9' && c >= '0')
        {
            if (ms->top != -1)
            {
                if (above != '+' && above != '-' && above != '*' && above != '/' && above != '(')
                {
                    printf("输入算式有错,请检查后重新运行此程序!");
                    return -1;
                }
            }
            while (c <= '9' && c >= '0')
            {
                e = e * 10 + c - '0';
                above = c;
                c = getchar();
            }
            PushStack(msn, (char)(e + '0'));
        }
        if (c == '+' || c == '-' || c == '*' || c == '/')
        {
            if (!(above != ')' || (above <= '9' && above >= '0')))
            {
                printf("输入算式有错,请检查后重新运行此程序!");
                return -1;
            }
            if (ms->top == -1)
                PushStack(ms, c);
            else if (PriCal(ms->data[ms->top]) >= PriCal(c))
            {
                while (PriCal(ms->data[ms->top]) >= PriCal(c))
                {
                    if (ms->data[ms->top] == '(')break;
                    num = c;
                    PopStack(ms, &num);
                    PushStack(msn, num);
                }
                PushStack(ms, c);
            }
            else PushStack(ms, c);
        }
        if (c == '(' || c == ')')
        {
            if (c == '(')
            {
                if (above != '+' &&above != '-' &&above != '*' &&above != '/'&&ms->top != -1)
                {
                    printf("输入算式有错,请检查后重新运行此程序!");
                    return -1;
                }
                PushStack(ms, c);
            }
            if (c == ')')
            {
                if (above < '0' || above > '9')
                {
                    printf("输入算式有错,请检查后重新运行此程序!");
                    return -1;
                }
                while (c != '(')
                {
                    PopStack(ms, &c);
                    if (c != '(')
                        PushStack(msn, c);
                }
            }
        }
        above = c;
        if (c == '\n')break;
        else c = getchar();
    }

注意在最后的c=getchar()前一定要加个c是否为换行符的判断,因为其它读取字符的操作可能它后面需要读取字符的时候,我们的输入已经没有字符了,又得让我们继续输入导致算式出错,同时记得把后缀表达式计算的数据范围改成

		if (ms->data[ms->top] <= '0' + 255 && ms->data[ms->top] >= '0')//原本数据范围是'0'-'9',如果要计算10以外则需要加大为'0'-'0'+255

猜你喜欢

转载自blog.csdn.net/MrBlind/article/details/77113568