Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Parsing options in the same way they are passed to main

Reply
Thread Tools

Parsing options in the same way they are passed to main

 
 
Jeff Rodriguez
Guest
Posts: n/a
 
      12-13-2003
If main is prototyped as:
int main(int argc, char *argv[]);

You will end up with a bunch of arguments in *argv, and the number in argc. Now
what I want to do is emulate that same action on a string. Say for example I have:

char *command = "./blah --arg1 --arg2 123 -x --arg2=w00t"

How do I acheive the same effect as in main()?


Jeff
 
Reply With Quote
 
 
 
 
Ben Pfaff
Guest
Posts: n/a
 
      12-13-2003
Jeff Rodriguez <(E-Mail Removed)> writes:

> If main is prototyped as:
> int main(int argc, char *argv[]);
>
> You will end up with a bunch of arguments in *argv, and the number in
> argc. Now what I want to do is emulate that same action on a
> string. Say for example I have:
>
> char *command = "./blah --arg1 --arg2 123 -x --arg2=w00t"
>
> How do I acheive the same effect as in main()?


It depends on the operating system, shell, and other things. If
all you want to do is to break apart the string into words at
white space, I suggest you just write code to do it. It's not
too hard.
--
"Given that computing power increases exponentially with time,
algorithms with exponential or better O-notations
are actually linear with a large constant."
--Mike Lee
 
Reply With Quote
 
 
 
 
Jeff Rodriguez
Guest
Posts: n/a
 
      12-13-2003
Ben Pfaff wrote:

> It depends on the operating system, shell, and other things. If
> all you want to do is to break apart the string into words at
> white space, I suggest you just write code to do it. It's not
> too hard.


Indeed: (crude code)
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
int i;
char *string = NULL;
char *str = NULL;
int size = 0;

for ( i = 1; i < argc; i++ )
{
if ( strlen(argv[i]) > size )
{
if ( (string = realloc(string, (size + strlen(argv[i])) * 2)) == NULL )
{
perror("Could not allocate memory");
exit(1);
}
}

string = strcat(string, argv[i]);
string = strcat(string, " ");
}

printf("%s %s\n", argv[0], string);

str = strtok(string, " \t\n");
printf("%s\n", str);
while ( (str = strtok(NULL, " \t\n")) != NULL )
{
printf("%s\n", str);
}
return 0;
}

However you run into problems like:
../a.out --search="Hello World!"

I would prefer not to have to reinvent the wheel on this since main() already
implements it! There must be /some/ way that it's a built-in function!

Jeff
 
Reply With Quote
 
Jack Klein
Guest
Posts: n/a
 
      12-13-2003
On Fri, 12 Dec 2003 22:02:24 -0700, Jeff Rodriguez
<(E-Mail Removed)> wrote in comp.lang.c:

> Ben Pfaff wrote:
>
> > It depends on the operating system, shell, and other things. If
> > all you want to do is to break apart the string into words at
> > white space, I suggest you just write code to do it. It's not
> > too hard.

>
> Indeed: (crude code)
> #include <stdio.h>
> #include <string.h>
> #include <unistd.h>


The header above is both non-standard and unneeded in your program.

> #include <stdlib.h>
>
> int main(int argc, char *argv[])
> {
> int i;
> char *string = NULL;
> char *str = NULL;
> int size = 0;
>
> for ( i = 1; i < argc; i++ )
> {
> if ( strlen(argv[i]) > size )
> {
> if ( (string = realloc(string, (size + strlen(argv[i])) * 2)) == NULL )
> {
> perror("Could not allocate memory");
> exit(1);
> }
> }
>
> string = strcat(string, argv[i]);


This is quite likely to crash the first time, since the first block
that realloc returns is uninitialized and there's no telling if it
will contain a terminating '\0' at all, let alone in the first
element.

> string = strcat(string, " ");
> }
>
> printf("%s %s\n", argv[0], string);
>
> str = strtok(string, " \t\n");
> printf("%s\n", str);
> while ( (str = strtok(NULL, " \t\n")) != NULL )
> {
> printf("%s\n", str);
> }
> return 0;
> }
>
> However you run into problems like:
> ./a.out --search="Hello World!"
>
> I would prefer not to have to reinvent the wheel on this since main() already
> implements it! There must be /some/ way that it's a built-in function!
>
> Jeff


No, main() does not already implement it. Either the host operating
system or the implementation's start-up code does. There is no C
standard library function to do so.

If you want source code, try Google.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++ ftp://snurse-l.org/pub/acllc-c++/faq
 
Reply With Quote
 
Ben Pfaff
Guest
Posts: n/a
 
      12-13-2003
Jeff Rodriguez <(E-Mail Removed)> writes:

> I would prefer not to have to reinvent the wheel on this since main()
> already implements it! There must be /some/ way that it's a built-in
> function!


main() doesn't implement this on any system I've used. For
example, under MS-DOS, the arguments are passed to the program as
a single string, and the C library startup routine carves it up
and passes it to main(). As another example, under UNIX-like
systems, the shell does the parsing into arguments and the
program receives them from the OS already in that form. In
neither case is there an easy way for the program to access the
functionality.
--
"I don't have C&V for that handy, but I've got Dan Pop."
--E. Gibbons
 
Reply With Quote
 
Kevin Goodsell
Guest
Posts: n/a
 
      12-13-2003
Jeff Rodriguez wrote:

> if ( (string = realloc(string, (size + strlen(argv[i])) * 2)) ==
> NULL )
> {
> perror("Could not allocate memory");
> exit(1);
> }


Aside from a few other errors that have already been pointed out, I
don't think you should be calling perror without first checking the
value of errno. I don't know off the top if my head whether realloc is
required to set errno, but my guess is that it is not. If it doesn't,
you may end up getting something like this:

