Using Stack to Implement Inverse Polish Calculator

The following uses the stack to implement an inverse Polish calculator, convert the infix expression entered by the user into a suffix expression, and then calculate the result.
Two chain stacks are used, and the elements in one stack are character types, used to process the data input by the user, converted into suffix expressions, stored in a character array, and then used another stack, the elements in the stack are integer Type, use the stack to process the suffix expression and then output.
PS. Only integer operations can be performed. If you are dealing with decimals, you need to change the element type in the stack that handles the suffix expression to float or double, and you need to process the decimal point.

Algorithm steps:
step1: Convert infix expression to suffix expression
Read each object in infix expression from beginning to end :, process each object:
1. Operand: direct output
2. Left parenthesis: in Stack
3. Right parenthesis: Pop the operator at the top of the stack and output it until the left parenthesis is encountered (out of stack, not output)
4. Operator: (priority: brackets> multiplication and division> addition and subtraction)
if the priority is greater than the stack The top operator is put on the stack.
If the priority is less than or equal to the top operator, the top operator is popped and output, and then the new top operator is compared until the operator is greater than the priority of the top operator. The operator is pushed onto the stack (in short, if it reads the plus and minus signs, it pops until the stack is empty or pops out is the left parenthesis, and then the plus and minus signs are pushed onto the stack; if it reads the multiply and divide symbols, it goes directly on the stack)
5. Object After the processing is complete, all the operators in the stack output
step2: calculate the suffix expression
1. Traverse each number and symbol of the infix expression from left to right
2. If it is a number, it is pushed into the stack
3. If it is a symbol, it is placed on the stack pop the top two numbers, calculates
4. the calculation result Stack
5 until the final results and final results of the stack

code show as below:

#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include<windows.h>

#define STACK_H_INCLUDED
#define DATASIZE 50//存放后缀表达式的数组长度
#define MAXBUFFER 10//最大缓冲区大小 

typedef char ElemType;
typedef int elemtype;

typedef enum Status 
{
    error, 
	success
} Status;

typedef struct StackNode
{
	ElemType data;
	struct StackNode *next;
}StackNode, *LinkStackPtr;

typedef struct LinkStack
{
	LinkStackPtr top;
	int	count;
}LinkStack;

typedef struct stacknode
{
	elemtype data;
	struct stacknode *next;
}stacknode, *linkstackptr;

typedef struct linkstack
{
	linkstackptr top;
	int	count;
}linkstack;

//函数的声明(链栈)
//栈内元素为字符型,用于处理输入的数据 
Status initLStack(LinkStack *s);//初始化栈
Status notEmptyLStack(LinkStack *s);//判断栈是否为空
void Push(LinkStack *s,ElemType data);//入栈
void Pop(LinkStack *s,ElemType *data);//出栈
//栈内元素为整型,用于处理输出的数据 
Status initlstack(linkstack *s);//初始化栈
void push(linkstack *s,elemtype data);//入栈
void pop(linkstack *s,elemtype *data);//出栈

//下面是字符型链栈基本操作的函数 
Status initLStack(LinkStack *s)
{
    s->top = NULL;
    s->count = 0;
    return success;
}

Status notEmptyLStack(LinkStack *s)
{
    if(s->top != NULL)//非空返回1
    {
        return success;
    }
    else
    {
        return error;
    }
}

void Push(LinkStack *s,ElemType data)
{
    LinkStackPtr new = (LinkStackPtr)malloc(sizeof(StackNode));
    if(new == NULL)
    {
        printf("内存分配失败\n");
        system("pause");
        exit(0);
    }
    new->data = data;
    new->next = s->top;
    s->top = new;
    s->count++;
}
 
void Pop(LinkStack *s,ElemType *data)
{
    if(s->top == NULL)
    {
        printf("栈空\n");
        system("pause");
        exit(0);
    }
    else
    {
        LinkStackPtr temp;
        *data = s->top->data;
        temp = s->top;
        s->top = s->top->next;
        free(temp);
        s->count--;
    }
}

//下面是整型链栈基本操作的函数
Status initlstack(linkstack *s)
{
    s->top = NULL;
    s->count = 0;
    return success;
}

void push(linkstack *s,elemtype data)
{
    linkstackptr new = (linkstackptr)malloc(sizeof(stacknode));
    if(new == NULL)
    {
        printf("内存分配失败\n");
        system("pause");
        exit(0);
    }
    new->data = data;
    new->next = s->top;
    s->top = new;
    s->count++;
}

void pop(linkstack *s,elemtype *data)
{
    if(s->top == NULL)//栈空,对应错误:如用户输入:1+= 
    {
        printf("\n出错:输入格式错误!\n");
        printf("请切换成英文,匹配好括号或者不要输入空格等等\n");
        system("pause");
        exit(0);
    }
    else
    {
        linkstackptr temp;
        *data = s->top->data;
        temp = s->top;
        s->top = s->top->next;
        free(temp);
        s->count--;
    }
}

