Monday, November 5, 2012

Perl - User defined function to simulate uc and lc



  uc and lc are Perl functions to convert strings into upper-case and lower-case respectively. In case, if the user wants to simulate the uc and lc functions by writing his own function, how to do it? Let us discuss in this article the different methods of how to simulate the uc and lc function?

Method 1:

  3 things should be known before going ahead with this one:

 1. The decimal values ranges of alphabets are:
       A - Z : 65 to 90
       a - z : 97 to 122
 2.  ord - Perl function which gives the decimal value of an ASCII character.
 3.  chr - Perl function which gives the ASCII character for a given value.

Program Logic:
  The logic to convert a character to uppercase is simple: If the decimal value of a ASCII character is between 97 and 122, subtract 32 which gives the decimal value of the lower case alphabet.

  Let us write a Perl script implementing the conversion of lowercase to uppercase:
#!/usr/bin/perl

$\="\n";

sub uc {
        my $x=shift;
        my $val="";
        my @arr=();
        while ($x=~/(.)/g) {
                $val=ord($1);
                $val=$val-32 if ($val >=98 && $val <=122);
                push @arr, chr($val);
        }
        local $"="";
        return "@arr";
}

my $str="the unix school";
my $res=&uc($str);
print "$res";
  •    The script uses a function whose name is same as the in-built function "uc". In order to get the user-defined function get invoked, the symbol "&" is put before the function call.
  •  Inside the function, the while loop reads character by character using the "g" flag. The character read is present in the special variable $1. As told earlier, check is done to see whether it is lower case, if so, converted to upper-case and pushed into an array.
  •  3. The array is returned in scalar form to the returning function. The special variable $" is the delimiter used to print elements inside double quotes which by default is a space. By maing it empty, the array elements can be returned in scalar fashion without spaces.

   Though this is one approach to convert, this is not the best of approaches since we are using functions a little bit.

Similarly, to simulate function for the uppercase to lowercase:
sub lc {
        my $x=shift;
        my $val="";
        my @arr=();
        while ($x=~/(.)/g) {
                $val=ord($1);
                $val=$val+32 if ($val >=65 && $val <=90);
                push @arr, chr($val);
        }
        local $"="";
        return "@arr";

}
Method 2:

Using Hashes with map function:
sub uc {
        my $x=shift;
        my %h1=map {$_ => chr(ord($_)-32)} 'a'..'z';
        $x=~s/([a-z])/$h1{$1}?$h1{$1}:$1/ge;
        return $x;
}
  Using the map function, a hash is populated with all the lower case alphebets as keys. Using the map function, the values for these keys are their upper-case counterparts.  Using the substition function, every lower case alphabet is repalced with its uppercase value. The replacement is done in such a way that if an hash element exists for the lowercase alphabet, the hash value contains its appropriate uppercase. 'ge' : g is global susbtitution which is to substitute for all matches, and 'e' for expression since the replacement part contains an expression.

Similarly, to simulate function for the uppercase to lowercase:
sub lc {
        my $x=shift;
        my %h1=map {$_ => chr(ord($_)+32)} 'A'..'Z';
        $x=~s/(.)/$h1{$1}?$h1{$1}:$1/ge;
        return $x;
}
Method 3:

Using hashes without map:
sub uc {
        my $x=shift;
        my @h1{'a'..'z'}=('A'..'Z');
        $x=~s/([a-z])/$h1{$1}/g;
        return $x;
}

  Perhaps the best of the 3 solutions. The hash is formed with the lowercase alphabets as keys, and their uppercase alphabets as values. And the substitution  simply happens for every alphabet.

Similarly, to simulate function for the uppercase to lowercase:
sub lc {
        my $x=shift;
        my @h1{'A'..'Z'}=('a'..'z');
        $x=~s/([A-Z])/$h1{$1}/g;
        return $x;
}

No comments:

Post a Comment