简体   繁体   English

使用fgets从文件读取一行

[英]Reading a Line From File using fgets

What should be incredible simple has me stumped. 让我感到难过的是简单的事情。 All I am doing is writing a getLine method that should read a line into a buffer. 我正在做的是编写一个getLine方法,该方法应将一行读入缓冲区。 I allocate memory to the buffer starting at 10 bytes , then fgets into a char array. 我从10 bytes开始向缓冲区分配内存,然后将fgets放入char数组。 The idea is that I attempt this over and over, doubling the size of the buffer, until it gets the whole line. 我的想法是,我一遍又一遍地尝试,使缓冲区的大小加倍,直到获得整行。 However what I seem to be observing is that it reads a portion of the line, and then on the next attempt continues where it ran out of room on the last attempt, so it gives the last part of the line. 但是,我似乎正在观察的是,它读取了行的一部分,然后在下一次尝试时继续进行,直到上一次尝试它在空间不足的地方,所以它给出了行的最后一部分。 Any insight it to what is wrong, I expect with my realloc memory to the buffer, would be much appreciated. 任何了解它什么是错的,我跟我的预期realloc内存缓冲区,将不胜感激。

char * mygetline( char **buffer,  FILE * infile )
{
    int buffSiz = 10;
    *buffer = calloc( buffSiz, 1 );
    do
    {
        char * result = fgets(*buffer, sizeof *buffer ,infile);
        if(result == NULL)
        {
            free(buffer);
            return NULL;
        }

        if(strchr(*buffer, '\n'))
            return *buffer;
        else
        {
            char *newBuf;
            buffSiz = buffSiz*2;
            newBuf = realloc(NULL, buffSiz);
            char *buffer = newBuf;
            printf("%d", buffSiz);
            printf("%s", *buffer);
        }
    } while (1);  // INFINITE LOOP - WE ONLY GET OUT BY RETURNING FROM WITHIN

There are multiple flaws: 有多个缺陷:

  • sizeof *buffer doesn't do what you want since it's a pointer. sizeof *buffer不能执行您想要的操作,因为它是一个指针。 You should use buffSiz instead 您应该改用buffSiz

  • char *buffer = newBuf; you're assigning the new memory to a local variable, ie a variable that disappears when the else is exited 您正在将新内存分配给局部变量,即,一个变量在退出else时消失

  • you're not passing your buffer to realloc , you're always passing NULL 您没有将缓冲区传递给realloc ,而是始终传递NULL

  • you're not checking the return of realloc 您没有检查realloc的返回

As a shameless self-promotion, here's a function I posted in another answer . 作为无耻的自我推广, 这是我在另一个答案中发布的功能

That's how the file functions works. 这就是文件功能的工作方式。 You have to get the file position at the start, then reset the position every time you attempt a new read. 您必须从头开始获取文件位置,然后在每次尝试进行新的读取时重置该位置。

You can get the current position with the ftell function, and then set the position with the fseek function. 您可以使用ftell函数获取当前位置,然后使用fseek函数设置位置。


Instead of doing that (getting position and constant repositioning the file position), why not use the fact that realloc reallocates the passed in buffer and keeps the contents together with the fact that the read functions reads the next part? 而不是这样做(获取位置并恒定地重新定位文件位置),为什么不使用realloc重新分配传入的缓冲区并保留内容以及read函数读取下一部分的事实呢? In that case you need to have a pointer to where to read next, and if no newline then just reallocate and advance the pointer? 在这种情况下,您需要有一个指向下一个要读取的位置的指针,如果没有换行符,那么只需重新分配并前进该指针?

Something like this: 像这样:

char *readpos = *buffer;
size_t readsize = bufSize;

while (1)
{
    char *p = fgets(readpos, readsize, infile);
    if (!p)
        break;  /* Error */

    /* Search from the end, as there's where the newline should be */
    if (strrchr(p, '\n') != NULL)
        return *buffer;  /* Found the newline */

    /* Need to allocate more memory */
    bufSize += bufsize;
    *buffer = realloc(*buffer, bufSize);

    /* Set the pointer to next position to read into */
    readpos = *buffer + strlen(buffer);

    /* Loop takes case of trying again */
}

Note: The above code was written in the browser, not tested, and might need some tuning to make it work properly. 注意:上面的代码是在浏览器中编写的,未经测试,可能需要进行一些调整才能使其正常运行。

realloc期望将需要重新分配的缓冲区作为其第一个参数。

realloc(*buffer, buffSiz);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM