2
#include <stdio.h>
  int main() {
        FILE *fp1, *fp2, *fp3;
        int n, i, num, flag = 0;
        /* open files to write even, odd seperately */
        fp1 = fopen("data.txt", "r");
        fp2 = fopen("even.txt", "w");
        fp3 = fopen("odd.txt", "w");

        fprintf(fp2, "Even Numbers:\n");
        fprintf(fp3, "Odd Numbers:\n");

        /* print even, odd and prime numbers in separate files */
        while (!feof(fp1)) {
                fscanf(fp1, "%d", &num);
                if (num % 2 == 0) {
                        fprintf(fp2, "%d ", num);
                } else {
                        if (num > 1) {
                                for (i = 2; i < num; i++) {
                                        if (num % i == 0) {
                                                flag = 1;
                                                break;
                                        }
                                }
                        }
                        fprintf(fp3, "%d ", num);
                        flag = 0;
                }
        }
        fprintf(fp2, "\n");
        fprintf(fp3, "\n");

        fclose(fp1);
        fclose(fp2);
        fclose(fp3);
        return 0;
  }

I want to use EOF instead of feof. I have tried !EOF = fp1 but it doesn't work and gives an error. I just want to replace feof with EOF. can anyone indicate what is the problem in my code?

Alexis
  • 41
  • 4
  • Likely related: https://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong?rq=1 – Christian Gibbons Jan 31 '18 at 19:45
  • You should check the return status of `fscanf` instead. If the end of file is reached, `fscanf` will return `EOF`. See the **RETURN VALUE** of [man fscanf](https://linux.die.net/man/3/scanf) – Pablo Jan 31 '18 at 19:51
  • 1
    `EOF` and `feof()` are entirely different things. `feof()` is a _function_ which checks to see if the end-of-file indicator has been set, and `EOF` is a _macro_ for the value returned by some functions when end-of-file has been reached. – ad absurdum Jan 31 '18 at 19:51
  • can you please tell me how do I replace with EOF? I am still not getting my answer – Alexis Jan 31 '18 at 19:51
  • 1
    See [`while (!feof(file))` is always wrong](https://stackoverflow.com/questions/5431941/) because it is, and your code runs into the problems that arise from abusing `feof()`. – Jonathan Leffler Jan 31 '18 at 19:51
  • 1
    Replace `while (!feof(fp1)) { fscanf(fp1, "%d", &num); … }` with `while (fscanf(fp1, "%d", &num) == 1) { … }`. Note that this behaves sanely even when you type a word instead of a number; it stops processing the (erroneous) data. It doesn't use EOF; comparing with EOF would not spot the problems with words instead of numbers. – Jonathan Leffler Jan 31 '18 at 19:52
  • EOF is an integer value returned by functions like `fgetc()` and `getchar()`. You're not using any of those functions, so you won't see one. – Lee Daniel Crocker Jan 31 '18 at 19:56
  • Your code doesn't seem to be treating prime numbers differently from odd numbers (yet — but the comments say you should/will be doing so, eventually). If you do end up treating primes differently, don't forget that 2 is both even and prime. – Jonathan Leffler Jan 31 '18 at 20:00

2 Answers2

3

fscanf returns EOF when the end-of-file is reached:

man fscanf

#include <stdio.h>

int scanf(const char *format, ...);
int fscanf(FILE *stream, const char *format, ...);
int sscanf(const char *str, const char *format, ...);

[...]

The scanf() function reads input from the standard input stream stdin, fscanf() reads input from the stream pointer stream, and sscanf() reads its input from the character string pointed to by str.

[...]

RETURN VALUE

On success, these functions return the number of input items successfully matched and assigned; this can be fewer than provided for, or even zero, in the event of an early matching failure.

The value EOF is returned if the end of input is reached before either the first successful conversion or a matching failure occurs. EOF is also returned if a read error occurs, in which case the error indicator for the stream (see ferror(3)) is set, and errno is set to indicate the error.

A solution would be to read save the return value of fscanf in a int variable and check it agains 0 and EOF, like this:

If you want to keep using fscanf:

int ret;
while((ret = fscanf(fp1, "%d, &num)) != EOF)
{
    if(ret == 0)
    {
        // fscanf failed to convert the input
        // let it consume a charatcer and try again.
        getc(fp1);
        continue;
    }

    if(num % 2 == 0)
        ...
}

edit

Avoid using feof to control looping on a file like this while(!feof(fp), see Why is “while ( !feof (file) )” always wrong? for more information about that.


edit 2

This was my original idea, but as Jonathan Leffler pointed out in the comments:

Jonathan Leffler wrote:

Your first solution demands a single number per line, which the code in the question does not

He's right, I didn't see that.

me from the past

One option would be to read the input line by line using fgets and then use sscanf to parse the line:

char buffer[1024];

while(fgets(buffer, sizeof buffer, fp1))
{
    if(sscanf(buffer, "%d", &num) != 1)
    {
        fprintf(stderr, "Could not read an integer, ignoring line\n");
        continue;
    }

    if (num % 2 == 0)
        ...
}
Pablo
  • 13,271
  • 4
  • 39
  • 59
0

Your condition for the while loop should be the fscanf() statement itself. EOF is always an integer. See the manual page for fscanf():

Return Value

The fscanf() function returns the number of fields that it successfully converted and assigned. The return value does not include fields that the fscanf() function read but did not assign.

The return value is EOF if an input failure occurs before any conversion, or the number of input items assigned if successful.

And, like everyone else I will refer you to Why is while ( !feof (file) ) always wrong?. This is essential reading on Stack Overflow for new C programmers.

#include <stdio.h>

int main(void) {
    FILE *fp1, *fp2, *fp3;
    int n, i, num, flag = 0, ret;

    /* fopen files */

    while ((ret = fscanf(fp1, "%d", &num)) != EOF) {
        if (ret == 0) {
            getc(fp1);
            continue;
        }
        if (num % 2 == 0) {
            fprintf(fp2, "%d ", num);
        }
        /* rest of the loop here */
    }

    /* fclose files */
}

If fscanf() fails to read a character, but does not return EOF, it can often solve things to getc(), to advance the buffer by one character. This method also works when using getchar() to advance stdin, after getting user input from scanf().

Tanner Babcock
  • 3,232
  • 6
  • 21
  • 23