Aby wykonać zadanie, muszę napisać funkcję, która wypisze liczbę parzystą, jeśli otrzyma ciąg liczb.
Użyłem fragmentu kodu, którego użyłem do poprzedniego zadania (aby wydrukować, 1
gdy liczba była parzysta, a 0
kiedy liczba była nieparzysta)
Mój problem polega na tym, że moja funkcja nadal drukuje 0
. Co ja robię źle?
Oto mój skrypt:
#!/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
}
Odpowiedzi:
Właśnie zapomniałeś zamienić na
$#
($
)element
wfor
pętli:Teraz, aby przetestować funkcję:
źródło
@dessert znalazł podstawowy problem, dam przegląd kodu:
/usr/bin/bash
Ubuntu nie ma . Jest/bin/bash
.Dobrze, że zadeklarowałeś
sum
local
i unikałeś zanieczyszczenia przestrzeni nazw zmiennych poza funkcją. Dodatkowo możesz zadeklarować ją jako zmienną całkowitą za pomocą-i
opcji:Zawsze podawaj swoje zmienne (i parametry)! W tym skrypcie nie jest konieczne, ale bardzo dobry nawyk, aby dostać się do:
To powiedziawszy, możesz pominąć
in "$@"
tutaj:Jeśli
in <something>
nie podano,for
pętla domyślnie zapętla się nad argumentami. Pozwala to uniknąć błędów, takich jak zapomnienie cytatów.Nie ma potrzeby obliczania, a następnie sprawdzania wyniku. Możesz bezpośrednio wykonać obliczenia w
if
:(( ... ))
jest kontekstem arytmetycznym . Jest to bardziej przydatne niż[[ ... ]]
do sprawdzania arytmetycznego, a dodatkowo można pominąć$
zmienne przed (co ułatwia odczyt, IMHO).Jeśli część sprawdzającą parzystość została przeniesiona do oddzielnej funkcji, może to poprawić czytelność i możliwość ponownego użycia:
źródło
sum=$((sum + 1 - element % 2))
.&1
aby sprawdzić niski bit, jeśli jest to dla ciebie bardziej czytelne). Ale możemy sprawić, by było bardziej czytelne:sum=$((sum + !(element&1) ))
użyć odwrotnej wartości logicznej zamiast+1 - condition
. Lub po prostu policz nieparzyste elementy za pomocą((odd += element&1))
, a na końcu wydrukuj za pomocąecho $(($# - element))
, ponieważeven = total - odd
.local -i
asum++
.Nie jestem pewien, czy jesteś otwarty na inne rozwiązania. Nie wiem też, czy możesz korzystać z zewnętrznych narzędzi, czy też jesteś ograniczony do wbudowanych bashów. Jeśli możesz
grep
na przykład użyć , twoja funkcja może być o wiele prostsza:To umieszcza każdą liczbę całkowitą na swojej linii, a następnie używa
grep
do zliczania linii kończących się parzystą cyfrą.Aktualizacja - @PeterCordes wskazało, że możemy to zrobić nawet bez grep - tylko czysty bash, o ile lista wejściowa zawiera tylko dobrze uformowane liczby całkowite (bez kropek dziesiętnych):
Działa to poprzez utworzenie listy wywoływanej
evens
przez odfiltrowanie wszystkich szans, a następnie zwrócenie długości tej listy.źródło
3.0
jako liczba parzysta; pytanie nie było precyzyjne, jaką formę przyjmą liczby.${/%/}
w@
tablicy wymagającej dopasowania na końcu łańcucha, wewnątrz inicjatora tablicy. Wydrukuj liczbę. Jako jedną wkładką do zdefiniowania i uruchomić go:foo(){ evens=( ${@/%*[13579]/} ); echo "${#evens[@]} even numbers"; printf "%s\n" "${evens[@]}"; }; foo 135 212 325 3 6 3 4 5 9 7 2 12310
. Obejmuje faktycznie wydrukowanie listy do debugowania. Odciski5 even numbers 212 6 4 2 12310
(na osobnych liniach)grep
faktycznie był szybszy niżbash
. Hmm, zastanawiam się, czy istnieje pytanie o kodegolfa, w którym mógłbym opublikować tę funkcję bash: P