command line argument

O

Owner

What I'm trying to do with argv is
swapping argv[0] to the end and files argument to the front
reason I'm doing that is in English
cmd options file... is nicely read
do this(cmd) how(option) with file...
but in my language
it's more naturally read
file.... option cmd
so I'm playing around with my codes.

this code below keeps changing argv[0] to file1
can anyone find a fault code below?

Thank you in advance.

void hcmd(int argc, char *argv[])
{
int i, j;
int opcount, agcount;
char **k, **op, **ag;
char *tmp;
char *newarg[100];

k = op = ag = argv;
opcount = agcount = 0;
/* Saving Command */
*k = argv[0];



/* first Option */
if (argc == 1) return;

i = 1;

if (argv[0] == '-' || argv[0] == '/'){
*op = argv[i++];
opcount++;
}

/* counting rest of options */
for (;i < argc && argv[0] == '-' || argv[0] == '/';i++)
opcount++;

/* first argument */
if (i < argc){
*ag = argv[i++];
agcount++;
}

/* rest of argument */
for (; i < argc; i++)
agcount++;

for(i=0; i< argc; i++)
printf("%s ", argv);

}
 
N

Nobody

What I'm trying to do with argv is
swapping argv[0] to the end and files argument to the front
reason I'm doing that is in English
cmd options file... is nicely read
do this(cmd) how(option) with file...
but in my language
it's more naturally read
file.... option cmd
so I'm playing around with my codes.

this code below keeps changing argv[0] to file1

Note that argv[0] is typically the name of the program. The first
real *argument* is argv[1].
 
P

Peter Nilsson

Owner said:
What I'm trying to do with argv is
swapping argv[0] to the end and files argument to the front

A strictly conforming program cannot modify the contents of argv[].
reason I'm doing that is in English
cmd options file... is nicely read
do this(cmd) how(option) with file...
but in my language
it's more naturally read
file.... option cmd
so I'm playing around with my codes.

this code below keeps changing argv[0] to file1
can anyone find a fault code below?

argv[0] is the name of the program (in most cases.)

If you just want to print the command line, with argv[0] last,
do something like...

int n;
for (n = 1; n < argc; n++) printf("%s ", argv[n]);
if (argc) puts(argv[0]);

There's no obvious reason to manipulate argv[] just to special
case argv[0].
 
B

Ben Bacarisse

Owner said:
What I'm trying to do with argv is
swapping argv[0] to the end and files argument to the front
reason I'm doing that is in English
cmd options file... is nicely read
do this(cmd) how(option) with file...
but in my language
it's more naturally read
file.... option cmd
so I'm playing around with my codes.

this code below keeps changing argv[0] to file1
can anyone find a fault code below?

Thank you in advance.

void hcmd(int argc, char *argv[])
{
int i, j;
int opcount, agcount;
char **k, **op, **ag;
char *tmp;
char *newarg[100];

k = op = ag = argv;

The code makes not assignments to argv so any changes to it occur
through one of these three aliases.
opcount = agcount = 0;
/* Saving Command */
*k = argv[0];

This has no effect so you might as well get rid of k althrogether (along
with j, tmp and newarg that are never even used).
/* first Option */
if (argc == 1) return;

argc can be < 1. However, I don't see why you want to do nothing when
argc == 1. I thought you would want to print argv[0] at least.
i = 1;

if (argv[0] == '-' || argv[0] == '/'){
*op = argv[i++];
opcount++;
}


This set argv[0] (op is equal to argv so *op is an alias for
*argv).
/* counting rest of options */
for (;i < argc && argv[0] == '-' || argv[0] == '/';i++)


Turn up your compiler warning level! This means

(i < argv && argv[0] == '-')
||
(argv[0] == '/')

and so this loop can run too far.
opcount++;

/* first argument */
if (i < argc){
*ag = argv[i++];

and here you set argv[0] because ag is equal to argv.
agcount++;
}

/* rest of argument */
for (; i < argc; i++)
agcount++;

for(i=0; i< argc; i++)
printf("%s ", argv);

}


