Reading a file character by character in C

Devan Buggay picture Devan Buggay · Jan 28, 2011 · Viewed 193.5k times · Source

I'm writing a BF interpreter in C and I've run into a problem reading files. I used to use scanf in order to read the first string, but then you couldn't have spaces or comments in your BF code.

Right now here is what I have.

char *readFile(char *fileName)
{
  FILE *file;
  char *code = malloc(1000 * sizeof(char));
  file = fopen(fileName, "r");
  do 
  {
    *code++ = (char)fgetc(file);

  } while(*code != EOF);
  return code;
}

I know the problem arises in how I'm assigning the next char in the file to the code pointer but I'm just not sure what that is.
My pointer knowledge is lacking which is the point of this exercise. The interpreter works fine, all using pointers, I'm just having a problem reading files in to it.

(I'm going to implement only reading +-><[]., into the file later, although if anyone has a good way to do it, it would be great if you'd let me know!)

Answer

dreamlax picture dreamlax · Jan 28, 2011

There are a number of things wrong with your code:

char *readFile(char *fileName)
{
    FILE *file;
    char *code = malloc(1000 * sizeof(char));
    file = fopen(fileName, "r");
    do 
    {
      *code++ = (char)fgetc(file);

    } while(*code != EOF);
    return code;
}
  1. What if the file is greater than 1,000 bytes?
  2. You are increasing code each time you read a character, and you return code back to the caller (even though it is no longer pointing at the first byte of the memory block as it was returned by malloc).
  3. You are casting the result of fgetc(file) to char. You need to check for EOF before casting the result to char.

It is important to maintain the original pointer returned by malloc so that you can free it later. If we disregard the file size, we can achieve this still with the following:

char *readFile(char *fileName)
{
    FILE *file = fopen(fileName, "r");
    char *code;
    size_t n = 0;
    int c;

    if (file == NULL)
        return NULL; //could not open file

    code = malloc(1000);

    while ((c = fgetc(file)) != EOF)
    {
        code[n++] = (char) c;
    }

    // don't forget to terminate with the null character
    code[n] = '\0';        

    return code;
}

There are various system calls that will give you the size of a file; a common one is stat.