2010-03-17 19 views
29

मेरे सी ++ एप्लिकेशन में, मेरे पास कुछ मान हैं जो अन्य मानों का प्रतिनिधित्व करने के लिए कोड के रूप में कार्य करते हैं। कोड का अनुवाद करने के लिए, मैं एक स्विच स्टेटमेंट या एक एसएलएल मानचित्र का उपयोग करने के बीच बहस कर रहा हूं।सी ++ लांग स्विच स्टेटमेंट या मानचित्र के साथ देखो?

int code; 
int value; 
switch(code) 
{ 
case 1: 
    value = 10; 
    break; 
case 2: 
    value = 15; 
    break; 
} 

नक्शा एक stl::map<int, int> होगा और अनुवाद कुंजी मान के रूप में इस्तेमाल कोड के साथ एक सरल देखने होगा: स्विच यह कुछ ऐसा दिखाई देगा।

कौन सा बेहतर/अधिक कुशल/क्लीनर/स्वीकार्य है? क्यूं कर?

+1

'मूल्य = 5 * (कोड + 1);' – kennytm

+5

@ केनीटीएम - उत्कृष्ट। सिवाय इसके कि वास्तविक मूल्य नहीं हैं ... – Rachel

+0

+1 एक दिलचस्प प्रश्न के लिए। –

उत्तर

7

व्यक्तिगत रूप से, मैं मानचित्र का उपयोग करता हूं, क्योंकि इसका उपयोग डेटा लुकअप का तात्पर्य है - एक स्विच का उपयोग आमतौर पर प्रोग्राम व्यवहार में अंतर दर्शाता है। इसके अलावा एक मानचित्र के साथ डेटा मैपिंग को संशोधित करना एक स्विच के मुकाबले आसान है।

यदि प्रदर्शन एक वास्तविक मुद्दा है, तो प्रोफाइलिंग एक उपयोगी उत्तर प्राप्त करने का एकमात्र तरीका है। यदि शाखा गलतफहमी अक्सर पर्याप्त होती है तो एक स्विच तेज नहीं हो सकता है।

एक और दृष्टिकोण को इस बारे में सोचने के लिए अगर यह एक आंकड़ा संरचना में कोड और संबद्ध मूल्य गठबंधन करने के लिए और अधिक मतलब नहीं होगा है, खासकर यदि कोड और मानों की श्रेणी स्थिर है:

struct Code { int code; int value; }; 

Code c = ... 

std::cout << "Code " << c.code << ", value " << c.value << std::end; 
+0

मुझे उस बिंदु को पसंद है जो आपने डेटा लुकअप और स्विचेस को इंगित करने वाले मानचित्रों के बारे में बताया है व्यवहार। – Rachel

0

मैं नक्शा कहता हूं कि यदि आप जो कुछ कर रहे हैं वह एक मूल्य असाइन कर रहा है। मेरा कारण यह है कि कोड बदलने के बिना यह एक्स्टेंसिबल है, जो आपका स्विच स्टेटमेंट नहीं है।

बीटीडब्ल्यू, enum के बारे में कैसे?

+0

इनट्स को इनट्स में अनुवाद करने के लिए एक enum नहीं कर सकता। – Rachel

7

अपने कोड पर्याप्त सन्निहित हैं और अपनी सीमा परमिट आप पुराने ढंग का सीधा सरणी के साथ की ज्यादा बेहतर होगा, जैसे

int lookup[] = {-1, 10, 15, -1 222}; 

तो स्विच बयान बस के रूप में

के रूप में लिखा जा सकता है कुछ तो मूल्य = लुकअप [कोड];

अन्य सभी विकल्प कुछ हद तक अतिरिक्त लागत पेश करते हैं।

+0

वे संगत नहीं हैं। वह समस्या का हिस्सा है। मैं इन्ट्स की यादृच्छिक सूची को इन्ट्स की यादृच्छिक सूची में कुशलतापूर्वक अनुवाद करने की कोशिश कर रहा हूं। – Rachel

+0

+1। इसे कभी-कभी "टेबल" दृष्टिकोण कहा जाता है –

