সি ++: পাঠ্য হিসাবে এনাম মানটি মুদ্রণ করুন


91

আমার যদি এ জাতীয় এনাম থাকে

enum Errors
{ErrorA=0, ErrorB, ErrorC};

তারপরে আমি কনসোলে মুদ্রণ করতে চাই

Errors anError = ErrorA;
cout<<anError;/// 0 will be printed

তবে আমি কী চাইছি "ত্রুটিএ" পাঠ্যটি, আমি / সুইচটি ব্যবহার না করে কি এটি করতে পারি?
এবং এই জন্য আপনার সমাধান কি?


আমার মনে হয় আমার উত্তরটি বেশ ভাল, আপনি কি একবার দেখে কিছু মনে করবেন?
জিয়াও


উত্তর:


64

মানচিত্র ব্যবহার:

#include <iostream>
#include <map>
#include <string>

enum Errors {ErrorA=0, ErrorB, ErrorC};

std::ostream& operator<<(std::ostream& out, const Errors value){
    static std::map<Errors, std::string> strings;
    if (strings.size() == 0){
#define INSERT_ELEMENT(p) strings[p] = #p
        INSERT_ELEMENT(ErrorA);     
        INSERT_ELEMENT(ErrorB);     
        INSERT_ELEMENT(ErrorC);             
#undef INSERT_ELEMENT
    }   

    return out << strings[value];
}

int main(int argc, char** argv){
    std::cout << ErrorA << std::endl << ErrorB << std::endl << ErrorC << std::endl;
    return 0;   
}

রৈখিক অনুসন্ধানের সাথে কাঠামোর অ্যারে ব্যবহার করে:

#include <iostream>
#include <string>

enum Errors {ErrorA=0, ErrorB, ErrorC};

std::ostream& operator<<(std::ostream& out, const Errors value){
#define MAPENTRY(p) {p, #p}
    const struct MapEntry{
        Errors value;
        const char* str;
    } entries[] = {
        MAPENTRY(ErrorA),
        MAPENTRY(ErrorB),
        MAPENTRY(ErrorC),
        {ErrorA, 0}//doesn't matter what is used instead of ErrorA here...
    };
#undef MAPENTRY
    const char* s = 0;
    for (const MapEntry* i = entries; i->str; i++){
        if (i->value == value){
            s = i->str;
            break;
        }
    }

    return out << s;
}

int main(int argc, char** argv){
    std::cout << ErrorA << std::endl << ErrorB << std::endl << ErrorC << std::endl;
    return 0;   
}

সুইচ / কেস ব্যবহার:

#include <iostream>
#include <string>

enum Errors {ErrorA=0, ErrorB, ErrorC};

std::ostream& operator<<(std::ostream& out, const Errors value){
    const char* s = 0;
#define PROCESS_VAL(p) case(p): s = #p; break;
    switch(value){
        PROCESS_VAL(ErrorA);     
        PROCESS_VAL(ErrorB);     
        PROCESS_VAL(ErrorC);
    }
#undef PROCESS_VAL

    return out << s;
}

int main(int argc, char** argv){
    std::cout << ErrorA << std::endl << ErrorB << std::endl << ErrorC << std::endl;
    return 0;   
}

12
-1। হ্যাশ-ম্যাপ ব্যবহার না করে কেবল একটি স্যুইচ-কেস করুন। জটিলতা বৃদ্ধি করা ভাল জিনিস নয়।
সাইমন

8
ভাল যুক্তি. পরের বার আমি করব :) তবে এখন আমি দেখতে পাচ্ছি যে আমি যে ধরণের কার্যকারিতাটি সন্ধান করছিলাম তা যুক্ত করতে আপনি ইতিমধ্যে আপনার পোস্ট সম্পাদনা করেছেন। ভাল করেছ!
সাইমন

