从静态数组赋值到文件中的数组

时间:2013-01-20 18:16:50

标签: c file-handling

我在主函数

之外有这段代码
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");/*{

请建议纠正措施。

1 个答案:

答案 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.cnum_xxxmax_xxx项的算法是处理增量分配的典型方法。它通常略微过度分配;如果您担心空间,可以在循环结束时使用xxx来释放额外的空间。 strings = realloc(strings, (num_strings+1) * sizeof(*strings)); max_strings = num_strings + 1;是允许空指针。通过每次分配大小加倍分配的大小,与每次递增1相比,可以避免二次行为。

请注意,如果+ 1失败,代码会小心避免丢失已分配的空间。你应该'永远''使用realloc()来避免失去你的指针。代码小心地避免了解除引用空指针,并在内存不足时停止读取。

space = realloc(space, new_size);