2013-09-01 7 views
6

मैं शायद असंभव हासिल करने की कोशिश कर रहा हूं, लेकिन स्टैक एक्सचेंज हमेशा मुझे आश्चर्यचकित करता है, इसलिए कृपया इस पर जाएं:क्या संकलन-समय की जांच की गई स्ट्रिंग-टू-इंट नक्शा संभव है?

मुझे एक पूर्णांक में एक नाम मैप करने की आवश्यकता है। नाम (लगभग 2k) अद्वितीय हैं। उस सूची में कोई जोड़ नहीं होगा और न ही हटाएगा और रनटाइम के दौरान मूल्य नहीं बदले जाएंगे।

उन्हें const int चर के रूप में लागू करने से मुझे अस्तित्व और प्रकार के लिए संकलन-समय की जांच मिलती है। यह भी कोड में बहुत स्पष्ट और verbose है। त्रुटियों को आसानी से देखा जाता है।

उन्हें std::map<std::string, int> के रूप में लागू करने से मुझे स्ट्रिंग मैनिपुलेशन के साथ नाम बनाने के लिए बहुत लचीलापन मिलता है। मैं स्ट्रिंग को उन कार्यों के पैरामीटर के रूप में देने के लिए उपयोग कर सकता हूं जो उस स्ट्रिंग में प्री-/ प्रत्यय जोड़कर कई मानों के लिए सूची से पूछताछ कर सकते हैं। मैं लूप वैरिएबल से कुंजी नाम का अंक भाग बनाकर कई मानों पर भी लूप कर सकता हूं।

अब मेरा प्रश्न है: क्या दोनों फायदे गठबंधन करने का कोई तरीका है? लापता संकलन-समय की जांच (विशेष रूप से कुंजी-अस्तित्व के लिए) लगभग मेरे लिए दूसरी विधि को मार देती है। (विशेष रूप से std::map चुपचाप 0 लौटाता है यदि कुंजी मौजूद नहीं है जो बग खोजने में कठोर बनाता है।) लेकिन लूपिंग और प्री-/ प्रत्यय जोड़ने की क्षमताओं बहुत उपयोगी हैं।

मैं ऐसे समाधान को पसंद करूंगा जो बढ़ावा देने जैसी किसी भी अतिरिक्त पुस्तकालय का उपयोग नहीं करता है, लेकिन कृपया उन्हें सुझाव दें, फिर भी मैं उन्हें फिर से लागू करने में सक्षम हूं।

मैं क्या नक्शे के साथ करते हैं पर एक उदाहरण:

void init(std::map<std::string, int> &labels) 
{   
    labels.insert(std::make_pair("Bob1" , 45)); 
    labels.insert(std::make_pair("Bob2" , 8758)); 
    labels.insert(std::make_pair("Bob3" , 436)); 
    labels.insert(std::make_pair("Alice_first" , 9224)); 
    labels.insert(std::make_pair("Alice_last" , 3510)); 
} 

int main() 
{  
    std::map<std::string, int> labels; 
    init(labels); 

    for (int i=1; i<=3; i++) 
    { 
    std::stringstream key; 
    key << "Bob" << i; 
    doSomething(labels[key.str()]); 
    } 

    checkName("Alice"); 
} 

void checkName(std::string name) 
{ 
    std::stringstream key1,key2; 
    key1 << name << "_first"; 
    key2 << name << "_last"; 
    doFirstToLast(labels[key1.str()], labels[key2.str()]); 
} 

एक और लक्ष्य है कि कोड के लिए आसान और संभव के रूप में के रूप में वर्बोज़ main() नियमित रहता है में दिखाया गया है। (गैर-प्रोग्रामर द्वारा समझा जाने की आवश्यकता है।) init() फ़ंक्शन कुछ टूल द्वारा कोड-जेनरेट किया जाएगा। doSomething(int) फ़ंक्शंस फ़िक्स्ड हैं, लेकिन मैं उनके चारों ओर रैपर फ़ंक्शन लिख सकता हूं। checkName() जैसे हेल्पर्स अधिक जटिल हो सकते हैं, लेकिन आसानी से डिबग करने योग्य होने की आवश्यकता है।

+1

ऐसा लगता है कि आप क्रम में श्रृंखला बनाते हैं चाहते हैं, लेकिन किसी भी तरह इस संकलन समय पर जाँच की है? –

+0

enums को उनके उचित तारों में परिवर्तित करने के तरीके हैं, इसलिए यह संभव होना चाहिए .. हालांकि यह देखने में कठिनाई होती है कि यदि आप रन टाइम में स्ट्रिंग्स बना रहे हैं तो यह संकलित समय कैसा है –

+0

'std :: map' निश्चित रूप से बताने की क्षमता है आप एक तत्व डाला गया था या नहीं। एक तरीका 'डालने' है। – chris

