r2d222 r2d222 - 1 month ago 10
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

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');