我有一個C程序與錯誤代碼的一些定義。就像這樣:按值打印#define的名稱?
#define FILE_NOT_FOUND -2
#define FILE_INVALID -3
#define INTERNAL_ERROR -4
#define ...
#define ...
是否可以打印由它的價值定義的名字嗎?像這樣:
PRINT_NAME(-2);
// output
FILE_NOT_FOUND
我有一個C程序與錯誤代碼的一些定義。就像這樣:按值打印#define的名稱?
#define FILE_NOT_FOUND -2
#define FILE_INVALID -3
#define INTERNAL_ERROR -4
#define ...
#define ...
是否可以打印由它的價值定義的名字嗎?像這樣:
PRINT_NAME(-2);
// output
FILE_NOT_FOUND
不,這是不可能的。這將打印什麼?
#define FILE_NOT_FOUND 1
#define UNIT_COST 1
#define EGGS_PER_RATCHET 1
PRINT_NAME(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)
爲什麼不選擇使用枚舉呢?
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);
}
總之,沒有。要做到這一點,最簡單的辦法就是像這樣(請注意:這是假定你永遠不能有一個分配給零/零錯誤):
//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)
};
現在,你只需要一次輸入宏名,減少的機會錯別字。
+1看起來是單一方式。 – Jack 2012-04-05 17:20:50
不自動。編譯過程中名稱丟失,代碼中只保留常量。
但是你可以建立這樣的事情:
const char * a[] = {"","","FILE_NOT_FOUND","FILE_INVALID"};
,並通過定義值絕對值作爲索引來訪問它。
爲此使用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
。
如果您的錯誤代碼總是負數,您只需在打印之前取消代碼。但是反過來這樣做可能是一個好主意:讓代碼成爲正數並檢查其符號的返回值。如果它是負值,則錯誤代碼將是該值的否定。
這是我如何做到這一點在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.
}
你可以做這樣的事情。
#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));
}
我最喜歡這個版本,因爲與基於數組的解決方案不同,如果您碰巧有不明確/重複的錯誤代碼,它會給您一個編譯器錯誤。 – 5gon12eder 2015-12-16 20:35:41
我認爲,沒有它可能做這樣的事情在C.也許與一些OOP語言,如C#和思考。 – Jack 2012-04-05 17:16:35
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