उत्तर

1

एक तरह से एक enum और टोकन चिपकाने उपयोग कर रहा है, इस

enum { 
    Bob1 = 45, 
    Bob2 = 8758, 
    Bob3 = 436, 
    Alice_first = 9224, 
    Alice_last = 3510 
}; 

#define LABEL(a, b) (a ## b) 

int main() 
{  

    doSomething(LABEL(Bob,1)); 
    doSomething(LABEL(Bob,2)); 
    doSomething(LABEL(Bob,3)); 
} 


void checkName() 
{ 
    doFirstToLast(LABEL(Alice,_first), LABEL(Alice,_last)); 
} 

की तरह किया जाए या नहीं यह सबसे अच्छा है, जहां के नाम से आते हैं पर निर्भर करता है।

आप पाश यूज-केस के लिए समर्थन करने के लिए की जरूरत है, तो विचार करना

int bob[] = { 0, Bob1, Bob2, Bob3 }; // Values from the enum 

int main() 
{  
    for(int i = 1; i <= 3; i++) { 
    doSomething(bob[i]); 
    } 
} 
+0

प्रीप्रोसेसर (जो डिबगिंग के दौरान अपनी समस्याओं के साथ आता है) का उपयोग करने के बावजूद, यह समस्या को अच्छी तरह से हल करता है और काफी वर्बोज़ और कोड को समझने में आसान बनाता है। मुझे वास्तविक कोड में जांचना होगा यदि यह वास्तव में सभी बक्से लगाता है, लेकिन मुझे पहले से ही यह पसंद है। –

+0

हालांकि-loops के लिए नहीं कर सकता, क्योंकि यह अभी भी रनटाइम पर उपलब्ध होगा। या प्रीप्रोसेसर के साथ लूप के लिए एक गैर-बुरा चाल है? –

1

मुझे यकीन नहीं है कि मैं आपकी सभी आवश्यकताओं को समझता हूं, लेकिन std::map का उपयोग किए बिना ऐसा कुछ कैसे करें। मुझे लगता है कि आपके पास तीन तार हैं, "FIRST", "SECOND" और "THIRD" कि आप क्रमश: 42, 17 और 37 पर मानचित्र बनाना चाहते हैं।

#include <stdio.h> 

const int m_FIRST = 0; 
const int m_SECOND = 1; 
const int m_THIRD = 2; 

const int map[] = {42, 17, 37}; 

#define LOOKUP(s) (map[m_ ## s]) 

int main() 
{ 
    printf("%d\n", LOOKUP(FIRST)); 
    printf("%d\n", LOOKUP(SECOND)); 
    return 0; 
} 

नुकसान यह है कि आप LOOKUP साथ चर तार का उपयोग नहीं कर सकते हैं। लेकिन अब आप मूल्यों पर फिर से शुरू कर सकते हैं।

+0

दिलचस्प विचार। लूपिंग को लगातार मूल्यों तक सीमित करता है, लेकिन यह वास्तव में काफी स्वीकार्य है। दुर्भाग्यवश, डीबग करना भी मुश्किल है (सरणी में 1276 वें मान को खोजने का प्रयास करें)। –

0

enum आप इसे ऊपर संकलन समय की जांच और आप पाश कर सकते हैं दोनों का उपयोग किया है:

How can I iterate over an enum?

+0

लिंक कहता है कि अगर मैं ईएनएन के लिए मनमानी संख्याओं का उपयोग करता हूं तो मैं उस पर लूप नहीं कर सकता, जो मामला होगा यदि मैं नाम-से-int मानचित्र स्टोर करने के लिए enum का उपयोग करता हूं। –

1

हो सकता है कि यह (untested) की तरह कुछ?

struct Bob { 
    static constexpr int values[3] = { 45, 8758, 436 }; 
}; 

struct Alice { 
    struct first { 
     static const int value = 9224; 
    }; 
    struct last { 
     static const int value = 3510; 
    }; 
}; 

template <typename NAME> 
void checkName() 
{ 
    doFirstToLast(NAME::first::value, NAME::last::value); 
} 

...अपने उदाहरण को लागू करने के

constexpr int Bob::values[3]; // need a definition in exactly one TU 

int main() 
{ 
    for (int i=1; i<=3; i++) 
    { 
     doSomething(Bob::values[i]); 
    } 

    checkName<Alice>(); 
} 
+0

अच्छा विचार है, लेकिन मेरे मामले में संभव नहीं है। सूची भरने वाले कोड जनरेटर की जटिलता को काफी बढ़ाया जाना चाहिए। मैं प्रत्येक पंक्ति को आउटपुट करने के तरीके को संशोधित कर सकता हूं, लेकिन मैं जटिल निर्णय लेने को जोड़ नहीं सकता हूं। –

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