Pour une affectation, je dois écrire une fonction qui imprime le nombre de nombres pairs lorsqu'il est fourni avec une séquence de nombres.
J'ai utilisé le morceau de code que j'ai 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 est maintenant que ma fonction continue d'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
}
Réponses:
Vous avez juste oublié de remplacer
$#
par ($
)element
dans lafor
boucle:Maintenant, pour tester la fonction:
la source
@dessert a trouvé le problème principal, je vais donner une révision du code:
/usr/bin/bash
en a pas dans Ubuntu. Ça l'est/bin/bash
.C'est bien que vous ayez déclaré
sum
local
et évité de polluer l'espace de noms de variable en dehors de la fonction. De plus, vous pouvez le déclarer une variable entière en utilisant l'-i
option: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:
Cela dit, vous pouvez omettre
in "$@"
ici:Quand
in <something>
n'est pas donné, lafor
boucle boucle implicitement sur les arguments. Cela peut éviter des erreurs comme oublier les devis.Il n'est pas nécessaire de calculer puis de vérifier le résultat. Vous pouvez directement faire le calcul dans
if
:(( ... ))
est le contexte arithmétique . C'est plus utile que[[ ... ]]
pour effectuer des vérifications arithmétiques, et en outre, vous pouvez omettre les$
variables avant (ce qui le rend plus facile à lire, à mon humble avis).Si vous avez déplacé la partie de vérification uniforme dans une fonction distincte, cela pourrait améliorer la lisibilité et la réutilisabilité:
la source
sum=$((sum + 1 - element % 2))
.&1
pour vérifier le bit faible si cela vous semble plus lisible). Mais nous pouvons le rendre plus lisible:sum=$((sum + !(element&1) ))
utiliser un inverse booléen au lieu de+1 - condition
. Ou tout simplement compter les éléments impairs avec((odd += element&1))
, et à la fin imprimer avececho $(($# - element))
, parce queeven = total - odd
.local -i
etsum++
.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 builds bash. Si vous pouvez utiliser
grep
, par exemple, votre fonction pourrait être beaucoup plus simple:Cela place chaque entier d'entrée sur sa propre ligne, puis utilise
grep
pour compter les lignes qui se terminent par un chiffre pair.Mise à jour - @PeterCordes a souligné que nous pouvons même le faire sans grep - juste du bash pur, tant que la liste d'entrée ne contient que des entiers bien formés (sans virgule décimale):
Cela fonctionne en créant une liste appelée
evens
en filtrant toutes les chances, puis en renvoyant la longueur de cette liste.la source
3.0
comme un nombre pair; la question n'était pas précise sur la forme que prendraient les chiffres.${/%/}
du@
tableau pour exiger une correspondance à la fin de la chaîne, à l'intérieur d'un initialiseur de tableau. Imprimez le décompte. En tant que one-liner pour définir et exécuter:foo(){ evens=( ${@/%*[13579]/} ); echo "${#evens[@]} even numbers"; printf "%s\n" "${evens[@]}"; }; foo 135 212 325 3 6 3 4 5 9 7 2 12310
. Inclut l'impression de la liste pour le débogage. Impressions5 even numbers 212 6 4 2 12310
(sur lignes séparées)grep
c'était en fait plus rapide quebash
. Hmm, je me demande s'il y a une question de codegolf où je pourrais poster cette fonction bash: P