I've looked around on the internet for a while now and I've found that the C++ way of getting user input as a hexadecimal number is using cin >> hex >> variable
. I can't currently get this to work in my situation. Here's what I want to happen for a range of user inputs:
>0xFF -> variable = 0xFF;
>FF -> variable = 0xFF;
>122 -> variable = 0x122;
>garbage -> ask again;
>0XFfFfA -> variable = 0xFFFFA;
Here is the code I have and the problem with it:
int endAddr;
do { printf("Enter end addr: "); } while (!(cin >> hex >> endAddr));
Problem: after entering garbage, it continues to loop printing out "Enter end addr: " instead of letting the user try again.
Any help regarding this code snippet would be very useful. Thanks in advance.
EDIT:
As per suggestion I've looked at this post and adjusted my code accordingly:
while (true) {
printf("Enter start addr: ");
if (cin >> hex >> startAddr) {
break;
}
cin.clear();
cin.ignore();
}
//rest of code
The issue now is that if I enter a string such as le
, it prints the prompt again however it then continues to the rest of the code. Why is this? If I remove cin.ignore()
, it does the loopy thing discribed above.
cin.ignore()
will ignore the last character in its internal buffer. You need to use cin.ignore(std::numeric_limits<std::streamsize>::max())
to reset back to the last EOF. Then you can check the next input reliably.
After trying to work this one out (good practice with streams :D), I have come up with a solution
int startAddr;
std::cin.exceptions(std::ios_base::failbit);
while (true) {
std::cout << "Enter start addr: ";
try {
std::cin >> std::hex >> startAddr;
break;
} catch(std::exception&) {
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
std::cout << "Invalid number\n";
}
}
This makes use of the ability to set a failbit as an exception for std::iostream
s meaning we are guaranteed to catch the error and std::numeric_limits
as a more reliable way to clear the buffer