4
# পি কি? যদি এনামের পরিবর্তে তৃতীয় উদাহরণে আমি এনাম ক্লাস ব্যবহার করি তবে শ্রেণীর নাম বাদে কেবল এনাম স্ট্রিং পাওয়া সম্ভব?
rh0x

4
#pপ্রিপ্রসেসর স্ট্রিংফাইং পি। তাই কলিং PROCESS_VAL(ErrorA)ইচ্ছা আউটপুট: case(ErrorA): s = "ErrorA"; break;
নাশেনাস

আমি একজন সন্তোষজনক সমাধান হিসেবে বিবেচনা না: কারণ: 1) আমি বজায় রাখার জন্য আছে দ্বিগুণenum মান যা আমি মনে হয় নো গো । 2) আমি যখন সমাধানটি সঠিকভাবে বুঝতে পারি তখন এটি কেবল একের জন্য কাজ করে enum
পিটার ভারাগা

30

ম্যাচের মানগুলির সাথে একটি অ্যারে বা ভেক্টর ব্যবহার করুন:

char *ErrorTypes[] =
{
    "errorA",
    "errorB",
    "errorC"
};

cout << ErrorTypes[anError];

সম্পাদনা: উপরের সমাধানটি প্রযোজ্য হবে যখন এনামটি সংক্ষিপ্ত হয়, অর্থাৎ 0 থেকে শুরু হয় এবং কোনও নির্ধারিত মান নেই। এটি প্রশ্নের এনামের সাথে পুরোপুরি কাজ করবে।

এনাম 0 থেকে শুরু হয় না এমন ক্ষেত্রে এটি আরও প্রমাণ করতে, ব্যবহার করুন:

cout << ErrorTypes[anError - ErrorA];

4
দুর্ভাগ্যক্রমে, এনাম আমাদের উপাদানগুলিকে মান নির্ধারণের অনুমতি দেয়। আপনার যদি অবিচ্ছিন্ন এনাম, লাইনের 'এনাম স্থিতি {ঠিক আছে = 0, ব্যর্থ = -1, আউটফেমারি = -2, আইওআরার = -1000, রূপান্তরকরণের -2000} `(সুতরাং আপনি পরে আইওআরআরগুলি যোগ করতে পারেন তবে কীভাবে আপনি কাজ করতে পারেন? -1001-1999 পরিসীমাতে)
নর্ডিক মেনফ্রেমে

@ লুথার: হ্যাঁ, এটি কেবল সংঘবদ্ধ এনামগুলির সাথে কাজ করবে, যা বেশিরভাগ এনামগুলি । যদি এনামটি অস্পষ্ট হয় তবে আপনাকে অন্য একটি পদ্ধতির অর্থাত্ মানচিত্র ব্যবহার করতে হবে। তবে সংঘবদ্ধ এনামের ক্ষেত্রে আমি এই পদ্ধতিকে ব্যবহার করার পরামর্শ দিই, এবং অত্যধিক জটিল না করার জন্য।
ইগোর ওকস

4
সুতরাং, যদি আমার সহকর্মী একটি এনামে নিউভ্যালু যুক্ত করে এবং ত্রুটিটিপস অ্যারে আপডেট না করে, তবে ত্রুটি টাইপস [নিউভ্যালু] কী ফল দেয়? এবং আমি কীভাবে নেতিবাচক এনাম মানগুলি পরিচালনা করব?
নর্ডিক মেনফ্রেমে

4
@ লুথার: আপনাকে ত্রুটি টাইপগুলি আপডেট রাখতে হবে। আবার, সরলতা এবং সর্বজনীনতার মধ্যে একটি বাণিজ্য রয়েছে যা ব্যবহারকারীর জন্য আরও গুরুত্বপূর্ণ depends নেতিবাচক এনাম মানগুলির সাথে কী সমস্যা?
ইগোর ওকস

4
এই অ্যারেটি মেমরির দক্ষতার জন্য স্থির হওয়া উচিত নয়? এবং সুরক্ষার জন্য কনস্ট?
জোনাথন

15

