C ++ में enums का उपयोग कैसे करें


218

मान लें कि हमारे पास enumनिम्नलिखित की तरह है:

enum Days {Saturday, Sunday, Tuesday, Wednesday, Thursday, Friday};

मैं इसका एक उदाहरण बनाना चाहता हूं enumऔर इसे एक उचित मूल्य के साथ शुरू करना चाहता हूं , इसलिए मैं करता हूं:

Days day = Days.Saturday;

अब मैं एक मौजूदा enumमूल्य के साथ अपने चर या उदाहरण की जांच करना चाहता हूं , इसलिए मैं करता हूं:

if (day == Days.Saturday)
{
    std::cout << "Ok its Saturday";
}

जो मुझे एक संकलन त्रुटि देता है:

त्रुटि: 'से पहले अपेक्षित प्राथमिक अभिव्यक्ति'। टोकन

तो स्पष्ट होने के लिए, क्या अंतर है:

if (day == Days.Saturday) // Causes compilation error

तथा

if (day == Saturday)

?

इन दोनों का वास्तव में क्या उल्लेख है, इसमें एक ठीक है और एक संकलन त्रुटि का कारण बनता है?


4
मुझे पता है, मुझे पता है कि ओ मुझे त्रुटि क्यों दे रहा है!
रिका

1
इसका बुधवार यहाँ है। C ++ कंपाइलर के लिए आपके पास बहुत अधिक वाक्यविन्यास त्रुटियां हैं। En एनम ’से शुरू।
06ö तिइब

1
@ होसेन, क्योंकि दोनों भाषाओं में एक ही वाक्यविन्यास (और शब्दार्थ) नहीं हैं। एक नई भाषा में एक सुविधा का उपयोग करने की कोशिश करते समय त्रुटि मिलने के बाद पहली चीज मैं उस भाषा में वाक्यविन्यास (या यदि संभव हो तो) को देखता हूं।
क्रिस

@ क्रिस: मुझे पता है, मैं वही सटीक काम करता हूं। वैसे मुझे मेरा जवाब मिल गया है। मैंने इस सवाल को और अधिक स्पष्ट करने के लिए अपडेट किया है। वैसे आप धन्यवाद;)
रिका

17
" जहाँ तक मुझे पता है कि इन दोनों भाषाओं में घोषणा और उपयोग समान हैं। " आपकी समस्या है, वहीं है। C # C ++ जैसी भाषा नहीं है । विशेष रूप से, उनके पास एनम के लिए अलग वाक्यविन्यास है।
रोब

जवाबों:


350

यह कोड गलत है:

enum Days {Saturday, Sunday, Tuesday, Wednesday, Thursday, Friday};
Days day = Days.Saturday;
if (day == Days.Saturday)

क्योंकि Daysन कोई स्कोप है, न कोई वस्तु। यह एक प्रकार है। और प्रकार खुद सदस्यों के पास नहीं है। आपने जो लिखा है वह उसके समकक्ष है std::string.clearstd::stringएक प्रकार है, इसलिए आप इस .पर उपयोग नहीं कर सकते । आप .एक उदाहरण पर उपयोग करते हैं एक वर्ग के ।

दुर्भाग्य से, enums जादुई हैं और इसलिए सादृश्य वहाँ बंद हो जाता है। क्योंकि एक वर्ग के साथ, आप std::string::clearसदस्य फ़ंक्शन के लिए एक संकेतक प्राप्त करने के लिए कर सकते हैं , लेकिन C ++ 03 में, Days::Sundayअमान्य है। (जो दुखद हो)। ऐसा इसलिए है क्योंकि C ++ सी के साथ कुछ हद तक पीछे है, और C का कोई नामस्थान नहीं है, इसलिए गणना को वैश्विक नामस्थान में होना था। तो सिंटैक्स बस है:

enum Days {Saturday, Sunday, Tuesday, Wednesday, Thursday, Friday};
Days day = Saturday;
if (day == Saturday)

