如何为C中长度未知的字符串数组分配内存
我有一个数组,比如文本,它包含由另一个函数读入的字符串。字符串的长度未知,字符串的数量也未知我应该如何将内存分配给字符串数组(而不是字符串本身,它们已经作为单独的数组存在) 我现在设置的内容似乎可以很好地读取字符串,并且似乎能够正确地完成我希望完成的后处理(我使用静态数组进行了尝试)。然而,当我试图打印文本的元素时,我得到了一个分段错误。更准确地说,当我试图打印文本的特定元素时,例如文本[3]或文本[5],我会遇到分段错误。我假设这意味着我没有正确地为文本分配内存,并且所有读取的字符串都没有正确地保存为文本 到目前为止,我已经尝试了不同的方法,比如首先分配一定数量的如何为C中长度未知的字符串数组分配内存,c,arrays,string,dynamic,realloc,C,Arrays,String,Dynamic,Realloc,我有一个数组,比如文本,它包含由另一个函数读入的字符串。字符串的长度未知,字符串的数量也未知我应该如何将内存分配给字符串数组(而不是字符串本身,它们已经作为单独的数组存在) 我现在设置的内容似乎可以很好地读取字符串,并且似乎能够正确地完成我希望完成的后处理(我使用静态数组进行了尝试)。然而,当我试图打印文本的元素时,我得到了一个分段错误。更准确地说,当我试图打印文本的特定元素时,例如文本[3]或文本[5],我会遇到分段错误。我假设这意味着我没有正确地为文本分配内存,并且所有读取的字符串都没有正确
size\u t=k,k*sizeof(char)
,然后在cnt=(k-2)的情况下重新分配更多内存(使用realloc k*sizeof(char)),其中cnt是**文本的索引
我试图搜索这个,但我发现唯一类似的问题是未知长度的字符串数量
我想自己尽可能多地找出答案,因此没有发布实际代码。然而,如果这些都没有任何意义,我会发布它
编辑:这是代码
int main(void){
char **text;
size_t k=100;
size_t cnt=1;
int ch;
size_t lng;
text=malloc(k*sizeof(char));
printf("Input:\n");
while(1) {
ch = getchar();
if (ch == EOF) {
text[cnt++]='\0';
break;
}
if (cnt == k - 2) {
k *= 2;
text = realloc(text, (k * sizeof(char))); /* I guess at least this is incorrect?*/
}
text[cnt]=readInput(ch); /* read(ch) just reads the line*/
lng=strlen(text[cnt]);
printf("%d,%d\n",lng,cnt);
cnt++;
}
text=realloc(text,cnt*sizeof(char));
print(text); /*prints all the lines*/
return 0;
}
C没有字符串。它只是有指向(通常以null结尾)字符序列的指针,并将其称为字符串
因此,只需首先分配一个指针数组:
size_t nbelem= 10; /// number of elements
char **arr = calloc(nbelem, sizeof(char*));
您确实需要calloc
,因为您确实希望清除该数组,所以那里的每个指针都是NULL
。当然,您可以测试calloc
是否成功:
if (!arr) perror("calloc failed"), exit(EXIT_FAILURE);
最后,填充数组的一些元素:
arr[0] = "hello";
arr[1] = strdup("world");
(不要忘记释放strdup
的结果和calloc
的结果)
您可以使用realloc
扩展阵列(但我不建议这样做,因为当realloc
失败时,您可能会丢失数据)。您可以简单地通过分配一个更大的副本来扩展它,在内部复制它,并重新定义指针,例如
{ size_t newnbelem = 3*nbelem/2+10;
char**oldarr = arr;
char**newarr = calloc(newnbelem, sizeof(char*));
if (!newarr) perror("bigger calloc"), exit(EXIT_FAILURE);
memcpy (newarr, oldarr, sizeof(char*)*nbelem);
free (oldarr);
arr = newarr;
}
不要忘记在Linux上使用gcc-Wall-g
编译(改进代码直到没有警告),并学习如何使用gdb
调试器和valgrind
内存泄漏检测器。在c中,不能直接分配字符串数组。您应该使用指向char数组的指针将其用作字符串数组。所以使用
char* strarr[length];
并对字符数组进行注释
您可以采取类似的方法:
通过调用malloc()
跟踪输入的大小
当您需要增加缓冲区大小时,调用realloc(ptr,size)
简而言之,除非您知道要分配多少内存,否则无法直接分配内存
但是,有多种方法可以确定需要分配多少
这有两个方面。一是知道需要处理多少字符串。必须有某种明确的认识方式;要么给你一个计数,要么有一个特定的指针值(通常为空),告诉你何时到达终点
要将指针数组分配给指针,最简单的方法可能是计算所需指针的数量,然后分配空间。假设以空结尾的列表:
size_t i;
for (i = 0; list[i] != NULL; i++)
;
char **space = malloc(i * sizeof(*space));
...error check allocation...
对于每个字符串,可以使用strdup()
;假设字符串格式良好,因此以null结尾。或者,您可以编写自己的strdup()
模拟代码
另一种方法是扫描指针列表一次,但多次使用malloc()
和realloc()
。总体而言,这可能较慢
如果您不能可靠地判断字符串列表何时结束或字符串本身何时结束,那么您就被套住了。完全彻底冲洗。分段故障是一个特殊问题。发布您的代码将使我们能够准确地确定是什么导致了您的分段错误,而不是试图从您含糊不清的描述中想象是什么导致了它。换句话说,阅读你做错的具体事情可能比阅读关于如何做每件事的冗长回复更有帮助。在Linux上,使用gcc-Wall-g
编译,并学习使用gdb
调试器和valgrind
内存泄漏检测器。^我一直在尝试这样做,但它并没有说什么对我有帮助的。在segfault在reader.c:47在reader.c:116.c:47在main()中用gdb回溯到2 0x000000000040087f(text=0x602010),但是,嗯,这并没有真正帮助我。您对read
的调用是非常错误的,因为read(2)
是一个带有3个参数的系统调用。对不起。我只是给他们起了个名字,因为原来的名字不是英文的。read(ch)->readinput(ch)或其他东西。听起来就像海报上给出的作为尝试示例的方法。如果length
是同一函数或块中的一个变量,这可能不起作用。请注意,strdup不是标准C,因此不能保证可移植。理论上同意。您是否知道许多实现提供了良好的calloc
,但缺少strdup
?大多数底层嵌入式系统(“一致性独立实现”)可能没有strdup,因为它们试图将标准库的实现降到最低。另一方面,他们甚至可能不支持整个标准库(而且他们不需要)。我必须试着让它工作,至少看起来它应该能起作用。不熟悉strdup,似乎很有用。谢谢你的建议@Lundin:IMHO,符合独立式植入术
for (i = 0; list[i] != NULL; i++)
{
space[i] = strdup(list[i]);
...error check allocation...
}