逆波兰计算器改进版

前面有写过逆波兰计算器,那时候只能进行个位数计算,现在采用分隔符的办法实现多位数即小数的计算,即在每个数字或者运算符或括号之后加上空格,来确定这个数是否输入结束。逆波兰式保存在一个数组里,然后按照逆波兰计算规则就可以了,注意要使用atof转换。下面是代码部分。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define CAPACITY 50
typedef struct stack
{
    int top;
    char arr[CAPACITY];
}*pStack,stack;
pStack initStack1()
{
    pStack st = (pStack)malloc(sizeof(stack));
    st->top = 0;
    return st;
}
int stackEmpty1(pStack st)
{
    return(st->top <= 0);
}
int stackFull1(pStack st)
{
    return(st->top >= CAPACITY);
}
int pushStack1(pStack st, char a)
{
    if(stackFull1(st))
        {
            printf("栈满!\n");
            return 0;
        }
    else
        {
            st->arr[st->top++] = a;
            return 1;
        }
}
char popStack1(pStack st)
{
    char a;
    if(stackEmpty1(st))
    {
        printf("栈空!\n");
        return 0;
    }
    else
    {
        a = st->arr[--st->top];
        return a;
    }
}
char getTop1(pStack st)
{
    if(!stackEmpty1(st))
        return st->arr[st->top-1];
    else
        printf("Empty stack");
    return 0;
}
typedef struct
{
    int top;
    float data[CAPACITY];
}*dataStack;
dataStack initStack2()
{
    dataStack st = (dataStack)malloc(sizeof(dataStack));
    st->top = 0;
    return st;
}
int stackEmpty2(dataStack st)
{
    return(st->top <= 0);
}
int stackFull2(dataStack st)
{
    return(st->top >= CAPACITY);
}
int pushStack2(dataStack st, double data)
{
    if(stackFull2(st))
        {
            printf("栈满!\n");
            return 0;
        }
    else
        {
            st->data[st->top++] = data;
            return 1;
        }
}
double popStack2(dataStack st)
{
    double data;
    if(stackEmpty2(st))
    {
        printf("栈空!\n");
        return 0;
    }
    else
    {
        data = st->data[--st->top];
        return data;
    }
}
double getTop2(dataStack st)
{
    if(!stackEmpty2(st))
        return st->data[st->top-1];
    else
        printf("Empty stack");
    return 0;
}
int priority(char op)
{
    switch(op)
    {
    case '*':
    case '/':return 2;
    case '+':
    case '-':return 1;
    default: return 0;
    }
}
int main(void)
{
    int p = 0;
    int i = 0;
    int  m;
    double result, tmp1, tmp2;
    char ch, temp;
    char infix[CAPACITY] = "\0";
    char output[CAPACITY];
 
    pStack st = initStack1();
    dataStack st2 = initStack2();
	printf("请输入中缀表达式:");
	scanf("%s", &infix);
    
    for(ch = infix[p];ch !='\0';ch = infix[++p])
    {
        switch(ch)
        {
        case '(':pushStack1(st,ch);break;
        case ')':
            {
				
                while(getTop1(st) != '(')
                    {
						output[i++] = ' ';
                        output[i++] = getTop1(st);
                        popStack1(st);
                    }
                popStack1(st);
                break;
            }
        case '+':
        case '-':
        case '*':
        case '/':
            {
				output[i++] = ' ';
                while(!stackEmpty1(st))
                    {
                        temp = getTop1(st);
                        if(priority(temp) >= priority(ch))
                        {
                            output[i++] = temp;
							output[i++] = ' ';
                            popStack1(st);
                        }
                        else
                        {
                            break;
                        }
                    }
                pushStack1(st, ch);
                break;
            }
        default:output[i++] = ch;
        }
    }
    while(!stackEmpty1(st))
    {
		output[i++] = ' ';
        temp = popStack1(st);
        output[i++] = temp;
        if(temp == '(')
        {
            printf("表达式有误!");
            exit(EXIT_FAILURE);
        }	
    }
    output[i] = '\0';
    free(st);
    printf("    后缀表达式为:");
    for(m = 0; m <= i; m++)
	printf("%c", output[m]);
    printf("\n");
    double num = 0;
    char *pt = output;
    while(*pt != '\0')
    {
	while(*pt >= '0' && *pt <= '9')
	{
	    num = 10*num + (*pt - '0');
	    pt++;
	}
	if(*pt == '.')
	{
	    pt++;
	}
	float pow = 1.0;
	while(*pt >= '0' && *pt <= '9')
	{
	    pow /= 10;
	    num = num + (*pt - '0')*pow;
	    pt++;
	}
	if(*pt == ' ')
	{
	    if(*(pt-1) >= '0' && *(pt-1) <= '9')
	    {
		pushStack2(st2, num);
		num = 0;
	    }
	    pt++;
	}
	if(priority(*pt) > 0)
	{
	    switch(*pt++)
	    {
		case'+':tmp1 = popStack2(st2);tmp2 = popStack2(st2);result = tmp1 + tmp2;pushStack2(st2, result);break;
		case'-':tmp1 = popStack2(st2);tmp2 = popStack2(st2);result = tmp2 - tmp1;pushStack2(st2, result);break;
		case'*':tmp1 = popStack2(st2);tmp2 = popStack2(st2);result = tmp2 * tmp1;pushStack2(st2, result);break;
		case'/':tmp1 = popStack2(st2);tmp2 = popStack2(st2);result = tmp2 / tmp1;pushStack2(st2, result);break;
		default:break;
	    }
	}
    }
    printf("      计算结果为: %f\n", getTop2(st2));

    return 0;
}
这个问题从当初的几乎判定为不能进行多位数的运算,到能表达出有多位数的逆波兰表达式,到能实现多位数的计算,一点一点逼近目标。有时候困难并不是想象的那样不可逾越,把复杂的问题细分成很多小步,逐个击破,这是我编写这个程序得到的收获,也是适用于其他学习的学习方法。


你可能感兴趣的:(逆波兰计算器改进版)