Printing the name #define by its value?

I have a C program with some error code definitions. Like this:

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

Is it possible to print the name of a definition by its value? Like this:

 PRINT_NAME(-2); // output FILE_NOT_FOUND 
+6
source share
8 answers

In short, no. The easiest way to do this is with something like this (PLEASE NOTE: this assumes you can never have a zero / zero error):

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

Enjoy it!

Also, if you want to type more text, you can use the preprocessor macro to make it even more neat:

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

Now you only need to enter the macro name once, reducing the chance of typos.

+5
source

No, It is Immpossible. What would it print?

 #define FILE_NOT_FOUND 1 #define UNIT_COST 1 #define EGGS_PER_RATCHET 1 PRINT_NAME(1); 
+3
source

Kind...

 #define ERROR_CODE_1 "FILE_NOT_FOUND" #define ERROR_CODE_2 "FILE_FOUND" #define PRINT_NAME(N) ERROR_CODE_ ## N 

or

 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
source

Why not choose an enumeration instead?

 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); } 
+1
source

Not automatically. The name is lost at compile time, and only a constant number remains in the code.

But you can build something like this:

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

and access it using the absolute value of the parameter value as an index.

+1
source

To do this, use the designated C99 initializers, but care needs to be taken if your error codes are negative.

First version for positive values:

 #define CODE(C) [C] = #C static char const*const codeArray[] = { CODE(EONE), CODE(ETWO), CODE(ETHREE), }; enum { maxCode = (sizeof codeArray/ sizeof codeArray[0]) }; 

An array with the required length and line pointers in the correct positions is allocated here. Note that duplicate values ​​are allowed by the standard, the latter is the one that is actually stored in the array.

To print the error code, you will need to check if the index is less than maxCode .

If your error codes are always negative, you just need to cancel the code before printing. But it's probably not bad to do the opposite: have codes positive and check the return value for your character. If this is a negative error code it will be a negation of the value.

+1
source

You can do something like this.

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

Here's how I do it in 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" 

Now you can use the declared switch-case macro wherever possible:

<WhereEver.c>

 #include "MyDefines.h" #include "MyDefineInfo.h" void PrintThings() { Print(GetDefineName(SUCCEEDED)); Print(GetDefineName(INTERNAL_ERROR)); Print(GetDefineName(-1); // etc. } 
0
source

Source: https://habr.com/ru/post/912517/


All Articles