C++ для начинающих. Ввод только чисел

Одним из вопросов, возникающих у новичков при попытках защитить программу от неправильного ввода данных, оказывается вопрос ввода только чисел. Во многих первых учебных задачах требуется ввод именно числовых значений. Над решением такой задачи можно поломать голову. Защита своей программы от потенциальных проблем — одна из обязательных истин любого программиста. Ведь если вы напишете программу, которая будет или работать странно, или раз через раз выдавать ошибки — мало какому пользователю понравится.
Одним из наиболее употребляемых способов обязательного ввода чисел может оказаться вот такой:

В некоторых случаях такой защиты от дурака достаточно.
Для решения этой задачи можно использовать ввод строки с последующим преобразованием строки в числовое значение. Строку удобно проверять на присутствие нехарактерных числам символов:

Этот способ лучше первого тем, что если ввести в число несколько, например, точек: 598.66.66 — то это будет считаться ошибкой, а в первом способе будет считаться, что было введено 598.66

Недостаток этого способа — это то, что приходится делать преобразования, а любые преобразования влияют на время работы программы. И ещё один недостаток — это не очень хорошая степень логичности. Это немного ненормально, что для того, чтобы ввести число, мы сначала вводим строку.

  • Для преобразования строки к числу в С используют или функцию atof (для дробного представления), или функцию atoi (для представления строки как целого число).
Теперь посмотрим на наиболее распространённые варианты решений. Тому, кто хочет побольше узнать, имеет смысл почитать описываемое ниже.
Напишем простую программу, вычисляющую среднее арифметическое. Предположим, вы работаете в страховой компании и ваша страховая компания оплачивает страховку в случае кораблекрушения, покрывая некоторую часть расходов убытка клиента из-за кораблекрушения. Согласно вашему договору с клиентом, вы оплачиваете половину стоимости груза. Вот нам и нужно посчитать, сколько мы будем платить. Для облегчения (в пользу сейчас обучающегося) предположим, что у корабля есть санкции, ограничивающие количество перевозимого товара, отчего корабль не имеет права перевозить больше 5 наименований груза. Но не будем ограничиваться стоимостью. Поскольку нас интересует только цена и известно, что есть максимум 5 предметов торговли, а надо рассчитать среднюю стоимость — то приступим к написанию программы.
По условию сложившейся задачи вы должны самостоятельно прикидывать, что потребуется для решения. В данном случае нам понадобится массив из 5 элементов, в ячейки которого мы будем записывать цену каждого предмета торговли потерпевшего крушения судна.

Если собрать программу из показанного кода, то чтобы не вводить все значения, можно ввести любое не число и тогда ввод прекратится. Также ввод будет прекращён, если ввести весь максимум значений.
Несмотря на кажущееся удобство есть в этом примере небольшой подводный камень. Если вводить в arr_cost[i] не число, то цикл конечно прекращается, но прекращается не только цикл: отключается вообще ввод в cin. Пример листинга #4 показывает попытку развития программы, где нагляден эффект отключения, обычно непонятный простым новичкам:

Поскольку ввод из-за попытки внедрения cin неожидаемого cin-ом типа отключился, то и попытки тщетны. Чтобы заново включить ввод, нужно будет добавить немного кода (см строки 37-):

В зависимости от типа запиываемого значения может быть небольшое различие, но в целом если тип символьный, то нужно учитывать символ нажатого Enter, эта строчка закомментирована, а если числовой, то просто нужно забрать из буфера введённый символ, останется переключить cin в рабочее состояние, для чего использовалось cin.clear().
Теперь поговорим о самом коде, о цикле while и что это в нём за cin >> arr_cost[i].

