二叉樹計算包含函數的中綴表達式

        二叉樹計算中綴表達式,支持科學計數法,支持前導正負號,支持指數運算符“^”,支持括號,支持函數,具有錯誤檢查。以字符串形式輸入。

 

#include <stdio.h>
#include <conio.h>
#include <math.h>
#include <ctype.h>
#include <float.h>
#include <signal.h>
#include <string.h>
#include <stdlib.h>
#ifdef _WIN32
   #include <windows.h>
   #include <malloc.h>
#else
   #include <alloc.h>
#endif

#ifndef STRICT
   #define STRICT 1
#endif

/* 判斷雙精度double變量是否溢出的宏,參數x爲雙精度變量 */
#define inf_double(x) (((*((unsigned long *)&(x)) == 0) && (*((unsigned long *)&(x) + 1) == 0x7ff00000)) ? 1 : 0)
/* 判斷雙精度double變量是否是未定義結果的宏,參數x爲雙精度變量 */
#define ind_double(x) (((*((unsigned long *)&(x)) == 0) && (*((unsigned long *)&(x) + 1) == 0xfff80000)) ? 1 : 0)
/* 判斷單精度float變量是否溢出的宏,參數x爲單精度變量 */
#define inf_float(x) ((*((unsigned long *)&(x)) == 0x7f800000) ? 1 : 0)
/* 判斷單精度float變量是否是未定義結果的宏,參數x爲單精度變量 */
#define ind_float(x) ((*((unsigned long *)&(x)) == 0xffc00000) ? 1 : 0)
#define filldoublewithinf(x) (*((unsigned long *)&(x)) = 0x0, *(((unsigned long *)&(x) + 1)) = 0x7ff00000)
#define filldoublewithind(x) (*((unsigned long *)&(x)) = 0x0, *(((unsigned long *)&(x) + 1)) = 0xfff80000)

#ifdef _WIN32
   #define checkdouble_(x) ((!_finite(x)) || (_isnan(x)))
#else
   #define checkdouble_(x) (inf_double(x) || ind_double(x))
#endif
#define checkdouble(x)  if (checkdouble_(x)) return 0
#define inf_double_return(x)  if (checkdouble_(x)) return(x)
#define checkdoublereturn(x)  if (checkdouble_(x)) return 0; else return 1

#define lchild2 lchild->lchild
#define lchild3 lchild2->lchild
#define rchild2 rchild->rchild
#define rchild3 rchild2->rchild
#define next2   next->next
#define next3   next2->next

#define E     2.7182818284590452353602874713526624977572
#define PI    3.1415926535897932384626433832795028841971
#define PI_2  1.5707963267948966192313216916397514420985
#define SQRT2 1.4142135623730950488016887242096980785696

#define SIGNMARK     0x80
#define BRACKETSMARK 0x40
#define FUNCTIONMARK 0x20
#define BRAC_FUNMARK (BRACKETSMARK | FUNCTIONMARK)
#define MAXBUFFERLEN 1024
#define MAXBRACKETSDEPTH 10000

#define CHECKBRACKETSDEPTH 1

/* 宏:直接計算括號內只有一步計算的表達式,例如(12.34+56.78)
#define DIRECTCASIMPLE 1
*/

typedef void(* vfunptr)(void);
typedef double(* dfunptr1)(double);
typedef double(* dfunptr2)(double, double);
typedef double(* dfunptr3)(double, double, double);

typedef struct tagbintree
{
 char op;
 unsigned char mark;
 double fvalue;
 void *vdataptr;  /* 用來處理數組類型數據 */
 struct tagbintree *lchild;
 struct tagbintree *rchild;
}bintree;

typedef struct tagparanode
{
 struct tagbintree *bintreenode;
 struct tagparanode *next;
}paranode, *List;

/* 用於表達式中函數計算
   函數節點前增加一個前驅,函數節點作爲其右子樹
   mark設函數標記,op保存函數參數個數:鏈表參數的記爲-1 */
typedef struct tagfunnode
{
 vfunptr funptr;           /* 通用無類型函數指針 */
 char *szfunname;          /* 保存函數名稱的緩衝區 */
 struct tagparanode *para; /* 保存函數參數的鏈表 */
}funnode;

typedef double(* lfunptr)(const List);

#define Alloctree ((bintree *)malloc(sizeof(bintree)))
#define Allocparanode ((paranode *)malloc(sizeof(paranode)))
#define Allocfunnode ((funnode *)malloc(sizeof(funnode)))

char getoperatorlevel(char op);
int isoperator(unsigned char c);
double caltree(const bintree *node);
void preorderdistree(const bintree *node);
void postorderdistree(const bintree *node);
void destorytree(bintree **node);
void destroyparalist(paranode *head);
bintree *appendnode(bintree **node, char op, double value, char sign);
int getfunptr(const char *szfunname, vfunptr *funp);
int isconstant(const char *sznum, double *variable);
int isvariable(const char *sznum, double *variable);
int checknum(const char *sznum);
int islegaldoublenum(const char *sznum);
int bracketsmatchingcheck(const char *szsrc);
long getmaxbracketsdepth(const char *szsrc);
double strtodouble(const char *sznum);
bintree *createtree(const char *szexpress);
bintree *createtree_(const char **szexpress, long *para);
int checkexpression(const char *szexpress);
int checkexpression_(const char **szexpress, int colon, long *para);
double calfun1(const funnode *node);
double calfun2(const funnode *node);
double calfun3(const funnode *node);
double cot(double x);
double sec(double x);
double csc(double x);
double sgn(double x);
double logr(double b, double x);
double max_(const List head);
double min_(const List head);
double mean(const List head);
double sum(const List head);
double squaresum(const List head);
double cubicsum(const List head);
double mid3(double v1, double v2, double v3);
double iiif(const List head);
double iif(const bintree *condition, const bintree *truepart, const bintree *falsepart);
double nofun(const List head, unsigned long index);
#ifdef _WIN32
  void catcher(int sig);

  void catcher(int sig)
  {
   printf("divide by 0.\n");
  }

  int _matherr(struct _exception *e)
  {
   filldoublewithind(e->retval);

   return 1;
  }
#else
  void catcher(int sig, int type, int *reglist);

  void catcher(int sig, int type, int *reglist)
  {
   printf("divide by 0.\n");
  }

  int matherr(struct exception *e)
  {
   filldoublewithind(e->retval);

   return 1;
  }
#endif

int main(int argc, char *argv[], char *env[])
{
 char s[1000];
 bintree *root;

 signal(SIGFPE, SIG_IGN);  /* 將被零除信號設爲忽略 */

 strcpy(s, "-1+2*3^-2^-2^-(1*(2+1)^-4^-1.4)");
 printf("%s\n", s);
 root = createtree(s);
 postorderdistree(root);
 printf("\n=%.10lf\n\n", caltree(root));
 destorytree(&root);

 strcpy(s, "((((-(11.86)-2)+54.89*(45.8)*54)*2)*-(-12.39+-(23^-pow(2,0.81))))*2^ -3 + 2^3^-0.3");
 printf("%s\n", s);
 root = createtree(s);
 postorderdistree(root);
 printf("\n=%.10lf\n\n", caltree(root));
 destorytree(&root);

 strcpy(s, "iif(3> 2, 0, 20) ? sin(PI): cos(PI_2)+ -1+mean(10 + pi*sqrt(12.890),max(12.34 , -90, 67.21) , 123.21) + fabs (-(1+sin(1+logr(10,190)))/cos(12)+sqrt(2)^2)");
 printf("%s\n", s);
 root = createtree(s);
 postorderdistree(root);
 printf("\n=%.10lf\n\n", caltree(root));
 destorytree(&root);

 strcpy(s, "0 ? 10: log(-max(12.34,5.6*1.2,3.45^2.1^-2.9,PI,logr(2,10)))");

 printf("%s\n", s);
 while(1)
  {
   printf("input expression(0 to end):");
   gets(s);

   if (s[0] == '0' && s[1] == '\0')
    break;

   if (bracketsmatchingcheck(s))
    {
     #ifdef CHECKBRACKETSDEPTH
       if (getmaxbracketsdepth(s) > MAXBRACKETSDEPTH)
        {
         printf("The brackets are too cpmplex.\n");
         continue;
        }
     #endif
     if (checkexpression(s))
      {
       if ((root = createtree(s)) != NULL)
        {
         postorderdistree(root);
         printf("\n=%.10lf\n", caltree(root));
         destorytree(&root);
        }
       else
        printf("Fails to create tree.");
      }
     else
      printf("Expression error.\n");
    }
   else
    printf("Brackets do not match.\n");
  }

 printf("\n");
 getch();
}

