1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
|
#include <iostream>
#include <sstream>
#include <string>
bool isValidValue(double val) {
return (val > 0.0);
}
bool isValidOp(char op) {
static const std::string allowed_ops = "+-/*%^";
return allowed_ops.npos != allowed_ops.find(op);
}
bool processLine(const std::string& line);
void test_processLine();
int main() {
bool running = true;
do {
std::cout << "Enter simple arithmetic expression or 'exit' to end program\n";
std::cout << ">";
std::string line;
std::getline(std::cin, line);
// really need to trim leading and trailing spaces...
if(line == "exit") {
running = false;
} else if(line == "test") {
test_processLine();
} else {
processLine(line);
}
} while(running);
return 0;
}
bool processLine(const std::string& line) {
bool result = false;
std::istringstream iss(line);
double lhs = 0.0;
double rhs = 0.0;
char op = '\0';
char dummy = '\0';
if ( !(iss >> lhs >> op >> rhs) // get what we want
|| (iss >> std::ws && iss.get(dummy)) // try to get more if got it ok
|| !isValidOp(op) // check results
|| !isValidValue(lhs)
|| !isValidValue(rhs) ) {
std::cout << "parse failed!\n";
} else {
std::cout << "parse succeeded:\n"
<< "lhs = " << lhs << "\n"
<< "rhs = " << rhs << "\n"
<< "op = " << op << "\n";
result = true ;
}
return result;
}
void test_processLine() {
struct TestCase {
const char* line;
bool expectedResult;
};
static const TestCase testCases[] = {
// pass cases
{"1.0+2.0", true},
{"1.0-2.0", true},
{"1.0*2.0", true},
{"1.0/2.0", true},
{"1.0%2.0", true},
{"1.0^2.0", true},
{"1.0 + 2.0", true},
{"1.0 - 2.0", true},
{"1.0 * 2.0", true},
{"1.0 / 2.0", true},
{"1.0 % 2.0", true},
{"1.0 ^ 2.0", true},
// fail cases
{"0.0 + 2.0", false},
{"1.0 + 0.0", false},
{"-1.0 + 2.0", false},
{"1.0 + -2.0", false},
{"1.0 + penguin", false},
{"penguin + 2.0", false},
{"1.0 @ 2.0", false},
{"1.0 plus 2.0", false},
{"1.0 + 2.0 penguins", false},
{"1.0 2.0", false},
{"1.0 +", false},
{"+ 2.0", false},
{"1.0", false},
{"+", false},
{"@", false},
{"penguin", false},
// etc
};
static const int count = sizeof(testCases)/sizeof(testCases[0]);
int passed = 0;
for(int i = 0 ; i < count; ++i) {
const TestCase& tc = testCases[i];
std::cout << "test case #" << (i + 1) << " : \"" << tc.line << "\"\n";
bool result = processLine(tc.line);
if(result == tc.expectedResult) {
++passed;
std::cout << "pass\n";
} else {
std::cout << "fail\n";
}
}
std::cout << "\n";
std::cout << "Passed " << passed << " out of " << count << "\n";
}
|