6

I'm doing a problem where it asks to input an account number, which consists only of four digits. This has to be accomplished with basic beginner C++.

I need to figure out a way to restrict the input of the integer to four digits. A user should be able to put in 0043 or 9023 or 0001 and it should be an acceptable value....

I think I know how to accomplish it with a string.... getline(cin,input) and then check if input.length()==4?

But I've no idea how I would even do this with an integer input.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
B.K.
  • 9,982
  • 10
  • 73
  • 105

6 Answers6

2

Note that if 0043 is intended to be distinct from 43, then the input is not in fact a number, but a digit string, just like a telephone "number".

Read the line as a string input.

Check that the length of input is 4.

Check that each character in the string is <= '9' and >= '0'.

Something like:

std::string read4DigitStringFromConsole()
{
    bool ok = false;
    std::string result;
    while (!ok)
    {
        std::cin >> result;
        if (result.length() == 4)
        {
            bool allDigits = true;
            for(unsigned index = 0; index < 4; ++index)
            {
                allDigits = allDigits && ( 
                    (result[index] >= '0') && 
                    (result[index] <='9') 
                    );
            }
            ok = allDigits;
        }
    }
    return result;
}
Keith
  • 6,756
  • 19
  • 23
  • While this might "work", invalid input will simply leave the user stuck in an infinite "input mode" until he figures out how to finally feed an "ok" value – emartel Jan 25 '13 at 02:46
1

I like your idea to use a string as the input. This makes sense because an account "number" is simply an identifier. You don't use it in calculations. By if (sizeof(input)==4) I think you are trying to check the length of the string. The correct way to do this is if (input.length() == 4). This will check that the user inputs 4 characters. Now you need to make sure that each of the characters is also a digit. You can do this easily by taking advantage of the fact that the ASCII codes for digit characters are ordered as you expect. So if (input[i] >= '0' && input[i] <= '9') will do the trick with an appropriate for loop for the index i. Also, you probably need some kind of loop which continues to ask for input until the user enters something which is deemed to be correct.

Edit:

As an alternative to checking that each character is a digit, you can attempt to convert the string to an int with int value = atoi(input.c_str());. Then you can easily check if the int is a four-or-less-digit number.

Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268
  • @Marlon Haha, I completely missed that. Thank you for explaining the downvote. – Code-Apprentice Jan 25 '13 at 02:40
  • @Marlon I fixed it. So an undo will be greatly appreciated ;-) – Code-Apprentice Jan 25 '13 at 02:42
  • Typo at <= 9, should be '9' – doug65536 Jan 25 '13 at 02:50
  • Ah, yes, I messed that up too.. string.length() instead of sizeof() Thanks I'll steer away from the input[i] option because that's an array, unless i'm mistaken, and we didn't go over those yet – B.K. Jan 25 '13 at 03:09
  • @user2006048 You can use array notation with a string. Alternatively, you can use `input.at(i)`. – Code-Apprentice Jan 25 '13 at 03:11
  • Haven't gone over arrays yet. I'll just do length(). – B.K. Jan 25 '13 at 03:21
  • @user2006048 The problem is that just checking the length still allows an accounter number such as "abcd". Are letters and other characters allowed or just digits? – Code-Apprentice Jan 25 '13 at 03:22
  • Well, just digits. But, I think he'll pretty lenient about input validation at this point, since we haven't even reached arrays and just started on functions. – B.K. Jan 25 '13 at 03:30
  • @user2006048 Your teacher might also be expecting you to read the input as an `int` unlike my answer here. – Code-Apprentice Jan 25 '13 at 03:34
  • Yeah, he also wants it to be able to store things like 0004 as a valid account number. – B.K. Jan 25 '13 at 05:54
  • @Noobacode Does your teacher expect you to *store* the account number as "0004" or does he want you to *display* it that way? There is a huge difference. I have also added another suggestion to my answer. – Code-Apprentice Jan 26 '13 at 00:11
  • He expects it to be submitted as equivalent of 0004, so he should be able to enter any 4 digits, even 0's and they'd be an acceptable value. I went ahead with the string option. Hopefully it'll satisfy the requirement. – B.K. Jan 26 '13 at 01:56
  • @Noobacode What do you mean by "submitted"? This still doesn't answer my question. Input, output, and storage are three *very* different things. You can easily allow "0004" as input, store it as the `int` value `4` and output it as "0004". Alternatively, you can store it as the string "0004" or even the string "4" and still do the output as just described. – Code-Apprentice Jan 27 '13 at 00:29
1