सौभाग्य से, माइक सेमोर ने देखा कि यह C ++ 11 में संबोधित किया गया है। बदलें enumकरने के लिए enum classऔर यह अपने आप ही गुंजाइश हो जाता है; इसलिए Days::Sundayयह न केवल मान्य है, बल्कि उपयोग करने का एकमात्र तरीका है Sunday। खुशी के दिन!


254
सौभाग्य से, आपकी शिकायत C ++ 11 में संबोधित की गई है। बदलें enumकरने के लिए enum classऔर यह अपने आप ही गुंजाइश हो जाता है; इसलिए Days::Sundayयह न केवल मान्य है, बल्कि उपयोग करने का एकमात्र तरीका है Sunday। खुशी के दिन!
माइक सेमुर

11
C ++ त्रुटि संदेशों से प्यार होगा ... वे साबित करते हैं कि भाषा अच्छी प्रतिक्रिया देने के लिए बोझिल है। मैं इसे एक 'प्राथमिक-अभिव्यक्ति' एक वस्तु या एक गुंजाइश या कोई अन्य चीज है जो एक प्रकार नहीं है। शायद एक प्रकार एक 'माध्यमिक-अभिव्यक्ति' है। और क्या एक सी ++ डेवलपर एक 'डॉट ऑपरेटर' कह सकता है सी ++ कंपाइलर केवल एक 'टोकन' कह सकता है। जब यह हो जाता है कि त्रुटि संदेशों को समझना मुश्किल है, तो मुझे लगता है कि भाषा में कुछ गड़बड़ है।
ट्रैविस

4
@Travis: en.cppreference.com/w/cpp/language/... । एक प्राथमिक अभिव्यक्ति एक अभिव्यक्ति में सिर्फ पहली चीज है, आमतौर पर एक नाम या चर या शाब्दिक। दूसरे भाग के रूप में, मैं नहीं बीच एक बड़ा अंतर देख पा रहे हैं '.' tokenऔर dot operatorअन्य की तुलना में यह एक टोकन और नहीं एक ऑपरेटर है, है, और यह बजाय एक नाम से, सटीक प्रतीक को दर्शाता है।
मिंग डक

@ माइक सीमौर मैंने संकलकों के एक समूह पर गुंजाइश रिज़ॉल्यूशन ऑपरेटरों के बिना एनमों तक पहुंचने की कोशिश की है, और यह काम करने लगता है। आपने कहा था कि C ++ के रूप में 11 यह एक ही रास्ता है, किसी कारण के लिए मैं सिर्फ वैश्विक रूप enum मूल्यों का उपयोग कर सकते, :: की जरूरत नहीं है
Zebrafish

1
@TitoneMaurice: यदि आपके पास कोई है enum, तो आप कोई गुंजाइश, या वैश्विक गुंजाइश ( ::Saturday) का उपयोग कर सकते हैं । यदि आप एक है, तो enum class(जो एक बहुत अलग बात है), तो आप है उपयोग करने के लिए Days::Saturday
डिंग डक

24

यह आपके एनम चर घोषित करने और इसकी तुलना करने के लिए पर्याप्त होगा:

enum Days {Saturday, Sunday, Tuesday, Wednesday, Thursday, Friday};
Days day = Saturday;
if (day == Saturday) {
    std::cout << "Ok its Saturday";
}

ऐसा क्यों कहना गलत है अगर (दिन == दिन। दिन)? उन्हें समान होना चाहिए, इसलिए कंपाइलर इसके बारे में शिकायत क्यों कर रहा है?
राइका

1
@ हसीन आपकी कक्षा में घोषित मूल्य वर्ग या संरचनात्मक सदस्य चर की तरह व्यवहार नहीं करते हैं। यह उपयोग करने के लिए सही वाक्यविन्यास नहीं है
गणितज्ञ

2
@ होसेन: क्योंकि Daysकोई स्कोप नहीं है, न ही ऑब्जेक्ट। यह एक प्रकार है। और प्रकार खुद सदस्यों के पास नहीं है। std::string.clearउसी कारण से संकलन करने में भी विफल रहता है।
मूइंग डक

