0

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 ?

user4950013
  • 137
  • 5
  • 6
    possible duplicate of [Why is “while ( !feof (file) )” always wrong?](http://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong) – Dmitri Aug 16 '15 at 06:38
  • http://faq.cprogramming.com/cgi-bin/smartfaq.cgi?id=1043284351&answer=1046476070 find you answer in any of two provided links in comments. – ameyCU Aug 16 '15 at 06:40
  • @Dmitri i have give my code with all the possible ans how this be dup with your above link – user4950013 Aug 16 '15 at 06:41
  • It explains why `feof()` alone isn't enough to properly watch for end-of-file, which seems to be what you're asking. `feof()` only indicates end-of-file after a read has already failed due to end-of-file. – Dmitri Aug 16 '15 at 06:45
  • @user4950013 In the above links it has briefly described the problem with `feof` to control loop it is completely wrong. Take a look there and if have a doubt you can ask. – ameyCU Aug 16 '15 at 06:46
  • So basically, you need to check the return from `getc()` and `fgets()` to see whether they've failed (probably due to end-of-file). If you want to, you can use `feof()` to verify that they hit end-of-file rather than failing for some other reason... but don't use it as the primary means of detecting end of file. – Dmitri Aug 16 '15 at 07:02
  • Keeping `while` as infinite loop and inside `if(feof(fp)) break;` can used . – ameyCU Aug 16 '15 at 07:03
  • @ameyCU That's no better... it still won't break the loop until after a failed read. `feof()` doesn't indicate whether there's more to read, it indicates that you've *already* tried to read too much. – Dmitri Aug 16 '15 at 07:08
  • @Dmitri Well then `fgets` or `fscanf` are the safest for this task. – ameyCU Aug 16 '15 at 07:10

1 Answers1

2

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@
David C. Rankin
  • 81,885
  • 6
  • 58
  • 85