/*
*    名稱: preorderdistree
*    功能: 前序遍歷顯示錶達式樹結構
*  返回值: 無返回值
*    參數: const bintree *node  指向要顯示錶達式樹根節點的常指針
*/
void preorderdistree(const bintree *node)
{
 if (node != NULL)
  {
   if (node->mark & FUNCTIONMARK)
    {
     paranode const *p = (paranode const *)((funnode const *)node->rchild)->para;
     printf("%s( ", ((funnode const *)node->rchild)->szfunname);

     while(p)
      {
       postorderdistree(p->bintreenode);
       printf(p->next ? "," : ") ");
       p = p->next;
      }
    }
   else
    {
     if (node->op)
      printf("%c ", node->op);
     else
      printf("%5.3f ", node->fvalue);

     preorderdistree(node->lchild);
     preorderdistree(node->rchild);
    }
  }
}

/*
*    名稱: postorderdistree
*    功能: 後序遍歷顯示錶達式樹結構
*  返回值: 無返回值
*    參數: const bintree *node  指向要顯示錶達式樹根節點的常指針
*/
void postorderdistree(const bintree *node)
{
 if (node != NULL)
  {
   if (node->mark & FUNCTIONMARK)
    {
     paranode const *p = (paranode const *)((funnode const *)node->rchild)->para;
     printf("%s( ", ((funnode const *)node->rchild)->szfunname);

     while(p)
      {
       postorderdistree(p->bintreenode);
       printf(p->next ? "," : ") ");
       p = p->next;
      }
    }
   else
    {
     postorderdistree(node->lchild);
     postorderdistree(node->rchild);

     if (node->op)
      printf("%c ", node->op);
     else
      printf("%5.3f ", node->fvalue);
    }
  }
}

/*   名稱: destorytree
*    功能: 銷燬樹
*  返回值: 無返回值
*    參數: bintree **node  指向要銷燬樹的根節點的二級指針
*/
void destorytree(bintree **node)
{
 if (*node == NULL)
  return;

 if ((*node)->mark & FUNCTIONMARK)  /* 銷燬函數部分 */
  {
   funnode *p = (funnode *)(*node)->rchild;

   free(p->szfunname);
   destroyparalist(p->para);  /* 銷燬函數參數鏈表部分 */
   free(p);
   free(*node);
   *node = NULL;
   return;
  }

 if ((*node)->lchild != NULL)
  destorytree(&(*node)->lchild);
 if ((*node)->rchild != NULL)
  destorytree(&(*node)->rchild);

 free(*node);
 *node = NULL;
}

/*   名稱: destroyparalist
*    功能: 銷燬函數參數鏈表
*  返回值: 無返回值
*    參數: paranode *head  函數參數鏈表頭指針
*/
void destroyparalist(paranode *head)
{
 paranode *p;

 if (head == NULL)
  return;

 p = head->next;
 destorytree(&head->bintreenode);
 free(head);
 while(p)
  {
   head = p->next;

   destorytree(&p->bintreenode);
   free(p);
   p = head;
  }
}

/*   名稱: appendnode
*    功能: 向表達式樹添加節點
*  返回值: 添加成功 返回指向生成的新節點的指針,失敗 返回 NULL
*    參數: bintree **node  指向表達式樹根節點(已生成的非空節點)的二級指針
*          char op         運算符
*          double value    右操作數的值
*          char sign       右操作數符號(0:正,1:負)
*/
bintree *appendnode(bintree **node, char op, double value, char sign)
{
 bintree *nodeop;
 bintree *nodenum;

 if ((nodeop = Alloctree) == NULL)
  return NULL;

 nodeop->op = op;
 nodeop->mark = 0;

 if ((nodenum = Alloctree) == NULL)
  {
   free(nodeop);

   return NULL;
  }

 nodenum->op = 0;
 nodenum->mark = 0;
 if (sign == 0)
  {
   nodenum->fvalue = value;
   nodenum->lchild = NULL;
   nodenum->rchild = NULL;
  }
 else if (op == '^')  /* ^由符號位記錄負號 */
  {
   nodenum->fvalue = value;
   nodenum->lchild = NULL;
   nodenum->rchild = NULL;
   nodeop->mark |= SIGNMARK;
  }
 else  /* 其他運算符右操作數的負號處理成0- */
  {
   nodenum->op = '-';
   if ((nodenum->lchild = Alloctree) == NULL)
    {
     free(nodeop);
     free(nodenum);

     return NULL;
    }
   nodenum->lchild->op = 0;
   nodenum->lchild->fvalue = 0;
   nodenum->lchild->mark = 0;
   nodenum->lchild2 = NULL;
   nodenum->lchild->rchild = NULL;

   if ((nodenum->rchild = Alloctree) == NULL)
    {
     free(nodeop);
     free(nodenum->lchild);
     free(nodenum);

     return NULL;
    }
   nodenum->rchild->op = 0;
   nodenum->rchild->fvalue = value;
   nodenum->rchild->mark = 0;
   nodenum->rchild->lchild = NULL;
   nodenum->rchild2 = NULL;
  }

 if (op == '^')  /* ^向右下穿透負指數項 */
  {
   bintree *rp;
   if (getoperatorlevel(op) == getoperatorlevel((*node)->op) && op != (*node)->op)
    {
     nodeop->lchild = *node;
     *node = nodeop;
    }
   else if (getoperatorlevel(op) < getoperatorlevel((*node)->op) || ((*node)->mark & BRACKETSMARK) || getoperatorlevel((*node)->op) == 0)
    {
     nodeop->lchild = *node;
     *node = nodeop;
    }
   else if (getoperatorlevel(op) > getoperatorlevel((*node)->op))
    {
     rp = *node;

     while(getoperatorlevel(op) > getoperatorlevel(rp->rchild->op) && (rp->rchild->mark & BRACKETSMARK) != BRACKETSMARK && getoperatorlevel(rp->rchild->op))
      {
       rp = rp->rchild;
      }
     if ((getoperatorlevel(op) == getoperatorlevel(rp->rchild->op) && op != rp->rchild->op) || (getoperatorlevel(op) < getoperatorlevel(rp->rchild->op) || (rp->rchild->mark & BRACKETSMARK) == BRACKETSMARK || getoperatorlevel(rp->rchild->op) == 0))
      {
       nodeop->lchild = rp->rchild;
       rp->rchild = nodeop;
       nodeop->rchild = nodenum;

       return nodeop;
      }

     nodeop->rchild = rp->rchild;  /* rp->rchild 第一項指數項 */
     while(op == nodeop->rchild->op)
      {
       if (nodeop->rchild->mark & BRACKETSMARK)
        break;

       if (nodeop->rchild->mark & SIGNMARK)
        rp = nodeop->rchild;

       nodeop->rchild = nodeop->rchild2;
      }

     nodeop->lchild = rp->rchild;
     rp->rchild = nodeop;
    }
   else
    {
     int te = 1;
     rp = nodeop->rchild = *node;

     while(op == nodeop->rchild->op)
      {
       if (nodeop->rchild->mark & BRACKETSMARK)
        break;

       if (nodeop->rchild->mark & SIGNMARK)
        {
         rp = nodeop->rchild;
         te = 0;
        }

       nodeop->rchild = nodeop->rchild2;
      }
     if (te)
      {
       nodeop->lchild = *node;
       *node = nodeop;
      }
     else
      {
       nodeop->lchild = rp->rchild;
       rp->rchild = nodeop;
      }
    }

   nodeop->rchild = nodenum;

   return nodeop;
  }

 /* 添加非指數運算符節點 */
 if (getoperatorlevel(op) > getoperatorlevel((*node)->op) && ((*node)->mark & BRACKETSMARK) != BRACKETSMARK && getoperatorlevel((*node)->op))
  {
   nodeop->rchild = *node;

   while(getoperatorlevel(op) > getoperatorlevel(nodeop->rchild2->op) && (nodeop->rchild2->mark & BRACKETSMARK) != BRACKETSMARK && getoperatorlevel(nodeop->rchild2->op))
    {
     nodeop->rchild = nodeop->rchild2;
    }
   nodeop->lchild = nodeop->rchild2;
   nodeop->rchild2 = nodeop;
  }
 else
  {
   nodeop->lchild = *node;
   *node = nodeop;
  }

 nodeop->rchild = nodenum;

 return nodeop;
}

