Results 1 to 18 of 18

Thread: convert char* array to string array

  1. #1

    Thread Starter
    Frenzied Member markman's Avatar
    Join Date
    Nov 2000
    Location
    Florida.
    Posts
    1,197

    convert char* array to string array

    Im trying to convert the command line arguments to string form instead of char*, but it obviously isnt working since Im asking this question
    Heres the code:
    Code:
    string* charstararray2stringarray(int args, char* argv[]);
    int main(int args, char* argv[])
    {
    string* stringarray;
    	stringarray = charstararray2stringarray(args,argv);
    retrun 0;
    }
    
    string* charstararray2stringarray(int args, char* argv[])
    {
        //converts char*[] to string[]
        //used for command line
        string* retVal;
        retVal = new string[args];
        for (unsigned int i = 0; i <= args; i++)
        {
    	retVal[i] = (string)argv[i];
        }
        return *retVal;
        delete [] retVal;
    }
    retired member. Thanks for everything

  2. #2

    Thread Starter
    Frenzied Member markman's Avatar
    Join Date
    Nov 2000
    Location
    Florida.
    Posts
    1,197
    I didnt quite understand what I did in returning the array, it was a copy & paste job when I couldnt figure out how to return an array

    (im quite new at this; I took a full year class and I still forget how to make an if statement! what a waste of time that was )
    retired member. Thanks for everything

  3. #3
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    You basically have the typical array-returning problem that many new C/C++ programmers have.

    You should never return an array from a function. It will always get you into trouble.

    It's a matter of scoping. Consider this code:
    Code:
    int *retar();
    int main()
    {
      int *ar = retar();
    }
    
    int *retar()
    {
      int ar[10] = {0};
      return ar;
    }
    Where's the problem with that code? ar in retar is created on the stack, therefore it is destroyed once the function exits. ar in main now contains a pointer to the destroyed array, it is invalid memory!

    You might want to solve this by using new or malloc (as you have done). Then there is the problem of freeing this memory. The caller should not be responsible for this, after all he can't know it's really dynamic memory, it could be something else. You're bound to get memory leaks when you do this.
    Neither can the calling function free the memory. There are two ideas:
    Code:
    int *funcy()
    {
      int * p = new int[20];
      // free the memory
      delete [] p;
      // and return
      return p;
    }
    This obviously can't work as p is invalid after the delete.
    Here's what you did:
    Code:
    int *morefunc()
    {
      int *p = new int[20];
      return p;
      delete [] p;
    }
    Now why doesn't this work?
    The moment the cpu encounters the return statement it leaves the function. The delete line is never executed. You have a memory leak.

    The Solution
    You never return an array. Instead the called passes a buffer which will be filled.
    A buffer is any memory location. It can be statically allocated, dynamically allocated, it doesn't matter because the caller knows what to do with it. To prevent overflow (writing more data in the buffer than it can hold) the size of the buffer is passed too, either in bytes or (better) in the number of elements it can hold.
    This would work:
    Code:
    // return value is usually the actual number of elements written
    // but could also be some sort of error code
    int charstararray2stringarray(int bufsize, string *buffer, int args, char * argv[]);
    
    int main(int args, char *argv[])
    {
      // you could either allocate a static array:
      // string ararg[20];
      // or dynamically allocate it
      string *ararg = new string[args];
      int elems = charstararray2stringarray(args /* or 20 if statically allocated*/,
          ararg, args, argv);
    
      // if you allocated dynamically, you must free it
      delete [] arargs;
    }
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  4. #4

    Thread Starter
    Frenzied Member markman's Avatar
    Join Date
    Nov 2000
    Location
    Florida.
    Posts
    1,197
    Thanks for spending the effor to teach me this. It is much appreciated




    But:

    What would be the code for the charstararraytostringarray function in the solution? What do I do with the new variable passed to it? instead of returning something I change the address of the ararg? If so then whats elems there for?
    retired member. Thanks for everything

  5. #5
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    You fill the provided array:
    Code:
    int charstararray2stringarray(int bufsize, string *buffer, int args, char * argv[])
    {
      int count = min(args, bufsize);
      for (unsigned int i = 0; i < count; ++i)
      {
        buffer[i] = argv[i];
      }
      return count;
    }
    Some things:
    a) in loops that traverse an array from start to end, it's always
    for(loopvar = 0; loopvar < arlength, ++loopvar)
    or loopvar++, doesn't really matter on a good compiler.
    If you use loopvar <= arlength then there will be one iteration where loopvar == arlength. Since C/C++ arrays start indexing at 0, arlength is not a valid index anymore.

    b) You don't do (string)"text" to convert a char array to string. This is the old C-style cast and not to be used. Instead you either explicitly call the contructor: string("text") or in this case take advantage of the fact that the = operator is overloaded to take char*:
    string s = "text";
    This avoid creating a temporary string object and is therefore faster.
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  6. #6

    Thread Starter
    Frenzied Member markman's Avatar
    Join Date
    Nov 2000
    Location
    Florida.
    Posts
    1,197
    Thanks

    I learned a lot from that
    retired member. Thanks for everything

  7. #7
    Fanatic Member MoMad's Avatar
    Join Date
    Oct 2000
    Location
    Seattle, WA
    Posts
    625
    Originally posted by CornedBee
    Code:
    for (unsigned int i = 0; i < count; ++i)
      {
        buffer[i] = argv[i];
      }
      return count;
    }
    Take away unsigned since count is signed, it will give compiler warnings... i dont know if this is usefull but i dont like seeing ANY ERRORS or WARNINGS when i compile :P
    :MoMad:
    Nice Sig!

    http://go.to/momad/ Status: Not Ready

  8. #8

    Thread Starter
    Frenzied Member markman's Avatar
    Join Date
    Nov 2000
    Location
    Florida.
    Posts
    1,197
    why would it be signed? it only goes up...
    retired member. Thanks for everything

  9. #9
    Monday Morning Lunatic parksie's Avatar
    Join Date
    Mar 2000
    Location
    Mashin' on the motorway
    Posts
    8,169
    Originally posted by MoMad
    Take away unsigned since count is signed, it will give compiler warnings... i dont know if this is usefull but i dont like seeing ANY ERRORS or WARNINGS when i compile :P
    Rather than removing the unsigned, make sure that count is unsigned (which it should be).
    I refuse to tie my hands behind my back and hear somebody say "Bend Over, Boy, Because You Have It Coming To You".
    -- Linus Torvalds

  10. #10

    Thread Starter
    Frenzied Member markman's Avatar
    Join Date
    Nov 2000
    Location
    Florida.
    Posts
    1,197
    Originally posted by CornedBee
    You fill the provided array:
    Code:
    int charstararray2stringarray(int bufsize, string *buffer, int args, char * argv[])
    {
      int count = min(args, bufsize);
      for (unsigned int i = 0; i < count; ++i)
      {
        buffer[i] = argv[i];
      }
      return count;
    }
    Some things:
    a) in loops that traverse an array from start to end, it's always
    for(loopvar = 0; loopvar < arlength, ++loopvar)
    or loopvar++, doesn't really matter on a good compiler.
    If you use loopvar <= arlength then there will be one iteration where loopvar == arlength. Since C/C++ arrays start indexing at 0, arlength is not a valid index anymore.

    b) You don't do (string)"text" to convert a char array to string. This is the old C-style cast and not to be used. Instead you either explicitly call the contructor: string("text") or in this case take advantage of the fact that the = operator is overloaded to take char*:
    string s = "text";
    This avoid creating a temporary string object and is therefore faster.
    I got:
    cant convert from char* to string, and min() not defined...

    Using g++ on redhat7.3
    retired member. Thanks for everything

  11. #11
    Fanatic Member MoMad's Avatar
    Join Date
    Oct 2000
    Location
    Seattle, WA
    Posts
    625
    use:

    PHP Code:

    int min 
    (int firstint second) {
      return (
    first<second) ? first second;
    }

    // and that string  to char* conversion, use
    buffer[i] = string(argv[i]); 
    :MoMad:
    Nice Sig!

    http://go.to/momad/ Status: Not Ready

  12. #12

    Thread Starter
    Frenzied Member markman's Avatar
    Join Date
    Nov 2000
    Location
    Florida.
    Posts
    1,197
    thanks everyone

    I actually figured it out before I read this by MAKING A MACRO FOR IT!!!! Im so proud. Excuse me while I praise myself
    retired member. Thanks for everything

  13. #13
    Fanatic Member MoMad's Avatar
    Join Date
    Oct 2000
    Location
    Seattle, WA
    Posts
    625
    Hey CB, whats that you said about gcc and post-incrementing? Is it not good??

    Isnt i++ and ++i in a for loop the same, since as soon as its out of that line, it will increment, or it will increment first, then execute the line. hmm... in msvc i realized that it doesnt matter weather or not u post/pre increment in the FOR loop, because by the time it finishes with that line:

    [code]
    for (step 1; step2; step 3) {
    step 4;
    }
    step 5;

    it executes like this:

    step 1
    step 2
    step 4
    step 3
    // repeat 4 and 3 as necessary
    then step 5
    [/php]

    so each step thru, it will only do the increments either before the step or after (pre/post). But in step 3, there is nothing else going on, so it doesnt matter wether u use pre or post increment/decrement.

    So, after all this ranting, i wanna ask you weather or not you agree with this or what is with the ++i (maybe a preference or ?)

    Thanks man,
    MoMad the NoMad
    :MoMad:
    Nice Sig!

    http://go.to/momad/ Status: Not Ready

  14. #14
    Monday Morning Lunatic parksie's Avatar
    Join Date
    Mar 2000
    Location
    Mashin' on the motorway
    Posts
    8,169
    ++i is faster, at least on x86.
    I refuse to tie my hands behind my back and hear somebody say "Bend Over, Boy, Because You Have It Coming To You".
    -- Linus Torvalds

  15. #15

    Thread Starter
    Frenzied Member markman's Avatar
    Join Date
    Nov 2000
    Location
    Florida.
    Posts
    1,197
    Maybe I shouldnt praise myself just yet. I came across a problem when cout-ing the first 3 elements in ararg. When I type './a.out arg2 arg3' I get two Q's with squiggles in them (the first is lowercase and the seocnd is upper) that I get after the bash prompt. There isnt even a new line where I had the endl on the cout statements. No compiler errors or warnings...
    Attached Files Attached Files
    retired member. Thanks for everything

  16. #16

    Thread Starter
    Frenzied Member markman's Avatar
    Join Date
    Nov 2000
    Location
    Florida.
    Posts
    1,197
    nevermind. Had a big of an 'order-of-things' problem.

    But now when compiling, it doesnt like changing an unsigned int to int in that min() function. I cant see an unsigned int though...
    retired member. Thanks for everything

  17. #17
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    parksie: yes count should be unsigned, but args is signed (and that is given), so in order to avoid all conversions all variables should be signed.

    Here's a better form of the min function/macro:
    Code:
    template <typename T>
    inline T min(T a, T b) {
      return a < b ? a : b;
    }
    As fast and flexible as a macro, yet more safe.

    About pre and postfix...
    Write this code in a file:
    Code:
    int = 0;
    i++;
    ++i;
    Compile in debug mode and ask the compiler to output assembly code. Then take a look at it. It should look something like
    Code:
    $i = -4
    ; blabla, start code of main
    ; int i = 0
    mov eax 0
    mov DWORD PTR [ebp + $i] eax
    ; i++
    mov edx DWORD PTR [ebp+$i]
    inc edx
    mov DWORD PTR [ebp+$i] edx
    ; ++i
    mov eax DWORD PTR [ebp+$i]
    inc eax
    mov DWORD PTR [ebp+$i] eax
    Actually it is more likely that the inc e?x instructions would be add e?x 1 instructions, they are nearly equivalent.
    If you compile in release mode you'll have no code at all.

    Where is the difference between the two commands? Obviously only the register in which the value is saved. eax is called the accumulator, it is the best register for mathematical operations and is treated in a special way by the cpu: additions are much faster there than anywhere else. add eax ??? takes 2 cycles compared to 7 in any other register!
    All compilers will by default do a i++ in edx and a ++i in eax, this is why ++i is faster.

    doesn't really matter on a good compiler.
    I said this because I assume that if nothing special is done most compilers are smart enough to optimize this difference away and do a i++ in eax. Yet I'm not sure.
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  18. #18
    Fanatic Member MoMad's Avatar
    Join Date
    Oct 2000
    Location
    Seattle, WA
    Posts
    625
    Cool thanks for clarifying that!

    [EDIT]
    Even though, i barely understood what u said.. isss all goooodddd!!! thz
    :MoMad:
    Nice Sig!

    http://go.to/momad/ Status: Not Ready

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width