c语言实现计算器

昨天的是用顺序栈实现的
今天的这个是链栈实现的
并且计算的算法也改了
不再先转换为后缀表达式再求值
一步搞定
结果导致cal()超级复杂
让我debug了半天
虽说不符合模块化设计要求
不过我对自己可以解决那么多重嵌套还是很开心的


/***************************************************************************
 *   Copyright (C) 2008 by root   *
链栈实现表达式求值
 ***************************************************************************/



#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef double ElemTypeOpnd;
typedef char ElemTypeOptr;

typedef struct opnd
{
    ElemTypeOpnd elem;
    struct opnd * next;
}Lopnd,*ListOpnd;
typedef struct optr
{
    ElemTypeOptr elem;
    struct optr * next;
}Loptr,*ListOptr;
ElemTypeOptr GetOptrTop ( ListOptr L );
ElemTypeOpnd GetOpndTop ( ListOpnd L );
void InitOpnd ( ListOpnd *L );
int IsOpndNULL ( ListOpnd L );
int PushOpnd ( ListOpnd *L,ElemTypeOpnd e );
int PopOpnd ( ListOpnd *L );
void DestoryOpnd ( ListOpnd *L );
void InitOptr ( ListOptr *L );
int IsOptrNULL ( ListOptr L );
int PushOptr ( ListOptr *L,ElemTypeOptr e );
int PopOptr ( ListOptr *L );
void DestoryOptr ( ListOptr *L );
int IsRight ( char *exp );
int ShowPower ( char a );
int In ( char e );
int Precede ( char a,char b );
double  cal ( char exp1[] )
{
    char exp[100]="";
    strncat ( exp,exp1,strlen ( exp1 ) );
    strncat ( exp,"#",1 );
    char *p=exp;
    ListOptr Optr;
    ListOpnd Opnd;
    InitOptr ( &Optr );
    InitOpnd ( &Opnd );
    PushOptr ( &Optr,'#' );
    double a,b;
    while ( *p!='/0' )
    {
        if ( !In ( *p ) )
        {
            a=strtod ( p,NULL );
            PushOpnd ( &Opnd,a );
            while ( !In ( *++p ) );
                continue;
           
        }
        else
        {
            if ( *p!='#'&&*p!='('&&*p!=')' )
            {
                if ( Precede ( *p, GetOptrTop ( Optr ) ))
                {
                    PushOptr(&Optr,*p);
                }
                else
                {
                    while (! Precede ( *p, GetOptrTop ( Optr ) ))
                    {
                        b=GetOpndTop(Opnd);
                        PopOpnd(&Opnd);
                        a=GetOpndTop(Opnd);
                        PopOpnd(&Opnd);
                        char s=GetOptrTop(Optr);
                        if(s=='+')
                        {
                            a=a+b;
                            PushOpnd(&Opnd,a);
                        }
                        if(s=='-')
                        {
                            a=a-b;
                            PushOpnd(&Opnd,a);
                        }
                        if(s=='*')
                        {
                            a=a*b;
                            PushOpnd(&Opnd,a);
                        }
                        if(s=='/')
                        {
                            a=a/b;
                            PushOpnd(&Opnd,a);
                        }
                        PopOptr(&Optr);
                    }
                    PushOptr(&Optr,*p);
                }
            }
            if(*p=='#')
            {
                while(GetOptrTop(Optr)!='#')
                {
                    char s=GetOptrTop ( Optr );
                    b=GetOpndTop ( Opnd );
                    PopOpnd ( &Opnd );
                    a=GetOpndTop ( Opnd );
                    PopOpnd ( &Opnd );
                    if ( s=='+' )
                    {
                        a=a+b;
                        PushOpnd ( &Opnd,a );
                    }
                    if ( s=='-' )
                    {
                        a=a-b;
                        PushOpnd ( &Opnd,a );
                    }
                    if ( s=='*' )
                    {
                        a=a*b;
                        PushOpnd ( &Opnd,a );
                    }
                    if ( s=='/' )
                    {
                        a=a/b;
                        PushOpnd ( &Opnd,a );
                    }
                    PopOptr ( &Optr );
                }
                PopOptr ( &Optr );
            }
            if(*p=='(')
            {
                PushOptr(&Optr,*p);
            }
            if(*p==')')
            {
                while(GetOptrTop(Optr)!='(')
                {
                    char s=GetOptrTop ( Optr );
                    b=GetOpndTop ( Opnd );
                    PopOpnd ( &Opnd );
                    a=GetOpndTop ( Opnd );
                    PopOpnd ( &Opnd );
                    if ( s=='+' )
                    {
                        a=a+b;
                        PushOpnd ( &Opnd,a );
                    }
                    if ( s=='-' )
                    {
                        a=a-b;
                        PushOpnd ( &Opnd,a );
                    }
                    if ( s=='*' )
                    {
                        a=a*b;
                        PushOpnd ( &Opnd,a );
                    }
                    if ( s=='/' )
                    {
                        a=a/b;
                        PushOpnd ( &Opnd,a );
                    }
                    PopOptr ( &Optr );
                }
                PopOptr ( &Optr );
            }
           
           

        }
        p++;
    }
    a=GetOpndTop(Opnd);
    //PopOpnd(&Opnd);
    DestoryOptr(&Optr);
    DestoryOpnd(&Opnd);
   
    return a;
}

