0

I'm trying to write a program that will validate a Canadian postal code.

Given the two formats

  1. A1A1A1
  2. A1A 1A1

Problem

I have problems getting my code to recognize the white space in the second format.

When I validate for the second format, it prints "Invalid" twice even though it's a legitimate postal code.

Code

public class validatePostalCodeTest {
  public static void main(String[] args) {
    Scanner kb = new Scanner(System.in);
    System.out.println("Please enter postalcode:");
    while (kb.hasNext()){
        String posCode = kb.next();
        if (posCode.length() > 7) 
            System.out.println("\nInvalid");
        if (posCode.length() < 6) 
            System.out.println("\nInvalid");    
        if (posCode.length()== 7){
            boolean valid = true;
            for (int i = 0; i < posCode.length(); i++){
                char a = posCode.charAt(0);
                char b = posCode.charAt(2);
                char c = posCode.charAt(4);
                char d = posCode.charAt(1);
                char e = posCode.charAt(5);
                char f = posCode.charAt(6);
                char g = posCode.charAt(3);
                if(! Character.isLetter(a))
                    valid = false; 
                else if (! Character.isLetter(b))
                    valid = false;
                else if (! Character.isDigit(c))
                    valid = false;
                else if (! Character.isDigit(d))
                    valid = false;
                else if (! Character.isLetter(e))
                    valid = false;
                else if (! Character.isDigit(f))
                    valid = false;
                else if (! Character.isWhitespace(g))
                    valid = false;
                break;
            }
            if (valid) System.out.println("\nValid");
            else System.out.println("\nInvalid");
        }
        if (posCode.length()== 6){
            boolean valid = true;
            for (int i = 0; i < posCode.length(); i++){
                char a = posCode.charAt(0);
                char b = posCode.charAt(2);
                char c = posCode.charAt(4);
                char d = posCode.charAt(1);
                char e = posCode.charAt(3);
                char f = posCode.charAt(5);
                if(! Character.isLetter(a))
                    valid = false; 
                else if (! Character.isLetter(b))
                    valid = false;
                else if (! Character.isLetter(c))
                    valid = false;
                else if (! Character.isDigit(d))
                    valid = false;
                else if (! Character.isDigit(e))
                    valid = false;
                else if (! Character.isDigit(f))
                    valid = false;
                break;                    
            }
            if (valid) System.out.println("\nValid");
            else System.out.println("\nInvalid");
        }
        System.out.println("\nPlease enter a postalcode:");
    }
    System.out.println("Program ending due to end-of-file");
  }
}
hc_dev
  • 8,389
  • 1
  • 26
  • 38
Arima
  • 13
  • 1
  • 5
  • If the input is `"A1A 1A1"`, then `posCode.charAt(0)` is `'A'`, `posCode.charAt(2)` is `'A'`, `posCode.charAt(4)` is `'1'`. – ajb Nov 01 '16 at 04:14
  • 2
    Is this an assignment? A regular expression might be much simpler. – Kevin Krumwiede Nov 01 '16 at 04:23
  • I fixed the proper char positions but I'm still running into the same problem - and yeah this is an assignment and we haven't been taught about regular expressions yet so I'm not sure if that would be accepted – Arima Nov 01 '16 at 04:28

6 Answers6

1

You can reduce a lot of if-else statements and reduce the lines of your code.

The following code have same logic as yours and it's checking for the postal code as you want it to:

public class validatePostalCodeTest {

    public static void main(String[] args) throws java.lang.Exception {

        Scanner kb = new Scanner(System.in);
        System.out.println("Please enter postalcode:");
        char charPC[] = kb.nextLine().toCharArray();
        boolean valid = false;

        if (charPC.length == 7) {
            if (Character.isLetter(charPC[0]) && Character.isLetter(charPC[2]) && Character.isLetter(charPC[5])
                    && Character.isDigit(charPC[4]) && Character.isDigit(charPC[1]) && Character.isDigit(charPC[6])
                    && Character.isWhitespace(charPC[3])) {
                valid = true;
            }
        }

        else if (charPC.length == 6) {
            if (Character.isLetter(charPC[0]) && Character.isLetter(charPC[2]) && Character.isLetter(charPC[4])
                    && Character.isDigit(charPC[1]) && Character.isDigit(charPC[3]) && Character.isDigit(charPC[5])) {
                valid = true;
            }
        }

        if (valid)
            System.out.println("\nValid");
        else 
            System.out.println("\nInvalid");

        System.out.println("Program ending due to end-of-file");
    }
}
Raman Sahasi
  • 30,180
  • 9
  • 58
  • 71
