web-gelistirme-sc.com

Enum öğe adını değerinden alma

Enum tipini bu şekilde ilan ettim.

enum WeekEnum
{
Mon = 0;
Tue = 1;
Wed = 2;
Thu = 3;
Fri = 4;
Sat = 5;
Sun = 6;
};

Zaten "0, 1, vb." Değerine sahip olduğumda, "Pzt, Sal, etc" ismini nasıl alabilirim?

Zaten böyle bir işleve sahibim

Log(Today is "2", enjoy! );

Ve şimdi aşağıdaki çıktıyı istiyorum 

Bugün çar, zevk

26
Nano HE

Doğrudan yapamazsınız, C++ 'da enum Java numaralarına benzemez. 

Genel yaklaşım bir std::map<WeekEnum,std::string> oluşturmaktır.

std::map<WeekEnum,std::string> m;
m[Mon] = "Monday";
//...
m[Sun] = "Sunday";
22
Luchian Grigore

hayır, C++ 'daki değerden "isim" yi elde etmenin bir yolu yok çünkü tüm semboller derleme sırasında atılıyor. 

Bu şekilde ihtiyacınız olabilir X Makrolar

9
RolandXu

Bir numaralandırma, ters diziden oluşan bir şeydir. İstediğine inandığım şey şudur:

const char * Week[] = { "", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };  // The blank string at the beginning is so that Sunday is 1 instead of 0.
cout << "Today is " << Week[2] << ", enjoy!";  // Or whatever you'de like to do with it.
7
Cosine

Çıkışı gerçekleştiren bir işleç tanımlayabilirsiniz.

std::ostream& operator<<(std::ostream& lhs, WeekEnum e) {
    switch(e) {
    case Monday: lhs << "Monday"; break;
    .. etc
    }
    return lhs;
}
6
Puppy

İşte X Macro kullanarak enum tanımlamak için başka bir temiz hile:

#include <iostream>

#define WEEK_DAYS \
X(MON, "Monday", true) \
X(TUE, "Tuesday", true) \
X(WED, "Wednesday", true) \
X(THU, "Thursday", true) \
X(FRI, "Friday", true) \
X(SAT, "Saturday", false) \
X(Sun, "Sunday", false)

#define X(day, name, workday) day,
enum WeekDay : size_t
{
    WEEK_DAYS
};
#undef X

#define X(day, name, workday) name,
char const *weekday_name[] =
{
    WEEK_DAYS
};
#undef X

#define X(day, name, workday) workday,
bool weekday_workday[]
{
    WEEK_DAYS
};
#undef X

int main()
{
    std::cout << "Enum value: " << WeekDay::THU << std::endl;
    std::cout << "Name string: " << weekday_name[WeekDay::THU] << std::endl;
    std::cout << std::boolalpha << "Work day: " << weekday_workday[WeekDay::THU] << std::endl;

    WeekDay wd = Sun;
    std::cout << "Enum value: " << wd << std::endl;
    std::cout << "Name string: " << weekday_name[wd] << std::endl;
    std::cout << std::boolalpha << "Work day: " << weekday_workday[wd] << std::endl;

    return 0;
}

Canlı Demo: https://ideone.com/bPAVTM

Çıktılar:

Enum value: 3
Name string: Thursday
Work day: true
Enum value: 6
Name string: Sunday
Work day: false
3
Killzone Kid

Zaten sahip olduğumda, "Pzt, Sal, vb." Başlık adını nasıl alabilirim. öğe değeri "0, 1, vb."

Bazı eski C kodlarında (bir süre önce), aşağıdakilere benzer bir kod buldum:

std::string weekEnumToStr(int n)
{
   std::string s("unknown");
   switch (n)
   {
   case 0: { s = "Mon"; } break;
   case 1: { s = "Tue"; } break;
   case 2: { s = "Wed"; } break;
   case 3: { s = "Thu"; } break;
   case 4: { s = "Fri"; } break;
   case 5: { s = "Sat"; } break;
   case 6: { s = "Sun"; } break;
   }
   return s;
}

Con: Bu, numaralandırma değerleri ve fonksiyon arasında "patolojik bir bağımlılık" kurar ... yani numaralandırmayı değiştirirseniz, fonksiyonun eşleşmesi için değiştirmeniz gerekir. Sanırım bu bir std :: map için bile doğru. 

Belli ki enum kodundan işlev kodunu oluşturmak için bir yardımcı program bulduğumuzu hatırlıyorum. Enum tabla uzunluğu birkaç yüze çıkmıştı ... ve bir noktada kod yazmak için kod yazmak belki de sağlam bir seçim. 


