Gordon Low wrote: > > Wondered if anyone can throw some light on why this script won't act > properly.
Certainly. > Wrote it to convert a string using a ceaser cipher for a course I am > doing. Basically get the string and replace each character with the > character offset by 3 or 4 up to 26. Have to try up to 26 times so it > was crying out for a script, trouble is it doesn't work the way I > intended and I cannot see how. > > No real attempts at error catching have been done as it was only > supposed to be used by myself. > Supposed to do this > Enter > >cipher.pl phhw dw plgqljkw > ...and get all 26 different combinations to crack the message. > Trouble is I get this..... > qiix ex qmhrmklx -------> offset = 1 <------- > qiix ex qmhrmklx -------> offset = 1 <------- > rjjy fy rnisnlmy -------> offset = 2 <------- > qiix ex qmhrmklx -------> offset = 1 <------- > rjjy fy rnisnlmy -------> offset = 2 <------- > skkz gz sojtomnz -------> offset = 3 <------- > qiix ex qmhrmklx -------> offset = 1 <------- > rjjy fy rnisnlmy -------> offset = 2 <------- > skkz gz sojtomnz -------> offset = 3 <------- > tlla ha tpkupnoa -------> offset = 4 <------- > > Instead of just going through once it is repeating ie loops to 1 then > loops to 2 then loops to 3 up till loops to 25. Cracks the message ok at > offset 23 but I don't want it looping all the time. Code follows, I am > on Linux 8.0 with Perl 5.8, there is probably better ways to do this but > it is driving me mad trying to see the logical problem, hoping someone > can help. > > ******************************************************************* > #!/usr/bin/perl -w > use strict; > > my @alpha = > ("a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"); Ouch. Writing out each letter is error prone. It is better to use the range operator to create the list. my @alpha = 'a' .. 'z'; > my %alphat; > my $count; > my $ceascount; > my $op = ""; > > foreach (@alpha){ # set up a lookup table for the array > offset > $alphat{$alpha[$count]} = $count; > $count++; > } When this loop runs I get the warning: Use of uninitialized value in array element at ./cipher.pl line 92. Where line 92 is "$alphat{$alpha[$count]} = $count;" because the initial value in $count is undef. You can explicitly set $count: my $count = 0; foreach ( @alpha ){ # set up a lookup table for the array offset $alphat{ $alpha[ $count ] } = $count; $count++; } However, I was wondering why you are looping through the values in @alpha but not using them? foreach ( @alpha ){ # set up a lookup table for the array offset $alphat{ $_ } = $count++; } That eliminates the warnings message and makes the code shorter and easier to read but you can do the same thing without the foreach loop and the $count variable by using a hash slice: # set up a lookup table for the array offset @alphat{ @alpha } = 0 .. $#alpha; > for ($ceascount = 1; $ceascount < ($#alpha +1);$ceascount++,print > $op){ # try all ceaser cipher offsets That looks more like C then Perl. :-) A more perl-ish way to write that is: for my $ceascount ( 1 .. $#alpha ) { # try all ceaser cipher offsets ... } continue { print $op; } Your problem is that after printing $op it retains the contents from the previous iteration of the loop. You need to clear out the contents of $op after you print it: for my $ceascount ( 1 .. $#alpha ) { # try all ceaser cipher offsets ... } continue { print $op; $op = ''; } > foreach (@ARGV){ # take in each command line arg > for ($count=0; $count < length($_); $count++){ # go through > each arg and convert with cipher A more perl-ish for loop would be: for my $count ( 0 .. length() - 1 ){ # go through each arg and convert with cipher > $op .= $alpha[($alphat{substr($_,$count,1)} + $ceascount) % > ($#alpha+1)]; # conversion > } > $op .= " "; # space between args > } > $op .= " -------> offset = $ceascount <-------\n"; # final result > } # use another ceaser cipher offset A simpler way to write that: #!/usr/bin/perl use warnings; use strict; my @alpha = 'a' .. 'z'; my @ceaser = @alpha[ 1 .. $#alpha, 0 ]; my %alphat; @alphat{ @alpha } = @ceaser; my $code = "@ARGV"; for my $ceascount ( 1 .. $#alpha ) { ( my $message = $code ) =~ s/([EMAIL PROTECTED])/ exists $alphat{ $1 } ? $alphat{ $1 } : $1 /eg; print "$message -------> offset = $ceascount <-------\n"; @alphat{ @alpha } = @ceaser = @ceaser[ 1 .. $#ceaser, 0 ]; } __END__ John -- use Perl; program fulfillment -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] <http://learn.perl.org/> <http://learn.perl.org/first-response>