I have built a CLI calculator in Bash and can't figure out why I am getting multiple incorrect calculatons even though I am usine BC

huangapple go评论73阅读模式
英文:

I have built a CLI calculator in Bash and can't figure out why I am getting multiple incorrect calculatons even though I am usine BC

问题

以下是你的代码的翻译部分:

主要脚本:

#!/bin/bash

source utilities/menu.sh
source utilities/input_validation.sh

header="从以下选项中选择(示例:1、2、3 等...):"
options=("1" "2" "3" "4" "5")
option_descriptions=("加" "减" "乘" "除" "退出")
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 "除以0未定义"
  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 "再见"

实用脚本(utilities/menu.sh 和 utilities/input_validation.sh)的翻译不包括具体的代码,只包括文件名和一般描述。

如果你有任何其他需要翻译的部分,请继续提出。

英文:

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
}

答案1

得分: 1

return 设置了函数的退出状态(与 C 中的 return 不同),退出状态是一个整数。你试图返回的是一个不是整数的东西,比如 1.2,因此会出现错误消息。例如:

$ foo() { return 1.2; }
$ foo
-bash: return: 1.2: 需要数值参数

你可能希望函数产生输出而不是设置退出状态,例如这样:

$ foo() { printf '%s\n' 1.2; }
$ var=$( foo )
$ echo "$var"
1.2

顺便提一下,关于:

is_numerical(){
  if ! [[ $user_input =~ whatever ]]
  then
    return 0
  else
    return 1
  fi
}

否定逻辑总是比肯定逻辑难以阅读,而且可能导致难以理解的双重否定,因此尽量避免在可能的情况下使用否定构造,你的代码中,else 部分的含义是“不是 $user_input 匹配 whatever” - 双重否定。只需改用肯定逻辑即可:

is_numerical(){
  if [[ $user_input =~ whatever ]]
  then
    return 1
  else
    return 0
  fi
}

同样适用于:

if ! [ $? = 0 ]
then
  echo "Input must be numerical"
else
  will_exit="1"
fi

与以下写法相比:

if [ $? = 0 ]
then
  will_exit="1"      
else
  echo "Input must be numerical"
fi

我猜测你的代码中可能还有其他地方也可以使用肯定逻辑,思考一下吧。

英文:

Choosing 1 of the questions in your question:

return sets the exit status for a function (as opposed to what return means in C, 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.

$ foo() { return 1.2; }
$ foo
-bash: return: 1.2: numeric argument required

You probably want to have the function produce output instead of setting it's exit status, e.g. something like this instead:

$ foo() { printf '%s\n' 1.2; }
$ var=$( foo )
$ echo "$var"
1.2

By the way, regarding:

is_numerical(){
if ! [[ $user_input =~ whatever ]]
then
return 0
else
return 1
fi
}

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:

is_numerical(){
if [[ $user_input =~ whatever ]]
then
return 1
else
return 0
fi
}

Ditto for:

if ! [ $? = 0 ]
then
echo "Input must be numerical"
else
will_exit="1"
fi

vs:

if [ $? = 0 ]
then
will_exit="1"      
else
echo "Input must be numerical"
fi

and I'd guess other places in your code - think positive.

huangapple
  • 本文由 发表于 2023年5月29日 10:57:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/76354433.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定