accessing and storing character arguements from command line

Discussion in 'C Programming' started by Dawn Minnis, Feb 17, 2005.

  1. Dawn Minnis

    Dawn Minnis Guest

    Hey guys

    If I have a program (see codeSnippet1) that I compile to be called test.o
    Then run it as test.o n n 2 3 4
    I want the code to be able to strip out the two characters at the start
    (always going to be 2) and store them as characters. But I can't seem to
    get it to work because it is a pointer to a vector of characters.

    However, if I only run with integer arguements and use codeSnippet2 it works
    fine and they convert nicely to integers.

    So therefore, I want to ammend my nice little loop to start converting to
    integers from x=2 onwards. Which I can do fine. But how do I get the two
    characters that are actual characters to be stored as characters. It
    doesn't seem to be straightforward - or am I missing something stupidly
    obvious?



    codeSnippet1
    int main(int argc, char *argv[])
    {
    int x;
    char a, b;

    /*Need these two lines to work ie get the first two arguements stored as
    single characters for use elsewhere*/
    a = argv[0];
    b = argv[1];
    /**************************/

    }

    codeSnippet2
    int main(int argc, char *argv[])
    {
    int x;
    int params[10];
    for(x=0; x<argc; x++)
    {
    params[x] = atoi(argv[x]);
    }
    }
     
    Dawn Minnis, Feb 17, 2005
    #1
    1. Advertising

  2. Dawn Minnis wrote:

    > Hey guys
    >
    > If I have a program (see codeSnippet1) that I compile to be called test.o
    > Then run it as test.o n n 2 3 4
    > I want the code to be able to strip out the two characters at the start
    > (always going to be 2) and store them as characters. But I can't seem to
    > get it to work because it is a pointer to a vector of characters.
    >
    > However, if I only run with integer arguements and use codeSnippet2 it works
    > fine and they convert nicely to integers.
    >
    > So therefore, I want to ammend my nice little loop to start converting to
    > integers from x=2 onwards. Which I can do fine. But how do I get the two
    > characters that are actual characters to be stored as characters. It
    > doesn't seem to be straightforward - or am I missing something stupidly
    > obvious?
    >
    >
    >
    > codeSnippet1
    > int main(int argc, char *argv[])
    > {
    > int x;
    > char a, b;
    >
    > /*Need these two lines to work ie get the first two arguements stored as
    > single characters for use elsewhere*/
    > a = argv[0];
    > b = argv[1];
    > /**************************/
    >
    > }


    a = *argv[1];
    b = *argv[2];

    argv is a char **, so argv[1] is a char *. If you want the char pointed
    to by argv[1] you need to dereference it again... BTW, argv[0] is the
    program name if such is available.

    -David
     
    David Resnick, Feb 17, 2005
    #2
    1. Advertising

  3. Dawn Minnis

    Kiru Sengal Guest

    Dawn Minnis wrote:
    > Hey guys
    >
    > If I have a program (see codeSnippet1) that I compile to be called

    test.o
    > Then run it as test.o n n 2 3 4
    > I want the code to be able to strip out the two characters at the

    start
    > (always going to be 2) and store them as characters.


    \

    > But how do I get the two
    > characters that are actual characters to be stored as characters. It


    > doesn't seem to be straightforward - or am I missing something

    stupidly
    > obvious?
    >


    You're missing the fact that main is passed a pointer to pointer to
    char
    (or you can think of it as an array of pointers to char).

    >
    >
    >
    > codeSnippet1
    > int main(int argc, char *argv[])
    >


    The *argv[] parameter shows that main is receiving an array of pointers
    to char (since arrays are really passed as pointers, this becomes a
    pointer to a pointer to char - **argv is equivalent)

    > {
    > int x;
    > char a, b;
    >
    > /*Need these two lines to work ie get the first two arguements stored

    as
    > single characters for use elsewhere*/
    > a = argv[0];
    > b = argv[1];
    >


    With once subscript attached to argv, you are only dereferencing by one
    level.
    a is being assigned the first element in the array (which is a pointer
    to the first string). b is being assigned the second element in the
    array (which is a pointer to the second string). The command line
    interpreter considers each word (word being a sequence of
    non-whitespace characters) entered at the command line as a separate
    string, where the program name is the first string (pointed to by
    argv[0]).

    I presume you want to work with the characters of the second string
    (which is the first string after the program name). To do this, use
    this type of subscripting: argv[1] , which is character i of string
    1 (remember numbering starts at 0).

    So something like this would work if the "first two characters" are NOT
    separated by whitespace (which is what I assumed you wanted in the
    above paragraph):

    a = argv[1][0]; /* character 0 of string 1 */
    b = argv[1][1]; /* character 1 of string 1 */



    This would work if the first two characters are separated by
    whitespace:

    a = argv[1][0]; /* character 0 of string 1 */
    b = argv[2][0]; /* character 0 of string 2 */



    Although I wouldn't do this in a serious program because the user might
    not provide the expected input at the command-line (user might enter
    more than 1 character before whitespace). You are better dealing with
    entire strings, which will allow you to do more error checking.


    Remember, string 0 is the name of the program and is pointed to by
    argv[0], so I don't think you want to play with argv[0] -pointer to
    string 0- or argv[0][x] -character x of string 0-.
     
    Kiru Sengal, Feb 17, 2005
    #3
  4. Dawn Minnis

    Michael Mair Guest

    Dawn Minnis wrote:
    > Hey guys
    >
    > If I have a program (see codeSnippet1) that I compile to be called test.o
    > Then run it as test.o n n 2 3 4


    <OT>
    It is probably not a brilliant idea to call a program *.o as often
    ".o" marks object files which are created by compiling a translation
    unit and several of which may be linked together to obtain the final
    program
    </OT>

    > I want the code to be able to strip out the two characters at the start
    > (always going to be 2) and store them as characters. But I can't seem to
    > get it to work because it is a pointer to a vector of characters.


    You do not need to "strip out" the characters. You probably mean
    'n' and 'n' which are argv[1][0] and argv[2][0] in your example.
    The first two characters could also be 't' and 'e' (you do not
    express that clearly).
    If something is a char **, you obviously have to "get rid" of
    two levels of indirection, so you either want
    char mycharacter, **pp = argv;
    pp++; /* advance to &argv[1] */
    mycharacter = **pp;
    or
    char mycharacter, *p = argv[1];
    mycharacter = *p;
    or
    char mycharacter = *(argv[1]); /* gratuituous parens for clarifying */
    or
    char mycharacter = argv[1][0];

    > However, if I only run with integer arguements and use codeSnippet2 it works
    > fine and they convert nicely to integers.


    You are converting strings to integers.
    This is different from extracting one character from a string.
    >
    > So therefore, I want to ammend my nice little loop to start converting to
    > integers from x=2 onwards. Which I can do fine. But how do I get the two
    > characters that are actual characters to be stored as characters. It
    > doesn't seem to be straightforward - or am I missing something stupidly
    > obvious?
    >
    >
    >
    > codeSnippet1
    > int main(int argc, char *argv[])
    > {
    > int x;
    > char a, b;
    >
    > /*Need these two lines to work ie get the first two arguements stored as
    > single characters for use elsewhere*/
    > a = argv[0];
    > b = argv[1];


    Check for argc > 2 first. Then:
    You probably want
    a = *argv[1];
    b = *argv[2];
    argv[0] (if existing) is the name of the program.
    > /**************************/
    >
    > }
    >
    > codeSnippet2
    > int main(int argc, char *argv[])
    > {
    > int x;
    > int params[10];
    > for(x=0; x<argc; x++)
    > {
    > params[x] = atoi(argv[x]);


    This does not make sense.
    Please read up on argv in your C book.
    You want to have:

    if (argc >= 11)
    for (x=0; x<10; x++)
    params[x] = atoi(argv[x+1]);
    > }
    > }



    Cheers
    Michael
    --
    E-Mail: Mine is an /at/ gmx /dot/ de address.
     
    Michael Mair, Feb 17, 2005
    #4
  5. Dawn Minnis

    Dawn Minnis Guest

    Thank you

    Lots of food for thought there.

    I must have about 7 or 8 C programming books surrounding me but I still get
    confused by referencing and dereferencing pointers.

    Sorry about the confusion over the first element being the filename - I did
    actually know that, but I wrote the code out of my head because getting the
    code would have meant booting up my Linux machine and thats just too tedious
    for this time of night for one bit of code.

    > The *argv[] parameter shows that main is receiving an array of pointers
    > to char (since arrays are really passed as pointers, this becomes a
    > pointer to a pointer to char - **argv is equivalent)


    So just to clarify, even thought I have written char *argv[] it still
    means a double pointer? My supervisor kept writing char **argv[] but I
    thought that just overcomplicated things so I thought writing char *argv[]
    lessened the level of abstraction used.

    Maybe I'm away off in a world of my own again. I have a cold. Be gentle
    with me.

    Dawn
     
    Dawn Minnis, Feb 17, 2005
    #5
  6. Dawn Minnis

    Michael Mair Guest

    Dawn Minnis wrote:
    > Thank you
    >
    > Lots of food for thought there.
    >
    > I must have about 7 or 8 C programming books surrounding me but I still get
    > confused by referencing and dereferencing pointers.
    >
    > Sorry about the confusion over the first element being the filename - I did
    > actually know that, but I wrote the code out of my head because getting the
    > code would have meant booting up my Linux machine and thats just too tedious
    > for this time of night for one bit of code.


    But having three people to "repair" an error that is not there
    is better?


    >>The *argv[] parameter shows that main is receiving an array of pointers
    >>to char (since arrays are really passed as pointers, this becomes a
    >>pointer to a pointer to char - **argv is equivalent)

    >
    > So just to clarify, even thought I have written char *argv[] it still
    > means a double pointer? My supervisor kept writing char **argv[] but I
    > thought that just overcomplicated things so I thought writing char *argv[]
    > lessened the level of abstraction used.


    Your supervisor may have written char **argv -- certainly not
    char **argv[] as this is equivalent to char ***argv in a
    function parameter list.
    You can think of it like that:
    Arrays are never passed by value in C. Instead, the address of
    the first element is passed to a function requiring a
    T array[]
    parameter (where T is some type). T *array also contains the
    address of an object of type T -- which obviously can be the
    first element of an array. The array subscripting works the
    same in both cases.
    Note: T array[][] does not work as a replacement for T **array.
    Working out the reason is left as an exercise :)


    > Maybe I'm away off in a world of my own again. I have a cold. Be gentle
    > with me.


    Welcome to the fun world of C.


    Cheers
    Michael
    --
    E-Mail: Mine is an /at/ gmx /dot/ de address.
     
    Michael Mair, Feb 17, 2005
    #6
  7. Dawn Minnis

    Dawn Minnis Guest

    >> Sorry about the confusion over the first element being the filename - I
    >> did actually know that, but I wrote the code out of my head

    >
    > But having three people to "repair" an error that is not there
    > is better?
    >


    actually, upon reflection, I didn't even notice I was doing it until it was
    pointed out to me in this line:

    > params[x] = atoi(argv[x+1]);


    Thanks for that. Now I can see that even thought I read, listened,
    understood etc, I still went ahead and abandoned all rational thinking in
    favour of stupid/cold-infected coding.

    > Your supervisor may have written char **argv -- certainly not
    > char **argv[] as this is equivalent to char ***argv in a
    > function parameter list.


    Would love to concede to you on that one but afraid not. But in fairness,
    he does have a tendancy to say one thing and then write another. Or
    describe row-major as column-major. I think his brain is actually too
    intelligent for the rest of his body to keep up.

    > Welcome to the fun world of C.


    PAH !!! *shoots sarcastic look across the web* :-D
     
    Dawn Minnis, Feb 17, 2005
    #7
  8. Dawn Minnis

    Kenneth Bull Guest

    Dawn Minnis wrote:
    > >> Sorry about the confusion over the first element being the

    filename - I
    > >> did actually know that, but I wrote the code out of my head

    > >
    > > But having three people to "repair" an error that is not there
    > > is better?
    > >

    >
    > actually, upon reflection, I didn't even notice I was doing it until

    it was
    > pointed out to me in this line:
    >
    > > params[x] = atoi(argv[x+1]);

    >
    > Thanks for that. Now I can see that even thought I read, listened,
    > understood etc, I still went ahead and abandoned all rational

    thinking in
    > favour of stupid/cold-infected coding.
    >
    > > Your supervisor may have written char **argv -- certainly not
    > > char **argv[] as this is equivalent to char ***argv in a
    > > function parameter list.

    >
    > Would love to concede to you on that one but afraid not. But in

    fairness,
    > he does have a tendancy to say one thing and then write another. Or
    > describe row-major as column-major. I think his brain is actually

    too
    > intelligent for the rest of his body to keep up.
    >
    > > Welcome to the fun world of C.

    >
    > PAH !!! *shoots sarcastic look across the web* :-D



    Long ago my opinion of this world changed from thinking it was a
    meritocracy to thinking it was based mostly on other factors like
    luck, timing, randmoness of the universe, politics, and a little merit
    too. How your supervisor got to become a supervisor is a prime example
    (especially when I know genius programmers in every country who can't
    seem to find jobs).
     
    Kenneth Bull, Feb 17, 2005
    #8
  9. Dawn Minnis wrote:
    > I must have about 7 or 8 C programming books surrounding me but I

    still get
    > confused by referencing and dereferencing pointers.


    A pointer is just an address. If you have ten cubby holes numbered 100
    to 109, then at any point you will either want to know the number of
    the cubby hole or you will want what is actually in it. The only tricky
    part is that sometimes you have to write down and store the address of
    one cubby hole in another one.

    > So just to clarify, even thought I have written char *argv[] it

    still
    > means a double pointer?


    There are only cubby hole numbers and cubby hole contents in C,
    regardless of what symbols you might be using.

    char** stringArray1; //an array of strings
    char* stringArray2[]; //an array of strings
    char stringArray3[][]; //an array of strings

    In general though, I would recommend the top one for main(). What the
    "imaginary" difference is between a pointer and an array is that an
    array you (as the programmer) know exists and know has a set length:

    char tempBuffer[100]; /*temporary buffer with a definite max length*/

    While a pointer is just a way of saying, "Well I know that there's some
    data over that-a-way" but you really aren't certain of the
    length--probably because the length will be determined by the code
    itself, not you when coding.

    char* tempBuffer; /* buffer that we will allocate some random amount
    of bytes to */

    So when you first receive your command line arguments from main(), you
    will still have no idea how many parameters the user passed in nor how
    long any of those are. So as a way of pointing that out to yourself you
    are better off to use two *s instead of two []s.

    int main(int argc, char** argv) { /* accept any number of random
    thingies from user */
    return 0;
    }

    Note:

    char* string1 = "hello"; /* set text to print out */
    char string2[] = "hello"; /* generic string that we might edit later
    */

    This is a case you need to be careful about. C can treat these two
    cases differently, with the first one pointing to a fixed string that
    might be stored in a place you aren't allowed to write to, while as the
    second will always be created in a place you can fiddle about with
    freely.
    But if you stick to the basic idea that * just means something you
    "kind of" know about, while [] is for things you are very certain about
    then you should be able to remember this case. The pointer one is off
    in some controlled space while as the array is over with the you and
    rest of your variables.

    -Chris
     
    Chris Williams, Feb 18, 2005
    #9
  10. On 17 Feb 2005 20:58:25 -0800, "Chris Williams"
    <> wrote:

    > Dawn Minnis wrote:
    > > I must have about 7 or 8 C programming books surrounding me but I

    > still get
    > > confused by referencing and dereferencing pointers.

    >
    > A pointer is just an address. If you have ten cubby holes numbered 100
    > to 109, then at any point you will either want to know the number of
    > the cubby hole or you will want what is actually in it. The only tricky
    > part is that sometimes you have to write down and store the address of
    > one cubby hole in another one.
    >
    > > So just to clarify, even thought I have written char *argv[] it

    > still
    > > means a double pointer?

    >

    Yes.

    > There are only cubby hole numbers and cubby hole contents in C,
    > regardless of what symbols you might be using.
    >

    Sort of. With the caveat that different cubbyholes have different
    'shapes' -- and thus certain cubbyhole numbers can only be used to
    point to (and store or fetch) certain kinds of contents.

    > char** stringArray1; //an array of strings
    > char* stringArray2[]; //an array of strings
    > char stringArray3[][]; //an array of strings
    >
    > In general though, I would recommend the top one for main(). What the
    > "imaginary" difference is between a pointer and an array is that an
    > array you (as the programmer) know exists and know has a set length:
    >

    No. Arrays in C are really arrays not just pre-set pointers as they
    were in B and BCPL; in all but a few cases they _convert_ to a
    pointer, which we informally call decay. The first two are equivalent
    _for a function parameter_ because a parameter whose type is array is
    'rewritten' as a pointer -- at the top level only; they are not
    equivalent for a variable. The third is not the same ever, and is
    outright illegal in C99 -- you now cannot even declare an array of
    incomplete type. See FAQ section 6 at the usual places and
    http://www.eskimo.com/~scs/C-faq/top.html .

    > char tempBuffer[100]; /*temporary buffer with a definite max length*/
    >
    > While a pointer is just a way of saying, "Well I know that there's some
    > data over that-a-way" but you really aren't certain of the
    > length--probably because the length will be determined by the code
    > itself, not you when coding.
    >

    Length not known in advance is one reason; "I want to control the
    lifetime" (less than static but more than automatic) is another and "I
    want to access different things in different circumstances" a third.

    Aside: I would say the length is determined by the code at execution
    time, or by execution of the code; even a staticly declared length is
    still 'determined by the code'.

    > char* tempBuffer; /* buffer that we will allocate some random amount
    > of bytes to */
    >

    Not truly random, except in very rare cases, but variable and perhaps
    even random-seeming. <G>

    > So when you first receive your command line arguments from main(), you
    > will still have no idea how many parameters the user passed in nor how
    > long any of those are. So as a way of pointing that out to yourself you
    > are better off to use two *s instead of two []s.
    >
    > int main(int argc, char** argv) { /* accept any number of random
    > thingies from user */
    > return 0;
    > }
    >

    Arguable. Either char** or char*[] is the same to the compiler in this
    context. Some people prefer to see that it is really a pointer (which
    is used to access an array); some people prefer to see that its
    'purpose' is to access the array. Six of one ....

    > Note:
    >
    > char* string1 = "hello"; /* set text to print out */
    > char string2[] = "hello"; /* generic string that we might edit later
    > */
    >
    > This is a case you need to be careful about. C can treat these two
    > cases differently, with the first one pointing to a fixed string that
    > might be stored in a place you aren't allowed to write to, while as the
    > second will always be created in a place you can fiddle about with
    > freely.


    Right. More precisely, it violates the standard to write into the
    first (literal) string no matter how the compiler stores it. It is
    legal to modify the second -- but only within its allocated length,
    which for the example given means you can't _extend_ it.

    > But if you stick to the basic idea that * just means something you
    > "kind of" know about, while [] is for things you are very certain about
    > then you should be able to remember this case. The pointer one is off
    > in some controlled space while as the array is over with the you and
    > rest of your variables.
    >
    > -Chris


    - David.Thompson1 at worldnet.att.net
     
    Dave Thompson, Feb 28, 2005
    #10
    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. d davis
    Replies:
    0
    Views:
    494
    d davis
    Apr 27, 2004
  2. Rob Meade
    Replies:
    5
    Views:
    468
    Rob Meade
    Dec 5, 2005
  3. Ganesh Gella
    Replies:
    2
    Views:
    339
    John Harrison
    Nov 2, 2004
  4. Replies:
    40
    Views:
    894
    Michael Wojcik
    Jul 25, 2006
  5. Replies:
    1
    Views:
    132
    Ben Morrow
    Nov 10, 2006
Loading...

Share This Page