2012-04-05 11 views
6

Tôi có một chương trình C với một số định nghĩa cho mã lỗi. Như thế này:In tên #define theo giá trị của nó?

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

Có thể in tên định nghĩa theo giá trị của nó không? Như thế này:

PRINT_NAME(-2); 

// output 
FILE_NOT_FOUND 
+0

Tôi nghĩ rằng không thể làm điều gì đó giống như trong C. Có thể bằng một số ngôn ngữ có OOP, như C# và phản xạ. Bộ xử lý trước – Jack

+0

c thay thế tên. Bạn cần phản xạ. bạn có thể sử dụng Phản ánh CERN https://root.cern.ch/how/how-use-reflex https://stackoverflow.com/questions/359237/why-does-c-not-have-reflection – katta

Trả lời

3

Không, điều đó là không thể. Điều này sẽ in gì?

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

PRINT_NAME(1); 
1

Kinda ...

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

#define PRINT_NAME(N) ERROR_CODE_ ## N 

hay:

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

Tại sao không chọn sử dụng một điều tra để thay thế?

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

Tóm lại, không. Cách dễ nhất để thực hiện việc này sẽ giống như vậy (XIN LƯU Ý: điều này giả định rằng bạn không bao giờ có lỗi được gán cho số không/không):

//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; 
    } 
} 

Tận hưởng!

Ngoài ra, nếu bạn muốn tiết kiệm gõ hơn nữa, bạn có thể sử dụng một macro tiền xử lý để làm cho nó thậm chí neater:

#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) 
    }; 

Bây giờ bạn chỉ cần gõ tên vĩ mô một lần, làm giảm nguy cơ lỗi chính tả.

+0

+1 Có vẻ như Một chiều. – Jack

1

Không tự động. Tên bị mất trong quá trình biên dịch và chỉ có số không đổi vẫn còn trong mã.

Nhưng bạn có thể xây dựng một cái gì đó như thế này:

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

và truy cập nó bằng cách sử dụng xác định giá trị giá trị tuyệt đối như chỉ mục.

1

Sử dụng bộ khởi tạo C99 được chỉ định cho điều này, nhưng cần phải cẩn thận một chút nếu mã lỗi của bạn là số âm.

Lần đầu tiên một phiên bản cho các giá trị tích cực:

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

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

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

này phân bổ một mảng với chiều dài mà bạn cần và với các con trỏ chuỗi tại các vị trí đúng. Lưu ý rằng các giá trị trùng lặp được cho phép theo tiêu chuẩn, giá trị cuối cùng sẽ là giá trị thực sự được lưu trữ trong mảng.

Để in mã lỗi, bạn phải kiểm tra xem chỉ mục có nhỏ hơn maxCode hay không.

Nếu mã lỗi của bạn luôn âm, bạn chỉ cần từ chối mã trước khi in. Nhưng nó có lẽ là một ý tưởng tốt để làm điều đó theo cách khác vòng: có các mã được tích cực và kiểm tra một giá trị trả lại cho dấu hiệu của nó. Nếu nó là tiêu cực, mã lỗi sẽ là sự phủ định của giá trị.

0

Đây là cách tôi làm điều đó trong 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" 

Bây giờ, bạn có thể sử dụng các tuyên bố chuyển đổi hợp cụ vĩ mô bất cứ nơi nào như thế này:

< WhereEver.c>

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

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

Bạn có thể làm một cái gì đó như thế này.

#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

Tôi thích phiên bản này tốt nhất bởi vì không giống như các giải pháp dựa trên mảng, nó cung cấp cho bạn một lỗi biên dịch nếu bạn tình cờ có các mã lỗi không rõ ràng/trùng lặp. – 5gon12eder