in reply to Hashes and Associative Arrays

hello phizymonk, welcome to the monastery and to the wonderful world of Perl

following the path GrandFather drawn for you (think about the program before coding) and as you are learning Perl i propose you some pseudo-code insetead of a a full featured script that satisfy your task. I add some sparse suggestion that you can try to expand to code. GrandFather insisted on specifications: how the user will interact with the program? it is important! Generally speaking if you are able to write in plain language the solution, then you'll be able to code it or at least (if your skill are not enought) to spot what part you are not able to code: it is a great advantage.

As foreword suggestions, try to code in a plain and well documented way, idiomatically: as already said by GrandFather use strict and warnings, use open with 3 arguments (idiomatic = more reliable and less error prone). Try to isolate behaviours in subroutines: it will help a lot when the code become more complex. And, very important, choose meaningfull names for your variables.

I think you simply need an array instead of an hash: you definetively read an array of lines from file. Work with this array; it is indexed, it is easy to use and faster and without side effects (duplicate can exists in a file and in array not in an hash)

# pseudocode # PART 0 - load useful stuffs and define some useful vars use strict; use warnings; # maybe use Term::ReadLine; # a useful tool to grab user input my $filename = $ARGV[0] || 'defaultfile.txt'; my $separator = ' - '; # in your OP you split using '-' and this leave +s a blank space after the item an another before the price! my $was_modified = 0; # count total modifications make a copy of the original file with a date in the name and possibly +another exstension, just in case open the file for reading my @alllines = <$file_handle>; # in list context <> reads all the line +s (good for not huge files) # ATTENTION: you still have all newline +s at end of each record!! close file_handle or die # PART 1 - present the file to the user: show also the index of the ar +ray that we will use to modify the entry, later # better to define a sub to show the file content: sub showfile { foreach my $index( 0 .. $#alllines ) { # $#alllines is the last ind +ex (the number of) of the @alllines array chomp $alllines[$index]; # remove newlines print "[$index] $alllines[$index]\n" } modify_from_input; # call teh sub defined below: grab user input and +come back to this sub again } showfile; # call the sub # PART 2 - edit prices # grab the user input and modify the array entry. a sub is better sub modify_from_input { print "Enter the index you want to modify: (0 - $#alllines)\n"; my $input = ... # grab the input chomp $input; # remember newlines! if input is invalid warn something and call the same sub again else my ($name, $price) split $separator, $alllines[$index]; print "Enter new price for [$name] (was [$price]) or 'write' to writ +e the file:\n" my $new_price = <STDIN>; chomp $new_price; # validate $new_price ? if new_price is empty -> remove the item? -> splice the array -> sho +wfile return if $new_price eq 'write'; # break the loop of the 2 subs and +go to the end of program # modification! $was_modified++; $alllines[$index] = $name.$separator.$new_price; showfile; # we go back in show mode } # PART 3 - modify the file: we arrive here only if user enter 'write' +while in the modify_from_input sub open my $write, '>', filename or die # here we are rewriting the orig +inal file print $write "$_\n" for @alllines; if $was_modified print "$was_modified modifications were applied\n" else print "no modifications\n" close $write or die; print "$filename succesfully written\n"; exit 0;


have fun filling the blanks!

L*

There are no rules, there are no thumbs..
Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
  • Comment on Re: Hashes and Associative Arrays -- modify an array given user input
  • Download Code