2012-11-14 23 views
9

मैं बाइनरी झंडे का उपयोग कर परिमित राज्य मशीन बनाने के लिए सी ++ में एक enum बना रहा हूँ। ऐसा लगता है:अधिकतम int अनुमति के मूल्यों के साथ एक enum कैसे बनाने के लिए?

enum VStates 
{ 
    NEUTRAL   = 0x00000000,  // 000000 
    // Physical Status 
    DRY    = 0x00000001,  // 000001 
    WET    = 0x00000002,  // 000010 
    HOT    = 0x00000004,  // 000100 
    COLD   = 0x00000008,  // 001000 
    BURNED   = 0x00000016,  // etc.. 
    FROZEN   = 0x00000032, 
    EROS   = 0x00000064,  // 
    THANATOS  = 0x00000128,  // 
    SLEEP   = 0x00000256, 
    STUNNED   = 0x00000512, 
    PARALYZED  = 0x00001024, 
    POISONED  = 0x00002048,  // 
    BLIND   = 0x00004096, 
    SOFT   = 0x00008192,  // Flexible 
    TOUGH   = 0x00016384,  // Resistent 
    MAGNETIZED  = 0x00032768, 
    POSSEDERUNT  = 0x00131072,  // 
    // Mental Status 
    ANGRY   = 0x00262144, 
    DRUGGED   = 0x00524288, // Drugs Meaning 
    HORNY   = 0x01048576, // Sexual Meaning 
    // Material Status 
    METAL   = 0x02097152, 
    WOOD   = 0x04194304, 
    GLASS   = 0x08388608, 
    AIR    = 0x16777216, 
    EARTH   = 0x33554432, 
    DUST   = 0x67108864, 
    LIGHT   = 0x134217728, 
    SHADOW   = 0x268435456, 
    WATER   = 0x536870912, 
    // Total Status 
    PROTECTED  = 0x1073741824, 
    INVULNERABLE = 0x2147483648 

}; 

कुछ स्थिति असंगत हैं, इसलिए मैं उन्हें प्रबंधित करने के लिए बिटवाई ऑपरेटरों का उपयोग करता हूं। अब, मेरा कंपाइलर कहता है:

warning: integer constant is too large for 'long' type 

क्या यह इस enum घोषित करने का सही तरीका है? मुझे चेतावनी से बचना पसंद है, मैं इस समस्या को कैसे हल कर सकता हूं?

+1

कोई जवाब नहीं है, लेकिन यह लिखना और पढ़ने के लिए बहुत आसान होगा यदि मान हेक्स स्थिरांक के रूप में लिखे गए थे। –

+9

@PeteBecker: वे वास्तव में * हेक्स स्थिरांक के रूप में लिखे गए हैं - लेकिन ऐसा लगता है कि वह दशमलव स्थिरांक के लिए अंकों का उपयोग कर रहा है (उदाहरण के लिए, उसके पास 0x00000512 है, जो वास्तव में 512 या 0x200 होना चाहिए)। –

+0

@ जेरीकॉफिन - ओह। –

उत्तर

10

(नोट: मेरा उत्तर मैं कुछ मैं नहीं था में जोड़ देंगे पूरा करने के लिए नोटिस करने में समय नहीं लगता है लेकिन अन्य ने ध्यान दिया है: आप 0x उपसर्ग का उपयोग कर रहे हैं, जिसका अर्थ है कि आपकी संख्या हेक्साडेसिमल के रूप में व्याख्या की जाएगी। वे वास्तव में दो की शक्ति नहीं होंगे, और आपके बिटफ्लैग परीक्षणों ने काम नहीं किया होगा!)

यदि आपकी गणना इस तरह से नियंत्रण से बाहर हो रही है, तो एक गणना प्रकार का उपयोग न करें। std::bitset जैसे कुछ का उपयोग करें। फिर आपका enum सेट में बिट्स की स्थिति के लिए नामों की एक साधारण क्रमांकित सूची हो सकता है ... और आप अपने गणना स्थान को तेजी से समाप्त नहीं करेंगे!

उदाहरण के लिए:

enum VState { 
    NEUTRAL, 
    DRY, 
    WET, 
    COLD, 
    BURNED, 
    FROZEN, 
    /* ... */ 
    VState_Max 
}; 

bitset<VState_Max> state; 

state[COLD] = true; 
if (state[COLD]) { 
    cout << "I am cold\n"; 
} 

अब आप अपने enum सिर्फ छोटे, पोषणीय संख्या है और आप एक 64-बिट मंच या whatnot पर होने के बारे में चिंता करने की जरूरत नहीं है।

मुझे लगता है कि आपने अपने मूल उदाहरण में NEUTRAL के लिए "0" का मान दिया है। यदि आपका इरादा अन्य चीजों के साथ संयोजन में इसका उपयोग करना संभव था ... जैसे कि state = NEUTRAL | INVULNERABLE | SHADOW और NEUTRAL के लिए अलग-अलग परीक्षण करने में सक्षम होना, जो पहले काम नहीं करता था। अब यह होगा ... आप बस बिटसेट को अनुक्रमणित करने के लिए गणना में रखेंगे।

लेकिन अगर यह "सेट कुछ भी नहीं" के लिए एक नाम के रूप में है, तो आप यह enum से परीक्षण नहीं बिट्स के साथ सेट के लिए हटाने और बजाय होगा इरादा:

if (state.none()) { 
    // we are in the "NEUTRAL" state of nothing set... 
} 

