2

Perl guide

-

This is one of the best guides on the internet on Perl and now it’s incomplete.

Any plans to put the full guide on again anytime soon, guys?

Cheers and good job!

VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)
0

Chapter 2 – How to run Perl

-

Chapter 2 – How to run Perl

This quick guide was written towards Windows users.  Some modifications will have to be done for Linux or Mac users but this guide should still cover the basics.

Step 1:
Right click on Dekstop and select New>Text document

Step 2:
Rename the file as test.p;. PL is the Perl file extension.

Step 3:
Double click test.pl and enter the Perl codes as you see below. (start at the top of the document)

Step 4:
Click on your Start menu and click Run.  Type in cmd or command depending what version of Windows you are running.  Click enter.

Step 5:
If you are not on the Desktop, you need to navigate the command line until you’re on the desktop.

Step 6:
To run a perl script, you need to type in perl filename.  In our example, test.pl is our filename so we type in perl test.pl.  Click enter and the script should run.

VN:F [1.9.22_1171]
Rating: 8.0/10 (1 vote cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)
0

Chapter 18 – Introduction to Perl’s DB

-

Perl Tutorials – Chapter 18 – Intro To Perl’s DB

Perl has a number of built-in databases (or databases which can be used via modules) that are freely used to store data. Along with these databases, Perl can also connect to the major databases such as Oracle, MySQL and Excel.

Like everything else in Perl, TIMTYWTDI (There Is More Than One Way To Do It) so if you come from a scripting or programming background and have relational database experience, chances are you’d prefer the power of MySQL or Oracle over the built-in databases already available for you.

Each database comes at a price. The use of MySQL or Oracle can create initial overheard while it loads and connects to the appropriate DBIs to speak with the database. Unless the database is expected to get quite large or the script requires related data or advanced sorting techniques, using a flatfile database such as DB_File might be perform better.

Flatfile databases don’t have the overheard that relational databases do which makes them load faster and require less CPU processing power. These are great if you have only a few sets of data that needs to be saved such as traffic logs, usernames and passwords, dates, etc. There are limitations when it comes to information stored within a flatfile database. SDBM_File allows only a certain number of characters to be stored within a key or value.

If you were scraping web sites for data (let’s say lyrics for example), you’d exceed the character limitations in the database and the data stored would be truncated and thus be inaccurate. The other problem with flatfile databases is the ability (or lacktherof) to do advanced sorting on the data.

Relational databases have larger overhead and are a million fold more powerful than flatfiles while flatfiles process faster and require less code to perform.

In this tutorial we will be taking a brief look at Perl’s built-in database DB_File. These flatfiles are key/value pairs which sounds awfully too similar to the %hash datatype. Because of this, we store the contents of the database into our hash for manipulation or printing.


Calling the DB_File database

DB_File is the module DB_File.pm and is used like the CGI module or strict that you’re familiar with.

Before we can use the database, we need to tell our script to use the database module.

use DB_File;


Connecting to the DB_File database

Unlike relational databases which require usernames and passwords, the only information needed to connect to DB_File is the name of the variable you’re tying to it, the database name and location and the file permissions of the database.

my %db;
my $storage = “counter.db”;

tie %db, “DB_File”, “$storage”, O_CREAT|O_RDWR, 0644,
or die “Cannot open file $storage: $!\n”;

Above, we are declaring %db so we can tie it to the database. The scalar $storage is the database name and location. If there isn’t a file path within the $scalar assignment, it will assume the database is in the same directory as the script that’s running.

Next, we are tieing our variable %db from above TO the database DB_File which is followed by the variable $storage which contains the filename and location of the database. O_CREAT|O_RDWR, 0644, are the file permissions used on the database. Be careful not to give out too many permissions or other people will be able to tamper with your data. 0644 or 0666 is generally as high as you want to go to keep the database relatively secure.

Some, or all, of the parameters can be left out when connecting to DB_File. For example, the following two snippets are identical.

tie %db, “DB_File”, $storage, O_CREAT|O_RDWR, 0666 ;

tie %db, “DB_File”, $storage;

 

Tying variables

When using databases such as DB_File and SDBM_File, variables are tied to the contents of the database. This is to say, when %db is tied to $storage using DB_File, the hash %db contains all the data inside %storage.

Similar to filehandles, data is read from and written to the database using the variable tied variable instead of speaking to it directly. Since the data is stored within our hash variable, it makes data retrieval and manipulation simple.


