zizou
zizou

Reputation: 67

Undefined behaviour when entering `char` for integer variable with `std::cin`

I have this while loop, just to check if the entered number is 2. If the user entered by accident a letter instead of a number the loop goes to infinity even though I've added isdigit, but didn't fix the loop from going crazy if the input is a character. This is code:

int num1;
bool cond {false};
while(!cond){
    cout<<"enter 2:";
    cin>>num1;
    if (!isdigit(num1)){
        cout<<"not a digit:";
        cin>>num1;
    }
    //
    if(num1 == 2)
        cond = true;
}

Upvotes: 3

Views: 1273

Answers (5)

AngryParticle
AngryParticle

Reputation: 1539

I would suggest trying something a little more straightforward instead of your current code:

#include <iostream>
#include <limits>
using namespace std;

int main()
{
   int num1;
   cout << "Please enter the number 2:";
   cin >> num1;
   while (num1 != 2)
   {
       cin.clear(); //Clears the error flag on cin. 
       cin.ignore(numeric_limits<streamsize>::max(), '\n');
       cout << "You did not enter the number 2, Please try again:";
       cin >> num1;
   }
   
   return 0;

}

Now, cin.ignore(numeric_limits<streamsize>::max(), '\n'); is when it ignores up until '\n' or EOF \n is the delimiter meaning that, that is the character at which cin will stop ignoring.

Furthermore, numeric_limits<streamsize>::max() is basically saying there is no limit to the number of characters to ignore.

You need to use the header file #include<limits> to use this.

Upvotes: 2

user14248283
user14248283

Reputation:

Why does the loop iterate infinitely?

Let's take this example

int a;

std::cin >> a;
std::cout << "Entered: " << a;

Now let's test it with different inputs

with int

5
Entered: 5

10
Entered: 10

Yes just as we would expect, but what happens when you enter a char?

with char

r
Entered: 0

f
Entered: 0

Why does this happen?

When you declare the variable int, and then do std::cin >> , you are telling the input method that the user will enter an integer, but when it doesn't get what it expected, it will fail. C++ will not implicitly convert the value of char into int. Hence, you get strange results.

How to solve this?

As I have mentioned earlier, it fails. When this fails you can catch it this way

if (!(std::cin >> a)) 
{
    std::cout << "Invalid input ! \n";
}

We're saying, if the input fails, show the message.

let's test this new code.

int a;
if (!(std::cin >> a))
{
    std::cout << "Invalid input !\n";
}
else
{
    std::cout << "Entered: " << a;
}

5
Entered: 5

r
Invalid input !

How to print char value of the int?

If you want to just print the ASCII value of the entered number, you need to cast the value into char.

You can do

int num = 48;
char character_value = num;

Here C++ will implicitly convert char into int.

But if you need a safer type of conversion, prefer using static_cast<>. The syntax looks like this

int a = 5;
char character_value = static_cast<char>(a);

Static cast in C++
Type casting in C++
Dealing with invalid input in C++

Upvotes: 0

sfb103
sfb103

Reputation: 384

I recommend separating the reading of input data from converting it to a number. A good method for this is to use stringstream. Here's a working example:

#include <iostream>
#include <string>
#include <sstream>

using namespace std;

int main()
{
    int num1;
    string input;
    bool cond{ false };
    cout << "enter 2:";
    while (!cond) {
        getline(cin, input);
        stringstream ss(input);
        ss >> num1;
        if( ss.fail() ){
            cout << "not a digit:";
            continue;
        }
        //
        if (num1 == 2)
            cond = true;
        else
            cout << "enter 2:";
    }

    return 0;
}

Upvotes: 2

erwoods89
erwoods89

Reputation: 43

int num1;
bool cond {false};
do{
    cout<<"enter 2:";
    cin>>num1;
    if (cin.good()) {
        cond = true;
    }else {
        cin.clear();
        cin.ignore();
        cout << "Invalid, please enter 2." << endl;
    }
}while(!cond);

While false, execute statements. Also, if you want the user to re-enter a number, cin must be flushed.

Upvotes: 1

the_devulaper
the_devulaper

Reputation: 34

Try declaring the variable num1 as char because isdigit(ch) works for char and not for int.

I hope this solves your problem

Upvotes: 0

Related Questions