Something like this should work. Once the user enters something with exactly four characters you can validate it. The rest of the logic is up to you.

#include <iostream>
#include <string>

int main() {
    std::cout << "Enter a PIN Number: ";
    std::string pinStr;
    while(std::getline(std::cin,pinStr) && pinStr.size() != 4) {
        std::cout << "Please enter a valid value\n";
    }
}

Should you want to store it in an integer form, holding the integers in an std::vector might be beneficial. You can do this easily (loop unrolling was for clarity):

#include <iostream>
#include <string>
#include <vector>

int main() {
    std::cout << "Enter a PIN Number: ";
    std::string pinStr;
    while(std::getline(std::cin,pinStr) && pinStr.size() != 4 ) {
        std::cout << "Please enter a valid value\n";
    }
    std::vector<int> pin;
    pin[0] = pinStr[0] - '0';
    pin[1] = pinStr[1] - '0';
    pin[2] = pinStr[2] - '0';
    pin[3] = pinStr[3] - '0';

    //pin now holds the integer value.
    for(auto& i : pin)
        std::cout << i << ' ';
}

You can see it running here

Rapptz
  • 20,807
  • 5
  • 72
  • 86
  • Yeah, that's pretty much what I had as far as string goes... guess I'm stuck with a string. Oh well, I hope he accepts it. I mean... we haven't gone over anything that would suggest me that I could do it in any other way. I could do a while loop that keeps on reading in characters until I have four, but I'm not sure if that would work. – B.K. Jan 25 '13 at 03:04
  • 1
    @user2006048 did you check my edit? It shows you a way to store it in an integer form, by holding it in an array of ints. That way `0000` is valid. – Rapptz Jan 25 '13 at 03:05
  • Yeah, unfortunately I can't use arrays yet. Thanks though. I think I'll just go with the good ol' string and length(). – B.K. Jan 25 '13 at 03:22
0
// generic solution
int numDigits(int number)
{
    int digits = 0;
    if (number < 0) digits = 1; // remove this line if '-' counts as a digit
    while (number) {
        number /= 10;
        digits++;
    }
    return digits;
}

similar to this post. Then you can call this function to check if the input is 4 digits.

Community
  • 1
  • 1
Mark
  • 8,046
  • 15
  • 48
  • 78
  • This would work for anything that uses numbers such as 1234... however, if the account number is 0001, it'll display the number of digits as 1. I think for simplicity I'll go with string, and pray that he accepts it, I just don't know anything in basic form of C++ that would do it. – B.K. Jan 25 '13 at 03:19
  • that means, you are checking if a char array (string) is a four digit-all-numeric string? – Mark Jan 25 '13 at 03:23
0

You probably want your code to be responsive to the user input, so I would suggest getting each character at a time instead of reading a string:

std::string fourDigits;
char currentDigit;

std::cout << "Enter 4 digits\n";
for(int i = 0; i < 4; ++i)
{
    currentDigit = getch();
    if(isdigit(currentDigit))
    {
        fourDigits += currentDigit;
        std::cout << currentDigit; // getch won't display the input, if it was a PIN you could simply std::cout << "*";
    }
    else
    {
            // Here we reset the whole thing and let the user know he entered an invalid value
        i = 0;
        fourDigits = "";
        std::cout << "Please enter only numeric values, enter 4 digits\n";
    }
}

std::cout << "\nThe four digits: " << fourDigits.c_str();

This way you can handle gracefully invalid character instantly. When using strings, the input will only be validated once the user hits Enter.

emartel
  • 7,712
  • 1
  • 30
  • 58
  • That's an awesome solution, however, I'd have to include conio.h and 1. I can't get it to work with NetBeans (tried before)... 2. We haven't this header, so I don't want to mess with it for this assignment... Thanks though. – B.K. Jan 25 '13 at 03:14
  • Its too bad because the way the input is buffered with `std::cin` is really annoying for this kind of thing, no feedback is possible until a new line is entered. – emartel Jan 25 '13 at 04:19
0

So I was going over how I can use an integer type to get the input, and looked at char... since it's technically the smallest integer type, it can be used to get the code... I was able to come up with this, but it's definitely not refined yet (and I'm not sure if it can be):

int main() {
    int count=0;

    while(!(count==4)){
        char digit;
        cin.get(digit);
        count++;
    }

    return 0;
}

So, the loop keeps going until 4 characters are collected. Well, in theory it should. But it doesn't work. It'll stop at 2 digits, 5 digits, etc.... I think it could be the nature of cin.get() grabbing white space, not sure.

B.K.
  • 9,982
  • 10
  • 73
  • 105