Using the stored data

The tied variable to the DB_File database is a hash. The hash is no different than any other hash you’ve used within your scripts.

To print out all the contents, a foreach() loop could iterate over all the key/value pairs like so:

foreach my $key (%db)
{
  print “$key => $key{$key}<br>”;
}

Saving the information to the database is identical to the procedure used to add another key/value pair to the original hash. Just create a unique hash key and assign it a value. If the hash key already exists, the previous value will be overwritten with the new information.

$db{“username”} = “password”;

If the database was designed for usernames and passwords, you could check to see whether or not a username (key) exists using an if conditional.

if (exists $db{“username”})
{
  # do this
}


Joining and Splitting

When using flatfile databases associated in key/pair values, we are limited in how much information we can store for each key in order to keep the information grouped together.

The previous example was a username/password combination which would run cleanly. But if you wanted to store more than just one piece of information to the value, joining the data to save and splitting it back into usable variables when you need it is the workaround.

Our scenario: We have an employee database where the key is an employee ID number and the value consists of their name, hourly wage, position and their favorite caffeinated beverage.

%employees = (“100″ => “Fred Flinstone::14.08::scribe::coffee”, “101″ => “Lisa Simpson::23:17::educator::red bull”);

From the hash (assume it’s the database), the value of employee 100 is Fred Flinstone::14.08::scribe::coffee.

All these values are contained within one inseparable string, right? Wrong. When the information is grouped together with a common delimiter the string can be broken up into smaller variables. The most commonly used delimiter is a double colon :: but if the data being stored can contain ::, a different delimiter is required or the data will be broken prematurely.

Take for instance:

$db{“100″} = “Fred Flintstone::14.08::scribe::coffee”;

There are 4 groups of information within the single value which means we’ll create 4 new variables and split() on the common delimiter.

my ($name, $pay, $position, $drink) = split(/::/, $employees{“100″});

The first step is to create meaningful scalar variables which the splitted results will be assigned to. These new variables are assigned (in order they care created!) to the value of the splitted value our hash key 100. Inside split(/ /) is the delimiter in which to separate the data. If two 8s were used as delimiters, it would have looked like

split(/88/,

After the values are extracted into the new variables, they are accessible anywhere throughout the rest of the script.

use DB_File;

my %db;
my $storage = “employees.db”;

tie %db, “DB_File”, $storage;

my %employees = (“100″ => “Fred Flinstone::14.08::scribe::coffee”, “101″ => “Lisa Simpson::23:17::educator::red bull”);

my ($name, $pay, $position, $drink) = split(/::/, $employees{“100″});

print “Their name was $name, their pay was $pay, their position was $position and their favorite drink is $drink”;

Joining information into one storable string is the same idea but is in reverse of the split().

The variable is assigned to the conjoined values of the list of strings or variables at the end of the assignment. Similar to split(), the delimiter to join on is specified before the variables or strings.

my $single_string = join(“::”, $name, $pay, $position, $drink);

print $single_string;

The printout would look something similar to: Superman::1000::superhero::kryptonite. Then to assign the new string back into our database, we’d use the hash assignment.

$employees{“102″} = $single_string;

 

A complete example

#!/usr/bin/perl

use warnings;
use strict;

use CGI qw/:standard/;
use DB_File;

my %db;
my $storage = “employees.db”;

tie %db, “DB_File”, $storage;

my %employees = (“100″ => “Fred Flinstone::14.08::scribe::coffee”, “101″ => “Lisa Simpson::23:17::educator::red bull”);

### example of splitting
my ($name, $pay, $position, $drink) = split(/::/, $employees{“100″});

print “Their name was $name, their pay was $pay, their position was $position and their favorite drink is $drink”;

### example of joining

my $single_string = join(“::”, $name, $pay, $position, $drink);

print $single_string;

VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)
1

Chapter 17 – Perl CGI Introduction

-

Chapter 17 – Perl CGI Introcution

Perl’s gateway to cyberspace is CGI (Common Gateway Interface). Perl scripting is for scripting for your own computer, CGI scripting is for web servers and web sites.

The main difference between Perl and CGI (though CGI in essence is just a series of Perl modules) is CGI is generally object oriented. If the thought of using objects frightens you, rest assured you’re not required to use that format.

When you get into using different modules, many modules are object-oriented so you’ll need to look up the documentation before you’ll be able to use their code.

