2017-12-19 31 views
4

해당 오류 메시지에 매핑해야하는 오류 코드 (011011203040, ...)가 있습니다. 오류 코드는 편리하게 배열로 indeces로 사용할 수 없으므로 (이는 희소하고 낭비입니다) 나는 이것이 매크로 및/또는 열거 형으로 어떻게 든 수행 될 수 있다고 생각합니다.정수를 const 문자열에 프로그래밍 방식으로 매핑하는 방법은 무엇입니까?

기본적으로 나는 const char *my_strerror(int errorcode) 함수를 만들려고합니다.

const char *err00 = "an error message"; 
const char *err01 = "a different one"; 
const char *err10 = "another one"; 

const char* chatter_strerror(int error){ 
    switch(error){ 
     case 0: 
      return err00; 
     case 1: 
      return err01; 
     case 10: 
      return err10; 

     .... // 10 more cases 
    } 
} 

확실히 더 좋은 방법이 있습니까?

+0

당신은 가능한 한 효율적으로 스위치를 소문자로 컴파일러를 신뢰할 수 있습니다. 네, 이것이 최선의 방법입니다. –

+0

매크로는 컴파일 할 때 평가되기 때문에 매크로로 처리 할 수 ​​없습니다. 런타임 중에 오류 코드가 생성되었다고 확신합니다. –

+0

@AjayBrahmakshatriya 하나의 오류 코드는 하나의 오류 메시지에만 해당하며 컴파일시 정적입니다. 그리고 접근 방식의 효율성에 관심이 없기 때문에 구현의 우아함, 단순성, 확장 성 및 자세한 정보에 더 관심이 있습니다. – vasia

답변

4

한 가지 해결책은 오류 코드에 대한 int 필드와 오류 메시지에 대한 char * 필드를 포함하는 오류 메시지 구조를 만드는 것입니다. 그런 다음 오류 코드 struct의 배열을 오류 코드 및 메시지와 함께 초기화 할 수 있습니다. 이 방법을 사용하면 코드를 새로운 오류 메시지로 쉽게 업데이트 할 수 있으며 .msg 필드에 오류 메시지 배열의 마지막 부분 인 struct이 null 포인터가있는 센티널로 사용되는 경우 배열을 반복하는 함수는 알 필요가 없습니다 얼마나 많은 요소가 들어 있는지.

다음은 예입니다. get_error() 함수는 배열을 반복하며 원하는 오류 코드가 발생하면 루프를 벗어납니다. 센티널 값에 도달하여 일치하는 항목이 없으면 "인식 할 수없는 오류 코드"메시지가 반환됩니다. 새로운 오류 메시지가 error_codes[] 배열에 추가되므로 get_error() 함수를 수정할 필요가 없습니다.

#include <stdio.h> 

struct Errors 
{ 
    const char *msg; 
    int code; 
}; 

struct Errors error_codes[] = { 
    { .code = 1, .msg = "input error" }, 
    { .code = 5, .msg = "format error" }, 
    { .code = 10, .msg = "allocation error" }, 
    { .msg = NULL } 
}; 

const char * get_error(int err_code); 

int main(void) 
{ 
    printf("Error: %s\n", get_error(1)); 
    printf("Error: %s\n", get_error(5)); 
    printf("Error: %s\n", get_error(10)); 
    printf("Error: %s\n", get_error(-1)); 

    return 0; 
} 

const char * get_error(int err_code) 
{ 
    struct Errors *current = error_codes; 
    const char *ret_msg = "Unrecognized error code"; 

    while (current->msg) { 
     if (current->code == err_code) { 
       ret_msg = current->msg; 
       break; 
     } 
     ++current; 
    } 

    return ret_msg; 
} 

영업 이익은 int 오류 코드를 지정뿐만 아니라 enum의 언급했다. 다음은 enum을 사용한 수정입니다. 여기에 enum을 사용하면 얻을 수있는 장점 중 하나는 판독 가능성이 향상된다는 것입니다. 단점은 오류 메시지가 변경 될 때 코드를 두 곳에서 수정해야한다는 것입니다.

#include <stdio.h> 

/* Modify both the Error_Codes enum and the following error_codes[] array 
    when adding new error messages. */ 

enum Error_Codes { 
    ERRINPUT = 1, 
    ERRFORMAT = 5, 
    ERRALLOC = 10 
}; 

struct Errors 
{ 
    const char *msg; 
    enum Error_Codes code; 
}; 

struct Errors error_codes[] = { 
    { .code = ERRINPUT, .msg = "input error" }, 
    { .code = ERRFORMAT, .msg = "format error" }, 
    { .code = ERRALLOC, .msg = "allocation error" }, 
    { .msg = NULL } 
}; 

const char * get_error(enum Error_Codes err_code); 

int main(void) 
{ 
    printf("Error: %s\n", get_error(ERRINPUT)); 
    printf("Error: %s\n", get_error(ERRFORMAT)); 
    printf("Error: %s\n", get_error(ERRALLOC)); 
    printf("Error: %s\n", get_error(-1)); 

    return 0; 
} 

const char * get_error(enum Error_Codes err_code) 
{ 
    struct Errors *current = error_codes; 
    const char *ret_msg = "Unrecognized error code"; 

    while (current->msg) { 
     if (current->code == err_code) { 
       ret_msg = current->msg; 
       break; 
     } 
     ++current; 
    } 

    return ret_msg; 
} 

프로그램 출력 :

Error: input error 
Error: format error 
Error: allocation error 
Error: Unrecognized error code 
+0

이것은 내가 끝내는 접근법이 아니지만 충분히 우아합니다. 11 개 이상의 오류 코드가 있다면이 방법이 될 것입니다. 나는 const * chars의 배열, 그리고 그것에 색인을 붙이는 데 사용하는 열거 형으로 정했다.귀하의 접근 방식이 마음에 들지만, 완전히 판매되지 않은 유일한 이유는 구조체 배열을 반복하고 오류 코드를 비교해야한다는 것입니다. – vasia

+0

물론 고양이를 다듬는 많은 방법이 있습니다. 이 접근 방식에 대해 좋아하는 점은 오류 메시지를 변경하거나 추가하는 것이 쉽다는 것입니다. 한 곳에서 코드를 수정하면됩니다. 오류 메시지에 대해서는 효율성이 주요 고려 사항이라고 생각하지 않습니다. 반면에 유지 보수의 용이성은 근본적으로 중요하게 보입니다. –

+0

당신은 절대적으로 옳았으며 귀하의 접근 방법으로 전환을 고려하고 있습니다. 아무도 생성 매크로/열거 형을 사용하는 솔루션을 게시하지 않은 경우 (귀하의 것보다 더 좋습니다) (imo) 나는 이것을 곧 채택으로 표시 할 것입니다. – vasia