0

You have used kb.next() which will read data with space separation, So when you will enter postal code as A1A 1A1 it will take it 2 times first one is A1A and second one is 1A1 and therefor you will get invalid output 2 times as it will take 2 time data with one space, so you need to use nextLine() it will help you to resolve your issue,

Check below resolved answer

public class validatePostalCodeTest 
{
   public static void main (String[] args) throws java.lang.Exception
   {

      Scanner kb = new Scanner(System.in);
      System.out.println("Please enter postalcode:");
      String posCode = kb.nextLine();

       if (posCode.length() > 7) 
           System.out.println("\nInvalid");
       if (posCode.length() < 6) 
           System.out.println("\nInvalid");    
       if (posCode.length()== 7){
           boolean valid = true;

            char a = posCode.charAt(0);
            char b = posCode.charAt(2);
            char c = posCode.charAt(4);
            char d = posCode.charAt(1);
            char e = posCode.charAt(5);
            char f = posCode.charAt(6);
            char g = posCode.charAt(3);
            if(! Character.isLetter(a))
                valid = false; 
            else if (! Character.isLetter(b))
                valid = false;
            else if (! Character.isDigit(c))
                valid = false;
            else if (! Character.isDigit(d))
                valid = false;
            else if (! Character.isLetter(e))
                valid = false;
            else if (! Character.isDigit(f))
                valid = false;
            else if (! Character.isWhitespace(g))
                valid = false;

           if (valid) System.out.println("\nValid");
           else System.out.println("\nInvalid");
       }
       if (posCode.length()== 6){
           boolean valid = true;

            char a = posCode.charAt(0);
            char b = posCode.charAt(2);
            char c = posCode.charAt(4);
            char d = posCode.charAt(1);
            char e = posCode.charAt(3);
            char f = posCode.charAt(5);
            if(! Character.isLetter(a))
                valid = false; 
            else if (! Character.isLetter(b))
                valid = false;
            else if (! Character.isLetter(c))
                valid = false;
            else if (! Character.isDigit(d))
                valid = false;
            else if (! Character.isDigit(e))
                valid = false;
            else if (! Character.isDigit(f))
                valid = false;


           if (valid) System.out.println("\nValid");
           else System.out.println("\nInvalid");
       }
       System.out.println("Program ending due to end-of-file");
   }
}    
Vickyexpert
  • 3,147
  • 5
  • 21
  • 34
0

Let's start with simplifying your code.

Your loops will only ever execute at most once, given that you have a break at the end of them, which does raise the question, why bother with the loops at all?

You describe the Canadian postal code format, which has the general form:

/[A-Z]\d[A-Z]\d[A-Z]\d/

for no spaces, and

/[A-Z]\d[A-Z]\s\d[A-Z]\d/

...where [A-Z] represent the upper-case character classes A through Z, \d represents a digit from 0 to 9, and \s represents a whitespace character. I know that you're not using regular expressions, but this is how I plan on representing the data you need to solve.

Let's start with the simplifying the case without a space in it. That's your entire second loop. We start with switching from next to nextLine() for use in our scanner.

String posCode = kb.nextLine();

Now, we want to simply read that entire line in and check its length. If it's equal to six, we carry on - your code already does this.

if(posCode.length() == 6) {
    // validation logic
}

Now here's the tricky part. Do you recall the regular expressions I mentioned above? It so happens that there's a pattern with them:

  • Even-place characters must be a character from A to Z.
  • Odd-place characters must be a digit from 0 to 9.

With that, we can construct a loop to check a few things for us based on this logic. Notice the negation on Character.isLetter and Character.isDigit.

for(int i = 0; i < posCode.length(); i++) {
    if(i % 2 == 0) { // even digits
        if(!Character.isLetter(posCode.charAt(i))) {
            // reject!
            System.out.println("Invalid!");
            break;
        }
    } else { // odd digits
        if(!Character.isDigit(posCode.charAt(i))) {
            // reject!
            System.out.println("Invalid!");
            break;
        }
    }
}

Realistically speaking, this is all you need to do. The whitespace character is a special case, and it can be easily ignored by skipping it.

int spaceLocation = posCode.indexOf(" ");
if(spaceLocation != -1) {
    // carve the space out and concatenate
    posCode = posCode.substring(0, spaceLocation) + posCode.substring(spaceLocation + 1, posCode.length());
}