Initial script setup

To make your Perl scripts CGI, you use the CGI module

use CGI qw/:standard/;

The top section of your scripts would look something like

#!/usr/bin/perl

use warnings;
use strict;
use CGI qw/:standard/;

The first thing you need to know when using CGI (remember there are more than one way to do things. There are other ways to use the CGI module or get around it completely by typing out all the HTML for your web site) is the need to print out the HTTP Headers.

This is done by

print header, start_html();

Before you print() anything out to the browser you must print out the headers. It may be easier to put this code near the top of your script if your script allows it. If you attempt to print out information before the headers are set, you’ll get an Internal Server Error (ISE).

Your Perl-ish errors won’t work in CGI, if you have a missing semicolon on line 159 or you didn’t predeclare a variable name under the strict pragma. To turn on CGI warning we use fatalsToBrowser which will show us any and all Perl-ish errors. This will only catch errors that occur after you initialize the warnings which means if you setup warnings on line 7 and the error is on line 5, you’ll get an Internal Server Error (ISE) instead of a real error message.

Because of this, if you choose to use this while creating your CGI script it should be setup near the top of the script. Please note: when writing your script it is encouraged you use the fatalsToBrowser but once the script is live you should remove it. The error message could possibly give away too much server information to potential computer wannabe hackers.

#!/usr/bin/perl

use warnings;
use strict;

use CGI qw/:standard/;
use CGI::Carp ‘fatalsToBrowser’;

print header, start_html();


Printing to browser

Printing to the browser is no different than printing to the command line. You print() your strings using print “”; as you can see below. Any text or variables you decide to print will appear in the user’s browser.

The only difference here is your ability to output your data any way you wish. Since you can now use HTML, you can align your text using tables, make links, change font sizes and colors or even print out JavaScript as well.

print “Hello, CGI World!”;

If you’re not using CGI’s object oriented (OO) interface you’ll need to be careful not to nest unescaped quotes inside of quotes when you are printing out HTML. Take, for instance, assigning a font color. The HTML code would be :

print “<font color=”red”>Hello, CGI World!</font>”;

This would result in incorrect syntax. When printing out HTML there are three ways you could accomplish the same thing.

The first being print qq(). printqq() represents printing a quoted quote string. You nest your string in parenthesis so the quotes from the HTML won’t affect your script.

print qq( <font color=”red”>Hello, CGI World!</font>);

The second way of printing HTML to the screen is escaping the quotes. Using this method will often make your text less readable and harder to maintain so this is the least recommended. The escape character is the / slash. You place this in front of the nested quotes.

print “<font color=/”red/”>Hello, CGI World!</font>”;

The third and final way to print HTML without having to worry about quotes is using herdocs. This method is recommended if you have more than one line of output to print at a time.

A heredoc allows you to print as many lines as you want with only one print statement. You know longer need to use the enclosing quotes or semicolons when you use herdocs which makes this the fasted method to printout mass amounts of HTML or even text output.

You print to a filehandle which you create in caps. In our example we used ENDOFPRINT which could have been ENDOFFILE, EOF, FORM or even CAT. You can name this nearly whatever you want but keep it all A-Z characters for simplicity.

All lines between the print line and the line at the very bottom that contains just the ENDOFPRINT (or whichever filehandle you used) will be printed. Note: the closing filehandle must be on it’s own line with no trailing spaces and at least one full blank line below it.

print <<”ENDOFPRINT”;

<font color=”red”>Hello, CGI World!</font>
<center><h2>We are line #1</J2></center>
<table border=”1″ width=”50″>
<tr>
<td>I am inside a table!</td>
</tr>
</table>

ENDOFPRINT

 

Ending the CGI script

Once all the data is printed to the browser you need to close off the HTML tags. the print header, start_html() from earlier prints out the beginning HTML tag, all the HEAD information and the starting BODY tag.

When you’re done, you need to close off the BODY aznd the HTML tag. Like with everything else in Perl and CGI, there is more than one way to do it (TIMTOWTDI).

You can hard code the closures yourself within a basic print statement.

print “</body></html>”;

Or you could use the CGI function of end_html; neither are suggested over the other, it’s all a principle of coder’s preference.

print end_html;


Uploading the script

In order for CGI to work, the web server you are working on has to have CGI enabled. If they do, you should already have a cgi-bin directory within your main HTML directory. All of the CGI scripts you develop or install need to inside the cgi-bin folder.

