in reply to help with user selected hash operations?
G'day lunette,
Welcome to the Monastery.
"i am at the end of my rope here, honestly ..."
Don't Panic! There are no insurmountable problems here.
"it feels like nothing is working. ..."
Most of the individual parts of your code are fine; in fact, for a raw novice, it's pretty good (I've certainly seen a lot worse). I get the impression that you've got the basic logic correct in your head — you just haven't translated that to Perl code.
In the following, I've aimed to highlight the good and the bad, and how to fix the latter. Your assignment may have read something like "Do A, B and C only using X, Y and Z", but you haven't told us that. You also haven't said what the main focus of the assignment was: are you learning about hashes? I/O? UI presentation? something else? If you have another question at a later date, that's useful information to include. I've tried to keep my suggestions in line with with the level of code you've presented; for instance, I haven't used any references or regular expressions. If I've used something you weren't supposed to use, and you can't determine an alternative, just ask.
The first thing I had a problem with was your indentation. Your first if block is like this:
if ($choice eq 'a'){ ... }
At first glance, it appears that '}' is the closing brace for the if block. But it's not! That's the closing brace for a different if block: one that appears in "...", indented two more levels, inside another line of code.
Indentation doesn't matter to Perl (it does in some other languages and file formats); it does, however, matter a lot to humans who have to read, and possibly modify, the code. You've done the same thing with "if ($choice eq 'd') ...". In both cases, Perl sees a code structure like this:
if (CONDITION1) { ... } if (CONDITION2) { ... }
However, what you really wanted was a code structure more like this:
if (CONDITION1) { ... if (CONDITION2) { ... } }
Fixing that code structure throughout, will resolve a lot of your current issues.
Also, instead of a series of if statements, all of whose conditions Perl has to check; consider the following construct, where conditions are only checked until one is found to be TRUE.
if (CONDITION1) { ... } elsif (CONDITION2) { ... } elsif (CONDITION3) { ... } else { ... }
There may be better ways to handle that but, as I said at the start, I'm aiming to keep things simple. See "perlintro: Conditional and looping constructs" for more about that.
[By the way, the expression if loop is wrong. If you call it a loop, and start thinking in terms of loops, you likely add another level of confusion.]
Another problem you have is with changing cases. It's good that you thought to canonicalise the input; unfortunately, you haven't got it quite right. If the user enters "Jeff", "JEFF", or any other combination (perhaps even something daft like "jEfF"), lc will change that to "jeff":
$ perl -E 'my @x = qw{Jeff JEFF jEfF}; say lc $_ for @x' jeff jeff jeff
But, "jeff" isn't one of the keys of '%son_father' — "Jeff" is though (oops!). You can fix that by also using ucfirst:
$ perl -E 'my @x = qw{Jeff JEFF jEfF}; say ucfirst lc $_ for @x' Jeff Jeff Jeff
Although there would be better ways to do that in general code, it works with the data you've presented, so I've avoided anything more complex. You can use it for both the keys and values. You do need both the ucfirst and the lc:
$ perl -E 'my @x = qw{Jeff JEFF jEfF}; say ucfirst $_ for @x' Jeff JEFF JEfF
If you deal with those two main areas, you can probably get your program up and running reasonably well. There are a few other areas which, while not actually breaking your current code, are poor choices, bad practices, and habits you don't really want to get into.
Here's an example script that just implements the "a" and "e" menu selections. It has examples of all the points I've made above.
#!/usr/bin/env perl use strict; use warnings; { my %father_of = get_son_to_father_map(); display_menu(); while (1) { my $menu_selection = get_menu_selection(); if ($menu_selection eq 'e') { print "Exiting ...\n"; last; } elsif ($menu_selection eq 'a') { print "Son-father pair addition.\n"; print "Enter son's name: "; chomp( my $son = ucfirst lc <STDIN> ); if (exists $father_of{$son}) { print "$father_of{$son} is the father of $son\n"; } else { print "Enter father's name: "; chomp( my $father = ucfirst lc <STDIN> ); $father_of{$son} = $father; } } else { print "Invalid menu selection! Try agin.\n"; } } print "Done!\n"; } sub display_menu { print <<'MENU'; Menu Selections =============== a - add son-father pair e - exit MENU return; } sub get_menu_selection { print "\nEnter menu selection: "; chomp( my $selection = lc <STDIN> ); return $selection; } sub get_son_to_father_map { return ( Jeff => 'Doug', Thomas => 'Evan', Robert => 'Jason', Bruce => 'Richard', Clark => 'Jon', ); }
Here's a sample run:
Menu Selections =============== a - add son-father pair e - exit Enter menu selection: qwerty Invalid menu selection! Try agin. Enter menu selection: Invalid menu selection! Try agin. Enter menu selection: a Son-father pair addition. Enter son's name: JEFF Doug is the father of Jeff Enter menu selection: a Son-father pair addition. Enter son's name: bRuCe Richard is the father of Bruce Enter menu selection: a Son-father pair addition. Enter son's name: fred Enter father's name: BILL Enter menu selection: a Son-father pair addition. Enter son's name: FrEd Bill is the father of Fred Enter menu selection: e Exiting ... Done!
— Ken
|
|---|