(0) যদি কাজ করার মতো একটি স্যুইচ কেস ছেড়ে যায় তবে কি ব্যবহার করছে?


108

আমার এমন একটি পরিস্থিতি রয়েছে যেখানে আমি সি ++ স্যুইচ বিবৃতিতে দুটি ক্ষেত্রেই তৃতীয় কেস হতে পারি। বিশেষত, দ্বিতীয় কেসটি তৃতীয় কেসের মধ্যে পড়বে, এবং প্রথম কেসটিও দ্বিতীয় মামলার মধ্য দিয়ে না গিয়েই তৃতীয় মামলায় পড়ে যাবে ।

আমি একটি বোবা ধারণা ছিল, এটি চেষ্টা, এবং এটি কার্যকর! আমি একজন দ্বিতীয় ক্ষেত্রে আবৃত if (0) {... }। দেখে মনে হচ্ছে:

#ifdef __cplusplus
#  include <cstdio>
#else
#  include <stdio.h>
#endif

int main(void) {
    for (int i = 0; i < 3; i++) {
        printf("%d: ", i);
        switch (i) {
        case 0:
            putchar('a');
            // @fallthrough@
            if (0) {        // fall past all of case 1 (!)
        case 1:
            putchar('b');
            // @fallthrough@
            }
        case 2:
            putchar('c');
            break;
        }
        putchar('\n');
    }
    return 0;
}

আমি যখন এটি চালনা করি, তখন আমি পছন্দসই আউটপুট পাই:

0: ac
1: bc
2: c

আমি এটি সি এবং সি উভয় ক্ষেত্রেই চেষ্টা করেছি (ঝনঝন দিয়ে উভয়) এবং এটি একই কাজ করেছিল।

আমার প্রশ্নগুলি: এটি কি বৈধ সি / সি ++? এটা কি এটা করার কথা?


33
হ্যাঁ, এটি বৈধ এবং ডাফের ডিভাইসটি কেন একই কারণেই কাজ করে।
dxiv

41
মনে রাখবেন যে এর মতো কোড আপনাকে এমন একটি পরিবেশে যে কোনও কোড ওয়াকথ্রো থেকে সরিয়ে ফেলবে যা পাঠযোগ্যতা এবং রক্ষণাবেক্ষণের সামান্য কিছুটা যত্নশীল।
অ্যান্ড্রু হেনেল

15
এটা ভয়াবহ। ডাফের ডিভাইসের চেয়েও ভয়ঙ্কর, মনে রাখবেন। সম্পর্কিত, আমি সম্প্রতি কিছু দেখেছি switch(x) { case A: case B: do_this(); if(x == B) also_do_that(); ... }। আইএমওও ছিল ভয়াবহ। দয়া করে, কেবল স্টেটগুলি লিখুন যেমন বিবৃতিগুলি, এমনকি এর অর্থ আপনাকে দুটি স্থানে একটি লাইন পুনরাবৃত্তি করতে হবে। দুর্ঘটনাক্রমে কেবলমাত্র এক জায়গায় আপডেট হওয়ার ঝুঁকি কমাতে ফাংশন এবং ভেরিয়েবল (এবং ডকুমেন্টেশন!) ব্যবহার করুন।
ইলকচাচু

46
:-) এই কোডটি দেখার কারণে যারা আহত বা বিকলাঙ্গ হয়েছিলেন তাদের জন্য আমি এটি ভাল ধারণা বলে নি good আসলে, আমি বলেছিলাম এটি বোবা ধারণা।
মার্ক অ্যাডলার

4
নোট করুন যে এই জাতীয় সুইচের অভ্যন্তর
নির্মাণগুলি

উত্তর:


53

হ্যাঁ, এটি অনুমোদিত, এবং এটি আপনি যা চান তা করে। একটি switchবিবৃতি হিসাবে, সি ++ স্ট্যান্ডার্ড বলেছেন :

কেস এবং ডিফল্ট লেবেলগুলি নিজেরাই নিয়ন্ত্রণের প্রবাহকে পরিবর্তন করে না, যা এই ধরনের লেবেলগুলিতে অবিরাম অবিরত থাকে। একটি স্যুইচ থেকে প্রস্থান করতে, বিরতি দেখুন।

