Why would we call cin.clear() and cin.ignore() after reading input?
The cin.clear()
clears the error flag on cin
(so that future I/O operations will work correctly), and then cin.ignore(10000, '\n')
skips to the next newline (to ignore anything else on the same line as the non-number so that it does not cause another parse failure). It will only skip up to 10000 characters, so the code is assuming the user will not put in a very long, invalid line.
What happens when operator is trying to input a value bigger than a variable can contain?
On std::istream& std::istream::operator>>(std::istream&, int&)
, cppreference says:
Behaves as a FormattedInputFunction. After constructing and checking the sentry object, which may skip leading whitespace, extracts an integer value by calling
std::num_get::get()
...
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<T>::max()
orstd::numeric_limits<T>::min()
is written and failbit flag is set. (since c++11)
It's not normative, but it does provide a decent summary of what is happening here.
FormattedInputFunctions will construct a sentry from the stream and check the value. If the sentry object evaluates as false
, then no input is performed.
The sentry object will evaluate as false
if, among other situations, the stream being operated on has the failbit set.
So, what's happening is this:
- The stream tries to read in an integer too large to hold in the
int
data type. - The
int
passed into its function is set to the maximum possible value anint
can store. - The stream passed into the function has its failbit set.
- Further reads to the stream fail and do nothing, because the stream's failbit is set.
You can detect these overflow errors by checking the failbit and value of the integer after the read operation you are performing, as mentioned in the accepted answer to the question Read int from istream, detect overflow.
You can recover from these errors by unsetting the failbit with std::basic_ios::clear
. Following a call to clear
which unsets the failbit, further reads will behave as you expect.
Python. Code fails to work with larger numbers, but works with smaller numbers. Why?
Simple error. You need to use floor division:
c = c // 2
This will fix it. The original c = c/2
turns your c
into float
which fails for large numbers. Compare:
>>> int(914136090224822879032 / 2)
457068045112411422720
>>> 914136090224822879032 // 2
457068045112411439516
With that change, you will get:
>>> add_binary(800998058044843321128,113138032179979557904)
'1100011000111000101111110010101100001001000111000000001000001100111000'
if you want a short version:
def add_binary(a, b):
return '{:b}'.format(a+b)
How to handle wrong data type input
The reason the program goes into an infinite loop is because std::cin
's bad input flag is set due to the input failing. The thing to do is to clear that flag and discard the bad input from the input buffer.
//executes loop if the input fails (e.g., no characters were read)
while (std::cout << "Enter a number" && !(std::cin >> num)) {
std::cin.clear(); //clear bad input flag
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); //discard input
std::cout << "Invalid input; please re-enter.\n";
}
See the C++ FAQ for this, and other examples, including adding a minimum and/or maximum into the condition.
Another way would be to get the input as a string and convert it to an integer with std::stoi
or some other method that allows checking the conversion.
Checking cin input stream produces an integer
You can check like this:
int x;
cin >> x;
if (cin.fail()) {
//Not an int.
}
Furthermore, you can continue to get input until you get an int via:
#include <iostream>
int main() {
int x;
std::cin >> x;
while(std::cin.fail()) {
std::cout << "Error" << std::endl;
std::cin.clear();
std::cin.ignore(256,'\n');
std::cin >> x;
}
std::cout << x << std::endl;
return 0;
}
EDIT: To address the comment below regarding input like 10abc, one could modify the loop to accept a string as an input. Then check the string for any character not a number and handle that situation accordingly. One needs not clear/ignore the input stream in that situation. Verifying the string is just numbers, convert the string back to an integer. I mean, this was just off the cuff. There might be a better way. This won't work if you're accepting floats/doubles (would have to add '.' in the search string).
#include <iostream>
#include <string>
int main() {
std::string theInput;
int inputAsInt;
std::getline(std::cin, theInput);
while(std::cin.fail() || std::cin.eof() || theInput.find_first_not_of("0123456789") != std::string::npos) {
std::cout << "Error" << std::endl;
if( theInput.find_first_not_of("0123456789") == std::string::npos) {
std::cin.clear();
std::cin.ignore(256,'\n');
}
std::getline(std::cin, theInput);
}
std::string::size_type st;
inputAsInt = std::stoi(theInput,&st);
std::cout << inputAsInt << std::endl;
return 0;
}
std::cin input with spaces?
You have to use cin.getline()
:
char input[100];
cin.getline(input,sizeof(input));
Return an error for two inputs of numbers if not an integer
You need to check the error state of std::cin
before you act on the value returned by operator>>
. Try something more like this instead:
#include <iostream>
#include <fstream>
#include <limits>
using namespace std;
int main () {
int num1, num2; // two integers
int choice; // chosen integers
int ch1 = 0, ch2 = 0, ch3 = 0, ch4 = 0, ch5 = 0; // to keep track of chosen functions
//const for choice of menu
const int addition = 1,
substruction = 2,
multiplication = 3,
division = 4,
modulo = 5,
numberChange = 6;
//intro
cout << "This program has been made for arithmetic operations.\n";
cout << "Please choose two integers for arithmetic operations\n";
//return error if input is not integers
while (!(cin >> num1 >> num2)) {
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Error! Please enter only integers!\n";
}
do {
cout << "Choose number of the operation you want to do\n";
cout << "1. addition\n";
cout << "2. subtraction\n";
cout << "3. multiplication\n";
cout << "4. division\n";
cout << "5. modulo\n";
cout << "6. CHANGE OF NUMBERS\n";
cout << "To exit menu enter -1!\n";
//return error if input is not integer
while (!(cin >> choice)) {
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Error! Please enter only integers!\n";
}
// validate the input for right number
switch (choice) {
case 1:
cout << "Result: " << num1 << " + " << num2 << " = " << num1 + num2 << '\n';
ch1++;
break;
case 2:
cout << "Result: " << num1 << " - " << num2 << " = " << num1 - num2 << '\n';
ch2++;
break;
case 3:
cout << "Result: " << num1 << " * " << num2 << " = " << num1 * num2 << '\n';
ch3++;
break;
case 4:
cout << "Result: " << num1 << " / " << num2 << " = " << num1 / num2 << '\n';
ch4++;
break;
case 5:
cout << "Result: " << num1 << " % " << num2 << " = " << num1 % num2 << '\n';
ch5++;
break;
case 6:
cout << "Okay, you can choose different numbers\n";
while (!(cin >> num1 >> num2)) {
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Error! Please enter only integers!\n";
}
break;
case -1: {
ofstream myfile ("/Users/margaritakholostova/Desktop/us.txt");
if (myfile.is_open()) {
myfile << "Addition was selected " << ch1 << " times\n";
myfile << "Subtraction was selected " << ch2 << " times\n";
myfile << "Multiplication was selected " << ch3 << " times\n";
myfile << "Division was selected " << ch4 << " times\n";
myfile << "Modulo was selected " << ch5 << " times\n";
myfile.close();
}
else
cout << "Unable to open file\n";
return 0;
}
default:
cout << "Please choose a valid option from the menu (1-5)\n";
break;
}
}
while (true);
}
Related Topics
Gcc Std::Thread Not Found in Namespace Std
Equality-Compare Std::Weak_Ptr
C++11 Change 'Auto' Lambda to a Different Lambda
Reasonably Portable Way to Get Top 64-Bits from 64X64 Bit Multiply
Why to Use Higher Base for Implementing Bigint
Most Efficient Way to Check If All _M128I Components Are 0 [Using <= Sse4.1 Intrinsics]
C++: Why Does Space Always Terminate a String When Read
What Is This Crazy C++11 Syntax ==> Struct:Bar {} Foo {};
Is There Any Danger in Calling Free() or Delete Instead of Delete[]
Generate a Plane with Triangle Strips
How to Do Performance Test Using the Boost Library for a Custom Library
Boost C++ Regex - How to Get Multiple Matches
Remove Duplicates from a List<Int>
What's the Difference Between Sockaddr, Sockaddr_In, and Sockaddr_In6