cfileungetc

fefo is not checking EOF during its last iteration in while loop?


I have a code which uses ungetc,and fefo function but i noticed that fefo is not checking for EOF below is my code

 #include<stdio.h>
 int main ()
{
 FILE *fp;
  int c;
 char buffer [200];

 fp = fopen("", "r");
 if( fp == NULL ) 
 {
  perror("Error in opening file");
  return(-1);
  }
 while(!feof(fp)) 
 {
   c = getc (fp);
  if(c==EOF) // **why i need to check for EOF if fefo does?**
   break;
   /* replace ! with + */
   if( c == '!' ) 
   {
     ungetc ('@', fp);
   }
   else 
   {
     ungetc(c, fp);
   }
   fgets(buffer, 255, fp);
   fputs(buffer, stdout);
  }
  return(0);
}

input is :

   hello !world

outout if EOF is not chcked explicitly

     hello @world
     hello @world // Bad its repeat

output when EOF is checked explicitly

   hello @world // Good

Why do i need to check for EOF and break when fefo does ?


Solution

  • If I understand correctly, you are reading from a file into a buffer and substituting '@' for '!' when it occurs. Each of the comments above have provided you the reason, and a link to, why reading characters in a while loop and testing with feof is bad.

    Putting the comments together, and cleaning up the logic a bit, the following shows a standard way to accomplish this task. I have left your code commented inline to make the changes more apparent. Take a look and drop a comment if you have questions.:

    #include <stdio.h>
    
    #define MAXC 255
    
    int main (int argc, char **argv) {
    
        FILE *fp = NULL;
        int c;
        char input[MAXC];
        char buffer[MAXC];
        size_t idx = 0;
    
        if (argc < 2) {
            fprintf (stderr, "\n error: insufficient input, filename required.\n");
            return 1;
        }
    
        if (!(fp = fopen (argv[1], "r")))  {
            fprintf (stderr, "\n error: file open failed '%s' (%p)\n", argv[1], fp);
            return 1;
        }
    
        while ( (c = getc (fp)) != EOF ) 
        {
            input[idx] = c;
    
            if (c == '!') c = '@';
            buffer[idx++] = c;
    
            if (idx == MAXC) {  /* normally realloc if buffer is allocated */
                printf (" warning: maximum size of buffer reached  (%d char)\n", MAXC);
                break;
            }
            // {
            //     ungetc ('@', fp);
            // } else {
            //     ungetc (c, fp);
            // }
            // fgets (buffer, 255, fp);
            // fputs (buffer, stdout);
        }
        fclose (fp);
    
        input[idx] = buffer[idx] = 0;
        // fputs (buffer, stdout);
    
        printf ("\n characters in input & buffer are:\n\n");
        printf ("\n  original : %s\n  modified : %s\n\n", input, buffer);
    
        return 0;
    }
    

    Output

    $ ./bin/whyfeofbad dat/qbfox2.txt
    
     characters in input & buffer are:
    
    
      original : The quick! brown fox jumps over the lazy! dog. He never says "Hi!", he just saunters up and jumps!
    
      modified : The quick@ brown fox jumps over the lazy@ dog. He never says "Hi@", he just saunters up and jumps@