[দ্রষ্টব্য 1: সাধারণত, সাবস্টেটমেন্টটি যা একটি স্যুইচের বিষয়বস্তু হয় যৌগিক এবং কেস এবং ডিফল্ট লেবেলগুলি (যৌগিক) সাবস্টেটমেন্টের মধ্যে থাকা শীর্ষ স্তরের বিবৃতিতে উপস্থিত হয়, তবে এটি প্রয়োজন হয় না। ঘোষণাগুলি একটি স্যুইচ স্টেটমেন্টের সাবস্টেটমেন্টে উপস্থিত হতে পারে। - শেষ নোট]

সুতরাং যখন ifবিবৃতিটি মূল্যায়ন করা হয়, তখন ifকেস লেবেলকে হস্তক্ষেপ না করে নিয়ন্ত্রণ প্রবাহ বিবৃতিটির নিয়ম অনুসারে এগিয়ে যায় ।


13
এর একটি নির্দিষ্ট কেস হিসাবে, কেউ বুট.কর্োটাইনগুলিতে পেট-মন্থন ম্যাক্রোগুলির একটি সেটের জন্য দেখতে পারেন যা এই নিয়মের (এবং সি ++ এর অর্ধ ডজন অন্যান্য কর্নার কেস) সি ++ 03 বিধি ব্যবহার করে কর্টিনগুলি প্রয়োগ করতে সহায়তা করে। সি ++ ২০ না হওয়া পর্যন্ত এগুলিকে ভাষার অংশ করা হয়নি, তবে এই ম্যাক্রোগুলি তাদেরকে কাজ করে ... যতক্ষণ আপনি নিজের অ্যান্টাসিডকে প্রথমে নিয়েছেন!
আম্মোনকে

56

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

যা বলেছিল, বাস্তবে এটি সম্ভবত একটি গোটো স্টেটমেন্ট দিয়ে এটি লেখার পক্ষে আরও পরিষ্কার হয়েছে:

    switch (i) {
    case 0:
        putchar('a');
        goto case2;
    case 1:
        putchar('b');
        // @fallthrough@
    case2:
    case 2:
        putchar('c');
        break;
    }

4
"যখন কোনও ব্লকের মাঝখানে ঝাঁপ দেওয়ার সময় গোয়োটার সাথে একই গুপ্তচরগুলি ভেরিয়েবলগুলির সূচনাকরণের উপর ঝাঁপ দেওয়ার বিষয়ে প্রয়োগ করে" ইত্যাদি কী সাবধানতা থাকবে? আপনি ভেরিয়েবলের সূচনাতে লাফিয়ে উঠতে পারবেন না
উইংস উইথ উইন্ডোজ

4
@ অ্যাসটারয়েডস উইথ উইংস, আপনার মানে কী কোনও মান-মানিয়ে যাওয়া দৃষ্টিকোণ থেকে, বা কোনও সংকলক এটির অনুমতি দেবে না এমন ধরনের ব্যবহারিক দৃষ্টিকোণ থেকে? কারণ আমার জিসিসি একটি সতর্কতা সহ এটি সি মোডে অনুমতি দেয়। এটি যদিও এটি সি ++ মোডে অনুমতি দেয় না।
ইলকচাচু

