sourcecode

Cenum으로 인쇄하다. 값 대신 텍스트.

copyscript 2022. 9. 5. 23:12
반응형

Cenum으로 인쇄하다. 값 대신 텍스트.

int main()
{

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

  Days TheDay;

  int j = 0;

  printf("Please enter the day of the week (0 to 6)\n");

  scanf("%d",&j);

  TheDay = Days(j);

  //how to PRINT THE VALUES stored in TheDay

  printf("%s",TheDay);  //   isnt working

  return 0;
}

당신의 코드 안에 편리한 이름이 C에서 이 항목은 모두 숫자이다.그들은 단순 문자열, 이름을 그들에게는 소스 코드에 할당된 당신의 프로그램으로 나누고, 그들은 런타임에 접근할 수 없다 편집한 것은 아니다.

를 들어, (여기에서는 선언합니다.)enum Days of main

const char* getDayName(enum Days day) 
{
   switch (day) 
   {
      case Sunday: return "Sunday";
      case Monday: return "Monday";
      /* etc... */
   }
}

/* Then, later in main: */
printf("%s", getDayName(TheDay));

또는 지도로, 예를 들어 배열을 사용할 수 있다.

const char* dayNames[] = {"Sunday", "Monday", "Tuesday", /* ... etc ... */ };

/* ... */

printf("%s", dayNames[TheDay]);

서는 아마 '어디서든'을 붙이는 게 것 같아요.Sunday = 0비록 대부분의(틀림없이 누군가 또는 거부 이것을 확인할 논평할 것이다)더라도 C규격 컴파일러는 0에서 열거형을 시작하야 한다 잘 모르겠어요.

나는:이 것을 사용한다.

파일"EnumToString에서.h":

#undef DECL_ENUM_ELEMENT
#undef DECL_ENUM_ELEMENT_VAL
#undef DECL_ENUM_ELEMENT_STR
#undef DECL_ENUM_ELEMENT_VAL_STR
#undef BEGIN_ENUM
#undef END_ENUM

#ifndef GENERATE_ENUM_STRINGS
    #define DECL_ENUM_ELEMENT( element ) element,
    #define DECL_ENUM_ELEMENT_VAL( element, value ) element = value,
    #define DECL_ENUM_ELEMENT_STR( element, descr ) DECL_ENUM_ELEMENT( element )
    #define DECL_ENUM_ELEMENT_VAL_STR( element, value, descr ) DECL_ENUM_ELEMENT_VAL( element, value )
    #define BEGIN_ENUM( ENUM_NAME ) typedef enum tag##ENUM_NAME
    #define END_ENUM( ENUM_NAME ) ENUM_NAME; \
            const char* GetString##ENUM_NAME(enum tag##ENUM_NAME index);
