算术表达式可以使用中缀表达式和后缀表达式(逆波兰表达式)计算,以下分别实现这两个方法,以下实现方法可以在算术表达式中包含部分函数,如三角函数sin等。
由于普通的算术操作符(如“+-*/”)只包含一个字符,而函数会包含多个字符,为了方便先将函数用一个FunctionId的枚举替代,该枚举从1开始,算术表达式一般为明文字符串,这些枚举数只要使用20以下的数字就不会发生冲突,只是打印出来会是乱码,计算不会受影响。
enum FunctionId
{
None = 0,
Sin = 1,
Cos = 2,
Tan = 3,
Cot = 4,
FunctionMax,
};
然后定义函数和运算符的结构FunctionInfo和OperatorInfo,以及一些全局变量和方法。
struct FunctionInfo
{
FunctionId funcId;
char funcStr[10];//函数名,如"sin"
int bytesOfStr;//函数名字节数,如"sin"为3字节
FunctionInfo(FunctionId InFuncId, const char* InFuncStr, int InBytes = 0)
{
funcId = InFuncId;
memset(funcStr, 0, 10);
bytesOfStr = InBytes > 0 ? InBytes : strlen(InFuncStr);
memcpy(funcStr, InFuncStr, bytesOfStr);
}
static FunctionInfo None;
};
FunctionInfo FunctionInfo::None = FunctionInfo(FunctionId::None, "", 0);
FunctionInfo g_functionInfos[] =
{
FunctionInfo(FunctionId::Sin, "sin", 3),
FunctionInfo(FunctionId::Cos, "cos", 3),
FunctionInfo(FunctionId::Tan, "tan", 3),
FunctionInfo(FunctionId::Cot, "cot", 3),
FunctionInfo::None
};
//判断是否是函数
FunctionInfo GetFunctionInfo(const char* InExp)
{
for (int i = 0; i < FunctionId::FunctionMax; i++)
{
if (g_functionInfos->funcId == FunctionId::None)
{
return FunctionInfo::None;
}
if (memcmp(InExp, g_functionInfos[i].funcStr, g_functionInfos[i].bytesOfStr) == 0)
{
return g_functionInfos[i];
}
}
return FunctionInfo::None;
}
struct OperatorInfo
{
char ch;//运算符
int priority;//优先级
OperatorInfo(char InChar, int InPriority)
{
ch = InChar;
priority = InPriority;
}
};
OperatorInfo g_operatorInfos[] =
{
OperatorInfo('(', 0),
OperatorInfo(')', 0),
OperatorInfo('+', 1),
OperatorInfo('-', 1),
OperatorInfo('*', 2),
OperatorInfo('/', 2),
OperatorInfo('%', 2),
OperatorInfo('^', 3),
OperatorInfo('\0', -1)
};
//判断是否为操作符
bool IsOperator(char c)
{
for (int i = 0;; i++)
{
if (g_operatorInfos[i].ch