Für eine Aufgabe muss ich eine Funktion schreiben, die die Anzahl der geraden Zahlen druckt, wenn sie mit einer Folge von Zahlen versehen ist.
Ich habe den Code verwendet, den ich für eine vorherige Aufgabe verwendet habe (um zu drucken, 1
wann eine Zahl gerade und 0
wann die Zahl ungerade war)
Mein Problem ist jetzt, dass meine Funktion weiter druckt 0
. Was mache ich falsch?
Hier ist mein Drehbuch:
#!/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
}
Antworten:
Sie haben nur vergessen, in der Schleife durch
$#
($
) zu ersetzen :element
for
Testen Sie nun die Funktion:
quelle
@dessert hat das Kernproblem gefunden, ich gebe eine Codeüberprüfung :
/usr/bin/bash
In Ubuntu gibt es keine . Es ist/bin/bash
.Es ist gut, dass Sie
sum
local
den Variablennamensraum außerhalb der Funktion deklariert und nicht verschmutzt haben. Darüber hinaus können Sie es mit der folgenden-i
Option als Ganzzahlvariable deklarieren :Zitieren Sie immer Ihre Variablen (und Parameter)! In diesem Skript ist es nicht erforderlich, aber es ist eine sehr gute Angewohnheit, sich darauf einzulassen:
Das heißt, Sie können das
in "$@"
hier weglassen :Wenn dies
in <something>
nicht angegeben ist,for
durchläuft die Schleife implizit die Argumente. Dies kann Fehler wie das Vergessen der Anführungszeichen vermeiden.Es ist nicht erforderlich, das Ergebnis zu berechnen und anschließend zu überprüfen. Sie können die Berechnung direkt in den folgenden Schritten durchführen
if
:(( ... ))
ist der arithmetische Kontext . Dies ist nützlicher als die[[ ... ]]
Durchführung von arithmetischen Prüfungen. Außerdem können Sie die$
Vor-Variablen weglassen (was das Lesen erleichtert, IMHO).Wenn Sie den Teil mit der geraden Prüfung in eine separate Funktion verschoben haben, kann dies die Lesbarkeit und Wiederverwendbarkeit verbessern:
quelle
sum=$((sum + 1 - element % 2))
.&1
um das niedrige Bit zu überprüfen, ob es für Sie besser lesbar ist). Aber wir können es lesbarer machen:sum=$((sum + !(element&1) ))
Verwenden Sie stattdessen eine Boolesche Inverse+1 - condition
. Oder zählen Sie einfach die ungeraden Elemente mit((odd += element&1))
und drucken Sie am Ende mitecho $(($# - element))
, weileven = total - odd
.local -i
undsum++
.Ich bin mir nicht sicher, ob Sie für andere Lösungen offen sind. Ich weiß auch nicht, ob Sie externe Dienstprogramme verwenden können oder ob Sie sich nur auf Bash-Builtins beschränken. Wenn Sie
grep
zum Beispiel verwenden können, könnte Ihre Funktion viel einfacher sein:Dadurch wird jede Eingabe-Ganzzahl in eine eigene Zeile gesetzt und anschließend
grep
die Zeilen gezählt, die mit einer geraden Ziffer enden.Update - @PeterCordes wies darauf hin, dass wir dies sogar ohne grep tun können - nur reine Bash, solange die Eingabeliste nur gut geformte Ganzzahlen enthält (ohne Dezimalstellen):
Dies funktioniert, indem Sie eine Liste erstellen, die aufgerufen wird,
evens
indem Sie alle Quoten herausfiltern und dann die Länge dieser Liste zurückgeben.quelle
3.0
als gerade Zahl; Die Frage war nicht genau, wie die Zahlen aussehen würden.${/%/}
im@
Array eine Übereinstimmung am Ende der Zeichenfolge innerhalb eines Array-Initialisierers angeben. Zählung drucken. Als One-liner , sie zu definieren und auszuführen:foo(){ evens=( ${@/%*[13579]/} ); echo "${#evens[@]} even numbers"; printf "%s\n" "${evens[@]}"; }; foo 135 212 325 3 6 3 4 5 9 7 2 12310
. Beinhaltet das tatsächliche Drucken der Liste zum Debuggen. Abzüge5 even numbers 212 6 4 2 12310
(in sep. Zeilen)grep
tatsächlich schneller wäre alsbash
. Hmm, ich frage mich, ob es eine Codegolf-Frage gibt, wo ich diese Bash-Funktion posten könnte: P