0

I'm using java to write a program for class. I have the first portion of code written but I can't quite figure out what I'm doing wrong. When I run the program it lets me enter a card number but then it gives me an error. My professor said that it's because for this program the card number is too long to be stored as an int. I understand that, so it's being stored in a String. But I'm still getting an error. Help please.

package creditCard;

import java.util.Scanner;

public class Card {

    public static void main(String[] args) {
        //Set up a scanner
        Scanner in = new Scanner(System.in);
        
        //Set up a boolean named creditCard and set it to false
        boolean validCreditCard = false;
        
        //Loop while not a valid credit card
        while (!validCreditCard) {
            
            //Prompt the user for a potential credit card number
            System.out.print("Please enter a card number: ");
            
            //Get the credit card number as a String - store in potentialCCN 
            String potentialCCN = in.next();
            
            //Use Luhn to validate a credit card
            //Store the digit as an int for later use in lastDigit
            int lastDigit = Integer.parseInt(potentialCCN);
            
            //Test then comment out! -check the last digit
            System.out.println(lastDigit+"Check the last digit");
            
            //Remove the last digit from potentialCCN and store in potentialCCN using String's substring
            potentialCCN = potentialCCN.substring(15);
            
            //Test then comment out! - check potential credit card number
            System.out.println(potentialCCN);
            
        }

    }

}
Federico klez Culloca
  • 26,308
  • 17
  • 56
  • 95
  • 2
    What error do you get? Which number did you enter? – Reporter Oct 14 '20 at 15:17
  • 2
    Credit card numbers are generally 15-16 digits long, but can be up to 19 digits. An `int` can only store 9-10 digits, so `parseInt()` will throw `NumberFormatException` because the value exceeds the range supported by `int`. You could maybe use `long` or `BigInteger`, but why? You're never going to be treating a credit card number as a numerical value, even though it's all digits, so keep it as a `String`. – Andreas Oct 14 '20 at 15:23
  • I think the problem may be `int lastDigit = Integer.parseInt(potentialCCN);`, here I assume (because of the variable name) you want to pick "the last digit", but `parseInt()` is parsing the whole String. I agree with @Andreas, you can work with String and pick the desired digits for your checks. – Adam Oct 14 '20 at 15:28
  • @Andreas it appears that OP wants to extract/parse the last digit for the Luhn algorithm – OneCricketeer Oct 14 '20 at 15:30

4 Answers4

0

Your problem is with parseInt. You can overcome this problem using BigInteger, like

BigInteger bi = new BigInteger(potentialCCN);

or you can use regular expressions to validate that potentialCCN is a 16 digit number, like

^[0-9]{16,16}$

ControlAltDel
  • 33,923
  • 10
  • 53
  • 80
  • 3
    That might fix the int issue, but still makes no sense. There is no point to have a cardnumber as either int or BigInteger. – Tom Oct 14 '20 at 15:22
  • 1
    *"validate that potentialCCN is a 16 digit number"* Not all credit card numbers are 16 digits long. They can be between [12 and 19 digits](https://en.wikipedia.org/wiki/Payment_card_number#Issuer_identification_number_(IIN)). – Andreas Oct 14 '20 at 15:24
  • 1
    I'm not sure real cards can have leading zeros, but it's still possible, so int/bigint wouldn't work – OneCricketeer Oct 14 '20 at 15:25
0

If the number you entered as a card number is larger than Integer.MAX_VALUE that has a value of 2147483647, then this line of code (copied below) is always going to throw you a NumberFormatException.

         int lastDigit = Integer.parseInt(potentialCCN);

The reason for it is that int is not able to hold such a value, but is restricted to 2^31 − 1 or as written above, 2147483647. Therefore, if you are eligible to enter such values as card numbers you should use some type that does not have such constraints.

kiselitza
  • 119
  • 8
0

If you want the last digit, you've got your substring backwards, it's removing everything up to that digit, then storing it back in your card number variable.

You're also parsing the entire number rather than getting the last digit

Try the following

        String potentialCCN = in.nextLine();
        
        //Use Luhn to validate a credit card
        //Store the digit as an int for later use in lastDigit
        int lastDigit = Integer.parseInt(potentialCCN.substring(potentialCCN.length()-2);
        
        //Test then comment out! -check the last digit
        System.out.println(lastDigit+"Check the last digit");
        
        //Remove the last digit from potentialCCN and store in potentialCCN using String's substring
        potentialCCN = potentialCCN.substring(0, potentialCCN.length()-2);
        
OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
0

You're never going to be treating a credit card number as a numerical value, even though it's all digits, so keep it as a String.

I have the same opinion as Andreas. You can do a substring operation to get the part of the cardNumber that you want to validate, and then do a Long.parseLong()

Other thingys that I saw in your code:

  • prefer BufferedReader and InputStream (https://stackoverflow.com/a/34955813/7192651) over Scanner because it is more faster
  • write as few comments as possible as clean code principles suggest, because comments become outdated, if you forget to change them, after changing your source code. If you added them specifically for stackoverflow users sake then that is not a problem ;)
Yuqiu G.
  • 348
  • 4
  • 7
  • Your remake regarding BufferedReader and Scanner is generally true, but makes no difference when reading from System.in, especially when a user manually writes the input into the console window. – Tom Oct 15 '20 at 09:52