0
#!/bin/bash

set -x

count=0
number=0
loops=0
average=0

read -p " Please enter a number between 1 and 100? " number

while [ $count -lt $number ]
done

average=`expr $score / $number`

echo $average

Create a shell program that asks the user to enter a number between 1 and 100 and exists the loops once the sentinel value of -1 is entered. The program must keep a count of all of the loops iterations, total counts along with the average number once the program ends.

I'm guessing I have to use an if statement but I don't quite know how to.

0

4 Answers 4

6

There are probably more efficient ways of doing this, but the following script should do the job:

#!/bin/bash

loops=0
sum=0

# Loop forever
while true; do
    read -p "Please enter a number between 1 and 100: " input

    # Check for the exit condition.
    if [[ $input -eq -1 ]]; then
        break
    fi

    # Use a regex to check that input is a one-digit, two-digit or three-digit number and that the input is in [1,100] .
    if [[ $input =~ ^[0-9]{1,3}$ && $input -gt 0 && $input -le 100 ]]; then
        # Use arithmetic expansion to increment loop counter and add the new input to sum.
        ((loops++))
        ((sum += input))
    else
        echo "Invalid input. Skipping..."
    fi

done

# For the edge case where there is no valid input.
if [[ $loops -eq 0 ]]; then
    echo "Average undefined - no valid input."
    exit
fi

average=$((sum/loops))

echo "Average: $average"

Sample run:

Please enter a number between 1 and 100: 2
Please enter a number between 1 and 100: 3
Please enter a number between 1 and 100: 4
Please enter a number between 1 and 100: 5
Please enter a number between 1 and 100: 6
Please enter a number between 1 and 100: -1
Average: 4
8
  • If there are no numbers given, it doesn't make sense to calculate an average at all. The average of nothing isn't zero, it's just undefined.
    – ilkkachu
    Dec 13, 2018 at 7:27
  • @ilkkachu Thanks for the indentation edit and the feedback. I've modified the error checking if to echo a message and exit.
    – Haxiel
    Dec 13, 2018 at 11:10
  • It's debatable whether "between 1 and 100" means the inclusive range 1-100 or 2-99. I would have gone for 1-100 because 2-99 seems rather arbitrary and awkward.
    – Kusalananda
    Dec 13, 2018 at 11:17
  • @Kusalananda Right, that makes sense. In that case, I could start with a regex to check for a 1 to 3-digit number, then check n>0 and n<= 100. Do you see a more efficient way?
    – Haxiel
    Dec 13, 2018 at 11:37
  • Or you could just look for a non-digit and skip if found. And, yes, check [1,100] if no non-digit was found.
    – Kusalananda
    Dec 13, 2018 at 11:42
2

I did not understand your requirement correctly. Still I tried to do my level best. If you need something else, comment below so that I can edit this answer.

Here is the Shell Script:

$ cat sentinel_2.sh
score=0
loops=0
average=0
while :
do
        read -p "Please enter a number between 1 and 100 : " number
        if ! [ "$number" -eq "$number" ] 2> /dev/null
        then
                echo "Not integer"
        elif [ $number -eq -1 ]
        then
                echo "You entered -1, program exits"
                break
        elif [ $number -gt 100 ] || [ $number -lt 1 ]
        then
                echo "Out of range"
        else
                loops=`expr $loops + 1`
                score=`expr $score + $number`
                echo 'iteration= '$loops' and score = '${score}
        fi
done
echo 'Final score = ' $score
echo 'Total iterations= ' $loops
if [ $score -eq 0 ] || [ $loops -eq 0 ]
then
        echo "score and iteration are needed to calculate average"
else
        echo 'Average = Final Score / Total iterations'
        average=$(($score / $loops))
        echo 'Average is = '${average}
fi

Sample Output:

$ sh sentinel_2.sh
Please enter a number between 1 and 100 : 3
iteration= 1 and score = 3
Please enter a number between 1 and 100 : 5
iteration= 2 and score = 8
Please enter a number between 1 and 100 : 2
iteration= 3 and score = 10
Please enter a number between 1 and 100 : abcd
Not integer
Please enter a number between 1 and 100 : 102
Out of range
Please enter a number between 1 and 100 : 4
iteration= 4 and score = 14
Please enter a number between 1 and 100 : -1
You entered -1, program exits
Final score =  14
Total iterations=  4
Average = Final Score / Total iterations
Average is = 3

Sample Output with Negative Cases:

$ sh sentinel_2.sh
Please enter a number between 1 and 100 :
Not integer
Please enter a number between 1 and 100 :
Not integer
Please enter a number between 1 and 100 :
Not integer
Please enter a number between 1 and 100 : abc
Not integer
Please enter a number between 1 and 100 : 100
iteration= 1 and score = 100
Please enter a number between 1 and 100 : 102
Out of range
Please enter a number between 1 and 100 : -1
You entered -1, program exits
Final score =  100
Total iterations=  1
Average = Final Score / Total iterations
Average is = 100
$ sh sentinel_2.sh
Please enter a number between 1 and 100 : 0
Out of range
Please enter a number between 1 and 100 : 102
Out of range
Please enter a number between 1 and 100 : abcd
Not integer
Please enter a number between 1 and 100 : -1
You entered -1, program exits
Final score =  0
Total iterations=  0
score and iteration are needed to calculate average
0
#!/bin/bash

declare -i num total avg cnt ;

while read -p "Enter a number: " num ; do
    [[ "$num" == "" ]] || [[ $num -eq 0 ]] || [[ $num -gt 100 ]] || [[ $num -lt -1 ]] && echo "ERROR: Out of range" && continue;
    [ $num -eq -1 ] && break ;

    ((cnt++));
    ((total+=$num));
    avg=$(($total/$cnt));
done ;

echo "Count: $cnt Total: $total Avg: $avg"
0

Rather than using if-statements:

#!/bin/bash

while IFS= read -r -p 'Enter number 1-100: '
do
    case $REPLY in
        -1)
            break
            ;;
        [1-9]|[1-9][0-9]|100)
            sum=$(( sum + REPLY ))
            nums=$(( nums + 1 ))
            ;;
        *)
            printf '%s is not a valid input\n' "$REPLY" >&2
    esac
done

printf '\n'
printf 'Sum of %d numbers is %d\n' "$nums" "$sum"
printf 'Avg of %d numbers is %d\n' "$nums" "$(( sum/nums ))"

This uses the pattern [1-9]|[1-9][0-9]|100 to match valid input (numbers 1-9, 10-99, and 100). It also allows the user to exit the loop by pressing Ctrl+D, which is commonly used to signal the end of input.

2
  • beware of division by zero. Dec 13, 2018 at 16:54
  • @glennjackman Why? The shell displays an appropriate error message when that happens.
    – Kusalananda
    Dec 13, 2018 at 17:03

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .