সি ++ এনামকে স্ট্রিংয়ে রূপান্তর করার কোনও সহজ উপায় আছে কি?


123

ধরুন আমাদের কিছু নামযুক্ত এনাম রয়েছে:

enum MyEnum {
      FOO,
      BAR = 0x50
};

আমি যার জন্য গুগল করেছি তা হ'ল একটি স্ক্রিপ্ট (যে কোনও ভাষা) যা আমার প্রকল্পের সমস্ত শিরোনাম স্ক্যান করে এবং এনাম প্রতি এক ফাংশন সহ একটি শিরোনাম উত্পন্ন করে।

char* enum_to_string(MyEnum t);

এবং এর মতো কিছু সহ একটি বাস্তবায়ন:

char* enum_to_string(MyEnum t){
      switch(t){
         case FOO:
            return "FOO";
         case BAR:
            return "BAR";
         default:
            return "INVALID ENUM";
      }
 }

গোটাচা সত্যই টাইপফিডযুক্ত এনামগুলি এবং নামবিহীন সি স্টাইলের এনামগুলির সাথে রয়েছে। কেউ কি এর জন্য কিছু জানে?

সম্পাদনা: উত্পন্ন ফাংশন ব্যতীত সমাধানটি আমার উত্সটি পরিবর্তন করবে না। এনামগুলি একটি এপিআইতে থাকে, সুতরাং এখন পর্যন্ত প্রস্তাবিত সমাধানগুলি ব্যবহার করা কেবল একটি বিকল্প নয়।


ম্যাক্রো ভিত্তিক কারখানা সম্পর্কে উত্তর stackoverflow.com/questions/147267/… এ স্থানান্তরিত হয়েছে - প্রশ্ন আপডেট হওয়ার পরে, এটি এখানে আর প্রাসঙ্গিক নয়।
সুমা

উত্তর:


48

আপনি জিসিসিএক্সএমএল পরীক্ষা করতে চাইতে পারেন ।

আপনার নমুনা কোডটিতে জিসিসিএক্সএমএল চালানো উত্পাদন করে:

<GCC_XML>
  <Namespace id="_1" name="::" members="_3 " mangled="_Z2::"/>
  <Namespace id="_2" name="std" context="_1" members="" mangled="_Z3std"/>
  <Enumeration id="_3" name="MyEnum" context="_1" location="f0:1" file="f0" line="1">
    <EnumValue name="FOO" init="0"/>
    <EnumValue name="BAR" init="80"/>
  </Enumeration>
  <File id="f0" name="my_enum.h"/>
</GCC_XML>

আপনি এনুমারেশন এবং এনামভ্যালু ট্যাগগুলি বের করতে এবং আপনার পছন্দসই কোড উত্পন্ন করতে পছন্দ করেন এমন কোনও ভাষা আপনি ব্যবহার করতে পারেন।


অসাধারণ! একটি সাধারণ অজগর স্ক্রিপ্ট সহ কবজ হিসাবে কাজ করেছিলেন। ধন্যবাদ।
এডু ফেলিপ

6
+1, জিসিসিএক্সএমএল দেখতে খুব সুন্দর দেখাচ্ছে! (যদিও আমি প্রাথমিকভাবে এটি এনামটি এনকোড করার জন্য উপরের ভার্বোস এক্সএমএল সিনট্যাক্সটি ব্যবহার করার পরামর্শ হিসাবে প্রথমে এটির ভুল পরামর্শ দিয়েছি - একটি সমাধান যা খুব বেশি পরিমাণে রেকর্ডিংয়ের প্রত্যাশা করে!)
j_random_hacker 12:49

1
অজগর স্ক্রিপ্ট পোস্ট করতে পারেন কোন পরিবর্তন?
ফিলিপওয়ে

74

এক্স-ম্যাক্রোজ হ'ল সেরা সমাধান। উদাহরণ:

#include <iostream>

enum Colours {
#   define X(a) a,
#   include "colours.def"
#   undef X
    ColoursCount
};

char const* const colours_str[] = {
#   define X(a) #a,
#   include "colours.def"
#   undef X
    0
};

std::ostream& operator<<(std::ostream& os, enum Colours c)
{
    if (c >= ColoursCount || c < 0) return os << "???";
    return os << colours_str[c];
}

int main()
{
    std::cout << Red << Blue << Green << Cyan << Yellow << Magenta << std::endl;
}

colours.def:

X(Red)
X(Green)
X(Blue)
X(Cyan)
X(Yellow)
X(Magenta)

যাইহোক, আমি সাধারণত নিম্নলিখিত পদ্ধতিটি পছন্দ করি, যাতে স্ট্রিংটি কিছুটা টুইট করা সম্ভব হয়।

#define X(a, b) a,
#define X(a, b) b,

X(Red, "red")
X(Green, "green")
// etc.

11
নিফটি, যদিও আমি অতিরিক্ত ফাইলটি পছন্দ করি না
রনি ব্রেন্ডেল

2
কেবলমাত্র নিশ্চিত হয়ে নিন যে আপনার বিল্ড প্রক্রিয়াটি প্রতিটি অন্তর্ভুক্ত ফাইলের আগে # একবারে (একবারে)
প্রিপেন্ড

24
আমি "সেরা" সমাধান সম্পর্কে নিশ্চিত নই!
অরবিট

2
এই সমাধানটি কোনও সুইচ কেস বা অ্যারে ভিত্তিক একের চেয়ে কেবল মাত্রাতিরিক্ত উচ্চতর, কারণ এটি নামগুলি নকল করে না, ফলে অঙ্কটি পরিবর্তন করা সহজ হয়।
জুলিয়েন গের্টল্ট

2
@ ikku100- এর বিষয়ে আপনি ভুল #define X(a, b) #b। এটি কেবল তখনই প্রয়োজন যখন সংজ্ঞাটি X(Red, red)উত্তরটির মতো দেখানো সংজ্ঞাটির চেয়ে X(Red, "red")
এইরূপটি দেখায়

43

@ হাইড্রো: অতিরিক্ত ফাইল ছাড়াই:

#define SOME_ENUM(DO) \
    DO(Foo) \
    DO(Bar) \
    DO(Baz)

#define MAKE_ENUM(VAR) VAR,
enum MetaSyntacticVariable{
    SOME_ENUM(MAKE_ENUM)
};

#define MAKE_STRINGS(VAR) #VAR,
const char* const MetaSyntacticVariableNames[] = {
    SOME_ENUM(MAKE_STRINGS)
};

আমি এই সমাধান ভালোবাসি। এটি আরও পরিষ্কার হবে যদি SOME_UNION এবং MAKE_UNION কে SOME_ENUM এবং MAKE_ENUM বলা হয় তবে।
ব্রুনো মার্টিনেজ

এটি একটি দুর্দান্ত সমাধান। আমার সাথে সর্বাধিক রক্ষণাবেক্ষণযোগ্য সি ++ রিসোর্স ম্যানেজার রয়েছে যা আমি এর সাথে ডিল করেছি।
ডুকারো

আমাকে এই সহজ সমাধানটির জন্য আপনাকে অবশ্যই ধন্যবাদ জানাতে হবে :-) - MetaSyntacticVariableNames[]একটি পদ্ধতি তৈরি করে কোনও শ্রেণির ঘোষণার অংশ হওয়ার জন্য আমি কিছুটা হলেও এটি সংশোধন করেছিstatic const char* getNameByEnum(MetaSyntacticVariable e) { /*code to return the static string*/ }
ডেকারডিকে

চমত্কার উত্তর! পুরো প্রক্রিয়াটিকে আরও সহজ করে দিয়ে আমি একক ম্যাক্রোতে MAKE_ENUM এবং MAKE_STRINGS গ্রুপ করে আরও সহজ করেছি l যদি কেউ আগ্রহী হয় তবে আমি এই থ্রেডটিতে এই কোডটিতে একটি উত্তর যুক্ত করেছি।
ফ্রাঙ্কোইস বার্ট্র্যান্ড

35

আমি যা করতে চাই তা হ'ল এন ক্রমের সাথে একই ক্রম এবং অবস্থানের নামের সাথে একটি অ্যারের তৈরি করা।

যেমন।

