noobcoder
noobcoder

Reputation: 33

How to allow only numbers in a variable?

I am having some problems with my code, here is a part of the code I am having problem with.

Point of this code is that if a user enters something that is not a number, for example a character p, program should ask user to enter again, this part works.

If user enters a combination of numbers and characters program should ask user to enter again. For example n12 or 12n are not valid.

Part where a character comes first, like n12 doesn't cause problems, but the problem comes where a number is first and something else second, like 12n, which is not valid, but my code prints out the number 12 and later says that number is not valid.

#include <iostream>

using namespace std;

int main ()
{
    int n;

    while(1)
    {

        cout<<"Enter a number, 0 for exit: ";
        cin>>n;

        if(!cin)
        {
            cout<<"You didnt enter a valid number\n";
            cin.clear();
            cin.ignore(1000,'\n');
            continue;
        }
        cout<<"Number is: "<<n<<endl;

        if(n==0) return 0;
    }
}

Examples of output of the code:

Enter a number, 0 for exit: 12
Number is: 12

Enter a number, 0 for exit: n
You didnt enter valid number

Enter a number, 0 for exit: n12
You didnt enter valid number

4° <--- this one does not work properly

Enter a number, 0 for exit: 12n
Number is: 12
Enter a number, 0 for exit: You didnt enter valid number

Edit: if it's possible, I'd like to solve this problem without including additional libraries.

Upvotes: 1

Views: 684

Answers (3)

gsamaras
gsamaras

Reputation: 73376

You could use isdigit(), std::string and std::all_of() from additional standard libraries (which is okay, not an overkill), like this (you store the input in the string and then you check if for every character of that string the isdigit function succeeds, which means that the input is purely numerically in that case):

#include <iostream>
#include <cctype>
#include <string>

int main()
{
    std::string str;
    std::cin >> str;
    (std::all_of(str.begin(), str.end(), [] (char c) { return isdigit(c); })) ? std::cout << "It's a number!\n" : std::cout << "isdigit() failed\n";
    return 0;
}

Output:

Georgioss-MacBook-Pro:~ gsamaras$ g++ -Wall -std=c++0x main.cpp 
Georgioss-MacBook-Pro:~ gsamaras$ ./a.out 
4
It's a number!
Georgioss-MacBook-Pro:~ gsamaras$ ./a.out 
f
isdigit() failed
Georgioss-MacBook-Pro:~ gsamaras$ ./a.out 
12n
isdigit() failed

Upvotes: 4

Remy Lebeau
Remy Lebeau

Reputation: 596703

You need to check the whole line that the user entered, not just part of it. istream::operator>> stops reading when it encounters a character that does not belong to the data type currently being read. That is why input like 12n gets processed as 12 and n separately.

You are not going to solve this using just <iostream> functionality alone. This is best handled using things like std::getline() and std::stoi()/std::strtol(), eg:

#include <iostream>
#include <string>

using namespace std;

bool to_int(const string &str, int &i)
{
    size_t pos;
    i = stoi(str, &pos);
    return (str.c_str()[pos] == '\0');
}

int main ()
{
    string line;
    int n;

    do
    {
        cout << "Enter a number, 0 for exit: ";
        getline(cin, line);

        if (!to_int(line, n))
        {
            cout << "You didn't enter a valid number\n";
            continue;
        }

        cout << "Number is: " << n << endl;

        if (n == 0) break;
    }
    while (1);

    return 0;
}

If you don't want to use a conversion function like std::stoi(), at least use a std::istringstream instead:

#include <iostream>
#include <string>
#include <sstream>

using namespace std;

bool to_int(const string &str, int &i)
{
    char c;
    istringstream iss(str);
    iss >> i;
    return !(iss.fail() || iss.get(c));
}

int main ()
{
    string line;
    int n;

    do
    {
        cout << "Enter a number, 0 for exit: ";
        getline(cin, line);

        if (!to_int(line, n))
        {
            cout << "You didn't enter a valid number\n";
            continue;
        }

        cout << "Number is: " << n << endl;

        if (n == 0) break;
    }
    while (1);

    return 0;
}

Upvotes: 1

Nyck
Nyck

Reputation: 183

Loop through the number, if it has something other than a digit, print "You didnt enter valid number", else print the number. We will be getting input as a string and using ctype.h to verify if the string's character it is a digit:

#include <iostream>
#include <string>
#include <ctype.h>
using namespace std;

int main()
{
    string n;
    bool is_valid = true;

    while (1)
    {

        cout << "Enter a number, 0 for exit: ";
        cin >> n;
        for (size_t i = 0; i < n.length(); i++) {

            if (!isdigit(n[i])) {
                cout << "You didnt enter a valid number\n";
                is_valid = false;
                break;
            }
        }
        if (is_valid) cout << "Number is: " << n << endl;

        if (n == "0") return 0;
    }
}

Upvotes: 0

Related Questions