How to return an array of strings 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

thank

+8
source share
7 answers

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 an array of strings, you need to reserve it dynamically:

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 a string array as follows:

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

For beginner programmers, the concept of a “stack” or “heap” can be a bit confusing, especially if you started programming in a higher level language such as Ruby, Java, Python, etc.

Consider:

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

, , .

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

, ​​ .

, , , - :

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

:

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

, , . , ! ( ).

, : ?

+5

:
char(*)[20]. .
Do:
malloc sub_str char**.

+2

, , . , char *, char **.

, , , :

1) . 2) () .

# 1 , malloc ( , ).

, , :

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

, , , .

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

- , , , . .

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

, . .

# 2 , , . , / , , -.

void processStrings ( char ** strArray, int numberOfStrings, int strLength );
+1

, malloc heap .

array of string, API .

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

:

4 , 4 . , 4 .

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

:

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

, .

+1

, char .

malloc() .

, , , ( , malloc() NULL).

myFunction() , .

, (, myFunction()), .

However, be careful to either agree on a fixed size for such calls (via a global constant), or pass the maximum size as an additional parameter so that you do not limit the limits of buffer overwriting.

0
source
char *f()
{   
    static char str[10][20];

    // ......

    return (char *)str;
}

int main()
{

    char *str;
    str = f();

    printf( str, "%s\n" );

    return 0;
}

You can use static instead of malloc. This is your choice.

-3
source

Source: https://habr.com/ru/post/1772812/


All Articles