enum colours { red, green, blue };
const char *colour_names[] = { "red", "green", "blue" };

তারপরে আপনি যে জায়গাগুলিতে মানব-পঠনযোগ্য মান চান, সেখানে আপনি অ্যারে ব্যবহার করতে পারেন

colours mycolour = red;
cout << "the colour is" << colour_names[mycolour];

আপনি স্ট্রিংাইজিং অপারেটরের সাথে কিছুটা পরীক্ষা করতে পারেন (আপনার প্রিপ্রোসেসর রেফারেন্সে # দেখুন) যা কিছু আপনি চাইলে করবেন - যেমন:

#define printword(XX) cout << #XX;
printword(red);

স্টাডাউটে "লাল" মুদ্রণ করবে। দুর্ভাগ্যক্রমে এটি একটি চলকটির জন্য কাজ করবে না (যেমন আপনি ভেরিয়েবলটির নাম মুদ্রণ করে পাবেন)


শেষ ক্যাভিয়েট (কোনও ভেরিয়েবলের জন্য কাজ করবে না) হ'ল একটি বড় অপূর্ণতা, তবে যাইহোক +1।
chappjc

3
আপনি যদি এনাম এন্ট্রিগুলিতে বিশেষ সংখ্যাসূচক মান সেট না করেন কেবল তখনই কাজ করে।
kyb

11

আমার কাছে ম্যাক্রো ব্যবহারের জন্য অবিশ্বাস্যরকম সহজ যা এটি সম্পূর্ণ ডিআরওয়াই ফ্যাশনে করে। এটিতে ভের্যাডিক ম্যাক্রোগুলি এবং কিছু সাধারণ পার্সিং যাদু জড়িত। এখানে যায়:

#define AWESOME_MAKE_ENUM(name, ...) enum class name { __VA_ARGS__, __COUNT}; \
inline std::ostream& operator<<(std::ostream& os, name value) { \
std::string enumName = #name; \
std::string str = #__VA_ARGS__; \
int len = str.length(); \
std::vector<std::string> strings; \
std::ostringstream temp; \
for(int i = 0; i < len; i ++) { \
if(isspace(str[i])) continue; \
        else if(str[i] == ',') { \
        strings.push_back(temp.str()); \
        temp.str(std::string());\
        } \
        else temp<< str[i]; \
} \
strings.push_back(temp.str()); \
os << enumName << "::" << strings[static_cast<int>(value)]; \
return os;} 

আপনার কোডে এটি ব্যবহার করতে, কেবল করুন:

AWESOME_MAKE_ENUM(Animal,
    DOG,
    CAT,
    HORSE
);

1
দৃ idea়ভাবে টাইপ করা এনুম (এনাম ক্লাস) ব্যবহার করে ভাল ধারণা। এখানে একটি ডেমো: cpp.sh/4ife
chappjc

এটি বাহ্যিকভাবে সংজ্ঞায়িত গণনা / চিহ্ন সহ কাজ করে। উদাহরণস্বরূপ, ওএস সংজ্ঞায়িত বা লাইব্রেরি সংখ্যার ফাঁক দিয়ে সংজ্ঞাযুক্ত সংকেত?
জেসন হ্যারিসন

খুব সুন্দর, তবে ক্লাসের ভিতরে রাখলে সংকলন করে না (কেন আমি বুঝতে পারি না)।
সর্বদা

আমি এটি ভিএস ২০১৫ এ সংকলন করতে পারিনি। আমি একটি সতর্কতা এবং একটি ত্রুটি পেয়েছি: সতর্কতা: মাল্টি-লাইন মন্তব্য [-Wcomment] # নির্ধারণ করা হয়েছে MAKE_ENUM (নাম, ...) এনুম শ্রেণীর নাম { VA_ARGS , __COUNT} ত্রুটি: প্রোগ্রাম স্ট্রেডে স্ট্রে * # 'স্ট্রিং এনুমনেম = # নাম
ক্রেগ F

8

কিউটি এটি টানতে সক্ষম (মেটা অবজেক্ট সংকলককে ধন্যবাদ):

QNetworkReply::NetworkError error;

error = fetchStuff();

if (error != QNetworkReply::NoError) {

    QString errorValue;

    QMetaObject meta = QNetworkReply::staticMetaObject;

    for (int i=0; i < meta.enumeratorCount(); ++i) {

        QMetaEnum m = meta.enumerator(i);

        if (m.name() == QLatin1String("NetworkError")) {

            errorValue = QLatin1String(m.valueToKey(error));

            break;

        }

    }

    QMessageBox box(QMessageBox::Information, "Failed to fetch",

                "Fetching stuff failed with error '%1`").arg(errorValue),

                QMessageBox::Ok);

    box.exec();

    return 1;

}

Qt এ Q_OBJECT ম্যাক্রোযুক্ত প্রতিটি শ্রেণিতে স্বয়ংক্রিয়ভাবে QMetaObject টাইপের একটি স্ট্যাটিক সদস্য "স্ট্যাটিকমেটাওজেক্ট" থাকবে। তারপরে আপনি বৈশিষ্ট্য, সংকেত, স্লট এবং প্রকৃতপক্ষে এনামগুলির মতো দুর্দান্ত সব ধরণের জিনিস খুঁজে পেতে পারেন।

উৎস


7

এটি সি ++ 11 এ করা যেতে পারে

#include <map>
enum MyEnum { AA, BB, CC, DD };

static std::map< MyEnum, const char * > info = {
   {AA, "This is an apple"},
   {BB, "This is a book"},
   {CC, "This is a coffee"},
   {DD, "This is a door"}
};

void main()
{
    std::cout << info[AA] << endl
              << info[BB] << endl
              << info[CC] << endl
              << info[DD] << endl;
}

1
এটি ওপি-র প্রশ্নের উত্তর দেয় না: তিনি কোনও এনামের সদস্যের নাম স্ট্রিং হিসাবে ফিরিয়ে দেওয়ার জন্য কোনও ফাংশন স্বয়ংক্রিয়ভাবে তৈরি করার উপায় খুঁজছিলেন ।
স্পোকি

7

আমি আজই এই চাকাটি পুনরায় উদ্ভাবন করেছি এবং ভেবেছিলাম আমি এটি ভাগ করব।

এই প্রয়োগের ক্ষেত্রে কোডগুলিতে ধ্রুবককে সংজ্ঞায়িত করে এমন কোনও পরিবর্তন প্রয়োজন হয় না , যা গণনা বা #defineগুলি বা কোনও পূর্ণসংখ্যার সাথে রূপান্তরকারী অন্য কোনও জিনিস হতে পারে - আমার ক্ষেত্রে আমার অন্যান্য চিহ্নগুলির নিরিখে সংকেতগুলি সংজ্ঞায়িত করা হয়েছিল। এটি বিরল মানগুলির সাথেও ভাল কাজ করে। এটি সর্বদা সর্বদা প্রথমটি ফিরে আসার জন্য একই মানটির জন্য একাধিক নামকেও মঞ্জুরি দেয়। একমাত্র নেতিবাচকতাটি হ'ল এটির জন্য আপনার ধ্রুবকের একটি টেবিল তৈরি করা দরকার যা উদাহরণস্বরূপ নতুন যুক্ত হওয়ার সাথে সাথে এটি পুরানো হয়ে যেতে পারে।

struct IdAndName
{
   int          id;
   const char * name;
   bool operator<(const IdAndName &rhs) const { return id < rhs.id; }
};
#define ID_AND_NAME(x) { x, #x }

const char * IdToName(int id, IdAndName *table_begin, IdAndName *table_end)
{
   if ((table_end - table_begin) > 1 && table_begin[0].id > table_begin[1].id)
      std::stable_sort(table_begin, table_end);

   IdAndName searchee = { id, NULL };
   IdAndName *p = std::lower_bound(table_begin, table_end, searchee);
   return (p == table_end || p->id != id) ? NULL : p->name;
}

template<int N>
const char * IdToName(int id, IdAndName (&table)[N])
{
   return IdToName(id, &table[0], &table[N]);
}

আপনি এটি কীভাবে ব্যবহার করবেন তার একটি উদাহরণ:

