CIS 33A Perl handout week 11 part 1

Preliminary material should be here.

Sample programs from Clare Nguyen (edited by Ira Oldham)

############## more reference ############

Lecture week 11 hour 1 Example Part 1

#########################

# subroutine to swap the contents of two arrays
1. @arr1=(1,2,3);
2. @arr2=(10,20,30);

# pass a pointer to each array
3. swap(\@arr1,\@arr2);
# print the resulting arrays
4. foreach(@arr1){print "$_\n"}
5. foreach(@arr2){print "$_\n"}

6. sub swap
7. {
# save arguments in local variables
8. my ($arrRef1, $arrRef2) = @_;
9. my @temp;

# three way swap, using temporary storage
# @ is used to dereference the array references
10. @temp = @$arrRef1;
11. @$arrRef1 = @$arrRef2;
12. @$arrRef2 = @temp;
13. }

#########################

Lecture week 11 hour 1 Example Part 2

#########################

1. $arrRef = makeList();
2. foreach (@$arrRef) {print "$_\n"};

3. sub makeList
4. {
# local variable points to a anonymous empty array
5. my ($listRef) = [];

# push the numbers 2 3 4 5 into the array
# we have used push to push one value onto the end of the 
#    array
# this shows pushing a list of 4 values all at the end of 
#    the array
6. push(@$listRef,2..5);
7. return $listRef;
8. }

# The very interesting thing about this example is the use 
#    of  my
# my is used to make $listRef local
# while the pointer variable $listRef is local,
# the anonymous array itself is NOT
# thus after the value of the pointer has been returned,
# that pointer value can be access the global anonymous 
#    array

#########################

Lecture week 11 hour 1 Example Part 3

#########################

# subroutine computes the dot product of two vectors

1. @arr1 = (1,2,3);
2. @arr2 = (3,2,1);
# pass pointers to the arrays
3. $result = dot_product(\@arr1,\@arr2);
4. print "$result\n";			# prints 10

5. sub dot_product
6. {
# copy pointers to local variables
7. my ($ref1, $ref2) = @_ ;
# initialize the product to zero
8. my $product = 0;

# error return if the lengths of the vectors do not match
# note the arrays are used in scalar context
9. return 0 if @$ref1 != @$ref2;

# multiply the corresponding vector elements 
#    and add up the total
# $i is the loop variable, goes through the subscripts
10. for ($i=0; $i<@$ref1; $i++)
11. {
# dereference the pointers and use the matching elements
12. $product += $ref1->[$i] * $ref2->[$i];
13. }
14. return $product;
15. }

#########################

Lecture week 11 hour 1 Example Part 4

#########################

1. %h1 = (a,1,b,2,c,3,d,4);
2. %h2 = (b,9,c,10);

3. $sum = sum_values_of_common_keys(\%h1,\%h2);
4. print "$sum\n";

5. sub sum_values_of_common_keys
6. {
7. my ($href1, $href2) = @_;
8. my $total=0;

# for each key in the first hash
9. foreach $key (keys %$href1)
10.   {
# if there is a matching key in the second hash
11.   if exists $href2->{$key}
12.     {
# add the corresponding values from both hashes
13.     $total += $href1->{$key} + $href2->{$key};
14.     }
15.   }
16. return $total;
17. }

#########################

Lecture week 11 hour 1 Example Part 5

#########################

1. $hashRef = make_hash();
2. foreach (keys %$hashRef)
3. {
4. print "$_ $hashRef->{$_}\n;
5. }

6. sub make_hash
7. {
# create a pointer to an empty anonymous hash
8. my $hashref = {};

# use A B C D E as keys with values 65 66 67 68 69
9. foreach ('A'..'E')
10. {
# save the corresponding ASCII number for the key
11. $hashRef->{$_} = ord($_);
12. }
13. return $hashRef;
14. }

# output
# A 65
# B 66
# C 67
# D 68
# E 69

# Similar to the array example, this subroutine has a local 
# pointer, that points to a global anonymous hash

More discussion should go here.

Sample File programs from Clare Nguyen (edited by Ira Oldham)

############## File::Copy, File::Find ############

Lecture week 11 hour 1 Example File::Copy, File::Find

#########################


1. use File::Copy;

2. system ("ls -l fileA fileB");
3. print "fileA copied to fileB\n" if copy("fileA","fileB");
4. system ("ls -l fileA fileB");
5. print "fileA copied to dir1/fileB\n" if copy("fileA", "dir1/fileB");
6. system ("ls -l dir1/fileB");
7. print "fileA copied to dir1\n" if copy("fileA", "dir1");
8. system ("ls -l dir1/file*");

# screen output
# Cannot access fileB: No such file or directory
# -rw-r--r--  1 unc2140 staff      4 Mar 10 09:58 fileA
# fileA copied to fileB
# -rw-r--r--  1 unc2140 staff      4 Mar 10 09:58 fileA
# -rw-r--r--  1 unc2140 staff      4 Mar 11 23:42 fileB
# fileA copied to dir1/fileB
# -rw-r--r--  1 unc2140 staff      4 Mar 11 23:42 dir1/fileB
# fileA copied to dir1
# -rw-r--r--  1 unc2140 staff      4 Mar 11 23:42 dir1/fileA
# -rw-r--r--  1 unc2140 staff      4 Mar 11 23:42 dir1/fileB

#########################

1. use File::Find;

# use printLab subroutine; start in the current directory
2. find (\&printLab, ".");

# use printText sub; start in pwd, then cis70 under parent 
#   directory
3. find (\&printText, ".", "../cis70");

4. sub printLab
5. {
# print all file names containing lab4
# uses the dir command in the Find library
6. print "$File::Find::dir/$_\n" if /lab4/;
7. }

8. sub printText
9. {
10. print all file names that have size over 10,000 Bytes
11. print "$File::Find::dir/$_\n" if -s $_ > 10000;
12. }

# $_ contains the current file name
# $File::Find::dir contains the current directory

############## File::Find ############

Lecture week 11 hour 1 Example 2 for File::Find

#########################

# Recursive Directory Descent using find
# Print the directory and name of all your files with
#    names ending with .txt

1. use File::Find ;

# Process each file name using the printTxt subroutine
# Start in ~ which is your home directory

2. find ( \&printTxt, "~" ) ;

3. sub printTxt
4. {
5. if (/\.txt$/)	# match operator default binding to $_
6. {
7. print "$File::Find::name\n" ;
8. }
9. }

# $_ contains the current file name
# $File::Find::dir contains the current directory
# $File::Find::name contains the directory and file:
#    "$File::Find::dir/$_"
# match operator and if test  selects file names that 
#    end with .txt

############## File::Path ############

Lecture week 11 hour 1 Example File::Path

#########################

1. use File::Path

2. mkpath (['/foo/bar/baz', 'blurf1/quux'], 1, 0711) ;
3. rmtree (['/foo/bar/baz', 'blurf1/quux'], 1, 1) ;

# this code makes and removes two paths
# the first argument references an anonymous array of paths
#    (If you have only one path, an array is not needed)
# the second argument is TRUE, causing each directory name 
#    to be printed as it is created
# the third argument in mkpath specifies the permissions
# the third argument in rmtree is TRUE, skips files you do 
#    not have permission to delete