【c语言小项目】简单计算器

应用栈实现表达式求值,具体思路如下:

  • 创建两个栈,一个用来存数字,一个用来存符号。起始,数字栈为空,符号栈底先存一个’\n’用来标记开始,用输入的’\n’标记结尾。

  • 开始处理输入的字符,当字符是运算符号时,根据运算符的优先关系:如果当前符号优先关系大于栈顶符号,入栈;如果小于,则拿出栈顶符号,再从数字栈拿出两个数字进行运算,将结果放在数字栈里;如果等于,说明是两个括号相遇,此时括号内的运算已经完成,将括号脱栈。

  • 遇到用户输入的回车符结束运算,并从数字栈里拿出运算结果。

代码如下:

#include
#include
#define STACKMAX 100
#define STACKADD 10


/**********************************符号栈****************************/
typedef struct StackChar
{
    char *base;
    char *top;
    int stacksize;
}SC;

void InitStackSC(SC *S)
{
    S->base = (char*)malloc(STACKMAX*sizeof(char));
    S->top = S->base;
    S->stacksize = STACKMAX;
}

void PushSC(SC *S,char e)
{
    if(S->top - S->base >= S->stacksize)
    {
        S->base = (char*)realloc(S->base,(S->stacksize+STACKADD)*sizeof(char));
        if(!S->base)
            return;
        S->top = S->base + S->stacksize;
        S->stacksize += STACKADD;
    }
    *S->top++ = e;
}
int StackEmptySC(SC* S)
{
    if(S->base == S->top)
        return 1;
    return 0;
}
void PopSC(SC *S,char *e)
{
    *e = *--S->top;
}

char GetTopSC(SC *S)
{
    if(StackEmptySC(S))
        return 0;
    return *(S->top-1);
}

/**************************************数字栈******************/
typedef struct StackData
{
    double *base;
    double *top;
    int stacksize;
}SD;

void InitStackSD(SD *S)
{
    S->base = (double*)malloc(STACKMAX*sizeof(double));
    S->top = S->base;
    S->stacksize = STACKMAX;
}
int StackEmptySD(SD* S)
{
    if(S->base == S->top)
        return 1;
    return 0;
}
void PushSD(SD *S,double e)
{
    if(S->top - S->base >= S->stacksize)
    {
        S->base = (double*)realloc(S->base,(S->stacksize+STACKADD)*sizeof(double));
        if(!S->base)
            return;
        S->top = S->base + S->stacksize;
        S->stacksize += STACKADD;
    }
    *S->top++ = e;
}

void PopSD(SD *S,double *e)
{
    *e = *--S->top;
}

double GetTopSD(SD *S)
{
    if(StackEmptySD(S))
        return 0;
    return *(S->top-1);
}

/*******************************************/
char Precede(char x,char y)//判断操两个操作符优先度
{
    int i,j;
    char ch[7] = {'+','-','*','/','(',')','\n'};
    char cmp[7][7] = {
        //+  -    *  /   (   )    \n
        {'>','>','<','<','<','>','>',},// +
        {'>','>','<','<','<','>','>',},// -
        {'>','>','>','>','<','>','>',},// *
        {'>','>','>','>','<','>','>',},// /
        {'<','<','<','<','<','=',' ',},// (
        {'>','>','>','>',' ','>','>',},// )
        {'<','<','<','<','<',' ','=',},// \n        
    };
    for(i=0; i<7; i++)
    {
        if(ch[i] == x) break;
    }
    for(j=0; j<7; j++)
    {
        if(ch[j] == y) break;
    }
    return cmp[i][j];
}

double Operate(double a,char op,double b)//计算函数
{
    switch(op)
    {
    case'+':
        return a+b;
        break;
    case'-':
        return a-b;
        break;
    case'*':
        return a*b;
        break;
    case'/':
        return a/b;
        break;
    default:
        return 0;
    }
}

int In(char c)//检查是否为符号,是返回1,否则返回0
{
    if(c=='+' || c=='-' || c=='*' || c=='/' || c=='(' || c==')' || c=='\n')
        return 1;
    return 0;
}
double EvaluateExpression()
{
    SC C;//运算符
    SD D;//操作数
    SD *OPND = &D;
    SC *OPTR = &C;
    double a,b;
    char c,oper,tmp;
    InitStackSC(OPTR);//运算符
    PushSC(OPTR,'\n');
    InitStackSD(OPND);//操作数
    c = getchar();
    while(c!='\n' || GetTopSC(OPTR)!='\n')
    {
        if(!In(c))//不是运算符,进栈
        {
            c -= '0';//将字符转化为数字
            PushSD(OPND,c);
            c = getchar();
        }
        else
        {
            switch(Precede(GetTopSC(OPTR),c))
            {
            case'>'://栈顶元素优先权大,退栈并将运算结果入栈
                PopSC(OPTR,&oper);
                PopSD(OPND,&b);
                PopSD(OPND,&a);
                PushSD(OPND,Operate(a,oper,b));
                break;
            case'='://脱括号并且接受下一个字符
                PopSC(OPTR,&tmp);
                c = getchar();
                break;
            case'<'://入符号栈并接收下一个字符
                PushSC(OPTR,c);
                c = getchar();
                break;
            }
        }
    }
    return GetTopSD(OPND);
}

int main()
{
    printf("%0.2lf\n",EvaluateExpression());
    return 0;
}

测试结果:
【c语言小项目】简单计算器_第1张图片

此程序没有检测输入,如果多出空格或者乱输会得到错误答案,添加一个函数检测c即可,留坑,日后来填。

你可能感兴趣的:(c语言学习)