Primary script:
#!/bin/bash
source utilities/menu.sh
source utilities/input_validation.sh
header="Choose from the options below(Example: 1, 2, 3 etc...):"
options=("1" "2" "3" "4" "5")
option_descriptions=("Add" "Subtract" "Multiply" "Divide" "Exit")
prompt="> "
calculate(){
if [[ $option == "1" ]]
then
echo "$num1 + $num2" | bc
elif [[ $option == "2" ]]
then
echo "$num1 - $num2" | bc
elif [[ $option == "3" ]]
then
echo "$num1 * $num2" | bc
elif [[ $option == "4" && $num2 != "0" ]]
then
echo "scale=2; $num1 / $num2" | bc
elif [[ $option == "4" && $num2 == "0" ]]
then
echo "Dividing by 0 is undefined"
else
exit=0
fi
}
calculator(){
persistant_get_menu_option "$header" "$options" "$option_descriptions"
option=$?
if [[ $option == "5" ]]
then
return 1
else
persistent_get_number "$prompt"
num1=$?
persistent_get_number "$prompt"
num2=$?
echo "------------------------------------"
calculate "$option" "$num1" "$num2"
echo "------------------------------------"
return 0
fi
}
will_exit="0"
while [[ $will_exit == "0" ]]
do
calculator
if ! [ $? = 0 ]
then
will_exit="1"
else
will_exit="0"
fi
done
echo "Good bye"
Utility scripts:
#!/bin/bash
is_option(){
for option in "${options[@]}"
do
if [ "${option}" = "$choice" ]
then
return 0
fi
done
return 1
}
persistant_get_menu_option(){
choice=""
will_exit="0"
while [[ $will_exit == "0" ]]
do
echo ""
echo "$header"
echo "-----------------------------------------------------------"
i=0
for description in "${option_descriptions[@]}"
do
echo "${options[i]}: $description"
i=$((i + 1))
done
echo ""
read -r choice
is_option "${options[@]}" "$choice"
if [[ $? == "1" ]]
then
echo "You must choose from the options given"
else
will_exit="1"
fi
done
return "$choice"
}
And:
#!/bin/bash
is_numerical(){
if ! [[ $user_input =~ (^-?0\.[0-9]*[1-9]+[0-9]*$)|(^-?[1-9]+[0-9]*((\.[0-9]*[1-9]+[0-9]*$)|(\.[0-9]+)))|(^-?[1-9]+[0-9]*$)|(^0$){1} ]]
then
return 0
else
return 1
fi
}
persistent_get_number(){
user_input=""
will_exit="0"
while [ $will_exit == "0" ]
do
echo "$prompt"
read -r user_input
is_numerical "$user_input"
if ! [ $? = 0 ]
then
echo "Input must be numerical"
else
will_exit="1"
fi
done
return "$user_input"
}
When I try to add 1.2 and 1.2 I get this(the result is 4):
1
>
1.2
utilities/input_validation.sh: line 27: return: 1.2: numeric argument required
>
1.2
utilities/input_validation.sh: line 27: return: 1.2: numeric argument required
------------------------------------
4
------------------------------------
I get the same output when I try to multiple 1.2 by 1.2 as when I add them
The result is almost always wrong when performing calculations with negative numbers.
Example(Trying to multiply -1 by -1 gives 65025 ):
>
-1
>
-1
------------------------------------
65025
------------------------------------
I know I am listing quite a few things here. Posting a separate question for each incorrect calculation seemed kind of redundant so I listed a few here.
Update moved from where it was originally mistakenly added at the end of an answer:
@ Ed Morton I understand what you mean about the negative logic and I intend to fix that I just wanted to be able to actually get the calculations right. Thank you for pointing out my mistake with the return value I have solved the problem with this:
calculator(){
persistant_get_menu_option "$header" "$options" "$option_descriptions"
option=$?
if [[ $option == "5" ]]
then
return 1
else
echo "> "
num1=$(persistent_get_number)
echo "> "
num2=$(persistent_get_number)
echo "------------------------------------"
calculate "$option" "$num1" "$num2"
echo "------------------------------------"
return 0
fi
}
And:
persistent_get_number(){
will_exit="0"
while [ $will_exit == "0" ]
do
read -r user_input
is_numerical "$user_input"
if ! [ $? = 0 ]
then
echo "Input must be numerical"
else
will_exit="1"
fi
done
echo $user_input
}
Choosing 1 of the questions in your question:
returnsets the exit status for a function (as opposed to whatreturnmeans inC, for example) and an exit status is an integer. You're trying to return something that is not an integer, e.g. 1.2, hence the error message. e.g.You probably want to have the function produce output instead of setting it's exit status, e.g. something like this instead:
By the way, regarding:
Negative logic is always harder to read than positive and it can lead to the indecipherable double-negatives so avoid using negative constructs like
!wherever possible. In your code above the "else" reads "it is NOT true that NOT $user_input matches whatever" - a double negative. Just write positive logic instead:Ditto for:
vs:
and I'd guess other places in your code - think positive.