0

I was really hoping I could use enum's as follows

typedef enum {
    GPS_FULL_COLD = "$PMTK104*37",
    GPS_COLD = "$PMTK103*30",
    GPS_WARM = "$PMTK102*31",
    GPS_HOT = "$PMTK101*32"
} gps_start_mode;

so that I can have a function that type checks for a gps_start_mode and also has the value it needs. It seems however that c requires integral constants for enum values.

void configureStartMode(gps_start_mode mode) {
    gpsWrite(mode);
}

I was wondering if their is some other enum-like type I can use in place of enum here.

Otherwise, it seems I'll need to have a separate array to hold the string values, which isn't a huge hassle but not ideal.

user3817250
  • 1,003
  • 4
  • 14
  • 27
  • 4
    Generally, `#define` operations are used instead. Not as elegant, but folks have managed that way for decades. Another technique is to use a numeric `enum` and then pass the `enum` value to a method that returns the corresponding string. – Hot Licks Sep 02 '14 at 19:51
  • 3
    Using enum to hold indices to an array seems to be the best solution - it is simple and keeps type-checking, with cost of not-so-much boilerplate. – Frax Sep 02 '14 at 19:58

2 Answers2

2

The way I usually do this is to have an array of const char * containing strings that correspond to the elements in the enum.

The problem with this approach is that it is easy for the two data structures to become out-of-sync, for example if a new enum element is added, but the string array is not updated.

To provide some defensiveness against this, I add an additional element to the enum, which provides the number of elements in the enum. If the array of strings has static storage, then any elements not explicitly set, will automatically be set to NULL. You can therefore at least assert that the last element in the array is non-NULL resulting in immediate program termination if the string array has become out-of-sync with the enum.

Code example:

#include <stdio.h>
#include <assert.h>

typedef enum gps_start_mode_
{
    GPS_FULL_COLD,
    GPS_COLD,
    GPS_WARM,
    GPS_HOT,
    gps_num_start_modes
}
gps_start_mode;

const char *start_mode_to_string[gps_num_start_modes] =
{
    "$PMTK104*37",
    "$PMTK103*30",
    "$PMTK102*31",
    "$PMTK101*32"
};


int main(int argc, const char *argv[])
{
   assert(start_mode_to_string[gps_num_start_modes - 1] != NULL);

   printf("Start mode %d is %s\n", GPS_HOT, start_mode_to_string[GPS_HOT]);
   return 0;
}
j b
  • 5,147
  • 5
  • 41
  • 60
  • I got this far yesterday but weary of the out-of-sync issues I was hoping to go a little further and define the string array as: `const char *s_m_t_s[4];` and then `s_m_t_s[GPS_COLD] = "$PMTK...";` Which would guard me against the enum being rearranged. However I haven't found a way to do this that made the compiler happy. – user3817250 Sep 03 '14 at 13:17
  • 1
    Yup, there are some [pretty horrible solutions](http://stackoverflow.com/questions/207976/how-to-easily-map-c-enums-to-strings) to this involving variadic macros. It makes you realise the rationale behind the design of newer languages like Swift, which includes [more powerful enum support](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Enumerations.html). – j b Sep 03 '14 at 14:00
0

You can use #define directive for your requirements. Enums are not the solutions. For #define directive. Eg.

#define key1 value1
#define key2 value2

int main(void){

  //your code here

  and remember all keys replaces their respecive value

}

You can even define macros in between but the point is you can only use it below its definition.

sagar
  • 725
  • 2
  • 13
  • 30