+0

@ राहेल: क्या दोनों यादृच्छिक सूचियां संकलित समय में ज्ञात हैं? यदि हां और असंतुलन बड़ा नहीं है, तो लुकअप टेबल अभी भी एक अच्छा तरीका है। – kennytm

0

मुझे लगता है कि "कोड" की मात्रा बड़ी हो जाने पर स्विच-केस संरचना का जेनरेट कोड काफी बड़ा हो सकता है, इस मामले में मुझे लगता है कि stl :: map अधिक उपयुक्त है।

2

स्विच स्टेटमेंट तेज़ होगा लेकिन यदि यह आपके अनुप्रयोगों में प्रदर्शन की बाधा नहीं है तो आपको वास्तव में इसकी परवाह नहीं करनी चाहिए।

आपके कोड को लंबे समय तक बनाए रखने के लिए आसान बनाता है।

आपका नमूना उस संबंध में कोई सार्थक कॉल करने के लिए बहुत छोटा है।

4

यह बल्कि इस बात पर निर्भर करता है कि कोड क्या हैं और कितने हैं। अच्छे कंपाइलर्स में स्विच कथन को अनुकूलित करने के लिए उपयोग की जाने वाली विभिन्न चालें होती हैं, जिनमें से कुछ सीधे/यदि कथन के साथ काम नहीं करेंगे। अधिकांश उदाहरण के लिए 0, 1, 2 या केस 3, 6, 9 के लिए सरल गणित करने के लिए पर्याप्त उज्ज्वल हैं या लुकअप/जंप टेबल का उपयोग करते हैं।

बेशक कुछ नहीं करते हैं, और कई आसानी से मूल्यों के असामान्य या अनियमित सेटों द्वारा फॉइल किए जाते हैं। इसके अलावा यदि कई मामलों को संभालने के लिए कोड उल्लेखनीय रूप से समान दिखता है, तो कट और पेस्ट रखरखाव के मुद्दों का कारण बन सकता है।आप कई कोड है, लेकिन वे समूहों में एल्गोरिदम रूप से विभाजित किया जा सकता है, तो आप के बजाय उदाहरण के लिए कई/नेस्ट स्विच बयान पर विचार हो सकता,:

switch (code) { 
    case 0x0001: ... 
    case 0x0002: ... 
    ... 
    case 0x8001: ... 
    case 0x8002: ... 
    ... 
} 

आप उपयोग कर सकते हैं:

if (code & 0x8000) { 
    code &= ~0x8000; 
    switch (code) { 
     case 0x0001: ... // actually 0x8001 
     case 0x0002: ... // actually 0x8002 
     ... 
    } 
} 
else { 
    switch (code) { 
     case 0x0001: ... 
     case 0x0002: ... 
     ... 
    } 
} 

कई भाषा अनुवादक को डिकोड इस तरह से opcodes, चूंकि एक बाइट ऑपोड में विभिन्न बिट्स में पैक की गई अतिरिक्त जानकारी हो सकती है, और सभी संभावित संयोजनों को ट्रांसक्रिप्ट करना और उनके हैंडलर दोहराए जाने वाले और नाजुक होंगे। दूसरी तरफ, अत्यधिक बिट मैंगलिंग कंपाइलर द्वारा किसी भी अनुकूलन को हराने और काउंटर-उत्पादक बन सकता है।

जब तक आप सुनिश्चित न हों कि यह एक वास्तविक प्रदर्शन बाधा है, तो मैं समयपूर्व अनुकूलन से बचूंगा: ऐसा करने के लिए जो भी आपको उचित रूप से मजबूत और कार्यान्वित करने के लिए त्वरित रूप से हमला करता है। जैसे ही आपका एप्लिकेशन बहुत धीरे-धीरे चल रहा है, प्रोफाइल करें और तदनुसार अनुकूलित करें।

-1
  • तरह सरणी/वेक्टर अंतर्निहित सरणी
+0

क्यों न केवल std :: map का उपयोग करें? प्रदर्शन गारंटी समान हैं और कोड सरल है। – Peter