Once the script is uploaded, you’ll need to chmod the file (set the file permissions) to 755. If you don’t know how to do this, consult your FTP client’s help menu. 655 isn’t enough permissions to run CGI scripts and 777 is giving away too many rights. Regardless of what the author of the script says, never set the permissions higher than 755.

 

Setting the header information

Many times the CGI script will be a standalone complete script. This means you may have to create more specific header information such as the title, meta content, header type, the CSS files, etc.

print start_html (
-title=>”title of your page goes here”,
-base=>”true”,
-target=>”_blank”,
-meta=>{“keywords” =>”keywords go here”,
“copyright” =>”copyright 1996 King Tut”,
“description”=>”descript info”},
-style=>{“src” =>”/location/of/css.css”}, -BGCOLOR=>”gray”);

Note this isn’t a complete list of the header information you can customize within CGI but this should give you. If you need more information, consult your favorite search engine and search “cgi.pm” tutorials.

The CGI attributes are named after the HTML equivalents so they are pretty self explanatory.

VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)
0

Chapter 16 – Perl Directory Handling

-

Chapter 16 – Perl Directory Handling

Reading directories and scanning for files may seem like a difficult task but in Perl, it’s actually quite trivial.

This tutorial is geared more towards CGI usage but it can just as easily be converted back into command-line Perl so you can scan your own system. You open directories much the same way as you learned to up files from an earlier tutorial.

opendir(FILEHANDLE, $directory);

When you open the directory, you’re actually opening and using the filehandle to access the directory findings. The $directory is the file path of the directory you wish to access. It could have been hard coded such as

opendir(FILEHANDLE, “/home/user/public_html/”);

One thing to remember whenever you open a file or directory is to flip on the warnings of or die to ensure that it opened successfully. By default, if a file or directory is not opened for whatever reason (whether it be bad permissions or the directory or file cannot be found), Perl will not give you an error. It will continue on and pretend it’s working.

opendir(FILEHANDLE, $directory) or die “Error occurred: $!”;

Once you have the directory opened we need to read from it using readdir. Since we’re actually working with the filehandle itself and not the directory, we use

opendir(FILEHANDLE, $directory) or die “Error occurred: $!”;
my @files = readdir(FILEHANDLE);

Then of course you should close the filehandle once you’re done using it. No sense to keep a filehandle open longer than it has to be and accidently expose it to some unnatural events.

opendir(FILEHANDLE, $directory) or die “Error occurred: $!”;
my @files = readdir(FILEHANDLE);
close(FILEHANDLE);

From here, all you’d need to do is print out the array @files to see everything that you found in your directory.  When reading the print out, not all files will have a file extension so-to-speak. Even though most of these are more than likely directory names, there are some files that just don’t have extensions.

opendir(FILEHANDLE, $directory) or die “Error occured: $!”;
my @files = readdir(FILEHANDLE);
close(FILEHANDLE);

foreach(@files)
{
  print “$_<br>”;
}

.
..
cb.shtml
cgi-bin
_vti_pvt
adboxes.shtml
.htaccess
_vti_log
_private
_vti_txt
images
_vti_cnf
_vti_bin
tutorials
scripts
demo
archives.shtml
contact.shtml
custom.shtml

If you want to check to see which are directories and which of the items contained in @files are actually files, we can check with -d. This will check to see if the tested item is a directory. Since your array @files only contains the filename at this point, you need to prepend the $directory back onto it. This is the reason we prefer to store the directory in a variable rather than having to type it in numerous times.

my $directory = “/home/user/public_html/”; opendir(FILEHANDLE, $directory) or die “Error occured: $!”;
my @files = readdir(FILEHANDLE);
close(FILEHANDLE);

foreach my $file (@files)
{
  if (-d “$directory/$file”)
  {
    print “Directory: $file<br>”;
  }
  else
  {
    print “File: $file<br>”;
  }
}

There are many other ways to manipulate your files or directories that you’ve scanned. Let’s say for example you wanted to only find the .txt files that are in your directory.  To do this, we’d just take a regex and a simple if conditional.

my $directory = “/home/spyders/public_html/”; opendir(FILEHANDLE, $directory) or die “Error occured: $!”;
my @files = readdir(FILEHANDLE);
close(FILEHANDLE);

foreach my $file (@files)
{
  if ($file =~ m/\.txt$/i)
  {
    print “Directory: $file<br>”;
  }
  }

