Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

Re^3: help with user selected hash operations?

by holli (Abbot)
on Oct 30, 2017 at 09:07 UTC ( [id://1202319]=note: print w/replies, xml ) Need Help??


in reply to Re^2: help with user selected hash operations?
in thread help with user selected hash operations?

if ($choice ne 'a', 'r', 'o', 'd', 'e') { print "Invalid choice, TRY AGAIN!\n"; }
No, conditions don't work that way. You cannot have a list of options on the right hand side of an eq.
Possible solutions:
# Very explicit: if ($choice ne 'a' && $choice ne 'r' && $choice ne 'o' && $choice ne ' +d' && $choice ne 'e') { print "Invalid choice, TRY AGAIN!\n"; } # Testing if the element is in a List of options: unless ( grep { $_ eq $choice } ('a', 'r', 'o', 'd','e') ) { print "Invalid choice, TRY AGAIN!\n"; } # Testing if the element matches a regular expression: unless ( $choice =~ /^(a|r|o|d|e)$/ ) { print "Invalid choice, TRY AGAIN!\n"; }


holli

You can lead your users to water, but alas, you cannot drown them.

Replies are listed 'Best First'.
Re^4: help with user selected hash operations?
by choroba (Cardinal) on Oct 30, 2017 at 09:15 UTC
    You can also use a character class in a regex:
    unless ($choice =~ /^[arode]$/) {

    Also, some people prefer List::Util::none to negated grep:

    use List::Util qw{ none }; if (none { $_ eq $choice } qw( a r o d e )) {
    ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
Re^4: help with user selected hash operations?
by haukex (Archbishop) on Oct 30, 2017 at 10:34 UTC
Re^4: help with user selected hash operations?
by lunette (Acolyte) on Oct 30, 2017 at 17:07 UTC

    okay, i thought it was something like that. the problem with working on code so long is after a while you just throw stuff at the wall and see what sticks.

    and thank you! i was trying to understand the "unless" condition last night but i think my brain was just scrambled. that makes sense!

      lunette:

      Heh, while I understand the frustration, "throwing stuff at the wall and seeing what sticks" is a terrible habit for a programmer. It's like going to a foreign country and speaking your native language slowly and loudly in an attempt to be understood by the locals.

      Rather than making an uninformed guess as to why your program is doing something strange, try running the code under the debugger and executing through it line by line. That way, if your if statements are nested incorrectly, you'll see it happen. Also, while you're in the debugger, you can ask perl what the value of a variable is, so you can see what's happening and give you important clues as to what the problem actually is. Once you identify the true problem, often the fix is really simple.

      For example, let's start running your code as found in Re^2: help with user selected hash operations? under the debugger (using the -d flag). First, let's start it up:

      $ perl -d pm_1202351.pl Loading DB routines from perl5db.pl version 1.49_001 Editor support available. Enter h or 'h h' for help, or 'man perldebug' for more help. main::(pm_1202351.pl:4): my %son_father; DB<1>

      OK, perl started up, and told us how to get help for the debugger commands, and showed us the next line it wants to execute, specifically line 4 (my %son_father;). It then prompts us (DB <1>) telling us it's ready to accept a command. I've already looked over your program, so we won't tediously execute each and every line. Instead, we'll tell perl to continue running until just after it accepts your first menu choice. The if statement after that is line 41, so we'll tell perl to run until it gets to line 41 (c 41) then we'll ask it to display the value of $choice (p $choice):

      DB<1> c 41 SON_FATHER Hash Operations a- Add a son-father pair d- Delete a son-father pair e- exit the program g- Get a father o- Output the hash neatly r- Replace a father x- get a grand father Make your choice: g main::(pm_1202351.pl:41): if ($choice eq 'a'){ DB<2> p $choice g

      Good, it holds 'g', just as expected. Obviously, it's not going to match 'a', so if we execute the next line, we expect that the program will skip over the whole if statement, and wind up on line 53, the if statement for the next choice (if ($choice eq 'd') {. Let's see what happens:

      DB<3> n main::(pm_1202351.pl:44): } if (exists $son_father{$name1} +) { DB<3>

      Nope! The next statement is line 44. See the closing curly at the beginning of the line? That's the matching curly for the one at the end of line 41. Your indentation shows that you want line 44 to be inside the if statement on line 41, but your curly braces tell perl otherwise. (Perl looks at the curly braces, and doesn't care a whit about whitespace. The whitespace is just to help programmers understand the code structure.)

      So we'll quit the debugger, and change from:

      if ($choice eq 'a'){ print "Enter a male name: "; chomp (my $name1 = ucfirst lc <STDIN>); } if (exists $son_father{$name1}) { print "Duplicate name -- try again!\n"; } else { print "Add a father: "; chomp (my $add_dad = ucfirst lc <STDIN>); $son_father{$name1} = {$add_dad}; next; }

      to this:

      if ($choice eq 'a'){ print "Enter a male name: "; chomp (my $name1 = ucfirst lc <STDIN>); if (exists $son_father{$name1}) { print "Duplicate name -- try again!\n"; } else { print "Add a father: "; chomp (my $add_dad = ucfirst lc <STDIN>); $son_father{$name1} = {$add_dad}; next; } }

      Now, let's try again:

      $ perl -d pm_1202351.pl Loading DB routines from perl5db.pl version 1.49_001 Editor support available. Enter h or 'h h' for help, or 'man perldebug' for more help. main::(pm_1202351.pl:4): my %son_father; DB<1> c 41 SON_FATHER Hash Operations a- Add a son-father pair d- Delete a son-father pair e- exit the program g- Get a father o- Output the hash neatly r- Replace a father x- get a grand father Make your choice: g main::(pm_1202351.pl:41): if ($choice eq 'a'){ DB<2> p $choice g DB<3> n main::(pm_1202351.pl:54): if ($choice eq 'd') {

      Success! This time, it successfully skipped the first choice, and is now checking whether we selected 'd'. Let's run the next statement, and...

      DB<3> n main::(pm_1202351.pl:57): } if (exists $son_father{$name2} +) {

      Oops! Did it again.

      As you can see, running the code under the debugger is pretty simple. Just press 'h' to get a list of available commands:

      DB<1> h List/search source lines: Control script execution: l [ln|sub] List source code T Stack trace - or . List previous/current line s [expr] Single step [in +expr] v [line] View around line n [expr] Next, steps over + subs f filename View source in file <CR/Enter> Repeat last n or + s /pattern/ ?patt? Search forw/backw r Return from subr +outine M Show module versions c [ln|sub] Continue until p +osition Debugger controls: L List break/watch +/actions o [...] Set debugger options t [n] [expr] Toggle trace [m +ax depth] ][trace expr] <[<]|{[{]|>[>] [cmd] Do pre/post-prompt b [ln|event|sub] [cnd] Set b +reakpoint ! [N|pat] Redo a previous command B ln|* Delete a/all bre +akpoints H [-num] Display last num commands a [ln] cmd Do cmd before li +ne = [a val] Define/list an alias A ln|* Delete a/all act +ions h [db_cmd] Get help on command w expr Add a watch expr +ession h h Complete help page W expr|* Delete a/all wat +ch exprs |[|]db_cmd Send output to pager ![!] syscmd Run cmd in a sub +process q or ^D Quit R Attempt a restar +t Data Examination: expr Execute perl code, also see: s,n,t expr x|m expr Evals expr in list context, dumps the result or lists + methods. p expr Print expression (uses script's current package). S [[!]pat] List subroutine names [not] matching pattern V [Pk [Vars]] List Variables in Package. Vars can be ~pattern or ! +pattern. X [Vars] Same as "V current_package [Vars]". i class inherita +nce tree. y [n [Vars]] List lexicals in higher scope <n>. Vars same as V. e Display thread id E Display all thread ids. For more help, type h cmd_letter, or run man perldebug for all docs.

      I generally use very few of these commands. I mostly use:

      • c # - to execute code up to the specified line number
      • n - to execute the line the debugger showed just before the prompt until the next line number. This will skip over subroutines.
      • s - Execute until we get to another line of code. If the current line calls a subroutine, then you'll wind up inside it. When you get familiar with c, n and s, you can navigate through your code fairly quickly.
      • p - to print an expression (This is pretty nice, as it's just like the print statement in your program, so you can do things like:
        DB<3> p "FOO! <$choice>\n" FOO! <g> DB<4>
      • x - to look at a data structure and dump its contents (hashes are printed as keys on the even lines, values on the odd lines):
        DB<4> x %son_father 0 'Bruce' 1 'Richard' 2 'Robert' 3 'Jason' 4 'Clark' 5 'Jon' 6 'Jeff' 7 'Doug' 8 'Thomas' 9 'Evan'
      • v # - show the source code around a particular line number:
        DB<6> v 50 47: print "Add a father: "; 48: chomp (my $add_dad = ucfirst lc <STDIN>); 49: $son_father{$name1} = {$add_dad}; 50: next; 51 } 52 } 53 54: if ($choice eq 'd') { 55: print "Enter a male name: "; 56: chomp (my $name2 = ucfirst lc <STDIN>);
      • r - continue executing code until we return from the current subroutine.

      I'd consider that my "minimum set" of debugger commands. As you get more familiar with perl, you'll want to learn more of the debugger commands so you can get even faster at figuring out what's happening. (Breakpoints and watch expressions are very nice!)

      To start off, I'd suggest running your program in the debugger, and just use the s command to execute step-by-step, and using p and x to examine variables. You'll get a feel for things pretty quickly, and you won't have to guess what your program is doing, you'll be able to watch it in as much detail as you want.

      ...roboticus

      When your only tool is a hammer, all problems look like your thumb.

        this is really helpful!! we haven't gone over this at all in class, but i'll make a note of it for myself, for future reference.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others taking refuge in the Monastery: (5)
As of 2024-04-18 20:18 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found