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