While Loop with LCV of cin won't exit in C++ - c++

This is hw. I have asked my professor why the following code won't exit the while loop, and he/she couldn't tell me. My understanding is that once the input stream has no more values to read, the cin will return a value of false, and should cause the while loop to exit. Mine does not. It seems to keep read the input values (a set of integers) process through the loop, then wait for more input. Can anyone tell me why? Below is the code.
# include <iostream>
using namespace std;
int main()
{
int iEvenSum = 0;
int iOddSum = 0;
int iNum;
// prompt user
cout << "Input any set of integers, separated by a space:\n";
cin >> iNum;
cout << "You input: ";
while (cin)
{
cout << iNum << " ";
if (iNum % 2 == 0)
iEvenSum = iEvenSum + iNum;
else
iOddSum = iOddSum + iNum;
cin >> iNum;
}
cout << "\n\nThe sum of Even numbers is " << iEvenSum << "." << endl;
cout << "The sum of Odd numbers is " << iOddSum << "." << endl;
return 0;
}

while(cin) remains true as long as the cin stream is ok and becomes false if cin encounters an end of file character or an error.
In your case, while(cin) will keep on reading the numbers until it encounters an EOF character or an error. Type Ctrl-D when you don't have any more input numbers and it should quit the while loop

Related

Why does a second cin getting skipped over after a while(cin) loop fail?

This code gets a series of integers using a while(cin>>x) loop.
The variable x is pushed back on each iteration to vector<int> ivec.
The loops should exit at a non integer input.
After that I want to get one more integer cin>>y to check its freq. inside the vector.
Code:
cout << "Enter a sequence of integers separated with a space: " << flush;
vector<int> ivec;
int x = 0, y = 0;
while( (cin>>x) && (cin.good()) )
{
ivec.push_back(x);
}
cin.clear();
cout << "Enter an integer to count it's frequency: "<< endl;
cin>>y;
cout << "Y: " <<y<< " X: "<<x << endl;
cout << "Occurred "<< count(ivec.cbegin(), ivec.cend(), y)<< " times."<< endl;
for( int i : ivec)
{
cout << " "<<i << flush;
}
cout << endl;
Problem:
When I input a series of integer & the last character is a eof, the while loop gets exited & the second cin>>y never executes.
But the rest of the program executes normally. just no more cin statements can be executed.
The only case where the second cin executes is: if I enter a series of integers separated by a space, press return key, then type the eof (^Z) on a line on its own. I don't know why does it act that way?
What I've tried:
I tried cin.clear(), it does not resolve the problem.
Also I used auto stat = cin.rdstate() before the while loop and cin.setstate(stat) after the loop still the second cin never executes.
ScreenShot:
I know cin ignores space, tab & newline, so why does a new line make a difference?
I am asking this to how cin works and why its behaving this way. I am aware that I can use getline().

Trying to validate input in C++

The idea behind this code in c++ is to calculate the sum of all the entered numbers. When the user enters 0, the program should stop. This part of the code is working as I intended, but I'd like to include a variant which recognizes that a character different than a float number has been entered, ignore it in the calculation and allow the user to continue entering float numbers. At the moment, entering anything else but a float number stops the program.
I know there's a "if (!(cin >> numb))" condition, I've tried parsing it in different places in the code, but I can't figure out how to force the program to ignore these invalid inputs. I would be very grateful for any help.
#include <iostream>
#include <stdlib.h>
using namespace std;
float numb; float sum=0;
int main()
{
cout << "This app calculates the sum of all entered numbers." << endl;
cout << "To stop the program, enter 0." << endl << endl;
cout << "Enter the first number: ";
cin >> numb;
while(true)
{
sum += numb;
if (numb!=0)
{
cout << "Sum equals: " << sum << endl << endl;
cout << "Enter another number: ";
cin >> numb;
}
else
{
cout << "Sum equals: " << sum << endl << endl;
cout << "Entered 0." << endl;
cout << "Press Enter to terminate the app." << endl;
exit(0);
}
}
return 0;
}
You have three options:
trial and error: try to read a float, and in case of error clear the error flag, ignore the bad input and read again. The problem is that you don't know really how many of the input is to be ignored.
read strings: read space delimited strings, try to convert the string using stringstream, and just ignore the full string in case of error. The problem is that if the input starts with a valid float but then contains invalid characters (e.g. 12X4), the invalid part will be ignored (e.g. X4)
control parsing: read space delimited strings, try to convert the string using std::stof(), and check that all characters of the string where successfully read
Here the second approach, with a slightly restructured loop, so that a 0 entry will lead to exiting the loop and not the full program:
string input;
while(cin >> input)
{
stringstream sst(input);
if (sst>>numb) {
sum += numb;
cout << "Sum equals: " << sum << endl << endl;
if (numb==0)
{
cout << "Entered 0." << endl;
break; // exits the while loop
}
cout << "Enter another number: ";
}
else
{
cout << "Ignored entry "<<input<<endl;
}
}
cout << "Press Enter to terminate the app." << endl;
Online demo
If you prefer a more accurate parsing, consider something like:
size_t pos=0;
float xx = stof(input, &pos );
if (pos!=input.size()) {
cout << "error: invalid trailing characters" <<endl;
}
You have to clear the failbit after a failed read. After that, you can read in the invalid stuff into a string (that you just ignore). This function will read in values and add them up until it encounters a 0 or the end of the input stream.
int calc_sum_from_input(std::istream& stream) {
int sum = 0;
// If it couldn't read a value, we just read the thing into here
std::string _ignored;
while(stream) // Checks if the stream has more stuff to read
{
int value;
if(stream >> value)
{
if(value == 0) // Exit if it read the value 0
break;
else
sum += value; // Otherwise update the sum
}
else {
// Clear the failbit
stream.clear();
// Read ignored thing
stream >> _ignored;
}
}
return sum;
}
The logic is basically:
set the initial sum to 0
check if there's stuff to read
if there is, try reading in a value
if successful, check if the value is 0
if it's 0, exit and return the sum
otherwise, add the value to the sum
otherwise, clear the failbit (so that you can read stuff in again) and read the bad value into a string (which gets ignored)
otherwise, return the value

