Infinite Loop With Cin When Typing String While a Number Is Expected

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); // 21

    The 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 an std::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 affects cout throughout the program. It is about whether you care, but for bigger projects, I suggest using printf("%.06f"), or "%.06g", then flush if necessary.



Related Topics



Leave a reply



Submit