0

Всем доброго времени суток! Мне нужно вводить имя книги и проверять в блоке try, если введена пустая строка или клавиша ENTER, то выводилось сообщение о неверном вводе. У меня получается так что блок catch почему то пропускается и не ловит ошибку. Заранее спасибо за ответы!

char* namebook = (char*)malloc(20);//буфер записи названи
puts("Введите название книги");
        try //проверка исключения
        {
            scanf("%s", namebook);
            int a = strlen(namebook);
            if (a == 0)
                throw(char*)"Вы ввели пустую строку";
        }
        catch (const char* exception)
        {
            puts(exception);
            throw(char*)"Вы ввели пустую строку";
        }
pumpkin
  • 13
  • 4
  • https://stackoverflow.com/questions/7970617/how-can-i-check-if-char-variable-points-to-empty-string В первом же ответе показано решение вашей задачи – Frehzy May 24 '22 at 20:56
  • 2
    scanf не может вводить пустые строки – avp May 24 '22 at 20:59
  • Я попытася вводить через cin и сделал проверку на конец строки (написал "\0") и все равно при нажатии ENTER не выводится сообщение об исключении – pumpkin May 24 '22 at 21:12
  • Покажите, как именно через cin. – HolyBlackCat May 24 '22 at 21:19
  • std::cin >>namebook; if (namebook == "\0" or namebook == "\n") throw(char*)"Вы ввели пустую строку"; – pumpkin May 24 '22 at 21:22
  • >> тоже не может в пустые строки. Правильно так: std::string str; std::getline(std::cin, str);. Дальше str.empty() проверяет на пустоту. Еще, сырые строки обычно не кидают как исключения (и что за странный каст?). Лучше throw std::runtime_error("текст");. – HolyBlackCat May 24 '22 at 21:49
  • Еще, пишите в начале комметария @username, а то мы не получаем уведомления. – HolyBlackCat May 24 '22 at 21:50
  • @HolyBlackCat, как я понял, сначала инициализируем строку, затем вводим, проверяем на пустоту. Только вот у меня уже строка создана через char* namebook = (char*)malloc(20); и поэтому у меня сразу выводит сообщение об исключении, т.к строка изначально пуста и консоль не дает ввести ее – pumpkin May 24 '22 at 22:07
  • И ещё if (namebook == "\0" or namebook == "\n") не сработает, так как namebook - указатель, и вы сравниваете указатели, а не строки. Правильно: if (strcmp(namebook,"\0") == 0 || strcmp(namebook,"\n") == 0), или так: if (namebook[0] == '\0' || namebook[0] == '\n' && namebook[1] =='\0') – LShadow77 May 24 '22 at 22:12
  • @pumpkin А чем std::string не угодил? – HolyBlackCat May 24 '22 at 22:20
  • @HolyBlackCat к сожалению по требованию преподавателя нужно именно так, как я описал выше. Есть варианты что делать если консоль не дает вводить и сразу бросает исключение? – pumpkin May 24 '22 at 22:25

1 Answers1

0

Как вам такой вариант?

#define BUFFER_SIZE 20

char* namebook = (char*)malloc(BUFFER_SIZE);//буфер записи названи puts("Введите название книги");

try //проверка исключения { fgets(namebook, BUFFER_SIZE, stdin); if (namebook[0]=='\0' || namebook[0]=='\n') throw "Вы ввели пустую строку"; } catch (const char* exception) { puts(exception); throw "Вы ввели пустую строку"; }

fgets() умеет работать с пустыми строками, к тому же защищает от переполнения буфера.

LShadow77
  • 2,157
  • хороший вариант! но к сожалению так же не дает ввести название и сразу бросает исключение( не понимаю почему консоль не дает ввести данные – pumpkin May 24 '22 at 22:36
  • @pumpkin а вот это странно. У меня всё вводится, и исключение бросается правильно, как и должно быть. Вызов fflush(stdin); перед fgets(...) не забыли? Если нет, то может закралась ошибка в другой части вашего кода, а не в этом фрагменте... – LShadow77 May 24 '22 at 22:40
  • честно говоря, я пишу сейчас код на онлайн компиляторе т.к у меня мак, а на visual studio 2022 для мак нету поддержки c++, поэтому возможно вы правы, что ошибка где то в остальном коде, в любом случае спасибо за ответы! – pumpkin May 24 '22 at 22:44
  • 1
    Автору вопроса: скорее всего, вы что-то вводите перед названием книги с использованием >> или scanf — см. вопрос https://ru.stackoverflow.com/q/834447/195342 Автору ответа: приведение к char* строкового литерала — мягко говоря, неоднозначное решение. Чтоб не выразиться куда резче... – Harry May 25 '22 at 04:26
  • генерировать исключение, в стиле "С" коде? Для чего это смешивание языков? – AR Hovsepyan May 25 '22 at 08:20
  • @Harry "приведение к char* строкового литерала — мягко говоря, неоднозначное решение" - скорее бессмысленное, поправил) – LShadow77 May 25 '22 at 08:51
  • @AR Hovsepyan C-код зачастую менее ресурсоёмкий, к тому же является законной частью языка C++. Так что почему нет? – LShadow77 May 25 '22 at 08:53
  • @Harry "Автору вопроса: скорее всего, вы что-то вводите перед названием книги с использованием >> или scanf — см. вопрос ru.stackoverflow.com/q/834447/195342" Скорее всего так и есть. Вообще-то вызов fflush(stdin) был призван решить как раз эту проблему, однако похоже, что в случае stdin это не работает. Вот, что нашёл: https://stackoverflow.com/questions/9122550/fflushstdin-function-does-not-work – LShadow77 May 25 '22 at 09:05
  • Я говорю о стиле, а не о языковых средствах. Если полагаться на преимуществ "С" и на программиста, тогда нужно проверять errno, а не кидать исключение. В данном случаи стиль "С " абсолютно никакого преимущество не дает по сравнению с проверкой, например, if (cin.peek() != '\n') cin >> namebook; else throw " ??? "; – AR Hovsepyan May 25 '22 at 09:21
  • 1
    fflush(stdin) эту проблему не решает ничуть, это же не опустошение буфера... – Harry May 25 '22 at 09:29
  • P.S. Чтобы генерировать снова, достаточно сказать throw, но это ни к чему(приведет к необработанному исключению), так как исключение обрабатывается на месте. – AR Hovsepyan May 25 '22 at 09:41
  • @Harry я тут немного порылся - оказывается это далеко нетривиальная задача, стандартными средствами C++ очистить ввод от паразитных '\n' и при этом не блокировать поток. Поразительно просто! Я бы плюнул, и сделал это с помощью Win API... – LShadow77 May 25 '22 at 09:52