昨天的是用顺序栈实现的
今天的这个是链栈实现的
并且计算的算法也改了
不再先转换为后缀表达式再求值
一步搞定
结果导致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;
}
今天的这个是链栈实现的
并且计算的算法也改了
不再先转换为后缀表达式再求值
一步搞定
结果导致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;
}