4
@ কোয়েটজলক্যাটল জিসিসি -9 এবং ক্ল্যাং -6 উভয়ই এই কোডটিকে অনুমতি দেয়, সম্ভাব্য অবিচ্ছিন্নকরণ সম্পর্কে সতর্ক করে bee(সি মোডে; সি ++ এ তারা ত্রুটিযুক্ত "" এই কেস লেবেলে স্যুইচ স্টেটমেন্ট থেকে লাফ দিতে পারে না / জাম্প পরিবর্তনশীল আরম্ভকে বাইপাস করে ")।
রুসলান

7
আপনি জানেন যে আপনি যখন কিছু ভুল করছেন তখন gotoক্লিনার সলিউশন।
কনরাড রুডলফ

9
@ কনরাডরুডল্ফ: gotoঅনেকটা ম্যালিড হয়েছে তবে আপনি যদি নিজে নিজে থেকে জটিল নিয়ন্ত্রণ কাঠামো তৈরি না করে থাকেন তবে এ সম্পর্কে আসলে আপত্তিজনক কিছু নেই। পুরো "ক্ষতিকারক হিসাবে বিবেচিত" এটি এইচএলএল (উদাঃ সি) কোডটি লেখার বিষয়ে ছিল যা দেখে মনে হয় একটি সংকলক দ্বারা নির্গত asm (পুরো জায়গা জুড়ে jmps)। গোটোর প্রচুর ভাল কাঠামোগত ব্যবহার রয়েছে যেমন- কেবলমাত্র ফরওয়ার্ড (ধারণার চেয়ে আলাদা breakবা শুরুর চেয়ে আলাদা নয় return), অসম্ভব-পুনরায় চেষ্টা-লুপ কেবল (সাধারণ প্রবাহের পথকে অস্পষ্ট করে এড়িয়ে যায় এবং নেস্টেড- এর অভাবে ক্ষতিপূরণ দেয় continue) ইত্যাদি ইত্যাদি
আর .. গিটিহাব থামান হেল্পিং আইসিসি

28

অন্যান্য উত্তর যেমন উল্লেখ করেছে, এটি প্রযুক্তিগতভাবে মান দ্বারা অনুমোদিত, তবে কোডের ভবিষ্যতের পাঠকদের কাছে এটি খুব বিভ্রান্তিকর এবং অস্পষ্ট।

এ কারণেই switch ... caseস্টেটমেন্টগুলি সাধারণত ফাংশন কলগুলি দিয়ে লেখা উচিত এবং প্রচুর ইনলাইন কোডের সাথে নয়।

switch(i) {
case 0:
    do_zero_case(); do_general_stuff(); break;
case 1:
    do_one_case(); do_general_stuff(); break;
case 2:
    do_general_stuff(); break;
default:
    do_default_not_zero_not_one_not_general_stuff(); break;
}

মনে রাখবেন যে প্রশ্নের কোডটি do_general_stuffডিফল্টর জন্য নয় , কেবল কেস 2 (এবং 0 এবং 1) এর জন্য। iযদিও এটি 0..2 সীমার বাইরে কখনও স্যুইচ চালায় না ।
পিটার কর্ডস

@ পিটারকর্ডস - নোট করুন যে উত্তরে কোডটি do_general_stuffডিফল্ট জন্য নয় , কেবল কেস 2 (এবং 0 এবং 1) এর জন্য।
পিট বেকার

একটি পরামর্শ - সম্ভবত ডিফল্ট কেসটি মুছে ফেলা বা নাম বদলানো উচিত? বিভিন্ন ফাংশনটির নাম মিস করা বেশ সহজ।
I.Am.A.Guy

@ পেটবেকার: ওহ, আইডিকে কীভাবে আমি এটি মিস করেছি generalএবং defaultবিভিন্ন শব্দ ছিল। ওও, এটি একটি পরিচিত সত্য যে মাঝারি অক্ষরগুলি স্ক্র্যাম্বল করা থাকলে মানুষ সাধারণত একটি শব্দ পড়তে পারে; আমরা শুরু এবং শেষের দিকে নজর রাখি, সুতরাং কেবল মধ্যমটি আলাদা হওয়া সম্ভবত স্কিমেবিলিটির জন্য আদর্শ নয়। সম্ভবত do_উপসর্গটি মুছে ফেলুন ।
পিটার কর্ডেস

4
@ সুপের্যাট: এটি "সুপরিচিত তথ্য" বিভিন্ন অক্ষর দ্বারা মধ্যবর্তী অক্ষরগুলি প্রতিস্থাপনের বিষয়ে নয়, কেবল তখনকার ক্রমকে মেশানো সম্পর্কে। "যদি সিআইএনএম গ্রানিয়েলে সত্যি থাকে তবে আপনি রেহিত তিহসকে স্লুহড করুন" "
মাইকেল কারচার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.