static IdAndName WindowsErrorTable[] =
{
   ID_AND_NAME(INT_MAX),               // flag value to indicate unsorted table
   ID_AND_NAME(NO_ERROR),
   ID_AND_NAME(ERROR_INVALID_FUNCTION),
   ID_AND_NAME(ERROR_FILE_NOT_FOUND),
   ID_AND_NAME(ERROR_PATH_NOT_FOUND),
   ID_AND_NAME(ERROR_TOO_MANY_OPEN_FILES),
   ID_AND_NAME(ERROR_ACCESS_DENIED),
   ID_AND_NAME(ERROR_INVALID_HANDLE),
   ID_AND_NAME(ERROR_ARENA_TRASHED),
   ID_AND_NAME(ERROR_NOT_ENOUGH_MEMORY),
   ID_AND_NAME(ERROR_INVALID_BLOCK),
   ID_AND_NAME(ERROR_BAD_ENVIRONMENT),
   ID_AND_NAME(ERROR_BAD_FORMAT),
   ID_AND_NAME(ERROR_INVALID_ACCESS),
   ID_AND_NAME(ERROR_INVALID_DATA),
   ID_AND_NAME(ERROR_INVALID_DRIVE),
   ID_AND_NAME(ERROR_CURRENT_DIRECTORY),
   ID_AND_NAME(ERROR_NOT_SAME_DEVICE),
   ID_AND_NAME(ERROR_NO_MORE_FILES)
};

const char * error_name = IdToName(GetLastError(), WindowsErrorTable);

IdToNameফাংশন উপর নির্ভর std::lower_boundদ্রুত লুক-, যা টেবিল সাজানো করা প্রয়োজন হবে। যদি টেবিলের প্রথম দুটি এন্ট্রিগুলি অর্ডার থেকে বাইরে থাকে তবে ফাংশনটি এটি স্বয়ংক্রিয়ভাবে সাজবে।

সম্পাদনা: একটি মন্তব্য আমাকে একই নীতিটি ব্যবহার করার অন্য উপায় সম্পর্কে ভাবতে বাধ্য করেছে। একটি ম্যাক্রো একটি বড় switchবিবৃতি প্রজন্মকে সহজতর করে ।

#define ID_AND_NAME(x) case x: return #x

const char * WindowsErrorToName(int id)
{
    switch(id)
    {
        ID_AND_NAME(ERROR_INVALID_FUNCTION);
        ID_AND_NAME(ERROR_FILE_NOT_FOUND);
        ID_AND_NAME(ERROR_PATH_NOT_FOUND);
        ID_AND_NAME(ERROR_TOO_MANY_OPEN_FILES);
        ID_AND_NAME(ERROR_ACCESS_DENIED);
        ID_AND_NAME(ERROR_INVALID_HANDLE);
        ID_AND_NAME(ERROR_ARENA_TRASHED);
        ID_AND_NAME(ERROR_NOT_ENOUGH_MEMORY);
        ID_AND_NAME(ERROR_INVALID_BLOCK);
        ID_AND_NAME(ERROR_BAD_ENVIRONMENT);
        ID_AND_NAME(ERROR_BAD_FORMAT);
        ID_AND_NAME(ERROR_INVALID_ACCESS);
        ID_AND_NAME(ERROR_INVALID_DATA);
        ID_AND_NAME(ERROR_INVALID_DRIVE);
        ID_AND_NAME(ERROR_CURRENT_DIRECTORY);
        ID_AND_NAME(ERROR_NOT_SAME_DEVICE);
        ID_AND_NAME(ERROR_NO_MORE_FILES);
        default: return NULL;
    }
}

ভাল সমাধান। তবে আমার পক্ষে আমি পছন্দ করতাম switch and caseকারণ এটি সহজ এবং সহজে বোঝা যায়।
15:34

6
#define stringify( name ) # name

enum MyEnum {
    ENUMVAL1
};
...stuff...

stringify(EnumName::ENUMVAL1);  // Returns MyEnum::ENUMVAL1

এই পদ্ধতি সম্পর্কে আরও আলোচনা

নতুনদের জন্য প্রিপ্রসেসর নির্দেশিক কৌশল


4
আসলে এটি মোটামুটি অকেজো, যেহেতু স্ট্রিংফাই পদ্ধতিটি সংকলনের সময় এবং বেশ আক্ষরিক। আপনি যদি বলেন যে কোনও ভেরিয়েবলের মধ্যে এনাম টাইপ প্রশ্ন রয়েছে, ভেরিয়েবলটিকে স্ট্রাইফাই করার চেষ্টা করা আপনাকে কেবল ভেরিয়েবলের নাম দেবে, এনাম টাইপের নাম নয়।
srcspider

5

উপায় সংখ্যা দেখতে আকর্ষণীয়। আমি এখানে অনেক আগে ব্যবহার করেছি:

ফাইল myenummap.h এ:

#include <map>
#include <string>
enum test{ one, two, three, five=5, six, seven };
struct mymap : std::map<unsigned int, std::string>
{
  mymap()
  {
    this->operator[]( one ) = "ONE";
    this->operator[]( two ) = "TWO";
    this->operator[]( three ) = "THREE";
    this->operator[]( five ) = "FIVE";
    this->operator[]( six ) = "SIX";
    this->operator[]( seven ) = "SEVEN";
  };
  ~mymap(){};
};

main.cpp এ pp

#include "myenummap.h"

...
mymap nummap;
std::cout<< nummap[ one ] << std::endl;

এটি কনস্ট নয়, তবে এটি সুবিধাজনক।

সি ++ 11 বৈশিষ্ট্যগুলি ব্যবহার করে এমন অন্য উপায় এখানে। এটি কনস্ট্যান্ট, কোনও এসটিএল ধারক উত্তরাধিকার সূত্রে প্রাপ্ত নয় এবং এটি সামান্য পরিপাটি:

#include <vector>
#include <string>
#include <algorithm>
#include <iostream>

//These stay together and must be modified together
enum test{ one, two, three, five=5, six, seven };
std::string enum_to_str(test const& e)
{
    typedef std::pair<int,std::string> mapping;
    auto m = [](test const& e,std::string const& s){return mapping(static_cast<int>(e),s);}; 
    std::vector<mapping> const nummap = 
    { 
        m(one,"one"), 
        m(two,"two"), 
        m(three,"three"),
        m(five,"five"),
        m(six,"six"),
        m(seven,"seven"),
    };
    for(auto i  : nummap)
    {
        if(i.first==static_cast<int>(e))
        {
            return i.second;
        }
    }
    return "";
}

int main()
{
//  std::cout<< enum_to_str( 46 ) << std::endl; //compilation will fail
    std::cout<< "Invalid enum to string : [" << enum_to_str( test(46) ) << "]"<<std::endl; //returns an empty string
    std::cout<< "Enumval five to string : ["<< enum_to_str( five ) << "] "<< std::endl; //works
    return 0;
}

1
এটি পুরোপুরি আইনী। আমি সব সময় এটা।
জোনাথন গ্রেহল

ভাল সমাধান। এটি সি ++ সুতরাং stl মানচিত্র ব্যবহার করা ঠিক আছে।
অ্যাডাম ব্রাস

4
#include <stdarg.h>
#include <algorithm>
#include <string> 
#include <vector>
#include <sstream>
#include <map>

#define SMART_ENUM(EnumName, ...)                                   \
class EnumName                                                      \
{                                                                   \
private:                                                            \
    static std::map<int, std::string> nameMap;                      \
public:                                                             \
    enum {__VA_ARGS__};                                             \
private:                                                            \
    static std::map<int, std::string> initMap()                     \
    {                                                               \
        using namespace std;                                        \
                                                                    \
        int val = 0;                                                \
        string buf_1, buf_2, str = #__VA_ARGS__;                    \
        replace(str.begin(), str.end(), '=', ' ');                  \
        stringstream stream(str);                                   \
        vector<string> strings;                                     \
        while (getline(stream, buf_1, ','))                         \
            strings.push_back(buf_1);                               \
        map<int, string> tmp;                                       \
        for(vector<string>::iterator it = strings.begin();          \
                                               it != strings.end(); \
                                               ++it)                \
        {                                                           \
            buf_1.clear(); buf_2.clear();                           \
            stringstream localStream(*it);                          \
            localStream>> buf_1 >> buf_2;                           \
            if(buf_2.size() > 0)                                    \
                val = atoi(buf_2.c_str());                          \
            tmp[val++] = buf_1;                                     \
        }                                                           \
        return tmp;                                                 \
    }                                                               \
public:                                                             \
    static std::string toString(int aInt)                           \
    {                                                               \
        return nameMap[aInt];                                       \
    }                                                               \
};                                                                  \
std::map<int, std::string>                                          \
EnumName::nameMap = EnumName::initMap();

