in reply to Re^2: Switch statement?
in thread Switch statement?

Well, I've used the code corian posted. And, o course, it works perfectly. Except, I edited it in places, and now wierd stuff happens. :(. Basically, when I use the -c or -r option, it works great. But when I use the -a option, it tells me I've left off the option, but doesn't give me the error until AFTER it prints SOME of the data. Strange. The other thing is, why does the order change everytime the script is run?
#!/usr/bin/perl -w use strict; my $infile = $ARGV[0]; my $act = $ARGV[1]; my $included = "n"; my $lvar =""; my @validchars = ("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"); if ($#ARGV < 1) { print "Usage: $0 <file> <chars> Where <chars> can be -a or -c: -a: show all charactors. (ie, spaces, etc.) -c: show only regular charactors, but keep case. (ie, x is diff +erent than X.) -r: show only regular charactors, disregard case. (ie, t and T +are the same.)\n"; exit; } my $count = 0; system("cls"); #win system("clear"); #*nix open INPUT, "<$infile" or die "Couldn't open '$infile' : $!"; my $input = do { local $/; <INPUT> }; my %histogram; for my $char (split //, $input) { $included = "n"; if ($act eq "-a") { $histogram{$char}++; $count++; } elsif ($act eq "-c") { foreach $lvar (@validchars){ if ($lvar eq uc($char)) {$included = "y";} } if ($included eq "y") { $histogram{$char}++; $count++; } } elsif ($act eq "-r") { foreach $lvar (@validchars){ if ($lvar eq uc($char)) {$included = "y";} } if ($included eq "y") { $histogram{uc($char)}++; $count++; } } else { print "Bad charactor option: '$act'.\n"; exit; } }; print "Of $count charactors:\n\n"; for (keys %histogram) { if ($_ eq "\n") { print "'\\n' occurred $histogram{$_} times. (".(($ +histogram{$_}/$count)*100)."%)\n"} else { print "'$_' occurred $histogram{$_} times. (".(($histogram{$ +_}/$count)*100)."%)\n" } };
Thanks again, -Jack C jack@crepinc.com

Replies are listed 'Best First'.
Re^2: Switch statement?
by Corion (Patriarch) on Jul 19, 2004 at 20:15 UTC

    The reason that your order of keys is different every time is that a hash has no predefined order of keys (due to the mechanics of how hashes work, and due to the fact that Perl randomizes that order some more). So you will maybe want to sort the keys before printing them:

    for (sort keys %histogram) { ... };

    I find a style issue with your @validchars usage - normally, if you want to quickly check whether something is contained in a list in Perl, you use a hash:

    my %validchars = map { $_ => uc $_ } (qw( A B C D E F ... Z a b c d .. +. z )); # this sets # $validchars{A} = A # ... # $validchars{Z} = Z # $validchars{a} = A # ... # and the later: if (exists $validchars{$_}) { my $target = $validchars{$_}; $histogram{$target}++ };

    For your different switches, you should simply initialize %validchars to different values instead of rechecking your switch values every time. This will clean up your inner loop as the program behaviour is centralized.

    my %validchars; if ( $arg eq '-a' ) { %validchars = map { $_ => uc $_ } ( \x00 .. \xff ); } elsif ( $arg eq '-c' ) { %validchars = map { $_ => $_ } ( 'A' .. 'Z', 'a'..'z' ); };

    Whenever you are repeating code, think about how you can avoid that repetition.