8
@ होसेन: क्योंकि यह नहीं है कि कैसे सी + + में काम करते हैं। अघोषित गणनाओं ने उनके मूल्यों को आसपास के नामस्थान में डाल दिया; स्कोप्ड ( enum class, 2011 में नए) का अपना दायरा है, और स्कोप ऑपरेटर का उपयोग करके एक्सेस किया जाता है Days::Saturday। सदस्य अभिगम संचालक ( .) का उपयोग केवल कक्षा सदस्यों तक पहुँचने के लिए किया जाता है।
माइक सेमोर

@MooDUDUck और MikeSeymour क्या आप में से कोई एक उत्तर के रूप में अपना उत्तर पोस्ट करेगा? क्योंकि यह वही है जो मैं इस प्रश्न को जारी करने के बाद था;)
रिको

22

इसमें से बहुत कुछ आपको संकलन त्रुटियों को देना चाहिए।

// note the lower case enum keyword
enum Days { Saturday, Sunday, Monday, Tuesday, Wednesday, Thursday, Friday };

अब, Saturday, Sunday, आदि उच्च-स्तरीय नंगे स्थिरांक के रूप में इस्तेमाल किया जा सकता है, और Daysएक प्रकार के रूप में इस्तेमाल किया जा सकता:

Days day = Saturday;   // Days.Saturday is an error

और इसी तरह बाद में, परीक्षण करने के लिए:

if (day == Saturday)
    // ...

ये enumमान नंगे स्थिरांक की तरह हैं - वे अन- कोडेड हैं - संकलक से थोड़ी अतिरिक्त मदद के साथ: (जब तक कि आप C ++ 11 enum classes का उपयोग नहीं कर रहे हैं ) वे उदाहरण के लिए ऑब्जेक्ट या संरचना के सदस्यों की तरह इनकैप्सुलेट नहीं होते हैं , और आप उन्हें सदस्यों के रूप में संदर्भित नहीं कर सकते Days

आपके पास C ++ 11 के साथ जो आप देख रहे हैं , वह एक परिचय होगा enum class:

enum class Days
{
    SUNDAY,
    MONDAY,
    // ... etc.
}

// ...

if (day == Days::SUNDAY)
    // ...

ध्यान दें कि यह C ++ कुछ तरीकों से C से थोड़ा अलग है, एक यह है कि C को enumचर घोषित करते समय कीवर्ड के उपयोग की आवश्यकता होती है :

// day declaration in C:
enum Days day = Saturday;

मैंने इस सवाल को अपडेट किया है, मुझे लगता है कि अब मैं स्पष्ट हूँ कि मैं इसके बाद क्या कर रहा हूँ :) वैसे तो थैंक्यू :)
रीका

14

आप अपनी इच्छानुसार स्कोप का उपयोग करने के लिए एक ट्रिक का उपयोग कर सकते हैं, बस इस तरह से एनम घोषित करें:

struct Days 
{
   enum type
   {
      Saturday,Sunday,Tuesday,Wednesday,Thursday,Friday
   };
};

Days::type day = Days::Saturday;
if (day == Days::Saturday)

9

इफ-स्टेटमेंट्स के एक समूह का उपयोग करने के बजाय, एनम स्वयं बयानों को स्विच करने के लिए अच्छी तरह से उधार देते हैं

मैं अपने गेम के लिए जिस स्तर के बिल्डर का निर्माण कर रहा हूं, उसमें कुछ एनुम / स्विच संयोजन का उपयोग करता हूं।

संपादित करें: एक और बात, मुझे लगता है कि आपको सिंटैक्स समान चाहिए;

if(day == Days.Saturday)
etc

आप इसे C ++ में कर सकते हैं:

if(day == Days::Saturday)
etc

यहाँ एक बहुत ही सरल उदाहरण दिया गया है:

EnumAppState.h

#ifndef ENUMAPPSTATE_H
#define ENUMAPPSTATE_H
enum eAppState
{
    STARTUP,
    EDIT,
    ZONECREATION,
    SHUTDOWN,
    NOCHANGE
};
#endif

Somefile.cpp

#include "EnumAppState.h"
eAppState state = eAppState::STARTUP;
switch(state)
{
case STARTUP:
    //Do stuff
    break;
case EDIT:
    //Do stuff
    break;
case ZONECREATION:
    //Do stuff
    break;
case SHUTDOWN:
    //Do stuff
    break;
case NOCHANGE:
    //Do stuff
    break;
}

यहाँ अच्छी बात यह है कि संकलक आपको बताएंगे कि क्या आप एक केस डालने से चूक गए हैं?
क्रिस

क्या आपको इस मामले में क्लास एनम का उपयोग करना चाहिए?
रिका

1
enum C ++ में सिर्फ एक datatype है। इसलिए एक enum की घोषणा करते हुए जैसे मैंने .h फ़ाइल में ऊपर किया था, और फिर उस फ़ाइल को जो भी .cpp फ़ाइल में आप इसका उपयोग करना चाहते हैं, उसमें आपको enum तक पहुँच प्रदान करेगा। बस मैं अपने .cpp उदाहरण में #include जोड़ना भूल गया। संपादन।
डीन नाइट

इसके अलावा, मैं किसी और को यह कहते हुए देखता हूं कि C ++ में एनम वैश्विक हैं। मेरे अनुभव में, मेरे पास उपरोक्त तरीके का उपयोग करते हुए, मैं केवल उन तक पहुँच प्राप्त कर सकता हूं जब मैंने .h को शामिल किया है। इसलिए यह वैश्विक पहुंच को भी रोकता है, जो हमेशा अच्छा होता है। संपादित करें: ऐसा लगता है कि मैं अनजाने में सी ++ 11 तरीके से एनमों का उपयोग कर रहा हूं अगर मैं चीजों को सही पढ़ रहा हूं ...
डीन नाइट

9

यदि आप अभी भी C ++ 03 का उपयोग कर रहे हैं और Enums का उपयोग करना चाहते हैं, तो आपको नाम स्थान के अंदर enums का उपयोग करना चाहिए। उदाहरण के लिए:

namespace Daysofweek{
enum Days {Saturday, Sunday, Tuesday,Wednesday, Thursday, Friday};
}

आप नाम स्थान के बाहर एनुम का उपयोग कर सकते हैं जैसे,

Daysofweek::Days day = Daysofweek::Saturday;

if (day == Daysofweek::Saturday)
{
    std::cout<<"Ok its Saturday";
}

8

आप दृढ़ता से टाइप किए गए एन्यूमरेशन की तलाश कर रहे हैं , जो C ++ 11 में उपलब्ध है मानक । यह गुंजाइश मूल्यों के साथ वर्गों में गणना करता है।

अपने स्वयं के कोड उदाहरण का उपयोग करना, यह है:

  enum class Days {Saturday, Sunday, Tuesday,Wednesday, Thursday, Friday};
  Days day = Days::Saturday;

  if (day == Days::Saturday)  {
    cout << " Today is Saturday !" << endl;
  }
  //int day2 = Days::Sunday; // Error! invalid

::यदि सी + + मानक C ++ 11 को लक्षित करने के लिए अभिगमकर्ताओं के अभिगमकर्ताओं के रूप में उपयोग करना विफल हो जाएगा। लेकिन कुछ पुराने कंपाइलरों ने इसका समर्थन नहीं किया है, साथ ही कुछ IDE इस विकल्प को ओवरराइड करते हैं, और एक पुराना C ++ std सेट करते हैं।

यदि आप GCC का उपयोग कर रहे हैं, तो C + 11 को -std = c ++ 11 या -std = gnu11 के साथ सक्षम करें ।

खुश रहो!


