您的位置:首页 > C 表达式计算器
站内搜索

表达式计算器

原帖及讨论:

http://bbs.bc-cn.net/dispbbs.asp?BoardID=5&ID=172017

为了方便了解流程,在程序中把计算过程也输出了.而且栈操作的实现部分也是自己实现的.
程序用两个栈,optr寄存运算符,opnd寄存操作数和运算结果.输入的表达式以等号结束,例如:2*(1+2)=
/**************表达式计算器************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <malloc.h>

#define STACK_SIZE 100
#define APPEND_SIZE 10

struct SNode{
    float data; /*存放操作数或者计算结果*/
    char ch; /*存放运算符*/
};

struct Stack{
    SNode *top;
    SNode *base;
    int size;
};

/*栈操作函数*/
int InitStack(Stack &S); /*创建栈*/
int DestroyStack(Stack &S); /*销毁栈*/
int ClearStack(Stack &S); /*清空栈*/
int GetTop(Stack S, SNode &e); /*取出栈顶结点并返回节点值*/
int Push(Stack &S,SNode e); /*将结点e压入栈*/
int Pop(Stack &S,SNode &e); /*删除栈顶结点并返回其节点值*/

/*表达式计算器相关函数*/
char get_precede(char s,char c); /*判断运算符s和c的优先级*/
int isOpr(char c); /*判断输入的字符是不是运算符,是则返回0,否返回1*/
float operate(float x, char opr, float y); /*计算x和y经过运算符opr计算后的结果*/
float compute(); /*表达式结算器主函数*/
char *killzero(float result); /*去掉结果后面的0*/

int InitStack(Stack &S)
{
    S.base=(SNode *)malloc(STACK_SIZE * sizeof(struct SNode));
    if(S.base==NULL)
    {
        printf("动态分配内存失败!");
        return -1;
    }
    S.top=S.base;
    S.size=STACK_SIZE;
    return 0;
}

int DestroyStack(Stack &S)
{
    free(S.base);
    return 0;
}

int ClearStack(Stack &S)
{
    S.top=S.base;
    return 0;
}

int GetTop(Stack S,SNode &e)
{
    if(S.top==S.base)
    {
        printf("栈以为空!");
        return -1;
    }
    e=*(S.top-1);
    return 0;
}

int Push(Stack &S,SNode e)
{
    if(S.top-S.base>=S.size)
    {
        S.base=(SNode *)realloc(S.base,(S.size+APPEND_SIZE)*sizeof(struct SNode));
        if(S.base==NULL)
        {
            printf("动态分配内存失败!");
            return -1;
        }
        S.top=S.base+S.size;
        S.size+=APPEND_SIZE;
    }
    *S.top=e;
    S.top++;
    return 0;
}

int Pop(Stack &S,SNode &e)
{
    if(S.top==S.base)
    {
        printf("栈为空!");
        return -1;
    }
    e=*(S.top-1);
    S.top--;
    return 0;
}

char get_precede(char s,char c)
{
    switch(s)
    {
        case '+':                
        case '-':
             if(c=='+'||c=='-')
                 return '>';
             else if(c=='*'||c=='/')
                 return '<';
             else if(c=='(')
                 return '<';
             else if(c==')')
                 return '>';
             else
                 return '>';
        case '*':
        case '/':
             if(c=='+'||c=='-')
                 return '>';
             else if(c=='*'||c=='/')
                 return '>';
             else if(c=='(')
                 return '<';
             else if(c==')')
                 return '>';
             else
                 return '>';
        case '(':
             if(c=='+'||c=='-')
                 return '<';
             else if(c=='*'||c=='/')
                 return '<';
             else if(c=='(')
                 return '<';
             else if(c==')')
                 return '=';
             else
                 return 'E';
        case ')':
             if(c=='+'||c=='-')
                 return '>';
             else if(c=='*'||c=='/')
                 return '>';
             else if(c=='(')
                 return 'E';
             else if(c==')')
                 return '>';
             else
                 return '>';
        case '#':
             if(c=='+'||c=='-')
                 return '<';
             else if(c=='*'||c=='/')
                 return '<';
             else if(c=='(')
                 return '<';
             else if(c==')')
                 return 'E';
             else
                 return '=';
        default:
             break;
    }
    return 0;    
}

