Last active
December 21, 2015 00:19
-
-
Save chengluyu/6219251 to your computer and use it in GitHub Desktop.
Calculator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <stdexcept> | |
#include <string> | |
#include <sstream> | |
#include <cmath> | |
using namespace std; | |
class parse_error : exception { | |
string msg; | |
public: | |
parse_error(const char * str) : msg(str) { } | |
virtual ~parse_error() throw () { } | |
virtual const char * what() const throw () { | |
return msg.c_str(); | |
} | |
}; | |
void error(const char * info) { | |
throw parse_error(info); | |
} | |
double T(istream & in); | |
double S(istream & in) { | |
double val = T(in); | |
while (in.peek() == '-' || in.peek() == '+') | |
if (in.get() == '+') | |
val += T(in); | |
else | |
val -= T(in); | |
return val; | |
} | |
double V(istream & in) { | |
double val; | |
bool negative = false; | |
while (in.peek() == '-' || in.peek() == '+') | |
negative ^= in.get() == '-'; | |
if (in.peek() == '(') { | |
in.get(); | |
val = S(in); | |
if (in.get() != ')') | |
error("Bracket doesn't match."); | |
} else { | |
if (!isdigit(in.peek())) | |
error("Missing a operand."); | |
in >> val; | |
} | |
return negative ? -val : val; | |
} | |
double U(istream & in) { | |
double val = V(in), index, result; | |
if (in.peek() == '^') { | |
in.get(); | |
index = U(in); | |
result = pow(val, index); | |
} else | |
result = val; | |
return result; | |
} | |
double T(istream & in) { | |
double val = U(in); | |
while (in.peek() == '*' || in.peek() == '/') | |
if (in.get() == '*') | |
val *= U(in); | |
else | |
val /= U(in); | |
return val; | |
} | |
int main(int argc, const char *argv[]) { | |
// istringstream in("1.2+(9.6^2.5---3+9*9)"); | |
istream & in = cin; | |
try { | |
cout << S(in) << endl; | |
} catch (parse_error e) { | |
cerr << e.what() << endl; | |
} | |
return 0; | |
} |
使用自己的算式,注释第67行
,取消注释第66行
。
反之,使用输入流,注释第66行
,取消注释第67行
。
另附:未添加错误处理,程序会读到第一个非算式字符(非
0123456789./*-+^()
的字符)终止。
negative ^= in.get() == '-';
怎么不用 in.get() == '-' && negative = true
我一元正负号规则搞错了? -_-
规则应该是是这样的吧:
+-3=-3
++3=3
--3=3
-+3=-3
和异或的规则一样:
true ^ false == true
false ^ true == true
true ^ true == false
false ^ false == false
所以用异或。
我对bool的类型了解不是很深入。昨天看了下,原来bool类型只有true和false。这样也是可以的。我原本以为bool类型可能有别的值,意思是用&&的条件短路来做。
其实用bool
类型就行了,没必要
typedef int BOOL;
。
BOOL在微软的定义中是会返回3个值的,0,1,-1。
微软的奇葩定义……一直觉得微软的东西还是封装一下比较好。
加入了错误显示。还有对6-+-(67^5)
这样表达式的支持。
还应该加入除0错误的提示
rule<phrase_scanner_t> factor, term, exp;
factor = real_p | ('(' >> exp >> ')'); // real_p | !(ch_p('+')|ch_p('-')) >> ('(' >> exp >> ')') 注释部分是带正负号的规则
term = factor >> *(('*' >> factor) | ('/' >> factor));
exp = term >> *(('+' >> term) | ('-' >> term));
const char *szExp = "(2+3)";
parse_info<> rule = parse( szExp , exp, space_p);
cout << "parse " << (rule.full?"success":"fail") << endl;
我在网上找到的用boost::spirit对四则运算的验证,后面注释是我改写的可以在括号前面带正负号规则验证。
这倒不错,spirit十分方便,直接写cfg就行了,不过一直嫌boost配置太麻烦。
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
计算器,支持+-*/^()。