ব্যবহার:

SMART_ENUM(MyEnum, ONE=1, TWO, THREE, TEN=10, ELEVEN)
cout<<MyEnum::toString(MyEnum::TWO);
cout<<MyEnum::toString(10);

1
আমি আপনার এপিআই পছন্দ করি তবে দুর্ভাগ্যক্রমে আপনার স্মার্টইনাম আসলে একটি এনাম "টাইপ" তৈরি করে না। আপনি করতে পারবেন না MyEnum x = MyEnum::TWO;। এটি সমর্থন করার জন্য আমি আপনার ক্লাসের আমার সম্পাদনা পোস্ট করেছি।
লাকাটা

4

সুমার ম্যাক্রো সলিউশনটি দুর্দান্ত । যদিও আপনার দুটি আলাদা ম্যাক্রোর দরকার নেই। সি ++ উইল সুখে দু'বার শিরোনাম অন্তর্ভুক্ত করে। শুধু অন্তর্ভুক্ত গার্ড ছেড়ে দিন।

সুতরাং আপনি একটি foobar.h চাই ঠিক সংজ্ঞায়িত

ENUM(Foo, 1)
ENUM(Bar, 2)

এবং আপনি এটি এর মতো অন্তর্ভুক্ত করবেন:

#define ENUMFACTORY_ARGUMENT "foobar.h"
#include "enumfactory.h"

enumfactory.h 2 #include ENUMFACTORY_ARGUMENTটি করবে। প্রথম দফায়, এটি সুমার মতো ENUM প্রসারিত করে DECLARE_ENUM; দ্বিতীয় রাউন্ডে ENUM এর মতো কাজ করে DEFINE_ENUM

আপনি এনামফ্যাক্টরিওয়াল_আরজিমেণ্টের জন্য বিভিন্ন # সংজ্ঞায়িত যতক্ষণ পাস করেন ততক্ষণ আপনি এনামফ্যাক্টরি.কে একাধিকবার অন্তর্ভুক্ত করতে পারেন too


সুমা মনে হয় উত্তরটি এখানে সরিয়ে নিয়েছে । আপনি নিজের উত্তরে লিঙ্কটি অন্তর্ভুক্ত করতে চাইতে পারেন। আমি কেবলমাত্র সুযোগ পেয়ে মন্তব্যটি পেয়েছি এবং
বুদ্ধিমান সুমাস উত্তরটি এটির

3

মনে রাখবেন যে আপনার রূপান্তর ফাংশনটি আদর্শভাবে কনস্ট চর * ফেরত পাঠানো উচিত ।

যদি আপনি তাদের এনামগুলিকে তাদের পৃথক শিরোলেখ ফাইলগুলিতে রাখার সামর্থ্য রাখেন তবে আপনি ম্যাক্রোগুলির সাহায্যে এ জাতীয় কিছু করতে পারেন (ওহ, এটি কুরুচিপূর্ণ হবে):

#include "enum_def.h"
#include "colour.h"
#include "enum_conv.h"
#include "colour.h"

যেখানে enum_def.h রয়েছে:

#undef ENUM_START
#undef ENUM_ADD
#undef ENUM_END
#define ENUM_START(NAME) enum NAME {
#define ENUM_ADD(NAME, VALUE) NAME = VALUE,
#define ENUM_END };

এবং enum_conv.h এর রয়েছে:

#undef ENUM_START
#undef ENUM_ADD
#undef ENUM_END
#define ENUM_START(NAME) const char *##NAME##_to_string(NAME val) { switch (val) {
#define ENUM_ADD(NAME, VALUE) case NAME: return #NAME;
#define ENUM_END default: return "Invalid value"; } }

এবং অবশেষে, কলর হ'র রয়েছে:

ENUM_START(colour)
ENUM_ADD(red,   0xff0000)
ENUM_ADD(green, 0x00ff00)
ENUM_ADD(blue,  0x0000ff)
ENUM_END

এবং আপনি রূপান্তর ফাংশনটি এটি হিসাবে ব্যবহার করতে পারেন:

printf("%s", colour_to_string(colour::red));

এটি কুৎসিত, তবে এটি একমাত্র উপায় (প্রিপ্রোসেসর স্তরে) যা আপনাকে কেবল আপনার কোডের একক জায়গায় আপনার এনামটি সংজ্ঞায়িত করতে দেয়। এনামে পরিবর্তনের কারণে আপনার কোড ত্রুটিযুক্ত না। আপনার এনাম সংজ্ঞা এবং রূপান্তর ফাংশন সর্বদা সিঙ্কে থাকবে। তবে, আমি আবার বলছি, এটি কুৎসিত :)


3

আর একটি উত্তর: কিছু প্রসঙ্গে, কোনও সিএসভি, ওয়াইএএমএল, বা এক্সএমএল ফাইলের মতো একটি নন-কোড ফর্ম্যাটে আপনার অঙ্কটি সংজ্ঞায়িত করা এবং এরপরে সংজ্ঞা থেকে সি ++ গণনা কোড এবং টু-স্ট্রিং কোড উভয়ই জেনারেট করে তোলে। এই পদ্ধতির প্রয়োগ বা আপনার ব্যবহারিক প্রয়োগ নাও হতে পারে, তবে এটি মনে রাখা দরকার to


3

এটি @ ব্যবহারকারী 3360260 উত্তরের একটি পরিবর্তন। এটিতে নিম্নলিখিত নতুন বৈশিষ্ট্য রয়েছে

  • MyEnum fromString(const string&) সমর্থন
  • ভিজুয়ালস্টুডিও 2012 এর সাথে সংকলন করে
  • এনাম হ'ল একটি আসল পিওডি টাইপ (কেবলমাত্র কনস্ট্যান্ট ডিক্লারেশন নয়), সুতরাং আপনি এটিকে ভেরিয়েবলের জন্য নির্ধারণ করতে পারেন।
  • এনামের উপরে "ফোরচ" পুনরাবৃত্তির অনুমতি দেওয়ার জন্য সি ++ "রেঞ্জ" বৈশিষ্ট্য (ভেক্টরের আকারে) যুক্ত করা হয়েছে

ব্যবহার:

SMART_ENUM(MyEnum, ONE=1, TWO, THREE, TEN=10, ELEVEN)
MyEnum foo = MyEnum::TWO;
cout << MyEnum::toString(foo);  // static method
cout << foo.toString();         // member method
cout << MyEnum::toString(MyEnum::TWO);
cout << MyEnum::toString(10);
MyEnum foo = myEnum::fromString("TWO");

// C++11 iteration over all values
for( auto x : MyEnum::allValues() )
{
  cout << x.toString() << endl;
}

এখানে কোড

