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: %sn", 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 -string-and-taking-in-c.html得到一个正确的答案
char *f() { static char str[10][20]; // ...... return (char *)str; } int main() { char *str; str = f(); printf( "%sn", str ); return 0; }
您可以使用static而不是malloc。 这是你的选择。
需要了解更多c/c++开发分享如何从函数返回一个字符串数组,也可以关注C/ C++技术分享栏目---计算机技术网(www.ctvol.com)!
以上就是c/c++开发分享如何从函数返回一个字符串数组相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/980342.html