/*   名稱: getoperatorlevel
*    功能: 獲取運算符級別(包括分隔符)
*  返回值: 返回運算符的級別
*    參數: char op  運算符
*
*    說明: 以查表方式獲取
*          運算符中指數運算符^單獨設最高級
*/
char getoperatorlevel(char op)
{
 #ifdef _WIN32
    static const char charactertype[384] =
 #else
          static char charactertype[384] =
 #endif
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0,64,64, 4, 2,64, 2, 0, 4, 0, 0, 0, 0,
   0, 0, 0, 0, 0, 0,64, 0, 1, 0, 1,64, 0, 0, 0, 0, 0, 0, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   0, 0, 0, 0};

 return charactertype[op + 128];
}

/*   名稱: isoperator
*    功能: 識別字符是否爲運算符
*  返回值: 是運算符返回級別值(非0),不是運算符返回0
*    參數: char c  欲識別字符
*
*    說明:沒使用
*/
int isoperator(unsigned char c)
{
 if (c == '+' || c == '-' || c == '*' || c == '/' || c == '^' || c == '<' || c == '>' || c == '(' || c == ')' || c == ',' || c == '?' || c == ':')
  return 1;

 return 0;
}

/*   名稱: cot
*    功能: 計算三角函數的餘切函數
*  返回值: 以x爲參數值的餘切值;參數爲INF或IND時直接返回
*    參數: double x  弧度表示的角
*/
double cot(double x)
{
 inf_double_return(x);

 return tan(PI_2 - x);
}

/*   名稱: sec
*    功能: 計算三角函數的正割函數
*  返回值: 以x爲參數值的正割值;參數爲INF或IND時直接返回
*    參數: double x  弧度表示的角
*/
double sec(double x)
{
 inf_double_return(x);

 return 1 / cos(x);
}

/*   名稱: csc
*    功能: 計算三角函數的餘割函數
*  返回值: 以x爲參數值的餘割值;參數爲INF或IND時直接返回
*    參數: double x  弧度表示的角
*/
double csc(double x)
{
 inf_double_return(x);

 return 1 / sin(x);
}

/*   名稱: sgn
*    功能: 返回參數的符號
*  返回值: 參數 > 0 返回 1,參數 == 0 返回 0, 參數 < 0 返回 -1;參數爲INF或IND時直接返回
*    參數: double x  雙精度變量
*/
double sgn(double x)
{
 inf_double_return(x);

 if (x > 0)
  return 1;
 if (x < 0)
  return -1;

 return 0;
}

/*   名稱: logr
*    功能: 計算以b爲底的x的對數
*  返回值: 成功 返回計算結果,不成功 返回IND值;參數中有INF或IND時直接返回
*    參數: double b  底數
*          double x  真數
*
*    說明:b > 0 且b ≠ 1,x > 0
*/
double logr(double b, double x)
{
 inf_double_return(x);
 inf_double_return(b);

 if (x < 0 || b < 0 || b == 1)
  {
   filldoublewithind(x);
   return x;
  }

 x = log(x);
 inf_double_return(x);
 b = log(b);
 inf_double_return(b);

 return x / b;
}

/*   名稱: max_
*    功能: 返回參數中的最大值
*  返回值: 返回最大值;參數中有INF或IND時直接返回
*    參數: const List head  指向參數鏈表頭結點的常指針
*/
double max_(const List head)
{
 double v;
 double v1;
 register List p = head;

 v = caltree(p->bintreenode);
 inf_double_return(v);

 p = p->next;
 while(p)
  {
   v1 = caltree(p->bintreenode);
   inf_double_return(v1);

   if (v1 > v)
    v = v1;
   p = p->next;
  }

 return v;
}

/*   名稱: min_
*    功能: 返回參數中的最小值
*  返回值: 返回最小值;參數中有INF或IND時直接返回
*    參數: const List head  指向參數鏈表頭結點的常指針
*/
double min_(const List head)
{
 double v;
 double v1;
 register List p = head;

 v = caltree(p->bintreenode);
 inf_double_return(v);

 p = p->next;
 while(p)
  {
   v1 = caltree(p->bintreenode);
   inf_double_return(v1);

   if (v1 < v)
    v = v1;
   p = p->next;
  }

 return v;
}

/*   名稱: mean
*    功能: 返回參數的算術平均數
*  返回值: 返回算術平均數;參數中有INF或IND時直接返回
*    參數: const List head  指向參數鏈表頭結點的常指針
*/
double mean(const List head)
{
 double sum;
 register long n = 1L;
 register List p = head;

 sum = caltree(p->bintreenode);
 inf_double_return(sum);

 p = p->next;
 while(p)
  {
   sum += caltree(p->bintreenode);
   inf_double_return(sum);

   n++;
   p = p->next;
  }

 return sum / n;
}

/*   名稱: mid3
*    功能: 返回三個數中的中間值
*  返回值: 返回中間值;參數中有INF或IND時直接返回
*    參數: double v1  第一個數
*          double v2  第二個數
*          double v3  第三個數
*/
double mid3(double v1, double v2, double v3)
{
 inf_double_return(v1);
 inf_double_return(v2);
 inf_double_return(v3);

 if (v1 > v2)
  {
   if (v2 > v3)
    return v2;
   else
    return (v1 > v3) ? v3 : v1;
  }
 else
  {
   if (v3 > v2)
    return v2;
   else
    return (v1 > v3) ? v1 : v3;
  }
}

/*   名稱: sum
*    功能: 返回參數的和
*  返回值: 返回和;參數中有INF或IND時直接返回
*    參數: const List head  指向參數鏈表頭結點的常指針
*/
double sum(const List head)
{
 double v;
 double sum;
 register List p = head;

 v = caltree(p->bintreenode);
 inf_double_return(v);
 sum = v;
 inf_double_return(sum);

 p = p->next;
 while(p)
  {
   v = caltree(p->bintreenode);
   inf_double_return(v);
   sum += v;
   inf_double_return(sum);
   p = p->next;
  }

 return sum;
}

/*   名稱: squaresum
*    功能: 返回參數的平方和
*  返回值: 返回平方和;參數中有INF或IND時直接返回
*    參數: const List head  指向參數鏈表頭結點的常指針
*/
double squaresum(const List head)
{
 double v;
 double sumofsquare;
 register List p = head;

 v = caltree(p->bintreenode);
 inf_double_return(v);
 sumofsquare = v * v;
 inf_double_return(sumofsquare);

 p = p->next;
 while(p)
  {
   v = caltree(p->bintreenode);
   inf_double_return(v);
   sumofsquare += v * v;
   inf_double_return(sumofsquare);
   p = p->next;
  }

 return sumofsquare;
}

/*   名稱: cubicsum
*    功能: 返回參數的立方和
*  返回值: 返回立方和;參數中有INF或IND時直接返回
*    參數: const List head  指向參數鏈表頭結點的常指針
*/
double cubicsum(const List head)
{
 double v;
 double sumofcubic;
 register List p = head;

 v = caltree(p->bintreenode);
 inf_double_return(v);
 sumofcubic = v * v * v;
 inf_double_return(sumofcubic);

 p = p->next;
 while(p)
  {
   v = caltree(p->bintreenode);
   inf_double_return(v);
   sumofcubic += v * v * v;
   inf_double_return(sumofcubic);
   p = p->next;
  }

 return sumofcubic;
}

/*   名稱: iif
*    功能: 根據表達式結果選擇返回兩個結果中的一個
*  返回值: condition爲非0時返回 truepart計算結果,0時返回 falsepart計算結果;condition爲INF或IND時直接返回
*    參數: const bintree *condition  做爲比較條件的表達式樹根節點
*          const bintree *truepart   做爲返回值的表達式樹根節點
*          const bintree *falsepart  做爲返回值的表達式樹根節點
*/
double iif(const bintree *condition, const bintree *truepart, const bintree *falsepart)
{
 double v = caltree(condition);

 inf_double_return(v);

 if (v)
  return caltree(truepart);
 else
  return caltree(falsepart);
}

/*   名稱: iiif
*    功能: 根據表達式結果選擇返回若干結果中的一個
*  返回值: condition爲1時返回參數鏈表中的第二項的值,2時返回第三項的值,以此類推;condition爲INF或IND時直接返回
*    參數: const List head  指向參數鏈表頭結點的常指針
*
*    說明: 參數至少必須有兩項,condition小於1時,返回第二項的值,大於參數項數時返回最後一項
*/
double iiif(const List head)
{
 const unsigned long firstvalue = 2UL;

 register List p = head;
 List p1;
 double v;
 unsigned long i, n;

 if (p == NULL || p->next == NULL)
  return 0;

 v = caltree(p->bintreenode);
 inf_double_return(v);

 if (v < firstvalue)
  return caltree(p->next->bintreenode);

 if (v <= 4294967295UL)
  n = (unsigned long)v;
 else
  n = 4294967295UL;

 i = firstvalue;
 p1 = p->next;
 p = p->next2;
 while(p)
  {
   p1 = p;
   if (i == n)
    return caltree(p->bintreenode);

   p = p->next;
   i++;
  }

 return caltree(p1->bintreenode);
}