#define SMART_ENUM(EnumName, ...)                                   \
class EnumName                                                      \
{                                                                   \
public:                                                             \
    EnumName() : value(0) {}                                        \
    EnumName(int x) : value(x) {}                                   \
public:                                                             \
    enum {__VA_ARGS__};                                             \
private:                                                            \
    static void initMap(std::map<int, std::string>& tmp)                     \
    {                                                               \
        using namespace std;                                        \
                                                                    \
        int val = 0;                                                \
        string buf_1, buf_2, str = #__VA_ARGS__;                    \
        replace(str.begin(), str.end(), '=', ' ');                  \
        stringstream stream(str);                                   \
        vector<string> strings;                                     \
        while (getline(stream, buf_1, ','))                         \
            strings.push_back(buf_1);                               \
        for(vector<string>::iterator it = strings.begin();          \
                                                it != strings.end(); \
                                                ++it)                \
        {                                                           \
            buf_1.clear(); buf_2.clear();                           \
            stringstream localStream(*it);                          \
            localStream>> buf_1 >> buf_2;                           \
            if(buf_2.size() > 0)                                    \
                val = atoi(buf_2.c_str());                          \
            tmp[val++] = buf_1;                                     \
        }                                                           \
    }                                                               \
    int value;                                                      \
public:                                                             \
    operator int () const { return value; }                         \
    std::string toString(void) const {                              \
            return toString(value);                                 \
    }                                                               \
    static std::string toString(int aInt)                           \
    {                                                               \
        return nameMap()[aInt];                                     \
    }                                                               \
    static EnumName fromString(const std::string& s)                \
    {                                                               \
        auto it = find_if(nameMap().begin(), nameMap().end(), [s](const std::pair<int,std::string>& p) { \
            return p.second == s;                                   \
        });                                                         \
        if (it == nameMap().end()) {                                \
        /*value not found*/                                         \
            throw EnumName::Exception();                            \
        } else {                                                    \
            return EnumName(it->first);                             \
        }                                                           \
    }                                                               \
    class Exception : public std::exception {};                     \
    static std::map<int,std::string>& nameMap() {                   \
      static std::map<int,std::string> nameMap0;                    \
      if (nameMap0.size() ==0) initMap(nameMap0);                   \
      return nameMap0;                                              \
    }                                                               \
    static std::vector<EnumName> allValues() {                      \
      std::vector<EnumName> x{ __VA_ARGS__ };                       \
      return x;                                                     \
    }                                                               \
    bool operator<(const EnumName a) const { return (int)*this < (int)a; } \
};         

দ্রষ্টব্য যে স্ট্রিং-এ রূপান্তরটি একটি দ্রুত লুক আছে, অন্যদিকে স্ট্রিং থেকে রূপান্তরটি একটি ধীর রৈখিক অনুসন্ধান। তবে স্ট্রিংগুলি যে কোনও উপায়েই ব্যয়বহুল (এবং সম্পর্কিত ফাইল আইও), আমি কোনও বিম্যাপটি অনুকূলিতকরণ বা ব্যবহারের প্রয়োজন বোধ করি নি।


আপনার এবং ব্যবহারকারী 3360260 এর একটি ভাল সমাধান রয়েছে। পরিবর্তে মাল্টিম্যাপ হচ্ছে না কেন?
ভিনসেন্ট

3