Not - 

gömülü bir sistem geliştirme çalışmasında ekibim, enum int değerlerini metin dizelerine eşlemek için kullanılan çok sayıda boş sonlandırılmış dizge tablosu (100+?) değiştirdi.

Tablolardaki problem, aralığın dışındaki bir değerin genellikle fark edilmemesiydi, çünkü bu tabloların çoğu kod/belleğin bir bölgesine toplandı; bir sonraki tablodan boş bir sonlandırılmış dize döndürdü. 

Function-with-switch ifadesinin kullanılması, anahtarın varsayılan cümlesinde bir assert eklememize de izin verdi. Varlıklar test sırasında birkaç kodlama hatası daha buldular ve iddialarımız saha teknisyenlerimizin arayabileceği statik-ram-sistem günlüğüne bağlandı. 

1
2785528

Gerçek enum etiketlerinin değerleri ile ilişkili olduğunu biliyorsanız, kapsayıcıları ve C++ 17's std::string_view değerlerini ve değerlerini hızlı bir şekilde erişmek için [] operatörüyle dizge gösterimlerini kullanabilirsiniz. std::string_view, yalnızca oluşturulduğunda bellek ayırır. Daha fazla performans tasarrufu için çalışma zamanında kullanılabilir olmalarını istiyorsanız, static constexpr ile de atanabilirler. Bu küçük konsol uygulaması oldukça hızlı olmalı.

#include <iostream>
#include <string_view>
#include <Tuple>    
int main() {
    enum class Weekdays { //default behavior starts at 0 and iterates by 1 per entry
        Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday
    };

    static constexpr std::string_view Monday    = "Monday";
    static constexpr std::string_view Tuesday   = "Tuesday";
    static constexpr std::string_view Wednesday = "Wednesday";
    static constexpr std::string_view Thursday  = "Thursday";
    static constexpr std::string_view Friday    = "Friday";
    static constexpr std::string_view Saturday  = "Saturday";
    static constexpr std::string_view Sunday    = "Sunday";
    static constexpr std::string_view opener    = "enum[";
    static constexpr std::string_view closer    = "] is ";
    static constexpr std::string_view semi      = ":";

    std::pair<Weekdays, std::string_view> Weekdays_List[] = {
        std::make_pair(Weekdays::Monday,    Monday),
        std::make_pair(Weekdays::Tuesday,   Tuesday),
        std::make_pair(Weekdays::Wednesday, Wednesday),
        std::make_pair(Weekdays::Thursday,  Thursday),
        std::make_pair(Weekdays::Friday,    Friday),
        std::make_pair(Weekdays::Saturday,  Saturday),
        std::make_pair(Weekdays::Sunday,    Sunday)
    };

    for (int i=0;i<sizeof(Weekdays_List)/sizeof(Weekdays_List[0]);i++) {
        std::cout<<opener<<i<<closer<<Weekdays_List[(int)i].second<<semi\
        <<(int)Weekdays_List[(int)i].first<<std::endl;
    }    
    return 0;
}

Çıktı: 

enum[0] is Monday:0
enum[1] is Tuesday:1
enum[2] is Wednesday:2
enum[3] is Thursday:3
enum[4] is Friday:4
enum[5] is Saturday:5
enum[6] is Sunday:6
0

@RolandXu tarafından gösterilen X makrolarına benzer bir teknikle mükemmel bir başarı elde ettim. Stringize operatörünü de yoğun bir şekilde kullandık. Teknik, öğelerin hem karakter hem de sayısal simge olarak göründüğü bir uygulama alanınız olduğunda bakım kabusunu azaltır.

Makro X(...) satırlarının otomatik olarak üretilebilmesi için makinede okunabilen belgeler mevcut olduğunda özellikle kullanışlı olur. Yeni bir dökümantasyon derhal, her iki yönde birbirinden geçen dizeleri, numaraları ve sözlükleri kapsayan tutarlı bir program güncellemesi ile sonuçlanacaktır. (PCL6 belirteçleriyle uğraşıyorduk).

Önişlemci kodu oldukça çirkin gözükse de, tüm bu teknik özellikler bir daha hiç dokunulmaması gereken başlık dosyalarında gizlenebilir ve kaynak dosyalar da yapılmaz. Her şey güvenlidir. Değişen tek şey, tüm X(...) satırlarını içeren ve muhtemelen otomatik olarak oluşturulan bir metin dosyasıdır.

0