how to return a string array from a function

后端 未结 9 645
暖寄归人
暖寄归人 2020-12-29 10:53
char * myFunction () {

    char sub_str[10][20]; 
    return sub_str;

} 

void main () {

    char *str;
    str = myFunction();

}

error:return

相关标签:
9条回答
  • 2020-12-29 11:09

    A string array in C can be used either with char** or with char*[]. However, you cannot return values stored on the stack, as in your function. If you want to return the string array, you have to reserve it dynamically:

    char** myFunction() {
        char ** sub_str = malloc(10 * sizeof(char*));
        for (int i =0 ; i < 10; ++i)
            sub_str[i] = malloc(20 * sizeof(char));
        /* Fill the sub_str strings */
        return sub_str;
    }
    

    Then, main can get the string array like this:

    char** str = myFunction();
    printf("%s", str[0]); /* Prints the first string. */
    

    EDIT: Since we allocated sub_str, we now return a memory address that can be accessed in the main

    0 讨论(0)
  • 2020-12-29 11:09

    As others correctly said you should use dynamic memory allocation by malloc to store your array inside heap and return a pointer to its first element.

    Also I find it useful to write a simple array of string implementation which has a minimal API for data manipulation.

    Type and API:

    typedef struct {
      char **array_ptr;
      int array_len;
      int string_len;
    } array_t;
    
    array_t* array_string_new(int array_len, int string_len);
    int array_string_set(array_t *array, int index, char *string);
    char* array_string_get(array_t *array, int index);
    int array_string_len(array_t *array);
    

    Usage:

    It creates an array with 4 dimensions that can store strings with 4 characters length. If the string length goes beyond the specified length, just its first 4 characters will be stored.

    int main()
    {
      int i;
      array_t *array = array_string_new(4, 4);
    
      array_string_set(array, 0, "foo");
      array_string_set(array, 1, "bar");
      array_string_set(array, 2, "bat");
      array_string_set(array, 3, ".... overflowed string");
    
      for(i = 0; i < array_string_len(array); i++)
        printf("index: %d - value: %s\n", i, array_string_get(array, i));
    
      /* output:
    
         index: 0 - value: foo
         index: 1 - value: bar
         index: 2 - value: bat
         index: 3 - value: ...
    
      */
    
      array_string_free(array);
    
      return 0;
    }
    

    Implementation:

    array_t*
    array_string_new(int array_len, int string_len)
    {
      int i;
      char **array_ptr = (char**) malloc(array_len * sizeof(char**));
    
      for(i = 0; i < array_len; i++) {
        array_ptr[i] = (char*) malloc(string_len * sizeof(char));
      }
    
      array_t *array = (array_t*) malloc(sizeof(array_t*));
      array->array_ptr = array_ptr;
      array->array_len = array_len;
      array->string_len = string_len;
    
      return array;
    }
    
    int
    array_string_set(array_t *array, int index, char *string)
    {
      strncpy(array->array_ptr[index], string, array->string_len);
      return 0;
    }
    
    char*
    array_string_get(array_t *array, int index)
    {
      return array->array_ptr[index];
    }
    
    int
    array_string_len(array_t *array)
    {
      return array->array_len;
    }
    
    int
    array_string_free(array_t *array)
    {
      int i;
      for(i = 0; i < array->array_len; i++) {
        free(array->array_ptr[i]);
      }
      free(array->array_ptr);
      return 0;
    }
    

    Notice that it is just a simple implementation with no error checking.

    0 讨论(0)
  • 2020-12-29 11:12

    Reason:
    you need the return type to be char(*)[20]. But even in this case you don't want to return a pointer to a local object from the function.
    Do:
    Use malloc to allocate sub_str, and return char**.

    0 讨论(0)
  • 2020-12-29 11:13
    char *f()
    {   
        static char str[10][20];
    
        // ......
    
        return (char *)str;
    }
    
    int main()
    {
    
        char *str;
        str = f();
    
        printf( "%s\n", str );
    
        return 0;
    }
    

    You can use static instead of malloc. It's your choice.

    0 讨论(0)
  • 2020-12-29 11:22

    i use that function to split a string to string array

    char  ** split(char *str, char *delimiter)
    {
        char *temp=strtok(str,delimiter);
        char *arr[]={temp};
        int i=0;
    
        while(true)
        {
           elm=strtok (NULL, delimiter);
    
           if(!temp) break;
    
           arr[++i]=temp;
        }
    
        return arr;
    }
    
    0 讨论(0)
  • 2020-12-29 11:23

    The cause of your compiler error is simple, but not the answer to what you really want to do. You are declaring that the function returns a char *, while returning a char **.

    Without knowing the details of what you're doing, I'm going to assume one of two things are true:

    1) The purpose of the function is to create and return an array of strings. 2) The function performs some operation(s) on an array of strings.

    If #1 is true, you need several malloc calls to make this work (It can really be done with only two, but for purposes of simplicity, I'll use several).

    If you don't know how large the array is supposed to be, your function declaration should look like this:

    char ** allocateStrings ( int numberOfStrings, int strLength );
    

    The reason for this is because you're essentially returning a pointer to an array of pointers and you need to know how many strings and how long each string is.

    char ** allocateStrings ( int numberOfStrings, int strLength )
    {
        int i;
    
        //The first line is allocating an array of pointers to chars, not actually allocating any strings itself
        char ** retVal = ( char ** ) malloc ( sizeof ( char * ) * numberOfStrings );
    
        //For each string, we need to malloc strLength chars
        for ( i = 0; i < numberOfStrings; i ++ )
        {
            //Allocate one extra char for the null pointer at the end
            retVal [ i ] = ( char * ) malloc ( sizeof ( char ) * ( strLength + 1 ) );
        }
    
        return retVal;
    }
    

    As somebody else pointed out, it's best practice to have whatever does the allocating also do the deallocating. So a cleanup function is needed.

    void cleanupStrings ( char ** strArray, int numberOfStrings )
    {
        int i;
    
        for ( i = 0; i < numberOfStrings; i ++ )
        {
            //Should be checking to see if this is a null pointer.
            free ( strArray [ i ] );
        }
    
        //Once the strings themselves are freed, free the actual array itself.
        free ( strArray );
    }
    

    Now, keep in mind that once the cleanup function is called, you no longer have access to the array. Trying to still use it will most likely cause your application to crash.

    If #2 is true, then you want to allocate the strings, process the strings, and clean them up. You should use the two functions above to allocate/deallocate your strings, then a third function to do whatever with them.

    void processStrings ( char ** strArray, int numberOfStrings, int strLength );
    
    0 讨论(0)
提交回复
热议问题