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:

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.


In reply to Re^5: help with user selected hash operations? by roboticus
in thread help with user selected hash operations? by lunette

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.