define 된 값을 역으로 알아내려면?

ssehoony의 이미지

다음 과 같이

#define ERR_RETRY 132

int GetError()
{
    return ERR_RETRY;
}

printf("ErrCode[%d]\n", GetError());

define 된 값을 찍어서 에러를 확인하는 방법을 사용하는데요.
저렇게 해서 132 라는 값을 얻으면 다시 헤더파일을 참조해서
132 가 무슨 에러인지를 확인해야 하는 번거러움이 있습니다.
(에러핸들링뿐만이 아니고 다른 많은 경우에도)

그래서 이런 macro 를 하나 말 수 없을까 라는 생각을 했죠.
#define mydefine(def_str, def_int)
이런 매크로를 만들어서

mydefine(ERR_RETRY, 132); 
mydefine(ERR_WAIT, 133); 

이렇게 소스를 입력하면
#define ERR_RETRY 132
#define ERR_RETRY 133
const char* def2str(int def_int) 
{
    if(def_int == 132) return "ERR_RETRY";
    if(def_int == 133) return "ERR_WAIT";
    return NULL;
}

이와 같은 결과가 나오도록 할 수 없을까 하고요.

헌데 좋은 수를 도통 알 수가 없어 조언을 듣고자 이렇게 질문을 올립니다.
꼭 이 방법이 아니더라도 같은 효과를 얻을 수 있는 방법은 없을까요?

girneter의 이미지

결국 님이 하신 방법대로 하는 수밖에 없지 않을까요?

printf("error is %s\n",  def2str(err));

이렇게 출력하게 하고
err string 은 if 문으로 하지 말고
아예 가능한 err string 을 배열로 만들어서

const char* err_string[] = {
...
};

err code 를 index 로 사용해서 return 하게끔이요

개념없는 초딩들은 좋은 말로 할때 DC나 웃대가서 놀아라. 응?

정태영의 이미지

cpp 로.. 전처리기만 통과시키시고.. 어떻게 변했는지 보시면 되겠죠 :)

오랫동안 꿈을 그리는 사람은 그 꿈을 닮아간다...

http://mytears.org ~(~_~)~
나 한줄기 바람처럼..

doldori의 이미지

배열로 처리할 수도 있겠으나 C++을 쓰신다면 map도 괜찮은 해결책으로 보입니다.
제가 요긴하게 쓰는 boost의 assign도 같이 썼습니다.

#include <map>
#include <boost/assign/list_of.hpp>

enum ErrorCode
{
    err_retry = 132,
    err_cancel = 133
};

#define ENTRY(item) (item, #item)

typedef const std::map<ErrorCode, const char*> Dictionary;

Dictionary dictionary =
    boost::assign::map_list_of ENTRY(err_retry)
                               ENTRY(err_cancel);

const char* error_string(ErrorCode error) 
{
    Dictionary::const_iterator it = dictionary.find(error);
    if (it != dictionary.end())
        return it->second;
    else
        return "unknown error";
} 
ssehoony의 이미지

if else 를 반복하는 것 보다 map 이나 배열을 이용한 인덱싱이 좋겠군요.

그럼 이제 남은 중요한 사항은
define 을 위해 소스를 define 부분과 역으로 표시해 주는 부분 두 곳을 고치는게 번거럽다는거죠.
이걸 한번에 해결할 좋은 방법이 뭘까? 가장 큰 고민인데요.
일단 제가 봉착한 문제는

#define mydefine(def_name, def_value) #define def_name def_value

이와 같이 매크로 안에 #define 같은 걸 사용 할 수 가 없네요.
#define 를 문자열로 인식하게 할 수 있는 방법이 마련되어 있을 듯 한데.
여기저기 전처리기에 대한 문서를 뒤적거렸는데 못 찾겠네요.

pinetr2e의 이미지

현제 제가 프로젝트에서 사용하고 있는 방법으로
매크로를 좀 과하게 사용하여 에러 명세 헤더화일로 부터
컴파일 타임에 string 변환소스부를 생성합니다.

filename : uec.h

에러 명세를 기술 합니다.


#if !defined(UEC_H) || defined(U_GEN_ENUM_STR)
#include "umacro_local.h"

/**
 * error codes
 * @enum UEc Error Code
 */
U_START_TYPEDEF_ENUM( UEc )
{
	U_ENUM_DEF( U_ERR,			-1,		"ERR"			)
	U_ENUM_DEF( U_EAGAIN,		-10,	"EAGAIN"		)	
	U_ENUM_DEF( U_EINVAL,		-11,	"EINVAL"		)
	U_ENUM_DEF( U_EEXIST,		-12,	"EEXIST"		)
	U_ENUM_DEF( U_ENOENT,		-13,	"ENOENT"		)
	U_ENUM_DEF( U_EFULL,		-14,	"EFULL"			)
	U_ENUM_DEF( U_EEMPTY,		-15,	"EEMPTY"		)
	U_ENUM_DEF( U_EUNAVAIL	,	-16,	"EUNAVAIL"		)
	U_ENUM_DEF( U_EINIT,		-20,	"EINIT"			)
	U_ENUM_DEF( U_EADDRINUSE,	-60,	"EADDRINUSE"	)
	U_ENUM_DEF( U_ENOSUPPORT,	-126,	"ENOSUPPORT"	)
	U_ENUM_DEF( U_EUNKNOWN,		-127,	"EUNKNOWN"		)
	U_ENUM_DEF_END( UEc, 0 )
}
U_END_TYPEDEF_ENUM( UEc );
#endif

#ifndef UEC_H
/*
 * normal header content goes here
 */
#define UEC_H				

/**
 * return error code string corresponding to @a ec
 */
const char* ustr_ec( UEc ec );



#endif

filename : umacro_local.h

이방법의 핵심으로 이 헤더화일을 포함하기전에 U_GEN_ENUM_STR의
정의 여부에 따라 enum type 이나 enum to string 소스를
표현합니다.


#undef U_START_TYPEDEF_ENUM
#undef U_END_TYPEDEF_ENUM
#undef U_ENUM_DEF
#undef U_ENUM_DEF_END

#ifdef U_GEN_ENUM_STR
#define U_START_TYPEDEF_ENUM( type ) switch( U_GEN_ENUM_STR ) 
#define U_END_TYPEDEF_ENUM( type )
#define U_ENUM_DEF( name, value, str ) case name: return str;
#define U_ENUM_DEF_END(type, defaultStr) default: return defaultStr;
#else
#define U_START_TYPEDEF_ENUM( type ) typedef enum _##type
#define U_END_TYPEDEF_ENUM( type ) type
#define U_ENUM_DEF( name, value, str ) name = value,
#define U_ENUM_DEF_END( type, defaultStr) type##_U_ENUM_VAL_END
#endif


filename : main.c
테스트 소스 입니다.

const char* ustr_ec( UEc ec )
{
#define U_GEN_ENUM_STR ec
#include "uec.h"
#undef U_GEN_ENUM_STR
}

int main() {

	printf ("%d = %s", U_EAGAIN, ustr_ec( U_EAGAIN ) );
}

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.