0

I'm a beginner in coding, in general, and as an academic student, I, along with my colleagues, started learning C++ first in our first year.

I was given an assignment to write a simple calculator using the aforementioned language. And while I could work through it using the 'switch' method, I still have a problem with my program:

#include <iostream>
using namespace std;

int main() {
    char z;
    double x,y,a,b,c,d;
    cout << "Enter two operands, and an operator: ";
    cin >> x >> y >> z;
    a = x + y;
    b = x-y;
    c = x /y;
    d = x * y;
    switch (z) {
    case '+':
        cout << "The result is: " << a << endl;
        break;
    case '-':
        cout << "The result is: " << b << endl;
        break;
    case '/':
        cout << "The result is: " << c << endl;
        break;
    case '*':
        cout << "The result is: " << d << endl;
        break;
    default: 
        cout << "Your operator is good! \n";
    }
    return 0;
}

In execution, after the first 'cout' statement appears, I tried entering an 'operator' or any other character; assigning it to the 'x' variable and expecting to get an error due to assigning a character to a 'double'-type variable (x). However, this didn't happen and doing so returned my switch's default statement instead.

Why did that happen?

Walter
  • 44,150
  • 20
  • 113
  • 196
tin tan
  • 49
  • 3
  • Related: https://stackoverflow.com/questions/10349857/how-to-handle-wrong-data-type-input – scohe001 Dec 13 '18 at 20:04
  • What kind of error did you expect? If you entered any character that wasn't a `double`, when `cin` was expecting a `double`, then the `cin` fails.. It's just you don't check if it succeeds, or fails. e.g.: `if (cin>>x>>y>>z) { /* Operation succeeded */ } else { /* Operation failed */ }` – Algirdas Preidžius Dec 13 '18 at 20:05
  • 1
    related/dupe: https://stackoverflow.com/questions/26187729/stdcin-doesnt-throw-an-exception-on-bad-input?rq=1 – NathanOliver Dec 13 '18 at 20:07
  • *expecting to get an error* You didn't ask. `cin>>x>>y>>z;` -> `if(cin>>x>>y>>z) { do stuff with x,y,z } else { handle error }`. You can also turn on exceptions, but exceptions should be reserved for exceptional events, and the user hitting the wrong keys is far from an exceptional event. – user4581301 Dec 13 '18 at 20:28
  • 1
    Possible duplicate of [std::cin doesn't throw an exception on bad input](https://stackoverflow.com/questions/26187729/stdcin-doesnt-throw-an-exception-on-bad-input) – eliasah Dec 14 '18 at 08:10

1 Answers1

2

where is my error?

In execution, after the first 'cout' statement appears, I tried entering an 'operator' or any other character; assigning it to the 'x' variable and expecting to get an error due to assigning a character to a 'double'-type variable (x).

Not sure how to put it in a nice way... Your expectations are wrong! If you do something wrong in your code then you dont get a nice candy error message that told you what went wrong. If you do something wrong then wrong things will happen. For user input that means: You have to actively check if the input suceeded. If you dont then you risk bad things to happen (read about undefined behaviour if you dont know what it is).

here you go

That being said, in some sense there actually is what you were expecting. From cppreference:

If extraction fails (e.g. if a letter was entered where a digit is expected), value is left unmodified and failbit is set. (until C++11)

If extraction fails, zero is written to value and failbit is set. If extraction results in the value too large or too small to fit in value, std::numeric_limits::max() or std::numeric_limits::min() is written and failbit flag is set.

So when the user enters "operator", then the extraction fails because "operator" is not a double. You can catch such wrong input by inspecting the failbit flag. Long story short: streams can convert to bools, if the result is true the input was succesful:

double x = 0.0;
std::cin >> x;
if (std::cin) std::cout << x;
else {
   std::cout << "input failed";
   std::cin.clear();            // reset error state flags
                                // and ignore characters left in the stream
   std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}

conclusion

Maybe in one place you want to throw an exception in case of wrong input (see here for an example), while in a different place the input may fail silently and performance is a concern. C++ philosophy is: You do not pay for what you do not need. It takes some effort to get user input right. However, if you use the tools given to you, you can easily detect wrong input and act accordingly.

Last but not least, always do initialize your variables! Only since C++11 you can be sure that x will have a value after std::cin >> x;. (Even after C++11 you should initialize it.)

TL;DR

Why did that happen?

If you are compiling "pre C++11" then your code has undefined behaviour (x is used uninitialized here: a = x + y;). Since C++11 the reason is simply that z is not any of the other characters +,-... but \0 (cin reads one character and then fails, not only x but also all the other input operations fail).

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185