Programming in the large

Subroutines

Example:

#!/usr/local/bin/perl
# main program

open(IN,"test.html");
@file=<IN> ;
foreach $line (@file){
    find_closing_tags($line);
}
close IN;

# end of main
sub find_closing_tags {
    my $line = $line;
    if ($line =~ /(<\/.*?>)/i){
       print "$1\n";
   }
}

Note: Instead of my $line = $line; it would be better to write my $line = $_[0]; because variables should be sent to subroutines in the @_ array. But the first version is easier to remember and works in many cases.

Exercise

Add a second subroutine to the example that prints all tags that are not closing tags. Before the subroutines are called, let the main routine print a heading "these are the opening tags" and "these are the closing tags". (Note: this script only finds the first tag in every line. To change that so that it finds all tags you would have to insert line breaks after the tags - compare last week's exercise 5).

Example:

#!/usr/local/bin/perl
#
# main soubroutine
#
$file="input.txt";
@textfile= read_file($file);
push (@textfile,"this is the last line");
write_file($file,@textfile);
system('more input.txt');
##############################
sub read_file {
    my $inputfile = $file;
   open (INPUT, $inputfile);
   @text = <INPUT> ;
   chomp @text;
   close (INPUT);
   return @text;
}
#########################
sub write_file {
   my $outputfile = $file;
   my @text = @textfile;
   open (OUTPUT, ">$outputfile");
   foreach $line (@text) {
      print OUTPUT "$line\n";
   }
   close (OUTPUT);
}

The main routine sends $file as argument to the subroutine read_file and receives @text from it as return value. The subroutine sends values to the main routine via the "return" function.

Exercise

Write a third subroutine for the script. The subroutine is called get_input. It takes @textfile as argument and also returns it. The subroutine asks a user to input some text. The text is inserted at the end of the file. Optional: the user is also asked for the line where the text will be inserted.

Local and Global Variables

my ($number)=0;
local ($string)="";

Each subroutine should use its own set of variables so that the different subroutines do not interfere with each other. "Global variables" are variables that are used in the main routine and in subroutines. In the previous script $file and @textfile are global variables. But in the subroutines they are renamed to $inputfile, $outputfile and @text. All variables in subroutines should be defined with "my".

Variables declared with "local" are visible in the subroutine and all subroutines that are called from the subroutine.

If "use strict" is used, global variables are not permitted. In that case all variables must be sent to subroutines using the @_ array.

Exercise:

Modify the previous example so that the user is asked for his/her first name, last name, email address. The information is stored in the file in the following format:
Mary | Smith | mary@somecompany.com
John | Miller | miller@somecompany.com

A fourth subroutine is added that asks a user for her/his last name and retrieves the email address from the file. To do that every line of the file is split into an array. The second element in that array is compared to the current user's last name.