... और यदि आप चाहते थे सभी बिट्स को झूठी पर सेट करने के लिए, आप इसके साथ जाएंगे:

state.reset(); 
+4

यह मेरे मुकाबले एक बेहतर जवाब है, क्योंकि आप सही अंतर्निहित मुद्दे को सही करते हैं। झंडे के संग्रह के लिए 'std :: बिटसेट 'का प्रयोग करें, न कि enums। सूचकांक के लिए एक एनम का उपयोग करने से भी बेहतर यह उस वर्ग में लपेटना होगा जिसमें 'std :: bitset' नामित सदस्य पहुंच कार्यों वाले निजी सदस्य के रूप में है। 'कक्षा VStates {सार्वजनिक: बूल is_dry() const {वापसी बिट्स [1]; } ...}; ' –

+0

@ डेविडस्टोन धन्यवाद। और यदि पैकिंग जानकारी इस दर्शकों के लिए ब्याज की है, तो मेरी [एनस्टेट लाइब्रेरी] (http://hostilefork.com/nstate/) ब्याज की हो सकती है ... – HostileFork

+0

मैं इसका उपयोग कर समाप्त कर सकता हूं। मैं वर्तमान में एक ऐसे एप्लिकेशन पर काम कर रहा हूं जहां मेरे समय के ~ 2/3 को डेटा कॉपी करने में खर्च किया जाता है। मेरे प्रासंगिक डेटा संरचनाओं के आकार में 50% की कमी रन टाइम में 30% की कमी से थोड़ा कम है, और ऐसा लगता है कि मेरे आवेदन का कम से कम हिस्सा उस समाधान के लिए उपयुक्त हो सकता है। –

0

छोटी संख्याओं का उपयोग करें। एक enum केवल एक लंबे समय के रूप में बड़ा हो सकता है। लंबे समय का आकार कंपाइलर पर निर्भर करता है, लेकिन एक सामान्य आकार या तो 32 या 64 बिट्स है। मैं वहां कुछ 10 अंकों हेक्स संख्या देखता हूं, वे बहुत बड़े हैं।

3

आप सी ++ 11 का उपयोग कर रहे हैं, तो आप unsigned long long के रूप में एक परिभाषित प्रकार के साथ एक जोरदार टाइप enum घोषणा कर सकते हैं (Windows में _int64, हालांकि आप शायद पोर्टेबल uint64_t का उपयोग करना चाहिए), अगर है कि आपके रेंज काफी दूर तक फैली हुई है। सी ++ 11 enum उपयोग के उदाहरण के लिए एक लिंक के लिए जोकिम को

धन्यवाद: Strongly Typed Enums

+0

उदा। देखें [यह विकिपीडिया लिंक] (http://en.wikipedia.org/wiki/C++11#Strongly_typed_enumerations) दृढ़ता से टाइप किए गए enums पर, और उन्हें परिभाषित करने के लिए कैसे। विभिन्न पूर्णांक प्रकारों के साथ। –

+0

@ जोचिमपिलबोर्ग धन्यवाद, दिमाग अगर मैं उस लिंक का उत्तर सुधारने के लिए उपयोग करता हूं? –

+0

निश्चित रूप से, आगे बढ़ें। :) –

12

सी ++ 11 में, आप enum के अंतर्निहित प्रकार निर्दिष्ट कर सकते हैं।

#include <cstdint> 

enum VStates : uint64_t { 
    // Values 
} 

एक तरफ ध्यान दें, मैं उन सभी शक्तियों की गणना के खिलाफ अनुशंसा करता हूं। आपने एक हेक्स स्थिर लिखकर अपनी गणना में एक त्रुटि की है लेकिन इसे आधार -10 अंक के अंक दे रहे हैं। हालांकि, उन सभी को पुन: गणना करने की बजाय, मैं कुछ सुझाव देता हूं:

#include <cstdint> 

enum VStates : uint64_t { 
    NEUTRAL = 0ULL, 
    DRY = 1ULL << 0, 
    WET = 1ULL << 1, 
    HOT = 1ULL << 2, 
    COLD = 1ULL << 3, 
    // etc. 
} 

तब आप सुनिश्चित हैं कि कोई गलती न करें। ULL प्रत्यय सुनिश्चित करता है कि शाब्दिक को कम से कम 64-बिट चौड़ा पूर्णांक के रूप में स्वीकार किया जाता है।

4

गणना में 31 शून्य-शून्य मान हैं, इसलिए वे सभी 32-बिट हस्ताक्षरित मूल्य में फिट हो सकते हैं। समस्या यह है कि यहां के मान बिट-वैल्यू नहीं हैं। या तो उन्हें दशमलव मान के रूप में लिखें (आगे से 0x हटाएं) या उन्हें हेक्साडेसिमल मान (0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, आदि) के रूप में लिखें, मुझे व्यक्तिगत रूप से यह पसंद नहीं है, लेकिन कुछ लोग लिखते हैं बदलाव के साथ लगातार इस तरह की: 1 < < 0, 1 < < 1, 1 < < 2, 1 < < 3, आदि

+2

मुझे उत्सुकता है कि आपको बदलावों के बारे में क्या पसंद नहीं है? वे कम त्रुटि प्रवण हैं और enum पर एक त्वरित नज़र हैं और आप तुरंत जानते हैं कि आप उस पर bitwise संचालन का उपयोग कर सकते हैं। – Joe

+2

@ जो - यह पूरी तरह से कृत्रिम है। वे हेक्स मानों से कम त्रुटि प्रवण नहीं हैं, और मुझे लगता है कि वे बदसूरत हैं। –