473,386 Members | 1,699 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

Parsing options in the same way they are passed to main

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
Nov 14 '05 #1
18 1938
Jeff Rodriguez <ne********@gurugeek.EXAMPLENOSPAM.com> 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
Nov 14 '05 #2
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
Nov 14 '05 #3
On Fri, 12 Dec 2003 22:02:24 -0700, Jeff Rodriguez
<ne********@gurugeek.EXAMPLENOSPAM.com> 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
Nov 14 '05 #4
Jeff Rodriguez <ne********@gurugeek.EXAMPLENOSPAM.com> 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
Nov 14 '05 #5
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.
Nov 14 '05 #6
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
Nov 14 '05 #7
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 (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
Nov 14 '05 #8
nrk
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.
Nov 14 '05 #9
nrk
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.
Nov 14 '05 #10
Jeff Rodriguez wrote:
Kevin Goodsell wrote:
Jeff Rodriguez wrote:
if ( (string = realloc(string, (size + strlen(argv[i])) * 2))
== NULL )
{


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.


Any time you fail to free memory that you've [m|c|re]alloc'ed, it is a
memory leak. Using realloc in this manner guarantees that you will not
be able to free the memory you've already allocated once realloc fails.

Some people don't bother freeing memory when the program is exiting.
This is not a very good idea. Some systems reclaim memory when a program
exits, but not all.

Also, what happens when the code is used in a different program, where
exiting on an allocation failure isn't an option?

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.
Nov 14 '05 #11
CBFalconer wrote:
char *string = NULL;

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


I could be wrong, but I think 'str' identifiers are reserved for use as
external identifiers. Since this is local it might shadow an external
declaration, but I don't think it will conflict.

Of course, avoiding reserved identifiers completely (even where they are
safe) is probably the best thing to do.

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.
Nov 14 '05 #12
Kevin Goodsell <us*********************@neverbox.com> wrote:
Some people don't bother freeing memory when the program is
exiting. This is not a very good idea. Some systems reclaim
memory when a program exits, but not all.


Can you cite an example of a system where it makes any difference
at all?

--
Floyd L. Davidson <http://web.newsguy.com/floyd_davidson>
Ukpeagvik (Barrow, Alaska) fl***@barrow.com
Nov 14 '05 #13
Floyd Davidson wrote:
Kevin Goodsell <us*********************@neverbox.com> wrote:
Some people don't bother freeing memory when the program is
exiting. This is not a very good idea. Some systems reclaim
memory when a program exits, but not all.

Can you cite an example of a system where it makes any difference
at all?


Sure. A TI-89 or TI-92+ calculator using TI-GCC. If you fail to free
memory, you don't get it back until you reset the whole thing, wiping
the entire memory.

There are a lot of systems out there other than desktop systems.

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.
Nov 14 '05 #14
Groovy hepcat Jeff Rodriguez was jivin' on Fri, 12 Dec 2003 20:36:37
-0700 in comp.lang.c.
Parsing options in the same way they are passed to main's a cool
scene! Dig it!
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()?


First of all, don't try to do this with a string literal; use an
array.
Use strtok() to get each token in turn, and add each (pointer
returned from strtok()) to an array of pointers to char which has been
dynamically allocated with realloc(), until (and including) strtok()
returns a null pointer. For example:

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

char **gettoks(char *s, int *num)
{
char **tok = NULL, **tmp;
char *t;
int n = 0;

t = strtok(s, " \t\v\r\n");

while(t)
{
n++;

tmp = realloc(tok, n * sizeof *tmp);
if(!tmp)
{
free(tok);
return NULL;
}
tok = tmp;

tok[n - 1] = t;

t = strtok(NULL, " \t\v\r\n");
}

tmp = realloc(tok, (n + 1) * sizeof *tmp);
if(!tmp)
{
free(tok);
return NULL;
}
tok = tmp;

tok[n] = NULL;

*num = n;
return tok;
}

int main(void)
{
char command[] = "./blah --arg1 --arg2 123 -x --arg2=w00t";
char **argv;
int argc, i;

argv = gettoks(command, &argc);
if(!argv)
{
fprintf(stderr, "Memory allocation error.\n");
return EXIT_FAILURE;
}

printf("%d args found:\n", argc);

for(i = 0; i < argc; i++)
{
printf("\t%d: \"%s\"\n", i, argv[i]);
}

free(argv);
return 0;
}

--

Dig the even newer still, yet more improved, sig!

http://alphalink.com.au/~phaywood/
"Ain't I'm a dog?" - Ronny Self, Ain't I'm a Dog, written by G. Sherry & W. Walker.
I know it's not "technically correct" English; but since when was rock & roll "technically correct"?
Nov 14 '05 #15
CBFalconer <cb********@yahoo.com> wrote in message news:<3F***************@yahoo.com>...

<snipped>
int main(int argc, char *argv[])
{
int i;
char *string = NULL;


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


I dont think so; as it is local to main, its not a problem.
otoh, it really *is* rather bad form.

goose,
Nov 14 '05 #16
Jeff Rodriguez <ne********@gurugeek.EXAMPLENOSPAM.com> wrote in message news:<3F**************@gurugeek.EXAMPLENOSPAM.com> ...

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


there are a few ways:
1. the system it runs on may not guarantee that it cleans up after
processes.
2. the process that is currently running where realloc fails
could have been a forked-type process, and the other party
of the fork may have to end before the memory is released.
since there is no guarantee that the other process *will*
end, the memory is gone forever.
3. the error code of 1 ("exit (1)") may be interpreted by the
caller (OS) as "please restart from main without resetting
anything": the only portable codes to use are EXIT_FAILURE
and EXIT_SUCCESS.
:-)

hth
goose,
Nov 14 '05 #17
On Sat, 13 Dec 2003 21:13:25 GMT, Kevin Goodsell
<us*********************@neverbox.com> wrote:
CBFalconer wrote:
char *string = NULL;

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


I could be wrong, but I think 'str' identifiers are reserved for use as
external identifiers. Since this is local it might shadow an external
declaration, but I don't think it will conflict.

Standard library function names, plus the extension ranges beginning
with mem str wcs is to, are reserved as external names always, and as
file-scope identifiers *and macros* (unless #undef'ed) if the relevant
header is #include'd, and in this case string.h was.

That said, I would bet 'string' in particular will never be used, at
least not for a function, partly because it describes a thing not an
operation, and partly to avoid conflict with C++'s std::string.
Of course, avoiding reserved identifiers completely (even where they are
safe) is probably the best thing to do.

Concur.

- David.Thompson1 at worldnet.att.net
Nov 14 '05 #18
ru**@webmail.co.za (goose) writes:
[...]
3. the error code of 1 ("exit (1)") may be interpreted by the
caller (OS) as "please restart from main without resetting
anything": the only portable codes to use are EXIT_FAILURE
and EXIT_SUCCESS.


And 0.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://www.sdsc.edu/~kst>
Schroedinger does Shakespeare: "To be *and* not to be"
(Note new e-mail address)
Nov 14 '05 #19

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

8
by: Gerrit Holl | last post by:
Posted with permission from the author. I have some comments on this PEP, see the (coming) followup to this message. PEP: 321 Title: Date/Time Parsing and Formatting Version: $Revision: 1.3 $...
4
by: Josef Wolf | last post by:
Hello! Is it possible to have CVS-style command line options with the optparse module? I could get as far as: import sys from optparse import OptionParser, OptionGroup parser =...
6
by: egg | last post by:
Dear Sir/Madam, I'm about to start a project, the idea is to have a web interface to let user specify the URL of a target HTML document, based on that URL, retrieved and parsed the HTML document...
3
by: Girish | last post by:
Hi All, I have written a component(ATL COM) that wraps Xerces C++ parser. I am firing necessary events for each of the notifications that I have handled for the Content and Error handler. The...
2
by: Rashida | last post by:
Hi all! I have written a function to fetch lebels from xml file for cross-language interoperability. Please refer function code below. I am invoking itfrom my asp page saying...
18
by: Atara | last post by:
In my apllication I use the following code: '-- My Code: Public Shared Function strDate2Date(ByVal strDate As String) As System.DateTime Dim isOk As Boolean = False If (strDate Is Nothing)...
0
by: Benny the Guard | last post by:
I have become familiar with optparse code to parse various options into a program. But right now having some difficulties with a new project I am working on (not a class project, just a new script)....
0
by: Gordon Fraser | last post by:
Hi, Am Dienstag, den 07.10.2008, 15:30 +0100 schrieb Orestis Markou: That seems to work, thanks. Still trying to make sense of the manual for eval, as it says if the passed globals dict lacks...
3
by: GazK | last post by:
I have been using an xml parsing script to parse a number of rss feeds and return relevant results to a database. The script has worked well for a couple of years, despite having very crude...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.