Entering specific character into while loop

I am writing a code for class that asks the user to input a size that is an odd number equal to or greater than 7. I have been able to make that part of my code work successfully. However, the next part consists of asking the user to enter a specific letter, in this case 'c'. If they do not enter 'c' then the loop should ask them to input another character. Whenever I run this code, it is creating an infinite loop whether I enter 'c' or another letter. I think my expression in my second while loop is incorrect, but I haven't been able to find a lot of information regarding this that could help me.
#include <iostream>
using namespace std;
int main() {
int s, l;
cout << "Welcome to the letter printer." << endl;
cout << "Enter the size: " << endl;
cin >> s;
while (s < 7 || s%2==0 || s<0)
{
cout << "Invalid size. Enter the size again: " << endl;
cin >> s;
}
cout << "Enter the letter: " << endl;
cin >> l;
while (l != 'c')
{
cout << "Invalid letter. Enter the letter again: " << endl;
cin >> l;
}
return 0;
}
because you are getting char for int variable
wrong:
int s, l;
right one:
int s;
char l;
what is why it goes on infinite loop in second while
explanation for infinite loop
This is how basic_istream works. In your case when cin >> l gets
wrong input - failbit is set and cin is not cleared. So next time it
will be the same wrong input. To handle this correctly you can add
check for correct input and clear&ignore cin in case of wrong input.
incorporated from here

Programming Principles and Practice: chapter 4 drill part 1

I just can't seem to get this program to work properly. I can get it to accept two integers and print them to the screen. But I can't get the program to terminate when the '|' is used. Once that its entered it loops infinitely. Here is the code that I have so far:
#include "../../std_lib_facilities.h"
int main()
{
int num1 = 0;
int num2 = 0;
char counter = '\0';
cout << "Please enter two integers and press enter. \n";
bool test = true;
while (counter != '|')
{
cin >> num1 >> num2;
cout << "Your numbers are: " << num1 << " " << num2 << endl;
if (cin.fail())
{
cout << "Goodbye!\n";
test = false;
}
else (counter != '|');
cout << "Enter more numbers or press '|' to exit.\n";
}
system("pause");
}
You are using the wrong condition in your while loop. You are never changing counter so the loop will never end. However you do change test to false in the while loop if the input fails. You can change the condition of the while loop to use test instead like
while(test)
{
//...
}
Since counter is no longer being used you can get rid of it completely.
Please note that unless you change to taking in string and parsing the input any input that will cause cin to fail will end the loop not just a |.

fixing an unintentional infinite loop

when i input a random number like 63453462 it responds with "invalid number" but in an infinite loop but if i put a number like 2,000,002 it just says invalid number with no loop. I need help with not making an infinite loop when someone inserts a random number like 2145345665465.
#include <iostream>
using namespace std;
int main ()
{
int sum , input , number;
cout << "Enter any positive integer that is less than or " ;
cout << "equal to 2,000,000 to determine if it is divisible by 11.";
cout << endl;
cout << "If the number is greater than 99, we use Dodgsons's rule";
cout << endl;
cout << "which determines if it is a factor or not.\n";
cout << endl;
cin >> input;
while ((input < 1) || ( input > 2000000 ))
{
cout << "Invalid number detected, please enter a positive integer.\n";
cin >> input;
}
number = input;
while ((input>=100) && (input < 2000000))
{
sum = input % 10;
input = input /10 - sum;
cout << input << endl;
}
if (input % 11 == 0)
cout << "the number is divisible by 11." << endl;
else
cout << "the number is not divisible by 11." << endl;
system ("Pause");
return 0;
}
while ((input < 1) || ( input > 2000000 ))
{
cout << "Invalid number detected, please enter a positive integer.\n";
cin >> input;
cin.clear();
}
cin.clear() will clear any previous state that cause the infinite loop.
You need to properly check whether your input operation succeeded. If you enter something that cannot be parsed as an integer, or some value that is more than INT_MAX or less than INT_MIN, then after
cin >> input
the stream std::cin will enter a failed state, that means the failbit is set. After that, each following input operation will also fail, unless you take care of it.
The usual approach here is to clear the input buffer (with the input that could not be handled) and just try again:
while (not (cin >> input) or not is_valid(input)) {
cout << "Invalid input, try again" << endl;
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
cin.clear();
}
This first does the input operation (cin >> input) and checks whether it not succeeded, and only if that is not true (i.e. the input operation succeeded) checks whether the input is not valid using some is_valid function. In that case an error is printed, all characters up to and including the next newline are removed from the stream, and the failbit is cleared, in order to allow a new take on getting valid input.
Note, that having two variables of the same type and doing
number = input;
is useless here, you can directly read into number (which is more appropriately named) and drop the variable input all together.