create.txt
test.txt
sample.txt

This concludes this lessonon reading from a directory. There are many more ways to manipulate your results to fit your needs. The sky and your imagination are the only limits.

VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)
0

Chapter 15 – Perl Subroutines

-

Chapter 15 – Perl Subroutines

functions. We learned about some built-in Perl functions in various earlier chapters such as chomp() and reverse(@array). User-created functions gives us more control and can be used to clean up your code.

Like variables, sub routines have their own namespace and are generally preceded by it’s defining character; the ampersand &. Though the ampersand preceding your function (we will use function and sub routine interchangeable from here on out) isn’t always required, get accustomed to using it unless you are absolutely sure it’s optional.

Depending on whom you talk to and what programming background they have, they will tell you different places to create your sub routines. A few programmers will tell you it’s best to create your sub routines at the top of your script, others will say it’s better format at the bottom. To each their own but on a personal note, the author of this article prefers to create sub routines at the bottom of the script as it helps remove the clutter from the main script.

To call a sub routine:

&compare;

The name compare in our example isn’t special. It can contain any letters, numbers or underscores as long as it does not begin with a digit. The following two examples are all acceptable function calls and names.

&money;
&magick;


Creating a sub routine

Creating your sub routine isn’t much different than creating a conditional or loop in terms of syntax.

sub compare
{
  # do this
}

The main difference between a simple eq or == and a m//, is one tests for equality and the other tests for the existence of the value inside the string.

When creating your sub routine you don’t use the sub character &, you precede it with sub. Within the user-created function you can accomplish any tasks your script requires such as math, string manipulation, page parsing, etc. Functions are global by nature but the variables used within your functions may either be locally scoped or global.


Locally scoped variables VS Global variables

Before we continue it is important to recognize the differences between locally scoped “private” variables and global variables which we’ve been using through our sample codes in the past tutorials.

A global variable is any variable that is accessible to any loop, sub routine or function. This is to say, a global variable can be altered anywhere within your script. Under the use strict pragma, we are required to my our variable declarations.

When you my a variable within a function call or a loop (any time you’re within { and } braces) the variable becomes locally scoped or “private” and can only be used within the braces you created the variable inside.

If you don’t require the variable to be used elsewhere, you will save memory if you declare them locally. Locally scoped variables have quicker access times.

To make a variable global, you declare the variable within the main script’s scope where it’s not interlocked within { } braces.

The following example demonstrates locally scoped variables because the variables are declared within the function. Since my is used within the braces, the $num1 and $num2 variables will not be accessible to any other function or to the main script itself.

sub compare
{
  my $num1 = 1;
  my $num2 = 2;

  print $num1 + $num2;
}

The next example demonstrates global variables. The variables are declared with my inside the main scope of the script; not within the sub routine. The variable assignments inside the sub routine will change the variable contents when you use it elsewhere.

my $num1;
my $num2;
sub compare
{
  $num1 = 1;
  $num2 = 2;

  print $num1 + $num2;
}


Returned Values

Sometimes you will want to return a locally scoped variable within your function to be used within your main script (or an entirely separate function). The last calculation in the function will be the returned value.

In the example below, the last known calculation was the addition of our two locally scoped variables. Even though they are locally scoped you can retrieve the return value and store it into a variable by assigning the variable to the sub routine itself. my $count = &add;

my $cnt = &add;
print $cnt;

sub add
{
  my $num1 = 1;
  my $num2 = 2;
  $num1 + $num2;
}

The last calculation doesn’t have to be math-related; any calculation on the final line will be the returned value.

Every function has a return value, whether that value means anything important is up to you. The value is either 1 if the function ends successfully, 0 if it doesn’t OR any value you tell it to return.

For example, if you end the function with a print statement the return value probably won’t be what you expect.

my $cnt = &add;
print $cnt;

sub add
{
  my $num1 = 1;
  my $num2 = 2;
  my $count = $num1 + $num2;
  print “$count”;
}

31

The subroutine above has a return value of 31, not the value of 3 that you’d expect from the calculation. This is because you are getting two separate return values. The first number (3) is the correct calculation of 1+2. The (1) at the end is returned because the final calculation was a print statement and it was successful. Since it was successful, the second returned value is a 1.

To make the return value accurate, the final calculation needs to be a variable value.


The Return operator

There may be times the value calculation within a function may be required before the entire sub routine is executed. To return values when you need them, the return operator sends the values back to your script.