/*   名稱: nofun
*    功能: 返回參數鏈表中的指定項
*  返回值: index 1 返回參數鏈表中的第一項的值,2 返回參數鏈表中的第二項的值,以此類推
*    參數: const List head  指向參數鏈表頭結點的常指針
*          unsigned long index 索引
*/
double nofun(const List head, unsigned long index)
{
 register List p = head;
 register unsigned long n = 1UL;
 double v;

 while(p)
  {
   if (n == index)
    return caltree(p->bintreenode);

   if (n == 4294967295UL)
    break;

   p = p->next;
   n++;
  }

 filldoublewithind(v);

 return v;
}

/*   名稱: getfunptr
*    功能: 獲取函數指針
*  返回值: 返回函數參數個數
*    參數: const char *szfunname 指向函數名稱字符串的常指針
*          vfunptr *funp  指向函數指針變量的指針
*/
int getfunptr(const char *szfunname, vfunptr *funp)
{
 if (szfunname == NULL || funp == NULL)
  return 0;

 if (strcmp(szfunname, "sin") == 0)
  {
   *funp = (vfunptr)&sin;
   return 1;
  }
 if (strcmp(szfunname, "cos") == 0)
  {
   *funp = (vfunptr)&cos;
   return 1;
  }
 if (strcmp(szfunname, "tan") == 0)
  {
   *funp = (vfunptr)&tan;
   return 1;
  }
 if (strcmp(szfunname, "cot") == 0)
  {
   *funp = (vfunptr)&cot;
   return 1;
  }
 if (strcmp(szfunname, "asin") == 0)
  {
   *funp = (vfunptr)&asin;
   return 1;
  }
 if (strcmp(szfunname, "acos") == 0)
  {
   *funp = (vfunptr)&acos;
   return 1;
  }
 if (strcmp(szfunname, "atan") == 0)
  {
   *funp = (vfunptr)&atan;
   return 1;
  }
 if (strcmp(szfunname, "sinh") == 0)
  {
   *funp = (vfunptr)&sinh;
   return 1;
  }
 if (strcmp(szfunname, "cosh") == 0)
  {
   *funp = (vfunptr)&cosh;
   return 1;
  }
 if (strcmp(szfunname, "tanh") == 0)
  {
   *funp = (vfunptr)&tanh;
   return 1;
  }
 if (strcmp(szfunname, "csc") == 0)
  {
   *funp = (vfunptr)&csc;
   return 1;
  }
 if (strcmp(szfunname, "sec") == 0)
  {
   *funp = (vfunptr)&sec;
   return 1;
  }
 if (strcmp(szfunname, "sqrt") == 0)
  {
   *funp = (vfunptr)&sqrt;
   return 1;
  }
 if (strcmp(szfunname, "log") == 0)
  {
   *funp = (vfunptr)&log;
   return 1;
  }
 if (strcmp(szfunname, "log10") == 0)
  {
   *funp = (vfunptr)&log10;
   return 1;
  }
 if (strcmp(szfunname, "fabs") == 0)
  {
   *funp = (vfunptr)&fabs;
   return 1;
  }
 if (strcmp(szfunname, "exp") == 0)
  {
   *funp = (vfunptr)&exp;
   return 1;
  }
 if (strcmp(szfunname, "sgn") == 0)
  {
   *funp = (vfunptr)&sgn;
   return 1;
  }
 if (strcmp(szfunname, "ceil") == 0)
  {
   *funp = (vfunptr)&ceil;
   return 1;
  }
 if (strcmp(szfunname, "floor") == 0)
  {
   *funp = (vfunptr)&floor;
   return 1;
  }

 if (strcmp(szfunname, "atan2") == 0)
  {
   *funp = (vfunptr)&atan2;
   return 2;
  }
 if (strcmp(szfunname, "pow") == 0)
  {
   *funp = (vfunptr)&pow;
   return 2;
  }
 if (strcmp(szfunname, "logr") == 0)
  {
   *funp = (vfunptr)&logr;
   return 2;
  }
 if (strcmp(szfunname, "fmod") == 0)
  {
   *funp = (vfunptr)&fmod;
   return 2;
  }

 if (strcmp(szfunname, "mid3") == 0)
  {
   *funp = (vfunptr)&mid3;
   return 3;
  }
 if (strcmp(szfunname, "iif") == 0)
  {
   *funp = (vfunptr)&iif;
   return 3;
  }

 if (strcmp(szfunname, "max") == 0)
  {
   *funp = (vfunptr)&max_;
   return -1;
  }
 if (strcmp(szfunname, "min") == 0)
  {
   *funp = (vfunptr)&min_;
   return -1;
  }
 if (strcmp(szfunname, "mean") == 0)
  {
   *funp = (vfunptr)&mean;
   return -1;
  }
 if (strcmp(szfunname, "sum") == 0)
  {
   *funp = (vfunptr)∑
   return -1;
  }
 if (strcmp(szfunname, "squaresum") == 0)
  {
   *funp = (vfunptr)&squaresum;
   return -1;
  }
 if (strcmp(szfunname, "cubicsum") == 0)
  {
   *funp = (vfunptr)&cubicsum;
   return -1;
  }
 if (strcmp(szfunname, "iiif") == 0)
  {
   *funp = (vfunptr)&iiif;
   return -1;
  }

 return 0;
}

/*   名稱: strtodouble
*    功能: 將字符串轉爲double型浮點數
*  返回值: 返回轉換後double值
*    參數: const char *sznum  指向數字字符串常指針
*/
double strtodouble(const char *sznum)
{
 double v;

 if (isconstant(sznum, &v))
  return v;

 /* 變量 */
 if (isvariable(sznum, &v))
  return v;

 return atof(sznum);
}

/*   名稱: isconstant
*    功能: 檢查字符串是否爲常數
*  返回值: 是 由variable接收常量值 返回1,不是返回0
*    參數: const char *sznum  欲檢查字符串
*          double *variable   用於接收常量值的指針,爲NULL時不反回常量值
*/
int isconstant(const char *sznum, double *variable)
{
 if (sznum == NULL)
  return 0;

 if (sznum[1] == '\0')
  {
   if (sznum[0] == 'E')
    {
     if (variable != NULL)
      *variable = E;

     return 1;
    }
  }
 if (sznum[2] == '\0')
  {
   if ((sznum[0] == 'P' && sznum[1] == 'I') || (sznum[0] == 'p' && sznum[1] == 'i'))
    {
     if (variable != NULL)
      *variable = PI;

     return 1;
    }
  }
 else if (sznum[4] == '\0')
  {
   if ((sznum[0] == 'P' && sznum[1] == 'I' && sznum[2] == '_' && sznum[3] == '2') || (sznum[0] == 'p' && sznum[1] == 'i' && sznum[2] == '_' && sznum[3] == '2'))
    {
     if (variable != NULL)
      *variable = PI_2;

     return 1;
    }
  }
 else if (strcmp(sznum, "SQRT2") == 0)
  {
   if (variable != NULL)
    *variable = SQRT2;

   return 1;
  }

 return 0;
}

/*   名稱: isvariable
*    功能: 檢查字符串是否爲已定義的變量
*  返回值: 是 由variable接收變量值 返回1,不是返回0
*    參數: const char *sznum  欲檢查字符串
*          double *variable   用於接收變量值的指針,爲NULL時不返回變量值
*/
int isvariable(const char *sznum, double *variable)
{
 if (sznum == NULL)
  return 0;

 return 0;
}

/*   名稱: checknum
*    功能: 檢查字符串是否爲合法浮點數
*  返回值: 合法返回1,不合法返回0
*    參數: const char *sznum  要檢查的字符串
*/
int checknum(register const char *sznum)
{
 int point = 0;
 int exponent = 0;
 int space = 0;
 long num1 = 0L, num2 = 0L;

 if (sznum == NULL)
  return 0;

 while(*sznum)
  {
   if (isdigit(*sznum))
    {
     if (space)
      return 0;

     if (exponent)
      num2++;
     else
      num1++;
    }
   else if (*sznum == '+' || *sznum == '-')
    {
     if (space)
      return 0;

     if (exponent)  /* 指數部分 */
      {
       if (*(sznum - 1) != 'e' && *(sznum - 1) != 'E')
        return 0;
      }
     else  /* 開頭部分 */
      {
       if (num1 > 0L || point)
        return 0;
      }
    }
   else if (*sznum == '.')
    {
     if (point || exponent || space)
      return 0;

     point = 1;
    }
   else if (*sznum == 'e' || *sznum == 'E')
    {
     if (exponent || num1 == 0L || space)
      return 0;

     exponent = 1;
    }
   else if (*sznum == ' ')
    {
     if (num1 || point)
      space = 1;
    }
   else
    {
     return 0;
    }

   sznum++;
  }

 if (num1 == 0L || (exponent && num2 == 0L))
  return 0;

 return 1;
}

