返回列表 发帖

C语言表达式计算器

为了方便了解流程,在程序中把计算过程也输出了.而且栈操作的实现部分也是自己实现的.# C. \! }+ E2 ^4 l  ~6 l; S
程序用两个栈,optr寄存运算符,opnd寄存操作数和运算结果.输入的表达式以等号结束,例如:2*(1+2)=* s1 k2 Y* W% M, P1 F+ x
/**************表达式计算器************/
. d2 ?2 R% c% K" d- s' L- Q" x! k#include <stdio.h>$ K- M, {/ X8 j! Q  v. K
#include <stdlib.h>
$ q# y( w% O( n#include <string.h>
+ x/ T( Y' T$ T% U7 U. J#include <conio.h>: u; r! `7 |9 n' W7 q0 P
#include <malloc.h>
( W8 b+ ~$ o/ q4 V/ C1 b3 X
0 U! w5 a# x* E3 X#define STACK_SIZE 1007 l1 P5 u6 K# g+ l. K6 T! _) [/ n
#define APPEND_SIZE 10" p" H7 z% }" S, Q; v, f$ z

6 `: ]8 U8 p; T5 hstruct SNode{
7 |$ ~5 m8 N9 A8 m9 A    float data; /*存放操作数或者计算结果*/4 M# L3 Q  k: w7 O  x8 r
    char ch; /*存放运算符*/
# V4 g7 X6 O% x$ q! p! ^: Z0 Q};
9 e- `# \0 K4 k4 B' m
8 x% j4 G5 t' J3 G9 @struct Stack{
0 p) u6 H2 L# b) B$ f    SNode *top;' e. g+ ^5 r7 E. g+ q* h
    SNode *base;
2 M/ f; I( q7 b% r* A; i* o$ T: c" D    int size;
3 X$ }, i; B; ^};
* M: r0 R( \: `: ]. y. o9 @4 N6 T8 B' J2 x" i' y* W8 \
/*栈操作函数*/, x- R8 ^4 i& s- m% o1 H9 t
int InitStack(Stack &S); /*创建栈*/" ]6 C* i" d) Z, M5 K9 S* B$ f4 q* e
int DestroyStack(Stack &S); /*销毁栈*/
8 ^" R. R  L9 @7 ?int ClearStack(Stack &S); /*清空栈*/
- W# \, m& ~- X/ b* G2 }% Cint GetTop(Stack S, SNode &e); /*取出栈顶结点并返回节点值*// m! {5 n$ }+ ~
int Push(Stack &S,SNode e); /*将结点e压入栈*/
" W% |& l1 w! A: C7 `5 P( {int Pop(Stack &S,SNode &e); /*删除栈顶结点并返回其节点值*/3 m1 V: K7 b+ I8 [

0 |, |# ]& U! Y) q  ?$ ^/*表达式计算器相关函数*/
, l+ \7 b1 W5 D9 t& `& Xchar get_precede(char s,char c); /*判断运算符s和c的优先级*// X$ ]2 {% O) B& L; W1 d
int isOpr(char c); /*判断输入的字符是不是运算符,是则返回0,否返回1*/$ `( m3 H- l) i. {4 I
float operate(float x, char opr, float y); /*计算x和y经过运算符opr计算后的结果*/7 G& {) o" g: P$ R6 k& J
float compute(); /*表达式结算器主函数*/
6 L$ U3 s# ^7 ~% Mchar *killzero(float result); /*去掉结果后面的0*/
7 [* T8 d0 v; L$ ^
4 O6 |6 U: _9 i* r. U3 Oint InitStack(Stack &S)
$ n' y( _" q! X! z$ q{
, K+ `6 ~) A6 C' e    S.base=(SNode *)malloc(STACK_SIZE * sizeof(struct SNode));: d" Z+ Z. a5 _! k2 _' f
    if(S.base==NULL). \# L/ H1 r/ G9 @; N/ U. R6 |/ W
    {
; ~! t2 v& {/ m+ Q        printf("动态分配内存失败!");
, x. g& w0 c9 a' d* [        return -1;
0 D7 E! m: ]: U) N9 H6 F    }1 p4 D7 q" X& G, b: a
    S.top=S.base;( X- P5 B- p" q& Q- S- e& z$ _( A
    S.size=STACK_SIZE;
. U  T$ f  X3 C% a    return 0;
. p1 Q( N: x( z6 |9 u5 `}
6 d- J0 W/ T- G+ @7 P) |
3 ^2 e) U3 O: r0 Y6 A. j0 ^" Mint DestroyStack(Stack &S)! t' a$ j/ S& p6 M1 g0 H
{
, s/ o3 j+ m% u4 |2 X    free(S.base);
  E* c" a* u) q  _    return 0;! R, V7 K4 W  I" X  H9 G7 ~
}% E  ^( N+ G5 }* W/ I( m9 Q4 s. M: x- s

" W* X% w# o- [) Jint ClearStack(Stack &S)
7 x% J! q; T) k- F- I{: Z  @5 V3 N& I/ \
    S.top=S.base;
" z* `# Q. E( v8 ^    return 0;
7 c& [2 f4 e7 F2 {}+ }( _; X. y) \+ T
& P0 q, N, U/ `/ f
int GetTop(Stack S,SNode &e)7 w8 @% o& Q7 o7 ?: W/ d
{1 L/ z) r* B# e% z
    if(S.top==S.base)6 C$ P, R7 q7 `8 ?, v3 }1 Z
    {
: u% @& d8 R2 L/ x9 S        printf("栈以为空!");. P, G$ r0 X& z7 e( y
        return -1;4 i  r- E( `2 |
    }" U' U% C; n/ }
    e=*(S.top-1);$ N" Z) N$ E& e" c, j( r
    return 0;
' w6 o% s5 v3 @) [' P8 Y3 O}8 v: N& T6 z9 ~& Q4 X2 C% @

& h8 d# \# O* Xint Push(Stack &S,SNode e)
6 o$ D$ ^8 k8 g& h) \9 ?  g{( F6 }6 j% S; U
    if(S.top-S.base>=S.size)
% T/ k. E. t' a( W5 A0 r# o    {
- p) r9 i' j& ^3 M$ d6 ?) I        S.base=(SNode *)realloc(S.base,(S.size+APPEND_SIZE)*sizeof(struct SNode));9 d' V- c) G6 J7 h0 ]( N
        if(S.base==NULL)
! k$ {8 i# S7 l% f& \        {
& j, y8 b/ W& @1 W; q2 Y! o            printf("动态分配内存失败!");
2 h( m3 V: Q  f1 t: T            return -1;4 x4 Z7 x3 u; U& L% Y3 U% q
        }
0 R' Y2 r1 t: B. |, F        S.top=S.base+S.size;
+ [6 ^: F) c' \% _        S.size+=APPEND_SIZE;
2 \: R/ F$ i8 F; `1 s! N    }
. r" S( T0 q8 {4 B7 L" r    *S.top=e;: d, D% X1 p1 M; E: J; c# ~
    S.top++;) Q  D" o( {% D6 r$ t5 y( W8 o
    return 0;; z6 U$ ^! g; r1 a) z
}
% ~1 Z0 U% ^7 }4 S, \9 J- t
4 e$ E, N& D9 e+ xint Pop(Stack &S,SNode &e)! h6 y: U- b+ K/ |$ x# V' ^7 j/ I
{
7 D) w0 m6 C" X! y    if(S.top==S.base)
0 V, d$ i! F. \4 R, ^0 C8 s    {
3 Z( }) P- g# h6 g) z  o& o6 F        printf("栈为空!");
9 q+ d& e4 B# J5 v0 I        return -1;# h( x6 x; d8 m$ V/ w2 J
    }
