万用计算器函数,接受数学算式字符串为参数——考虑运算顺序、可无限嵌套括号、支持加、减、乘、除、乘方运算!
使用方法:long SzCal(const char* const sz), 其中sz为算式,如"15+6" "589*78"等。乘方符号为^, 如2的16次方表示为"2^16"。返回值为运算结果。例: long lResult = SzCal("(1*(5-6)+4)^3"); // lResult == 27
代码如下(头文件<cmath>):
由于是以字符串为参数,所以无论是console还是windows程序都能使用,只是一些console标准流的输出在windows程序中需稍稍修改(如cerr改为MessageBox)。
需声明using namespace std;
const long SzCal(const char* const sz)
{
int i = 0;
return SzCal(sz, i);
}
const long SzCal(const char* const sz, int& i)
{
long n1 = 0, n2 = 0;
char szTemp[500] = {0};
int j = 0, k = 0;
char op = 0;
if (sz[i] == '(') // 若是左括号,则递归处理,并将括号值付给操作数1
{
i++;
n1 = SzCal(sz, i);
}
else
{
for (j = 0; isdigit(sz[i]); i++, j++) // 读入操作数1
szTemp[j] = sz[i];
szTemp[j] = '\0';
n1 = atol(szTemp);
}
while (sz[i] != '\0' && sz[i] != ')')
{
op = sz[i]; // 获取运算符
i++;
if (sz[i] == '(') // 若是左括号,则递归处理,并将括号值付给操作数2
{
i++;
n2 = SzCal(sz, i);
}
else
{
for (j = 0; isdigit(sz[i]); i++, j++) // 读入操作数2
szTemp[j] = sz[i];
szTemp[j] = '\0';
n2 = atol(szTemp);
}
switch (op) // 运算
{
case '+':
DoAdd(sz, i, n1, n2);
break;
case '-':
DoSubtract(sz, i, n1, n2);
break;
case '*':
DoMultiply(sz, i, n1, n2);
break;
case '/':
DoDivide(sz, i, n1, n2);
break;
case '%':
DoMod(sz, i, n1, n2);
break;
case '^':
n1=pow((double)n1, (double)n2);
break;
default:
cerr << "\aError: Operator error \n";
exit(1);
}
}
i += sz[i] == ')' ? 1 : 0; // 跳过右括号
return n1;
}
void DoMultiply(const char* const sz, int& i, long& n1, long& n2)
{
long n3 = 0;
int j = 0;
char op = 0;
char szTemp[500] = {0};
if (sz[i] == '^') // ^的优先级更高
{
op = sz[i];
while (op == '^')
{
i++;
if (sz[i] == '(')
n3 = SzCal(sz, i);
else
{
for (j=0; isdigit(sz[i]); i++, j++)
szTemp[j] = sz[i];
szTemp[j] = '\0';
n3 = atol(szTemp);
}
n2 = pow((double)n2, (int)n3);
op = sz[i];
}
n1 *= n2;
}
else
n1 *= n2;
}
void DoDivide(const char* const sz,int& i, long& n1, long& n2)
{
long n3 = 0;
int j = 0;
char op = 0;
char szTemp[500] = {0};
if (sz[i] == '^') // ^的优先级更高
{
op = sz[i];
while (op == '^')
{
i++;
if (sz[i] == '(')
n3 = SzCal(sz, i);
else
{
for (j = 0; isdigit(sz[i]); i++, j++)
szTemp[j] = sz[i];
szTemp[j] = '\0';
n3 = atol(szTemp);
}
n2 = pow((double)n2, (int)n3);
op = sz[i];
}
if (n2 == 0)
{
cerr << "\aError: Divided error \n";
exit(1);
}
n1 /= n2;
}
else
{
if (n2 == 0)
{
cerr << "\aError: Divided error \n";
exit(1);
}
n1 /= n2;
}
}
void DoAdd(const char* const sz, int& i, long& n1, long& n2)
{
long n3 = 0;
int j = 0;
char op = 0;
char szTemp[500] = {0};
if (sz[i] == '*' || sz[i] == '/' || sz[i] == '%' || sz[i] == '^')
{
op = sz[i];
while (sz[i] == '*' || sz[i] == '/' || sz[i] == '%' || sz[i] == '^')
{
i++;
if (sz[i] == '(')
n3 = SzCal(sz, i);
else
{
for (j = 0; isdigit(sz[i]); i++, j++)
szTemp[j] = sz[i];
szTemp[j] = '\0';
n3 = atol(szTemp);
}
switch (op)
{
case '*':
DoMultiply(sz, i, n2, n3);
break;
case '/':
DoDivide(sz, i, n2, n3);
break;
case '%':
DoMod(sz, i, n2, n3);
break;
case '^':
n2 = pow((double)n2, (int)n3);
break;
}
op = sz[i];
}
n1 += n2;
}
else
n1 += n2;
}
void DoSubtract(const char* const sz, int& i, long& n1, long& n2)
{
long n3 = 0;
int j = 0;
char op = 0;
char szTemp[500] = {0};
if (sz[i] == '*' || sz[i] == '/' || sz[i] == '%' || sz[i] == '^')
{
op = sz[i];
while (sz[i] == '*' || sz[i] == '/' || sz[i] == '%' || sz[i] == '^')
{
i++;
if (sz[i] == '(')
n3 = SzCal(sz, i);
else
{
for (j = 0; isdigit(sz[i]); i++, j++)
szTemp[j] = sz[i];
szTemp[j] = '\0';
n3 = atol(szTemp);
}
switch (op)
{
case '*':
DoMultiply(sz, i, n2, n3);
break;
case '/':
DoDivide(sz, i, n2, n3);
break;
case '%':
DoMod(sz, i, n2, n3);
break;
case '^':
n2 = pow((double)n2, (int)n3);
break;
}
op = sz[i];
}
n1 -= n2;
}
else
n1 -= n2;
}
void DoMod(const char* const sz, int& i, long& n1, long& n2)
{
long n3 = 0;
int j = 0;
char op = 0;
char szTemp[500] = {0};
if (sz[i] == '^') // ^的优先级更高
{
op = sz[i];
while (op == '^')
{
i++;
if (sz[i] == '(')
n3 = SzCal(sz, i);
else
{
for (j = 0; isdigit(sz[i]); i++, j++)
szTemp[j] = sz[i];
szTemp[j] = '\0';
n3 = atol(szTemp);
}
n2 = pow((double)n2, (int)n3);
op = sz[i];
}
if (n2 == 0)
{
cerr << "\aError: Divided error \n";
exit(1);
}
n1 %= n2;
}
else
{
if (n2 == 0)
{
cerr << "\aError: Mod error \n";
exit(1);
}
n1 %= n2;
}
}