Search code examples
arrayscmemorydynamic

Dynamically allocating memory to an array and reading a large text file


I've had a look at some other similar questions and examples but I'm stumped. My goal is to open a very large text file (novel sized), allocate memory to an array, and then store the text into that array so I'm able to do further processing in the future.

This is my current code:

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

#define LINELEN 74

int main(void) {

FILE *file;
char filename[] = "large.txt";
int count = 0, i = 0, len;

/* Open the file */
  file = fopen(filename, "r");
  if (file == NULL) {
      printf("Cannot open file");
      return -1;
  }
    
/* Get size of file for memory allocation */
    fseek(file, 0, SEEK_END);
    long size = ftell(file);
    fseek(file, 0, SEEK_SET);
    
/* Allocate memory to the array */
  char *text_array = (char*)malloc(size*sizeof(char));
    
/* Store the information into the array */
    while(fgets(&text_array[count], LINELEN, file) != NULL) {
      count++;
      }

  len = sizeof(text_array) / sizeof(text_array[0]);

  while(i<len) {
    /* printf("%s", text_array); */
    i++;
  }
  printf("%s", text_array);

/* return array */
    return EXIT_SUCCESS;
}

I was expecting to have a large body of text printed from text_array at the bottom. Instead I get a garbled mess of random characters much smaller than the body of text I was hoping for. What am I doing wrong? I suspect it has something to do with my memory allocation but don't know what.

Any help is much appreciated.


Solution

  • There's no need to call fgets() in a loop. You know how big the file is, just read the entire thing into text_array with one call:

    fread(text_array, 1, size, file);
    

    However, if you want to treat text_array as a string, you need to add a null terminator. So you should add 1 when calling malloc().

    Another problem is len = sizeof(text_array) / sizeof(text_array[0]). text_array is a pointer, not an array, so you can't use sizeof to get the amount of space it uses. But you don't need to do that, since you already have the space in the size variable.

    There's no need to print text_array in a loop.

    #include <stdio.h>
    #include <stdlib.h>
    
    #define LINELEN 74
    
    int main(void) {
    
        FILE *file;
        char filename[] = "large.txt";
        int count = 0, i = 0, len;
    
    /* Open the file */
        file = fopen(filename, "r");
        if (file == NULL) {
            printf("Cannot open file");
            return -1;
        }
        
    /* Get size of file for memory allocation */
        fseek(file, 0, SEEK_END);
        size_t size = ftell(file);
        fseek(file, 0, SEEK_SET);
        
    /* Allocate memory to the array */
        char *text_array = (char*)malloc(size*sizeof(char) + 1);
        
    /* Store the information into the array */
        fread(text_array, 1, size, file);
        text_array[size] = '\0';
        printf("%s", text_array);
    
    /* return array */
        return EXIT_SUCCESS;
    }