作者在 2011-04-17 16:46:15 发布以下内容
#include<iostream>
#include<string>
using namespace std;
class Computer
{
double result;//保存运算结果
int index; //保存expr的下标,index只会增大或者不变,不可能减少
string expr; //保存表达示
int paren; /*'(' paren加1,')'paren减1。一旦paren为负时就肯定是输入有错,运算全部结束后其值不为零也是出错。可以增加一个小类来做为paren的类型*/
protected:
char getSign();//获取运算符号
double getDouble();//提取一个整数,供下面两个函数调用
double getLeftV(bool);//bool这个参数的作用是用来说明获取的操作数能不能马上返回
double getRightV(bool);
double comput(double lv);//计算的核心函数
public:
operator double()
{
return result;
}
Computer(const std::string);
};
Computer::Computer(const std::string str):expr(str),result(0),index(0),paren(0)
{
result = comput(getLeftV(true));
}
//每遇到一个左括号都会当成一个新的表达示来调用comput(double),所以在comput(double)里不用考虑括号的情况
double Computer::comput(double lv)
{
while(index < expr.size())//控制运行
{
char sign = expr[index++];//获取运算符号
switch(sign)
{
case '-':
return comput(lv - getRightV(false));
case '+':
return comput(lv + getRightV(false));
case '*':
return comput(lv * getRightV(true));//设置成true是因为乘除的优先级高,可以马上获取右操作数
case '/':
{
double rv = getRightV(true);
if(rv)
return comput(lv / rv);
else
;//出错处理
}
default:
;
//错误处理
}
}
return lv;
}
double Computer::getDouble()
{
double r = 0;
char ch;
while(isdigit(ch = expr[index]))/*这里不使用atoi(const char*)是考虑到通过r 的长度来获取消耗字符的数量不一定准确*/
{
index++;
r *= 10;
r += ch-'0';
}
if(ch == '.')
{
int i = index;
double r2 = 0;
while(isdigit(ch = expr[i]))
{
r2 *= 10;
r2 += ch-'0';
++i;
}
if(i-index >1)//防止r2除0
{
r += r2/(10*(i-index-1));
}
index = i;//更新
}
return r;
}
double Computer::getLeftV(bool t)
{//判断下index的值是否合法,代码会更健壮
char c = expr[index];
if(c == '-')//处理负数和取反的代码
{
++index;
return -getLeftV(true);//通过传递参数true让getLeftV()尽可能快的返回它获取的值
}
if(c == '(')
{
++index;
paren++;//括号的处理
return comput(getLeftV(true));//调用comput()是把括号里的表达看成一个新的表达示。
}
if(isdigit(c))
{
double lv = getDouble();
char sign = expr[index];//获取操作数后面紧跟着的运算符号
if(t || sign==')' || sign=='-' || sign=='+')//t就是传递进来的bool参数
{
if(sign==')'){
--paren;//维护paren的值
++index;//跳过右括号
}
return lv;
}
else
{
return comput(lv);//否则就把获取的值当成新的表达示的第一个操作数。
}
}
//进入这里的都是出错的情况
}
double Computer::getRightV(bool t)//参看getLeftV(bool)
{
return getLeftV(t);
#include<string>
using namespace std;
class Computer
{
double result;//保存运算结果
int index; //保存expr的下标,index只会增大或者不变,不可能减少
string expr; //保存表达示
int paren; /*'(' paren加1,')'paren减1。一旦paren为负时就肯定是输入有错,运算全部结束后其值不为零也是出错。可以增加一个小类来做为paren的类型*/
protected:
char getSign();//获取运算符号
double getDouble();//提取一个整数,供下面两个函数调用
double getLeftV(bool);//bool这个参数的作用是用来说明获取的操作数能不能马上返回
double getRightV(bool);
double comput(double lv);//计算的核心函数
public:
operator double()
{
return result;
}
Computer(const std::string);
};
Computer::Computer(const std::string str):expr(str),result(0),index(0),paren(0)
{
result = comput(getLeftV(true));
}
//每遇到一个左括号都会当成一个新的表达示来调用comput(double),所以在comput(double)里不用考虑括号的情况
double Computer::comput(double lv)
{
while(index < expr.size())//控制运行
{
char sign = expr[index++];//获取运算符号
switch(sign)
{
case '-':
return comput(lv - getRightV(false));
case '+':
return comput(lv + getRightV(false));
case '*':
return comput(lv * getRightV(true));//设置成true是因为乘除的优先级高,可以马上获取右操作数
case '/':
{
double rv = getRightV(true);
if(rv)
return comput(lv / rv);
else
;//出错处理
}
default:
;
//错误处理
}
}
return lv;
}
double Computer::getDouble()
{
double r = 0;
char ch;
while(isdigit(ch = expr[index]))/*这里不使用atoi(const char*)是考虑到通过r 的长度来获取消耗字符的数量不一定准确*/
{
index++;
r *= 10;
r += ch-'0';
}
if(ch == '.')
{
int i = index;
double r2 = 0;
while(isdigit(ch = expr[i]))
{
r2 *= 10;
r2 += ch-'0';
++i;
}
if(i-index >1)//防止r2除0
{
r += r2/(10*(i-index-1));
}
index = i;//更新
}
return r;
}
double Computer::getLeftV(bool t)
{//判断下index的值是否合法,代码会更健壮
char c = expr[index];
if(c == '-')//处理负数和取反的代码
{
++index;
return -getLeftV(true);//通过传递参数true让getLeftV()尽可能快的返回它获取的值
}
if(c == '(')
{
++index;
paren++;//括号的处理
return comput(getLeftV(true));//调用comput()是把括号里的表达看成一个新的表达示。
}
if(isdigit(c))
{
double lv = getDouble();
char sign = expr[index];//获取操作数后面紧跟着的运算符号
if(t || sign==')' || sign=='-' || sign=='+')//t就是传递进来的bool参数
{
if(sign==')'){
--paren;//维护paren的值
++index;//跳过右括号
}
return lv;
}
else
{
return comput(lv);//否则就把获取的值当成新的表达示的第一个操作数。
}
}
//进入这里的都是出错的情况
}
double Computer::getRightV(bool t)//参看getLeftV(bool)
{
return getLeftV(t);
}
int main()
{
string str;
cin >> str;
cout << Computer(str) <<endl;
return 0;
}
int main()
{
string str;
cin >> str;
cout << Computer(str) <<endl;
return 0;
}