P
pemo
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;
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);
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);
}
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;
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);
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);
}