এখানে একটি ফাইলের সমাধান (@ মার্সিনের মার্জিত উত্তরের ভিত্তিতে:

#include <iostream>

#define ENUM_TXT \
X(Red) \
X(Green) \
X(Blue) \
X(Cyan) \
X(Yellow) \
X(Magenta) \

enum Colours {
#   define X(a) a,
ENUM_TXT
#   undef X
    ColoursCount
};

char const* const colours_str[] = {
#   define X(a) #a,
ENUM_TXT
#   undef X
    0
};

std::ostream& operator<<(std::ostream& os, enum Colours c)
{
    if (c >= ColoursCount || c < 0) return os << "???";
    return os << colours_str[c] << std::endl;
}

int main()
{
    std::cout << Red << Blue << Green << Cyan << Yellow << Magenta << std::endl;
}

2

আমি ম্যাক্রোগুলি দ্বারা উত্পাদিত পৃথক পাশাপাশি পাশের এনাম র‌্যাপার ক্লাসগুলির সাথে এটি করি। বিভিন্ন সুবিধা রয়েছে:

  • আমি যে সংজ্ঞাগুলি সংজ্ঞায়িত করি না তাদের জন্য এগুলি উত্পন্ন করতে পারে (যেমন: ওএস প্ল্যাটফর্মের শিরোনাম এনামগুলি)
  • মোড়ক ক্লাসে পরিসীমা পরীক্ষা করা অন্তর্ভুক্ত করতে পারে
  • বিট ফিল্ড এনামগুলির সাথে "স্মার্ট" ফর্ম্যাটিং করতে পারে

অবশ্যই খারাপ দিকটি হ'ল আমাকে ফর্ম্যাটর ক্লাসগুলিতে এনাম মানগুলি নকল করতে হবে এবং সেগুলি উত্পন্ন করার জন্য আমার কাছে কোনও স্ক্রিপ্ট নেই। এটি বাদে যদিও এটি বেশ ভালভাবে কাজ করছে বলে মনে হয়।

এখানে আমার কোডবেস থেকে এনামের উদাহরণ রয়েছে, সমস্ত কাঠামো কোড সান করে যা ম্যাক্রোগুলি এবং টেম্পলেটগুলি প্রয়োগ করে, তবে আপনি এই ধারণাটি পেতে পারেন:

enum EHelpLocation
{
    HELP_LOCATION_UNKNOWN   = 0, 
    HELP_LOCAL_FILE         = 1, 
    HELP_HTML_ONLINE        = 2, 
};
class CEnumFormatter_EHelpLocation : public CEnumDefaultFormatter< EHelpLocation >
{
public:
    static inline CString FormatEnum( EHelpLocation eValue )
    {
        switch ( eValue )
        {
            ON_CASE_VALUE_RETURN_STRING_OF_VALUE( HELP_LOCATION_UNKNOWN );
            ON_CASE_VALUE_RETURN_STRING_OF_VALUE( HELP_LOCAL_FILE );
            ON_CASE_VALUE_RETURN_STRING_OF_VALUE( HELP_HTML_ONLINE );
        default:
            return FormatAsNumber( eValue );
        }
    }
};
DECLARE_RANGE_CHECK_CLASS( EHelpLocation, CRangeInfoSequential< HELP_HTML_ONLINE > );
typedef ESmartEnum< EHelpLocation, HELP_LOCATION_UNKNOWN, CEnumFormatter_EHelpLocation, CRangeInfo_EHelpLocation > SEHelpLocation;

ধারণাটি তখন EHelpLocation ব্যবহারের পরিবর্তে হয়, আপনি SEHelpLocation ব্যবহার করেন; সবকিছু একই রকম হয় তবে আপনি এনাম ভেরিয়েবলের মধ্যে পরিসীমা পরীক্ষা এবং একটি 'ফর্ম্যাট ()' পদ্ধতি পান। আপনার যদি স্ট্যান্ড-একা মান বিন্যাস করতে হয় তবে আপনি CEnumFormatter_EHelpLocation :: FormatEnum (...) ব্যবহার করতে পারেন।

আশা করি এটি সহায়ক। আমি বুঝতে পেরেছি যে এটি অন্য শ্রেণীর উত্পন্ন করার জন্য কোনও স্ক্রিপ্ট সম্পর্কে মূল প্রশ্নটিও সম্বোধন করে না, তবে আমি আশা করি কাঠামোটি একই সমস্যাটি সমাধান করার চেষ্টা করতে বা এমন স্ক্রিপ্ট লিখতে কাউকে সহায়তা করে।


2

এটি অপ্রকাশিত সফ্টওয়্যার তবে মনে হচ্ছে ফ্রাঙ্ক লাবের BOOST_ENUM বিলটি ফিট করতে পারে। আমি এটির যে অংশটি পছন্দ করি তা হ'ল আপনি এমন একটি শ্রেণীর আওতায় একটি এনামকে সংজ্ঞায়িত করতে পারেন যা ম্যাক্রো ভিত্তিক বেশিরভাগ এনাম সাধারণত আপনাকে না দেয়। এটি বুস্ট ভল্টে অবস্থিত: http://www.boostpro.com/vault/index.php?action=downloadfile&filename=enum_rev4.6.zip&directory=& 2006 এর পরে এটি কোনও উন্নয়ন দেখেনি তাই আমি করি না নতুন বুস্ট রিলিজের সাথে এটি কতটা সংকলন করে তা জানুন। ব্যবহারের উদাহরণের জন্য libs / পরীক্ষার অধীনে দেখুন।


2

এটিই বুস্টের সাথে আমার সমাধান ছিল:

#include <boost/preprocessor.hpp>

#define X_STR_ENUM_TOSTRING_CASE(r, data, elem)                                 \
    case elem : return BOOST_PP_STRINGIZE(elem);

#define X_ENUM_STR_TOENUM_IF(r, data, elem)                                     \
    else if(data == BOOST_PP_STRINGIZE(elem)) return elem;

#define STR_ENUM(name, enumerators)                                             \
    enum name {                                                                 \
        BOOST_PP_SEQ_ENUM(enumerators)                                          \
    };                                                                          \
                                                                                \
    inline const QString enumToStr(name v)                                      \
    {                                                                           \
        switch (v)                                                              \
        {                                                                       \
            BOOST_PP_SEQ_FOR_EACH(                                              \
                X_STR_ENUM_TOSTRING_CASE,                                       \
                name,                                                           \
                enumerators                                                     \
            )                                                                   \
                                                                                \
            default:                                                            \
                return "[Unknown " BOOST_PP_STRINGIZE(name) "]";                \
        }                                                                       \
    }                                                                           \
                                                                                \
    template <typename T>                                                       \
    inline const T strToEnum(QString v);                                        \
                                                                                \
    template <>                                                                 \
    inline const name strToEnum(QString v)                                      \
    {                                                                           \
        if(v=="")                                                               \
            throw std::runtime_error("Empty enum value");                       \
                                                                                \
        BOOST_PP_SEQ_FOR_EACH(                                                  \
            X_ENUM_STR_TOENUM_IF,                                               \
            v,                                                                  \
            enumerators                                                         \
        )                                                                       \
                                                                                \
        else                                                                    \
            throw std::runtime_error(                                           \
                        QString("[Unknown value %1 for enum %2]")               \
                            .arg(v)                                             \
                            .arg(BOOST_PP_STRINGIZE(name))                      \
                                .toStdString().c_str());                        \
    }

এনাম তৈরি করতে, ঘোষণা করুন:

STR_ENUM
(
    SERVICE_RELOAD,
        (reload_log)
        (reload_settings)
        (reload_qxml_server)
)

রূপান্তরগুলির জন্য:

SERVICE_RELOAD serviceReloadEnum = strToEnum<SERVICE_RELOAD>("reload_log");
QString serviceReloadStr = enumToStr(reload_log);

2

কেউ যদি এটির কাজে লাগে সে ক্ষেত্রে এটি পোস্ট করতে চাই।

আমার ক্ষেত্রে, আমি কেবল একটি একক ফাইল থেকে একক সি ++ 11 এনাম তৈরি ToString()এবং FromString()ফাংশন করতে পারি .hpp

আমি একটি পাইথন স্ক্রিপ্ট লিখেছিলাম যা এনাম আইটেমগুলি সমন্বিত শিরোলেখ ফাইলটিকে পার্স করে এবং একটি নতুন .cppফাইলে ফাংশন উত্পন্ন করে ।

আপনার সাথে CMakeLists.txt মধ্যে এই স্ক্রিপ্টের যোগ করতে পারেন execute_process , অথবা ভিসুয়াল স্টুডিও কোনো প্রি-বিল্ড ঘটনা হিসাবে। .cppফাইলটি স্বয়ংক্রিয়ভাবে নিজে প্রতিটি সময় একটি নতুন enum আইটেমটি যোগ করা হয় আপডেট করার জন্য প্রয়োজন ছাড়াই তৈরি করা হবে।

generate_enum_strings.py

# This script is used to generate strings from C++ enums

import re
import sys
import os

fileName = sys.argv[1]
enumName = os.path.basename(os.path.splitext(fileName)[0])

with open(fileName, 'r') as f:
    content = f.read().replace('\n', '')

searchResult = re.search('enum(.*)\{(.*?)\};', content)
tokens = searchResult.group(2)
tokens = tokens.split(',')
tokens = map(str.strip, tokens)
tokens = map(lambda token: re.search('([a-zA-Z0-9_]*)', token).group(1), tokens)

textOut = ''
textOut += '\n#include "' + enumName + '.hpp"\n\n'
textOut += 'namespace myns\n'
textOut += '{\n'
textOut += '    std::string ToString(ErrorCode errorCode)\n'
textOut += '    {\n'
textOut += '        switch (errorCode)\n'
textOut += '        {\n'

for token in tokens:
    textOut += '        case ' + enumName + '::' + token + ':\n'
    textOut += '            return "' + token + '";\n'

textOut += '        default:\n'
textOut += '            return "Last";\n'
textOut += '        }\n'
textOut += '    }\n'
textOut += '\n'
textOut += '    ' + enumName + ' FromString(const std::string &errorCode)\n'
textOut += '    {\n'
textOut += '        if ("' + tokens[0] + '" == errorCode)\n'
textOut += '        {\n'
textOut += '            return ' + enumName + '::' + tokens[0] + ';\n'
textOut += '        }\n'

for token in tokens[1:]:
    textOut += '        else if("' + token + '" == errorCode)\n'
    textOut += '        {\n'
    textOut += '            return ' + enumName + '::' + token + ';\n'
    textOut += '        }\n'

textOut += '\n'
textOut += '        return ' + enumName + '::Last;\n'
textOut += '    }\n'
textOut += '}\n'

fileOut = open(enumName + '.cpp', 'w')
fileOut.write(textOut)

উদাহরণ:

ErrorCode.hpp

#pragma once

#include <string>
#include <cstdint>

namespace myns
{
    enum class ErrorCode : uint32_t
    {
        OK = 0,
        OutOfSpace,
        ConnectionFailure,
        InvalidJson,
        DatabaseFailure,
        HttpError,
        FileSystemError,
        FailedToEncrypt,
        FailedToDecrypt,
        EndOfFile,
        FailedToOpenFileForRead,
        FailedToOpenFileForWrite,
        FailedToLaunchProcess,

        Last
    };

    std::string ToString(ErrorCode errorCode);
    ErrorCode FromString(const std::string &errorCode);
}

চালান python generate_enum_strings.py ErrorCode.hpp

ফলাফল:

ErrorCode.cpp

#include "ErrorCode.hpp"

namespace myns
{
    std::string ToString(ErrorCode errorCode)
    {
        switch (errorCode)
        {
        case ErrorCode::OK:
            return "OK";
        case ErrorCode::OutOfSpace:
            return "OutOfSpace";
        case ErrorCode::ConnectionFailure:
            return "ConnectionFailure";
        case ErrorCode::InvalidJson:
            return "InvalidJson";
        case ErrorCode::DatabaseFailure:
            return "DatabaseFailure";
        case ErrorCode::HttpError:
            return "HttpError";
        case ErrorCode::FileSystemError:
            return "FileSystemError";
        case ErrorCode::FailedToEncrypt:
            return "FailedToEncrypt";
        case ErrorCode::FailedToDecrypt:
            return "FailedToDecrypt";
        case ErrorCode::EndOfFile:
            return "EndOfFile";
        case ErrorCode::FailedToOpenFileForRead:
            return "FailedToOpenFileForRead";
        case ErrorCode::FailedToOpenFileForWrite:
            return "FailedToOpenFileForWrite";
        case ErrorCode::FailedToLaunchProcess:
            return "FailedToLaunchProcess";
        case ErrorCode::Last:
            return "Last";
        default:
            return "Last";
        }
    }

    ErrorCode FromString(const std::string &errorCode)
    {
        if ("OK" == errorCode)
        {
            return ErrorCode::OK;
        }
        else if("OutOfSpace" == errorCode)
        {
            return ErrorCode::OutOfSpace;
        }
        else if("ConnectionFailure" == errorCode)
        {
            return ErrorCode::ConnectionFailure;
        }
        else if("InvalidJson" == errorCode)
        {
            return ErrorCode::InvalidJson;
        }
        else if("DatabaseFailure" == errorCode)
        {
            return ErrorCode::DatabaseFailure;
        }
        else if("HttpError" == errorCode)
        {
            return ErrorCode::HttpError;
        }
        else if("FileSystemError" == errorCode)
        {
            return ErrorCode::FileSystemError;
        }
        else if("FailedToEncrypt" == errorCode)
        {
            return ErrorCode::FailedToEncrypt;
        }
        else if("FailedToDecrypt" == errorCode)
        {
            return ErrorCode::FailedToDecrypt;
        }
        else if("EndOfFile" == errorCode)
        {
            return ErrorCode::EndOfFile;
        }
        else if("FailedToOpenFileForRead" == errorCode)
        {
            return ErrorCode::FailedToOpenFileForRead;
        }
        else if("FailedToOpenFileForWrite" == errorCode)
        {
            return ErrorCode::FailedToOpenFileForWrite;
        }
        else if("FailedToLaunchProcess" == errorCode)
        {
            return ErrorCode::FailedToLaunchProcess;
        }
        else if("Last" == errorCode)
        {
            return ErrorCode::Last;
        }

        return ErrorCode::Last;
    }
}

1
এখানে একটি অনলাইন জেনারেটর রয়েছে: th-thielemann.de/tools/cpp-enum-to-string.html
Th। Thielemann

2

জ্যাস্পার বেকার্সের দুর্দান্ত উত্তরে আরও সরলতা যুক্ত করা :

একবার সেট আপ করুন:

#define MAKE_ENUM(VAR) VAR,
#define MAKE_STRINGS(VAR) #VAR,
#define MAKE_ENUM_AND_STRINGS(source, enumName, enumStringName) \
    enum enumName { \
    source(MAKE_ENUM) \
    };\
const char* const enumStringName[] = { \
    source(MAKE_STRINGS) \
    };

তারপরে, ব্যবহারের জন্য:

#define SOME_ENUM(DO) \
    DO(Foo) \
    DO(Bar) \
    DO(Baz)
...
MAKE_ENUM_AND_STRINGS(SOME_ENUM, someEnum, someEnumNames)

2

আপনি পন্ডারের মতো প্রতিবিম্ব গ্রন্থাগার ব্যবহার করতে পারেন । আপনি এনামগুলিকে নিবন্ধভুক্ত করুন এবং তারপরে আপনি এপিআই দিয়ে এগুলি পিছনে রূপান্তর করতে পারবেন।

enum class MyEnum
{
    Zero = 0,
    One  = 1,
    Two  = 2
};

ponder::Enum::declare<MyEnum>()
    .value("Zero", MyEnum::Zero)
    .value("One",  MyEnum::One)
    .value("Two",  MyEnum::Two);

ponder::EnumObject zero(MyEnum::Zero);

zero.name(); // -> "Zero"

1

উত্তর 0 সহ একটি সমস্যা হ'ল এনাম বাইনারি মানগুলি 0 থেকে শুরু হয় না এবং প্রয়োজনীয়ভাবে সামঞ্জস্য হয় না।

আমার যখন এটির প্রয়োজন হয়, আমি সাধারণত:

  • আমার উত্স মধ্যে এনাম সংজ্ঞা টানুন
  • শুধু নাম পেতে এটি সম্পাদনা করুন
  • প্রশ্নটিতে কেস ক্লজে নাম পরিবর্তন করতে একটি ম্যাক্রো করুন, যদিও সাধারণত এক লাইনে থাকে: কেস ফু: রিটার্ন "ফু";
  • এটিকে আইনী করার জন্য স্যুইচ, ডিফল্ট এবং অন্যান্য সিনট্যাক্স যুক্ত করুন

1

নিম্নলিখিত রুবি স্ক্রিপ্টটি শিরোনামগুলি পার্স করার চেষ্টা করে এবং মূল শিরোনামের পাশাপাশি প্রয়োজনীয় উত্সগুলি বিল্ট করে।

#! /usr/bin/env ruby

# Let's "parse" the headers
# Note that using a regular expression is rather fragile
# and may break on some inputs

GLOBS = [
  "toto/*.h",
  "tutu/*.h",
  "tutu/*.hxx"
]

enums = {}
GLOBS.each { |glob|
  Dir[glob].each { |header|
    enums[header] = File.open(header, 'rb') { |f|
      f.read
    }.scan(/enum\s+(\w+)\s+\{\s*([^}]+?)\s*\}/m).collect { |enum_name, enum_key_and_values|
      [
        enum_name, enum_key_and_values.split(/\s*,\s*/).collect { |enum_key_and_value|
          enum_key_and_value.split(/\s*=\s*/).first
        }
      ]
    }
  }
}