Could not allocate memory: No error

Or something even more confusing, if errno has previously been set by a
different function.

This is also a guaranteed memory leak if realloc fails. The correct way
to use realloc is to store the result into a temporary pointer, and only
assign it to the destination pointer if it is non-null.

Finally, 1 is not a portable exit code. Consider using one of the
portable codes: 0, EXIT_SUCCESS, or EXIT_FAILURE.

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.
 
Reply With Quote
 
Jeff Rodriguez
Guest
Posts: n/a
 
      12-13-2003
Kevin Goodsell wrote:
> Jeff Rodriguez wrote:
>
>> if ( (string = realloc(string, (size + strlen(argv[i])) * 2)) ==
>> NULL )
>> {
>> perror("Could not allocate memory");
>> exit(1);
>> }

>
>
> Aside from a few other errors that have already been pointed out, I
> don't think you should be calling perror without first checking the
> value of errno. I don't know off the top if my head whether realloc is
> required to set errno, but my guess is that it is not. If it doesn't,
> you may end up getting something like this:
>
> Could not allocate memory: No error
>
> Or something even more confusing, if errno has previously been set by a
> different function.
>
> This is also a guaranteed memory leak if realloc fails. The correct way
> to use realloc is to store the result into a temporary pointer, and only
> assign it to the destination pointer if it is non-null.
>
> Finally, 1 is not a portable exit code. Consider using one of the
> portable codes: 0, EXIT_SUCCESS, or EXIT_FAILURE.
>
> -Kevin


Not that I typically do the above (note how I said crude code), but how would
this be a guaranteed memory leak? If realloc fails the program exits. I'm not
sure I understand how that would cause a memory leak.

Jeff
 
Reply With Quote
 
CBFalconer
Guest
Posts: n/a
 
      12-13-2003
Jeff Rodriguez wrote:
> Ben Pfaff wrote:
>
> > It depends on the operating system, shell, and other things. If
> > all you want to do is to break apart the string into words at
> > white space, I suggest you just write code to do it. It's not
> > too hard.

>
> Indeed: (crude code)
> #include <stdio.h>
> #include <string.h>
> #include <unistd.h>


*** Non-existent standard include ***

> #include <stdlib.h>
>
> int main(int argc, char *argv[])
> {
> int i;
> char *string = NULL;


*** Invading the systems name space. Use another id ***

> char *str = NULL;
> int size = 0;
>
> for ( i = 1; i < argc; i++ )
> {
> if ( strlen(argv[i]) > size )
> {
> if ( (string = realloc(string, (size + strlen(argv[i])) * 2)) == NULL )


*** Harmless in this context, but an evil habit ***
Try something like:
if (tmp = realloc(old, (size + strlen(argv[i])) *
2))
old = tmp;
else {
/* failure */
}

> {
> perror("Could not allocate memory");
> exit(1);
> }
> }



--
Chuck F ((E-Mail Removed)) ((E-Mail Removed))
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!


 
Reply With Quote
 
nrk
Guest
Posts: n/a
 
      12-13-2003
Jeff Rodriguez wrote:

> If main is prototyped as:
> int main(int argc, char *argv[]);
>
> You will end up with a bunch of arguments in *argv, and the number in
> argc. Now what I want to do is emulate that same action on a string. Say
> for example I have:
>
> char *command = "./blah --arg1 --arg2 123 -x --arg2=w00t"
>
> How do I acheive the same effect as in main()?
>
>
> Jeff


A simple hack is to use another C program that simply prints out its command
line arguments to a known file. Then invoke said program with the system
call:

/* assume that our argv printer is called cmdline
and is accessible through a "system" call */
char *command = "./cmdline ./blah --arg1 --arg2 123 -x --arg2=w00t";

system(command);

/* now read the file produced by cmdline to get
argv parsed version of command */

-nrk.
 
Reply With Quote
 
nrk
Guest
Posts: n/a
 
      12-13-2003
nrk wrote:

> Jeff Rodriguez wrote:
>
>> If main is prototyped as:
>> int main(int argc, char *argv[]);
>>
>> You will end up with a bunch of arguments in *argv, and the number in
>> argc. Now what I want to do is emulate that same action on a string. Say
>> for example I have:
>>
>> char *command = "./blah --arg1 --arg2 123 -x --arg2=w00t"
>>
>> How do I acheive the same effect as in main()?
>>
>>
>> Jeff

>
> A simple hack is to use another C program that simply prints out its
> command line arguments to a known file. Then invoke said program with the
> system call:
>
> /* assume that our argv printer is called cmdline
> and is accessible through a "system" call */
> char *command = "./cmdline ./blah --arg1 --arg2 123 -x
> --arg2=w00t";
>
> system(command);
>
> /* now read the file produced by cmdline to get
> argv parsed version of command */
>
> -nrk.


Just in case you're wondering what an "argv printer" might look like

#include <stdio.h>

int main(int argc, char **argv) {
while ( *argv ) {
printf("%s\n", *argv);
++argv;
}

return 0;
}

If you want one that ignores argv[0]:

#include <stdio.h>

int main(int argc, char **argv) {
if ( argc )
while ( *++argv ) printf("%s\n", argv);

return 0;
}

-nrk.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
int main() or int main(void)? Frederick Ding C Programming 10 12-04-2005 12:44 AM
adding main.aspx.vb & main.aspx.resx under aspx John M ASP .Net 1 05-29-2005 09:27 PM
int main(int argc, char *argv[] ) vs int main(int argc, char **argv ) Hal Styli C Programming 14 01-20-2004 10:00 PM
they turn, they power, they make nice pics Keith and Jenn Z. Digital Photography 0 09-21-2003 04:16 AM



Advertisments