my $cnt = &add;
print $cnt;

sub add
{
  my $num1 = 1;
  my $num2 = 2;
  return $num2;
  my $count = $num1 + $num2;
  print “The count was $count”;
}

2

Using the return operator will end the function prematurely. This is to say, anything after the return will not be executed. In the example above, neither the math addition nor the print out was processed.


Arguments

There will be times you don’t want to manually create variables within your function. When calling your sub routine, arguments can be passed directly to it for processing.

&add(1,2);

Arguments are passed within the optional parenthesis when you call your function. If you have more than one argument, as seen in the example above, the arguments are separated by commas.

Perl holds no real limitations in terms of the number of passable arguments as long as your system has the resources to accommodate.

The values passed are stored within a special Perl variable @_. Don’t get this confused with the special variable $_ when you use this. Remember, arrays have [] brackets at the end for indexes while the scalar variables do not.

my $cnt = &add(1,2);
print $cnt;

sub add
{
  my ($num1, $num2) = @_;
  return $num2;
}

2

The example above is passing 2 arguments to the function; 1 and 2. Inside the sub routine we are creating our local private variables for both of our arguments and are assigning them to @_. @_ is the special variable we just talked about that stores all of the passed arguments as array indexes. The first argument is @_[0], the second argument would be @_[1] (of course you’d write these as $_[0] and $_[1]) but when you assign to the array @_ itself, the variables pull the the indexes in order they are created.

To demonstrate single assignments, we would use the following.

my $cnt = &add(1,2);
print $cnt;

sub add
{
  my $num1 = $_[0];
  my $num2 = $_[1];

  $num1 + $num2;
}

3

This is a clear example of how the arguments passed are literally array indexes. Again, don’t confuse $_[0] and $_[1] as the special variable $_. The arguments are passed as array elements of @_.

What would happen if you pass more arguments to the sub routine than you expected? Luckily, if you don’t assign a variable to the extra argument(s), they’ll be ignored. In the previous example, if you passed my $cnt = &add(1,2,3); the results would be identical as the extra argument is being ignored since it wasn’t called or stored.

Sometimes this is good enough. The extra arguments are ignored but the circumstance may arise where you need to know for certain how many arguments was passed.

Below is one way to check how many arguments were really passed. If you assign a scalar to an array (even a special array), the scalar variable will be set to the number of elements inside the array. From here, you can build your own if/else conditionals based on your immediate requirements.

my $cnt = &add(12,34,56,78);
print $cnt;

