2012-04-05 73 views
6

我有一個C程序與錯誤代碼的一些定義。就像這樣:按值打印#define的名稱?

#define FILE_NOT_FOUND -2 
#define FILE_INVALID -3 
#define INTERNAL_ERROR -4 
#define ... 
#define ... 

是否可以打印由它的價值定義的名字嗎?像這樣:

PRINT_NAME(-2); 

// output 
FILE_NOT_FOUND 
+0

我認爲,沒有它可能做這樣的事情在C.也許與一些OOP語言,如C#和思考。 – Jack 2012-04-05 17:16:35

+0

c預處理器替換名稱。你需要反思。你可以使用CERN Reflections https://root.cern.ch/how/how-use-reflex https://stackoverflow.com/questions/359237/why-does-c-not-have-reflection – katta 2017-10-05 21:39:59

回答

3

不,這是不可能的。這將打印什麼?

#define FILE_NOT_FOUND 1 
#define UNIT_COST  1 
#define EGGS_PER_RATCHET 1 

PRINT_NAME(1); 
1

有點兒......

#define ERROR_CODE_1 "FILE_NOT_FOUND" 
#define ERROR_CODE_2 "FILE_FOUND" 

#define PRINT_NAME(N) ERROR_CODE_ ## N 

或:

static char* error_codes(int err) { 
    static char name[256][256] = { 

    }; 
    int base = .... lowest error code; 
    return name[err - base]; 
} 

#define PRINT_NAME(N) error_code(N) 
1

爲什麼不選擇使用枚舉呢?

enum errors {FILE_NOT_FOUND = -2, FILE_INVALID = -3, INTERNAL_ERROR = -4}; 

FILE *fp = fopen("file.txt", "r"); 


if(fp == NULL) { 
    printf("Error\n"); 
    exit(FILE_NOT_FOUND); 
} 
5

總之,沒有。要做到這一點,最簡單的辦法就是像這樣(請注意:這是假定你永遠不能有一個分配給零/零錯誤):

//Should really be wrapping numerical definitions in parentheses. 
#define FILE_NOT_FOUND (-2) 
#define FILE_INVALID (-3) 
#define INTERNAL_ERROR (-4) 

typdef struct { 
    int errorCode; 
    const char* errorString; 
} errorType; 

const errorType[] = { 
    {FILE_NOT_FOUND, "FILE_NOT_FOUND" }, 
    {FILE_INVALID, "FILE_INVALID" }, 
    {INTERNAL_ERROR, "INTERNAL_ERROR" }, 
    {NULL,   "NULL"   }, 
}; 

// Now we just need a function to perform a simple search 
int errorIndex(int errorValue) { 
    int i; 
    bool found = false; 
    for(i=0; errorType[i] != NULL; i++) { 
    if(errorType[i].errorCode == errorValue) { 
     //Found the correct error index value 
     found = true; 
     break; 
    } 
    } 
    if(found) { 
    printf("Error number: %d (%s) found at index %d",errorType[i].errorCode, errorType[i].errorString, i); 
    } else { 
    printf("Invalid error code provided!"); 
    } 
    if(found) { 
    return i; 
    } else { 
    return -1; 
    } 
} 

享受!

此外,如果你想節省打字甚至更多,你可以使用一個預處理宏,使其更簡潔:

#define NEW_ERROR_TYPE(ERR) {ERR, #ERR} 
const errorType[] = { 
     NEW_ERROR_TYPE(FILE_NOT_FOUND), 
     NEW_ERROR_TYPE(FILE_INVALID), 
     NEW_ERROR_TYPE(INTERNAL_ERROR), 
     NEW_ERROR_TYPE(NULL) 
    }; 

現在,你只需要一次輸入宏名,減少的機會錯別字。

+0

+1看起來是單一方式。 – Jack 2012-04-05 17:20:50

1

不自動。編譯過程中名稱丟失,代碼中只保留常量。

但是你可以建立這樣的事情:

const char * a[] = {"","","FILE_NOT_FOUND","FILE_INVALID"}; 

,並通過定義值絕對值作爲索引來訪問它。

1

爲此使用C99的指定初始值設定項,但如果您的錯誤代碼爲負值,則需要小心謹慎。

首先爲正值版本:

#define CODE(C) [C] = #C 

static 
char const*const codeArray[] = { 
CODE(EONE), 
CODE(ETWO), 
CODE(ETHREE), 
}; 

enum { maxCode = (sizeof codeArray/ sizeof codeArray[0]) }; 

這種分配一個數組,你需要的長度,並在合適的位置字符串指針。請注意,標準允許重複值,最後一個值將實際存儲在數組中。

要打印錯誤代碼,您必須檢查索引是否小於maxCode

如果您的錯誤代碼總是負數,您只需在打印之前取消代碼。但是反過來這樣做可能是一個好主意:讓代碼成爲正數並檢查其符號的返回值。如果它是負值,則錯誤代碼將是該值的否定。

0

這是我如何做到這一點在C:

< MyDefines.h>

#pragma once 

#ifdef DECLARE_DEFINE_NAMES 
// Switch-case macro for getting defines names 
#define BEGIN_DEFINE_LIST const char* GetDefineName (int key) { switch (key) { 
#define MY_DEFINE(name, value) case value: return #name; 
#define END_DEFINE_LIST } return "Unknown"; } 

#else 

// Macros for declaring defines 
#define BEGIN_COMMAND_LIST /* nothing */ 
#define MY_DEFINE(name, value) static const int name = value; 
#define END_COMMAND_LIST /* nothing */ 

#endif 

// Declare your defines 
BEGIN_DEFINE_LIST 

MY_DEFINE(SUCCEEDED,  0) 
MY_DEFINE(FAILED,   -1) 
MY_DEFINE(FILE_NOT_FOUND, -2) 
MY_DEFINE(INVALID_FILE, -3) 
MY_DEFINE(INTERNAL_ERROR -4) 
etc... 

END_DEFINE_LIST 

< MyDefineInfo.h>

#pragma once 
const char* GetDefineName(int key); 

< MyDefineInfo.c>

#define DECLARE_DEFINE_NAMES 
#include "MyDefines.h" 

現在,你可以使用聲明的switch-case宏的地方是這樣的:

< WhereEver.c>

#include "MyDefines.h" 
#include "MyDefineInfo.h" 

void PrintThings() 
{ 
    Print(GetDefineName(SUCCEEDED)); 
    Print(GetDefineName(INTERNAL_ERROR)); 
    Print(GetDefineName(-1); 
    // etc. 
} 
1

你可以做這樣的事情。

#include <stdio.h> 

#define FILE_NOT_FOUND -2 
#define FILE_INVALID -3 
#define INTERNAL_ERROR -4 

const char* name(int value) { 
#define NAME(ERR) case ERR: return #ERR; 
    switch (value) { 
     NAME(FILE_NOT_FOUND) 
     NAME(FILE_INVALID) 
     NAME(INTERNAL_ERROR) 
    } 
    return "unknown"; 
#undef NAME 
} 

int main() { 
    printf("==== %d %s %s\n", FILE_NOT_FOUND, name(FILE_NOT_FOUND), name(-2)); 
} 
+0

我最喜歡這個版本,因爲與基於數組的解決方案不同,如果您碰巧有不明確/重複的錯誤代碼,它會給您一個編譯器錯誤。 – 5gon12eder 2015-12-16 20:35:41