School Assignment? Project Due Tomorrow? Chat LIVE With A Programming Expert!

Welcome to Dream.In.Code
Become an Expert!

Join 306,960 Programmers for FREE! Get instant access to thousands of experts, tutorials, code snippets, and more! There are 1,926 people online right now. Registration is fast and FREE... Join Now!




Pattern matching, files, and hashes all in one

 

Pattern matching, files, and hashes all in one

CatchThi5Drift

4 Nov, 2009 - 09:40 AM
Post #1

New D.I.C Head
*

Joined: 12 Oct, 2009
Posts: 13


My Contributions
Hi. For a class, we're supposed to type out a program from the textbook, and then modify it to allow searching for names. When I first typed out the program, I couldn't get it to work, then, after changing a line as per the teacher's instructions, I got a whole whack of uninitialized warnings. At one point I had it doing the right thing when searching for e-mail addresses, but everything else came back not found. Now everything I search comes back not found.

Anyway, I'm not knowledgeable enough to be able to look at the program and see other mistakes that might have been in the text that the teacher didn't see (or, more likely, if I deleted or added something important).

If anyone could take a look and point me in the right direction, that would be great smile.gif .
CODE

#!/usr/bin/perl -w

open(PH, "customers.txt") or die "Cannot open customers.txt: $!\n";
while(<PH>) {
    chomp;
#    ($number, $email, $name) = ( split(/\s+/, $_) )[1,2,3]; this is the original line
    ($number, $email, $name) = ( split(/\t/, $_) )[1,2,3]; # changed s+ to t
    $Phone{$number} = $_;
    $Email{$email} = $_;
    $Name{$name} = $_;
}
close(PH);

print "Type 'q' to exit\n";
while (1) {
    print "\nNumber? ";
    $number = <STDIN>; chomp($number);
    $address = "";
    $name = "";
    if (! $number ) {
        print "E-Mail? ";
        $address = <STDIN>; chomp($address);
    }
    
    if (! $number and ! $address) {
        print "Name? ";
        $name = <STDIN>; chomp($name);
    }
    
    next if (! $number and ! $address and ! $name);
    last if ($number eq 'q' or $address eq 'q' or $name eq 'q');
    
    if ( $number and exists $Phone{$number} ) {
        print "Customer: $Phone{$number}\n";
        next;
    }
    
    if ( $address and exists $Email{$address} ) {
        print "Customer: $Email{$address}\n";
    }
    
    if ( $name and exists $Name{$name} ) {
        print "Customer $Name{$name}\n";
    }
    print "Customer record not found.\n";
    next;
}
print "\nAll done.\n";


The text file:
CODE
Smith,John (248)555-9430 jsmith@aol.com
Hunter,Apryl (819)555-3029 april@showers.org
Stewart,Pat (405)555-8710 pats@starfleet.co.uk
Ching,Iris (305)555-0919 iching@zen.org
Doe,John (212)555-0912 jdoe@morgue.com
Jones,Tom (312)555-3321 tj2342@aol.com
Smith,John (607)555-0023 smith@pocahontas.com
Crosby,Dave (405)555-1516 cros@csny.org
Johns,Pam (313)555-6790 pj@sleepy.com
Jeter,Linda (810)555-8761 netless@earthlink.net
Garland,Judy (305)555-1231 ozgal@rainbow.com


This post has been edited by CatchThi5Drift: 4 Nov, 2009 - 09:41 AM

User is offlineProfile CardPM
+Quote Post


dsherohman

RE: Pattern Matching, Files, And Hashes All In One

5 Nov, 2009 - 03:20 AM
Post #2

D.I.C Head
**

Joined: 29 Mar, 2009
Posts: 202



Thanked: 36 times
My Contributions
QUOTE(CatchThi5Drift @ 4 Nov, 2009 - 05:40 PM) *
CODE

#    ($number, $email, $name) = ( split(/\s+/, $_) )[1,2,3]; this is the original line
    ($number, $email, $name) = ( split(/\t/, $_) )[1,2,3]; # changed s+ to t

Both versions of this line are broken.

The original version will put the email address into $number, the name into $email, and nothing into $name. $name being undef would presumably be the cause of your original batch of "uninitialized value" warnings. The reason it does this is because Perl array indexes are 0-based; if you're going to specify indexes to pull from, your data will be appearing in 0, 1, and 2, not 1, 2, and 3.

