Home > Back-end >  Infinite loop at file reader in c *SOLVED*
Infinite loop at file reader in c *SOLVED*

Time:06-02

I tried to make a code that calculates the average time of execution from another process (that writes how many cores used and time took to it to finish). The thing is that it is getting stucked in the linecounter() function.

Here is a sample log.txt that I will be reading:

1 11.3484
1 10.8089
1 10.7293

And here is my code:

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

struct result{
  double *runtime;
  int *size;
}R1;

int linecounter(FILE *fileptr)
{
  int count_lines=0;
  int chr=getc(fileptr);
  while (chr != EOF)
  {
    //Count whenever new line is encountered
    if (chr == '\n') //works because I dont have any N in my txt, take care
    {
      count_lines  ;
    }
    //take next character from file.
    chr = getc(fileptr);
  }
  printf("Runtimes: %d\n",count_lines);
  rewind(fileptr);
  return count_lines;
}

int main()
{
  FILE *f;
  f=fopen("log.txt","r");
  if(f == NULL)
  {
    printf("Error! opening the file");   
    exit(1);             
  }
  
  int n=linecounter(f);

  R1.runtime=malloc(n*sizeof(double));
  R1.size=malloc(n*sizeof(int));

  int j=0,k=0;
  
  j=fscanf(f,"%d %lf",&R1.size[k],&R1.runtime[k]); //First number of cores, then runtime
  k  ;
  while(j!=EOF)
  {
    j=fscanf(f,"%d %lf",&R1.size[k],&R1.runtime[k]); //First number of cores, then runtime
    k  ;
  }
  
  double AvgRuntime=0;
  int i=0, prev_i;
  if(R1.size[i]==1)
  {
    while(R1.size[i]==1) //for 1 core
    {
      AvgRuntime =R1.runtime[i];
      i  ;
    }
    AvgRuntime=AvgRuntime/i;
    printf("Avg Runtime: %6.4f\n",AvgRuntime);
  }
  
  
  if(R1.size[i]==2)
  {
    prev_i=i;
    AvgRuntime=0;
    while(R1.size[i]==2) //for 2 core
    {
      AvgRuntime =R1.runtime[i];
      i  ;
    }
    AvgRuntime=AvgRuntime/(i-prev_i);
    printf("Avg Runtime: %6.4f\n",AvgRuntime);    
  }
  
  
  if(R1.size[i]==4)
  {
    prev_i=i;
    AvgRuntime=0;
    while(R1.size[i]==4) //for 4 core
    {
      AvgRuntime =R1.runtime[i];
      i  ;
    }
    AvgRuntime=AvgRuntime/(i-prev_i);
    printf("Avg Runtime: %6.4f\n",AvgRuntime);
  }
  
  fclose(f);
  return 0;
}

It is pretty simple, I have 3 options, to use 1 2 or 4 cores, so I calculate the average for each case and overwrite it for the next one. The problems come when trying to get how many lines were written in the file.

By adding a printf() in the linecounter function, I noticed that it never achieves the end of file. Has it some kind of solution? Thanks in advance!

CodePudding user response:

You have multiple errors in your code.

getc returns an int, not a char. If your char is unsigned by default, it is not able to hold value EOF and your comparison chr != EOF will never be true.

After you have counted the lines in the file, the file pointer is at the end of the file. You cannot read any further value from it. You must rewind it before you can scan the content.

Your format specifier %6.4f is invalid for scanf. You cannot specify precision. You can only do that when you print values.

Your format specifier %f expects a float* as argument but you provide double*. For double use %lf. You can print floats using %f but you must use %lf for scanf.

You print your calculated average using %6.4f but AvgRuntime is of type int. This also means that the calculation of the average is done using integer division. There will not be any decimals as the result is chopped off. Make AvgRuntime a `double instead.

Your compiler should tell you quite a few of these problems. If you did not get warnings, you should increase warning level significantly. If you did get these warnings, what made you just ignore all of them?

You also have logical errors. Your averaging only works if the entries in the log file are sorted. You must read all lines for core 1 first, then all lines for core 2 and then for core 4. If the file is not sorted, your calculations will fail.

Also, if you do not have entries for a core, you will do a division by zero as you don't check value of i vs. prev_i.

Finally, printf to stdout is normally line buffered. Output is not printed unless a \n is reached. You should add a \n at the end of your printf lines when you print the averages.

A fixed version (except the problems with calculating averages) could look like this:

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

struct result{
  double *runtime;
  int *size;
}R1;

int linecounter(FILE *fileptr)
{
  int count_lines=0;
  int chr=getc(fileptr);
  while (chr != EOF)
  {
//    printf("Inside the linecounter function()\n");
    //Count whenever new line is encountered
    if (chr == '\n') //works because I dont have any N in my txt, take care
    {
      count_lines  ;
    }
    //take next character from file.
    chr = getc(fileptr);
  }
  rewind (fileptr);
  return count_lines;
}

int main()
{
  FILE *f;
  f=fopen("log.txt","r");
  if(f == NULL)
  {
    printf("Error! opening the file");
    exit(1);
  }
  printf("Counting lines\n");
  int n=linecounter(f);

  R1.runtime=malloc(n*sizeof(double));
  R1.size=malloc(n*sizeof(int));

  int j=1,k=0;
  printf("Reading file\n");
  j=fscanf(f,"%d %lf",&R1.size[k],&R1.runtime[k]); //First number of cores, then runtime
  k  ;
  while(j==2)
  {
    j=fscanf(f,"%d %lf",&R1.size[k],&R1.runtime[k]); //First number of cores, then runtime
    k  ;
  }

  int i=0;
  double AvgRuntime=0.0;
  if(R1.size[i]==1)
  {
    while(R1.size[i]==1) //for 1 core
    {
      AvgRuntime =R1.runtime[i];
      i  ;
    }
  }
  AvgRuntime=AvgRuntime/i;
  printf("Avg Runtime: %6.4f\n",AvgRuntime);

  int prev_i=i;
  AvgRuntime=0.0;
  if(R1.size[i]==2)
  {
    while(R1.size[i]==2) //for 2 core
    {
      AvgRuntime =R1.runtime[i];
      i  ;
    }
  }
  AvgRuntime=AvgRuntime/(i-prev_i);
  printf("Avg Runtime: %6.4f\n",AvgRuntime);

  prev_i=i;
  AvgRuntime=0;
  if(R1.size[i]==4)
  {
    while(R1.size[i]==4) //for 4 core
    {
      AvgRuntime =R1.runtime[i];
      i  ;
    }
  }
  AvgRuntime=AvgRuntime/(i-prev_i);
  printf("Avg Runtime: %6.4f\n",AvgRuntime);

  fclose(f);
  return 0;
}

Output with your file:

Counting lines
Reading file
Avg Runtime: 10.9622
Avg Runtime:   -nan
Avg Runtime:   -nan
  • Related