# Now we build a .h and .cpp alongside the parsed headers
# using the template engine provided with ruby
require 'erb'

template_h = ERB.new <<-EOS
#ifndef <%= enum_name %>_to_string_h_
#define <%= enum_name %>_to_string_h_ 1

#include "<%= header %>"
char* enum_to_string(<%= enum_name %> e);

#endif
EOS

template_cpp = ERB.new <<-EOS
#include "<%= enum_name %>_to_string.h"

char* enum_to_string(<%= enum_name %> e)
{
  switch (e)
  {<% enum_keys.each do |enum_key| %>
    case <%= enum_key %>: return "<%= enum_key %>";<% end %>
    default: return "INVALID <%= enum_name %> VALUE";
  }
}
EOS

enums.each { |header, enum_name_and_keys|
  enum_name_and_keys.each { |enum_name, enum_keys|
    File.open("#{File.dirname(header)}/#{enum_name}_to_string.h", 'wb') { |built_h|
      built_h.write(template_h.result(binding))
    }

    File.open("#{File.dirname(header)}/#{enum_name}_to_string.cpp", 'wb') { |built_cpp|
      built_cpp.write(template_cpp.result(binding))
    }
  }
}

নিয়মিত এক্সপ্রেশন ব্যবহার করে এই "পার্সার "টিকে বেশ ভঙ্গুর করে তোলে, এটি আপনার নির্দিষ্ট শিরোনামকে গ্রেফতার করতে সক্ষম নাও হতে পারে।

ধরা যাক আপনার একটি শিরোনামের টোটো / আহ আছে, মাইইনাম এবং মাইএনুম 2 এনামগুলির সংজ্ঞা রয়েছে। স্ক্রিপ্টটি তৈরি করবে:

toto/MyEnum_to_string.h
toto/MyEnum_to_string.cpp
toto/MyEnum2_to_string.h
toto/MyEnum2_to_string.cpp

আরও দৃ solutions় সমাধানগুলি হ'ল:

  • এনোম এবং তাদের ক্রিয়াকলাপগুলি অন্য উত্স থেকে সংজ্ঞায়িত করে সমস্ত উত্স তৈরি করুন। এর অর্থ আপনি আপনার এনএমএসকে একটি এক্সএমএল / ওয়াইএমএল / যে কোনও ফাইলে সি / সি ++ এর তুলনায় পার্স করা সহজ easier
  • সত্যিকারের সংকলক যেমন অ্যাডির পরামর্শ দেওয়া ব্যবহার করুন।
  • টেমপ্লেটগুলি ছাড়াই বা ছাড়াই প্রিপ্রেসেসর ম্যাক্রোগুলি ব্যবহার করুন।

0

এটি সম্পন্ন করার একমাত্র উপায় (স্ট্রিংয়ের একটি অ্যারেও কাজ করতে পারে)।

সমস্যাটি হচ্ছে, একবার একটি সি প্রোগ্রাম সংকলিত হয়ে গেলে এনামের বাইনারি মানটি সমস্ত ব্যবহৃত হয় এবং নামটি চলে যায়।


0

এনামগুলিকে স্ট্রিংয়ে রূপান্তর করতে আমি এখানে লিখেছি একটি সি এল এলই প্রোগ্রাম। এটি ব্যবহার করা সহজ, এবং এটি সম্পন্ন করতে প্রায় 5 সেকেন্ড সময় লাগে (প্রোগ্রামটি অন্তর্ভুক্ত ডিরেক্টরিটিতে সিডির সময় সহ, তারপর এটি চালান, এটি এনামযুক্ত ফাইলটি পাস করে)।

এখানে ডাউনলোড করুন: http://www.mediafire.com/?nttignoozzz

এটি নিয়ে এখানে আলোচনার বিষয়: http://cboard.cprogramming.com/projects-job-rec بھرten / 127488-free-program-im-sharing-convertenumtostrings.html

কীভাবে এটি ব্যবহার করবেন তার বিবরণ পেতে প্রোগ্রামটি "--help" যুক্তি দিয়ে চালান।


