问题描述
我正在尝试制作一个简单的计算器。我敢肯定,如果你只是看一眼这段代码,你就会明白我在做什么。 输入一个数字,然后选择一个操作数,然后 vim 应该打印出一个最多 15 的表格,其中包含您的数字和操作数...
也许这个方法很愚蠢,试图在嵌套的 if 语句中嵌套大量循环。但我是 bash 新手。
错误是第 24 行“在 else 附近出现意外标记”,但我觉得我不理解的嵌套存在根本问题。
这是当前代码。
#!/bin/bash
choice=6
read -p "Enter a number bruv" num
#choose operand.
echo "Now choose an operand comrade"
#choices
echo "1. *"
echo "2. +"
echo "3. -"
echo "4. /"
echo "5. ^"
echo -n "Please choose [1,2,3,4,5]"
while [ $choice -eq 6 ]; do
read choice
if [ $choice -eq 1 ] ; then
for((i=0;i<=15;i++))
do
echo -n "$i * $num = $[ $i * $num ] "
echo " "
else
if [ $choice -eq 2 ] ; then
for((i=0;i<=15;i++))
do
echo -n "$i + $num = $[ $i + $num ] "
echo " "
else
if [ $choice -eq 3 ] ; then
for((i=0;i<=15;i++))
do
echo -n "$i - $num = $[ $i - $num ] "
echo " "
else
if [ $choice -eq 4 ] ; then
for((i=0;i<=15;i++))
do
echo -n "$i / $num = $[ $i / $num ] "
echo " "
else
if [ $choice -eq 5 ] ; then
for((i=0;i<=15;i++))
do
echo -n "$i ^$num = $[ $i ^$num ] "
echo " "
else echo "Please choose between 1 and 5!!!"
echo "1. *"
echo "2. +"
echo "3. -"
echo "4. /"
echo "5. ^"
echo -n "Please choose [1,5]"
fi
fi
fi
fi
fi
done
实施这个会更好吗?
# !/bin/bash
# Take user Input
echo "Enter number : "
read a
# Input type of operation
echo "Enter Choice :"
echo "1. Addition"
echo "2. Subtraction"
echo "3. Multiplication"
echo "4. Division"
echo "5. Power"
read ch
# Switch Case to perform
# calulator operations
case $ch in
1)res=`for((i=0;i<=15;i++))
do
echo -n "$i - $num = $[ $i - $num ] "
echo " "`
;;
2)res=`for((i=0;i<=15;i++))
do
echo -n "$i - $num = $[ $i - $num ] "
echo " "`
;;
3)res=`for((i=0;i<=15;i++))
do
echo -n "$i - $num = $[ $i - $num ] "
echo " "`
;;
4)res=`for((i=0;i<=15;i++))
do
echo -n "$i - $num = $[ $i - $num ] "
echo " "c`
;;
esac
echo "Result : $res" ```
解决方法
这是一个解决方案,使用一个函数:
#! /bin/bash
ITER_MAX=15
show_values() # n op
{
local n=$1 op=$2
for ((i=0; i<=ITER_MAX; i++)); do
((i>0)) && echo -n " ; "
echo -n "$i $op $n = $((i $op n))"
done
echo
}
# Take user Input
read -p "Enter number : " a
# Input type of operation
echo "Enter Choice (Ctrl+C to stop):"
PS3=">> "
select ch in Addition Subtraction Multiplication Division Power ; do
case "$ch" in
Add*) op="+" ;;
Sub*) op="-" ;;
Mul*) op="*" ;;
Div*) op="/" ;;
Pow*) op="**" ;;
*) echo "Bad choice,abort" >&2 ; break ;;
esac
show_values "$a" "$op"
done
一些解释:
-
(( ))
是算术计算,$(( ))
是算术展开 -
((i>0)) && echo -n " ; "
等价于if ((i>0)); then echo -n " ; " ; fi
-
read -p "Enter number : " a
等价于echo -n "Enter number : " ; read a
- 关于
select
,请参阅 bash 终端中的help select
。
Line 20:
for((i=0;i<=15;i++))
^-- SC1009: The mentioned syntax error was in this for loop.
^-- SC1073: Couldn't parse this arithmetic for condition. Fix to allow more checks.
Line 21:
do
^-- SC1061: Couldn't find 'done' for this 'do'.
Line 24:
else
^-- SC1062: Expected 'done' matching previously mentioned 'do'.
^-- SC1072: Unexpected keyword/token. Fix any mentioned problems and try again.
另一种选择:
read -p "Enter a number and an operator: " -a a
for n in {1..15}; do printf "%+10s\n" $((${a[@]} $n)); done
-p
告诉 read
提供提示。 -a
读入数组(此处命名为 a
)。{1..15}
是内置的 bash
序列语法。%+10s
告诉 printf
用空格键/右对齐到 10 个字符。${a[@]}
替换为数组的所有元素 - 数字和运算符。$(( ... ))
进行算术处理并用结果(作为字符串)替换自身。
因此,如果您输入“10 *”,则 $((${a[@]} $n))
第一次处理 10 * 1
,因此 printf "%+10s\n" $((${a[@]} $n))
输出带有尾随换行符的“10”。然后循环在每次迭代时用下一个数字替换 1,最多为 15。这也允许使用其他运算符,例如用于模数的 %
,但如果给出无效的值,则会崩溃。
如果你想要错误检查 -
while [[ ! "${a[*]}" =~ ^[0-9][0-9]*\ ([*/+-]|\*\*)$ ]]
do read -p "Enter a,integer and an operator (one of: + - * / **) " -a a
done
for n in {1..15}; do printf "%+10s\n" $((${a[@]} $n)); done
如果你想要浮点数学,试试bc
:
while [[ ! "${a[*]}" =~ ^[0-9]+.?[0-9]*\ ([*/+-]|\*\*)$ ]]
do read -p "Enter a,integer and an operator (one of: + - * / **) " -a a
done
for n in {1..15}; do printf "%+15s\n" $(bc -l <<< "scale=3;${a[@]} $n"); done
就个人而言,我会将输入放在命令行上。不太模糊,尽管它可能需要引用 *
运算符,具体取决于您的运行方式和目录中的内容。
#!/bin/bash
me=${0##*/}
use="
use: $me {number} {operator} [iterations] [scale]
Numbers may include one decimal point.
Operators must be one of: + - * / **
"
while getopts "n:o:i:s:" arg
do case $arg in
n) n="$OPTARG" ;;
o) o="$OPTARG" ;;
i) i="$OPTARG" ;;
s) s="$OPTARG" ;;
*) printf "%s\n" "Invalid argument '$arg' $use";
exit 1;;
esac
done
[[ -n "$n" && -n "$o" ]] || { echo "$use"; exit 1; }
[[ "$n" =~ ^[0-9]+.?[0-9]*$ ]] || { printf "%s\n" "Invalid number '$n' $use"; exit 1; }
[[ "$o" =~ ^([*/^+-]|\*\*)$ ]] || { printf "%s\n" "Invalid operator '$o' $use"; exit 1; }
[[ "${i:=15}" =~ ^[0-9]+.?[0-9.]$ ]] || { printf "%s\n" "Invalid number '$i' $use"; exit 1; }
[[ "${s:=3}" =~ ^[0-9]+$ ]] || { printf "%s\n" "Invalid scale '$s' (must be an integer) $use"; exit 1; }
c=1
while ((c < i))
do printf "%+15s\n" $(bc -l <<< "scale=$s; $n $o $c")
((c++))
done