এখানে বুস্ট.প্রিয় প্রসেসর ভিত্তিক একটি উদাহরণ রয়েছে:

#include <iostream>

#include <boost/preprocessor/punctuation/comma.hpp>
#include <boost/preprocessor/control/iif.hpp>
#include <boost/preprocessor/comparison/equal.hpp>
#include <boost/preprocessor/stringize.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/seq/size.hpp>
#include <boost/preprocessor/seq/seq.hpp>


#define DEFINE_ENUM(name, values)                               \
  enum name {                                                   \
    BOOST_PP_SEQ_FOR_EACH(DEFINE_ENUM_VALUE, , values)          \
  };                                                            \
  inline const char* format_##name(name val) {                  \
    switch (val) {                                              \
      BOOST_PP_SEQ_FOR_EACH(DEFINE_ENUM_FORMAT, , values)       \
    default:                                                    \
        return 0;                                               \
    }                                                           \
  }

#define DEFINE_ENUM_VALUE(r, data, elem)                        \
  BOOST_PP_SEQ_HEAD(elem)                                       \
  BOOST_PP_IIF(BOOST_PP_EQUAL(BOOST_PP_SEQ_SIZE(elem), 2),      \
               = BOOST_PP_SEQ_TAIL(elem), )                     \
  BOOST_PP_COMMA()

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


DEFINE_ENUM(Errors,
            ((ErrorA)(0))
            ((ErrorB))
            ((ErrorC)))

int main() {
  std::cout << format_Errors(ErrorB) << std::endl;
}

4
+1, এই সমাধানটি উপরের লুয়া উত্তরের মতো কোনও বাহ্যিক সরঞ্জামের উপর নির্ভর করে না, তবে খাঁটি সি ++, এটি ডিআরওয়াই নীতি অনুসরণ করে, এবং ব্যবহারকারী বাক্য গঠনটি পাঠযোগ্য (সঠিকভাবে ফর্ম্যাট করলে B বিটিডাব্লু), আপনার ব্যাকস্ল্যাশগুলির দরকার নেই DEFINE_ENUM ব্যবহার করার সময়, যা কিছুটা প্রাকৃতিক দেখায়, আইএমও)
ফ্যাবিও ফ্রেসাসি

4
@ ফ্যাবিও ফ্র্যাকাসি: "এই সমাধানটি কোনও বাহ্যিক সরঞ্জামের উপর নির্ভর করে না" বুস্ট একটি বাহ্যিক সরঞ্জাম - মানহীন সি ++ গ্রন্থাগার। তা ছাড়া এটি কিছুটা দীর্ঘ। কোনও সমস্যার সমাধান যতটা সম্ভব সহজ হওয়া উচিত। এই এক যোগ্যতা নেই ...
সিগটার্ম

4
আসলে এটিই হ'ল যা আপনি বেশিরভাগ কোডে রেখেছিলেন (আসলে প্রকৃত সংজ্ঞা ব্যতীত এটি সমস্ত) একক শিরোনামে রাখা যেতে পারে। সুতরাং এটি এখানে সংক্ষিপ্ততম সমাধানটি উপস্থাপন করা হয়েছে। এবং বাহ্যিক হওয়ার জন্য, হ্যাঁ, তবে উপরের লুয়া লিপিটি হ'ল উত্সের অংশগুলি প্রিপ্রোসেসিংয়ের জন্য ভাষার স্ক্রিপ্টের চেয়ে কম। বুস্টের পাশাপাশি স্ট্যান্ডার্ডের এতটাই কাছাকাছি যে এটি প্রতিটি সি ++ প্রোগ্রামার সরঞ্জামবাক্সে থাকা উচিত। অবশ্যই আইএমএইচও, অবশ্যই
ফ্যাবিও ফ্রেসাসি

