ccc ccc - 16 days ago 5
C Question

Read text from a file and realloc when needed

I want to read text from a text file line by line and do some processing on these lines. I can do all processing, but I can't do grow memory with malloc-realloc. I gave limited memory first, if my text file's lines characters are in this limit everything is ok. If I use large files like 10,000 chars per line it only reads until my limit. I don't exactly understand how to use

realloc()
. what can i do about this code?

void stat(char* fileptr)
{

FILE *fp;
char *linebuffer;
int line=0;
int sum=0;
int max=0;
int min=0;
int maxlinelen=512;
int i=0,j=0;
int maxlen=512;
int curlinelen[maxlen];

linebuffer=(char*) malloc(maxlinelen * sizeof(char));
if(linebuffer==NULL)
{
printf("Error occurred allocating memory for linebuffer");
exit(1);
}


if((fp=fopen(fileptr,"r"))!=NULL)
{
while((fgets(linebuffer,maxlinelen,fp))!=NULL)
{
if(strlen(linebuffer)==maxlinelen)
{
maxlinelen*=2;
linebuffer=realloc(linebuffer,maxlinelen * sizeof(char));
if(linebuffer==NULL)
{
printf("Error occurred reallocating space for linebuffer");
exit(1);
}
}
line++;

sum=sum+strlen(linebuffer);
curlinelen[i]=strlen(linebuffer);
i++;

}
}
min=curlinelen[0];
max=curlinelen[0];
for(j=0;j<line;j++)
{
if(curlinelen[j]<min)
{
min=curlinelen[j];
}
if(curlinelen[j]>max)
{
max=curlinelen[j];
}
}


printf("No. of lines =%d\n",line);
printf("Maximum line length =%d\n",max);
printf("Minimum line length =%d\n",min);
printf("Average line length =%8.2f\n",(float)sum/(float)line);

fclose(fp);
}

Answer
fgets(linebuffer,maxlinelen,fp)

reads and stores at most maxlinelen - 1 characters in linebuffer and 0-terminates it. Thus

if(strlen(linebuffer)==maxlinelen)

is never satisfied, strlen(linebuffer) can be at most maxlinelen - 1. Change the condition, and you will see that maxlinelen increases if the file contains long lines (unless realloc fails).

Your current code will however count the partial line read in as an entire line then, and read the next chunk of the line as a new line. To grow the buffer until the entire line fits in, you must continue reading from the file before collecting the line length and incrementing the line count.

while((fgets(linebuffer,maxlinelen,fp))!=NULL)
  {
  while(strlen(linebuffer) == maxlinelen-1)
  {
    maxlinelen*=2;
    linebuffer=realloc(linebuffer,maxlinelen * sizeof(char));
    if(linebuffer==NULL)
    {
        printf("Error occurred reallocating space for linebuffer");
        exit(1);
    }
    fgets(linebuffer + (maxlinelen/2 - 1), maxlinelen/2 + 1, fp);
  }

would be a (rather inefficient, due to the strlen calls) way to do that.