2

I want to parse user input commands in my C (just C) program. Sample commands:

add node ID

add arc ID from ID to ID

print

exit

and so on. Then I want to do some validation with IDs and forward them to specified functions. Functions and validations are of course ready. It's all about parsing and matching functions...

I've made it with many ifs and strtoks, but I'm sure it's not the best way... Any ideas (libs)?

Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105
DavidMG
  • 105
  • 1
  • 5
  • Is the program using its command line parameters, or is it reading the keyboard or a file? What are the IDs? – gbulmer Apr 11 '12 at 18:48
  • I have usually done it using loops and if statements, I am doubtful there is a library for processing shell commands. If you wanted to, perhaps you can have a first letter that identifies the type command and use a switch statement (-P is print, -R is add type command, -E is exit, etc. etc.) – Youssef G. Apr 11 '12 at 18:50
  • It's not about command line parameters, but reading user commands from keyboard while program is running. Something like "shlex" in Python. – DavidMG Apr 11 '12 at 19:04
  • If you want to implement your own shell in C, have you looked at this related question: http://stackoverflow.com/q/1500004/1025391 ? There are many useful links for you. – moooeeeep Apr 11 '12 at 19:11
  • Already tried GNU libreadline? http://cnswww.cns.cwru.edu/php/chet/readline/rltop.html – dAm2K Apr 11 '12 at 19:53

4 Answers4

3

I think what you want is something like this:

while (1) 
{
    char *line = malloc(128); // we need to be able to increase the pointer
    char *origLine = line;
    fgets(line, 128, stdin);

    char command[20];
    sscanf(line, "%20s ", command);

    line = strchr(line, ' ');

    printf("The Command is: %s\n", command);

    unsigned argumentsCount = 0;
    char **arguments = malloc(sizeof(char *));

    while (1)
    {
        char arg[20];
        if (line && (sscanf(++line, "%20s", arg) == 1))
        {
            arguments[argumentsCount] = malloc(sizeof(char) * 20);
            strncpy(arguments[argumentsCount], arg, 20);

            argumentsCount++;

            arguments = realloc(arguments, sizeof(char *) * argumentsCount + 1);
            line = strchr(line, ' ');
        }
        else {
            break;
        }
    }

    for (int i = 0; i < argumentsCount; i++) {
        printf("Argument %i is: %s\n", i, arguments[i]);
    }

    for (int i = 0; i < argumentsCount; i++) {
        free(arguments[i]);
    }

    free(arguments);
    free(origLine);
}  

You can do what you wish with 'command' and 'arguments' just before you free it all.

Richard J. Ross III
  • 55,009
  • 24
  • 135
  • 201
1

It depends on how complicated your command language is. It might be worth going to the trouble of womping up a simple recursive descent parser if you have more than a couple of commands, or if each command can take multiple forms, such as your add command.

I've done a couple of RDPs by hand for some projects in the past. It's a bit of work, but it allows you to handle some fairly complex commands that wouldn't be straightforward to parse otherwise. You could also use a parser generator like lex/yacc or flex/bison, although that may be overkill for what you are doing.

Otherwise, it's basically what you've described; strok and a bunch of nested if statements.

John Bode
  • 119,563
  • 19
  • 122
  • 198
1

I just wanted to add something to Richard Ross's reply: Check the returned value from malloc and realloc. It may lead to hard-to-find crashes in your program.

Fernando
  • 97
  • 4
0

All your command line parameters will be stored into a array of strings called argv.

You can access those values using argv[0], argv[1] ... argv[n].

Toby Speight
  • 27,591
  • 48
  • 66
  • 103
Teja
  • 13,214
  • 36
  • 93
  • 155
  • 1
    I think he is talking about non-command line commands, ie he is probably telling the user to input a command to edit a file or print some data from the program while it is running. – Youssef G. Apr 11 '12 at 18:55
  • Exactly as @YoussefG. said. It's live. – DavidMG Apr 11 '12 at 19:03
  • Even so I do not think it is worthy a down vote - vague question. – Morpfh Apr 11 '12 at 21:27
  • @user120115 agreed. I initially thought the question was about command line arguments, until I thought finished reading it. – Youssef G. Apr 11 '12 at 22:18