Для назначения я должен написать функцию, которая печатает количество четных чисел, когда предоставляется последовательность чисел.
Я использовал фрагмент кода, который использовал для предыдущего назначения (для печати, 1
когда число было четным, а 0
когда число было нечетным)
Моя проблема сейчас в том, что моя функция продолжает печатать 0
. Что я делаю неправильно?
Вот мой сценарий:
#!/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
}
Ответы:
Вы просто забыли заменить
$#
на ($
)element
вfor
цикле:Теперь для проверки функции:
источник
@dessert обнаружил основную проблему, я дам небольшой обзор кода:
/usr/bin/bash
в Ubuntu. Это/bin/bash
.Хорошо, что вы объявили
sum
local
, и избежали загрязнения пространства имен переменной вне функции. Кроме того, вы можете объявить его целочисленной переменной, используя-i
опцию:Всегда указывайте свои переменные (и параметры)! В этом сценарии нет необходимости, но есть очень хорошая привычка:
Тем не менее, вы можете опустить
in "$@"
здесь:Когда
in <something>
не задано,for
цикл неявно зацикливается на аргументах. Это может избежать ошибок, таких как забывание цитат.Там нет необходимости рассчитывать, а затем проверить результат. Вы можете напрямую сделать расчет в
if
:(( ... ))
это арифметический контекст . Это более полезно, чем[[ ... ]]
для выполнения арифметических проверок, и, кроме того, вы можете опустить$
переменные before (что упрощает чтение, IMHO).Если вы переместили четную часть в отдельную функцию, это может улучшить читаемость и возможность повторного использования:
источник
sum=$((sum + 1 - element % 2))
.&1
проверить младший бит, если он более читабелен для вас). Но мы можем сделать его более читабельным:sum=$((sum + !(element&1) ))
использовать вместо логического обратное выражение+1 - condition
. Или просто посчитайте нечетные элементы с помощью((odd += element&1))
, а в конце напечатайтеecho $(($# - element))
, потому чтоeven = total - odd
.local -i
иsum++
.Я не уверен, что вы открыты для других решений. Также я не знаю, можете ли вы использовать внешние утилиты или вы просто ограничены встроенными средствами bash. Если вы можете использовать
grep
, например, ваша функция может быть намного проще:Это помещает каждое входное целое число в свою собственную строку, а затем использует
grep
для подсчета строк, заканчивающихся четной цифрой.Обновление - @PeterCordes указало, что мы можем даже сделать это без grep - просто чистый bash, при условии, что входной список содержит только правильно сформированные целые числа (без десятичных точек):
Это работает путем создания списка, который вызывается
evens
путем фильтрации всех коэффициентов, а затем возвращается длина этого списка.источник
3.0
четным числом; вопрос не был точным о том, какую форму примут числа.${/%/}
на@
массиве требуется соответствие в конце строки, внутри инициализатора массива. Распечатать счет. Как однострочник определить и запустить его:foo(){ evens=( ${@/%*[13579]/} ); echo "${#evens[@]} even numbers"; printf "%s\n" "${evens[@]}"; }; foo 135 212 325 3 6 3 4 5 9 7 2 12310
. Включает в себя фактически печать списка для отладки. Отпечатки5 even numbers 212 6 4 2 12310
(на отдельных строках)grep
самом деле был быстрее, чемbash
. Хм, интересно, есть ли вопрос Codegolf, где я мог бы опубликовать эту функцию bash: P