(कैसे) मैं एक एनम में आइटम गिन सकता हूं?


98

यह सवाल मेरे दिमाग में आया, जब मुझे कुछ पसंद आया

enum Folders {FA, FB, FC};

और प्रत्येक फ़ोल्डर के लिए कंटेनरों की एक सरणी बनाना चाहते थे:

ContainerClass*m_containers[3];
....
m_containers[FA] = ...; // etc.

(का उपयोग करते हुए मानचित्र इसका उपयोग करने के लिए और अधिक सुंदर है: std::map<Folders, ContainerClass*> m_containers;)

लेकिन अपने मूल प्रश्न पर वापस आने के लिए: क्या होगा यदि मैं सरणी आकार को हार्ड-कोड नहीं करना चाहता हूं, क्या यह पता लगाने का एक तरीका है कि फ़ोल्डर में कितने आइटम हैं? (उदाहरण के FCलिए सूची में अंतिम आइटम होने पर भरोसा किए बिना जो ContainerClass*m_containers[FC+1]मुझे गलत नहीं लगने देता है।)


यह पोस्ट आपके प्रश्न का उत्तर दे सकती है: stackoverflow.com/questions/1390703/enumerate-over-an-enum-in-c
स्टैक्डक्रॉक्ड

1
सवाल थोड़ा अशिक्षित है। C ++ मानक के अनुसार, int(FA) | int(FB) | int (FC)एक Foldersचर के लिए एक कानूनी मूल्य भी है । यदि आप m_containersइतना बड़ा आकार दे रहे हैं कि कोई भी Foldersवैरिएबल एक वैध सूचकांक है, [FC+1]तो यह पर्याप्त बड़ा नहीं होगा।
8


मैं आप से समाधान की सिफारिश था stackoverflow.com/a/60216003/12894563 से और बेहतर संस्करण stackoverflow.com/a/60271408/12894563
ixjxk

जवाबों:


123

ऐसा करने का वास्तव में एक अच्छा तरीका नहीं है, आमतौर पर आप एनम में एक अतिरिक्त आइटम देखते हैं, अर्थात

enum foobar {foo, bar, baz, quz, FOOBAR_NR_ITEMS};

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

int fuz[FOOBAR_NR_ITEMS];

हालांकि अभी भी बहुत अच्छा नहीं है।

लेकिन निश्चित रूप से आप यह महसूस करते हैं कि एक एनम में आइटम की संख्या सुरक्षित नहीं है, उदाहरण के लिए

enum foobar {foo, bar = 5, baz, quz = 20};

आइटमों की संख्या 4 होगी, लेकिन एनम वैल्यूज़ का पूर्णांक मान ऐरे इंडेक्स रेंज से बाहर होगा। एरे इंडेक्सिंग के लिए एनम वैल्यू का उपयोग करना सुरक्षित नहीं है, आपको अन्य विकल्पों पर विचार करना चाहिए।

संपादित करें: जैसा कि अनुरोध किया गया है, विशेष प्रवेश छड़ी को और अधिक बाहर कर दिया।


27
इसे LAST या ALWAYS_AT_END कहें या ऐसा कुछ भी गुप्त नहीं है। इसे बाहर छड़ी बनाओ । ताकि बाद के अनुचर आप मार्कर समाप्त होने के बाद गलती से नई प्रविष्टियाँ न जोड़ें।
मार्टिन यॉर्क

3
बेहतर या बदतर के लिए, यह वह दृष्टिकोण है जिसे हम अपने संगठन में लेते हैं। हम आम तौर पर इसे FINAL_enumname_ENTRY कहते हैं, जैसे कि FINAL_foobar_ENTRY। मैंने यह भी देखा है कि लोग एक अलग स्थिर कॉन्स्टेबल FOOBAR_COUNT वैरिएबल का उपयोग एनम घोषणा के ठीक बाद परिभाषित करते हैं, एक दृष्टिकोण जो थोड़ा और अधिक त्रुटि वाला है।
डैरिल

1
कम से कम यह देखना काफी आसान है कि "एनम फू {a = 10, LAST}" विषम होने वाला है। और मुझे लगा कि "int arr [LAST]" इस मामले में 11 आइटम होंगे, 2 नहीं, इसलिए अधिकांश कोड काम करेंगे (लेकिन आप अमान्य इंडेक्स वैल्यू पर मेमोरी बर्बाद कर रहे हैं)
कोड Abominator

32

