开发者

how to return a string array from a function

char * myFunction () {

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

}开发者_开发知识库 

void main () {

    char *str;
    str = myFunction();

}

error:return from incompatible pointer type

thanks


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


To programmers just starting out, the concept of a "stack" or the "heap" might be a little confusing, especially if you have started programming in a higher level language like Ruby, Java, Python, etc.

Consider:

char **get_me_some_strings() {
  char *ary[] = {"ABC", "BCD", NULL};
  return ary;
}

The compiler will rightfully issue a complaint about trying to return address of a local variable, and you will most certainly get a segmentation fault trying to use the returned pointer.

and:

char **get_me_some_strings() {
  char *ary[] = {"ABC", "BCD", NULL};
  char **strings = ary;
  return strings;
}

will shut the compiler up, while still getting the same nasty segmentation fault.

To keep everyone but the zealots happy, you would do something a little more elaborate:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char **get_me_some_strings() {
  char *ary[] = { "ABC", "BCD", NULL };
  char **strings = ary; // a pointer to a pointer, for easy iteration
  char **to_be_returned = malloc(sizeof(char*) * 3);
  int i = 0;
  while(*strings) {
    to_be_returned[i] = malloc( sizeof(char) * strlen( *strings ) );
    strcpy( to_be_returned[i++], *strings);
    strings++;
  }
  return to_be_returned;
}

now use it:

void i_need_me_some_strings() {
  char **strings = get_me_some_strings();
  while(*strings) {
    printf("a fine string that says: %s", *strings);
    strings++;
  }
}

Just remember to free the allocated memory when you are done, cuz nobody will do it for you. That goes for all the pointers, not just the pointer to the pointers! (i think).

To make more sense of it all, you might also want to read this: What and where are the stack and heap?


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**.


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


As others have said, you cannot return a local char array to the caller, and have to use heap memory for this.

However, I would not advise using malloc() within the function.

Good practice is that, whoever allocates memory, also deallocates it (and handles the error condition if malloc() returns NULL).

Since your myFunction() does not have control over the memory it allocated once it returned, have the caller provide the memory in which to store the result, and pass a pointer to that memory.

That way, the caller of your function can de-allocate or re-use the memory (e.g. for subsequent calls to myFunction()) however he sees fit.

Be careful, though, to either agree on a fixed size for such calls (through a global constant), or to pass the maximum size as additional parameter, lest you end up overwriting buffer limits.


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.


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


first of all You can not return a string variable which is stored in stack you need use malloc to allocate memory dynamicaly here is given datails with the example Go https://nxtspace.blogspot.com/2018/09/return-array-of-string-and-taking-in-c.html get a proper answer


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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