Last active
December 21, 2015 00:19
-
-
Save chengluyu/6219251 to your computer and use it in GitHub Desktop.
Calculator
This file contains 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; | |
} |
还应该加入除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
加入了错误显示。还有对
6-+-(67^5)
这样表达式的支持。