/*   名稱: islegaldoublenum
*    功能: 檢查字符串內容表示的雙精度值是否合法
*  返回值: 合法返回1,不合法返回0
*    參數: const char *sznum  要檢查的字符串
*/
int islegaldoublenum(const char *sznum)
{
 double v;

 if (checknum(sznum))
  {
   v = atof(sznum);
   checkdoublereturn(v);
  }
 else
  return 0;
}

/*   名稱: bracketsmatchingcheck
*    功能: 檢查字符串括號是否匹配
*  返回值: 括號匹配正確 返回1值,否則返回0值。 
*    參數: const char *szsrc  爲待檢測字符串。
*/
int bracketsmatchingcheck(const char *szsrc)
{  
 const char *ptr = szsrc, *ptr1;  
 char c;  
 long brackets[3] = {0, 0, 0}; /* 括號計數器 0--(), 1--[], 2--{} */  
  
 if (szsrc == NULL)  
  return 1;
  
 while(*ptr) /* 第一次掃描 */  
  {  
   c = *ptr;    
   if (c == '(')  
    brackets[0]++;     
   else if (c == ')')  
    {  
     if (--brackets[0] == -1)  
      return 0;  
    }     
   else if (c == '[')  
    brackets[1]++;     
   else if (c == ']')  
    {  
     if (--brackets[1] == -1)  
      return 0;  
    }     
   else if (c == '{')  
    brackets[2]++;     
   else if (c == '}')  
    {  
     if (--brackets[2] == -1)  
      return 0;  
    }     
  
   ptr++;  
  }  
  
 if (brackets[0] != 0 || brackets[1] != 0 || brackets[2] != 0) /* 括號不匹配,退出 */  
  return 0;  
  
 ptr = szsrc;  
 while(*ptr) /* 第二次掃描 */  
  {  
   if (*ptr == ']')  
    {  
     brackets[0] = 0;  
     brackets[1] = 1;  
     brackets[2] = 0;  
     ptr1 = ptr - 1;  
     while(1)   
      {  
       c = *ptr1;  
       if (c == '[')   
        {  
         brackets[1]--;  
         if (brackets[1] == 0)   
          {  
           if ( brackets[0] != 0 || brackets[2] != 0)  
            return 0;  
           else  
            break;  
          }  
        }  
       else if (c == ']')   
        brackets[1]++;  
       else if (c == ')')   
        brackets[0]++;  
       else if (c == '(')   
        {  
         if (--brackets[0] == -1)  
          return 0;  
        }  
       else if (c == '}')   
        brackets[2]++;  
       else if (c == '{')   
        brackets[2]--;  
       ptr1--;  
      }  
    }  
   else if (*ptr == '}')  
    {  
     brackets[0] = 0;  
     brackets[1] = 0;  
     brackets[2] = 1;  
     ptr1 = ptr - 1;  
     while(1)   
      {  
       c = *ptr1;  
       if (c == '{')  
        {  
         brackets[2]--;  
         if (brackets[2] == 0)  
          {  
           if (brackets[0] != 0 || brackets[1] != 0)  
            return 0;  
           else  
            break;  
          }  
        }  
       else if (c == '}')  
        brackets[2]++;  
       else if (c == ')')   
        brackets[0]++;  
       else if (c == '(')   
        {  
         if (--brackets[0] == -1)  
          return 0;  
        }  
       else if (c == ']')  
        brackets[1]++;  
       else if (c == '[')  
        brackets[1]--;  
       ptr1--;  
      }  
    }  
    
   ptr++;  
  }  
  
 return 1;  
}  

/*   名稱: getmaxbracketsdepth
*    功能: 獲取字符串中括號嵌套最大深度
*  返回值: 返回最大深度值
*    參數: const char *szsrc  爲待檢測字符串。
*/
long getmaxbracketsdepth(const char *szsrc)
{
 long bracketsdepth = 0;
 long maxdepth = 0;

 if (szsrc == NULL)
  return 0;

 while(*szsrc)
  {
   if (*szsrc == '(' || *szsrc == '[' || *szsrc == '{')
    {
     if (++bracketsdepth > maxdepth)
      maxdepth = bracketsdepth;
    }
   else if (*szsrc == ')' || *szsrc == ']' || *szsrc == '}')
    {
     bracketsdepth--;
    }
   szsrc++;
  }

 return maxdepth;
}

/*   名稱: caltree
*    功能: 後序遍歷表達式數樹計算結果 
*  返回值: 返回計算結果
*    參數: const bintree *node  欲計算的表達式樹根節點
*/
double caltree(const bintree *node)
{
 double v1;
 double v2;

 if (node == NULL)
  {
   filldoublewithind(v1);

   return v1;
  }

 if (node->op == 0)
  return node->fvalue;

 if (node->op == '+')
  {
   v1 = caltree(node->lchild);
   inf_double_return(v1);

   v2 = caltree(node->rchild);
   inf_double_return(v2);

   return v1 + v2;
  }

 if (node->op == '-')
  {
   v1 = caltree(node->lchild);
   inf_double_return(v1);

   v2 = caltree(node->rchild);
   inf_double_return(v2);

   return v1 - v2;
  }

 if (node->op == '*')
  {
   v1 = caltree(node->lchild);
   inf_double_return(v1);

   v2 = caltree(node->rchild);
   inf_double_return(v2);

   return v1 * v2;
  }

 if (node->op == '/')
  {
   v1 = caltree(node->lchild);
   inf_double_return(v1);

   v2 = caltree(node->rchild);
   inf_double_return(v2);

   return v1 / v2;
  }

 if (node->op == '<')
  {
   v1 = caltree(node->lchild);
   inf_double_return(v1);

   v2 = caltree(node->rchild);
   inf_double_return(v2);

   return v1 < v2;
  }

 if (node->op == '>')
  {
   v1 = caltree(node->lchild);
   inf_double_return(v1);

   v2 = caltree(node->rchild);
   inf_double_return(v2);

   return v1 > v2;
  }

 if (node->op == '^')
  {
   v1 = caltree(node->lchild);
   inf_double_return(v1);

   v2 = caltree(node->rchild);
   inf_double_return(v2);

   if (node->mark & SIGNMARK)
    v1 = pow(v1, -v2);
   else
    v1 = pow(v1, v2);

   return v1;
  }

 if (node->mark & FUNCTIONMARK)
  {
   if (strcmp(((funnode *)(node->rchild))->szfunname, "iif") == 0)
    {
     /* return iif(((funnode *)(node->rchild))->para->bintreenode, ((funnode *)(node->rchild))->para->next->bintreenode, ((funnode *)(node->rchild))->para->next2->bintreenode); */
     v1 = caltree(((funnode *)(node->rchild))->para->bintreenode);
     inf_double_return(v1);

     if (v1)
      return caltree(((funnode *)(node->rchild))->para->next->bintreenode);
     else
      return caltree(((funnode *)(node->rchild))->para->next2->bintreenode);
    }
   else if (node->op == 1)
    /* return calfun1((funnode *)(node->rchild)); */
    return ((dfunptr1)((funnode *)(node->rchild))->funptr)(caltree(((funnode *)(node->rchild))->para->bintreenode));
   else if (node->op == 2)
    /* return calfun2((funnode *)(node->rchild)); */
    return ((dfunptr2)((funnode *)(node->rchild))->funptr)(caltree(((funnode *)(node->rchild))->para->bintreenode), caltree(((funnode *)(node->rchild))->para->next->bintreenode));
   else if (node->op == 3)
    /* return calfun3((funnode *)(node->rchild)); */
    return ((dfunptr3)((funnode *)(node->rchild))->funptr)(caltree(((funnode *)(node->rchild))->para->bintreenode), caltree(((funnode *)(node->rchild))->para->next->bintreenode), caltree(((funnode *)(node->rchild))->para->next2->bintreenode));
   else if (node->op == -1)
    return ((lfunptr)((funnode *)(node->rchild))->funptr)(((funnode *)(node->rchild))->para);
  }
}

