#!/usr/bin/perl use strict; use warnings; # We need to use Getopt::Long. This enables us to use the GetOptions function # defined in it (in perl's terminology we are importing the function). use Getopt::Long; # Store the operation and other args in here. my ($num1, $num2, $add, $mult, $div, $sub, $operation); # Store the result and the descriptive text here. my ($result, $text); # This is our usage message. my $usage = "Usage: $0 --number1=N --number2=M\n"; $usage .= "(--add|--subtract|--divide|--multiply])|\n"; $usage .= "(--operation=(add|substract|multiply|divide))\n"; # This syntax creates a regular expression that can be used in a match # just like any other but assigns it to a variable. my $re = qr/^-?\d+\.?\d*$/; # Call the GetOptions function, passing references to the scalar variables # that we are going to store the arguments in. We use the hash => because # it's more readable. my $opt_result = GetOptions( 'number1=i' => \$num1, 'number2=i' => \$num2, 'add' => \$add, 'multiply' => \$mult, 'divide' => \$div, 'subtract' => \$sub, 'operation=s' => \$operation); # If GetOptions returns false, it will have printed an error message. die $usage unless $opt_result; # Do some real checks on our data. # We don't want more than one of the operations to be specified. Each of # these has been set to one by GetOptions if it was present so adding them # up tells us if we have more than one of them. my $check = $add + $sub + $mult + $div; die $usage if $check > 1; # If operation was specified we don't want any of the others die $usage if $operation and $check; # Next, check we have things we can use as numbers in $num1 and $num2. # This is naive and not necessarily the best answer (check Friedl for the best). die $usage unless $num1 =~ $re and $num2 =~ $re; # Finally (!), if $operation is set, make sure it's some thing we like. if ($operation) { die $usage unless $operation =~ /^add|subtract|multiply|divide$/i; } else { die $usage unless $check; # No operation specified at all } # Copy $operation over to the other args if need be. This lets us only # examine on variable below. $add = 1 if lc($operation) eq 'add'; $div = 1 if lc($operation) eq 'divide'; $mult = 1 if lc($operation) eq 'multiply'; $sub = 1 if lc($operation) eq 'subtract'; # Do the sum! Store the result and the text we want to print. if ($add) { $result = $num1 + $num2; $text = 'added to' } elsif ($div) { die "$0: Divide by zero not allowed\n" unless $num2; $result = $num1 / $num2; $text = 'divided by'; } elsif ($sub) { $result = $num1 - $num2; $text = 'minus'; } else # Only multiply is left { $result = $num1 * $num2; $text = 'times'; } # Pretty print the results. printf "%0.4f %s %0.4f is %0.4f\n", $num1, $text, $num2, $result;