C语言 如何从函数返回字符串数组

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4085372/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 06:54:10  来源:igfitidea点击:

how to return a string array from a function

c

提问by friends

char * myFunction () {

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

} 

void main () {

    char *str;
    str = myFunction();

}

error:return from incompatible pointer type

错误:从不兼容的指针类型返回

thanks

谢谢

回答by Diego Sevilla

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:

C 中的字符串数组可以与char**或 一起使用char*[]。但是,您不能像在函数中一样返回存储在堆栈中的值。如果要返回字符串数组,则必须动态保留它:

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:

然后, main 可以像这样获取字符串数组:

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

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

编辑:由于我们分配了sub_str,我们现在返回一个可以在 main 中访问的内存地址

回答by Thomas E

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.

对于刚入门的程序员来说,“堆栈”或“堆”的概念可能有点令人困惑,特别是如果您已经开始使用 Ruby、Java、Python 等高级语言进行编程。

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?

为了更好地理解这一切,您可能还想阅读以下内容:堆栈和堆是什么以及在哪里?

回答by Chris Florin

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.

1) 该函数的目的是创建并返回一个字符串数组。2) 该函数对字符串数组执行一些操作。

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

如果 #1 为真,则需要多次 malloc 调用才能完成此工作(实际上只需要两次即可完成,但为了简单起见,我将使用多次)。

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.

如果#2 为真,那么您要分配字符串、处理字符串并清理它们。您应该使用上面的两个函数来分配/取消分配您的字符串,然后使用第三个函数来处理它们。

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

回答by Armen Tsirunyan

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

原因:
您需要返回类型为 char(*)[20]. 但即使在这种情况下,您也不希望从函数返回指向本地对象的指针。
做:
使用malloc分配sub_str,并返回char**

回答by Hamidreza Soleimani

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

正如其他人正确所说的那样,您应该使用动态内存分配malloc来将数组存储在内部heap并返回指向其第一个元素的指针。

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

此外,我发现编写一个简单的array of string实现很有用,该实现具有用于数据操作的最小 API。

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

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.

它创建了一个 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;
}

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.

请注意,它只是一个没有错误检查的简单实现。

回答by Ali

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

回答by DevSolar

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 notadvise using malloc()withinthe function.

但是,我建议malloc()函数使用。

Good practice is that, whoever allocatesmemory, also deallocatesit (and handles the error condition if malloc()returns NULL).

好的做法是,无论谁分配内存,都会释放它(并在malloc()返回 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.

由于您myFunction()无法控制它返回后分配的内存,因此让调用者提供存储结果的内存,并将指针传递给该内存。

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.

这样,您的函数的调用者可以解除分配或重新使用内存(例如,用于后续调用myFunction()),但他认为合适。

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

但是要小心,要么同意此类调用的固定大小(通过全局常量),要么将最大大小作为附加参数传递,以免最终覆盖缓冲区限制。

回答by omyoo7

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.htmlget a proper answer

首先,您不能返回存储在堆栈中的字符串变量,您需要使用 malloc 动态分配内存,这里给出了 datails 示例 Go https://nxtspace.blogspot.com/2018/09/return-array-of -string-and-taking-in-c.html得到正确答案

回答by Sid

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.

您可以使用 static 代替 malloc。这是你的选择。