Thread: Free program I'm sharing: ConvertEnumToStrings

  1. #91
    Registered User
    Join Date
    Oct 2008
    Posts
    1,262
    I've hacked together something for this that kind of sucks. It needs some work probably, but it doesn't involve the use of an external program. But maybe this gives others an idea for a better solutions.

    This is the code in "Enums.h":
    Code:
    #ifndef ENUMS_H_
    #define ENUMS_H_
    
    #include <string>
    #include <map>
    typedef std::map<unsigned int, std::string> EnumToName_;
    
    /* Step 1: Add the enums to the project */
    #define ENUM_START(Name) extern EnumToName_ Name##ToString; \
                             enum Name {
    #define ENUM_END         };
    #define ENUM_ITEM(Name)  Name
    #include "Enums"
    #undef  ENUM_START
    #undef  ENUM_END
    #undef  ENUM_ITEM
    
    /* Step 2: Generate the enum name lookup */
    #ifdef ENUMS_H_INCLUDE_MAP
      #define ENUM_START(Name) EnumToName_ Name##ToString;       \
                               struct Name##EnumToStringInit_ {  \
                                 Name##EnumToStringInit_() {     \
                                   int ignore, ignore2 = 0;      \
                                   EnumToName_ &cmap = Name##ToString;
      #define ENUM_ITEM(Name)      cmap[Name] = #Name; ignore = ignore2
      #define ENUM_END             ; \
                                 }   \
                               } Name##EnumToStringInit__;
    
      #include "Enums"
      #undef  ENUM_START
      #undef  ENUM_END
      #undef  ENUM_ITEM
    #endif
    
    #endif
    To use it, create a file called "Enums" (no extension), and add as many enums as you like like this:
    Code:
    ENUM_START(NameOfEnum)
    	ENUM_ITEM(ItemName),
    	ENUM_ITEM(ItemName2),
    	ENUM_ITEM(ItemName3) = 500
    ENUM_END
    Now, include Enums.h from where ever you need any of the enums. Make sure that in exactly one of the files (Enum.cpp or the main file), you use:
    Code:
    #define ENUMS_H_INCLUDE_MAP
    before you include Enums.h.

    Now, everywhere, you can use the enum normally (though only in global scope, but I couldn't think of a better solution), or use the enum name with appended "ToString". For instance, in the above case, that would be "NameOfEnumToString".

    As I said, it kind of sucks. Any better ideas for such a thing, so scoping doesn't matter (and there are a few other known flaws with this method)...

    Anyways, it works like this: it defines some macro's that normally only make the enum work (adding enum { around it and stuff). When the ENUMS_H_INCLUDE_MAP is defined, it will include "Enums" twice, the second time it generates a struct that populates a map with the proper name...

    Any better ideas for a hack method like this? ;-)
    Last edited by EVOEx; 06-12-2010 at 04:25 AM.

  2. #92
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Quote Originally Posted by Elysia View Post
    Code:
                    if (inputFilePath.at(i) < 'a') {
                        if (inputFilePath.at(i) != '_') {
                            if (inputFilePath.at(i) < 'A') {
                                if (inputFilePath.at(i) != '/') {
                                    if (inputFilePath.at(i) != '.') {
                                        if (inputFilePath.at(i) != ' ') {
    I LOLed at this. Try using the && operator.
    Which part?
    Hey, it works...
    I know I could use the '&&' operator, but I prefer to use my method because the if condition would end up being too long.

  3. #93
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    But the amount of levels is severely reduced. You can wrap the condition if it becomes too long.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  4. #94
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Quote Originally Posted by Elysia View Post
    But the amount of levels is severely reduced. You can wrap the condition if it becomes too long.
    Ok, how do I wrap it?

  5. #95
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Newlines. Like everything else. Eg:
    Code:
    if (inputFilePath.at(i) < 'a' && 
        inputFilePath.at(i) != '_')
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  6. #96
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Quote Originally Posted by Elysia View Post
    Newlines. Like everything else. Eg:
    Code:
    if (inputFilePath.at(i) < 'a' && 
        inputFilePath.at(i) != '_')
    Oh, duh...
    I should have guessed that.
    I forgot whitespace doesn't make any difference in code, because the compiler searches for the terminating characters.

  7. #97
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Ok, I changed it to one if statement:

    Code:
    if (inputFilePath.at(i) < 'a' &&
        inputFilePath.at(i) != '_' &&
        inputFilePath.at(i) < 'A' &&
        inputFilePath.at(i) != '/' &&
        inputFilePath.at(i) != '.' &&
        inputFilePath.at(i) != ' ') {
            cout<< "\nError! You did not use the correct format in your input filepath.\n"
                   "Please try again."<<endl;
            cout<< help() <<endl; //print help message
            cout<< "\n\nPress Enter to end this program." <<endl;
            cin.get(); //make the user press Enter
            return 1; //since the user inputted an unallowed character in the input filepath
    }
    Last edited by Programmer_P; 06-12-2010 at 08:16 AM. Reason: fixed formatting

  8. #98
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Quote Originally Posted by EVOEx View Post
    I've hacked together something for this that kind of sucks. It needs some work probably, but it doesn't involve the use of an external program. But maybe this gives others an idea for a better solutions.

    This is the code in "Enums.h":
    Code:
    #ifndef ENUMS_H_
    #define ENUMS_H_
    
    #include <string>
    #include <map>
    typedef std::map<unsigned int, std::string> EnumToName_;
    
    /* Step 1: Add the enums to the project */
    #define ENUM_START(Name) extern EnumToName_ Name##ToString; \
                             enum Name {
    #define ENUM_END         };
    #define ENUM_ITEM(Name)  Name
    #include "Enums"
    #undef  ENUM_START
    #undef  ENUM_END
    #undef  ENUM_ITEM
    
    /* Step 2: Generate the enum name lookup */
    #ifdef ENUMS_H_INCLUDE_MAP
      #define ENUM_START(Name) EnumToName_ Name##ToString;       \
                               struct Name##EnumToStringInit_ {  \
                                 Name##EnumToStringInit_() {     \
                                   int ignore, ignore2 = 0;      \
                                   EnumToName_ &cmap = Name##ToString;
      #define ENUM_ITEM(Name)      cmap[Name] = #Name; ignore = ignore2
      #define ENUM_END             ; \
                                 }   \
                               } Name##EnumToStringInit__;
    
      #include "Enums"
      #undef  ENUM_START
      #undef  ENUM_END
      #undef  ENUM_ITEM
    #endif
    
    #endif
    To use it, create a file called "Enums" (no extension), and add as many enums as you like like this:
    Code:
    ENUM_START(NameOfEnum)
    	ENUM_ITEM(ItemName),
    	ENUM_ITEM(ItemName2),
    	ENUM_ITEM(ItemName3) = 500
    ENUM_END
    Now, include Enums.h from where ever you need any of the enums. Make sure that in exactly one of the files (Enum.cpp or the main file), you use:
    Code:
    #define ENUMS_H_INCLUDE_MAP
    before you include Enums.h.

    Now, everywhere, you can use the enum normally (though only in global scope, but I couldn't think of a better solution), or use the enum name with appended "ToString". For instance, in the above case, that would be "NameOfEnumToString".

    As I said, it kind of sucks. Any better ideas for such a thing, so scoping doesn't matter (and there are a few other known flaws with this method)...

    Anyways, it works like this: it defines some macro's that normally only make the enum work (adding enum { around it and stuff). When the ENUMS_H_INCLUDE_MAP is defined, it will include "Enums" twice, the second time it generates a struct that populates a map with the proper name...

    Any better ideas for a hack method like this? ;-)
    Yeah, one that works with a normal enum and doesn't depend on global scopes.
    Btw, what is this line doing in your enums.h code:
    Code:
    #include "Enums"
    ? I thought you said "Enums" is supposed to include "enums.h", not the other way around...
    Last edited by Programmer_P; 06-12-2010 at 09:03 AM.
    I'm an alien from another world. Planet Earth is only my vacation home, and I'm not liking it.

  9. #99
    Registered User
    Join Date
    Oct 2008
    Posts
    1,262
    Quote Originally Posted by Programmer_P View Post
    Yeah, one that works with a normal enum and doesn't depend on global scopes.
    Yeah, the global scope bit is a problem as I said. But it might be possible to overcome. One that works with a normal enum... I disagree: I'd rather use a "special" enum like this than having to run an external program to dump that stuff into the application.

  10. #100
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Quote Originally Posted by EVOEx View Post
    Yeah, the global scope bit is a problem as I said. But it might be possible to overcome. One that works with a normal enum... I disagree: I'd rather use a "special" enum like this than having to run an external program to dump that stuff into the application.
    Well, I'm interested enough to try it if you ever get it working with non-global enums.
    Until then, I'll use ConvertEnumToStrings, and everyone else is free to use whatever they want as well.

    Oh, and seeing as I'm sharing the source code of the program, someone could easily programmatically convert an enum in another file to strings if they include the "CconvertEnumToStrings.h" file in a source of their program, create an object of class CconvertEnumToStrings and make use of the member functions.
    Look at the implementation in ConvertEnumToStrings.cpp to get an idea of how to do that.
    Last edited by Programmer_P; 06-12-2010 at 10:10 AM.
    I'm an alien from another world. Planet Earth is only my vacation home, and I'm not liking it.

  11. #101
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Ok, I now have all links to the ConvertEnumToStrings stuff in this post in response to C_ntua's request for a makefile:

    http://cboard.cprogramming.com/proje...tml#post953078
    I'm an alien from another world. Planet Earth is only my vacation home, and I'm not liking it.

  12. #102
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Ok, latest version is the last one (I think).
    I made a few minor changes to the implementation, as well as adding the map functionality in (which I guess I should have done from the beginning).
    Now, its easy to get all enumerators' values (both explicit and implicit) from an enum, using the string names of the enumerators. Since I provide the methods to get a vector<string> namesOfEnumerators and a vector<int>valuesOfEnumerators as well as a map <string, int> enumeratorsMap, its quite easy to iterate through the enum, and retrieve a value without hand-coding all the enumerator names of the enum (which was the whole objective all along anyway).

    A few notes:

    1. The program is designed to operate on C++ enum source code alone. Hence it cannot determine the value of a variable at runtime in your program, so you cannot use any variable names in enumerator assignments, or it wont work.
    2. You obviously should make sure your enum is valid first before passing the filepath to the file containing it to ConvertEnumToStrings.
    3. Formatting shouldn't be a issue now. It should handle single-line enums and multi-line enums with ease, and anything in between.
    4. Multiple enums with the same name in a single file are not handled that well. I wrote it so it'll handle the first enum in a file with a name, and then ignore later enums with the same name. This shouldn't be a problem though, as you really shouldn't be using multiple enums with the same name in a single file anyway.
    5. Thanks to everyone at the boards here who helped me achieve my goal. I really appreciate it.

    Here's a listing of the functions generated to file by ConvertEnumToStrings:

    Code:
    const vector<string>& getNamesOfEnumerators();
    const vector<int>& getValuesOfEnumerators();
    const string& getNameOfEnum();
    const int& getNumOfEnumerators();
    const map<string, int>& getEnumeratorsMap();
    const int& getEnumeratorValue(enumName enumerator);
    Note that all these functions are members of the relevant class generated for a specific enum. Each enum found in a file has its own class with its own functions generated for it. The classes' names will always look like this:

    CenumNameToStrings
    where "enumName" is the actual name of a given enum. So its easy to remember what the name of a generated enum class is, so you can create an object of it, and call the provided functions. So, say you have a file with the following enums in it:

    Code:
    enum Work {
    
      hard = 1,
      lazy = -1
    
    };
    
    //A little later in the file...
    
    enum Day {
    
      Sunday = 1,
      Monday,
      Tuesday,
      Wednesday,
      Thursday,
      Friday,
      Saturday
    
    }currentDay;
    ConvertEnumToStrings will generate a class called "CWorkToStrings" with the afore-mentioned member functions for the first enum it finds. And then it will generate a separate class for enum "Day" called "CDayToStrings" with its own functions which are given the same names as those functions in the other enum's class. This keeps everything nicely grouped and organized. So you can then just include the results file in your program, create an object of either class, and call its functions, and do whatever you want with the results after.

    Cheers.

    Oh, and I almost forgot...

    Here's the new download link:
    http://dl.dropbox.com/u/8029532/Conv...mToStrings.zip
    I'm an alien from another world. Planet Earth is only my vacation home, and I'm not liking it.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. im a noob at c++, do you think so?
    By belRasho in forum C++ Programming
    Replies: 6
    Last Post: 04-25-2010, 11:02 PM
  2. Client-server system with input from separate program
    By robot-ic in forum Networking/Device Communication
    Replies: 3
    Last Post: 01-16-2009, 03:30 PM
  3. help sharing a program with friends...
    By fingerlickin in forum C# Programming
    Replies: 1
    Last Post: 11-05-2005, 09:54 AM
  4. Replies: 3
    Last Post: 03-04-2005, 02:46 PM
  5. Making a program to free up Ram memory
    By cfrost in forum Windows Programming
    Replies: 1
    Last Post: 10-03-2004, 06:52 AM