动态分配内存到数组并读取大文本文件

问题描述

我看过其他一些类似的问题和示例,但是我很困惑。我的目标是打开一个非常大的文本文件(大小新颖),将内存分配给一个数组,然后将文本存储到该数组中,以便将来可以做进一步的处理。

这是我当前的代码

#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,SEEK_END);
    long size = ftell(file);
    fseek(file,SEEK_SET);
    
/* Allocate memory to the array */
  char *text_array = (char*)malloc(size*sizeof(char));
    
/* Store the @R_350_4045@ion 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;
}

我期望从底部的text_array打印大量文本。取而代之的是,我得到的乱码乱七八糟的随机字符比我希望的文本小得多。我究竟做错了什么?我怀疑这与我的内存分配有关,但不知道是什么。

非常感谢您的帮助。

解决方法

无需循环调用fgets()。您知道文件有多大,只需一次调用就将整个内容读入text_array

fread(text_array,1,size,file);

但是,如果要将text_array视为字符串,则需要添加一个空终止符。因此,在调用malloc()时应加1。

另一个问题是len = sizeof(text_array) / sizeof(text_array[0])text_array是一个指针,而不是数组,因此您不能使用sizeof来获取其使用的空间量。但是您不需要这样做,因为您已经在size变量中有了空格。

无需循环打印text_array

#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,SEEK_END);
    size_t size = ftell(file);
    fseek(file,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,file);
    text_array[size] = '\0';
    printf("%s,text_array);

/* return array */
    return EXIT_SUCCESS;
}
,

这部分

\2

有问题。

如果展开循环,则表示“有点像”:

while(fgets(&text_array[count],LINELEN,file) != NULL) {
  count++;
}

因此,在每次fgets(&text_array[0],file) fgets(&text_array[1],file) fgets(&text_array[2],file) 调用之间,您只将fgets目的地缓冲区提前一个字符。如果我们假设fgets读取多个字符,则第二个fgets会覆盖第一个fgets中的数据。第三个fgets覆盖第二个数据,依此类推。

您需要使用与实际读取的fgets一样多的字符来推进缓冲区,或者使用其他读取方式,例如fgets