सी ++ के लिए, विभिन्न प्रकार-सुरक्षित एनुम तकनीक उपलब्ध हैं, और उनमें से कुछ (जैसे प्रस्तावित-लेकिन-कभी-कभी-प्रस्तुत बूस्ट.ईएनम ) में एनम का आकार प्राप्त करने के लिए समर्थन शामिल नहीं है ।

सबसे सरल दृष्टिकोण, जो C के साथ-साथ C ++ में भी काम करता है, को घोषित करने का एक कन्वेंशन अपनाना है ... आपके प्रत्येक enum प्रकारों के लिए MAX मान:

enum Folders { FA, FB, FC, Folders_MAX = FC };
ContainerClass *m_containers[Folders_MAX + 1];
....
m_containers[FA] = ...; // etc.

संपादित करें : { FA, FB, FC, Folders_MAX = FC}बनाम के बारे में {FA, FB, FC, Folders_MAX]: मैं कुछ कारणों से एनम के अंतिम कानूनी मूल्य के लिए मैक्स वैल्यू सेट करना पसंद करता हूं:

  1. निरंतरता का नाम तकनीकी रूप से अधिक सटीक है (क्योंकि Folders_MAXअधिकतम संभव एनम मान देता है)।
  2. व्यक्तिगत रूप से, मुझे ऐसा लगता है कि Folders_MAX = FCअन्य प्रविष्टियों से थोड़ा अधिक बाहर खड़ा है (अधिकतम मूल्य को अपडेट किए बिना गलती से एनम मूल्यों को जोड़ना थोड़ा मुश्किल हो जाता है, एक समस्या मार्टिन यॉर्क संदर्भित)।
  3. जीसीसी में निम्नलिखित जैसे कोड के लिए "गणना में शामिल नहीं किया गया" जैसे उपयोगी चेतावनी शामिल हैं। फ़ोल्डरों_मैक्स == एफसी + 1 को उन चेतावनियों को तोड़ने देता है, जब से आप एक गुच्छा के साथ समाप्त होते हैं ... अधिकतम गणना मूल्यों को स्विच में शामिल नहीं किया जाना चाहिए।
स्विच (फ़ोल्डर) 
{
  मामला एफए: ...;
  मामला एफबी: ...;
  // उफ़, भूल गया एफसी!
}

3
क्यों नहीं करते enum Folders { FA, FB, FC, Folders_MAX }; ContainerClass *m_containers[Folders_MAX];:?
बिल

1
मैं यह स्पष्ट करना पसंद करता हूं कि अंतिम एक संख्या है, और उन सभी का एक ही नाम है:struct SomeEnum { enum type {FA, FB, FC, NB__};};
लूक हर्मिट्टे

2
वास्तव में मुझे लगता है कि उन "सहायक" चेतावनियों को गधे में एक सही दर्द है। मुझे अच्छी चेतावनियाँ पसंद हैं, जब मैं विकसित हो रहा हूँ, तो मैं हमेशा -वैलिटेड इत्यादि को सेट करता हूँ, लेकिन ये चेतावनी सिर्फ बेवकूफी है। केवल कुछ बदतर हैं, जैसे सुझाव के लिए parens && || और & ^ | संचालक वरीयता। मेरा मतलब है, मुझे लगा कि जावा दाई भाषा थी, सी और सी ++ का क्या हश्र हो रहा है ...
wich

2
Folders_max = FC होने का नकारात्मक पक्ष यह है कि आपको इसे हर बार बदलना होगा जब आप कुछ को एनम से जोड़ेंगे!
.tienne

2
enum फ़ोल्डर {एफए, एफबी, एफसी, फोल्डर्स_मिन = एफए, फोल्डर्स_मैक्स = एफसी}; बस जोर देने के लिए कि यह पुनरावृत्ति के लिए उपयोगी है?
gjpc 15

7

कैसे के बारे में लक्षण, एक एसटीएल फैशन में? उदाहरण के लिए:

enum Foo
{
    Bar,
    Baz
};

एक लिखें

std::numeric_limits<enum Foo>::max()

विशेषज्ञता (संभवतः अगर आप c ++ 11 का उपयोग करते हैं)। फिर, आपके परीक्षण कोड में, std :: संख्यात्मक_limits :: max () = last_item बाधाओं को बनाए रखने के लिए कोई भी स्थिर दावे प्रदान करते हैं।


2
दुर्भाग्य से यह इस उत्तर के अनुसार काम नहीं करेगा ।
आरआर-

