Надежно получить шестнадцатеричный ввод пользователя в C ++ с обработкой ошибок - PullRequest
2 голосов
/ 21 февраля 2020

Я некоторое время осматривал inte rnet и обнаружил, что C ++ способ получения пользовательского ввода в виде шестнадцатеричного числа использует cin >> hex >> variable. Я не могу заставить это работать в моей ситуации. Вот что я хочу сделать для диапазона пользовательских вводов:

>0xFF    -> variable = 0xFF;
>FF      -> variable = 0xFF;
>122     -> variable = 0x122;
>garbage -> ask again;
>0XFfFfA -> variable = 0xFFFFA;

Вот код, который у меня есть, и проблема с ним:

int endAddr;
do { printf("Enter end addr: ");   } while (!(cin >> hex >> endAddr));

Проблема: после ввода мусора это продолжает l oop распечатывать «Enter end addr:» вместо того, чтобы позволить пользователю повторить попытку.

Любая помощь относительно этого фрагмента кода была бы очень полезна. Заранее спасибо.

РЕДАКТИРОВАТЬ:

В соответствии с предложением я посмотрел на этот пост и соответственно скорректировал мой код:

while (true) {
    printf("Enter start addr: ");
    if (cin >> hex >> startAddr) {
        break;
    }
    cin.clear();
    cin.ignore();
}
//rest of code

проблема заключается в том, что если я введу строку, такую ​​как le, она снова напечатает подсказку, но затем продолжит работу с остальным кодом. Почему это? Если я уберу cin.ignore(), то получится зацикленное выше.

1 Ответ

3 голосов
/ 21 февраля 2020

cin.ignore() будет игнорировать символ последний во внутреннем буфере. Вам нужно использовать cin.ignore(std::numeric_limits<std::streamsize>::max()) для возврата к последнему EOF. Затем вы можете надежно проверить следующий вход.

После попытки поработать с этим (хорошая практика с потоками: D), я нашел решение

    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"; 
        }
    }

Это использует способности устанавливать биты как исключение для std::iostream s, что означает, что мы гарантированно отловим ошибку, и std::numeric_limits как более надежный способ очистки буфера

...