2
\$\begingroup\$

I'm pretty confident in this code but I want to be sure I haven't missed anything to do with optimization or error handling. The program takes input in the form of {number} {operator} {number} and prints the result. If the input is invalid it prints nothing.

Example input: 1.0 + 2.0 Output: 3

#include <iostream>
#include <string>
#include <stdexcept>
#include <regex>
double calculate(const double a, const char op, const double b)
{
 switch (op)
 {
 case '+':
 return a + b;
 case '-':
 return a - b;
 case '*':
 return a * b;
 case '/':
 if (b == 0.0)
 throw std::invalid_argument {"Divide by zero"};
 return a / b;
 default:
 throw std::invalid_argument {{op}};
 }
}
int main()
{
 const std::regex valid_input {
 "([0-9]*\\.?[0-9]*) ([\\+\\-\\*\\/]) ([0-9]*\\.?[0-9]*)"};
 std::string line;
 std::smatch terms;
 double a;
 double b;
 char op;
 while (std::getline(std::cin, line))
 {
 if (!std::regex_match(line, terms, valid_input))
 continue;
 a = std::stod(terms[1]);
 b = std::stod(terms[3]);
 op = terms[2].str().front();
 std::cout << calculate(a, op, b) << '\n';
 }
}
200_success
145k22 gold badges190 silver badges478 bronze badges
asked Jul 19, 2017 at 1:36
\$\endgroup\$

2 Answers 2

1
\$\begingroup\$

Escaping escape characters becomes confusing.
Use the appropriate string literal.

 // Your String
 "([0-9]*\\.?[0-9]*) ([\\+\\-\\*\\/]) ([0-9]*\\.?[0-9]*)"
 // A Raw String (no escape characters)
 R"RAW(([0-9]*\.?[0-9]*) ([\+\-\*\/]) ([0-9]*\.?[0-9]*))RAW"

Don't think your regular expressions are good enough.

([0-9]*\.?[0-9]*)
// Can map
.
<blank>

I would do:

// If you have the decimal point then you require at least on digit after it.
// If there is no decimal point then you require at least one digit.
(([0-9]*(\.[0-9]+))|[0-9]+)

Don't think regular expressions are the best way to capture number operator number. The stream operators support this already so prefer to use those.

while (std::getline(std::cin, line))
{
 std::stringstream lineStream(line);
 double a;
 double b;
 char op;
 char emptyTest;
 if (lineStream >> a >> op >> b && !(lineStream >> emptyTest)) {
 // Enter here if:
 // 1: We correctly read a op and b
 // 2: There are zero extra non-space characters on the line
 // We find this because the read to emptyTest fails.
 }

Declare your variables as close to the location that you use them. This also allows you to initialize them on declaration (which is always nice).

// Don't do this.
double a;
double b;
char op;
 // Now you can see the type and know that they are initialized.
 double a = std::stod(terms[1]);
 double b = std::stod(terms[3]);
 char op = terms[2].str().front();

Sure you can use a switch that is totally fine. But you can practice using the command pattern in this situation.

static std::map<char, std::function<double(double, doubel>> const actionMap = {
 {'+', [](double lhs, double rhs){return lhs + rhs;}},
 {'-', [](double lhs, double rhs){return lhs - rhs;}},
 {'*', [](double lhs, double rhs){return lhs * rhs;}},
 {'/', [](double lhs, double rhs){
 if (b == 0.0) {
 throw std::invalid_argument {"Divide by zero"};
 }
 return lhs / rhs;
 }
};
// Now use the action map to find the function you want to call.
auto find = actionMap.find(op);
if (find == actionMap.end()) {
 throw std::invalid_argument {{op}};
}
return find->second(a, b);
answered Jul 19, 2017 at 19:20
\$\endgroup\$
1
  • \$\begingroup\$ Thanks for the regex advice. After submitting the question I rewrote main to use stringstream and it works really good \$\endgroup\$ Commented Jul 20, 2017 at 1:32
0
\$\begingroup\$
  • What happens if I enter only + surrounded by spaces?
  • The program should not abort if I enter 0 / 0, but continue with the next line.
  • I'd like to omit the spaces around the operator.
  • In the regular expression, the operator part can be written as [+\\-*/].
answered Jul 19, 2017 at 5:19
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.