int In ( char e )
{
    if ( e=='#'||e=='+'||e=='-'||e=='*'||e=='/'||e=='('||e==')' )
        return 1;
    return 0;
}

int Precede ( char a,char b )
{
    if ( ShowPower ( a ) >ShowPower ( b ) )
    {

        return 1;
    }
    else
        return 0;
}

int ShowPower ( char a )
{
    if ( a=='*'||a=='/' )
    {
        return 2;
    }
    if ( a=='+'||a=='-' )
    {
        return 1;
    }
    if ( a=='(' )
    {
        return 0;
    }
    if ( a=='#' )
    {
        return -1;
    }
}

int IsRight ( char *exp )
{
    ListOptr S;
    InitOptr ( &S );

    char *p=exp;
    while ( *p!='/0' )
    {
        if ( *p=='(' )
        {
            PushOptr ( &S,*p );
        }
        if ( *p==')' )
        {
            if ( IsOptrNULL ( S ) )
            {
                return 0;
            }
            else
            {
                PopOptr ( &S );
            }
        }
        p++;
    }
    if ( IsOptrNULL ( S ) )
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

void DestoryOptr ( ListOptr *L )
{
    if(IsOptrNULL(*L))
    {
        return;
    }
    ListOptr p;
    ListOptr q=*L;
    while ( *L!=NULL )
    {
        p=*L;
        free ( *L );
        *L=p->next;
    }
   
}

ElemTypeOptr GetOptrTop ( ListOptr L )
{
    if ( IsOptrNULL ( L ) )
    {
        printf ( "stack is null/n" );
        return 0;
    }
    return L->elem;
}

int PopOptr ( ListOptr *L )
{
    if ( IsOptrNULL ( *L ) )
    {
        printf ( "stack is null/n" );
        return 0;
    }
    ListOptr p=*L;
    *L=p->next;
    free ( p );
    return 1;
}

int PushOptr ( ListOptr *L,ElemTypeOptr e )
{
    ListOptr s=malloc ( sizeof ( ElemTypeOptr ) );
    s->elem=e;
    s->next=*L;
    *L=s;
    return 1;
}

int IsOptrNULL ( ListOptr L )
{
    if ( L==NULL )
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

void InitOptr ( ListOptr *L )
{
    *L=NULL;
}



void DestoryOpnd ( ListOpnd *L )
{
    if(IsOpndNULL(*L))
    {
        return ;
    }
    ListOpnd p;
    ListOpnd q=*L;
    while ( *L!=NULL )
    {
        p=*L;
        free ( *L );
        *L=p->next;
    }

}

ElemTypeOpnd GetOpndTop ( ListOpnd L )
{
    if ( IsOpndNULL ( L ) )
    {
        printf ( "stack is null/n" );
        return 0;
    }
    return L->elem;
}

int PopOpnd ( ListOpnd *L )
{
    if ( IsOpndNULL ( *L ) )
    {
        printf ( "stack is null/n" );
        return 0;
    }
    ListOpnd p=*L;
    *L=p->next;
    free ( p );
    return 1;
}

int PushOpnd ( ListOpnd *L,ElemTypeOpnd e )
{
    ListOpnd s=malloc ( sizeof ( ElemTypeOpnd ) );
    s->elem=e;
    s->next=*L;
    *L=s;
    return 1;
}

int IsOpndNULL ( ListOpnd L )
{
    if ( L==NULL )
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

void InitOpnd ( ListOpnd *L )
{
    *L=NULL;
}



int main ( int argc, char *argv[] )
{
    char a[90];
    begin:
    printf ( "输入表达式/n" );
    scanf("%s",a);
    getchar();
    if(IsRight(a))
    {
        printf ( "表达式正确/n" );
    }
    else
    {
        printf ( "表达式不正确  重新输入/n" );
        goto begin;
    }
   
    printf("所得值为 %g/n",cal(a));
   
    printf("继续 c  退出 anykey/n");
    if(toupper(getchar())=='C')
    {
        getchar();
        goto begin;
    }

    return EXIT_SUCCESS;
}
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值