#else
    #define BEGIN_ENUM( ENUM_NAME) const char * GetString##ENUM_NAME( enum tag##ENUM_NAME index ) {\
        switch( index ) { 
    #define DECL_ENUM_ELEMENT( element ) case element: return #element; break;
    #define DECL_ENUM_ELEMENT_VAL( element, value ) DECL_ENUM_ELEMENT( element )
    #define DECL_ENUM_ELEMENT_STR( element, descr ) case element: return descr; break;
    #define DECL_ENUM_ELEMENT_VAL_STR( element, value, descr ) DECL_ENUM_ELEMENT_STR( element, descr )

    #define END_ENUM( ENUM_NAME ) default: return "Unknown value"; } } ;

#endif

그리고 어떠한 헤더 파일에 당신을 enum 선언 날 enum.h을 만든다.

#include "EnumToString.h"

BEGIN_ENUM(Days)
{
    DECL_ENUM_ELEMENT(Sunday) //will render "Sunday"
    DECL_ENUM_ELEMENT(Monday) //will render "Monday"
    DECL_ENUM_ELEMENT_STR(Tuesday, "Tuesday string") //will render "Tuesday string"
    DECL_ENUM_ELEMENT(Wednesday) //will render "Wednesday"
    DECL_ENUM_ELEMENT_VAL_STR(Thursday, 500, "Thursday string") // will render "Thursday string" and the enum will have 500 as value
    /* ... and so on */
}
END_ENUM(MyEnum)

그리고 파일에:EnumToString.c다.

#include "enum.h"

#define GENERATE_ENUM_STRINGS  // Start string generation

#include "enum.h"             

#undef GENERATE_ENUM_STRINGS   // Stop string generation

그리고 나중에 main.c:

int main(int argc, char* argv[])
{
    Days TheDay = Monday;
    printf( "%d - %s\n", TheDay, GetStringDay(TheDay) ); //will print "1 - Monday"

    TheDay = Thursday;
    printf( "%d - %s\n", TheDay, GetStringDay(TheDay) ); //will print "500 - Thursday string"

    return 0;
}

이렇게 선언되어 EnumToString에 포함된 모든 Enum에 대해 "자동" 문자열이 생성됩니다.c"

나는 이것을 dayNames에 열거하는 것을 좋아한다.입력을 줄이기 위해 다음을 수행할 수 있습니다.

#define EP(x) [x] = #x  /* ENUM PRINT */

const char* dayNames[] = { EP(Sunday), EP(Monday)};

매크로 및 문자열화 연산자(#)를 사용하면 이 작업을 수행할 수 있습니다.

#include <stdio.h>
typedef enum
{
    MON=0,
    TUE
}week;
int main()
{
    #define printt(data)        printf("%s",#data);
    printt(MON);
    return 0;
}

이 작업은 보통 문자열 표현을 같은 순서로 별도의 배열에 저장한 다음 배열에 열거 값을 사용하여 인덱스를 작성합니다.

const char *DayNames[] = { "Sunday", "Monday", "Tuesday", /* etc */ };
printf("%s", DayNames[Sunday]); // prints "Sunday"

enumC의 s는 기대했던 대로 동작하지 않습니다.미화된 상수(이러한 상수의 집합과 관련된 몇 가지 추가 이점 있음)와 같이 생각할 수 있습니다.그리고 "일요일"에 쓴 텍스트는 컴파일 중에 수치로 해결되어 최종적으로 폐기됩니다.

요컨대 원하는 것을 하기 위해서는 문자열 배열을 유지하거나 열거형 값에서 인쇄하고 싶은 텍스트로 매핑하는 함수를 만들어야 합니다.

파티에 늦은 건 알지만 이건 어때요?

const char* dayNames[] = { [Sunday] = "Sunday", [Monday] = "Monday", /*and so on*/ };
printf("%s", dayNames[Sunday]); // prints "Sunday"

해서 .enumchar*어레이가 동기화되어 있습니다.와 같다면 나중에 .enum및 , 。char*어레이가 유효하지 않은 문자열을 인쇄합니다.이 기능은 일반적으로 지원되지 않을 수 있습니다.그러나 대부분의 C 컴파일러는 이 지정된 이니셜 스타일을 지원합니다.

지정된 이니셜라이저에 대한 자세한 내용은 여기를 참조하십시오.

문제는 딱 한 번만 이름을 쓰고 싶다는 거예요.
에겐 다음과 것이 :

#define __ENUM(situation,num) \
    int situation = num;        const char * __##situation##_name = #situation;

    const struct {
        __ENUM(get_other_string, -203);//using a __ENUM Mirco make it ease to write, 
        __ENUM(get_negative_to_unsigned, -204);
        __ENUM(overflow,-205);
//The following two line showing the expanding for __ENUM
        int get_no_num = -201;      const char * __get_no_num_name = "get_no_num";
        int get_float_to_int = -202;        const char * get_float_to_int_name = "float_to_int_name";

    }eRevJson;
#undef __ENUM
    struct sIntCharPtr { int value; const char * p_name; };
//This function transform it to string.
    inline const char * enumRevJsonGetString(int num) {
        sIntCharPtr * ptr = (sIntCharPtr *)(&eRevJson);
        for (int i = 0;i < sizeof(eRevJson) / sizeof(sIntCharPtr);i++) {
            if (ptr[i].value == num) {
                return ptr[i].p_name;
            }
        }
        return "bad_enum_value";
    }

structure를 사용하여 열거형을 삽입하여 문자열에 대한 프린터가 정의된 각 열거형 값을 따를 수 있도록 합니다.

int main(int argc, char *argv[]) {  
    int enum_test = eRevJson.get_other_string;
    printf("error is %s, number is %d\n", enumRevJsonGetString(enum_test), enum_test);

>error is get_other_string, number is -203

쓰기가 숫자 쓰기를 싫어하면 쓰세요__LINE__할 수

#define ____LINE__ __LINE__
#define __ENUM(situation) \
    int situation = (____LINE__ - __BASELINE -2);       const char * __##situation##_name = #situation;
constexpr int __BASELINE = __LINE__;
constexpr struct {
    __ENUM(Sunday);
    __ENUM(Monday);
    __ENUM(Tuesday);
    __ENUM(Wednesday);
    __ENUM(Thursday);
    __ENUM(Friday);
    __ENUM(Saturday);
}eDays;
#undef __ENUM
inline const char * enumDaysGetString(int num) {
    sIntCharPtr * ptr = (sIntCharPtr *)(&eDays);
    for (int i = 0;i < sizeof(eDays) / sizeof(sIntCharPtr);i++) {
        if (ptr[i].value == num) {
            return ptr[i].p_name;
        }
    }
    return "bad_enum_value";
}
int main(int argc, char *argv[]) {  
    int d = eDays.Wednesday;
    printf("day %s, number is %d\n", enumDaysGetString(d), d);
    d = 1;
    printf("day %s, number is %d\n", enumDaysGetString(d), d);
}

>day Wednesday, number is 3 >day Monday, number is 1

매크로를 사용하여 보다 깔끔하게 작업을 수행할 수 있는 방법은 다음과 같습니다.

#include <stdio.h>
#include <stdlib.h>

#define DOW(X, S)                                                         \
    X(Sunday) S X(Monday) S X(Tuesday) S X(Wednesday) S X(Thursday) S X(Friday) S X(Saturday)

#define COMMA ,

/* declare the enum */
#define DOW_ENUM(DOW) DOW
enum dow {
    DOW(DOW_ENUM, COMMA)
};

/* create an array of strings with the enum names... */
#define DOW_ARR(DOW ) [DOW] = #DOW
const char * const dow_str[] = {
    DOW(DOW_ARR, COMMA)
};

/* ...or create a switchy function. */
static const char * dowstr(int i)
{
#define DOW_CASE(D) case D: return #D

    switch(i) {
        DOW(DOW_CASE, ;);
    default: return NULL;
    }
}


int main(void)
{
    for(int i = 0; i < 7; i++)
        printf("[%d] = «%s»\n", i, dow_str[i]);
    printf("\n");
    for(int i = 0; i < 7; i++)
        printf("[%d] = «%s»\n", i, dowstr(i));
    return 0;
}

완전 휴대용 B/W 프리프로세서인지는 모르겠지만 gcc에서 동작합니다.

이므로, 「c99 btw」를 해 주세요.c99 strict(온라인 컴파일러) ideone에 연결하면 됩니다.

The Day는 몇 가지 정수 타입으로 매핑됩니다.그래서:

printf("%s", TheDay);

The Day를 문자열로 해석하려고 하며 가비지 또는 크래시를 출력합니다.

printf는 typesafe가 아니기 때문에 올바른 값을 전달할 수 있습니다.값의 이름을 인쇄하려면 검색 테이블, 자이언트 스위치 문 등의 문자열에 열거 값을 매핑하는 메서드를 만들어야 합니다.

C의 열거는 기본적으로 자동으로 배열된 정수 값의 명명된 목록에 대한 구문 설탕입니다.즉, 다음 코드가 있는 경우:

int main()
{
    enum Days{Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday};

    Days TheDay = Monday;
}

컴파일러는 실제로 다음과 같이 출력합니다.

int main()
{
    int TheDay = 1; // Monday is the second enumeration, hence 1. Sunday would be 0.
}

따라서 C 열거를 문자열로 출력하는 것은 컴파일러에게 의미가 있는 작업이 아닙니다.이러한 문자열을 사람이 읽을 수 있도록 하려면 열거에서 문자열로 변환하는 함수를 정의해야 합니다.

처음이지만 스위치 스테이트먼트는 확실히 유효합니다.

#include <stdio.h>

enum mycolor;

int main(int argc, const char * argv[])

{
enum Days{Sunday=1,Monday=2,Tuesday=3,Wednesday=4,Thursday=5,Friday=6,Saturday=7};

enum Days TheDay;


printf("Please enter the day of the week (0 to 6)\n");

scanf("%d",&TheDay);

switch (TheDay)
 {

case Sunday:
        printf("the selected day is sunday");
        break;
    case Monday:
        printf("the selected day is monday");
        break;
    case Tuesday:
        printf("the selected day is Tuesday");
        break;
    case Wednesday:
        printf("the selected day is Wednesday");
        break;
    case Thursday:
        printf("the selected day is thursday");
        break;
    case Friday:
        printf("the selected day is friday");
        break;
    case Saturday:
        printf("the selected day is Saturaday");
        break;
    default:
        break;
}

return 0;
}

또 다른 해결책이 있습니다.고유한 동적 열거 클래스를 만듭니다., 0이 ,struct, 도 있습니다.이를 에 합니다.struct각 요소에는 이름에 문자열이 있습니다.또한 개별 요소를 저장하기 위한 유형, 비교하기 위한 함수 등이 있습니다.하다

#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


struct Enumeration_element_T
{
  size_t index;
  struct Enumeration_T *parent;
  char *name;
};

struct Enumeration_T
{
  size_t len;
  struct Enumeration_element_T elements[];
};
  


void enumeration_delete(struct Enumeration_T *self)
{
  if(self)
  {
    while(self->len--)
    {
      free(self->elements[self->len].name);
    }
    free(self);
  }
}

struct Enumeration_T *enumeration_create(size_t len,...)
{
  //We do not check for size_t overflows, but we should.
  struct Enumeration_T *self=malloc(sizeof(self)+sizeof(self->elements[0])*len);
  if(!self)
  {
    return NULL;
  }
  self->len=0;
  va_list l; 
  va_start(l,len);
  for(size_t i=0;i<len;i++)
  {
    const char *name=va_arg(l,const char *);
    self->elements[i].name=malloc(strlen(name)+1);
    if(!self->elements[i].name)
    {
      enumeration_delete(self);
      return NULL;
    }
    strcpy(self->elements[i].name,name);
    self->len++;
  }
  return self;
}


bool enumeration_isEqual(struct Enumeration_element_T *a,struct Enumeration_element_T *b)
{
  return a->parent==b->parent && a->index==b->index;
}

bool enumeration_isName(struct Enumeration_element_T *a, const char *name)
{
  return !strcmp(a->name,name);
}

const char *enumeration_getName(struct Enumeration_element_T *a)
{
  return a->name;
}

struct Enumeration_element_T *enumeration_getFromName(struct Enumeration_T *self, const char *name)
{
  for(size_t i=0;i<self->len;i++)
  {
    if(enumeration_isName(&self->elements[i],name))
    {
      return &self->elements[i];
    }
  }
  return NULL;
}
  
struct Enumeration_element_T *enumeration_get(struct Enumeration_T *self, size_t index)
{
  return &self->elements[index];
}

size_t enumeration_getCount(struct Enumeration_T *self)
{
  return self->len;
}

bool enumeration_isInRange(struct Enumeration_T *self, size_t index)
{
  return index<self->len;
}



int main(void)
{
  struct Enumeration_T *weekdays=enumeration_create(7,"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday");
  if(!weekdays)
  {
    return 1;
  }
    
  printf("Please enter the day of the week (0 to 6)\n");
  size_t j = 0;
  if(scanf("%zu",&j)!=1)
  {
    enumeration_delete(weekdays);
    return 1;
  }
  // j=j%enumeration_getCount(weekdays); //alternative way to make sure j is in range
  if(!enumeration_isInRange(weekdays,j))
  {
    enumeration_delete(weekdays);
    return 1;
  }

  struct Enumeration_element_T *day=enumeration_get(weekdays,j);
  

  printf("%s\n",enumeration_getName(day));
  
  enumeration_delete(weekdays);

  return 0;
}

열거 기능은 번역 단위로 해야 하는데, 쉽게 하기 위해 여기에 결합했습니다.

장점은 이 솔루션이 유연하고 DRY 원칙에 따라 정보를 각 요소와 함께 저장할 수 있으며 실행 시 새 열거를 작성할 수 있으며 실행 시 새 요소를 추가할 수 있다는 것입니다.단점은 이것이 복잡하고, 동적 메모리 할당이 필요하며, 사용할 수 없다는 것입니다.switch-case더 많은 메모리가 필요하고 속도가 느립니다.문제는 이것이 필요한 경우 더 높은 수준의 언어를 사용하면 안 되는가 하는 것입니다.

언급URL : https://stackoverflow.com/questions/3168306/print-text-instead-of-value-from-c-enum

반응형