sub add
{
  my $num_of_arguments = @_;
  if ($num_of_arguments != 2)
  {
    print “Incorrect number of arguments passed”;
   }
 {
else
{
  my ($num1, $num2) = @_;
  $num1 + $num2;
}
}

46

If the script requires more explicit argument checking, you may also check to see if an argument is within the appropriate range or apply a regex to see if it contains a specific search phrase. The script can be as specific as it needs to be to prevent errors from occurring.

my $cnt = &add(12,34,56,78);
print $cnt;

sub add
{
  my $data = $_[0];
  if ($data =~ m/[^a-zA-Z]/)
  {
    print “The arguement was not correct\n”;
  }
  else
  {
    return $data;
  }
}

46

In the beginning, it was stated that sub routines assist the code maintainers by cleaning out our code. It’s fine and dandy if you take our word for it but let’s see a real example of how sub routines can actually help make your code cleaner and more maintainable.

The following script is no other than the Word Scramble game we have for downloads here on SpyderScripts.com. The sub routines which contain most of the processing and “ugly” code are at the bottom of the script. All that is on the top is our basic framework of a layout with calls to our sub routine.

Since we can see our entire framework, if something goes wrong we know exactly which sub routine to look through.

001: #!/usr/bin/perl
002:
003: use warnings;
004:
005: use strict;
006:
007: #####################
008: # Configuration section
009: #####################
010:
011: my $beep_on_right = “1″;
012: ## If set, a beeping sound will play when you guess the word right
013:
014: my $max_attempts = 5;
015: ## The number of guesses you want before it moves on to the next word
016:
017: my $dictionary = “dict.txt”;
018:
019: my $hints = “2″;
020: ## The number of hints per word allowed
021:
022: #####################
023: # Do not edit below this line
024: #####################
025:
026: ############
027: # In-game variables
028: ############
029: my ($guess, $word, $backtotop);
030: my $hint_word = 0;
031: my $hint_count = 0;
032: my $won_game = 0;
033: my $lost_game = 0;
034: my $total_hints = 0;
035:
036:
037: &greetings;
038:
039: while (1)
040: {
041:
042: &pick_word;
043:
044: my $attempts = 0;
045:
046: while ($attempts++ < $max_attempts)
047: {
048: &guess;
049: &check_guess($backtotop);
050:
051: if ($backtotop)
052: {
053: last;
054: }
055: }
056:
057: while ($attempts > $max_attempts)
058: {
059: &word_solution;
060: last;
061: }
062:
063: }
064:
065: ##################################################
066: # Prepare subroutines beginning here
067: ##################################################
068:
069:
070: ###########
071: # Welcome message
072: ###########
073: sub greetings
074: {
075: system cls;
076: print <<” END”;
077: #####################################
078: ## WORD SCRAMBLE ##
079: #####################################
080: # #
081: # #
082: # Directions: Try to guess what the #
083: # scrambled word is before your #
084: # guesses run out. #
085: # #
086: # You may type in “exitgame” at any #
087: # time to quit WORD SCRAMBLE. #
088: # #
089: # You are allowed a few hints. Type #
090: # *hint* as your guess! #
091: #####################################
092: END
093:
094: }
095:
096: ###########
097: # Pick a random word
098: ###########
099: sub pick_word
100: {
101: open (DICT, $dictionary) or die “Cannot open $dictionary because: $!”;
102: my @words = <DICT>;
103:
104: foreach (@words)
105: {
106: chomp($_);
107: }
108:
109: $word = $words[rand @words];
110: $word = lc $word;
111:
112: my @scramble = split(//, $word);
113:
114: @scramble = sort { (-1,1)[rand 2] } @scramble;
115:
116: print “\n\nGuess the scrambled word: “;
117: foreach (@scramble) {print $_};
118: print “\n\n”;
119: }
120:
121:
122: ###########
123: # Take their input for guess
124: ###########
125: sub guess
126: {
127: print “\tGuess:”;
128: $guess = <STDIN>;
129: $guess = lc $guess;
130: chomp($guess);
131: }
132:
133:
134: ###########
135: # Answer checking and to see if they quit the game
136: ###########
137: sub check_guess
138: {
139: if ($guess eq “exitgame”)
140: {
141: print <<” END”;
142: \n\n
143: ##################################################
144: # SESSION STATS
145: ##################################################
146: #
147: # Words guessed: $won_game
148: # Words wrong: $lost_game
149: # Total hints: $total_hints
150: #
151: ##################################################
152: END
153:
154: print “\n\nWORD SCRAMBLE will now close.\n\n”;
155: exit;
156: }
157: elsif ($guess eq “*hint*”)
158: {
159: &display_hint;
160: }
161: elsif ($guess ne “$word”)
162: {
163: print “\t$guess is incorrect.\n”;
164: }
165: else
166: {
167: $won_game++;
168: print “\n##################################################\n”;
169: print “#Congratulations! The scrambled word was $word.\n”;
170: print “##################################################\n\n”;
171:
172: if ($beep_on_right) { print “\a”; }
173: $backtotop = “1″;
174: }
175: }
176:
177: ###########
178: # Give word solution
179: ###########
180: sub word_solution
181: {
182: $lost_game++;
183: print “\n:( :( :( :( :( :( :( :( :( :( :( :( :( \n”;
184: print “The correct answer was: $word\n”;
185: print “:( :( :( :( :( :( :( :( :( :( :( :( :( \n\n”;
186: }
187:
188: ###########
189: # Give word solution
190: ###########
191: sub display_hint
192: {
193: if ($hint_count >= $hints)
194: {
195: print “You are out of hints.\n\n”;
196: }
197: else
198: {
199: $hint_count++;
200: $total_hints++;
201: $hint_word = substr $word, 0, $hint_count;
202:
203: print “HINT: $hint_word\n\n”;
204: }
205: }

Challenges

1) What is another name for a sub routine?
————————————————————————
A function
————————————————————————

2) What is the special variable that sub routine arguments are stored in?
————————————————————————
They are stored in the @_ array variable
————————————————————————

3) What is the easiest way to count how many elements are found within an array?
————————————————————————
my $count = @array;

When you assign a scalar variable to an array, the results stored is the number of elements found within the array itself.
———————————————————————–

VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)