第六次作业
假期有事,实在没时间,这两天熬夜补出来
toget函数,用来将两个整书数组和符号数组汇集
void equation::toget() {
strcpy_s(eq, n);
int y = 0;
while (m[y] != 0) y++;
len = strlen(eq) + y;
for (int i = 0;i<len;i++)
{
if (i == 0 && eq[i] != '(')
{
for (int j = len - 1;j >= 0;j--)
{
eq[j + 1] = eq[j];
}
eq[i] = '|';
len++;
}
if ((eq[i] == '(' || eq[i] == '+') || eq[i] == '-' || eq[i] == '*' || eq[i] == '/')
{
if (eq[i + 1] != '(')
{
for (int j = len - 1;j>i;j--)
{
eq[j + 1] = eq[j];
}
eq[i + 1] = '|';
len++;
}
}
}
}
用栈计算:
主要代码:
double equation::result()//读取并计算表达式直到结束为止
{
do
{
readdata();
} while (readop());
calremain(); //处理栈中剩余的运算符
return v;
}
void equation::readdata() //在该出现数据的时候可能出现'('
{
// 如1+((2*3)) 左括号可能是多个
while (1) //读取数据失败,此时读取应该是'(',而v为double类型
{
op = eq[cnt1];
if ( op == '|')
{
cnt1++;
v = m[cnt2++];
break;
}
ops.push(op); //左括号入栈
cnt1++;
}
ds.push(v);
}
bool equation::readop() //读取运算符,可能出现右括号或者换行符(表达式结束)
{
//如(2*(3+4/(4-5))),右括号可能是多个
while (1)
{
op = eq[cnt1++];
if (op != ')') break;
while (ops.top() != '(')
{
rh = ds.top(); //取左操作数
ds.pop();
lh = ds.top();//取右操作数
ds.pop();
ds.push(cal(lh, ops.top(), rh)); //计算并入栈
ops.pop(); //取走运算符
}
ops.pop(); //丢弃'('
}
if (op == '=')
{
return false;
}
if (strchr("+-*/", op) == NULL) //无效运算符
{
throw string("无效运算符") + op;
}
while (!ops.empty() && ops.top() != '(' && !prior(op, ops.top()))
{
rh = ds.top(); ds.pop();
lh = ds.top(); ds.pop();
ds.push(cal(lh, ops.top(), rh)); //计算并入栈
ops.pop(); //取走运算符
}
ops.push(op);
return true;
}
void equation::calremain()
{
while (!ops.empty())
{
rh = ds.top(); ds.pop();
lh = ds.top(); ds.pop();
ds.push(cal(lh, ops.top(), rh)); //计算并入栈
ops.pop(); //取走运算符
}
if (ds.size() != 1)
{
throw string("无效的表达式");
}
v = ds.top();
ds.pop();
return;
}
double equation::cal(double lh, char op, double rh)
{
return op == '+' ? lh + rh : op == '-' ? lh - rh : op == '*' ? lh*rh : lh / rh;
}
bool equation::prior(char o1, char o2)//若o1比o2优先级高返回true,否则返回false
{
return o1 != '+' && o1 != '-' && o2 != '*' && o2 != '/';
}
运行截图
感想
赶出来的,有点累,理解起来有点难,不过我还是尽努力理解,并将计算方法和算输出联系起来。