工作中使用到的一份代码,用于计算全数字的公式。代码没有完全写完,比如公式合法性检查部分。
另外,如果是大量公式计算,可以考虑将内存分配修改为内存池,会省去N多系统调用。
可以根据自己需要进行优化。本人只当做个备份。
// 带括号的加减乘除算式计算
// 许建强
// cc - calculate.c
/*
#TODO
1、增加节点池,减少 malloc 调用
2、修改公式检测函数,增加检测条目
*/
#include “unistd.h”
#include “stdlib.h”
#include “string.h”
#include <stdio.h>
// 算式节点
typedef struct node
{
struct node *left;
struct node *right;
double value;
}
tagExpreNode;
int valid( const char *pExpre );
int priority(char c);
int push(char c);
int isLeaf( tagExpreNode *pExpreNode );
int erase(tagExpreNode *pExpreNode);
double c(tagExpreNode *pExpreNode);
// 优先级
int priority(char c)
{
if( (‘ ' == c) || ('-' == c) )
{
return 1;
}
if( ('*' == c) || ('/' == c) )
{
return 2;
}
return -1;
};
// 括号栈 用于匹配括号
int push(char c)
{
static char parenthesis[32] = {0};
static char top = 0;
if( 0 == top )
{
parenthesis[top ] = c;
return top;
}
parenthesis[top ] = c;
if( ’(‘ == parenthesis[top - 2] && ’)‘ == parenthesis[top - 1] )
{
top -= 2;
}
return top;
};
// 判断是否为叶节点
int isLeaf( tagExpreNode *pExpreNode )
{
return pExpreNode->left == pExpreNode->right;
};
// 释放二叉树资源
int erase(tagExpreNode *pExpreNode)
{
if( NULL != pExpreNode )
{
erase(pExpreNode->left);
erase(pExpreNode->right);
free(pExpreNode);
}
return 0;
};
// 计算二叉树的值
double c(tagExpreNode *pExpreNode)
{
if( isLeaf(pExpreNode) )
{
return pExpreNode->value;
}
switch( (int)pExpreNode->value )
{
case (int)' ':
return c(pExpreNode->left) c(pExpreNode->right);
case (int)'-':
return c(pExpreNode->left) - c(pExpreNode->right);
case (int)'*':
return c(pExpreNode->left) * c(pExpreNode->right);
case (int)'/':
return c(pExpreNode->left) / c(pExpreNode->right);
default:
printf(“[%s:%d] error.\n” , __FILE__ , __LINE__);
}
return 0;
};
// 检查算式是否合法
int valid( const char *pExpre )
{
// 括号是否匹配
char *pleft = strchr(pExpre , ’(‘);
if( NULL == pleft )
{
if( NULL == strchr(pExpre , ’)‘) )
return 1;
return 0;
}
int ret = 0;
while ( '\0' != *pleft )
{
if( ’(‘ == *pleft || ’)‘ == *pleft )
ret = push(*pleft);
pleft ;
}
return (0 == ret) 1 : 0 ;
// #TODO
// 是否有两个连续运算符
// 头一个字符是否是运算符
// 是否全是数字
// 是否包含非法字符 合法字符 0-9. -*/()
};
// 根据算式生成二叉树
int generateTree(tagExpreNode **pExpreNode , const char *pExpresion)
{
char number[32] = {0};
int index = 0;
tagExpreNode *pCurNode = NULL;
int bOper = 0;
while( '\0' != *pExpresion )
{
if( (' ' != *pExpresion) && ('-' != *pExpresion) && ('*' != *pExpresion) && ('/' != *pExpresion) )
{
number[index ] = *pExpresion;
number[index] = 0;
}
else // 找到一个运算符
{
if( !number[0] ) // 此运算符为符号位
{
number[index ] = *pExpresion;
number[index] = 0;
}
else
{
tagExpreNode *pNodeOper = (tagExpreNode *)malloc( sizeof(tagExpreNode) );
memset( pNodeOper , 0 , sizeof(tagExpreNode) );
tagExpreNode *pNodeValue = (tagExpreNode *)malloc( sizeof(tagExpreNode) );
memset( pNodeValue , 0 , sizeof(tagExpreNode) );
if( !number[0] )
{
printf(“[%s:%d] number is null , opr [%c].\n” , __FILE__ , __LINE__ , *pExpresion);
exit(-1);
}
pNodeValue->value = atof(number);
pNodeOper->value = *pExpresion;
if( NULL == pCurNode )
{