Problem with calculator script

I'm having some trouble implementing a basic calculator using command line options. The script is supposed to take (multiple) arguments -a,-d,-m,-s for addition, multiplication, division, and subtraction. I'm pretty sure I know how to parse through the options with getopt(), but I have no idea how to get both arguments to operate on (ex: 7 -a 7, no idea how to get both 7's). I'm pretty sure I can get the first one, but no idea how to get the second.

Here's my current code:

#!/bin/bash

function printhelp {
echo "mymath.sh usage:"
echo "   mymath.sh [-options] [num1 num2]"
echo ""
echo "where options include:"
echo ""
echo " options that require 2 arguments (multiple options are allowed):"
echo "   -a   add           add num1 and num2"
echo "   -s   subtract      perform num1 minus num2"
echo "   -d   divide        divide num1 by num2 (integer division)"
echo "   -m   multiply      multiply num1 and num2"
echo ""
echo " options that cannot take any arguments, nor any other option:"
echo "   -h   help          display this message"
echo "   -v   version       provides the script's version (hard-coded)"
}

function printversion {
echo "Welcome to MyMath! Current version is v1.0"
}

function add {
   sum="$1 + $2"
   echo $sum
}

function multiply {
   product="$1" * "$2"
   echo $product
}

function subtract {
   diff="$1" - "$2"
   echo $diff
}

function divide {
   quotient="$1"/"$2"
   echo $quotient
}

if [ $# -le 1 ];
then
   if [ "$1" == "-h" ]; then
      printhelp
   elif [ "$1" == "-v" ]; then
      printversion
   else 
      printhelp
   fi
fi

while getopts "a:s:d:m:" opt
do
  case "$opt" in
    a) add $oper1 $oper2    
    ;;
    s) subtract $oper1 $oper2
    ;;
    d) divide $oper1 $oper2
    ;;
    m) multiply $oper1 $oper2
    ;;
    \?) 
    echo "Invalid option: -$OPTARG" >&2
    echo ""
    printhelp;;
    :)
        echo "Option -$OPTARG requires an argument." >&2
    printhelp
        exit 1
      ;;

  esac
done

Thanks for any help.

take both values in 1 argument separated by ;(comma) or something else. then split values to use it as individuals.

mymath.sh -a 12;24

and in your code,

val1=`echo $optarg | cut -d";" -f1`
val2=`echo $optarg | cut -d";" -f2`

now pass val1 and val2 to your applicable function.

Thanks for the help, but that's not allowed.

Has to be in the form

mymath.sh [-options] [-args]

Valid examples:

mymath.sh -a 12 39
mymath.sh -m -d 44 17
mymath.sh 35 -a -d 88 -m

function subtract {
   diff="$1" - "$2"
   echo $diff
}

So your just printing out the equation?

If you want to do the math use

function subtract {
   diff=`expr $1 - $2`
   echo $diff
}

Yep, just figured that out. Not the part I'm having trouble with though. New code will do mymath -a 7 7 but not mymath 7 -d 7

fixed all of the functions, now use

  case "$opt" in
    a) oper1="$OPTARG"
    shift
    oper2=$OPTARG
    add $oper1 $oper2    
    ;;

for each case. Works with mymath -a 7 7, but not the other forms, and doesn't check to see if the user had more than two numbers (it can only take two)

Ok... Then u have to add below mentioned check conditions in your script.

1.> Make sure that only 3 command line arguments are entered.

if [ $# -gt 3  ] ; then display usage

2.> Make sure that arguments are entered properly. I mean first argument must be option and other two must be numbers.

echo $1 | egrep "^[+-][asdmhv]$" | if [ $? -gt 0 ] ; then ; exit ; fi
echo $2 | egrep "^[+-]*[0-9]$" | if [ $? -gt 0 ] ; then ; exit ; fi
echo $3 | egrep "^[+-]*[0-9]$" | if [ $? -gt 0 ] ; then ; exit ; fi

If these conditions are not meet then display usage and simply exit.

Believe me, I would love to do just that; however, like I stated above, the program must be able to accept multiple options (so if the user typed mymath -a -d -m -s 7 7, the script would output the results of each operation).

Ok. So u just want to input 2 numbers and want to perform all operations user has asked to. This is also simple. U have the count of arguments. Run a for loop and check whether only 2 arguments are numbers. See below.

count=0
for arg in `echo "$@"`
do
    echo "$arg" | egrep "^[+-]*[0-9][0-9]*$"
    if [ $? -eq 0 ] ; then
        (( $count += 1 ))
    else
        echo "$arg" | egrep "^[+-][asdm]$"
        if [ $? -gt 0 ] ; then ; display_usage ; exit ; fi
    fi

    if [ $count -gt 2 ] ; then ; display_usage ; exit ; fi
done

This will solve all the problems...:slight_smile:

That's a really good idea, the logic definitely solves part of my problem, but for some reason I'm getting errors.

zak 153 % mymath.sh 7 7 -a
7
mymath.sh: line 52: ((: 0 += 1 : attempted assignment to non-variable (error token is "+= 1 ")
7
mymath.sh: line 52: ((: 0 += 1 : attempted assignment to non-variable (error token is "+= 1 ")
-a

Oh sorry. $ should not be there.

(( count += 1 ))

Use the portable POSIX syntax:

count=$(( $count + 1 ))

Thanks. That takes care of some of it. The other problem is the input order. The getops is fantastic for taking in one argument, but only if they are after a switch.

For this, I would suggest u to develop your script in such a way that it accepts options first and than two numbers at last.

For example:

mymath.sh 7 7 -a        # Invalid
mymath.sh -a -m 7 7   # Valid
mymath.sh -a 7 -m 7 -s   # Invalid

So, build a logic which accepts two numbers followed by all valid options as command line arguments.

Did you ever get options and arguments interspersed properly? If so, how did you go about that?

Unfortunately, this isn't an option. For the assignment I must implement it so that the order does not matter.

Haven't quite figured it out yet. It current works on input that comes after the switches, but not before. It's supposed to be finished by today, but it looks like that won't be happening.

I'm in Curt's class too :wink:

Nice. Well if you have any luck, let me know. I'm pretty stuck.

class/homework - Thread closed!
Please follow the rules! there is a special forum for class / homework, and special rules apply