[আমি ম্যাক্রো অনুরোধে নিউলাইনগুলির অনির্বাচিত পলায়ন সরিয়ে ফেলেছি। তাদের প্রয়োজন নেই: একটি ম্যাক্রো অনুরোধ একাধিক লাইন বিস্তৃত করতে পারে]]
জেমস ম্যাকনেলিস

আমি যখন এটি ব্যবহার করার চেষ্টা করি তখন ম্যাক্রো DEFINE_ENUMআমাকে ত্রুটি দেয় multiple definition of `format_ProgramStatus(ProgramStatus)'
হ্যালো গুডবাই

6

আপনি যদি enumকোনও বাহ্যিক ফাইলে আপনার এন্ট্রি তালিকাবদ্ধ করতে ইচ্ছুক হন তবে আপনি একটি সহজ প্রাক-প্রসেসর কৌশল ব্যবহার করতে পারেন ।

/* file: errors.def */
/* syntax: ERROR_DEF(name, value) */
ERROR_DEF(ErrorA, 0x1)
ERROR_DEF(ErrorB, 0x2)
ERROR_DEF(ErrorC, 0x4)

তারপর একটি উৎস ফাইল, আপনি ফাইল আচরণ মতো ফাইল মধ্যে রয়েছে, তবে আপনি সংজ্ঞায়িত তুমি কি চাও ERROR_DEFনা।

enum Errors {
#define ERROR_DEF(x,y) x = y,
#include "errors.def"
#undef ERROR_DEF
};

static inline std::ostream & operator << (std::ostream &o, Errors e) {
    switch (e) {
    #define ERROR_DEF(x,y) case y: return o << #x"[" << y << "]";
    #include "errors.def"
    #undef ERROR_DEF
    default: return o << "unknown[" << e << "]";
    }
}

আপনি যদি কিছু উত্স ব্রাউজিং সরঞ্জাম ব্যবহার করেন (যেমন সিস্কোপ), আপনাকে এটি বাহ্যিক ফাইল সম্পর্কে জানাতে হবে।


4

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

আপডেট: এখানে লুয়ার জন্য # টি স্ক্রিপ্ট যা অপারেটর তৈরি করে << প্রতিটি নাম করা এনামের সাথে এটি মুখোমুখি হয়। এটি কম সাধারণ ক্ষেত্রে কাজ করার জন্য এটি কিছু কাজের প্রয়োজন হতে পারে [1]:

function make_enum_printers(s)
    for n,body in string.gmatch(s,'enum%s+([%w_]+)%s*(%b{})') do
    print('ostream& operator<<(ostream &o,'..n..' n) { switch(n){') 
    for k in string.gmatch(body,"([%w_]+)[^,]*") do
    print('  case '..k..': return o<<"'..k..'";')
    end
    print('  default: return o<<"(invalid value)"; }}')
    end
end

local f=io.open(arg[1],"r")
local s=f:read('*a')
make_enum_printers(s)

এই ইনপুট দেওয়া:

enum Errors
{ErrorA=0, ErrorB, ErrorC};

enum Sec {
    X=1,Y=X,foo_bar=X+1,Z
};

এটি উৎপন্ন করে:

ostream& operator<<(ostream &o,Errors n) { switch(n){
  case ErrorA: return o<<"ErrorA";
  case ErrorB: return o<<"ErrorB";
  case ErrorC: return o<<"ErrorC";
  default: return o<<"(invalid value)"; }}
ostream& operator<<(ostream &o,Sec n) { switch(n){
  case X: return o<<"X";
  case Y: return o<<"Y";
  case foo_bar: return o<<"foo_bar";
  case Z: return o<<"Z";
  default: return o<<"(invalid value)"; }}

সুতরাং এটি সম্ভবত আপনার জন্য একটি সূচনা।

[1] বিভিন্ন বা অ-নেমস্পেস স্কোপগুলিতে এনামস, ইনিশিয়ালার এক্সপ্রেশন সহ এনামস, যার মধ্যে একটি কোমা রয়েছে etc.


পোস্টারকে তাদের উত্তর ঠিক করার সুযোগ দেওয়ার জন্য এখানে কোনও '-1' মন্তব্য করা কি প্রথা নয়? শুধু জিজ্ঞাসা করা হচ্ছে ..
নর্ডিক মেনফ্রেম

4
আমি মনে করি নীচে (ফিলিপ থেকে) বুস্ট পিপি সমাধানটি আরও ভাল, কারণ বাহ্যিক সরঞ্জামগুলি ব্যবহার করা অত্যন্ত ব্যয়বহুল রক্ষণাবেক্ষণ হিসাবে গুরুত্বপূর্ণ। তবে না -1 কারণ উত্তরটি অন্যথায় বৈধ
ফ্যাবিও ফ্র্যাকাসি

4
বুস্ট পিপি হয় একটি রক্ষণাবেক্ষণ সমস্যা, কারণ আপনার সবাই প্রয়োজন বুস্ট পিপি metalanguage, যা বলতে ভয়ানক , সহজে বিরতি করতে (সাধারণত অব্যবহারযোগ্য ত্রুটি বার্তা দান) এবং কেবলমাত্র সীমিত ব্যবহারযোগ্যতা (Lua / পাইথন নির্বিচারে থেকে কোড / Perl তৈরি করতে পারেন এর বাহ্যিক ডেটা)। এটি আপনার নির্ভরতা তালিকায় উত্সাহ যোগ করে, যা প্রকল্পের নীতির কারণে এমনকি অনুমোদিত হতে পারে না। এছাড়াও, এটি আক্রমণাত্মক কারণ এটি আপনাকে একটি ডিএসএলে আপনার এনামগুলি সংজ্ঞায়িত করা প্রয়োজন। আপনার প্রিয় উত্স কোড সরঞ্জাম বা আইডিই এর সাথে সমস্যা হতে পারে। এবং শেষ কিন্তু সর্বনিম্ন নয়: আপনি প্রসারণে কোনও ব্রেকপয়েন্ট নির্ধারণ করতে পারবেন না।
নর্ডিক মেনফ্রেমে

4

আমি যখনই এনাম সংজ্ঞায়িত করি আমি একটি স্ট্রিং অ্যারে ব্যবহার করি:

প্রোফাইল

#pragma once

struct Profile
{
    enum Value
    {
        Profile1,
        Profile2,
    };

    struct StringValueImplementation
    {
        const wchar_t* operator[](const Profile::Value profile)
        {
            switch (profile)
            {
            case Profile::Profile1: return L"Profile1";
            case Profile::Profile2: return L"Profile2";
            default: ASSERT(false); return NULL;
            }
        }
    };

    static StringValueImplementation StringValue;
};

প্রোফাইল.সিপিপি

#include "Profile.h"

Profile::StringValueImplementation Profile::StringValue;

4

এটি একটি ভাল উপায়,

enum Rank { ACE = 1, DEUCE, TREY, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING };

এটিকে অক্ষরের অ্যারে দিয়ে মুদ্রণ করুন

const char* rank_txt[] = {"Ace", "Deuce", "Trey", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Jack", "Four", "King" } ;

এটার মত

std::cout << rank_txt[m_rank - 1]

4
আমার এনাম 2000 থেকে শুরু হলে কী হবে? এই সমাধান কাজ করবে না।
সীতেশ

3
#include <iostream>
using std::cout;
using std::endl;

enum TEnum
{ 
  EOne,
  ETwo,
  EThree,
  ELast
};

#define VAR_NAME_HELPER(name) #name
#define VAR_NAME(x) VAR_NAME_HELPER(x)

#define CHECK_STATE_STR(x) case(x):return VAR_NAME(x);

const char *State2Str(const TEnum state)
{
  switch(state)
  {
    CHECK_STATE_STR(EOne);
    CHECK_STATE_STR(ETwo);
    CHECK_STATE_STR(EThree);
    CHECK_STATE_STR(ELast);
    default:
      return "Invalid";
  }
}

int main()
{
  int myInt=12345;
  cout << VAR_NAME(EOne) " " << VAR_NAME(myInt) << endl;

  for(int i = -1; i < 5;   i)
    cout << i << " " << State2Str((TEnum)i) << endl;
  return 0;
}

2

আপনি একটি stl মানচিত্র ধারক ব্যবহার করতে পারেন ....

typedef map<Errors, string> ErrorMap;

ErrorMap m;
m.insert(ErrorMap::value_type(ErrorA, "ErrorA"));
m.insert(ErrorMap::value_type(ErrorB, "ErrorB"));
m.insert(ErrorMap::value_type(ErrorC, "ErrorC"));

Errors error = ErrorA;

cout << m[error] << endl;

4
এটি কীভাবে মানচিত্রের চেয়ে ভাল switch(n) { case XXX: return "XXX"; ... }? কোনটির ও (1) অনুসন্ধান আছে এবং এটি আরম্ভ করার দরকার নেই? অথবা রানটাইম চলাকালীন সময়ে এনামগুলি কীভাবে পরিবর্তিত হয়?
নর্ডিক মেনফ্রেমে

আমি সুইচ স্টেটমেন্ট (বা একটি ফাংশন পয়েন্টার খুব বেশি) ব্যবহার করার বিষয়ে @ লুথার ব্লিসেটের সাথে একমত
কেদারেক্স

4
ঠিক আছে, তিনি আউটপুট করতে চাইতে পারেন "এই আমার প্রিয় বন্ধু লুথারটি ত্রুটি এ" বা "এটি আমার প্রিয় বন্ধু অ্যাড্রিয়ান ত্রুটি বি" আছে। এছাড়াও, মানচিত্রটি আইওস্ট্রিম স্বাক্ষরের উপর নির্ভরতা সরিয়ে দেয়, যেমন তিনি অন্য কোথাও এটি ব্যবহার করতে পারবেন উদাহরণস্বরূপ স্ট্রিং সংমিশ্রণ সহ কোড, স্ট্রিং x = "হ্যালো" + এম [ত্রুটি]], ইত্যাদি
অ্যাড্রিয়ান রেগান

আমি নিশ্চিত std :: মানচিত্রে প্রচুর পরিমাণে যদি থাকে এবং স্যুইচ থাকে। আমি এটি পড়তে থাকি ' যদি লিখি এবং স্যুইচ না করে আমাকে না লিখে আমি এটি কীভাবে করতে পারি '
নর্ডিক মেনফ্রেম

আমি নিশ্চিত যে এটি এটি করেছে তবে সমস্যাটি সমাধানের জন্য অবশ্যই আপনার লুয়াতে একটি স্ক্রিপ্ট লিখতে হবে না ...
অ্যাড্রিয়ান রেগান

1

এই সমস্যার জন্য, আমি এই জাতীয় সহায়তা কার্য সম্পাদন করি:

const char* name(Id id) {
    struct Entry {
        Id id;
        const char* name;
    };
    static const Entry entries[] = {
        { ErrorA, "ErrorA" },
        { ErrorB, "ErrorB" },
        { 0, 0 }
    }
    for (int it = 0; it < gui::SiCount; ++it) {
        if (entries[it].id == id) {
            return entries[it].name;
        }
    }
   return 0;
}

লিনিয়ার অনুসন্ধান সাধারণত এর std::mapমতো ছোট সংগ্রহের চেয়ে বেশি দক্ষ ।


1

এই সমাধানটির জন্য আপনাকে কোনও ডেটা স্ট্রাকচার ব্যবহার করতে বা কোনও আলাদা ফাইল তৈরি করার প্রয়োজন হয় না।

মূলত, আপনি আপনার সমস্ত এনাম মানগুলিকে একটি # নির্ধারণে সংজ্ঞায়িত করেন, তারপরে সেগুলি অপারেটরে ব্যবহার করুন << @ Jxh ​​এর উত্তরের সাথে খুব মিল।

চূড়ান্ত পুনরাবৃত্তির জন্য আদর্শ লিঙ্ক: http://ideone.com/hQTKQp

সম্পূর্ণ কোড:

#include <iostream>

#define ERROR_VALUES ERROR_VALUE(NO_ERROR)\
ERROR_VALUE(FILE_NOT_FOUND)\
ERROR_VALUE(LABEL_UNINITIALISED)

enum class Error
{
#define ERROR_VALUE(NAME) NAME,
    ERROR_VALUES
#undef ERROR_VALUE
};

inline std::ostream& operator<<(std::ostream& os, Error err)
{
    int errVal = static_cast<int>(err);
    switch (err)
    {
#define ERROR_VALUE(NAME) case Error::NAME: return os << "[" << errVal << "]" #NAME;
    ERROR_VALUES
#undef ERROR_VALUE
    default:
        // If the error value isn't found (shouldn't happen)
        return os << errVal;
    }
}

int main() {
    std::cout << "Error: " << Error::NO_ERROR << std::endl;
    std::cout << "Error: " << Error::FILE_NOT_FOUND << std::endl;
    std::cout << "Error: " << Error::LABEL_UNINITIALISED << std::endl;
    return 0;
}

আউটপুট:

Error: [0]NO_ERROR
Error: [1]FILE_NOT_FOUND
Error: [2]LABEL_UNINITIALISED

এইভাবে এটি করার একটি দুর্দান্ত জিনিস হ'ল আপনি যদি মনে করেন যে আপনার যদি প্রয়োজন হয় তবে প্রতিটি ত্রুটির জন্য আপনি নিজের কাস্টম বার্তাও নির্দিষ্ট করতে পারেন:

#include <iostream>

#define ERROR_VALUES ERROR_VALUE(NO_ERROR, "Everything is fine")\
ERROR_VALUE(FILE_NOT_FOUND, "File is not found")\
ERROR_VALUE(LABEL_UNINITIALISED, "A component tried to the label before it was initialised")

enum class Error
{
#define ERROR_VALUE(NAME,DESCR) NAME,
    ERROR_VALUES
#undef ERROR_VALUE
};

inline std::ostream& operator<<(std::ostream& os, Error err)
{
    int errVal = static_cast<int>(err);
    switch (err)
    {
#define ERROR_VALUE(NAME,DESCR) case Error::NAME: return os << "[" << errVal << "]" #NAME <<"; " << DESCR;
    ERROR_VALUES
#undef ERROR_VALUE
    default:
        return os << errVal;
    }
}

int main() {
    std::cout << "Error: " << Error::NO_ERROR << std::endl;
    std::cout << "Error: " << Error::FILE_NOT_FOUND << std::endl;
    std::cout << "Error: " << Error::LABEL_UNINITIALISED << std::endl;
    return 0;
}

আউটপুট:

Error: [0]NO_ERROR; Everything is fine
Error: [1]FILE_NOT_FOUND; File is not found
Error: [2]LABEL_UNINITIALISED; A component tried to the label before it was initialised

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

inline std::ostream& operator<<(std::ostream& os, Error err)
{
    int errVal = static_cast<int>(err);
    switch (err)
    {
    #ifndef PRODUCTION_BUILD // Don't print out names in production builds
    #define ERROR_VALUE(NAME,DESCR) case Error::NAME: return os << "[" << errVal << "]" #NAME <<"; " << DESCR;
        ERROR_VALUES
    #undef ERROR_VALUE
    #endif
    default:
        return os << errVal;
    }
}

আউটপুট:

Error: 0
Error: 1
Error: 2

যদি এটি হয় তবে 525 ত্রুটি সন্ধান করা পিটা হবে be আমরা প্রাথমিকভাবে এনামগুলিতে ম্যানুয়ালি এইভাবে নম্বর নির্দিষ্ট করতে পারি:

#define ERROR_VALUES ERROR_VALUE(NO_ERROR, 0, "Everything is fine")\
ERROR_VALUE(FILE_NOT_FOUND, 1, "File is not found")\
ERROR_VALUE(LABEL_UNINITIALISED, 2, "A component tried to the label before it was initialised")\
ERROR_VALUE(UKNOWN_ERROR, -1, "Uh oh")

enum class Error
{
#define ERROR_VALUE(NAME,VALUE,DESCR) NAME=VALUE,
    ERROR_VALUES
#undef ERROR_VALUE
};

inline std::ostream& operator<<(std::ostream& os, Error err)
{
    int errVal = static_cast<int>(err);
    switch (err)
    {
#ifndef PRODUCTION_BUILD // Don't print out names in production builds
#define ERROR_VALUE(NAME,VALUE,DESCR) case Error::NAME: return os << "[" #VALUE  "]" #NAME <<"; " << DESCR;
    ERROR_VALUES
#undef ERROR_VALUE
#endif
    default:
        return os <<errVal;
    }
}
    ERROR_VALUES
#undef ERROR_VALUE
#endif
    default:
    {
        // If the error value isn't found (shouldn't happen)
        return os << static_cast<int>(err);
        break;
    }
    }
}

আউটপুট:

Error: [0]NO_ERROR; Everything is fine
Error: [1]FILE_NOT_FOUND; File is not found
Error: [2]LABEL_UNINITIALISED; A component tried to the label before it was initialised
Error: [-1]UKNOWN_ERROR; Uh oh

0

এ কেমন?

    enum class ErrorCodes : int{
          InvalidInput = 0
    };

    std::cout << ((int)error == 0 ? "InvalidInput" : "") << std::endl;

ইত্যাদি ... আমি জানি এটি একটি অত্যন্ত নিয়ন্ত্রিত উদাহরণ তবে আমি মনে করি এটির প্রয়োগ রয়েছে যেখানে প্রযোজ্য এবং প্রয়োজনীয় এবং এটি অবশ্যই এটির জন্য স্ক্রিপ্ট লেখার চেয়ে ছোট।


0

প্রিপ্রোসেসর ব্যবহার করুন:

#define VISIT_ERROR(FIRST, MIDDLE, LAST) \
    FIRST(ErrorA) MIDDLE(ErrorB) /* MIDDLE(ErrorB2) */ LAST(ErrorC)

enum Errors
{
    #define ENUMFIRST_ERROR(E)  E=0,
    #define ENUMMIDDLE_ERROR(E) E,
    #define ENUMLAST_ERROR(E)   E
    VISIT_ERROR(ENUMFIRST_ERROR, ENUMMIDDLE_ERROR, ENUMLAST_ERROR)
    // you might undefine the 3 macros defined above
};

std::string toString(Error e)
{
    switch(e)
    {
    #define CASERETURN_ERROR(E)  case E: return #E;
    VISIT_ERROR(CASERETURN_ERROR, CASERETURN_ERROR, CASERETURN_ERROR)
    // you might undefine the above macro.
    // note that this will produce compile-time error for synonyms in enum;
    // handle those, if you have any, in a distinct macro

    default:
        throw my_favourite_exception();
    }
}

এই পদ্ধতির সুবিধাটি হ'ল: - এটি এখনও বোঝা সহজ, তবুও - এটি বিভিন্ন দর্শন (কেবল স্ট্রিং নয়) এর জন্য অনুমতি দেয়

যদি আপনি প্রথমটি বাদ দিতে ইচ্ছুক হন তবে নিজেকে একটি বিদেশী () ম্যাক্রো তৈরি করুন #define ERROR_VALUES() (ErrorA, ErrorB, ErrorC)এবং তারপরে আপনার দর্শনার্থীদের লেখেন ফোর () এর পদে। তারপরে একটি কোড রিভিউ পাস করার চেষ্টা করুন :)।


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