Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

Why would this code work under one condition and fail for the second condition?

by dark314 (Sexton)
on Jul 26, 2006 at 19:09 UTC ( [id://563869]=perlquestion: print w/replies, xml ) Need Help??

dark314 has asked for the wisdom of the Perl Monks concerning the following question:

Thank You Meister Eckhart. Basically I was making 2 sets of values, because inside my elsif, during prompting, I was using the my command, I found 2 solutions:

1) use the same global variables, in other words, don't use my (bad programming practice)

elsif ($adduserargs == 0) { #use prompt here... $givenname = Prompt( 'First Name', '[a-zA-Z]', 'Bad name format (letters only)' ); $surname = Prompt( 'Last Name', '[a-zA-Z]', 'Bad name format (letters only)' ); $middle_initial = Prompt( 'Please enter middle inital (if it exists)', '^[a-zA-Z]{0, +1}$', "One or no letters only please" );
or...of course..

2) Do not use globals

sub adduser { my $username = generate_user_name( @_ ); }
-Eric Hodges' idea

one would think, well why have adduser in there at all? Well at this point adduser is doing nothing more than calling generate_user_name(); however, in the future it will contain some code to communicate with an ldap server.


----------------------------------------------------

Original Question Below

I know this shouldnt work at all because of the way arguments are passed to a function! However what I do not know is why generate_user_name() would work when called by adduser in COND1, and fail when called in the same fashion in COND2



COND1 : Fails

dark314@somebox:~/boxes/scripts/csl-ldap-01$ perl foo.pl -adduser First Name: Manuel Last Name: Castillo Please enter middle inital (if it exists): F Use of uninitialized value in concatenation (.) or string at foo.pl li +ne 98, <STDIN> line 3. Created username:

COND2 : WORKS FINE

dark314@somebox:~/boxes/scripts/csl-ldap-01$ perl foo.pl -adduser Manu +el,Castillo,F Created username: mcastillo dark314@chavez:~/boxes/scripts/csl-ldap-01$

Here is the code that seems to be the focus of the problem:
if (exists $options{adduser} ) { #if adduser is an argument my $adduserargs; { @adduser = $options{'adduser'}; @adduser = map{split /,/ } @adduser; $adduserargs = scalar(@adduser); } #break apart on comma, and find how many args to this option if ($adduserargs == 2 || $adduserargs == 3){ $givenname = $adduser[0]; $surname = $adduser[1]; $middle_initial = $adduser[2]; #connect_to_ldap(); my $username = adduser($givenname,$surname,$middle_initial); print "Created username: " . $username . "\n"; #addgroup($username, $username); } elsif ($adduserargs == 0) { #use prompt here... my $givenname = Prompt( 'First Name', '[a-zA-Z]', 'Bad name format (letters only)' ); my $surname = Prompt( 'Last Name', '[a-zA-Z]', 'Bad name format (letters only)' ); my $middle_initial = Prompt( 'Please enter middle inital (if it exists)', '^[a-zA-Z]{0, +1}$', "One or no letters only please" ); my $username = adduser($givenname,$surname,$middle_initial); print "Created username: " . $username . "\n"; } }
the code executed under the: if ($adduserargs == 2 || $adduserargs == 3) does not work, which is fine, arguments are passed to functions via @_, i understand, however, the code executed under the: elsif ($adduserargs == 0) works perfectly and creates the username. In other words, adduser seems to know the variables $givenname, $surname, and middle_initial in this case, but not in the first case.

And that, I believe is my true question.


This is the entire perl code...
#!/usr/bin/perl use Getopt::Long; #use getopt - long use Switch; use strict; use warnings "all"; # # Configuration # my $LDAP_SERVER = "csl-ldap-01.inside"; my $LDAP_BASE_DN = "dc=local"; my $DOMAIN = "thecsl.org"; my $MAIL_HOST = "thecsl.org"; my $MAX_USERNAME_LENGTH = 12; my $MIN_UID = "1000"; # # Global Variables # my $G_LDAP_CONNECTION = ""; # # Main # # # Global Variables # my $givenname = ''; my $surname = ''; my $middle_initial = ''; my @adduser = ''; my %options; #command line arguments... GetOptions ( \%options, 'adduser:s'); if (exists $options{adduser} ) { #if adduser is an argument my $adduserargs; { @adduser = $options{'adduser'}; @adduser = map{split /,/ } @adduser; $adduserargs = scalar(@adduser); } #break apart on comma, and find how many args to this option if ($adduserargs == 2 || $adduserargs == 3){ $givenname = $adduser[0]; $surname = $adduser[1]; $middle_initial = $adduser[2]; #connect_to_ldap(); my $username = adduser($givenname,$surname,$middle_initial); print "Created username: " . $username . "\n"; #addgroup($username, $username); } elsif ($adduserargs == 0) { #use prompt here... my $givenname = Prompt( 'First Name', '[a-zA-Z]', 'Bad name format (letters only)' ); my $surname = Prompt( 'Last Name', '[a-zA-Z]', 'Bad name format (letters only)' ); my $middle_initial = Prompt( 'Please enter middle inital (if it exists)', '^[a-zA-Z]{0, +1}$', "One or no letters only please" ); my $username = adduser($givenname,$surname,$middle_initial); print "Created username: " . $username . "\n"; #addgroup($username, $username); } } # # Functions # sub adduser { my $username = generate_user_name( $givenname, $surname, $middle_init +ial ); #####return $username; } ################# ## Subs ################# sub Prompt { my ( $prompt, $regex, $error ) = @_; my $result = ""; while ( !$result ) { print "$prompt: "; $result = <STDIN>; if ( $result !~ /$regex/ ) { print "$error\n"; $result = ""; } } chomp $result; return $result; } sub generate_user_name { my ( $first, $last, $mi ) = @_; $first = "\L$first"; $mi = "\L$mi"; $last = "\L$last"; #print "$first\n$mi\n$last\n"; return simple_concat( $first, $last ) || fi_mi_lastname( $first, $mi, $last ) || iter_concat( $first, $last ) || simple_concat( $last, $first ) || undef; } sub simple_concat { my $first = shift; my $last = shift; my $uname = ""; $uname = substr( $first, 0, 1 ) . $last; $uname = substr( $uname, 0, $MAX_USERNAME_LENGTH ); return $uname unless username_exists($uname); return undef; } sub username_exists { my $uname = shift; return getpwnam($uname) ? 1 : undef; } sub fi_mi_lastname { my $first = shift; my $mi = shift; my $last = shift; my $uname; unless ( $mi eq "" ) { $uname = substr( $first, 0, 1 ) . substr( $mi, 0, 1 ) . $last; $uname = substr( $uname, 0, $MAX_USERNAME_LENGTH ); return $uname unless username_exists($uname); } return undef; } sub iter_concat { my $first = shift; my $last = shift; my $uname; foreach my $num_letters ( 2 .. length($first) ) { $uname = substr( $first, 0, $num_letters ) . $last; $uname = substr( $uname, 0, $MAX_USERNAME_LENGTH ); return $uname unless username_exists($uname); } return undef; }

2006-07-27 Title restored by GrandFather

Replies are listed 'Best First'.
Re: Why would this code work under one condition and fail for the second condition?
by japhy (Canon) on Jul 26, 2006 at 19:33 UTC
    You have two different sets of variables you're using. At the top-most scope of the file, you've declared the lexicals $givenname, $surname, and $middle_initial; these three are set by the first conditional (if ($adduserargs == 2 || $adduserargs == 3){ ... }</c), and are visible to the adduser() function.  Then you have three other lexicals with the same name that are declared and set in the second conditional (<c>elsif ($adduserargs == 0) { ... }). They are not visible to your adduser() function which ends up looking at variables with no values in them.

    Jeff japhy Pinyan, P.L., P.M., P.O.D, X.S.: Perl, regex, and perl hacker
    How can we ever be the sold short or the cheated, we who for every service have long ago been overpaid? ~~ Meister Eckhart
Re: Why would this code work under one condition and fail for the second condition?
by eric256 (Parson) on Jul 26, 2006 at 21:44 UTC

    Why are you using globals in adduser when you are passing it arguments? Globals = bad, passing arguments = good, mixing both = very very bad!

    sub adduser { my $username = generate_user_name( @_ ); }

    ___________
    Eric Hodges
Re: Why would this code work under one condition and fail for the second condition?
by davido (Cardinal) on Jul 26, 2006 at 19:24 UTC

    Funny, I get a different error: "The getpwnam function is unimplemented at mytest.pl line 174, <STDIN> line 3.

    Did you post the entire script? Update: Ahh, I see that's an activestate under Win32 issue. ;)


    Dave

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://563869]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (6)
As of 2024-03-28 12:12 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found