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
|
#include <exception>
#include <iostream>
#include <limits>
#include <string>
#include <optional>
#include <utility>
#include <vector>
std::optional<double> stodNoExcept(const std::string& s);
std::optional<double> getGradient(const std::string& s);
void waitForEnter();
const std::vector<std::string> errs {
{ "Equal symbol missing: badly formed equation rejected.\n" }, // 0
{ "Two 'x' parameters detected: badly formed equation rejected.\n" }, // 1
{ "Two '+' symbols detected: badly formed equation rejected.\n" }, // 2
{ "Cannot recognize y-intercept term.\nEquation should be in the form "
"y = mx + b.\nPlease retry.\n" }, // 3
{ "Cannot extract gradient.\nEquation should be in the form "
"y = mx + b.\nPlease retry.\n" }, // 4
};
int main()
{
// y = mx + b
// --> m b
std::pair<double, double> par;
bool again { true };
do {
par = { 0.0, 0.0 };
std::cout << "Please enter equation (ex. y = mx + b): ";
std::string line;
std::getline(std::cin, line);
// Method: check for y = mx + b, y = mx (b==0), y = b (m==0).
// Don't check for mx + b = y, so if input "4 = y", then
// the equation is ill-formed and rejected.
// Discard up to '=' included.
std::string::size_type ps = line.find('=');
if(ps == std::string::npos) { std::cout << errs.at(0); continue; }
line = line.substr(ps+1);
// "line" could be: "mx + b", "mx", "b" or "y".
// Search for '+' and 'x' (there should be only one of each of them).
// 1) if both
// if '+' comes first, than "b + mx" otherwise "mx + b".
// 2) if 'x', than "mx" or "xm", otherwise "b" or "y".
std::string::size_type ps_x = line.find('x');
// no duplicate admitted
if(ps_x != std::string::npos && line.find('x', ps_x+1) != std::string::npos)
{ std::cout << errs.at(1); continue; }
ps = line.find('+');
if(ps != std::string::npos && line.find('+', ps+1) != std::string::npos)
{ std::cout << errs.at(2); continue; }
if(ps_x != std::string::npos) {
if(ps != std::string::npos) { // both "mx" and "b"
if(ps < ps_x) { // "b + mx"
std::optional<double> b = stodNoExcept(line);
if(b) { par.second = b.value(); }
else { std::cout << errs.at(3); continue; }
line = line.substr(ps+1);
std::optional<double> m = getGradient(line);
if(m) { par.first = m.value(); }
else { std::cout << errs.at(4); continue; }
} else { // "mx + b" or "xm + b"
std::optional<double> m = getGradient(line);
if(m) { par.first = m.value(); }
else { std::cout << errs.at(4); continue; }
line = line.substr(ps+1);
std::optional<double> b = stodNoExcept(line);
if(b) { par.second = b.value(); }
else { std::cout << errs.at(3); continue; }
}
} else { // only "mx" or "xm"
std::optional<double> m = getGradient(line);
if(m) { par.first = m.value(); }
else { std::cout << errs.at(4); continue; }
}
} else { // only "b" (or "y", i.e. not a number)
std::optional<double> b = stodNoExcept(line);
if(b) { par.second = b.value(); }
else { std::cout << errs.at(3); continue; }
}
std::cout << "Equation y = mx + b where m = " << par.first
<< " and b = " << par.second << ".\n"
"Do you want to enter another equation (y/n)? ";
char c {};
std::cin >> c;
std::cin.ignore(1000, '\n');
if('y' != c) { again = false; }
} while(again);
waitForEnter();
return 0;
}
std::optional<double> stodNoExcept(const std::string& s)
{
try {
double d = std::stod(s);
return { d };
} catch(std::logic_error& e) {
return std::nullopt;
}
}
// s: "mx", "xm", "mx + b", "xm + b" --> '+' must be after 'x' or missing
std::optional<double> getGradient(const std::string& s)
{
std::optional<double> g = stodNoExcept(s);
if(g) { return g; } // "mx" or "mx + b"
return stodNoExcept( s.substr(s.find('x')+1) ); // from char after 'x' on
}
void waitForEnter()
{
std::cout << "\nPress ENTER to continue...\n";
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
|