int main(void)
{
    //共用变量
    int i = 0;//数组下标
    //中缀表达式转换后缀表达式的变量
    LinkStack s;
    char c, d;//处理输入的数据
    char data[DATASIZE];//存放后缀表达式
    //计算后缀表达式的变量
    linkstack s1;
    char str[MAXBUFFER];//缓冲区,用于处理连续的数字
    elemtype n1, n2;//处理输出的数据
    int n = 0;//缓冲区内计数器

    //初始化两个栈
    if(!initLStack(&s))
    {
        printf("初始化失败\n");
        system("pause");
        return -1;
    }
    if(!initlstack(&s1))
    {
        printf("初始化失败\n");
        system("pause");
        return -1;
    }

    //下面将中缀表达式转换为后缀表达式储存在数组data中
    printf("请输入中缀表达式,以=作为结束标志(只能进行整数运算):");
    scanf("%c", &c);
    while( c != '=' )//一直接收用户输入,直到读取到=为止
    {
        while(c>='0' && c<='9')//整数直接存入数组
        {
            data[i] = c;
            i++;
            scanf("%c", &c);
            if(c<'0' || c>'9')//处理连续的数字
            {
                data[i] = ' ';
                i++;
            }
        }

        if(c == ')')
        {
            Pop(&s, &d);//出栈
            while(d != '(')//不是左括号就存入数组
            {
                data[i] = d;
                i++;
                Pop(&s, &d);
            }
        }
        else if(c == '+' || c == '-')
        {
            if(!notEmptyLStack(&s))//栈空即入栈
            {
                Push(&s, c);
            }
            else//栈非空则比较栈顶元素
            {
                do
                {
                    Pop(&s, &d);
                    if(d == '(')
                    {
                        Push(&s, d);
                    }
                    else//不是左括号就存入数组
                    {
                        data[i] = d;
                        i++;
                    }
                }while(notEmptyLStack(&s) && d != '(');
                //直到栈空或者读取到左括号
                Push(&s, c);//然后再入栈
            }
        }
        else if(c == '(' || c == '*' || c == '/')
        {
            Push(&s, c);
        }
        else if(c == '=')
        {
            break;
        }
        else
        {
            printf("\n出错:输入格式错误!\n");
            printf("请切换成英文,匹配好括号或者不要输入空格等等\n");
            system("pause");
            return -1;
        }

        scanf("%c", &c);
    }
    
    //检查如果=前无运算符,eg:1=
    if(!notEmptyLStack(&s))
    {
	    printf("\n出错:输入格式错误!\n");
	    printf("请切换成英文,匹配好括号或者不要输入空格等等\n");
	    system("pause");
    	return -1;
	}

    while(notEmptyLStack(&s))//将栈内剩余对象存放到数组
    {
        
        Pop(&s, &data[i]);
        i++;
        data[i] = '=';
		data[i+1] = '\0';//字符串结束标志
    }    

    printf("\n后缀表达式:\n");
    printf("%s\n", data);
    
    //下面计算后缀表达式
    for(i = 0; data[i] != '\0'; i++)
    {
    	//下面对数字进行处理
        while(isdigit(data[i]))
        {
            str[n++] = data[i];
            str[n] = '\0';//字符串结束
            if(n >= MAXBUFFER)
            {
                printf("输入的单个数据过大\n");
                system("pause");
                return -1;
            }
            i++;
            if(data[i] == ' ')//读取到空格时对前面的所有数字进行处理
            {
                n1 = atoi(str);//将字符串转换成整型数据
                push(&s1, n1);
                n = 0;//计数器重新初始化
                break;
            }
        }
        switch(data[i])//过滤掉数字后对剩下的符号进行选择
        {
            case '+':
            {
                pop(&s1, &n1);
                pop(&s1, &n2);
                push(&s1, n1 + n2);
                break;
            }
            case '-':
            {
                pop(&s1, &n1);
                pop(&s1, &n2);
                push(&s1, n2 - n1);
                break;
            }
            case '*':
            {
                pop(&s1, &n1);
                pop(&s1, &n2);
                push(&s1, n1 * n2);
                break;
            }
            case '/':
            {
                pop(&s1, &n1);
                pop(&s1, &n2);
                if(n1 != 0)
                push(&s1, n2 / n1);
                else
                {
                    printf("\n出错:除数不能为零\n");
                    system("pause");
                    return -1;
                }
                break;
            }
        }
    }
    pop(&s1, &n1);
    printf("\n计算结果为:%d\n\n", n1);
   
    system("pause");
    
    return 0;
}
Published 8 original articles · praised 7 · visits 346

Guess you like

Origin blog.csdn.net/weixin_45824303/article/details/105338950