Infinite loop with cin when typing string while a number is expected
Well you always will have an infinite loop, but I know what you really want to know is why cin doesn't keep prompting for input on each loop iteration causing your infinite loop to freerun.
The reason is because cin fails in the situation you describe and won't read any more input into those variables. By giving cin bad input, cin gets in the fail state and stops prompting the command line for input causing the loop to free run.
For simple validation, you can try to use cin to validate your inputs by checking whether cin is in the fail state. When fail occurs clear the fail state and force the stream to throw away the bad input. This returns cin to normal operation so you can prompt for more input.
if (cin.fail())
{
cout << "ERROR -- You did not enter an integer";
// get rid of failure state
cin.clear();
// From Eric's answer (thanks Eric)
// discard 'bad' character(s)
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
For more sophisticated validation, you may wish to read into a string first and do more sophisticated checks on the string to make sure it matches what you expect.
std::cin infinite loop from invalid input [duplicate]
By default, std::basic_istream::ignore()
ignores only 1 character:
basic_istream& ignore( std::streamsize count = 1, int_type delim = Traits::eof() );
(From http://en.cppreference.com/w/cpp/io/basic_istream/ignore)
More idiomatic use for your case seems to be the one from the example there:
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
Also, note that you want to call clear()
before the ignore()
call, so the input extraction of ignore()
will succeed instead of returning immediately.
Infinite loop with two cin [duplicate]
1) you forgot to remove the fail bit in std::cin
; use clear()
2) to detect an empty enter, I suggest to use a std::string
and std::getline()
I suggest something like
#include <iostream>
#include <string>
void read () {
int x;
while ( std::cin >> x ) ;
std::cin.clear();
std::cin.ignore(std::numeric_limits<int>::max(), '\n');
}
int main () {
std::string b;
do {
read();
std::getline(std::cin, b);
} while ( false == b.empty() );
return 0;
}
C++ Infinite while loop if given wrong type for condition
replace
do{
cout << msg;
cin >> value; // Values assumed to be numbers
}
while (value <= 0 and value != -1);
by
do {
cout << msg;
if (!(cin >> value)) {
string dummy;
cin.clear(); // to be able to read double
cin >> dummy; // to remove the non float
value = 0;
}
while (value <= 0 and value != -1);
you need to clear the error to be able to read again, then to bypass the wrong input, may be you can also just read a character, decide what to do in case of an error
Example :
#include <iostream>
using namespace std;
int main()
{
double value;
do {
cout << "value please" << endl;
if (!(cin >> value)) {
string dummy;
cin.clear();
cin >> dummy;
value = 0;
}
} while (value <= 0 and value != -1);
cout << "valid double :" << value << endl;
return 0;
}
Compilation and execution :
% ./a.out
value please
aze
value please
-12
value please
12
valid double :12
How do I prevent the program from going into infinite loop when writing a char to a float form?
The infinite loop problem occurs because cin
and underlying ifstream
expects a float
in your case. By not providing a float, cin
fails and the weird loop occurs. More information here.
Since you cannot control the user and you do not want the program to break if the user inputs characters, you can read the input to string
instead of float
. This way, no error flag is set by cin
.
Then, you should convert the string to float. atof
is suitable for this purpose.
#include <iostream>
#include <string>
#include <cstdlib>
...
std::string epsilon_str;
std::cin >> epsilon_str;
double epsilon = atof(epsilon_str.c_str());
From the documentation of atof
:
If the first sequence of non-whitespace characters in str does not form a valid floating-point number as just defined, or if no such sequence exists because either str is empty or contains only whitespace characters, no conversion is performed and the function returns 0.0.
Other general programming issues
There are lots of headers you include. Knowing what is required for which function or class is the best practice. I assume you included them when you needed, but if you won't use
setprecision
, then there is no reason to#include <iomanip>
.Using
define
means simply copy-paste. The compiler is not aware of what you are doing. See the following example.#define WRONG_MULTIPLY(a, b) a * b
#define CORRECTED_MULTIPLY(a, b) ((a) * (b))
...
int wrong_result = WRONG_MULTIPLY(1 + 2, 3 + 4); // 11
int corrected_result = CORRECTED_MULTIPLY(1 + 2, 3 + 4); // 21The best practice is using functions. That is the purpose of functions.
int multiply(int a, int b) {
return a * b;
}
...
int result = multiply(1 + 2, 3 + 4);I used uppercase letters for macros to attract attention that they are macros. Seriously, you do not want to deal with compiler errors where the cause is a macro that you are not aware of.
And at this point, I suggest going through a tutorial, like this one to understand the basic consepts.It is advised not to use
using namespace std;
. If there exists anstd::multiply
with the same signature as of your function (same input-output), the standard one will be called without you noticing it. There are ways to prevent this but not knowing what happened is the problem in the first place. Let the compiler guide you and do not trick yourself.The flow of the code and the uses of the labels seem complicated. Write code that you will understand, for example, two months later. I suggest breaking seperate functionalities into functions, like
readFloat
,checkEpsilonValid
etc.Declare variables when they are needed. This way it is easier to follow the code. Also, using meaningful variables instead of two-letter ones improves the readability and you do not even need to comment later.
Finally, be aware that
setprecision
affectscout
throughout the program. It is about whether you care, but for bigger projects, I suggest usingprintf("%.06f")
, or"%.06g"
, then flush if necessary.
Related Topics
C++ Unordered_Map Using a Custom Class Type as the Key
How to Iterate Over the Elements of an Std::Tuple
Returning Multiple Values from a C++ Function
What Do the Following Phrases Mean in C++: Zero-, Default- and Value-Initialization
Difference Between New/Delete and Malloc/Free
Why Can't the Switch Statement Be Applied on Strings
Why Do I Get the Same Sequence For Every Run With Std::Random_Device With Mingw Gcc4.8.1
Where Are Static Variables Stored in C and C++
How to Get Assembler Output from C/C++ Source in Gcc
How to Enable C++11/C++0X Support in Eclipse Cdt
How to Reverse a String in Place in C or C++
In Which Scenario Do I Use a Particular Stl Container
Problems Importing Libraries to My C++ Project, How to Fix This
What Platforms Have Something Other Than 8-Bit Char
How to Make My Custom Type to Work With "Range-Based For Loops"
How to Take Input to an Array With Unknown Number of Elements