Your changed version puts nothing into any of the variables because you're splitting on tabs and the fields do not appear to be tab-separated, so the entire string ends up in element 0 of the list, which you aren't storing anywhere. This could just be an artifact of DIC turning your tabs into spaces, but, even if it is, there was no need to change from \s to \t.

Note also that the fields in the data file are ordered name, number, email. The correct version of this split statement would, therefore, be either
CODE
my ($number, $email, $name) = ( split(/\s+/, $_) )[1,2,0];
or (better)
CODE
my ($name, $number, $email) = ( split(/\s+/, $_) );


You're also missing the "last" in your "if address" and "if name" clauses, causing it to incorrectly claim that the customer was not found after printing the customer record.

Aside from that, it seems to work in the way you appear to have intended.

(And then there's "use strict", lexical filehandles and three-arg open (i.e., "open $ph, '<', 'customers.txt' or die..."), but I recognize that you're just going by the book here and I'm pretty sure I explained those to you before, so you already know about them for when you start writing your own Perl. smile.gif )
User is offlineProfile CardPM
+Quote Post

CatchThi5Drift

RE: Pattern Matching, Files, And Hashes All In One

5 Nov, 2009 - 09:09 AM
Post #3

New D.I.C Head
*

Joined: 12 Oct, 2009
Posts: 13


My Contributions
Hey, thanks for helping me again. The fields weren't tab separated; the book said not to worry about how we space them out. I've done them with tabs now, though, just so I can use the line my teacher gave us *shrug*.

I'm still getting a warning:

CODE

open(PH, "customers.txt") or die "Cannot open customers.txt: $!\n";
while(<PH>) {
    chomp;
    my ($name, $number, $email) = ( split(/\t/, $_) );
    $Name{$name} = $_;
    $Phone{$number} = $_;
    $Email{$email} = $_; # Use of uninitialized value $email in hash element at assign4_q2.pl line 10, <PH> line 8.
}


This post has been edited by CatchThi5Drift: 5 Nov, 2009 - 09:16 AM
User is offlineProfile CardPM
+Quote Post

dsherohman

RE: Pattern Matching, Files, And Hashes All In One

6 Nov, 2009 - 03:36 AM
Post #4

D.I.C Head
**

Joined: 29 Mar, 2009
Posts: 202



Thanked: 36 times
My Contributions
QUOTE(CatchThi5Drift @ 5 Nov, 2009 - 05:09 PM) *
I'm still getting a warning:

CODE

open(PH, "customers.txt") or die "Cannot open customers.txt: $!\n";
while(<PH>) {
    chomp;
    my ($name, $number, $email) = ( split(/\t/, $_) );
    $Name{$name} = $_;
    $Phone{$number} = $_;
    $Email{$email} = $_; # Use of uninitialized value $email in hash element at assign4_q2.pl line 10, <PH> line 8.
}


The 8th line of input data contains only two tab-separated fields, so nothing is getting put into $email. Either it's missing a field or one of your separators is a space instead of a tab. (Which is a nice thing about using \s in the regex - it works with both tabs and spaces, so you don't have to worry about which is which.)

If you want to see what the offending line is, you can add
CODE
print "$_\n" unless $email;
anywhere after the split. Or
CODE
print "$name --- $number\n" unless $email;
if you want to see how the split divided it.
User is offlineProfile CardPM
+Quote Post

CatchThi5Drift

RE: Pattern Matching, Files, And Hashes All In One

6 Nov, 2009 - 07:52 AM
Post #5

New D.I.C Head
*

Joined: 12 Oct, 2009
Posts: 13


My Contributions
It was definitely a space instead of a tab for a separator. Thanks a lot for all your help cool.gif .
User is offlineProfile CardPM
+Quote Post

Fast ReplyReply to this topicStart new topic

Time is now: 11/21/09 04:07AM

Live Help!

Be Social

Dream.In.Code RSS Feed Dream.In.Code LinkedIn Group Follow Us On Twitter Fan Us On Facebook

Tutorials

Programming

Web Development

Reference Sheets

Code Snippets

DIC Chatroom

Bye Bye Ads

Monthly Drawing

Thumb Drive

Top Contributors

Top 10 Kudos This Month