斐波那契数列,标准输入必须是自然数1

斐波那契数列,标准输入必须是自然数1

我收到了这个测试问题:

在输出中的以下几行中,写入斐波那契数列从第一项到第 n 项(含)的下一项。我们假设斐波那契数列的第一项和第二项分别为 0 和 1。

我复制了 shell 代码来生成斐波那契数列(从这里),我只需要有条件1<=n<=50,但我不明白如何在 while 循环之后添加它:

function fib
{
  x=0
  y=1
  i=2
  echo "Fibonacci Series up to $n terms :"
  echo "$x"
  echo "$y"
  while [ $i -lt $n ]
  do
      i=`expr $i + 1 `
      z=`expr $x + $y `
      echo "$z"
      x=$y
      y=$z
  done
}
r=`fib $n`
echo "$r"

答案1

您可以在循环之前执行此操作以中止该函数:

if [[ $n -lt 1 ]] || [[ $n -gt 50 ]]
then
    return
fi

您还可以像这样限制输入值:

if [[ $n -lt 1 ]]
then
    n=1
fi
if [[ $n -gt 50 ]]
then
    n=50
fi

这是带有第一个选项的代码的工作版本:

function fib
{
  x=0
  y=1
  i=2
  n=$1
  
  if [[ $n -lt 1 ]] || [[ $n -gt 50 ]]
  then
    return
  fi
  
  echo "Fibonacci Series up to $n terms :"
  echo "$x"
  echo "$y"
  while [[ $i -lt $n ]]
  do
      i=`expr $i + 1 `
      z=`expr $x + $y `
      echo "$z"
      x=$y
      y=$z
  done
}
r=`fib $n`
echo "$r"

答案2

请注意,在 bash 和其他类似 Korn 的 shell 中,在算术表达式中使用未经清理的数据其中包括 Korn 风格的((...))和构造$((...))内部算术运算符的参数,[[...]]这引入了任意命令执行漏洞。

expr通常无法可靠使用,并且已经过时了几十年。

因此,在任何算术上下文中使用输入之前,您应该对输入进行清理,以确保它是您期望的格式的有效数字。

在 bash 算术表达式中,带有前导零的数字被解释为八进制,因此最好也拒绝它们。最后要过滤掉 1 .. 50 之外的数字,使用文本模式匹配可能会更容易:

case $1 in
  ([123456789] | [1234][0123456789] | 50) ;;
  (*) echo>&2 Not a decimal integer number in the 1..50 range; exit 1
esac

答案3

在现代 shell 中,避免旧的已弃用的数学语法和反引号,增强可读性:

#!/bin/bash

fib(){

    x=0 y=1 i=2 n=$1

    ((n < 1 || n > 50)) && return

    echo "Fibonacci Series up to $n terms :"
    echo "$x"
    echo "$y"
    while ((i++ < n)); do
        z=$((x+y))
        echo "$z"
        x=$y y=$z
    done
}

read -p 'Type an integer between 1 and 50 as max terms >>> ' n
r=$(fib $n)
echo "$r"

((...))$((...))是算术命令,如果表达式非零,则返回退出状态 0;如果表达式为零,则返回 1。如果需要副作用(分配),也用作“let”的同义词。看http://mywiki.wooledge.org/ArithmeticExpression


反引号用于旧式命令替换。foo=$(command)建议改用该语法。内部的反斜杠处理$()并不令人惊讶,并且$()更容易嵌套。看http://mywiki.wooledge.org/BashFAQ/082


expr是古代 shell 代码中用来做数学的程序。在 bash 等 Posix shell 中,使用$(( expression )).在 bash、ksh、mksh、pdksh、yash、dash、ash、sh 或 zsh 中,您还可以使用(( expression ))

相关内容