By doing the above, you only need the one method and you can successfully validate both cases.

Makoto
  • 104,088
  • 27
  • 192
  • 230
0

Why not use a regex?

Canadian postal code as regular-expression

Your two given formats for Canadian postal code have a pattern. This can be expressed as regular expression (regex):

regex example match variant
[A-Z]\d[A-Z]\d[A-Z]\d A1A1A1 without spaces
[A-Z]\d[A-Z]\s\d[A-Z]\d A1A1 A1 with a space between parts

Where:

  • [A-Z] represents an uppercase letter A through Z
  • \d represents a digit from 0 to 9
  • \s represents a whitespace character

Improved regex, test the demo on regex101:

^[A-Z]\d[A-Z]\d\s?[A-Z]\d$

  • Surround the regex with ^ and $ to match complete line from start (^) to end ($)
  • The added qunatifier on \s means zero or one whitespace (\s?). Can also replace by using the greedy quantifier * for zero or multiple (any).

Using this regex together with String.matches(regex) you can validate easily:

public static boolean isValidCanadianPostcode(String input) {
  return input.matches("^[A-Z]\\d[A-Z]\\d\\s?[A-Z]\\d$");
}

Note: For a correct regex inside a Java string we need to escape each backslash by another one (e.g. \s becomes \\s).

hc_dev
  • 8,389
  • 1
  • 26
  • 38
-1

I would just use a regular expression here:

boolean isPostalCodeValid (String postalcode) {
    return postalcode.matches("^\\w\\d\\w\\d\\w\\d|\\w\\d\\w\\s\\d\\w\\d$"));
}

Demo here:

ideone

Tim Biegeleisen
  • 502,043
  • 27
  • 286
  • 360
  • 1
    My instructor hasn't taught us about regular expressions yet so I'm not sure if this would be accepted – Arima Nov 01 '16 at 04:25
  • I think a regex is absolutely the way to go for this problem. I will leave this answer here, because others who might be searching SO would benefit from this approach. – Tim Biegeleisen Nov 01 '16 at 04:26
  • 1
    no need of that if block, you can simply return the String.matches("") – Jobin Nov 01 '16 at 04:36
-1
    public class validatePostalCodeTest {
    public static void main(String[] args) {
        Scanner kb = new Scanner(System.in);
        System.out.println("Please enter a Postcode:");
        while (kb.hasNext()){
            String posCode = kb.next();

            if (posCode.length()== 7){
                boolean valid = true;
                    char a = posCode.charAt(0);
                    char b = posCode.charAt(2);
                    char c = posCode.charAt(4);
                    char d = posCode.charAt(1);
                    char e = posCode.charAt(5);
                    char f = posCode.charAt(6);
                    char g = posCode.charAt(3);
                    if(! Character.isLetter(a))
                        valid = false; 
                    else if (! Character.isLetter(b))
                        valid = false;
                    else if (! Character.isLetter(c))
                        valid = false;
                    else if (! Character.isDigit(d))
                        valid = false;
                    else if (! Character.isDigit(e))
                        valid = false;
                    else if (! Character.isDigit(f))
                        valid = false;
                    else if (! Character.isWhitespace(g))
                        valid = false;

                if (valid) System.out.println("\nValid");
                else System.out.println("\nInvalid");
            }
            else if (posCode.length()== 6){
                boolean valid = true;
                    char a = posCode.charAt(0);
                    char b = posCode.charAt(2);
                    char c = posCode.charAt(4);
                    char d = posCode.charAt(1);
                    char e = posCode.charAt(3);
                    char f = posCode.charAt(5);
                    if(! Character.isLetter(a))
                        valid = false; 
                    else if (! Character.isLetter(b))
                        valid = false;
                    else if (! Character.isLetter(c))
                        valid = false;
                    else if (! Character.isDigit(d))
                        valid = false;
                    else if (! Character.isDigit(e))
                        valid = false;
                    else if (! Character.isDigit(f))
                        valid = false;

                if (valid) System.out.println("\nValid");
                else System.out.println("\nInvalid");
            }
else{
System.out.println("\nInvalid Length");
}

            System.out.println("\nPlease enter a Postcode:");
        }
        System.out.println("Program ending due to end-of-file");
    }

    }

Please try the above logic.I have optimized it.

Issac Saji
  • 106
  • 6