Perl - Reporting from the Last Good Guess Database

Well, we're going to cover quite a bit of ground in this last little program!  We'll see another looping structure, sort a list, and get the keys of an array.  Here's the little program that does all of this:

	#!/usr/bin/perl -w
	dbmopen (%last_good,"lastdb",0666) || die "can't dbmopen lastdb: $!"; 
	
	foreach $name (sort keys (%last_good)) { 
		$when = $last_good{$name}; 
		$hours = (time() - $when) / 3600; # compute hours ago 
		write; 
	} 

	format STDOUT = 
	User @<<<<<<<<<<<:  last correct guess was @<<< hours ago. 
	$name, $hours 
	.

To begin, the keys Perl built-in function takes a hash name as an argument and returns a list of all the keys of that hash in some unspecified order.  For the %words hash as defined in Lesson 11, the result is something like jason, michelle, tracey, karee, patrick, larry, in some unspecified order.  For the %last_good hash, the result will be a list of all users who have guessed their own secret word successfully.

The sort Perl built-in function sorts the returned list alphabetically (just as if you passed a text file through either the MS DOS or the UNIX sort command).  This makes certain that the list processed by the foreach statement is always in alphabetical order.

Finally, the Perl foreach statement is a lot like the UNIX C-shell foreach statement.  It takes a list of values and assigns each one in turn to a scalar variable (here $name) executing the body of the loop (a block) once for each value.  So, for six names in the list from the %last_good hash, we get six passes through the loop, with $name being a different value each time.

The body of the foreach loop loads up a couple of variables used with the STDOUT format and invokes the format.  Note that we figure out the age of the entry by subtracting the system time (stored in the array) from the current time (as returned by the Perl built-in time function) and then divide that by 3600 (to convert seconds to hours).

As you might well imagine, Perl provides easy ways to create and maintain text-oriented databases (like the UNIX Password file) and fixed-length-record databases (like the UNIX "last login" database maintained by the UNIX login program).  We'll take a look at these databases in a later lesson and also look at a number of "application programming interfaces" to SQL relational databases (including Perl DBI as well as the defacto Microsoft standard ODBC [another popular way to access data from Perl for Win32 users is to use the OLE Automation interface to Microsoft's ActiveX Data Objects {ADO}.  ADO is an OLE interface that provides uniform data access to any compliant data source {including ODBC}] - we'll be taking a look at that option in a later lesson also).

OK, how did you describe the crucial element that was missing from the program we wrote at the conclusion of Lesson 3?

See you next lesson!