Is there a way to improve this this c++ code?

Multi tool use


Is there a way to improve this this c++ code?
Hello
I'm a programming newbie. In fact, this is my second code ever (after the hello world code).
I did a lot of reading actually, here on stack overflow, and other websites, I also purchased "Jumping Into C++" By Alex Allain, And I put Everything I learned here In this code :
Simple Calculator.cpp :
#include <iostream>
#include <string>
using std::cout; using std::cin;
int main()
{
cout << "Calculator..... n";
cout << "Type '3a3'to exit... n";
double a=0 ,b=0;
char op = 'a'; //operator // 'a' is the exit operator, the value of the integers doesn't matter
int ch = 0; //while loop checker
do
{
cin >> a >> op >> b;
if (op == '/' && b == 0)
{
cout << "Division By Zero, Please Retry n" ;
goto retry;
}
switch (op)
{
case '+':
cout << a << " + "<< b << " = " << a+b << "n";
ch = 0 ;
break;
case '-':
cout << a << " - "<< b << " = " << a-b << "n";
ch = 0 ;
break;
case 'x':
case '*':
cout << a << " * "<< b << " = " << a*b << "n";
ch = 0 ;
break;
case '/':
cout << a << " / "<< b << " = " << a/b << "n";
ch = 0;
break;
case 'a':
ch = 1;
break;
default:
ch = 0;
cout << "Invalid operator, Please retry n";
}
retry: ;
}while (ch != 1);
}
I would Like To know If there's a way to further improve this code.
Thanks In Advance
and don't use goto; it works but in general it's not considered good practice (unless fully justified)
– Alberto Miola
1 hour ago
@Steve That was often requested at Meta SO, but ever declined so far (for good reasons).
– πάντα ῥεῖ
1 hour ago
@Steve Code Review doesn't want Close Migrations because their requirements for a good question (and with good reasons) are more stringent than many SO close-voters are. The fear is most of the migrated questions would just go there to die, wasting everyone's time.
– user4581301
1 hour ago
The two biggest things I see in this code are the lack of input validation (read more here: Good input validation loop using cin - C++) and the
goto
, which can be replaced by an else
paired with if (op == '/' && b == 0)
– user4581301
1 hour ago
goto
else
if (op == '/' && b == 0)
1 Answer
1
"foobar"s
with std::literals::string_literals::operator""s()
accessible in the global namespace constructs a std::string
from "foobar"
.
"foobar"s
std::literals::string_literals::operator""s()
std::string
"foobar"
#include <limits>
#include <string>
#include <iostream>
using namespace std::literals::string_literals;
int main()
{
std::cout << "Calculator..... nType '3a3' to exit...n";
char op;
do
{
double lhs, rhs;
while (std::cout << "> ", // print a promt. due to the comma operator this is not part of the condition
!(std::cin >> lhs >> op >> rhs) || // input error, cin is in a error state ... !cin
"+-*x/:a"s.find(op) == std::string::npos || // op is not a valid operation
"/:"s.find(op) != std::string::npos && rhs == .0) // op is division and the divisor (right-hand-side operand) is zero
{
std::cerr << "Input error!nn";
std::cin.clear(); // clear error state of cin
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), 'n'); // ignore everything up to a newline stille in the input buffer
}
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), 'n');
double result;
switch (op)
{
case '+':
result = lhs + rhs;
break;
case '-':
result = lhs - rhs;
break;
case '*':
case 'x':
result = lhs * rhs;
break;
case '/':
case ':':
result = lhs / rhs;
break;
}
if (op != 'a')
std::cout << lhs << ' ' << op << ' ' << rhs << " = " << result << 'n';
} while (op != 'a');
}
shorter:
#include <limits>
#include <string>
#include <iostream>
#include <functional>
using namespace std::literals::string_literals;
int main()
{
std::cout << "Calculator..... nType '3a3' to exit...n";
std::function<double(double, double)> ops{
[&](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) { return lhs / rhs; } };
char op;
do
{
double lhs, rhs;
std::size_t op_pos;
while (std::cout << "> ",
!(std::cin >> lhs >> op >> rhs) ||
(op_pos = "+ - *x/:a "s.find(op)) == std::string::npos ||
"/:"s.find(op) != std::string::npos && rhs == .0)
{
std::cerr << "Input error!nn";
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), 'n');
}
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), 'n');
if (op != 'a')
std::cout << lhs << ' ' << op << ' ' << rhs << " = " << ops[op_pos/2](lhs, rhs) << 'n';
} while (op != 'a');
}
Tight code, readable, but weak on explanation. For example, I doubt OP has gotten far enough in their text for
"+-*x/:a"s
, and if they have, it's an easy thing to miss.– user4581301
52 mins ago
"+-*x/:a"s
Thanks for the answer! Although I don't understand the while loop from line 18 to line 26.
– Skorpios
49 mins ago
@Skorpios I added comments to the condition in the while-statement.
– Swordfish
44 mins ago
@Swordfish Makes Much more sense now, thanks again.
– Skorpios
31 mins ago
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
If the code is all working as intended you should better ask that question at SE Code Review.
– πάντα ῥεῖ
1 hour ago