Question

I'm trying to normalize user input for Canadian postal codes.

The end goal is to get all input as A3A 3A3 - 7 characters, capitalized, with the first group letter number letter, second group as number letter number.

Users will sometimes use o or O for the number 0, or vice versa, so here is my function:

   $zip = htmlspecialchars($_REQUEST['zip']);
   if (!empty($zip)) {
       //if the format is A3A3A3, split it into two groups
        if (strlen($zip) == 6) {
            $zip = substr($zip, 0, 3) . " " . substr($zip, 3, 3);           
        }
       //now lets make sure there is only a empty space between groups
        if (strlen($zip) == 7) {
            $zip[3] = " ";
        }
       //let's put their o's, O's and 0's in the right places
        if ($zip[1] == ("O" || "o")) {
            $zip[1] = '0';
        }
        if ($zip[4] == ('O'||'o')) {
            $zip[4] = '0';
        }
        if ($zip[6] == ('O'||'o')) {
            $zip[6] = '0';
        }

        if ($zip[0] == '0') {
            $zip[0] = 'O';
        }
        if ($zip[2] == '0') {
            $zip[2] = 'O';
        }
        if ($zip[5] == '0') {
            $zip[5] = 'O';
        }
       //uppercase all the letters
        strtoupper($zip);
   }

The first tests I ran were of the sort:

input[0o0 O0o] => output[O0O 0O0]

Everything looks good I said to myself, it's working! But then I tried a normal postal code and keep getting unexpected results:

input[S7K3K1] => output[S0K 0K0]

I can't figure out why the code is deciding that ($zip[1] == ('O' || 'o') is true when $zip[1] == 7.

Any input would be greatly appreciated. Also, if you see a better way of normalizing this input, please share!

Was it helpful?

Solution

   //let's put their o's, O's and 0's in the right places
    if ($zip[1] == ("O" || "o")) {
        $zip[1] = '0';
    }

This code does not do what you think – your comparison logic are wrong, because so is your understanding of the || operator.

Use console.log(("O" || "o")) and see what you get in console – ooops, that’s just the letter O. Why? Because the || logical or operator in JS returns the first value that is not false-y.

You need to either write two individual comparisons here, and or-conjoin those – $zip[1] == "O" || $zip[1] == "o", or use an array with possible values and then check whether your variable value is among those (but the latter would be a bit over the top here).

Edit: Or, as bigmandan pointed out, you could also transform your letter to upper- or lower-case first, then you only have to do one comparison: ($zip[1]).toLowerCase() == "o" (Of course this works only in a special case like this – if it was not O or o, but a or b instead, you would still have to do individual comparisons.)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top