如何从函数返回一个字符串数组

char * myFunction () { char sub_str[10][20]; return sub_str; } void main () { char *str; str = myFunction(); } 

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

谢谢

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

 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; 

然后,main可以像这样得到字符串数组:

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

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

考虑:

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

只要记住在完成后释放已分配的内存,因为没有人会为你做这件事。 这适用于所有指针,而不仅仅是指向指针的指针! (我认为)。

为了更好地理解这一切,您可能还想阅读: 堆栈和堆的内容和位置是什么?

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

编译器错误的原因很简单,但不能解决您真正想要做的事情。 您声明该函数返回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; } 

正如其他人所指出的那样,最佳实践是分配也可以解除分配。 因此需要清理function。

 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为true,那么您希望分配字符串,处理字符串并清理它们。 你应该使用上面的两个函数来分配/释放你的字符串,然后使用第三个函数对它们做任何事情。

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

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

此外,我发现编写一个简单array of string实现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; } 

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

正如其他人所说,你不能将一个本地char数组返回给调用者,并且必须为此使用堆内存。

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

好的做法是,无论谁分配内存,也可以解除分配它(如果malloc()返回NULL,则处理错误条件)。

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

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

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

我使用该函数将字符串拆分为字符串数组

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

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

 char *f() { static char str[10][20]; // ...... return (char *)str; } int main() { char *str; str = f(); printf( "%s\n", str ); return 0; } 

您可以使用static而不是malloc。 这是你的选择。