এমনকি সংখ্যার গণনা করতে শেল ফাংশনে ভুল


12

একটি অ্যাসাইনমেন্টের জন্য আমাকে একটি ফাংশন লিখতে হবে যা সংখ্যার ক্রম সহ সরবরাহ করা হয় এমনকি সংখ্যার সংখ্যা প্রিন্ট করে।

আমি আগের অ্যাসাইনমেন্টের জন্য কোডের টুকরোটি ব্যবহার করেছি ( 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
}

2
আপনার শেবাঙে লিখুন '#! / usr / bin / bash -x' তারপরে আপনি দেখতে পাবেন ঠিক কী ঘটে।
জিয়াজিস

এটি আমাদের হোম ওয়ার্ক বলার জন্য +1 - এবং এটির জন্য যথেষ্ট প্রযোজনীয় সাহায্যের জন্য।
জো

উত্তর:


20

আপনি শুধু প্রতিস্থাপন করতে ভুলে গেছি $#সঙ্গে ( $) elementমধ্যে 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
}

এখন ফাংশনটি পরীক্ষা করতে:

$ 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

17

@ ডিজিটর মূল সমস্যাটি খুঁজে পেয়েছে, আমি কিছু কোড পর্যালোচনা দেব:

  1. শেবাং: /usr/bin/bashউবুন্টুতে নেই। এটা /bin/bash
  2. এটি ভাল যে আপনি ঘোষণা করেছেন sum localএবং ফাংশনের বাইরে ভেরিয়েবল নেমস্পেসকে দূষিত করা এড়ানো। অতিরিক্ত হিসাবে, আপনি -iবিকল্পটি ব্যবহার করে এটি একটি পূর্ণসংখ্যার ভেরিয়েবল ঘোষণা করতে পারেন :

    local -i sum=0
  3. সর্বদা আপনার ভেরিয়েবলগুলি (এবং পরামিতি) উদ্ধৃত করুন! এটি এই স্ক্রিপ্টে প্রয়োজনীয় নয়, তবে প্রবেশ করার একটি খুব ভাল অভ্যাস:

    for element in "$@"
    do

    এটি বলেছিল, আপনি in "$@"এখানে বাদ দিতে পারেন :

    for element
    do

    যখন in <something>দেওয়া হয় না, forলুপটি সুস্পষ্টভাবে আর্গুমেন্টের উপর লুপ করে। এটি উদ্ধৃতিগুলি ভুলে যাওয়ার মতো ভুল এড়াতে পারে।

  4. গণনা করার দরকার নেই এবং তারপরে ফলাফলটি চেক করুন। আপনি সরাসরি হিসাবটি এতে করতে পারেন if:

    if (( (element % 2) == 0 ))
    then
        ((sum = sum + 1))
    fi

    (( ... ))হয় গাণিতিক প্রসঙ্গ[[ ... ]]গাণিতিক চেক সম্পাদন করার চেয়ে এটি আরও কার্যকর এবং এর সাথে আপনি $ভেরিয়েবলগুলি আগে বাদ দিতে পারেন (যা পড়া সহজ করে তোলে, আইএমএইচও)।

  5. আপনি যদি সম-পরীক্ষার অংশটিকে একটি পৃথক ফাংশনে স্থানান্তরিত করেন তবে এটি পঠনযোগ্যতা এবং পুনঃব্যবহারযোগ্যতা উন্নতি করতে পারে:

    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"
    }

1
আপনি যদি টিয়ার লুপের বডি ব্যবহারের সন্ধান করেন sum=$((sum + 1 - element % 2))
ডেভিড ফোরস্টার

1
@ ডেভিডফোরস্টার টিসার এবং কম পাঠযোগ্য। ;-)
কনরাড রুডল্ফ