/*   名稱: calfun1
*    功能: 計算單參數函數
*  返回值: 返回計算結果
*    參數: const funnode *node  指向包含函數指針及參數的結構的指針
*/
double calfun1(const funnode *node)
{
 if (node == NULL)
  return 0;

 return ((dfunptr1)node->funptr)(caltree(node->para->bintreenode));
}

/*   名稱: calfun2
*    功能: 計算雙參數函數
*  返回值: 返回計算結果
*    參數: const funnode *node  指向包含函數指針及參數的結構的指針
*/
double calfun2(const funnode *node)
{
 if (node == NULL)
  return 0;

 return ((dfunptr2)node->funptr)(caltree(node->para->bintreenode), caltree(node->para->next->bintreenode));
}

/*   名稱: calfun3
*    功能: 計算三參數函數
*  返回值: 返回計算結果
*    參數: const funnode *node  指向包含函數指針及參數的結構的指針
*/
double calfun3(const funnode *node)
{
 if (node == NULL)
  return 0;

 return ((dfunptr3)node->funptr)(caltree(node->para->bintreenode), caltree(node->para->next->bintreenode), caltree(node->para->next2->bintreenode));
}

/*   名稱: createtree_
*    功能: 具體實現由字符串生成表達式樹
*  返回值: 成功 返回指向生成表達式樹的根節點的指針,失敗 返回 NULL
*    參數: const char **szexpress  指向要生成表達式樹的字符串的二級常指針
*          long *para              用於處理多參數函數的參數
*
*    說明:不直接使用由函數createtree調用,是爲了遍歷處理括號。
*          字符串應先由checkexpress做合法性檢查,否則可能出現不可測結果。
*/
bintree *createtree_(const char **szexpress, long *para)
{
 register const char **ptr = szexpress;
 char op = 0;
 char sign = 0;                     /* 符號位:無符號--0,'-'--sign = 1 - sign;,'+'--直接略過 */
 char numstr[MAXBUFFERLEN] = {"0"}; /* 保存數字,變量名,函數名的緩衝區 */
 char *ptrnum = numstr;
 bintree *root = NULL;

 while(**ptr)
  {
   if (ptrnum != numstr)  /* 先處理科學計數指數部分+- */
    {
     if (*(ptrnum - 1) == 'e' || *(ptrnum - 1) == 'E')  /* 可能是變量名 */
      {
       if (**ptr == '+' || **ptr == '-')
        {
         *ptrnum = '\0';
         if (!(isconstant(numstr, NULL) || isvariable(numstr, NULL)))
          {
           *ptrnum++ = **ptr;

           (*ptr)++;
           continue;
          }
        }
      }
    }
   if (**ptr == '(')
    {
     bintree *subexprtree;
     long paracount = 0L;

     if (root == NULL)
      {
       (*ptr)++;
       if (ptrnum != numstr)  /* 此處就是函數,numstr是函數名 */
        {
         funnode *pfunnode;
         paranode *p1;
         paranode *p2;

         *ptrnum = '\0';
         if ((root = Alloctree) == NULL)
          return NULL;

         if (sign) /* 沒有指數運算符問題 */
          {
           if ((root->lchild = Alloctree) == NULL)
            {
             free(root);

             return NULL;
            }

           if ((root->rchild = Alloctree) == NULL)
            {
             free(root->lchild);
             free(root);

             return NULL;
            }

           root->op = '-';
           root->mark = 0;
           root->lchild->op = 0;
           root->lchild->mark = 0;
           root->lchild->fvalue = 0;
           root->lchild2 = NULL;
           root->lchild->rchild = NULL;
           root->rchild->lchild = NULL;
           subexprtree = root->rchild;
          }
         else
          {
           root->lchild = NULL;
           subexprtree = root;
          }

         subexprtree->mark = BRAC_FUNMARK;
         if ((pfunnode = Allocfunnode) == NULL)
          {
           free(root);

           return NULL;
          }
         paracount = (long)(subexprtree->op = getfunptr(numstr, &pfunnode->funptr));
         if ((pfunnode->szfunname = (char *)malloc(strlen(numstr) + 1)) == NULL)
          {
           free(pfunnode);
           destorytree(&root);

           return NULL;
          }
         if ((p1 = p2 = pfunnode->para = Allocparanode) == NULL)
          {
           free(pfunnode->szfunname);
           free(pfunnode);
           free(root);

           return NULL;
          }
         strcpy(pfunnode->szfunname, numstr);
         subexprtree->rchild = (bintree *)pfunnode;

         while(paracount)  /* 以尾插法將函數參數的表達式樹存入參數鏈表 */
          {
           if (p2 == NULL)
            {
             if ((p2 = Allocparanode) == NULL)
              {
               destorytree(&root);

               return NULL;
              }
             p1->next = p2;
            }
           p2->next = NULL;
           if ((p2->bintreenode = createtree_(ptr, ¶count)) == NULL)
            {
             destorytree(&root);

             return NULL;
            }
           p1 = p2;
           p2 = NULL;
          }
        }
       else
        {
         if (sign == 0)
          {
           if ((root = createtree_(ptr, ¶count)) == NULL)
            return NULL;
          }
         else
          {
           if ((root = Alloctree) == NULL)
            return NULL;

           if ((root->lchild = Alloctree) == NULL)
            {
             free(root);

             return NULL;
            }

           if ((root->rchild = createtree_(ptr, ¶count)) == NULL)
            {
             free(root->lchild);
             free(root);

             return NULL;
            }

           root->op = '-';
           root->mark = 0;
           root->lchild->op = 0;
           root->lchild->mark = 0;
           root->lchild->fvalue = 0;
           root->lchild2 = NULL;
           root->lchild->rchild = NULL;
          }
        }
       op = 0;
       sign = 0;
       ptrnum = numstr;

       continue;
      }

     if ((subexprtree = appendnode(&root, op, 0, 0)) == NULL)
      {
       destorytree(&root);

       return NULL;
      }
     (*ptr)++;
     if (ptrnum != numstr)  /* 此處就是函數,numstr是函數名 */
      {
       funnode *pfunnode;
       paranode *p1;
       paranode *p2;

       *ptrnum = '\0';
       /* 直接使用subexprtree->rchild作爲函數節點前驅 */
       if (sign)  /* 函數前的符號位 */
        {
         if (op == '^')
          {
           subexprtree->mark |= SIGNMARK;
          }
         else  /* 0 - */
          {
           subexprtree = subexprtree->rchild;
           if ((subexprtree->lchild = Alloctree) == NULL)
            {
             destorytree(&root);

             return NULL;
            }
           subexprtree->lchild->op = 0;
           subexprtree->lchild->fvalue = 0;
           subexprtree->lchild->mark = 0;
           subexprtree->lchild2 = NULL;
           subexprtree->lchild->rchild = NULL;
           if ((subexprtree->rchild = Alloctree) == NULL)
            {
             destorytree(&root);

             return NULL;
            }
           subexprtree->rchild->lchild = NULL;
           subexprtree->rchild2 = NULL;
           subexprtree->op = '-';
          }
        }

       subexprtree->rchild->mark = BRAC_FUNMARK;
       if ((pfunnode = Allocfunnode) == NULL)
        {
         destorytree(&root);

         return NULL;
        }
       paracount = (long)(subexprtree->rchild->op = getfunptr(numstr, &pfunnode->funptr));
       if ((pfunnode->szfunname = (char *)malloc(strlen(numstr) + 1)) == NULL)
        {
         free(pfunnode);
         destorytree(&root);

         return NULL;
        }
       if ((p1 = p2 = pfunnode->para = Allocparanode) == NULL)
        {
         free(pfunnode->szfunname);
         free(pfunnode);
         destorytree(&root);

         return NULL;
        }
       strcpy(pfunnode->szfunname, numstr);
       subexprtree->rchild2 = (bintree *)pfunnode;

       while(paracount)  /* 以尾插法將函數參數的表達式樹存入參數鏈表 */
        {
         if (p2 == NULL)
          {
           if ((p2 = Allocparanode) == NULL)
            {
             destorytree(&root);

             return NULL;
            }
           p1->next = p2;
          }
         p2->next = NULL;
         if ((p2->bintreenode = createtree_(ptr, ¶count)) == NULL)
          {
           destorytree(&root);

           return NULL;
          }
         p1 = p2;
         p2 = NULL;
        }

       op = 0;
       sign = 0;
       ptrnum = numstr;

       continue;
      }

     free(subexprtree->rchild);  /* 刪除生成新節點的右子樹 */
     if (sign == 0)  /* (前的符號位 */
      {
       if ((subexprtree->rchild = createtree_(ptr, ¶count)) == NULL)
        {
         destorytree(&root);

         return NULL;
        }
      }
     else if (op == '^')  /* ^由符號位記錄負號 */
      {
       if ((subexprtree->rchild = createtree_(ptr, ¶count)) == NULL)
        {
         destorytree(&root);

         return NULL;
        }
       subexprtree->mark |= SIGNMARK;
      }
     else
      {
       if ((subexprtree->rchild = Alloctree) == NULL)
        {
         destorytree(&root);

         return NULL;
        }
       subexprtree->rchild->op = '-';
       subexprtree->rchild->mark = 0;
       subexprtree->rchild2 = NULL;
       if ((subexprtree->rchild->lchild = Alloctree) == NULL)
        {
         destorytree(&root);

         return NULL;
        }
       subexprtree->rchild->lchild->op = 0;
       subexprtree->rchild->lchild->fvalue = 0;
       subexprtree->rchild->lchild->mark = 0;
       subexprtree->rchild->lchild2 = NULL;
       subexprtree->rchild->lchild->rchild = NULL;
       if ((subexprtree->rchild2 = createtree_(ptr, ¶count)) == NULL)
        {
         destorytree(&root);

         return NULL;
        }
      }

     op = 0;
     sign = 0;
     ptrnum = numstr;
    }
   else if (**ptr == ')' || **ptr == ',')
    {
     if (ptrnum != numstr)
      {
       *ptrnum = '\0';
       if (root == NULL)  /* 只有一個數字,常量或變量 */
        {
         if ((root = Alloctree) == NULL)
          return NULL;

         root->op = 0;
         root->mark = 0;
         root->fvalue = (sign) ? -strtodouble(numstr) : strtodouble(numstr);
         root->lchild = NULL;
         root->rchild = NULL;

         if (**ptr == ',')
          {
           /* if (*para > 1)檢查用 */
           (*para)--;
          }
         else
          {
           if (*para)
            *para = 0;
          }

         (*ptr)++;

         return root;
        }

       if (appendnode(&root, op, (sign) ? -strtodouble(numstr) : strtodouble(numstr), 0) == NULL)
        {
         destorytree(&root);

         return NULL;
        }
      }

  #ifdef DIRECTCASIMPLE
     /* 直接計算括號內只有一步計算的表達式 */
     if (root->lchild->op == 0 && root->rchild->op == 0)
      {
       root->fvalue = caltree(root);
       root->op = 0;
       free(root->lchild);
       root->lchild = NULL;
       free(root->rchild);
       root->rchild = NULL;

       if (**ptr == ',')
        {
         /* if (*para > 1)檢查用 */
         (*para)--;
        }
       else
        {
         if (*para)
          *para = 0;
        }

       (*ptr)++;

       return root;
      }
  #endif

     if (**ptr == ')')
      {
       root->mark |= BRACKETSMARK;
       if (*para)
        *para = 0;
      }
     else
      {
       /* if (*para > 1)檢查用 */
       (*para)--;
      }

     (*ptr)++;

     return root;
    }
   else if (**ptr == '?')
    {
     bintree *subexprtree;
     funnode *pfunnode;

     if (ptrnum != numstr)
      {
       *ptrnum = '\0';
       if (root == NULL)  /* 只有一個數字,常量或變量 */
        {
         if ((root = Alloctree) == NULL)
          return NULL;

         root->op = 0;
         root->mark = 0;
         root->fvalue = (sign) ? -strtodouble(numstr) : strtodouble(numstr);
         root->lchild = NULL;
         root->rchild = NULL;
        }
       else if (appendnode(&root, op, (sign) ? -strtodouble(numstr) : strtodouble(numstr), 0) == NULL)
        {
         destorytree(&root);

         return NULL;
        }
      }
     (*ptr)++;

     if ((subexprtree = Alloctree) == NULL)
      {
       destorytree(&root);

       return NULL;
      }

     if ((pfunnode = Allocfunnode) == NULL)
      {
       free(subexprtree);
       destorytree(&root);

       return NULL;
      }

     subexprtree->op = getfunptr("iif", &pfunnode->funptr);
     if ((pfunnode->szfunname = (char *)malloc(strlen("iif") + 1)) == NULL)
      {
       free(pfunnode);
       free(subexprtree);
       destorytree(&root);

       return NULL;
      }
     if ((pfunnode->para = Allocparanode) == NULL)
      {
       free(pfunnode->szfunname);
       free(pfunnode);
       free(subexprtree);
       destorytree(&root);

       return NULL;
      }
     if ((pfunnode->para->next = Allocparanode) == NULL)
      {
       free(pfunnode->szfunname);
       free(pfunnode->para);
       free(pfunnode);
       free(subexprtree);
       destorytree(&root);

       return NULL;
      }
     if ((pfunnode->para->next2 = Allocparanode) == NULL)
      {
       free(pfunnode->szfunname);
       free(pfunnode->para->next);
       free(pfunnode->para);
       free(pfunnode);
       free(subexprtree);
       destorytree(&root);

       return NULL;
      }
     if ((pfunnode->para->next->bintreenode = createtree_(ptr, para)) == NULL)
      {
       free(pfunnode->szfunname);
       free(pfunnode->para->next2);
       free(pfunnode->para->next);
       free(pfunnode->para);
       free(pfunnode);
       free(subexprtree);
       destorytree(&root);

       return NULL;
      }
     if ((pfunnode->para->next2->bintreenode = createtree_(ptr, para)) == NULL)
      {
       free(pfunnode->szfunname);
       free(pfunnode->para->next2);
       destorytree(&pfunnode->para->next->bintreenode);
       free(pfunnode->para->next);
       free(pfunnode->para);
       free(pfunnode);
       free(subexprtree);
       destorytree(&root);

       return NULL;
      }

     subexprtree->lchild = NULL;
     subexprtree->mark = BRAC_FUNMARK;
     subexprtree->rchild = (bintree *)pfunnode;
     strcpy(pfunnode->szfunname, "iif");
     pfunnode->para->bintreenode = root;
     pfunnode->para->next3 = NULL;
     root = subexprtree;

     return root;
    }
   else if (**ptr == ':')
    {
     (*ptr)++;
     if (ptrnum != numstr)
      {
       *ptrnum = '\0';
       if (root == NULL)  /* 只有一個數字,常量或變量 */
        {
         if ((root = Alloctree) == NULL)
          return NULL;

         root->op = 0;
         root->mark = 0;
         root->fvalue = (sign) ? -strtodouble(numstr) : strtodouble(numstr);
         root->lchild = NULL;
         root->rchild = NULL;

         return root;
        }

       if (appendnode(&root, op, (sign) ? -strtodouble(numstr) : strtodouble(numstr), 0) == NULL)
        {
         destorytree(&root);

         return NULL;
        }
      }

     return root;
    }
   else if (getoperatorlevel(**ptr))
    {
     if (ptrnum != numstr)
      {
       *ptrnum = '\0';

       if (root == NULL)  /* 開頭的處理 */
        {
         if ((root = Alloctree) == NULL)
          return NULL;

         if (sign == 0)
          {
           root->op = 0;
           root->mark = 0;
           root->fvalue = strtodouble(numstr);
           root->lchild = NULL;
           root->rchild = NULL;
          }
         else
          {
           if ((root->lchild = Alloctree) == NULL)
            {
             free(root);

             return NULL;
            }
           if ((root->rchild = Alloctree) == NULL)
            {
             free(root->lchild);
             free(root);

             return NULL;
            }
           root->op = '-';
           root->mark = 0;
           root->lchild->op = 0;
           root->lchild->mark = 0;
           root->lchild->fvalue = 0;
           root->lchild2 = NULL;
           root->lchild->rchild = NULL;
           root->rchild->op = 0;
           root->rchild->mark = 0;
           root->rchild->fvalue = strtodouble(numstr);
           root->rchild->lchild = NULL;
           root->rchild2 = NULL;
          }
        }
       else if (appendnode(&root, op, strtodouble(numstr), sign) == NULL)
        {
         destorytree(&root);

         return NULL;
        }
       sign = 0;
       ptrnum = numstr;
       op = **ptr;
       (*ptr)++;
      }
     else /* 連續出現運算符 */
      {
       if (root == NULL) /* 字符串最開頭+-的處理 */
        {
         if (**ptr == '-')
          sign = 1 - sign;
        }
       else if (op == 0)
        {
         op = **ptr;
        }
       else if (**ptr == '-')
        {
         sign = 1 - sign;
        }

       (*ptr)++;
      }
    }
   else
    {
     if (**ptr != ' ')
      *ptrnum++ = **ptr;

     (*ptr)++;
    }
  }
 if (ptrnum != numstr)
  {
   *ptrnum = '\0';
   if (root == NULL)  /* 只有一個數字,常量或變量 */
    {
     if ((root = Alloctree) == NULL)
      return NULL;

     root->op = 0;
     root->mark = 0;
     root->fvalue = (sign) ? -strtodouble(numstr) : strtodouble(numstr);
     root->lchild = NULL;
     root->rchild = NULL;

     return root;
    }

   if (appendnode(&root, op, (sign) ? -strtodouble(numstr) : strtodouble(numstr), 0) == NULL)
    {
     destorytree(&root);

     return NULL;
    }
  }

 return root;
}