If all you want to do is print argv in a different order, then there is
not need to go to all this effort:

void hcmd(int argc, char *argv[])
{
int i;
for (i = 1; i < argc; i++)
if (argv[0] == '-' || argv[0] == '/')
printf("%s ", argv);
for (i = 1; i < argc; i++)
if (argv[0] != '-' && argv[0] != '/')
printf("%s ", argv);
if (argc > 0)
printf("%s", argv[0]);
}
 
F

Francois Grieu

A strictly conforming program cannot modify the contents of argv[].

Why ? 5.1.2.2.1p2 says
" — The parameters argc and argv and the strings pointed to by the
argv array shall be modifiable by the program, and retain their
last-stored values between program startup and program termination."

Francois Grieu
 
B

Ben Bacarisse

Francois Grieu said:
A strictly conforming program cannot modify the contents of argv[].

Why ? 5.1.2.2.1p2 says
" — The parameters argc and argv and the strings pointed to by the
argv array shall be modifiable by the program, and retain their
last-stored values between program startup and program termination."

That does not include the elements of the array whose first element is
pointed to by argv.

I once suggested that this permission (that the argv pointers themselves
can not be modified) is not very useful and that it may be an oversight.
I was assured that there are cases where it makes sense though it still
seems a little odd to me.

It is, however, certainly clear that the wording you quote does not
permit modification of argv[0] through to argv[argc] in a portable
program.
 
S

Seebs

A strictly conforming program cannot modify the contents of argv[].
Why ? 5.1.2.2.1p2 says
" ? The parameters argc and argv and the strings pointed to by the
argv array shall be modifiable by the program, and retain their
last-stored values between program startup and program termination."

To be picky:

That is two of the three. The contents of argv is the third.

We are assured that argc and argv themselves are modifiable. The members
of the argv array are not mentioned. The strings *pointed to* by the argv
array are mentioned. So imagine the following setup:

char writeable[] = "foo\0";
const char *first = &writeable[0];
char **argv = { (char *) first, NULL };

main(1, argv);

This complies with the description given in the standard, but if you
try to change argv[0], you invoke undefined behavior.

-s
 
O

Owner

After playing around with code, I got some productive result

the following code changes
for example
"program /1 /2 arg1 arg2 arg3" to
"arg1 arg2 arg3 /1 /2 program"

but here is the catch
if I take out the prinf("\n"); statement in main()
, it does not work
and I still don't know why.
wonder if this is one of the undefined behavior

can anyone guess?

#include <stdio.h>

char **hcmd(int argc, char **argv)
{
#define MAXSTR 100
int i;
int opcount, agcount;
int k, op, ag;

char *newarg[MAXSTR];

opcount = agcount = 0;
i = 0;
/* Saving Command */
k = i++;

/* first Option */
if (argc < i) return;

if (argv[0] == '-' || argv[0] == '/'){
op = i++;
opcount++;
}

/* counting rest of options */
for (;i < argc && argv[0] == '-' || argv[0] == '/';i++)
opcount++;

/* first argument */
if (i < argc){
ag = i++;
agcount++;
}

/* rest of argument */
for (; i < argc; i++)
agcount++;

i = 0;
for (; i < agcount; i++)
newarg = argv[ag++];

for (; i < opcount + agcount; i++)
newarg = argv[op++];

newarg = argv[k];
newarg[++i] = NULL;

return newarg;
}

int main
(int argc, char *argv[])
{
int i;

printf("\n");
argv = hcmd(argc, argv);
for (i = 0; i < argc; i++)
printf("%s ", argv);

}
 
B

Ben Bacarisse

Owner said:
After playing around with code, I got some productive result

the following code changes
for example
"program /1 /2 arg1 arg2 arg3" to
"arg1 arg2 arg3 /1 /2 program"

but here is the catch
if I take out the prinf("\n"); statement in main()
, it does not work
and I still don't know why.
wonder if this is one of the undefined behavior