3
std::numeric_limits<enum Foo>::max()हमेशा शून्य पर लौटता है ... (लिंक किए गए उत्तर के लिए प्रश्न देखें) सामान्य एनम ( enum Foo { ... }), टाइप-हिंटेड एनम ( enum class Foo : uint8_t { ... }) के साथ gcc 5.2.0 @ लिनक्स और MinGW 4.9.3 @ विंडोज पर परीक्षण किया गया ।
rr-

1
... (और मामले में std::numeric_limits<std::underlying_type<Foo>::type>::max(), यह 32-बिट पूर्णांक के लिए अंतर्निहित प्रकार के 0xFFFFFFFF का अधिकतम मान लौटाता है, जो इस संदर्भ में उपयोगी नहीं है।)
rr-

1
अजीब बात है, क्योंकि मेरे पास काम करने वाला कोड है जो मैंने वर्णित किया है। namespace gx { enum struct DnaNucleobase : char { A, C, G, T }; } तब: namespace std { template<> struct numeric_limits<enum ::gx::DnaNucleobase> { typedef enum ::gx::DnaNucleobase value_type; static constexpr value_type max() { return value_type::T; } (...) और std::cout << std::numeric_limits<::gx::DnaNucleobase>::max() << std::endl;प्रिंट अपेक्षित परिणाम। 5.2.1 और 4.8 / 4.9 जायके के साथ परीक्षण किया गया।
वोज्शिएक मिग्डा

2
-1; यदि आप जवाब बदलते हैं तो मुझे पिंग करें, ताकि मैं नीचा दिखा सकूं। इस जवाब का पालन करने के लिए एक बुरा सम्मेलन है। यह की अवधारणा का दुरुपयोग है numeric_limits<T>::max()। केवल एक चीज जो कार्य को यथोचित रूप से वापस कर सकती है वह है उच्चतम गणना मूल्य। यह वापस आ जाएगा 2, लेकिन ओपी (इस विशिष्ट मामले में) को इसे वापस करने की आवश्यकता होगी 3। एक बार जब आपके पास एनम ( FB = 2057) के लिए गैर-डिफ़ॉल्ट मान होते हैं, तो सभी दांव बंद हो जाते हैं, + 1ऑफ-वन-वन त्रुटि के आसपास हैक करने के लिए भी नहीं कर सकते । यदि कोई numeric_limits<T>::number_of_elements_of_the_set()(या छोटा नाम) था, तो इसका उपयोग अस्पष्टता के बिना किया जा सकता है।
मेरलिन मॉर्गन-ग्राहम

3

अपने एनम के अंत में एक प्रविष्टि जोड़ें, जिसे Folders_MAX या कुछ समान कहा जाता है और अपने सरणियों को प्रारंभ करते समय इस मान का उपयोग करें।

ContainerClass* m_containers[Folders_MAX];

2

मैं अपने कार्यों के लिए तर्क के रूप में एनम का उपयोग करना पसंद करता हूं। "विकल्पों" की एक निश्चित सूची प्रदान करना एक आसान साधन है। यहां शीर्ष मतदान जवाब के साथ परेशानी यह है कि इसका उपयोग करके, एक ग्राहक "अमान्य विकल्प" निर्दिष्ट कर सकता है। स्पिन ऑफ के रूप में, मैं अनिवार्य रूप से एक ही काम करने की सलाह देता हूं, लेकिन उनमें से गिनती को परिभाषित करने के लिए एनम के बाहर एक निरंतर इंट का उपयोग करें।

enum foobar { foo, bar, baz, quz };
const int FOOBAR_NR_ITEMS=4;

यह सुखद नहीं है, लेकिन यदि आप निरंतर अद्यतन किए बिना एनम को नहीं बदलते हैं तो यह एक स्वच्छ समाधान है।


1

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

enum example{ test1 = -2, test2 = -1, test3 = 0, test4 = 1, test5 = 2 }

जब आप 5 आइटमों की एक सरणी की आवश्यकता होती है, तो इस परिणाम में 3 आइटमों की एक सरणी बनाई जाएगी

enum example2{ test1 , test2 , test3 , test4 , test5 = 301 }

इसमें उदाहरण के लिए परिणाम 301 आइटमों की एक सरणी बनाएगा जब आपको 5 आइटमों की एक सरणी की आवश्यकता होगी

सामान्य मामले में इस समस्या को हल करने का सबसे अच्छा तरीका अपने ज्ञान के माध्यम से पुनरावृत्ति करना होगा, लेकिन यह मानक में नहीं है जहां तक ​​मुझे पता है

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.