আপনি দয়া করে এটি কোথাও কোনও সংগ্রহস্থল (গিথুব, গুগল কোড বা বিটবাকেট) এ রেখে মিডিয়াফায়ারের পরিবর্তে লিঙ্কটি এখানে পোস্ট করতে পারেন? আমি এটি বুঝতে আগ্রহী লোকেদের সহায়তা করব :)
এডু ফিলিপ

0

এত দিন আগে আমি কিউকমবক্সে এনামগুলিকে সঠিকভাবে প্রদর্শন করার জন্য এবং এক বিবৃতি হিসাবে এনাম এবং স্ট্রিং উপস্থাপনার সংজ্ঞা রাখতে কিছু কৌশল তৈরি করেছি

#pragma once
#include <boost/unordered_map.hpp>

namespace enumeration
{

   struct enumerator_base : boost::noncopyable
   {
      typedef
         boost::unordered_map<int, std::wstring>
         kv_storage_t;
      typedef
         kv_storage_t::value_type
         kv_type;
      kv_storage_t const & kv() const
      {
         return storage_;
      }

      LPCWSTR name(int i) const
      {
         kv_storage_t::const_iterator it = storage_.find(i);
         if(it != storage_.end())
            return it->second.c_str();
         return L"empty";
      }

   protected:
      kv_storage_t storage_;
   };

   template<class T>
   struct enumerator;

   template<class D>
   struct enum_singleton : enumerator_base
   {
      static enumerator_base const & instance()
      {
         static D inst;
         return inst;
      }
   };
}

#define QENUM_ENTRY(K, V, N)  K, N storage_.insert(std::make_pair((int)K, V));

#define QBEGIN_ENUM(NAME, C)   \
enum NAME                     \
{                             \
   C                          \
}                             \
};                            \
}                             \

#define QEND_ENUM(NAME) \
};                     \
namespace enumeration  \
{                      \
template<>             \
struct enumerator<NAME>\
   : enum_singleton< enumerator<NAME> >\
{                      \
   enumerator()        \
   {

//usage
/*
QBEGIN_ENUM(test_t,
   QENUM_ENTRY(test_entry_1, L"number uno",
   QENUM_ENTRY(test_entry_2, L"number dos",
   QENUM_ENTRY(test_entry_3, L"number tres",
QEND_ENUM(test_t)))))
*/

এখন আপনি enumeration::enum_singleton<your_enum>::instance()এনামগুলিকে স্ট্রিংয়ে রূপান্তর করতে সক্ষম হয়েছেন। আপনি যদি এর সাথে প্রতিস্থাপন kv_storage_tকরেন boost::bimap, আপনি পশ্চাদপদ রূপান্তর করতেও সক্ষম হবেন। রূপান্তরকারীের জন্য সাধারণ বেস শ্রেণিটি এটি কিউটি অবজেক্টে সংরক্ষণের জন্য চালু করা হয়েছিল, কারণ Qt অবজেক্টগুলি টেম্পলেট হতে পারে না

পূর্বের উপস্থিতি


0

বৈকল্পিক হিসাবে, সরল lib> http://codeproject.com/Articles/42035/Enum-to-String-and-Vice-Versa-in-C ব্যবহার করুন

কোডে

#include <EnumString.h>

enum FORM {
    F_NONE = 0,
    F_BOX,
    F_CUBE,
    F_SPHERE,
};

লাইন যুক্ত করুন

Begin_Enum_String( FORM )
{
    Enum_String( F_NONE );
    Enum_String( F_BOX );
    Enum_String( F_CUBE );
    Enum_String( F_SPHERE );
}
End_Enum_String;

সূক্ষ্ম কাজ করুন, যদি এনামের মানগুলি প্রজাতন্ত্রিক না হয়

ব্যবহারের উদাহরণ

enum FORM f = ...
const std::string& str = EnumString< FORM >::From( f );

এবং বিপরীতভাবে

assert( EnumString< FORM >::To( f, str ) );

0

এখানে << এবং >> স্ট্রিম অপারেটরগুলি কেবলমাত্র এক লাইনের ম্যাক্রো কমান্ড দিয়ে স্বয়ংক্রিয়ভাবে এনামে নেওয়ার চেষ্টা করা হচ্ছে ...

সজ্ঞা:

#include <string>
#include <iostream>
#include <stdexcept>
#include <algorithm>
#include <iterator>
#include <sstream>
#include <vector>

#define MAKE_STRING(str, ...) #str, MAKE_STRING1_(__VA_ARGS__)
#define MAKE_STRING1_(str, ...) #str, MAKE_STRING2_(__VA_ARGS__)
#define MAKE_STRING2_(str, ...) #str, MAKE_STRING3_(__VA_ARGS__)
#define MAKE_STRING3_(str, ...) #str, MAKE_STRING4_(__VA_ARGS__)
#define MAKE_STRING4_(str, ...) #str, MAKE_STRING5_(__VA_ARGS__)
#define MAKE_STRING5_(str, ...) #str, MAKE_STRING6_(__VA_ARGS__)
#define MAKE_STRING6_(str, ...) #str, MAKE_STRING7_(__VA_ARGS__)
#define MAKE_STRING7_(str, ...) #str, MAKE_STRING8_(__VA_ARGS__)
#define MAKE_STRING8_(str, ...) #str, MAKE_STRING9_(__VA_ARGS__)
#define MAKE_STRING9_(str, ...) #str, MAKE_STRING10_(__VA_ARGS__)
#define MAKE_STRING10_(str) #str

#define MAKE_ENUM(name, ...) MAKE_ENUM_(, name, __VA_ARGS__)
#define MAKE_CLASS_ENUM(name, ...) MAKE_ENUM_(friend, name, __VA_ARGS__)

#define MAKE_ENUM_(attribute, name, ...) name { __VA_ARGS__ }; \
    attribute std::istream& operator>>(std::istream& is, name& e) { \
        const char* name##Str[] = { MAKE_STRING(__VA_ARGS__) }; \
        std::string str; \
        std::istream& r = is >> str; \
        const size_t len = sizeof(name##Str)/sizeof(name##Str[0]); \
        const std::vector<std::string> enumStr(name##Str, name##Str + len); \
        const std::vector<std::string>::const_iterator it = std::find(enumStr.begin(), enumStr.end(), str); \
        if (it != enumStr.end())\
            e = name(it - enumStr.begin()); \
        else \
            throw std::runtime_error("Value \"" + str + "\" is not part of enum "#name); \
        return r; \
    }; \
    attribute std::ostream& operator<<(std::ostream& os, const name& e) { \
        const char* name##Str[] = { MAKE_STRING(__VA_ARGS__) }; \
        return (os << name##Str[e]); \
    }

ব্যবহার:

// Declare global enum
enum MAKE_ENUM(Test3, Item13, Item23, Item33, Itdsdgem43);

class Essai {
public:
    // Declare enum inside class
    enum MAKE_CLASS_ENUM(Test, Item1, Item2, Item3, Itdsdgem4);

};

int main() {
    std::cout << Essai::Item1 << std::endl;

    Essai::Test ddd = Essai::Item1;
    std::cout << ddd << std::endl;

    std::istringstream strm("Item2");
    strm >> ddd;

    std::cout << (int) ddd << std::endl;
    std::cout << ddd << std::endl;
}

যদিও এই প্রকল্পের সীমাবদ্ধতা সম্পর্কে নিশ্চিত নন ... মন্তব্য স্বাগত!


0
#include <iostream>
#include <map>
#define IDMAP(x) (x,#x)

std::map<int , std::string> enToStr;
class mapEnumtoString
{
public:
    mapEnumtoString(){  }
    mapEnumtoString& operator()(int i,std::string str)
    {
        enToStr[i] = str;
        return *this;
    }
public:
   std::string operator [] (int i)
    {
        return enToStr[i];
    }

};
mapEnumtoString k;
mapEnumtoString& init()
{
    return k;
}

int main()
{

init()
    IDMAP(1)
    IDMAP(2)
    IDMAP(3)
    IDMAP(4)
    IDMAP(5);
std::cout<<enToStr[1];
std::cout<<enToStr[2];
std::cout<<enToStr[3];
std::cout<<enToStr[4];
std::cout<<enToStr[5];
}

2
দয়া করে ব্যাখ্যা করুন কেন এটি উত্তর।
অলোক
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.