1

Let's say i am communicating with a serial-port device and have a significant number of commands (74) for controlling such a device. Wich is the best way to store and use them?

Of course i can organize them the following way:

static char *cmd_msgs[] =
{
    "start",
    "stop",
    "reset",
    "quit",
    "",
    "",
    "",
    "",
    ...
};

Or human readable:

char cmd_start_str[] = "start";
...
char cmd_quit_str[] = "quit";

Can someone point to a working example dealing such a task?

Maquefel
  • 480
  • 4
  • 16
  • "What problem are you trying to solve?" – tbert Aug 26 '12 at 09:20
  • it's really a matter of preference and how you'll be using them. Any particular reasons you're using a char array in the second example rather than a string? – John Carter Aug 26 '12 at 09:22
  • @tbert Trying to forge a master piece =). A simple daemon controlling a state of serial-port device and providing sensors data to a pipe. – Maquefel Aug 26 '12 at 09:27
  • @therefromhere Errrr string? I don't quite understand you. Are there such things as "string" in c language? – Maquefel Aug 26 '12 at 09:30
  • @Maquefel see http://stackoverflow.com/questions/9393291/pointer-to-const-char-vs-char-array-vs-stdstring?lq=1 / http://stackoverflow.com/questions/1704407/what-is-the-difference-between-char-s-and-char-s-in-c - usually it's better to use the immutable form unless you need to alter the string value in place. – John Carter Aug 26 '12 at 09:44
  • (or just make the array version const) – John Carter Aug 26 '12 at 09:50
  • @Maquefel So, in the end, you were looking for a way to perform a translation of incoming strings to a symbolic constant? I really could not have gotten that from your problem description. Clarity of communication is not just for others. – tbert Aug 26 '12 at 20:25
  • @tbert Not a translation - i have a simple rs232/rs485 device, wich accept some commands in ASCII, so i write to port what i see. It is not a problem, but rather search for a common C technic for such a task, instead of "inventing another bicycle". – Maquefel Aug 27 '12 at 03:41
  • @Maquefel actually, since what you're asking for is a "dictionary", a translation is exactly what you're looking for. Asking a clear question is the surest way to get a good answer. – tbert Aug 27 '12 at 07:33

3 Answers3

5

The first approach is fine - don't use a lot of global variables with a unique name, they're hard to reference especially when you want to loop through them. That's what the array of strings is for (your first way). If you want human readable code (which you should want), use a sensibly named enumeration of which the values correspond to the actual command strings. So do something like

const char *cmds[] = {
    "command 1",
    "command 2",
    "Print Hello World",
    "Explode House"
};

enum {
    COMMAND_ONE,
    COMMAND_TWO,
    COMMAND_SAYHELLO,
    COMMAND_BOOM
};

This way you can easily reference your commands by indexing the array, but you still have himan readability by writing cmds[COMMAND_SAYHELLO] etc.

  • 1
    Yup - enums + const string array is what I usually use for serial commands, or CLI verbs, whatever. Also, + 1 for "Explode House" :) – Martin James Aug 26 '12 at 10:11
1

If you use the first option, you would typically need a second set of constants, or #defines to define the offset of each string in the array:

e.g.

#DEFINE cmd_start 0
#DEFINE cmd_stop 1

so this could be used cmd_msgs[cmd_start]

So I would go with your second option

char* cmd_start_str = "start";
StuartLC
  • 104,537
  • 17
  • 209
  • 285
  • Except that this will result in `cmd_msgs[= 0;]` which is a syntax error. I'm wondering how somebody with 11k6 rep doesn't know how to use a simple preprocessor macro. –  Aug 26 '12 at 09:28
  • @h2co3 that would of course be because I last used C 15 years ago ... memory fails me. Fixed. Thanks *blush* – StuartLC Aug 26 '12 at 09:30
0

For this application, I would use an array of structures.

// Command handler signature. Choose as per your requirement.
    typedef int (*cmdHandlerType)(char * hostCmdString); 

    //Command Structure
    typedef struct
    {
        char *commandString; /**< points to the Command String*/
        cmdHandlerType cmdHandler; /**< points to the Command function*/
    } commandStruct;

    //All the commands and its functions
    static commandStruct  Commands[] = {
                            {"TEMP", TempCommand},
                            {"GAIN",   GainCommand}, 
                            {"SETPT", SetPtCommand},
                            {"...", ... },
                         };
int TempCommand( char *str)
{
     ...
}

This way when you get a command from the host, you could match the the command string and call the corresponding handler.

shr
  • 875
  • 10
  • 20
  • Thank you. Quite a nice solution. But first - it seems some kind of OOP emulation to me, and i like purity. Second IMHO it is better to stick with lex for a such approach. – Maquefel Aug 26 '12 at 11:21