r2d222 r2d222 - 1 year ago 56
Perl Question

Why is this Perl CGI Program not calculating items in hash array?

I wrote a program that allows users to pick the size of the product and put the sizes in a hash array. However, when I try to code the part where it adds up all the toppings listed (the user can pick multiple toppings but just 1 size), my formula is not working.

my %size = ('Regular' => 6.00,
'Large' => 8.00,
'Family' => 11.00);

my $size = param('size');

my @toppings = param('toppings');

my $total_topping = $toppings * 1.25;
my $total = $size + $total_topping;
print ('Total Due: $total');

Answer Source

As other have mentioned, you should alway include use strict and use warnings in your code. That would point out some of your problems.

Let's look at your code.

# This defines a hash mapping sizes of pizza to price
my %size = ('Regular' => 6.00,
        'Large' => 8.00,
        'Family' => 11.00);

# And this gets the size parameter from the user's request.
# Presumably, this value should be one of the keys from the %size hash.
my $size = param('size');

# This gets an array of all of the toppings the user has selected.
my @toppings = param('toppings');

# Each topping adds £1.25 to the price, so to get the total price
# for toppings, we need to multiply the number of toppings by 1.25.
# But that's not what you're doing here. You're using a new scalar 
# variable called $toppings. This will be undef and will therefore
# be interpreted as zero.
# This problem would have been picked up by "use strict"
my $total_topping = $toppings * 1.25;

# And here you're adding $size to $total_toppings to get the
# total price of the pizza. But $size doesn't contain the price,
# it contains the description of the size. Any of your sizes will
# be interpreted as 0 when used as a number. So $total will end
# up as 0 + 0 = 0.
# This problem would have been picked up by "use warnings".
my $total = $size + $total_topping;
print ('Total Due: $total');

So, you had two errors:

  1. You used $toppings instead of @toppings to get the number of toppings.
  2. You forgot to translate the size name to the size price.

Your code should look more like this:

my %size = (Regular => 6.00,
            Large   => 8.00,
            Family  => 11.00);

my $size = param{'size');
# Check for valid size
if (! exists $size{$size}) {
  die "$size is not a valid size of pizza";
}
# Convert name of size to cost of size.
my $size_cost = $size{$size};

my @toppings = param('toppings');

# Array in scalar context gives number of elements
my $total_toppings = @toppings * 1.25;

my $total = $size_cost + $total_topping;
print ('Total Due: $total');