You have undefined behaviour because the function returns the address of
a local object (one that is about to disappear). As a result, you can't
really rely on anything that happens.
can anyone guess?

#include <stdio.h>

char **hcmd(int argc, char **argv)
{
#define MAXSTR 100
int i;
int opcount, agcount;
int k, op, ag;

char *newarg[MAXSTR];

opcount = agcount = 0;
i = 0;
/* Saving Command */
k = i++;

This is not a clear way of writing this. For one thing it is simpler to
set i = 1, k = 0 but that does not explain what k is for. You might as
well set the command name right now:

newarg[argc - 1] = argv[0];

or you can get rid of k and write the line at the end of the function.
/* first Option */
if (argc < i) return;

return what?
if (argv[0] == '-' || argv[0] == '/'){
op = i++;
opcount++;
}

/* counting rest of options */
for (;i < argc && argv[0] == '-' || argv[0] == '/';i++)
opcount++;


see previous message.
/* first argument */
if (i < argc){
ag = i++;
agcount++;
}

/* rest of argument */
for (; i < argc; i++)
agcount++;

This increments agcount exactly argc - i times. You might as well write

agcount += argc - 1;
i = 0;
for (; i < agcount; i++)
newarg = argv[ag++];


You can get here without setting ag. This loop is therefore another
source of undefined behaviour.
for (; i < opcount + agcount; i++)
newarg = argv[op++];

newarg = argv[k];


k is always 0. Writing argv[0] is clearer than using a variable you set
right up the top of the function.
newarg[++i] = NULL;

return newarg;

This won't work. You will either have to allocate used allocated
storage or you can have the caller (main) pass an array into which you
write the re-ordered version of argv (that would be my preference).
}

int main
(int argc, char *argv[])
{
int i;

printf("\n");
argv = hcmd(argc, argv);
for (i = 0; i < argc; i++)
printf("%s ", argv);

}
 
F

Francois Grieu

A strictly conforming program cannot modify the contents of argv[].
Why ? 5.1.2.2.1p2 says
" The parameters argc and argv and the strings pointed to by the
argv array shall be modifiable by the program, and retain their
last-stored values between program startup and program termination."

To be picky:

That is two of the three. The contents of argv is the third.

We are assured that argc and argv themselves are modifiable. The members
of the argv array are not mentioned. The strings *pointed to* by the argv
array are mentioned. So imagine the following setup:

char writeable[] = "foo\0";
const char *first =&writeable[0];
char **argv = { (char *) first, NULL };

main(1, argv);

This complies with the description given in the standard, but if you
try to change argv[0], you invoke undefined behavior.

No contest: I misread "argv is modifiable" as meaning each element
of array argv[] is modifiable; but that's a figment of my imagination.

That's sad, because a few of my tools write into argv[], e.g. to
allow replacing an argument by a computed value.
I've never met an environment where that cause a visible problem.
I bet it is fairly unusual.

Francois Grieu
 
T

Tim Rentsch

Seebs said:
A strictly conforming program cannot modify the contents of argv[].
Why ? 5.1.2.2.1p2 says
" ? The parameters argc and argv and the strings pointed to by the
argv array shall be modifiable by the program, and retain their
last-stored values between program startup and program termination."

To be picky:

That is two of the three. The contents of argv is the third.

We are assured that argc and argv themselves are modifiable. The members
of the argv array are not mentioned. The strings *pointed to* by the argv
array are mentioned. So imagine the following setup:

char writeable[] = "foo\0";
const char *first = &writeable[0];
char **argv = { (char *) first, NULL };

main(1, argv);

This complies with the description given in the standard, but if you
try to change argv[0], you invoke undefined behavior.

You need a better example. This one doesn't compile, and if it
did by changing the argv declaration to what you presumably meant

char *argv[] = { (char*) first, NULL };

then changing argv[0] is not undefined but well-defined; the
'const' in the declaration of 'first' doesn't affect whether
argv[0] can be changed.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,763
Messages
2,569,562
Members
45,038
Latest member
OrderProperKetocapsules

Latest Threads

Top