Home > OS >  Im trying to get my function to stop at the end of the file, but its not working
Im trying to get my function to stop at the end of the file, but its not working

Time:12-11

This code is basically supposed to read a number from two files, determine which is smaller, write that smaller one to an output file, grab a new number, rinse and repeat. Its doing that well for the most part but when it gets to the end it doesnt stop. I've tried using EOF to tell it to stop once it reaches the end of the file but it just infinitely loops and adds the last number to the output file, so instead of looking like "123456789" like it should, it ends up looking like "123456788999999999999" the 8 prints twice and the 9 just repeats infinitely. Am I using EOF wrong? Or do I need to do something else entirely, keep in mind i'm very new to c and dont know very many things.

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


void mergeFuncs(FILE* num1txt, FILE* num2txt, FILE* outtxt);

int main(int argc, char* argv[]) {
    FILE* num1txt;
    num1txt = fopen("numbers1.txt", "r");
    if (num1txt == NULL) {
        printf("Error opening numbers1.txt!");
        exit(1);
    }
    FILE* num2txt;
    num2txt = fopen("numbers2.txt", "r");
    if (num2txt == NULL) {
        printf("Error opening numbers2.txt!");
        exit(1);
    }
    FILE* outtxt;
    outtxt = fopen("output.txt", "w");
    if (outtxt == NULL) {
        printf("Error opening output.txt!");
        exit(1);
    }
    mergeFuncs(num1txt, num2txt, outtxt);
    return 0;
}

void mergeFuncs(FILE* num1txt, FILE* num2txt, FILE* outtxt) {
    int num1, num2, loop = 1, endOfFile1, endOfFile2;
    endOfFile1 = fscanf(num1txt, "%d", &num1);
    printf("in getNum1 - %d\n", num1);

    endOfFile2 = fscanf(num2txt, "%d", &num2);
    printf("in getNum2 - %d\n", num2);
    while (loop) {
        printf("\nStart of a new loop! num1 is [%d], and num2 is [%d]\n", num1, num2);
        if (endOfFile1 == EOF && endOfFile2 == EOF) {
            if (num1 < num2) {
                fprintf(outtxt, "%d", num1);
                printf("num1 is smaller\n");
                fprintf(outtxt, "%d", num2);
                printf("done :) //uwu//");
                fclose(num1txt);
                fclose(num2txt);
                fclose(outtxt);
            }
            else if (num2 < num1) {
                fprintf(outtxt, "%d", num2);
                printf("num2 is smaller\n");
                fprintf(outtxt, "%d", num1);
                printf("done :) //uwu//");
                fclose(num1txt);
                fclose(num2txt);
                fclose(outtxt);
            }
            loop = 0;
        }
        else if (endOfFile1 == EOF) {
            fprintf(outtxt, "%d", num1);
            while (endOfFile2 !=EOF) {
                fprintf(outtxt, "%d", num2);
            }
            fprintf(outtxt, "%d", num2);
            loop = 0;
            fclose(num1txt);
            fclose(num2txt);
            fclose(outtxt);
        }
        else if (endOfFile2 == EOF) {
            fprintf(outtxt, "%d", num2);
            while (endOfFile1 != EOF) {
                printf(outtxt, "%d", num1);
            }
            printf(outtxt, "%d", num1);
            loop = 0;
            fclose(num1txt);
            fclose(num2txt);
            fclose(outtxt);
        }
        else if (num1 < num2) {
            fprintf(outtxt, "%d", num1);
            printf("num1 is smaller\n");
            endOfFile1 = fscanf(num1txt, "%d", &num1);
            printf("in getNum1 - %d\n", num1);
        }
        else if (num2 < num1) {
            fprintf(outtxt, "%d", num2);
            printf("num2 is smaller\n");
            endOfFile2 = fscanf(num2txt, "%d", &num2);
            printf("in getNum2 - %d\n", num2);
        }
    }
    return;
}

CodePudding user response:

You want to have a single place at which you read from the files. Read both until each is exhausted. If one file is exhausted first, fill its value with a bogus large value (INT_MAX from limits.h is a good choice) so that the other value is used as the minimum. Your function can be implemented as:

void 
mergeFuncs(FILE* num1txt, FILE* num2txt, FILE* outtxt)
{
        int n[2], r[2];
        while(
                (r[0] = fscanf(num1txt, "%d", n   0)),
                (r[1] = fscanf(num2txt, "%d", n   1)),
                (r[0] == 1 || r[1] == 1)
        ){
                for( int i = 0; i < 2; i  = 1 ){
                        if( r[i] != 1 ){ /* a value was not read from file i */
                                n[i] = INT_MAX;
                        }
                }
                fprintf(outtxt, "%d,", n[0] > n[1] ? n[1] : n[0]);
        }
        return;
}

Note that the above does not distinguish between reaching the end of file, invalid input, or a read error. If you care about that distinction, use feof and/or ferror to decide whether or not to emit an appropriate error message. It is a good exercise to modify the above to handle invalid input.

Also note that if your input files look like 1523 and 3181, the output file will not be 1121, since each of those inputs is just a single integer. scanf does not read individual digits. If you want to read individual digits, you will need to modify things. Your remark about your output file looking like 123456788999999999999 suggests you may be wanting to use a %c conversion specifier to read single digits. I've added a comma after each value in the output to help clarify that point.

CodePudding user response:

rather than relying on the return value of fscanf that may or maybe not actully return EOF use feof to know for sure if the file is empty.

according to the spec of fscanf the EOF is returned only when the file is already empty, but in your case you can have trailing whitespace at the end of the file that fscanf will not consume since there is no data to match after it.

  • Related