command line argument

Discussion in 'C Programming' started by Owner, Apr 5, 2011.

  1. Owner

    Owner Guest

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

    }
     
    Owner, Apr 5, 2011
    #1
    1. Advertising

  2. Owner

    Nobody Guest

    On Mon, 04 Apr 2011 22:52:07 -0400, Owner wrote:

    > 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].
     
    Nobody, Apr 5, 2011
    #2
    1. Advertising

  3. Owner <> wrote:
    > 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].

    --
    Peter
     
    Peter Nilsson, Apr 5, 2011
    #3
  4. Owner <> writes:

    > 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]);
    }

    --
    Ben.
     
    Ben Bacarisse, Apr 5, 2011
    #4
  5. On 05/04/2011 08:06, Peter Nilsson wrote:
    > 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
     
    Francois Grieu, Apr 5, 2011
    #5
  6. Francois Grieu <> writes:

    > On 05/04/2011 08:06, Peter Nilsson wrote:
    >> 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.

    --
    Ben.
     
    Ben Bacarisse, Apr 5, 2011
    #6
  7. Owner

    Seebs Guest

    On 2011-04-05, Francois Grieu <> wrote:
    > On 05/04/2011 08:06, Peter Nilsson wrote:
    >> 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
    --
    Copyright 2011, all wrongs reversed. Peter Seebach /
    http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
    http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
    I am not speaking for my employer, although they do rent some of my opinions.
     
    Seebs, Apr 5, 2011
    #7
  8. Owner

    Owner Guest

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

    }
     
    Owner, Apr 5, 2011
    #8
  9. Owner <> writes:

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


    --
    Ben.
     
    Ben Bacarisse, Apr 5, 2011
    #9
  10. On 05/04/2011 19:30, Seebs wrote :
    > On 2011-04-05, Francois Grieu<> wrote:
    >> On 05/04/2011 08:06, Peter Nilsson wrote:
    >>> 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
     
    Francois Grieu, Apr 5, 2011
    #10
  11. Owner

    Tim Rentsch Guest

    Seebs <> writes:

    > On 2011-04-05, Francois Grieu <> wrote:
    >> On 05/04/2011 08:06, Peter Nilsson wrote:
    >>> 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.
     
    Tim Rentsch, Apr 10, 2011
    #11
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Fong
    Replies:
    3
    Views:
    1,166
  2. Thomas Kellerer
    Replies:
    5
    Views:
    34,590
    Nomak
    Apr 13, 2005
  3. Justin Naidl

    Command line argument problems

    Justin Naidl, Sep 17, 2004, in forum: C++
    Replies:
    2
    Views:
    440
    Niels Dekker - no reply address
    Sep 18, 2004
  4. nic977

    reading in command line argument

    nic977, Sep 12, 2003, in forum: C Programming
    Replies:
    13
    Views:
    610
    Dave Thompson
    Sep 22, 2003
  5. Steven Knight
    Replies:
    0
    Views:
    448
    Steven Knight
    Nov 7, 2003
Loading...

Share This Page