arr_cost[i] — это просто очередная ячейка массива, индекс которой i, её можно использовать как обычную переменную, тип которой соответствует типу заявленному массиву.
(cin >> arr_cost[i]) — это уже более сложно, но тем не менее объяснимо. Сама по себе такая запись обозначает прочитать что-то с клавиатуры и запомнить прочитанное значение в arr_cost[i], но кроме непосредственно чтения, для нас существует возможность узнать произошёл ли ввод удачно или что-то пошло не так.

  • Если cin используется как часть проверочного условия, он преобразуется в тип bool. Преобразованное значение равно true, если ввод прошел успешно, и false — в противном случае.
Почему ввод прекращается, если введено некорректное значение? Это происходит потому что для логических выражений || и && порядок анализа всегда слева-направо, а если левая часть выполняет/нарушает условие (в зависимости от того, что именно нужно), то правая просто не выполняется. Т. е. компилятор просто не проверяет ненужный для проверки хвост.

Поскольку когда мы выходим на граничащее значение массива и наращиваем i, 5 < 5 == false — цикл завершается, а cin просто хвостовая ненужность.
В том случае, если надо ввести все, например, значения, то нужной подойти к программе немного не так, как было в произошедшем сейчас разборе. Предположим, что программа обнаружила неправильный ввод пользователя. Она должна выполнить три действия:

  • Сбросить состояние cin для принятия нового ввода
  • Освободиться от некорректного ввода
  • Предложить пользователю повторить ввод
Обратите внимание:

  • Программа должна сбросить cin перед тем, как отклонять неверный ввод.
Пример:

Все комментарии на сайте проверяются, поэтому ваш комментарий может появиться не сразу. Для вставки кода в комментарий используйте теги: [php]ВАШ_КОД[/php]

10 комментариев: C++ для начинающих. Ввод только чисел

  • Иван Иванов говорит:

    Гарантировать ввод числа (например, float) можно ещё так:

    Автор сайта отвечает
    Разница между кодом показанным в статье и кодом, показанным вами, в том, что код из статьи просто не даст вводить то, что к части числа не относится. Ваш код позволит вводить число с частью не относящейся к построению числа отбрасывая все, что за этой частью.

    Точнее если ввести 5ааа5ааа
    ваш код сохранит в переменную 5
    код из сайта сохранит в переменную 55

    тут подкорректирован для mingw




    1



    0
  • fENGO говорит:

    я ввожу плюс или минус,а возращает не false, a true




    0



    1
    • admin говорит:

      Да, это проверка, которая определяет + или — принадлежат к знаку числа или являются частью строки:
      +788 — число
      -55 — число
      55-99 — не число




      1



      0
      • fENGO говорит:

        ЭТО БУДЕТ ПЕРЕПОЛНЕНИЕ СТЕКА?




        0



        0
  • fENGO говорит:

    я ввожу плюс или минус,а возращает не false, a true




    0



    0
  • fENGO говорит:

    Не понимаю это обьясните,пожалуйсто




    0



    0
    • admin говорит:

      if (strcchr(Строка, Искомый_Символ) == NULL) return false;
      Функция strchr возвращает указазатель, если символа в строке найдено не было, то возвращается нулевой указатель. Если символа не нашлось (т. е. функция вернула нулевой указатель), то отдаём false




      0



      0
  • fENGO говорит:

    ЭТО БУДЕТ ПЕРЕПОЛНЕНИЕ СТЕКА?




    0



    0

Добавить комментарий

Ваш e-mail не будет опубликован.

+ 83 = 90

Поиск

 
     

Случайная книга в электронном формате

https://www.litres.ru/a-o-matushin/programmirovanie-mikrokontrollerov-strategiya-i-taktika-22879970/?lfrom=15589587

Последние комментарии

Яндекс.Метрика
НАГРАДИ АВТОРА САЙТА
WEBMONEY
R375024497470
U251140483387
Z301246203264
E149319127674

Демотиватор как забыть С++ для чайников

Выражаю свою признательность

  • Максиму очень признателен за указание на мои ошибки и неточности.
  • Sergio ===> за оказание помощи в исправлении моих ошибок
  • Gen ===> за правильное стремление помочь другим новичкам и выявления моих ошибок