int isOpr(char c)
{
    if(c=='+'||c=='-'||c=='*'||c=='/'||c=='('||c==')'||c=='=')
        return 0;
    else
        return 1;
}

float operate(float x, char opr, float y)
{
    float result;
    switch (opr)
    {
        case '+':
             result = x + y;
             break;
        case '-':
             result = x - y;
             break;
        case '*':
             result = x * y;
             break;
        case '/':
             if (y == 0)
             {
                printf("Divided by zero!/n");
                return 0;
             }
             else
             {
                 result = x / y;
                 break;
             }
       default:
             printf("Bad Input./n");
             return 0;
    }
    return result;
}    

float compute() /*计算的时候运算符栈顶结点的优先级始终最低*/
{
    Stack optr,opnd;
    struct SNode opr_in,opn_in,opr_top,opn_tmp,e,a,b,opr_t;
    char c;
    char buf[16];
    int i=0;
    
    InitStack(optr); /*用于寄存运算符*/
    InitStack(opnd); /*用于寄存操作数和计算结果*/
    memset(buf,0,sizeof(buf));
    
    printf("Enter your expression:");
        
    opr_in.ch='#';
    Push(optr,opr_in); /*'#'入栈*/
    GetTop(optr,opr_top);
    c=getchar();
    while(c!='='||opr_top.ch!='#')
    {
        if(isOpr(c)!=0) /*不是运算符则保存到buf中,以便得到操作数*/
        {
            buf[i]=c;
            i++;
            c=getchar();
        }
        else /*是运算符*/
        {
            buf[i]='/0';
            if(i) /*判断buf是否为空,不为空则取出值,压入操作数寄存器,并将buf置为空*/
            {
                 opn_in.data=(float)atof(buf);
                 Push(opnd,opn_in);
                 printf("opnd入栈:[%f]/n",opn_in.data);
                 i=0;
                 memset(buf,0,sizeof(buf));
            }
            opr_in.ch=c;
            switch(get_precede(opr_top.ch,c)) /*根据运算符优先级做相应操作*/
            {
                case '<': /*优先级小于栈顶结点,则运算符入栈*/
                     Push(optr,opr_in);
                     printf("optr入栈:[%c]/n",opr_in.ch);
                     c=getchar();
                     break;
                case '=': /*优先级等于栈顶结点,即是括号,去掉括号*/
                     Pop(optr,e);
                     printf("optr出栈:去掉括号/n");
                     c=getchar();
                     break;
                case '>': /*优先级大于栈顶结点,取操作数和运算符计算*/
                     Pop(optr,opr_t);
                     printf("optr出栈:[%c]/n",opr_t.ch);
                     if(Pop(opnd,b)<0)
                     {
                         printf("Bad Input!/n");
                         fflush(stdin);
                         return -1;
                     }
                     printf("opnd出栈:[%f]/n",b.data);
                     if(Pop(opnd,a)<0)
                     {
                         printf("Bad Input!/n");
                         fflush(stdin);
                         return -1;
                     }
                     printf("opnd出栈:[%f]/n",a.data);
                     opn_tmp.data=operate(a.data,opr_t.ch,b.data); /*计算*/
                     Push(opnd,opn_tmp); /*将计算结果压入操作数寄存器*/
                     printf("结果入栈:[%f]/n",opn_tmp.data);
                     break;
            }
        }
        GetTop(optr,opr_top); /*取出运算符寄存器栈顶结点*/                
    }
    GetTop(opnd,opn_tmp);
    DestroyStack(optr);
    DestroyStack(opnd);
    return opn_tmp.data;
}

char *killzero(char *res,float result)
{
    int i;

    sprintf(res,"%f",result);
    i=(int)strlen(res)-1;
    while(i&&res[i]=='0')
    {
        res[i]='/0';
        i--;
    }
    if(res[i]=='.')
        res[i]='/0';
    return res;
}

int main()
{
    char ch;
    char res[64];
    float result;
    while(1)
    {
        result=compute();
        printf("/nThe result is:%s/n",killzero(res,result));
        printf("Do you want to continue(y/n)?:") ;
        ch=getch();
        putchar(ch);
        if(ch=='n'||ch=='N')
            break;
        else
            system("cls");
    }
    return 0;
}

 

  • 上一篇:C语言中实现 点在多边形内 算法
  • 下一篇:C语言简单的一些简单例子