2

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.

Jachdich
  • 782
  • 8
  • 23
  • Please include the input you used with the supposedly broken snippet (i mean the "garbage" input) – 463035818_is_not_an_ai Feb 21 '20 at 16:28
  • @idclev463035818 I have specified what kind of input I gave to break each snippet. For the first one, it's entering garbage (i.e. not a hex number). For the second one, it's entering a partially valid hex number such as 0xASDF, and entering a hex number with the wrong capitalisation. – Jachdich Feb 21 '20 at 16:31
  • @idclev463035818 *anything* that's not a hex number. For example, 0xGEGEGAEOIHGAOIEHGHOUIAEGHOU is garbage. So is fajhbjiheegbiegbuegbuo. Literally anything that's not composed of 0-9, A-F, a-f. Valid input can start with 0x or 0X but that is not required – Jachdich Feb 21 '20 at 16:33
  • for the first snippet, the problem is not specific to hex numbers, but when input fails you have to do some clean up because there is still garbage left in the stream. For the second I have no clue because I dont know C i/o. Imho this is 2 questions in one and could be split – 463035818_is_not_an_ai Feb 21 '20 at 16:35
  • @idclev463035818 How do I do that then? It's one thing knowing the problem but I still do not know the solution to said problem. – Jachdich Feb 21 '20 at 16:38
  • I would try to look for a good duplicate for the first snippet, but it wouldnt cover the second, one of the reasons I think this is too many questions in one – 463035818_is_not_an_ai Feb 21 '20 at 16:40
  • 1
    For the first, see [How to use cin.fail() in c++ properly](https://stackoverflow.com/q/33284483/2602718) (there's probably a better dupe, but that's the first I could find). – scohe001 Feb 21 '20 at 16:41
  • https://wandbox.org/permlink/Za6WwNO4mB0Ktt9J – Marek R Feb 21 '20 at 16:42
  • @Jachdich This reads like C code, please use the C tag if you are asking a question about C code, if this is C++ code please use the C++ standard library (std::cout instead of printf, etc) – Object object Feb 21 '20 at 16:46
  • 1
    @TheGoldKnight23 if I remember correctly, `cin >> hex >> var` is c++ – Jachdich Feb 21 '20 at 16:47
  • @TheGoldKnight23 even if it looks like C, if it is compiled as C++ then it is C++ and the C tag would be offtopic – 463035818_is_not_an_ai Feb 21 '20 at 16:50
  • @Jachdich Yes but you use only C stuff in your code, scanf and printf are not type safe and generally arnt used in C++ code :) sorry not trying to have a go just trying to improve your code – Object object Feb 21 '20 at 16:51
  • also related: https://stackoverflow.com/a/32672104/4117728 you are basically just missing the call to `clear` – 463035818_is_not_an_ai Feb 21 '20 at 16:52
  • @idclev463035818 ok yep my mistake, I'll leave the comment as record but its incorrect, sorry – Object object Feb 21 '20 at 16:53
  • @TheGoldKnight23 i wouldnt care, but there are just too many questions begin wrongly tagged as C and C++ (actually not that many recently) – 463035818_is_not_an_ai Feb 21 '20 at 16:54
  • @TheGoldKnight23 yeah you're right, I shouldn't really be using printf but this *was* c code until I needed C++ features and I've not gotten around to replacing all of the `printf`s – Jachdich Feb 21 '20 at 16:56
  • @idclev463035818 I have removed one of the code snippets. See my edit for a new problem that has occured. – Jachdich Feb 21 '20 at 17:24

1 Answers1

3

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::iostreams meaning we are guaranteed to catch the error and std::numeric_limits as a more reliable way to clear the buffer

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
Object object
  • 1,939
  • 10
  • 19