我在主函数
之外有这段代码mystr * arrstr[] = {
"rec",
"cent",
"ece",
"ce",
"recent",
"nt",
};
我修改了它,以便它可以从文本文件中读取值。为此,我修改了这个工作代码,从文件读取到名为string的数组。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
int i=0,j;
char* string[100];
char line[100];
FILE *file;
file = fopen("patt", "r");
while(fgets(line, sizeof(line), file)!=NULL) {
printf("%s", line);
string[i] = (char*)malloc(strlen(line));
strcpy(string[i], line);
i++;
}
fclose(file);
return 0;
}
所以最终的代码现在是这样的。
..
..
char *getpatterns(const char *filename) {
int i=0;
char* string[100];
char line[100];
FILE *file;
file = fopen(filename, "r");
while(fgets(line, sizeof(line), file)!=NULL) {
//printf("%s", line);
string[i] = (char*)malloc(strlen(line));
strcpy(string[i], line);
i++;
}
fclose(file);
return(string);
}
mystr * arrstr[] = getpatterns("patt");/*{
"rec",
"cent",
"ece",
"ce",
"recent",
"nt",
};*/
..
..
但我得到这样的错误。
example1.c: In function ‘getpatterns’:
example1.c:43:2: warning: return from incompatible pointer type [enabled by default]
example1.c:43:2: warning: function returns address of local variable [enabled by default]
example1.c: At top level:
example1.c:45:1: error: invalid initializer
make: *** [example1.o] Error 1
这里第45行是这一行
mystr * arrstr[] = getpatterns("patt");/*{
请建议纠正措施。
答案 0 :(得分:2)
第一个警告是您尝试将char **
作为char *
返回(这不是一个好主意),并且您正在返回一个局部变量,该函数在函数返回时被释放(也不是一个好主意)。最后一个是告诉你不能在C中的全局变量初始化器中使用函数调用(你可以在C ++中做一些,但我不相信你能做到这一点。)
修复它需要重新思考。您需要该函数来返回已分配的内存,或者您需要将内存传递给该函数。而且你必须改变全局变量的类型。而且你需要知道数组中有多少条目,不知何故。
mystr **arrstr = 0; // Either
mystr *arrstr[100]; // Or
总的来说,我可能会选择内存分配和“或者”声明:
mystr **arrstr = 0;
char **getpatterns(const char *file)
{
char **array = 0;
...code similar to yours that allocates entries in the array...
...include space for a null pointer to mark the end of the list of strings...
return(array);
}
int main(void)
{
arrstr = getpatterns("patt");
...
}
(另一个“作弊”机制会在static char *string[100];
中使用getpatterns()
;您仍然需要修复返回类型和全局变量的类型。)
我试过这些,但错误没有解决:......
如果没有你的代码,不可能确切地说出错误。但是,下面的代码对我有用。源代码位于文件gp.c
中;源代码打印自己,并释放内存。在valgrind
下查看了健康清单。
请注意,您的原始代码没有为其复制的字符串分配足够的空间(因为您保留了fgets()
读取的换行符 - 但您至少使用的是fgets()
而不是{{1} },这非常重要)。此代码使用gets()
- 它可以使用memmove()
,因为保证不会重叠,但memcpy()
始终有效,memmove()
在源数据重叠时不一定有效目标数据。它知道字符串有多长,因此复制函数不需要测试被复制的字符是否为NUL memcpy()
。代码仔细确保指针列表末尾有一个空指针;这就是你何时到达字符串列表末尾的方式。当'\0'
是空文件时,代码也有效。
使用三个gp.c
,num_xxx
和max_xxx
项的算法是处理增量分配的典型方法。它通常略微过度分配;如果您担心空间,可以在循环结束时使用xxx
来释放额外的空间。 strings = realloc(strings, (num_strings+1) * sizeof(*strings)); max_strings = num_strings + 1;
是允许空指针。通过每次分配大小加倍分配的大小,与每次递增1相比,可以避免二次行为。
请注意,如果+ 1
失败,代码会小心避免丢失已分配的空间。你应该'永远''使用realloc()
来避免失去你的指针。代码小心地避免了解除引用空指针,并在内存不足时停止读取。
space = realloc(space, new_size);