tags:

views:

152

answers:

7

Hello,

I need to convert an enumeration member (its value, not the identifier) to a string. I have tried the following, which works for a MACRO (TYPE_A), but not for an enum value (typeA). This is a little bit strange in my opinion.

Do you have any idea how to do this?


#define _tostr(a) #a
#define tostr(a) _tostr(a)

typedef enum _SPECIAL_FOLDER_ID {
    typeA = 3,
    typeB = 4,
} SPECIAL_FOLDER_ID;

#define TYPE_A 3

int main() {
    //this is working, but the information is a macro (TYPE_A)
    printf("The string is " tostr(TYPE_A) ".\n");

    //this is not working for typeA (defined in an enumeration)
    printf("The string is " tostr(typeA) ".\n");
    return 0;
}


The output is:

The string is 3.
The string is typeA.

I need to modify the code in some way so that the second line of the output will be "The string is 3."

Thanks!

PS: I do not want to print the value using printf. I need a static string containing that value. I only use printf to test the result...

+2  A: 

Whats wrong with the following?

printf("The string is %d.\n", typeA );

You seem to be overcomplicating matters somewhat ...

Goz
You beat me by 18 seconds :)
qrdl
I do not want to print the string, but a need a static string having that representation. The issue is not printf here...
botismarius
Well then, AFAIK, you can't do it.You could create an array of strings the same length as the enum and update it manually. But there is no other way to my knowledge.
Goz
A: 

What's wrong with good old formated output?

printf("The string is %d", typeA)
qrdl
I need a static string containing that value (a string that is known at compile time)
botismarius
-1 cause @botismarius was clear it wasn't what they wanted. Why that doesn't work for them is not relevent in answering this question.
Aftermathew
@Aftermathews I've answered the original question, OP edited the question after that, so your downvote is unfair.
qrdl
sorry @qrdl, didn't know that. The system won't let me change my vote unless someone edits the question again. The system wouldn't allow me to change my vote back to 0 originally, only +1 or -1 after I initially entered a value. That seems like a pretty lame "feature" to me.
Aftermathew
right :)+1 from me and -1 from Aftermathew restores the original score.
botismarius
A: 

Using the two nested macros is a trick that forces the preprocessor expand any macro arguments (TYPE_A -> 3).

Enum values, however, are not expanded by the preprocessor, they are expanded by the compiler.

gnud
+3  A: 

The preprocessor does not know C. It simply knows "text".
When it processes your file, typeA is just 5 letters. Only the compiler will know (after the preprocessor is done) that typeA has a value, and that the value is 3.

pmg
to be nitpicky: what the preprocessor knows about are preprocessing tokens
Christoph
http://99-bottles-of-beer.net/language-c-c++-preprocessor-115.html It's possible to make the preprocessor (kinda) intelligent :)
pmg
A: 

There is no automatic way to do this since the compiler converts ENUMs to literal numbers.

The easy way is to have a static array of strings and be careful to keep it in sync.

char names[][8] { "","","","typeA","typeB", etc }
Then just use "names[typeA]"

A safer way is to have a function with a big switch statement.

Martin Beckett
+2  A: 

There's not really a good way to accomplish this. The best I could come up with is

#define typeA_ 3
#define typeB_ 4

enum
{
    typeA = typeA_,
    typeB = typeB_
};

#define tostr__(E) #E
#define tostr_(E) tostr__(E)
#define tostr(E) tostr_(E ## _)
Christoph
+1  A: 

I tend to use the static array approach. It's still a kluge, but it's reasonably clear and it works.

enum {
  typeA = 3,
  typeB = 4,
  NUM_LETTERS = 5
} Letters;

static const char* letterNames[NUM_LETTERS] {
  "", "", "",
  "3",
  "4"
};

printf("The string is " letterNames[(int)typeA] ".\n");

It looks as though Christoph's answer is good, but I have to be honest that I'm not familiar enough with macros to understand it ;-)

Edit; Another way: You mention that you want a 'static string' but I'm not sure that you need it at compile time. Can you use sprintf at the start of runtime? This solution would look something like this...

enum {
  typeA = 3,
  typeB = 4,
  NUM_LETTERS = 5
} Letters;


int main(void){
    char * typeAString = new char[sizeof("This is at least as long as the typeA string")];
    sprintf(typeAString, "This is the %d string", typeA);
    // use your string here
    return 0;
}

The way I used new here is not what I would recommend, but it shows of the idea of using sprintf in your program.

Aftermathew
I cannot make your snippet compile.
pmg