0

I want to merge two files in C, and stop in the end.

I have a program but it keeps spelling out words even after my file is ended. For example:

File 1:

a
b
c

File 2:

1
2
3
4
5

And the result I get is:

a
1
b
2
c
3
c
4
c
5

And I want:

a
1
b
2
c
3
4
5

I think it's my if statement in my while loop that is my issue. I don't know how to define that.

My code is:

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


int main(void) {

    char d[200];                        //char för da.txt
    char h[200];                        //char för hej.txt
    FILE *hptr, *dptr;

    hptr = fopen("hej.txt", "r");       //Öppna hej.txt => hptr
    dptr= fopen("da.txt", "r");         //Öppna da.txt => dptr

    /*
    if(((hptr) == NULL && (dptr) == NULL)) //Fall 1 
    {
        printf("Error, båda filerna är tom");
        exit(1);
    }


    if ((hptr) == NULL)                 //Fall 2 när hej.txt är tom
    {
        fscanf(dptr,"%[^/]", d);        //Hämtar från da.txt
        printf("\nFil 2:\n%s", d);      //Skriver ut från da.txt
        exit(1);
    }

    if ((dptr) == NULL)                 //Fall 3 när da.txt är tom
    {
        fscanf(hptr,"%[^/]", h);        //Hämtar från hej.txt
        printf("Fil 1:\n%s", h);        //Skriver ut från hej.txt
        exit (1);
    } */

    if(hptr != NULL || dptr != NULL)        //Fall 4 när ingen fil är tom
    {

        while (!feof (hptr) && !feof (dptr))
        {
            if (hptr ***I guess this is the problem*** == feof)
            {
            fgets(d, 200, dptr);
            printf("%s", d);
            }

            if (hptr == feof)  
            {
            fgets(h, 200, hptr);
            printf("%s", h);
            }

        }

        fclose (hptr);
        fclose (dptr);
    }
    //getch();
    return EXIT_SUCCESS;
}
Siguza
  • 21,155
  • 6
  • 52
  • 89
Karim
  • 1

4 Answers4

1

feof only updates when you try to do some IO. When you call fgets, and it reaches EOF and fails, you just print the string anyway, even though it wasn't updated. This is why you get the repeated "c"

Try this instead:

 while (!feof (hptr) || !feof (dptr))
 {
    if (fgets(d, 200, dptr))
    {
        printf("%s", d);
    }

    if (fgets(h, 200, hptr))  
    {
        printf("%s", h);
    }
}
Joseph Ireland
  • 2,465
  • 13
  • 21
  • 1
    Thanx for your help! We changed && to || and it's working fine. – Karim Dec 08 '16 at 15:20
  • Of course... BTW it seems like the code above doesn't actually give the output you said, i.e. the if statements shouldn't be entered, and the while ends at the sortest file. That makes it hard to comment on. – Joseph Ireland Dec 08 '16 at 15:24
  • 2
    Please read [Why is “while ( !feof (file) )” always wrong?](http://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong) – Jabberwocky Dec 08 '16 at 15:26
  • @MichaelWalz if you are talking to me, then, that question doesn't mention anything about `while (!feof(file1) || !feof(file2))` – Joseph Ireland Dec 08 '16 at 15:41
  • And, in this case it *does* test something useful. I guess it's better to declare the return value of `fgets` and use `while((d_line=fgets(d,200,dptr) ||(h_line=fgets(h,200,hptr))`, but that just looks messy – Joseph Ireland Dec 08 '16 at 15:43
  • @JosephIreland `feof` gives a valid information _after_ an attempt to read. BTW the downvote is not mine. – Jabberwocky Dec 08 '16 at 15:48
  • @JosephIreland *And, in this case it does test something useful.* Your code will process the last line of the first file that ends twice. – Andrew Henle Dec 08 '16 at 16:17
  • @MichaelWalz nope, thats what the if(fgets) is for – Joseph Ireland Dec 08 '16 at 16:27
  • It seems that we got our program to work properly but we dont really understand how the while loop can ”count” to the next string. Is it the fgets function that counts by itself to the next string? How does it work? – Karim Dec 08 '16 at 18:28
  • Yes, `fgets` handles that. The C `FILE*` stores your current location in the file, and `fgets` copies a line from the file into your buffer, and advances the file pointer. So when you call it repeatedly, you read a new line each time. – Joseph Ireland Dec 08 '16 at 20:03
  • @Karim also when you reach the end of the file it will return NULL and leave the buffer as it is, which is why you have the if statements – Joseph Ireland Dec 08 '16 at 20:03
0

Try to use

!feof (hptr) 

instead of

hptr == feof

Explanation: feof is a function -- you are comparing a file pointer hptr against a function pointer feof which will never work -- but since you can always compare pointers in C the compiler does not give you any errors.

You also appears to have a cut-and-paste error as you are using hptr in both if statements -- Im sure one of them should have been dptr

Soren
  • 14,402
  • 4
  • 41
  • 67
0

Actually you need this:

  if (hptr != NULL && dptr != NULL)        //Fall 4 när ingen fil är tom
  {               //^ you need && here, not ||

    do
    {
        if (fgets(d, 200, dptr) != NULL)
          printf("%s", d);

        if (fgets(h, 200, hptr) != NULL)
          printf("%s", h);
    } while (!(feof(hptr) && feof(dptr)));

    fclose(hptr);
    fclose(dptr);
  }

Please see this SO question: Why is “while ( !feof (file) )” always wrong?

Community
  • 1
  • 1
Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
-1

You don't need feof() (it is terrible!) , just use fgets()s return value, alternating between the two input files.

#include <stdio.h>

int main(void)
{
char buff[100];
int state;

FILE * one, *two;
one = fopen("one", "r" );
two = fopen("two", "r" );

if (!one || !two) return 1;

for (state=0; ; state ^=1 ) {
        if (!fgets( buff, sizeof buff, state ? two: one)) break;
        printf("%s", buff);
        }

while (fgets( buff, sizeof buff, state? one : two)) {
        printf("%s", buff);
        }
fclose(one);
fclose(two);

return 0;
}
joop
  • 4,330
  • 1
  • 15
  • 26