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>