Hello, OnlineGDB Q&A section lets you put your programming query to fellow community users. Asking a solution for whole assignment is strictly not allowed. You may ask for help where you are stuck. Try to add as much information as possible so that fellow users can know about your problem statement easily.

How do I make my cin only take numbers and nothing else?

+3 votes
asked Jan 19, 2021 by JULES ANDRE MAYONO (150 points)
Code: https://onlinegdb.com/SydeoB4J_ (main.cpp)

I'm making a simple calculator and have made functions for ease of use, I've made a block of code a function but it seems to be not working properly and I have no idea why.

I want the function "errorHandling" to do the same thing as my function "readNumberOnly" to only take in numbers and not characters or negative numbers but the output for errorHandling does not take any input at all and keeps looping.

2 Answers

0 votes
answered Nov 15, 2021 by Peter Fischi (320 points)

Jules,

   I created a simple bit of code that should solve your problems. https://onlinegdb.com/4QPjzcJbz. I made the code as self - explanatory as I could.

Hope this helps, 

     Peter Fischi 

commented Nov 15, 2021 by Peter Fischi (320 points)
I'm making a calculator also, but I wouldn't call it simple...
https://www.onlinegdb.com/Jf9Z-wQY1
commented Nov 15, 2021 by Peter Minarik (55,660 points)
Just a note here.

Checking if a string contains only digits (validating if it is an integral number) can be done simpler and more efficiently.

One can utilize the isdigit() function from the <cctype> header file. See here: https://www.cplusplus.com/reference/cctype/isdigit/

#include <cctype>

bool IsDigitsOnly(const string & input)
{
    for (int i = 0; i < input.length(); i++)
        if (!std::isdigit(input[i]))
            return false;
    
    return true;
}
0 votes
answered Nov 15, 2021 by Peter Minarik (55,660 points)

The Problem

When you fail to read something from std::cin, the input is not consumed, the buffer still contains data. Trying to read again will try to read the same invalid data (e.g. characters, when you're looking for digits) and that's why you end up with an infinite loop.

To fight this, you need to

  1. remove the error flag from the std::cin
  2. tell std::cin to ignore anything from the input that you do not want there (in your case everything until the end of the line)

The Fix

Please, see your fixed code below:

void errorHandling()
{
    bool valid = false;
    int operation = 0;
    while (valid == false)
    {   
        std::cout << std::endl << "\tEnter choice: ";
        if (!std::cin >> operation) // Did reading from std::cin fail?
        {
            std::cin.clear();       // Clear the error flag
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // Ignore anything until the new line character
        }
        if (operation >= 1 && operation <= 4) 
            valid = true;
        else 
            std::cout << "\tInput range is from 1 to 4 only." << std::endl;
    }
}

Welcome to OnlineGDB Q&A, where you can ask questions related to programming and OnlineGDB IDE and and receive answers from other members of the community.
...