Commandline argh [sic] processing

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • pemo

    Commandline argh [sic] processing

    Opinion please.

    The code below is an attempt at demonstrating commandline arg processing.

    I don't really like the repetitive use of ...

    if(!(*s))
    {
    // Make sure we don't go out of bounds.
    //
    p = i + 1 >= argc ? NULL : argv[++i];
    }

    and, of course, I'm not sure the code is either 'sound' or optimal for what
    it does.

    Feedback welcome.


    #include <stdio.h>
    #include <ctype.h>
    #include <string.h>
    #include <stdlib.h>


    #define trace(...) printf(__VA_ARG S__)



    void usage(void);

    // Tested with [as noise and signal]
    //
    // -f test.c -a -B --n 10 -ftest1 -n50 - f three -k
    //
    // as args.



    int main(int argc, char * argv[])
    {
    // Holds the switch char, e.g., given -f, this will be 'f' when it
    matters.
    //
    char c = 0;

    // Used to point at an argv.
    //
    char * s = NULL;
    char * p = NULL;

    // A buffer for the -f switch implementation to use.
    //
    char buffer[100];

    // A number for the -n switch implementation to use.
    int num = 0;

    // Loop counter for argc handling.
    //
    int i = 0;

    // If we've no useful args, tell the user [will exit].
    //
    if(argc <= 1)
    {
    usage();
    }

    // For each arg ...
    //
    for(i = 1; i < argc; ++i)
    {
    s = argv[i];

    p = NULL;

    // If this argv is a valid switch? The first char needs to be a /
    or a -,
    // and the following part must contain one of the chars we
    expect. The
    // leading @ in the test string is important as it's acting as a
    'guard'..
    // we don't want to return 0 if we find a valid char basically, so
    [0] has
    // a character we shouldn't find.
    //
    if((*s == '/' || *s == '-') && strcspn("@abfnA BFN", ++s))
    {
    // For each char after the / or - .... !p is there because if
    the
    // 'meat' of the switch directly follows the flag character,
    this
    // while loop will iterate through the non-switch-char
    characters.
    //
    while((c = *s++) && !p)
    {
    switch(toupper( c))
    {
    case '?':

    usage();

    break;


    case 'A':

    trace("-A switch found\n");

    break;


    case 'B':

    trace("-B switch found\n");

    break;


    case 'F': // -f indicates there's a string
    parameter coming.

    trace("-F switch found\n");

    {
    // If there's a '\0' following 'F', then the
    string
    // we're wanting should be in the next argv as
    this
    // argv is terminated.
    //
    if(!(*s))
    {
    // Make sure we don't go out of bounds.
    //
    p = i + 1 >= argc ? NULL : argv[++i];
    }

    // No terminator, so the filename is flush up
    against the -f - or was not given!
    //
    else

    {
    p = s;
    }

    if(!p)
    {
    fprintf(stderr, "\t-F: but no filename
    found!\n");
    }

    else

    {
    strncpy(buffer, p, sizeof(buffer)) ;

    trace("\tfilena me: %s\n", buffer);
    }
    }
    break;

    case 'N': // -n indicates there's a numeric
    parameter coming [expected].

    trace("-N switch found\n");

    {
    if(!(*s))
    {
    p = i + 1 >= argc ? NULL : argv[++i];
    }

    else

    {
    p = s;
    }

    if(!p)
    {
    fprintf(stderr, "\t-N: but no integer
    found!\n");
    }

    else

    {
    sscanf(p, "%d", &num);

    trace("\tvalue: %d\n", num);
    }
    }
    break;

    default:

    trace("\nShould n't get here ... unknown or badly
    formatted flag!: argv[%d] = '%s'\n\n", i, argv[i]);

    break;
    }
    }
    }
    else
    {
    trace("\n\tOthe r params ... input file etc?: %s\n\n", s);
    }
    }

    getchar();

    return EXIT_SUCCESS;
    }


    void usage(void)
    {
    puts("Usage:\n\ n");
    puts("\t-a, -b : test switches");
    puts("\t-f<filename> : test switch with a string parameter");
    puts("\t-n<num> : test switch with a numeric parameter");

    exit(0);
    }




    --
    ==============
    *Not a pedant*
    ==============


  • Ben Pfaff

    #2
    Re: Commandline argh [sic] processing

    "pemo" <usenetmeister@ gmail.com> writes:
    [color=blue]
    > The code below is an attempt at demonstrating commandline arg processing.
    >
    > I don't really like the repetitive use of ...
    >
    > if(!(*s))
    > {
    > // Make sure we don't go out of bounds.
    > //
    > p = i + 1 >= argc ? NULL : argv[++i];
    > }[/color]

    I would suggest writing a helper function or two. There are
    many, *many* libraries and examples out there for helping out
    with command-line processing. I'm sure you can find one you
    like.
    --
    int main(void){char p[]="ABCDEFGHIJKLM NOPQRSTUVWXYZab cdefghijklmnopq rstuvwxyz.\
    \n",*q="kl BIcNBFr.NKEzjwC IxNJC";int i=sizeof p/2;char *strchr();int putchar(\
    );while(*q){i+= strchr(p,*q++)-p;if(i>=(int)si zeof p)i-=sizeof p-1;putchar(p[i]\
    );}return 0;}

    Comment

    • Rod Pemberton

      #3
      Re: Commandline argh [sic] processing


      "pemo" <usenetmeister@ gmail.com> wrote in message
      news:dvv24r$4rd $1@news.ox.ac.u k...[color=blue]
      > Opinion please.
      >
      > The code below is an attempt at demonstrating commandline arg processing.
      >
      > I don't really like the repetitive use of ...
      >
      > if(!(*s))
      > {
      > // Make sure we don't go out of bounds.
      > //
      > p = i + 1 >= argc ? NULL : argv[++i];
      > }
      >[/color]

      You are reinventing getopt. But, that's okay. I've done it myself.

      I'd suggest the following:

      1) using argv[i][j] will save some grief over using s & p
      2) loop from 0 to argc, determine which argv's are flag args using strstr
      and/or strspn, storing the results in an flag indicator array and requoting
      args if necessary
      3) loop from 0 to argc, if flag array indicates arg is a flag, switch to
      appropriate setup routine ( At this point, I usually setup a control array
      where a value representing the selected option indexes into the control
      array returning the correct argv position. The control array can then be
      selectively used throughout your program to include or exclude code and you
      have access to the correct argv values immediately.)


      Rod Pemberton


      Comment

      • Arndt Jonasson

        #4
        Re: Commandline argh [sic] processing


        "Rod Pemberton" <do_not_have@so rry.bitbuck.cmm > writes:[color=blue]
        > "pemo" <usenetmeister@ gmail.com> wrote in message
        > news:dvv24r$4rd $1@news.ox.ac.u k...[color=green]
        > > Opinion please.
        > >
        > > The code below is an attempt at demonstrating commandline arg processing.
        > >
        > > I don't really like the repetitive use of ...
        > >
        > > if(!(*s))
        > > {
        > > // Make sure we don't go out of bounds.
        > > //
        > > p = i + 1 >= argc ? NULL : argv[++i];
        > > }
        > >[/color]
        >
        > You are reinventing getopt. But, that's okay. I've done it myself.
        >
        > I'd suggest the following:
        >
        > 1) using argv[i][j] will save some grief over using s & p
        > 2) loop from 0 to argc, determine which argv's are flag args using strstr
        > and/or strspn, storing the results in an flag indicator array and requoting
        > args if necessary
        > 3) loop from 0 to argc, if flag array indicates arg is a flag, switch to
        > appropriate setup routine ( At this point, I usually setup a control array
        > where a value representing the selected option indexes into the control
        > array returning the correct argv position. The control array can then be
        > selectively used throughout your program to include or exclude code and you
        > have access to the correct argv values immediately.)[/color]

        One can also use the fact that argv[argc] is a NULL pointer.

        Comment

        Working...