Pour une affectation, je dois écrire une fonction qui imprime le nombre de nombres pairs lorsqu'elle est fournie avec une séquence de nombres.
J'ai utilisé le morceau de code que j'avais utilisé pour une affectation précédente (pour imprimer 1
quand un nombre était pair et 0
quand le nombre était impair)
Mon problème maintenant est que ma fonction continue à imprimer 0
. Qu'est-ce que je fais mal?
Voici mon script:
#!/usr/bin/bash
# File: nevens.sh
# Write a function called nevens which prints the number of even numbers when provided with a sequence of numbers.
# Check: input nevens 42 6 7 9 33 = output 2
function nevens {
local sum=0
for element in $@
do
let evencheck=$(( $# % 2 ))
if [[ $evencheck -eq 0 ]]
then
let sum=$sum+1
fi
done
echo $sum
}
Vous avez simplement oublié de remplacer $#
par ($
) element
dans la boucle for
:
function nevens {
local sum=0
for element in $@; do
let evencheck=$(( element % 2 ))
if [[ $evencheck -eq 0 ]]; then
let sum=sum+1
fi
done
echo $sum
}
Maintenant pour tester la fonction:
$ nevens 42 6 7 9 33
2
$ nevens 42 6 7 9 33 22
3
$ nevens {1..10..2} # 1 to 10 step 2 → odd numbers only
0
$ nevens {2..10..2} # 2 to 10 step 2 → five even numbers
5
@ dessert a trouvé le problème principal, je vais vous donner un aperçu du code:
/usr/bin/bash
dans Ubuntu. C'est /bin/bash
.Il est bon que vous ayez déclaré sum
local
et évité de polluer l'espace de nom de variable en dehors de la fonction. De plus, vous pouvez déclarer une variable entière à l'aide de l'option -i
:
local -i sum=0
Citez toujours vos variables (et paramètres)! Ce n'est pas nécessaire dans ce script, mais c'est une très bonne habitude à prendre:
for element in "$@"
do
Cela dit, vous pouvez omettre le in "$@"
ici:
for element
do
Lorsque in <something>
n'est pas indiqué, la boucle for
boucle implicitement sur les arguments. Cela peut éviter des erreurs telles que l'oubli des guillemets.
Il n'est pas nécessaire de calculer et de vérifier le résultat. Vous pouvez directement faire le calcul dans le if
:
if (( (element % 2) == 0 ))
then
((sum = sum + 1))
fi
(( ... ))
est le contexte arithmétique . C'est plus utile que [[ ... ]]
pour effectuer des vérifications arithmétiques, et vous pouvez en outre omettre les variables $
avant (ce qui facilite la lecture, à mon humble avis).
Si vous avez déplacé la pièce même vérification dans une fonction distincte, cela pourrait améliorer la lisibilité et la réutilisabilité:
function evencheck
{
return $(( $1 % 2 ))
}
function nevens
{
local -i sum=0
for element
do
# `if` implicitly checks that the returned value/exit status is 0
if evencheck "$element"
then
(( sum++ ))
fi
done
echo "$sum"
}
Je ne sais pas si vous êtes ouvert à d'autres solutions. De plus, je ne sais pas si vous pouvez utiliser des utilitaires externes ou si vous êtes uniquement limité aux commandes internes bash. Si vous pouvez utiliser grep
, par exemple, votre fonction pourrait être beaucoup plus simple:
function nevens {
printf "%s\n" "$@" | grep -c '[02468]$'
}
Cela place chaque entier en entrée sur sa propre ligne, puis utilise grep
pour compter les lignes se terminant par un chiffre pair.
Mise à jour - @PeterCordes a souligné que nous pouvons même le faire sans grep - purement bash, tant que la liste en entrée contient des entiers bien formés (sans point décimal):
function nevens{
evens=( ${@/%*[13579]/} )
echo "${#evens[@]}"
}
Cela fonctionne en créant une liste nommée evens
en filtrant toutes les probabilités, puis en renvoyant la longueur de cette liste.