A loop and a character in int variable doesn't work as i expect - c++

i saw an unusual problem in this code:
#include <iostream>
using namespace std;
int main()
{
int number;
bool repeat=true;
while (repeat)
{
cout<<"\nEnter a number:";
cin>>number;
cout<<"\nNumber is:"
<<number;
cout<<"\nRepeat?:";
cin>>repeat;
}
system("pause");
return 0;
}
here in this code when i put a character such "A" in int type variable while loop repeats over and over and don't ask me whether to repeat or not.
this problem just appear when i put characters not integers.
this appears with for too.
why should happen this?
thanks

After reading in user input which cannot be converted, the input stream is in an invalid state. You need to empty the stream and call the clear method to reset the error bits on the stream in order to resume normal operation.
If you detect that input was not successful (using the input streams state bits, accessible via methods like good() or fail() etc.) you can reset the stream using code similar to this:
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

You put cin in an error state when you failed to extract an int from it, and didn't recover. So when you then tried to extract repeat from it, the stream is still in a failed state. You need to check for the failure of number (just use if(cin >> number)).

Related

Getting infinite loop when want to terminate it with a character like | in c++

So this is the code
#include<iostream>
using namespace std;
int main(){
int a,b;
while(true){
cout<<"Enter the value of a and b ";
cin>>a>>b;
if(a=='|'||b=='|')
break;
else
cout<<"The value of a is "<<a<<"\nThe value of b is "<<b<<endl;
}
}
and the question is Write a program that consists of a while-loop that (each time around the loop) reads in two ints and then prints them. Exit the program when a terminating '|' is entered.
When i enter input like | it prints infinitely "The value of a is and value of b is ". What is the reason for this?enter code here
std::cin (and I think all streams) by default will set an error flag when you try to read into an invalid data type (e.g. here with trying to read a char into an int variable) and that flag will prevent other std::cin to run until the flag is cleared. To rest the stream, use std::cin.clear() to the reset the error flag and then you have to remove the bad input, either through std::cin.ignore() or read into a string buffer or something, from the stream as it will still be there.
Your istream operator >> as_int is failing and really doing nothing so your loop just keeps going. Either input as chars and convert to ints with checks, or or check the stream for errors.
cin>>a>>b;
if( cin.fail( ) )
break;
istream reading after failure
Additionally: If you had have traced into the istream operator you would have seen why it was not blocking, that it had failed. Always trace when something is wrong...

Why does this do while loop repeat infinitely?

