0

我在主函数之外有这段代码

mystr * arrstr[] = {
    "rec",
    "cent",
    "ece",
    "ce",
    "recent",
    "nt",
};

我对其进行了修改,以便它可以从文本文件中读取值。为此,我修改了此工作代码以将文件中的行读取到名为字符串的数组中。

#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");/*{

请提出纠正措施。

4

1 回答 1

2

第一个警告是您试图将 achar **作为 a返回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];in getpatterns();您仍然必须修复返回类型和全局变量的类型。)


我尝试了这些,但错误没有解决:...

如果没有您的代码,就不可能准确地判断出了什么问题。但是,下面的代码对我有用。源代码在一个文件中gp.c;源代码打印自己,并释放内存。valgrind用干净的健康单检查。

请注意,您的原始代码没有为它正在复制的字符串分配足够的空间(因为您保留了读取的换行符fgets()- 但您至少使用了fgets()而不是gets(),这非常重要)。此代码使用memmove()- 它可以使用memcpy(),因为保证没有重叠,但当源数据与目标数据重叠时,它memmove()总是有效且memcpy()不一定有效。它知道字符串有多长,因此复制函数不需要测试被复制的字符是否为 NUL '\0'。代码仔细确保指针列表末尾有一个空指针;这就是您知道何时到达字符串列表末尾的方式。该代码也适用gp.c于空文件。

该算法使用三个项目num_xxxmax_xxxxxx是处理增量分配的典型方法。它通常会略微过度分配;如果您担心空间,可以strings = realloc(strings, (num_strings+1) * sizeof(*strings)); max_strings = num_strings + 1;在循环结束时使用以释放额外空间。这+ 1是为了允许空指针。通过将每次分配的大小大致翻倍,与每次增加一相比,您可以避免二次行为。

还要注意,如果realloc()失败,代码会小心地避免丢失分配的空间。您应该“从不”使用space = realloc(space, new_size);以避免丢失指针。代码小心地避免取消引用空指针,并在内存不足时停止读取。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

extern char **getpatterns(const char *filename);

char **getpatterns(const char *filename)
{
    size_t num_strings = 0;
    size_t max_strings = 0;
    char **strings = 0;
    FILE *file = fopen(filename, "r"); 

    if (file != 0)
    {
        char line[4096];
        while (fgets(line, sizeof(line), file) != NULL)
        {
            if (max_strings == 0 || num_strings >= max_strings - 1)
            {
                size_t   new_num = max_strings * 2 + 2;
                char   **new_space = realloc(strings, new_num * sizeof(*new_space));
                if (new_space == 0)
                    break;
                strings = new_space;
                max_strings = new_num;
            }
            size_t len = strlen(line);  /* Includes '\n' at end */
            strings[num_strings] = (char*)malloc(len);
            memmove(strings[num_strings], line, len - 1);
            strings[num_strings][len] = '\0';
            strings[++num_strings] = 0; /* Null terminate list of strings */
        }
        fclose(file);
    }
    return(strings);
}

int main(void)
{
    char **data = getpatterns("gp.c");
    char **argp = data;

    if (argp != 0)
    {
        /* Print data */
        while (*argp != 0)
            puts(*argp++);

        /* Free space */
        argp = data;
        while (*argp != 0)
            free(*argp++);
        free(data);
    }

    return(0);
}
于 2013-01-20T18:37:20.467 回答