二叉樹計算中綴表達式,支持科學計數法,支持前導正負號,支持指數運算符“^”,支持括號,支持函數,具有錯誤檢查。以字符串形式輸入。
#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;
}