Returning char arrays...ugh

This is a discussion on Returning char arrays...ugh within the C Programming forums, part of the General Programming Boards category; Ok, whenever i do any C i always seem to get stuck at this point: I want to return a ...

  1. #1
    Registered User
    Join Date
    Dec 2009
    Location
    UK
    Posts
    30

    Returning char arrays...ugh

    Ok, whenever i do any C i always seem to get stuck at this point:
    I want to return a char array from a function to be used in main, like so:

    Code:
    char *editString(char *someString, char *someOtherString){
    int i = 6;
    someString = (char*) malloc(i+1);
    someString = "hello";
    someOtherString = (char*) malloc(i+1);
    someOtherString = "byeee";
    }
    
    int main (){
    char *someString, *someOtherString;
    editString(someString, someOtherString);
    printf("%s - %s\n", someString, someOtherString);
    }
    By my knowledge, this should work fine, but for some reason or other fails miserably, printing out the edited strings either results in strings of rubbish or nothing at all!
    heeeelp!

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    22,127
    You are assigning the result of malloc() to a local pointer, and then assigning a string literal too. This means that the pointer in the main function remains the same, i.e., it continues to point to nothing in particular. What you do get is a memory leak.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Dec 2009
    Location
    UK
    Posts
    30
    So then how do i get the pointer in the main function to keep what is assigned in the other one? Perhaps what i wrote there was a bad example, what i do in my program is loop through the array, assigning letter by letter from another string, eg:

    Code:
    if((acceptStates = (char*) malloc(x+1)) != NULL){
    	for(l = l+1, y = 0; l < i; l++, y++){
    		acceptStates[y] = input[l];
    	}
    	acceptStates[y] = '\0';
    }
    acceptstates is one of the char arrays being passed into the function, as is input (though input already has some characters in it).

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    22,127
    One way is to allocate space in the main function, then pass a pointer to the first character of that array. strcpy, strncpy, etc, can then be used to populate the array given that pointer.

    Another way is to pass a pointer to a pointer, so that the pointer in the main function can be modified from the editString function. Again, strcpy, strncpy, etc, can be used to populate the dynamic array.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #5
    Banned
    Join Date
    May 2007
    Location
    Berkeley, CA
    Posts
    329
    Another alternative would be to use static. Here is an example...

    Code:
    #include <stdio.h>
    
    char *editString(char someString[])
    { 
      static char stuff[] = "bye";
    
      return stuff;
    }
    
    int main(void)
    {
      char someString[] = "hello";
      char *someOtherString;
      someOtherString = editString(someString);
      printf("%s - %s\n", someString, someOtherString);
    
      return 0;
    }
    [cd@localhost oakland]$ ./copyarr
    hello - bye
    [cd@localhost oakland]$
    Last edited by Overworked_PhD; 04-21-2010 at 12:19 PM. Reason: Malloc blows and not that well either.

  6. #6
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Instead of returning a local array, what I do is create the array in the calling function (main, whatever), and then BRING that array, into the local function that will be working with it, and then there is no need to return it - all the changes you make are saved in the array.

    Maybe just my opinion, but that's how C was made to do this, imo. It's ez and very transparent - try it.

  7. #7
    Registered User
    Join Date
    Aug 2007
    Location
    MD, USA
    Posts
    71
    You can return the address of allocated space OR you can pass an address as an argument and have it "serviced".
    Either way , the allocated space MUST be free()'d when the program is done with it.
    If it is not it then becomes a "memory leak".
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    char * return_str( size_t len)
    {
      char * s = calloc(1, len);
      strncpy(s, "hello", len);
    
      return s;
    }
    
    void assign_str(char * t, int len)
    {
      char * s = calloc(1, len);
      strncpy(s, "hello2", len);
      t = s;
    }
    
    int main(void)
    {
      char * sp1;
    
      sp1 = return_str(32);
      printf("sp1: %s \n", sp1);
      free(sp1);
    
      assign_str(sp1, 32);
      printf("sp1: %s \n", sp1);
      free(sp1);
    
      return 0;
    }
    At least I think that's right...
    Last edited by HowardL; 04-21-2010 at 04:26 PM.

  8. #8
    Registered User whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    7,751
    I would write assign_string in the following way instead. There is no real difference between the two if both functions allocate some space.

    Code:
    void assign_string (char *s , char *source , size_t len)
    {
       if (s == NULL || source == NULL) return ;
       s[0] = '\0';
       strncat (s , source , len - 1);
    }
    
    int main ()
    {
       int size = 32;
       char *space = malloc (size);
       assign_string (space , "hello world" , size);
       printf ("the string says '%s'\n" , space);
       free (space);
       return 0;
    }

  9. #9
    Registered User
    Join Date
    Aug 2007
    Location
    MD, USA
    Posts
    71
    There is no real difference between the two if both functions allocate some space.
    But yours allocates space in main() and NOT in the function.

  10. #10
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    22,127
    Quote Originally Posted by HowardL
    You can return the address of allocated space OR you can pass an address as an argument and have it "serviced".
    Ah yes, I neglected to mention the option of returning an address. However, my point about passing a pointer to a pointer if one wants to allocate space in the function holds: your assign_str function implementation is incorrect. More correctly:
    Code:
    void assign_str(char **s)
    {
        *s = malloc(sizeof("hello2"));
        strcpy(*s, "hello2");
    }
    Then in main:
    Code:
    assign_str(&sp1);
    EDIT:
    There is a problem with using strncpy as in your example: it assumes that len will be greater than strlen("hello") and strlen("hello2") respectively. If not, the null character will not be copied, and the caller will end up with a pointer to the first character of a dynamic array that does not contain a null terminated string.
    Last edited by laserlight; 04-21-2010 at 11:09 PM.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  11. #11
    Registered User
    Join Date
    Aug 2007
    Location
    MD, USA
    Posts
    71
    oops, I see what you're saying. Real sorry to post a bad example.
    Thanks for straightening me out on those things.
    Sometime I might start retaining some of this for more than a day... or maybe it's too late
    Last edited by HowardL; 04-22-2010 at 12:18 AM.

  12. #12
    Registered User whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    7,751
    Quote Originally Posted by HowardL View Post
    But yours allocates space in main() and NOT in the function.
    Quote Originally Posted by HowardL View Post
    You can return the address of allocated space OR you can pass an address as an argument and have it "serviced".
    Either way , the allocated space MUST be free()'d when the program is done with it.
    If it is not it then becomes a "memory leak".
    You're right with what you said here. I just wanted to demonstrate what you actually said. By requiring users to pass in an array you should eschew calling malloc anyway. Passing in the address of an array is different. It implies that the location of the array will change, which happens with malloc/realloc. I still stick by my earlier comment that your two examples are not very different. In fact the only difference is that the corrected example uses no return value, while another example does use a return value.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. I need help :(
    By ramenen in forum C++ Programming
    Replies: 1
    Last Post: 02-17-2010, 04:31 PM
  2. get keyboard and mouse events
    By ratte in forum Linux Programming
    Replies: 10
    Last Post: 11-17-2007, 05:42 PM
  3. The Interactive Animation - my first released C program
    By ulillillia in forum A Brief History of Cprogramming.com
    Replies: 48
    Last Post: 05-10-2007, 03:25 AM
  4. Need help understanding info in a header file
    By hicpics in forum C Programming
    Replies: 8
    Last Post: 12-02-2005, 12:36 PM
  5. How do you search & sort an array?
    By sketchit in forum C Programming
    Replies: 30
    Last Post: 11-03-2001, 05:26 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21