Thread: my own commandline parser function

  1. #1
    Registered User
    Join Date
    Jul 2003
    Posts
    85

    Thumbs up my own commandline parser function

    I've noticed the *nix has that nice getopt function to parse the commandline arguments. So I decided to make my own windows version. Here's what I have thus far (working):

    Code:
    #include <stdio.h>
    #include <string.h>
    
    int cmdlineparse(int argc, char **argv, const char *args, char *retval);
    
    int main(int argc, char *argv[])
    {
        int ch;
        char retval[100];
        while ((ch = cmdlineparse(argc, argv, ":bf:g", retval)) != -1) {
            switch (ch) {
            case 'b':
                printf("b found. retval = %s\n",retval);
                break;
            case 'f':
                printf("f found.\n");
                break;
            case 'g':
                printf("g found. reval = %s\n",retval);
                break;
            default: /* or case 0: */
                printf("bad argument!\n");
                break;
            }
        }
        getchar();
        return 0;
    }
    
    /*
     *       function: cmdlineparse
     *         author: scrappy
     *    description: commandline parser
     *
     *           int argc = number of commandline arguments
     *  const char **argv = 2d array of commandline arguments
     *   const char *args = options to check for. flag the option by
     *                      placing a ':' before it and retval will be
     *                      set to the commandline string following the
     *                      option that was found. see example for
     *                      clarification.
     *       char *retval = value set to argument following the option
     *                      if the flag is set (with ':'). returns 0 if
     *                      the argument does not exist.
     *
     *  return values:      0 - option wasn't found (bad argument)
     *                     -1 - function finished
     *                  other - returns character found (non zero)
     */
    
    int cmdlineparse(int argc, char **argv, const char *args, char *retval)
    {
        static int i = 1;
        int j = 0;
        int flag;
        while( i < argc ) /* goes through each argument from commandline */
        {
            for( j = 0; j < strlen(args); j++ ) /* goes through each option */
            {
                flag = 0;
    
                /* set flag to look for something after option/move onto next option */
                if( args[j] == ':' ) {
                    flag = 1; j++;
                }
    
                /* checks for option, something can precede it if you want */
                if( (argv[i][0] == args[j]) ^ (argv[i][1] == args[j]) ) {
                    if( flag == 1 ) {
                        if( i + 1 > argc - 1 ) { /* make sure next argument exists */
                            i++;
                            return 0;
                        }
                        strcpy( retval, argv[i+1] ); /* copy next argument into retval */
                        i++; /* additional increase to skip the next argument */
                    }
                    i++; /* move onto next argument */
                    return args[j];
                }
            } /* for( j = 0; j < strlen(args); j++ ) */
            i++;
            return 0; /* return 0 because option wasn't found in argument */
        } /* for( ; i < argc; i++ ) */
        return -1; /* end of function */
    }
    Suggestions, corrections, comments appreciated
    Last edited by scrappy; 08-21-2003 at 01:27 PM.

  2. #2
    Registered User
    Join Date
    Jul 2002
    Posts
    913
    I did one of those too, i just dont like that optarg thingy.

  3. #3
    Comment your source code! Lynux-Penguin's Avatar
    Join Date
    Apr 2002
    Posts
    533
    BEAUTIFUL!

    And you have comments!

    that is EXTREMELY sexy code

    Suggestion:
    add something for deliminators like the '-' char in Unix

    Ex: myprog -arg1 -arg2

    and maybe support for arguments for arguments

    Ex: myprog -do something

    but that is extremely sexy

    -LC
    Last edited by Lynux-Penguin; 08-21-2003 at 06:27 PM.
    Asking the right question is sometimes more important than knowing the answer.
    Please read the FAQ
    C Reference Card (A MUST!)
    Pointers and Memory
    The Essentials
    CString lib

  4. #4
    Registered User
    Join Date
    Jul 2003
    Posts
    85
    if you call cmdlineparse(argc, argv, ":bf:g", retval), then when both b and g are found they will put the next argument into retval.

    so if you called the program from the command line like this:

    program.exe b hi! g hello!

    then when b is found, reval will equal "hi!" and when g is found, reval will equal "hello!." also, i made it optional for there to be a character in front of the options. so the above program call could also be done the following way with the same results.

    program.exe -b hi! -g hello!

    what i'd like to do eventually is add the possibility to have it recognize options like -xvzf, but i'll save that for another day.

  5. #5
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    The only thing I see is that it's possible for your command line arguments to be longer than retval. You might want to use strncpy and add a parameter and pass the length of the buffer as an argument.

    It will make your program a bit more cludgey (one more argument), but it would make it safer, if safety is anything you're concerned about.

    Usually your standard command line will halt on longer lines of input (open your console and hold down a letter, it will eventually not let you type any more), however, if this were being piped in from a file or something else, you could have an overflow.

    Additionally, you could initially null value your array, just to not have to do it later:
    Code:
    char retval[100] = {0};
    But that's just a very minor point. I tend to do that out of habbit whenever using arrays (strings).

    Quzah.
    Hope is the first step on the road to disappointment.

  6. #6
    Registered User
    Join Date
    Jul 2003
    Posts
    85
    Originally posted by quzah
    The only thing I see is that it's possible for your command line arguments to be longer than retval. You might want to use strncpy and add a parameter and pass the length of the buffer as an argument.

    It will make your program a bit more cludgey (one more argument), but it would make it safer, if safety is anything you're concerned about.

    Usually your standard command line will halt on longer lines of input (open your console and hold down a letter, it will eventually not let you type any more), however, if this were being piped in from a file or something else, you could have an overflow.

    Additionally, you could initially null value your array, just to not have to do it later:
    Code:
    char retval[100] = {0};
    But that's just a very minor point. I tend to do that out of habbit whenever using arrays (strings).

    Quzah.
    i imagine instead of passing the extra parameter i could just use a #define BUF 100 to declare the size? then the strncpy function would look like this i suppose:

    strncpy( retval, argv[i+1] , BUF);
    or should i cast it?
    strncpy( retval, argv[i+1] , (size_t)BUF);
    or should it be BUF-1 to leave room for the null terminating character? all this string stuff makes the head spin

    thanks for the suggestions

  7. #7
    End Of Line Hammer's Avatar
    Join Date
    Apr 2002
    Posts
    6,231
    >>should it be BUF-1 to leave room for the null terminating character?
    Don't use a cast.
    strncpy will not account for the null terminator, so it could fill the array (size as per the 3rd arg) with valid characters. So if you pass it size N-1, then force array[N-1] to be '\0' afterwards, your string will be null terminated for sure.
    When all else fails, read the instructions.
    If you're posting code, use code tags: [code] /* insert code here */ [/code]

  8. #8
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    The point of having another argument is so that the function is portable, and could be in it's own library if you felt like it.

    If you hardcode the function to use a #define-ed BUF, then you have to remember to define BUF any time you use the function.

    If you just use an argument, then any time it's used, they just pass the size of the array along with it.

    If you don't care how portable it is, and you want to do it the easy way, then use 'BUFSIZ' for your buffers, since it's an ANSI definition.

    Quzah.
    Hope is the first step on the road to disappointment.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Getting an error with OpenGL: collect2: ld returned 1 exit status
    By Lorgon Jortle in forum C++ Programming
    Replies: 6
    Last Post: 05-08-2009, 08:18 PM
  2. In over my head
    By Shelnutt2 in forum C Programming
    Replies: 1
    Last Post: 07-08-2008, 06:54 PM
  3. Including lib in a lib
    By bibiteinfo in forum C++ Programming
    Replies: 0
    Last Post: 02-07-2006, 02:28 PM
  4. Question..
    By pode in forum Windows Programming
    Replies: 12
    Last Post: 12-19-2004, 07:05 PM
  5. dynamic function execution
    By Sargnagel in forum C Programming
    Replies: 7
    Last Post: 05-07-2003, 05:28 AM