/*   名稱: createtree
*    功能: 由字符串生成表達式樹
*  返回值: 成功 返回指向生成表達式樹的根節點的指針,失敗 返回 NULL
*    參數: const char *szexpress  指向要生成表達式樹的字符串的常指針
*
*    說明:具體由函數createtree_實現。
*          字符串應先由checkexpress做合法性檢查,否則可能出現不可測結果。
*/
bintree *createtree(const char *szexpress)
{
 const char *ptr = szexpress;
 long para = 0;

 if (szexpress == NULL)
  return NULL;

 return createtree_(&ptr, ¶);
}

/*   名稱: checkexpression
*    功能: 檢查字符串是否爲合法表達式
*  返回值: 合法 返回1,不合法返回 0
*    參數: const char *szexpress  指向要檢查字符串的常指針
*
*    說明:具體由函數checkexpression_實現。
*/
int checkexpression(const char *szexpress)
{
 const char *ptr = szexpress;
 long para = 0;

 if (szexpress == NULL)
  return 0;

 return checkexpression_(&ptr, 0, ¶);
}

/*   名稱: checkexpression_
*    功能: 檢查字符串是否爲合法表達式
*  返回值: 合法 返回1,不合法返回 0
*    參數: const char **szexpress  指向要檢查字符串的二級常指針
*          int colon  用於處理問號運算符,第二段爲1,非第二段爲0?
*          long *para 用於處理函數參數
*
*    說明:不直接使用由函數checkexpression調用,是爲了遍歷處理括號。
*/
int checkexpression_(const char **szexpress, int colon, long *para)
{
 register const char **ptr = szexpress;
 char op = 0;
 char nospace = 0;                   /* 用於輸入錯誤空格檢查 */
 char numstr[MAXBUFFERLEN] = {"0"};  /* 保存數字,變量名,函數名的緩衝區 */
 char *ptrnum = numstr;
 int crteatetree = 0;

 while(**ptr)
  {
   if (nospace && ptrnum != numstr)  /* 先處理科學計數指數部分+- */
    {
     if (*(ptrnum - 1) == 'e' || *(ptrnum - 1) == 'E')  /* 可能是變量名 */
      {
       if (**ptr == '+' || **ptr == '-')
        {
         *ptrnum = '\0';
         if (!(isconstant(numstr, NULL) || isvariable(numstr, NULL)))
          {
           *ptrnum++ = **ptr;

           (*ptr)++;
           continue;
          }
        }
      }
    }
   if (**ptr == '(')
    {
     long paracount = 0;

     if (crteatetree && op == 0)
      return 0;

     (*ptr)++;
     if (ptrnum != numstr)  /* 此處是函數,numstr是函數名 */
      {
       vfunptr funp;
       long n;  /* 用於記錄處理過的函數參數個數比如iiif的 */

       *ptrnum = '\0';
       if ((paracount = getfunptr(numstr, &funp)) == 0)  /* 檢查函數名 */
        return 0;

       n = 0;
       while(paracount)  /* 檢查函數參數 */
        {
         if ((crteatetree = checkexpression_(ptr, 0, ¶count)) == 0)
          return 0;

         n++;
        }
       if (strcmp(numstr, "iiif") == 0)  /* iiif至少必須有兩個參數 */
        {
         if (n < 2)
          return 0;
        }
      }
     else
      {
       if ((crteatetree = checkexpression_(ptr, 0, ¶count)) == 0)
        return 0;
      }

     op = 0;
     ptrnum = numstr;
     nospace = 0;
    }
   else if (**ptr == ')' || **ptr == ',')  /* ,用於分割函數參數 */
    {
     if (crteatetree == 0 && ptrnum == numstr)  /* 空括號報錯 */
      return 0;

     if (colon)
      return 0;

     if (**ptr == ',')
      {
       if (*para > 1)
        (*para)--;
       else if (*para != -1)
        return 0;
      }
     else
      {
       if (*para > 1)
        return 0;

       if (*para == 1 || *para == -1)
        *para = 0;
      }

     if (ptrnum != numstr)
      {
       *ptrnum = '\0';
       if (crteatetree == 0)  /* 只有一個數字 */
        {
         (*ptr)++;
         return islegaldoublenum(numstr) || isconstant(numstr, NULL) || isvariable(numstr, NULL);
        }
       else if (op == 0)
        return 0;

       crteatetree = islegaldoublenum(numstr) || isconstant(numstr, NULL) || isvariable(numstr, NULL);
      }
     else if (op)
      return 0;

     (*ptr)++;

     return crteatetree;
    }
   else if (**ptr == '?')
    {
     if (crteatetree == 0 && ptrnum == numstr)  /* 空串報錯 */
      return 0;

     if (ptrnum != numstr)
      {
       *ptrnum = '\0';
       if (crteatetree == 0)  /* 只有一個數字 */
        {
         if ((crteatetree = islegaldoublenum(numstr) || isconstant(numstr, NULL) || isvariable(numstr, NULL)) == 0)
          return 0;
        }
       else if (op == 0)
        return 0;

       if ((crteatetree = islegaldoublenum(numstr) || isconstant(numstr, NULL) || isvariable(numstr, NULL)) == 0)
        return 0;
      }
     else if (op)
      return 0;

     (*ptr)++;

     if ((crteatetree = checkexpression_(ptr, 1, para)) == 0)
      return 0;

     crteatetree = 0;
     op = 0;
     ptrnum = numstr;
     nospace = 0;
    }
   else if (**ptr == ':')
    {
     if (!colon)
      return 0;

     if (crteatetree == 0 && ptrnum == numstr)  /* 空串報錯 */
      return 0;

     if (ptrnum != numstr)
      {
       *ptrnum = '\0';
       if (crteatetree == 0)  /* 只有一個數字 */
        {
         if ((crteatetree = islegaldoublenum(numstr) || isconstant(numstr, NULL) || isvariable(numstr, NULL)) == 0)
          return 0;
        }
       else if (op == 0)
        return 0;

       if ((crteatetree = islegaldoublenum(numstr) || isconstant(numstr, NULL) || isvariable(numstr, NULL)) == 0)
        return 0;
      }
     else if (op)
      return 0;

     (*ptr)++;

     return crteatetree;
    }
   else if (getoperatorlevel(**ptr))
    {
     nospace = 0;
     if (ptrnum != numstr)
      {
       if (crteatetree && op == 0)
        return 0;

       *ptrnum = '\0';
       if ((crteatetree = (islegaldoublenum(numstr) || isconstant(numstr, NULL) || isvariable(numstr, NULL))) == 0)
        return 0;

       ptrnum = numstr;
       op = **ptr;
       (*ptr)++;
      }
     else  /* 連續出現運算符 */
      {
       if (crteatetree == 0)    /* 字符串最開頭+-的處理 */
        {
         if (**ptr == '-')
          ;                     /* sign = 1 - sign */
         else if (**ptr != '+') /* +-以外的運算符報錯 */
          return 0;             /* printf("err\n"); */
        }
       else if (op == 0)
        op = **ptr;
       else if (**ptr == '-')
        ;                       /* sign = 1 - sign */
       else if (**ptr != '+')   /* +-以外的運算符報錯 */
        return 0;               /* printf("err\n"); */

       (*ptr)++;
      }
    }
   else
    {
     if (**ptr == ' ')
      nospace = 0;
     else
      {
       if (ptrnum != numstr)
        {
         if (nospace == 0)  /* 錯誤空格 */
          return 0;         /* printf("err\n"); */
        }
       *ptrnum++ = **ptr;
       nospace = 1;
      }

     (*ptr)++;
    }
  }
 if (colon)
  return 0;

 if (ptrnum != numstr)
  {
   if (crteatetree && op == 0)
    return 0;

   *ptrnum = '\0';
   crteatetree = islegaldoublenum(numstr) || isconstant(numstr, NULL) || isvariable(numstr, NULL);
  }
 else if (op)
  return 0;

 return crteatetree;
}


 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章