英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论