1
आप लिखना भूल enum class Days { ...
मार्टिन हेनिंग्स

वास्तव में। इसे ठीक करना! धन्यवाद।
एलेक्स बर्थ

7

यह C ++ में काम नहीं करना चाहिए:

Days.Saturday

दिन एक गुंजाइश या वस्तु नहीं है जिसमें ऐसे सदस्य होते हैं जिन्हें आप डॉट ऑपरेटर के साथ एक्सेस कर सकते हैं। यह वाक्यविन्यास सिर्फ C # -ism है और C ++ में कानूनी नहीं है।

Microsoft ने C ++ एक्सटेंशन को लंबे समय तक बनाए रखा है जो आपको स्कोप ऑपरेटर का उपयोग करके पहचानकर्ताओं तक पहुंचने की अनुमति देता है:

enum E { A, B, C };

A;
E::B; // works with Microsoft's extension

लेकिन यह C ++ 11 से पहले गैर-मानक है। C ++ 03 में एक एनुम में घोषित किए गए पहचानकर्ता केवल उसी प्रकार के दायरे में मौजूद हैं, जैसे कि एनम टाइप।

A;
E::B; // error in C++03

C ++ 11 यह एनम पहचानकर्ताओं को एनम नाम के साथ अर्हता प्राप्त करने के लिए कानूनी बनाता है, और एनम वर्गों का भी परिचय देता है, जो पहचानकर्ताओं के लिए उन्हें आसपास के दायरे में रखने के बजाय एक नया स्कोप बनाते हैं।

A;
E::B; // legal in C++11

enum class F { A, B, C };

A; // error
F::B;

4

अफसोस की बात है कि एनम के तत्व 'वैश्विक' हैं। आप कर के उन्हें एक्सेस करें day = Saturday। इसका मतलब है कि आपके पास नहीं है enum A { a, b } ;और enum B { b, a } ;वे संघर्ष में हैं।


2
जब तक आप enum classC ++ 11 में उपयोग नहीं करते , वह है। इससे पहले, आपको डमी कक्षाएं बनाना होगा।
क्रिस

C ++ 11 नहीं जानते। मैं मान रहा हूं कि प्रश्न C ++ को संदर्भित करता है। हाँ, कक्षाओं या नाम स्थान का उपयोग करने की कोशिश करेंगे।
ग्रेजेगोर

@Grzegorz: मुझे लगता है कि क्रिस नए शुरू किए गए एनम वर्ग का जिक्र कर रहा है जो दृढ़ता से टाइप किए गए एनम प्रदान करता है।
रिका

@ होसेन: इसे इंगित करने के लिए धन्यवाद। मुझे अंक वर्ग का स्पष्टीकरण मिला है, और मुझे पता है कि क्रिस किस बारे में बात कर रहा था। बहुत बहुत धन्यवाद।
ग्रेजेगोर

@Grzegorz: मेरा अनादर करने का मतलब यह नहीं था, बस मुझे लगा कि मैं मदद कर सकता हूं, किसी भी संभावित गलतफहमी के लिए खेद है। फिर से आप अपने समय के लिए धन्यवाद और मेरी मदद कर रहे हैं;)
Rika

4

जबकि C ++ (C ++ 11 को छोड़कर) में दुश्मनी है, उनमें मान वैश्विक नामस्थान में "लीक" हैं।
यदि आप उन्हें लीक नहीं करना चाहते हैं (और एनम प्रकार का उपयोग करने की आवश्यकता नहीं है), तो निम्नलिखित पर विचार करें:

class EnumName {  
   public:   
      static int EnumVal1;  
      (more definitions)  
};  
EnumName::EnumVal1 = {value};  
if ([your value] == EnumName::EnumVal1)  ...

3

C ++ में Enums, आपके द्वारा दिए गए नामों से बने पूर्णांक की तरह हैं, जब आप अपने enum-values ​​घोषित करते हैं (यह केवल एक संकेत नहीं है कि यह कैसे काम करता है)।