@ ডেভিডফোরস্টার: আমার একই ধারণা ছিল যে আপনার কেবলমাত্র Mod-2 ফলাফলটি সরাসরি ব্যবহার করা উচিত। (বা আরও ভাল, &1যদি এটি আপনার কাছে আরও পাঠযোগ্য হয় তবে কম বিটটি পরীক্ষা করুন)। তবে আমরা এটিকে আরও পঠনযোগ্য করে তুলতে পারি: এর sum=$((sum + !(element&1) ))পরিবর্তে বুলিয়ান বিপরীত ব্যবহার করতে +1 - condition। বা কেবল সাথে বিজোড় উপাদানগুলি গণনা করুন ((odd += element&1)), এবং শেষে মুদ্রণ সহ echo $(($# - element)), কারণ even = total - odd
পিটার কর্ডস

ভাল কাজ, এবং ছোট বিষয়গুলি সূচিত করা ভাল যা প্রাথমিকভাবে মিস হয়, যেমন local -iএবং sum++
ধানের ল্যান্ডাউ

4

আপনি অন্যান্য সমাধানের জন্য উন্মুক্ত কিনা তা আমি নিশ্চিত নই। আপনি বাহ্যিক ইউটিলিটিগুলি ব্যবহার করতে পারেন বা আপনি যদি পুরোপুরি ব্যাশ বিল্টিনের মধ্যে সীমাবদ্ধ থাকেন তবে আমি জানি না। আপনি যদি ব্যবহার করতে পারেন grep, উদাহরণস্বরূপ, আপনার ফাংশনটি সম্পূর্ণ সহজ হতে পারে:

function nevens {
    printf "%s\n" "$@" | grep -c '[02468]$'
}

এটি প্রতিটি ইনপুট পূর্ণাঙ্গকে তার নিজস্ব লাইনে রাখে এবং তারপরে grepলাইনগুলি একটি সংখ্যায় শেষ হওয়া গণনা করে।


আপডেট - @ পিটারকর্ডস উল্লেখ করেছেন যে আমরা গ্রেপ ছাড়াই এটিও করতে পারি - কেবল খাঁটি বাশ, যতক্ষণ ইনপুট তালিকায় সবেমাত্র সুগঠিত পূর্ণসংখ্যা থাকে (কোনও দশমিক বিন্দু ছাড়াই):

function nevens{
    evens=( ${@/%*[13579]/} )
    echo "${#evens[@]}"
}

এটি evensসমস্ত প্রতিকূলতাকে ফিল্টার করে একটি তালিকা তৈরি করে কাজ করে , তারপরে সেই তালিকাটির দৈর্ঘ্য ফিরিয়ে দেয়।


আকর্ষণীয় পদ্ধতির। অবশ্যই এটি 3.0একটি সমান সংখ্যা হিসাবে গণনা করা হবে ; সংখ্যাটি কী রূপ নেবে সে সম্পর্কে প্রশ্নটি সুনির্দিষ্ট ছিল না।
জি-ম্যান 0:

@ জি-ম্যান যেহেতু বাশ ফ্লোটিং পয়েন্ট পাটিগণিত সমর্থন করে না, তাই পূর্ণসংখ্যা ধরে নেওয়া নিরাপদ
মুরু

যেহেতু প্রশ্নটিতে "এমনকি" (এবং, স্পষ্টতই, "বিজোড়") সংখ্যার উল্লেখ করা হয়েছে, এটি ধারণা করা কিছুটা নিরাপদ যে এটি পূর্ণসংখ্যা সম্পর্কে কথা বলছে। আমি যে সরঞ্জামটি ব্যবহারকারীর দ্বারা প্রত্যাশা করা হচ্ছে তার ক্ষমতা এবং সীমাবদ্ধতা থেকে প্রশ্ন সম্পর্কে সিদ্ধান্তে পৌঁছানোর বৈধতা আমি দেখতে পাচ্ছি না। মনে রাখবেন: প্রশ্নটি বলছে এটি একটি নিয়োগ - আমি স্কুলের জন্য অনুমান করি, কারণ এটি কোনও চাকরি থেকে আসা খুব তুচ্ছ। স্কুল শিক্ষকরা কিছু উন্মত্ত জিনিস নিয়ে আসে।
জি-ম্যান

2
বাশ তার নিজস্ব একটি তালিকা ফিল্টার করতে পারে যদি আমরা অনুমান করতে পারি যে কোনও উপাদান শ্বেত স্পেস রয়েছে না: অ্যারে আরম্ভকারীর ভিতরে স্ট্রিংয়ের শেষে একটি ম্যাচ প্রয়োজন ${/%/}হলে @অ্যারে ব্যবহার করে ফাঁকা স্ট্রিংয়ের সাথে বিজোড় সংখ্যার সাহায্যে আরগের তালিকাটি প্রসারিত করুন । গণনা মুদ্রণ করুন। : একটি এক-লাইনের সংজ্ঞায়িত এটি চালানোর জন্য হিসাবে 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(সেপ্টেম্বর লাইনে)
পিটার কর্ডস

1
সম্ভবত জেডএসএইচের একটি নতুন অ্যারে পুনর্নির্মাণের জন্য শব্দ বিভাজনের উপর নির্ভর করে কোনও তালিকা সঠিকভাবে ফিল্টার করার জন্য কিছু রয়েছে (আমি কিছুটা অবাক হয়েছিলাম বাশটি হয়নি; কেবল প্রতিটি উপাদানগুলিতে স্কেলার স্ট্রিং সম্প্রসারণ স্টাফ প্রয়োগ করে)। বড় তালিকার জন্য, আমি যদি সত্যিই grepতার চেয়ে দ্রুত হত তবে আমি অবাক হব না bash। হুম, আমি অবাক হয়েছি যদি সেখানে কোনও কোডগল্ফের প্রশ্ন থাকে যেখানে আমি সেই বাশ ফাংশনটি পোস্ট করতে পারি: পি
পিটার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.