I want to prompt the user to input an integer, but if the user enters a non-integer, the program should keep demanding an integer until the user complies.
int getInteger(){
int input;
do{
std::cout << "Enter an integer: ";
std::cin >> input;
} while(!(std::cin));
return input;
}
If the user enters an integer, the function returns it.
But if the user enters something like "Hello," the function goes on an infinite, cout-ing "Enter an integer: ".
How do I fix this?
!(std::cin)
will evaluate to true if std::cin is in a bad state, e.g. after an input operation failed. Then, all subsequent input operations will fail immediately and not change cin's error state, thus the infinite loop.
To get the behavior you want, you may use something like
while (!(std::cin >> input)) {
std::cout << "Try again\n";
// Clear away the error state
std::cin.clear();
// Ignore what ever garbage is still in the stream
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
In the real world, you may want to handle the (generally not recoverable) failures eof (someone sent an End of File character) and bad (cin is broken, should not happen) different than fail which happens after invalid input. This is, for example, shown on this reference page for ignore. However, this should not bite you in toy programs like yours seems to be.
Streams convert to true while there is none of the failure bits is set. Once a stream entered the failure state, i.e., std::ios_base::failbit (or std::ios_base::badbit) is set for the stream, it stays in that state until the failure bit is cleared using clear(). In addition to clearing the stated you'd also need to get rid of the offending character(s) causing it to get into this state, e.g., using ignore().

Why cin.fail() doesn't return false when entering a number followed by character?

I wrote this simple code:
#include <iostream>
using namespace std;
int main()
{
double s;
cin >> s;
if (cin.fail())
cout<<"Error";
return 0;
}
When I enter 12.03, cin.fail() returns false, and that's good.
And when I enter sd234, cin.fail() returns true, which is also good.
But if I enter 234.abcd, for example, or any number followed by a characters, cin.fail() returns true although I didn't enter a numerical to the double variable through the cin.
What am I missing?
std::istream::operator>>() reads characters as long as it fits to the current type (e.g. digits and . for double). Following characters are left in the input buffer for another extraction operator. If the characters read can satisfy the current type, no error is signaled.
Because it reads '234.', and that's a valid number.
The rest of the stuff that you've entered, 'abcd' is waiting for the next read.
The input asked for, i.e., a double coukd be satisfied, i.e., the read operation was successful. If you want to check that the stream continues with something you'd expect you need to read this. Alternatively you can check if the next character in the stream is of a certain kind.

c++ reading undefined number of lines with eof()

I'm dealing with a problem using eof().
using
string name;
int number, n=0;
while(!in.eof())
{
in >> name >> number;
//part of code that puts into object array
n++;
}
sounds normal to me as it whenever there are no more text in the file.
But what I get is n being 4200317. When I view the array entries, I see the first ones ats the ones in the file and other being 0s.
What could be the problem and how should I solve it? Maybe there's an alternative to this reading problem (having undefined number of lines)
The correct way:
string name;
int number;
int n = 0;
while(in >> name >> number)
{
// The loop will only be entered if the name and number are correctly
// read from the input stream. If either fail then the state of the
// stream is set to bad and then the while loop will not be entered.
// This works because the result of the >> operator is the std::istream
// When an istream is used in a boolean context its is converted into
// a type that can be used in a boolean context using the isgood() to
// check its state. If the state is good it will be converted to an objet
// that can be considered to be true.
//part of code that puts into object array
n++;
}
Why your code fails:
string name;
int number, n=0;
while(!in.eof())
{
// If you are on the last line of the file.
// This will read the last line. BUT it will not read past
// the end of file. So it will read the last line leaving no
// more data but it will NOT set the EOF flag.
// Thus it will reenter the loop one last time
// This last time it will fail to read any data and set the EOF flag
// But you are now in the loop so it will still processes all the
// commands that happen after this.
in >> name >> number;
// To prevent anything bad.
// You must check the state of the stream after using it:
if (!in)
{
break; // or fix as appropriate.
}
// Only do work if the read worked correctly.
n++;
}
in << name << number;
This looks like writing, not reading.
Am I wrong?
int number, n = 0;
You weren't initializing n, and you seem to have a typo.
This probably would be more correct
string name;
int number, n = 0;
while (in >> name && in >> number)
{
n++;
}
The eof is a bad practice.
Note that there is a subtle difference here from your code: your code ended when it encountered an eof or silently looped for infinite time if it found a wrong line (Hello World for example), this code ends when it encounters a non correctly formatted "tuple" of name + number or the file ends (or there are other errors, like disconnecting the disk during the operation :-) ). If you want to check if the file was read correctly, after the while you can check if in.eof() is true. If it's true, then all the file was read correctly.

cin.get in a while loop

I'm trying to get input from user and give output until s/he presses 'n'. It doesn't seem to work. Is problem in scanf or cin.get? When I press y it just takes "tekrar" as an input, thus gives "y" as output and goes into a loop. Also, doesn't stop when i give n as tekrar input.
char cevap[300]="";
char tekrar='y';
while (tekrar!='n')
{
cin.get(cevap,300);
cout<<cevap<<endl;
cout<<"Again? (y/n)";
scanf("%c",&tekrar);
}
output:
Hello
Again? (y/n)
y
Again? (y/n)
y
Again? (y/n)
n
Again? (y/n)
n
...
Mixing the various input methods on istream (get, getline, operator>>) can be fraught with peril if you're not aware of which methods leave the delimiter character in the stream and which don't, and handle them accordingly.
In this case, get will read 300 characters of input or input up until the newline, whichever happens first. The newline will not be extracted, and so will remain in the stream. That means your call to scanf() will read the newline and stop, leaving the y or n you just typed in the stream.
There are several ways to reorganize this code to make it do what it seems like you want. This is one way:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string cevap;
char tekrar='y';
while (tekrar!='n')
{
getline(cin,cevap);
cout<<cevap<<endl;
cout<<"Again? (y/n)";
tekrar = cin.get();
cin.ignore();
}
return 0;
}
This uses std::string and the non-member getline to read input in such a way as to not require you to be limited to 300 characters (not strictly speaking related to the question, but good practice usually). getline consumes and discards the delimiter, but get, used to read the continuation input, doesn't, so we discard it manually via ignore.
Use cin operator>> to read from stdin, instead of scanf:
string cevap;
char tekrar='y';
while (tekrar!='n')
{
getline(cin, cevap);
cout<<cevap<<endl;
cout<<"Again? (y/n)";
cin >> tekrar;
cin.get();
}
Edit: fixed the infinite loop. You should use std::string instead of a simple char array.