+0

छोटी मेमोरी पैर प्रिंट == बेहतर इलाका == बेहतर प्रदर्शन – EvilTeach

2

मैं आंशिक हूँ अपने आप टेबल देखने के लिए पर एक सरणी/वेक्टर में पूर्णांकों पढ़ें

  • उपयोग bsearch, क्योंकि असामान्य रूप से लंबे स्विच बयान मुझे कोड और डेटा के बीच अलगाव को भ्रमित करने के लिए प्रतीत होता है। मुझे यह भी लगता है कि टेबल भविष्य में बदलाव और रखरखाव के लिए खुद को बेहतर उधार देते हैं।

    बेशक सभी IMHO।

  • 1

    यदि आप tr1 का उपयोग कर सकते हैं तो आप मानों को हैश करने के लिए unordered_map का उपयोग कर सकते हैं (हैशिंग इट्स वास्तव में भी तेज़ हो सकता है), जो अधिकांश लुकअप निरंतर समय बनाना चाहिए।

    हालांकि जब तक आपके पास यह इंगित करने के लिए डेटा प्रोफाइल नहीं है कि यह आपके प्रोग्राम में एक बाधा है, तो इसे उस दृष्टिकोण में कोड करें जो डिज़ाइन दृष्टिकोण से सबसे अधिक समझ में आता है।

    2

    मैं सुझावों का एक स्थिर, निरंतर, तालिका का उपयोग करने का सुझाव देता हूं।

    struct Table_Entry 
    { 
        int code; 
        int value; 
    }; 
    
    static const Table_Entry lookup_table[] = 
    { 
        {1, 10}, 
        {2, 15}, 
        {3, 13}, 
    }; 
    
    static const unsigned int NUM_TABLE_ENTRIES = 
        sizeof(lookup_table)/sizeof(lookup_table[0]); 
    

    इस के लिए एक लाभ यह है कि टेबल एक std::map जो चलाने के समय के दौरान प्रारंभ किया जाना चाहिए विपरीत संकलन समय पर उत्पन्न होता है, है: यह देखो तालिका का दूसरा रूप है। यदि मात्रा बड़ी है, तो प्रविष्टि खोजने के लिए आप std::lower_bound का उपयोग कर सकते हैं, बशर्ते तालिका का आदेश दिया गया हो।

    एक और लाभ यह तकनीक डेटा संचालित है। डेटा खोज इंजन में बदलाव किए बिना बदल सकता है। कोड या प्रक्रिया में परिवर्तनों को गंभीर प्रतिगमन परीक्षण की आवश्यकता हो सकती है लेकिन डेटा परिवर्तन नहीं हो सकता है; YMMV।

    यह एक संकलक उत्पन्न करने के समान है।

    0

    आम तौर पर मैं एक नक्शा या लुकअप सरणी या शायद कुछ हाइब्रिड लुकअप राक्षस का सुझाव देता हूं (मान लीजिए कि आप गतिशीलता के बजाए गति या कोड आकार के लिए अनुकूलन कर रहे हैं), लेकिन यह ध्यान देने योग्य है कि नए संस्करण जीसीसी के लिए लुकअप टेबल पर स्विच/केस असाइनमेंट को प्रतिस्थापित करने के लिए पर्याप्त स्मार्ट हैं। हालांकि यह पूरी तरह से स्पैस कुंजी के लिए इतना अच्छा नहीं है, यह हो सकता है कि यदि आप चाबियाँ हैं जैसे कि 0, 1, 2, 3, 4, 5, 11, 12, 13, 14, 15, 1 9 3, 1 9 4 , 1 9 5 9, 1 9 6, 1 9 7, 1 9 81 ...

    बेशक यदि आप संभवतः रूपांतरण करने के लिए कुछ अंकगणित पसंद कर सकते हैं, तो बेहतर (आमतौर पर)।ऐसा कुछ करने पर कभी भी स्थानांतरण, अंतहीनता को स्वैप करना, या अधिक पारंपरिक गणित को नजरअंदाज न करें।

    संबंधित मुद्दे