开发者

ReadLine function for a file

I want the same functionality of readline but for a file. I don't want to pass开发者_运维知识库 a buffer and size. I'd like a method to malloc the right amount of space


With fgetc, you can read a character at a time from a file.

Thus, you can create a function that reads a file line by line by calling fgetc several times. If a line is over, fgetc reads a \n. If the file is over, it reads EOF.

Now, you do the following: You create a char line[1024] (resp. a char* that is created via malloc) (or any other size) at the beginning, and fill it either one of the following is the case:

  • fgetc gets \n: This means, that the current line is over, and you are done with this line.
  • fgetc gets EOF: This means, that the whole file is over and you are completely done.
  • fgetc gets anything else and there is still space available in line: Then you simply copy the char read into the appropriate position in line.
  • fgetc gets anything else and line is already completely filled: Then, you realloc new memory for line and grow the current line (to be more specific, it is practical to double the size of line in this step).

So basically you need to inform yourself about fgetc and realloc and combine these two functions (and some auxiliary functions) to get what you want.


Here's a solution I've used before. It will read a line from a text file up to and including the newline. It reads into a local, fixed-sized buffer first, and then appends that buffer to the result.

Reading ends when we see a newline or EOF or hit an error on input.

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

#define PAGE_SIZE ...  // some size large enough to handle most cases

char *getLine(FILE *stream)
{
  char *res = NULL; 
  char inbuf[PAGE_SIZE];
  size_t len = 0;

  /**
   * We want to use strcpy the first time through the loop,
   * then strcat afterward.  Using a function pointer means
   * we don't have to execute a test each time through the 
   * loop.  For a sane text file where individual lines aren't
   * more than a few dozen characters long, this really doesn't
   * buy us anything over an if-else statement; I just think it's a cool trick.
   *
   * For C99, the prototype should be
   *
   *    char *(*f)(char * restrict, const char * restrict)
   */
  char *(*f)(char *, const char *) = strcpy;

  while (fgets(inbuf, sizeof inbuf, stream))
  {
    char *tmp = realloc(res, len + strlen(inbuf) + 1);
    if (tmp)
    {
      res = tmp;
      f(res, inbuf);
      f = strcat;
      len += strlen(inbuf) + 1;
    }
    if (strchr(inbuf, '\n'))
      break;
  }
  if (feof(stream))
    // hit EOF
  else
    // error on read; how you deal with it is up to you.
  return res;
}

Note that if we hit EOF or error on the initial read, the function will return NULL.

You will need to free each line when you're done with it.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