By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
448,959 Members | 1,196 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 448,959 IT Pros & Developers. It's quick & easy.

Commandline argh [sic] processing

P: n/a
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_ARGS__)

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("@abfnABFN", ++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("\tfilename: %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("\nShouldn't get here ... unknown or badly
formatted flag!: argv[%d] = '%s'\n\n", i, argv[i]);

break;
}
}
}
else
{
trace("\n\tOther 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*
==============
Mar 23 '06 #1
Share this Question
Share on Google+
3 Replies


P: n/a
"pemo" <us***********@gmail.com> writes:
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];
}


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[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv wxyz.\
\n",*q="kl BIcNBFr.NKEzjwCIxNJC";int i=sizeof p/2;char *strchr();int putchar(\
);while(*q){i+=strchr(p,*q++)-p;if(i>=(int)sizeof p)i-=sizeof p-1;putchar(p[i]\
);}return 0;}
Mar 23 '06 #2

P: n/a

"pemo" <us***********@gmail.com> wrote in message
news:dv**********@news.ox.ac.uk...
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];
}


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
Mar 23 '06 #3

P: n/a

"Rod Pemberton" <do*********@sorry.bitbuck.cmm> writes:
"pemo" <us***********@gmail.com> wrote in message
news:dv**********@news.ox.ac.uk...
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];
}


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.)


One can also use the fact that argv[argc] is a NULL pointer.
Mar 24 '06 #4

This discussion thread is closed

Replies have been disabled for this discussion.