लेकिन आपके कोड में दो त्रुटियां हैं:

  1. enumसभी निचले मामलों को पढ़ें
  2. आपको Days.शनिवार से पहले की आवश्यकता नहीं है ।
  3. यदि यह एनम एक वर्ग में घोषित किया गया है, तो उपयोग करें if (day == YourClass::Saturday){}

प्रारंभिक पोस्ट ( संशोधन 1 से संशोधन 2 ) के 16 मिनट बाद ओपी ने वर्तनी / मामला बदल दिया ।
पीटर मोर्टेनसेन

1

मुझे लगता है कि आपका मूल मुद्दा .इसके बजाय का उपयोग है:: , जो नाम स्थान का उपयोग करेगा।

प्रयत्न:

enum Days {Saturday, Sunday, Tuesday, Wednesday, Thursday, Friday};
Days day = Days::Saturday;
if(Days::Saturday == day)  // I like literals before variables :)
{
    std::cout<<"Ok its Saturday";
}

यह काम नहीं करता है: Days::अपने उदाहरण के रूप में गुंजाइश का उपयोग करने के लिए, आपको enum class Daysसी + 03 + माइक्रोसॉफ्ट एक्सटेंशन या सी ++ 11 के साथ गणना को परिभाषित करना होगा ।
फ्यूटल सेप

@ फ़ुटल, ऊपर बोरलैंड सी ++ बिल्डर के साथ भाग गया। C ++ का Flavour / Version प्रश्न में नहीं है।
जेम्स ओर्वेक

1
बोरलैंड C ++ बिल्डर का आपका संस्करण C ++ 11 या नए का उपयोग करना चाहिए। जीसीसी और बजना दोनों त्रुटि या चेतावनी देता है कि यदि आपके उदाहरण के साथ संकलित किया गया है -std=c++98या -std=c++03। क्लैंग काफी स्पष्ट है warning: use of enumeration in a nested name specifier is a C++11 extension:।
फ्यूटल सेप

1

यदि हम सख्त प्रकार की सुरक्षा और स्कोप्ड एनम चाहते हैं, तो enum classC ++ 11 में उपयोग करना अच्छा है।

यदि हमें C ++ 98 में काम करना था, तो हम स्कोप्ड एनम को सक्षम करने के लिए InitializeSahib, दी गई सलाह का उपयोग कर सकते हैं San

यदि हम भी सख्त प्रकार की सुरक्षा चाहते हैं, तो अनुसरण कोड कुछ की तरह लागू कर सकते हैं enum

#include <iostream>
class Color
{
public:
    static Color RED()
    {
        return Color(0);
    }
    static Color BLUE()
    {
        return Color(1);
    }
    bool operator==(const Color &rhs) const
    {
        return this->value == rhs.value;
    }
    bool operator!=(const Color &rhs) const
    {
        return !(*this == rhs);
    }

private:
    explicit Color(int value_) : value(value_) {}
    int value;
};

int main()
{
    Color color = Color::RED();
    if (color == Color::RED())
    {
        std::cout << "red" << std::endl;
    }
    return 0;
}

कोड को कक्षा के उदाहरण से पुस्तक में संशोधित किया जाता है प्रभावी C ++ 3: आइटम 18


-15

सबसे पहले, एनुम में 'ई', लोअर केस के रूप में 'ई' बनाएं।

दूसरा, 'Days.Saturday' में ड्रॉप टाइप नाम 'डेज'।

तीसरा ... अपने आप को एक अच्छी सी ++ पुस्तक खरीदें।


5
क्षमा करें, आपको ये सभी डाउन-वोट मिले (मेरा मतलब है, इसका जवाब इस प्रकार का है), लेकिन इसका मतलब यह नहीं है कि आपको 6 साल के लिए समुदाय छोड़ना होगा। वापस आओ और हमारे साथ आओ। आपके पास योगदान देने के लिए भी कुछ है। सहायक बनें। शेयर का ज्ञान।
गेब्रियल स्टेपल्स
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.