从动态文本文件中读取一行

时间:2016-11-20 06:33:54

标签: c malloc dynamic-memory-allocation realloc

我正在尝试学习如何在读取文件时为很长的行动态分配内存。我在这里和网上搜索,我尝试了一些代码。

首先,这是我的第一个非动态代码:

char line[256];
file = fopen(inputFileName, "r");
// Here, of course I checked file is opened or not.
while (fgets(line, sizeof(line), file)) {
     // do some operations
}
// Closing operations

当我阅读文件时,这对我有用。但这里的行必须等于或少于255个字符。所以,我想从文件中读取300个字符长度的行。

我尝试了以下代码:

size_t maxl = 256;
//char line[256];
char *line = malloc(maxl * sizeof(char));
if(!line){
    printf("Memory not allocated!!\n");
    return -2;
}
file = fopen(inputFileName, "r");

while (fgets(line, sizeof(line), file)) {

    while(line[strlen(line) - 1] != '\n' || line[strlen(line) - 1] != '\r'){
        char *tmp = realloc (line, 2 * maxl);
        //fgets(line, sizeof(line), file);
        if (tmp) {
            line = tmp;
            maxl *= 2;
        }
        else{
            printf("Not enough memory for this line!!\n");
            return -3;
        }
    }
    // do some operations
}

我试图在这个问题中实现答案:Reading a line from file in C, dynamically

但它总是进入"没有足够的记忆"部分代码。那么,我做错了什么?

非常感谢您的回答和建议。

编辑:代码更新取决于第一条评论。

编辑2:代码始终从文件中读取相同的3个字符。

想象一下,该文件就像:

abcdabcdabcd...

line变量总是" abc"即使在重新分配操作之后。

1 个答案:

答案 0 :(得分:2)

以下是您需要做的一些更正:

  • char *tmp = realloc (line, 2 * maxl);更改为char *tmp = realloc (line, 2 * maxl * sizeof(char);(只是一个建议!)。
  • 重新分配内存后,您必须在文件中寻找完整的字符串。例如,fseek(file,0,SEEK_SET);将搜索文件inputFileName的开头。
  • sizeof(line)将始终是常量值,因为您正在计算字符指针的大小,而不是字符串长度。因此,请将while (fgets(line, sizeof(line), file)) {更改为while (fgets(line, maxl, file)) {
  • 将注释行//fgets(line, sizeof(line), file);移到if (tmp)块中,因为您需要在重新分配后再次从文件中读取字符串。
  • 表达式line[strlen(line) - 1] != '\n' || line[strlen(line) - 1] != '\r'在逻辑上是不正确的。仅当line的最后一个字符既不是'\n'也不是'\r'时,您可能只想进入循环。因此,您必须使用&&代替||

以下是修改后的代码:

size_t maxl = 256;
//char line[256];
char *line = malloc(maxl * sizeof(char));
if(!line){
    printf("Memory not allocated!!\n");
    return -2;
}
file = fopen(inputFileName, "r");

while (fgets(line, maxl, file)) {

    while(line[strlen(line) - 1] != '\n' && line[strlen(line) - 1] != '\r'){
        char *tmp = realloc (line, 2 * maxl * sizeof(char));

        fseek(file,0,SEEK_SET);          //or wherever you want to seek to
        if (tmp) {
            line = tmp;
            maxl *= 2;
            fgets(line, maxl, file);
        }
        else{
            printf("Not enough memory for this line!!\n");
            return -3;
        }
    }
    printf("%s\n",line);     //just to check
}

代码中的问题是:

  • 您只阅读了该文件中的几个字符,因为您只阅读sizeof(line)个字符数而不是maxl个字符数。
  • 您可能希望找回一些字节来再次读取整个字符串,但这取决于您。
  • 仅在重新分配成功后再次从文件中读取字符串(if(tmp))。

现在,为什么Not enough memory..正在打印?

这是因为你的循环运行了多次,重新分配的内存大小(maxl值)增加了,如256,512,1024,2048,...,65536,......

当此大小变得足够大以使编译器拒绝重新分配时,您打印了该错误字符串。如果您愿意,请尝试调试您的代码版本,或在内部maxl循环的每次迭代中打印while的值。