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>


Reply via email to