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

Reading a line from text file dynamically

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

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

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

但它总是输入"Not enough memory"部分代码。那么,我做错了什么?

感谢您的回答和建议。


编辑:代码根据第一条评论更新。


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

假设文件是​​这样的:

abcdabcdabcd...

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

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

  • 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、.. .

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