0 d0 I( B  [1 Z# S, j( S" U    e=*(S.top-1);
7 k, ^% r0 T9 V2 E# B" a    S.top--;$ O# b7 [7 j+ F3 b. F6 C* H8 o/ _% k
    return 0;9 R# v1 ~. u1 F* D0 M
}
# I  d& z* G6 f' A; z
* q% `$ O& J/ b- c2 Nchar get_precede(char s,char c)
) k* ^; T' k# |( s{4 d' g# s: ~# W) O/ k, G+ o
    switch(s)
( U  P6 u$ Q6 |% h    {
$ |& Z2 o  b  w& |        case '+':                   `2 A: C4 Y' C9 F( @6 H
        case '-':0 J8 x3 ?) \9 d6 z& P% M
             if(c=='+'||c=='-')
+ g5 i$ w- j8 m  W' @- r                 return '>';
+ h, |6 [' R8 B  `3 M4 E7 M: Y& p2 ^3 s             else if(c=='*'||c=='/')) K4 P  o, {# `1 ^" E, t  d
                 return '<';+ s( `% n6 u( k! b5 f( p( M) S# N
             else if(c=='(')  W) I6 y1 v* f6 Y
                 return '<';6 H) w6 J4 c; Q9 Q
             else if(c==')')
5 C. u9 C  I3 S; U% B3 J                 return '>';7 Z6 y/ ~/ l* y  X: J+ z0 E' Y) N
             else
- j8 J8 T; w6 j, f# W7 I. A- L                 return '>';8 W( e  I1 l* D- d9 P% n
        case '*':
* t' d* X& Q0 S, l, Y. \3 i        case '/':: E$ F( V8 C- A1 {9 s& q
             if(c=='+'||c=='-')
: ~2 E$ l5 A& y5 J5 f; B5 m1 L                 return '>';& Q. }- N2 ~; m6 [- }! Y
             else if(c=='*'||c=='/')
: E# j- U( A1 |2 L  \* M                 return '>';
4 m% v; G" i$ Q: D( h             else if(c=='(')$ k' T- n! M. \+ ^+ S
                 return '<';; x" e$ F9 G, S! `
             else if(c==')')
& j2 |7 {, P6 |8 e4 J' G                 return '>';' h0 t1 y! k4 G/ e) a4 g
             else" X* s  W& A: X
                 return '>';  M0 ?3 V$ {$ [# e) @
        case '(':+ }9 F& {, s! \: Q% k
             if(c=='+'||c=='-'). Q" L( S  b' i# S" I1 R, u& S
                 return '<';" s+ \! K+ v# @* c
             else if(c=='*'||c=='/')
0 q' v5 l0 x! e  g9 n                 return '<';) ]' j. O5 `8 d
             else if(c=='(')4 h% {& N2 I0 y/ T/ z
                 return '<';" f0 }9 C5 r+ @+ C: }
             else if(c==')')
3 ^' e  _8 F6 A                 return '=';
* S8 i! |' m2 {" V* Q& `9 a; W             else6 d5 B& ]+ I" W' h" H5 L
                 return 'E';! U2 ?! a5 K% I
        case ')':) `$ n; O- i! ~0 W1 ^
             if(c=='+'||c=='-')
  S- ]0 f! ]3 Y/ d, U6 o8 N- n                 return '>';
6 Q. Z+ i$ t2 b+ p' s! }! W( ?             else if(c=='*'||c=='/')
/ ?, O+ X, q2 C. Z, x- ?                 return '>';5 p' ]( A# Q6 W* H7 K1 n  ?" L' _, k
             else if(c=='(')
! S/ F* f3 A; X, W& N                 return 'E';
, o  X. \+ A3 u" U             else if(c==')')' S+ h% J- a7 n& o% M# \7 b$ k
                 return '>';, k  z- F' L$ R7 e" g; D4 P  J7 r5 j
             else/ w9 Y! v3 V! m7 S1 t( K- }
                 return '>';1 w0 h- y, A# v/ k6 D
        case '#':, I2 ?8 M4 L$ R- M. S
             if(c=='+'||c=='-')) N0 c+ c1 F8 P: [) P( ~% J$ x. I
                 return '<';" D% P- }8 k0 @- P6 W  X
             else if(c=='*'||c=='/')
) Z, A# v: \/ I. r& w; b                 return '<';: b, `  K# K) T3 ]# ~- F: f
             else if(c=='(')
3 L( K8 L# B: C$ Q                 return '<';
. |: |3 Y# p1 T" E: |  q/ F             else if(c==')')8 P: Y, |) o( o  K: m: J
                 return 'E';% @" @- S7 b% O$ s" r2 M6 _8 \
             else
) ~! D$ E: b6 y. j- o                 return '=';
* T0 [$ [$ {, B        default:3 n1 H6 z2 I+ p! N0 m
             break;
% N; f: w4 i5 V    }
3 V4 c9 a  E* {6 x8 b# }    return 0;   
5 ~& A7 f4 J8 ^5 o, I$ I- m+ |) a$ t/ s}9 A4 }  T  T+ c% I7 Q

' U, R1 a- N7 n; J5 w; tint isOpr(char c)
% k3 v0 Q, W. I" i% s; f{
: H) s6 Z( g7 j' H: X    if(c=='+'||c=='-'||c=='*'||c=='/'||c=='('||c==')'||c=='=')
9 w% V4 G* n/ q0 S        return 0;
% b; U+ a# }6 n) U3 A    else ( N$ f  W" }9 R
        return 1;: l4 f$ W# Q0 e5 P' o
}6 B8 A$ |4 f! m& s7 a, w

4 A: b! D( p9 q: Yfloat operate(float x, char opr, float y)3 k& Y* s, e' P
{
7 n2 h9 j+ q8 ~) X    float result;
; P2 Z+ P4 S! s- ^2 b' ]( Y    switch (opr)1 t; U6 R4 {/ g0 V7 F8 u8 _0 w
    {0 o. U3 K1 F# q9 w
        case '+': ' K# k7 N1 @  X) j5 z" ]( e7 y' Y
             result = x + y;6 ^0 p: L% y; s7 h$ x: E
             break;
  Z  E; M  D/ {/ O! T( Q        case '-': $ z* U+ S4 e3 o* v  U6 W  H  E
             result = x - y;- T) A4 ^& X7 a' s
             break;5 x& P# {; g* W
        case '*': ; h& E: c$ _% y
             result = x * y;# W: R7 d( k* s5 k
             break;( ~7 \; J  c, q9 R8 r. H- {
        case '/':
3 ~" P' P. s& ^6 K             if (y == 0); ?% s  @7 ?7 @
             {! {( v# {/ j! V# `$ D8 }
                printf("Divided by zero!\n");
" W: o$ Q: ~/ o! K2 E/ W                return 0;7 v: G$ X2 f( ]- R+ u- X
             }0 A. H: H1 j% J. G& X
             else
% q* Q, Y1 I/ Z             {
$ z9 Y, d+ W& B7 a( }4 S7 T) _                 result = x / y;
, Z% i* _0 j7 n% [& u                 break;  e# d7 t& Z' @& |5 P- X" [5 i
             }
- G/ x: l! J  u/ g  L* \  c3 o, r7 W       default:
& T# E( c0 R* r9 ^5 a             printf("Bad Input.\n"); ' y9 ^: X; S4 w" k5 K& L+ a
             return 0;$ R" V: P" c! |' d
    }
2 j  ^- _  Q' o& M    return result;
4 Q. b# v' ?& \; L}   
. B% M0 ^& l: J) |0 }* }9 F, a/ Z- e+ o) w9 N3 G; M
float compute() /*计算的时候运算符栈顶结点的优先级始终最低*/$ ]! _; P1 d6 a4 k
{: _, E5 p% q/ y3 U
    Stack optr,opnd;# l+ l% w0 D) I  f. w
    struct SNode opr_in,opn_in,opr_top,opn_tmp,e,a,b,opr_t;: B: g, L0 q6 r3 G' C
    char c;
- H9 H3 F+ D3 N$ u9 T7 b    char buf[16];  R' C  r, `$ t% ^/ R
    int i=0;! m, |+ p2 a1 R6 `! w5 d3 V
    5 d( l8 W2 U, w3 ?: O. [, i" \
    InitStack(optr); /*用于寄存运算符*// o9 Y6 T! _& B; B2 L& S; g
    InitStack(opnd); /*用于寄存操作数和计算结果*/2 f1 x7 c/ q: d
    memset(buf,0,sizeof(buf));+ u# X6 l$ ?- }  m, s* A( c4 i
    ' v+ E8 D6 n# \. M7 a4 O3 V* Y9 M+ i
    printf("Enter your expression:");! e+ b: g* y; c; D% r$ J& V
        9 g2 x. N3 k, i: l( a1 W
    opr_in.ch='#';! T( U; ?- r) v2 I  t. k* W7 f4 @
    Push(optr,opr_in); /*'#'入栈*/, A* A2 x, r! [! {: k2 W8 V- \
    GetTop(optr,opr_top);
7 K; C1 v' \7 `0 z# K- v+ h    c=getchar();3 b% p/ C7 C$ P
    while(c!='='||opr_top.ch!='#')- `( L+ D" R7 j5 ^+ r
    {0 q0 v0 |! v! e7 B+ E6 P! a
        if(isOpr(c)!=0) /*不是运算符则保存到buf中,以便得到操作数*/
) w4 ?8 @$ U0 e3 Z! o, O- f6 ^3 A        {: e, J2 ]% m3 \4 J
            buf=c;
# j' [- [$ g# K            i++;$ }9 G& M/ C+ K; A
            c=getchar();
; _7 R# `+ t8 N8 ~! g; s, G        }& t  b9 I0 T1 O- t
        else /*是运算符*/- p/ S1 X% z$ `2 P5 }3 c
        {1 \! a" ?& m- B8 B: P9 h+ W
            buf='\0';
8 x' H5 V; y9 V; R7 T2 Y1 w            if(i) /*判断buf是否为空,不为空则取出值,压入操作数寄存器,并将buf置为空*/
8 y; e/ H' p: e" i+ j1 x" M$ I2 s, a            {8 o$ \3 b( g; J1 L. ~
                 opn_in.data=(float)atof(buf);3 G! l3 O# Y$ }9 a' J
                 Push(opnd,opn_in);+ L# H2 \; m- y0 ~+ H& g
                 printf("opnd入栈:[%f]\n",opn_in.data);
) B/ U$ }8 m  Q. J: d& S                 i=0;
2 W0 ?* _; d0 r. a  U, j0 L/ e" T                 memset(buf,0,sizeof(buf));
+ J3 V8 T& ^1 W            }
+ m  ]6 p  Z6 L  E! [' O6 o            opr_in.ch=c;
5 d) X- a) t! ?" i5 E8 F; P            switch(get_precede(opr_top.ch,c)) /*根据运算符优先级做相应操作*/
$ U( w$ Z' n# i8 a+ T& T$ B2 C            {
9 {& k+ Q6 Y5 J                case '<': /*优先级小于栈顶结点,则运算符入栈*/
8 `0 v- g- @7 i3 V4 {0 K0 `                     Push(optr,opr_in);
- s, y( K" Z  H) H                     printf("optr入栈:[%c]\n",opr_in.ch);
8 @) x1 V) v( J. i6 d8 N9 `                     c=getchar();
7 _5 y' w3 k7 z                     break;, K. n/ f# g* |8 ~6 F2 D7 Q0 `
                case '=': /*优先级等于栈顶结点,即是括号,去掉括号*/
! l- X  k% _: i/ y% G" q" w                     Pop(optr,e);
1 q7 {( m. ^8 Z) J1 E" A) d6 C                     printf("optr出栈:去掉括号\n");
) p5 s6 }3 `+ \3 ]6 J/ P( v                     c=getchar();; E! h& t1 B' s" i
                     break;
$ i( \; L. F. e9 E                case '>': /*优先级大于栈顶结点,取操作数和运算符计算*/# U7 o2 ^2 ?0 P1 b
                     Pop(optr,opr_t);
5 T6 C. _4 j$ X9 g- r                     printf("optr出栈:[%c]\n",opr_t.ch);
! D& q  C" O- F4 m- M* e; X; G% l                     if(Pop(opnd,b)<0)/ Q7 f! T" |( Q
                     {! G0 x7 G/ X: j2 d( Z- B5 h
                         printf("Bad Input!\n");' M0 X8 Y9 u! d. l+ c. B- x3 ]
                         fflush(stdin);$ Q7 Q3 q) y8 F) N# t. H' }
                         return -1;
/ {7 t% h  ]% @1 O, ]' @! }' {0 ^                     }$ U. Y, U0 K" _; Q& K* Q* N5 r
                     printf("opnd出栈:[%f]\n",b.data);, c1 ]/ g9 W  v- T5 K9 M! u
                     if(Pop(opnd,a)<0)* f8 D% }4 Y5 c, T5 W
                     {. u* O- K5 S  f) e3 d
                         printf("Bad Input!\n");
! F. J, q6 t9 N4 [& O2 A                         fflush(stdin);- a+ w) |8 P# I2 N% q
                         return -1;
8 L" Z* }( ?  C/ A) A  A0 W* @7 s                     }
1 s$ L8 W5 M5 r' R$ r                     printf("opnd出栈:[%f]\n",a.data);3 r) q( ]. k( X+ s
                     opn_tmp.data=operate(a.data,opr_t.ch,b.data); /*计算*/! e# {( q8 c! ]# ~- ?
                     Push(opnd,opn_tmp); /*将计算结果压入操作数寄存器*/
2 Q3 L" A0 N# }. o                     printf("结果入栈:[%f]\n",opn_tmp.data);2 U0 u# I/ A# r/ V& \# ~
                     break;
  D5 k* T% S% H6 M; K# i) L            }
5 E( H, H; V: G6 }        }1 B7 T7 _7 R+ t  L* m: g" x; y
        GetTop(optr,opr_top); /*取出运算符寄存器栈顶结点*/                % T2 d( r. ^  ?! `9 U# l6 N7 ~
    }! F( |  i0 U) t: d- l
    GetTop(opnd,opn_tmp);
& v2 U! o* z- `9 A7 ~! A! B    DestroyStack(optr);% {5 l/ L' i) t+ r* Z5 _/ X# z, A
    DestroyStack(opnd);
4 D; u, t" w' g: a# I    return opn_tmp.data;
8 Z, |5 [, v3 O! O: i* u8 V/ q  s}# Q1 f5 t3 n' ^# _8 E' q/ ]1 N" _
, S  V' [- e  v8 e
char *killzero(char *res,float result)
+ p  {5 a/ |! L5 ~4 b! Q{
0 n$ f5 g5 b2 J* _& K& P* F, b    int i;- g  s7 Z) q. X& h2 g4 m

& l; }& Z' V# ?2 D    sprintf(res,"%f",result);
. \; a7 h) Y& r' L4 v    i=(int)strlen(res)-1;- U5 f3 l  {9 G7 ^, V0 b  e
    while(i&&res=='0')) k4 s) t( f, o+ x- B' o
    {
. K9 d* y, [1 z# v5 [# A% C        res='\0';; L* L# v) X' c
        i--;
8 @6 A2 m' I3 Q* `! R' O    }( R% e$ B- h, P
    if(res=='.')- m5 G# p1 Q8 a/ |' V
        res='\0';- {1 m, \- ]0 j+ k6 Q  F: j
    return res;  T2 l4 [! l$ ]7 K8 N. B
}
0 z: N8 R. D% ]8 C9 P6 Z* b1 D" [  i" z, F9 T1 f" }& l
int main()) ~1 v7 [+ j0 T6 j! U/ i' R
{: e- I, n! K: \& w3 T$ {( Y
    char ch;5 S9 E6 {8 `2 @, w4 U7 Z
    char res[64];
$ j( }2 Z1 s) ]; f* |    float result;) c1 x( F% C8 C. ^7 L! K
    while(1)
5 H7 j" u1 L2 V6 a: L    {
) j% J' H8 v' j& a        result=compute();
9 K$ I* e+ F1 Y7 V4 {6 J# Z        printf("\nThe result is:%s\n",killzero(res,result));
  B! J$ F; U" Y$ k4 V- |        printf("Do you want to continue(y/n)?:") ;
3 d" k$ U7 f* {/ V        ch=getch();
5 e; `/ ~/ u( s% }  c0 Z        putchar(ch);
+ C1 ]+ t. @( ^2 E9 ~        if(ch=='n'||ch=='N')
# `$ y8 A% f/ a$ U            break;
( [' F' S- O% p7 t9 u& [        else' u, u& t; a6 h/ E! ^8 O. Y
            system("cls");
4 {. T/ n# q7 U* D9 N- V    }9 Q+ Z2 F3 C2 J7 l9 B& O
    return 0;8 Z% [8 R7 H9 v# L4 E
}
5 T) v1 m' x; {7 D  @+ y, K

6 h9 S! ]% e7 u2 k[ 本帖最后由 zw2004 于 2008-1-21 17:21 编辑 ]

返回列表
【捌玖网络】已经运行: