1

So I have read multiple posts on why feof doesn't work properly and they all utilize using a while(fscanf(...) == 1) to read to end of file, the problem I have is that I have temp values that are different for each loop, because it is reading each line processing it and then moving to next line. The code I currently have reads all the input properly but prints the last line twice. I was wondering if there was a better way to go about this instead of just doing a hack job and removing the last line processed, since it is processed twice.

void readInputFile(Customer customers[]) {
    FILE *input = fopen("hw4input.txt", "r");

    while (!feof(input)) {
        char tempName[MAXNAMELEN];
        int tempQuantity;
        char tempItem[MAXNAMELEN];
        double tempPrice;
        fscanf(input, "%s %d %s $%lf", &tempName, &tempQuantity, &tempItem, &tempPrice);
        printf("%s %d %s %.2lf\n", tempName, tempQuantity, tempItem, tempPrice);
    }
    printf("EOF\n");
    fclose(input);
} 
chqrlie
  • 131,814
  • 10
  • 121
  • 189
Jacob
  • 113
  • 1
  • 10
  • 5
    [Why is “while ( !feof (file) )” always wrong?](https://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong) –  Jul 15 '17 at 19:35
  • 2
    `if(fscanf(input,...) == 4) printf(...) else break;` – BLUEPIXY Jul 15 '17 at 19:36
  • 2
    Besides the ***essential*** check of the return value fron `scanf` family you have passed incorrect arguments: remove the `&` where you are passing to `%s` format spec. `if(fscanf(input, "%s %d %s $%lf", tempName, &tempQuantity, tempItem, &tempPrice) != 4) . . .;` Moreover you make no attempt to prevent string overflow, by restricting string input lengths. – Weather Vane Jul 15 '17 at 19:40
  • @WeatherVane I'm not worried about string overflow, because this is a homework assignment and the input file isonly going to be in one format and nothign else. – Jacob Jul 16 '17 at 01:12
  • @Jacob start as you mean to continue: write robust code from day 1. Cardinal sin: assuming input data is as you expect it to be. It won't be, even if you prepared it yourself. – Weather Vane Jul 16 '17 at 01:26

2 Answers2

2

You cannot use feof() to detect end of file before attempting to read from the file. feof() will return the state of the end-of-file status only after a failed attempt at reading data from the file.

You should instead read values from the stream, with fscanf() for a quick and dirty throw away toy program, or with fgets() for a more robust parser:

void readInputFile(Customer customers[]) {
    FILE *input = fopen("hw4input.txt", "r");

    if (input != NULL) {
        char name[1024];
        int quantity;
        char item[1024];
        double price;

        while (fscanf(input, "%1023s %d %1023s %lf", name, &quantity, item, &price) == 4) {
            printf("%s %d %s %.2lf\n", name, quantity, item, price);
        }
        printf("EOF\n");
        fclose(input);
    } else {
        printf("Cannot open input file\n");
    }
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • Maybe `&name` --> `name` and comment about no width limit avec `"%s"`? – chux - Reinstate Monica Jul 16 '17 at 00:40
  • This code causes a crazy overflow and memory map thing. – Jacob Jul 16 '17 at 01:14
  • If the input file has very long words, the code would indeed have caused potential buffer overflows. `fscanf()` is clunky and limited, it is difficult to recover from formatting errors, it should only be used for *quick and dirty throw away toy programs*. – chqrlie Jul 16 '17 at 09:10
1

I was wondering if there was a better way to go about this instead of just doing a hack job and removing the last line processed

Yes, there is.

Check the return value from fscanf in your code. The call will fail when you try to read past the end of the file.

You should be checking it anyway. There are even a lot of people who post here who will opine that you shouldn't use any of the *scanf() functions anyway because they're very difficult if not impossible to use in any robust way. There's almost always a way you can feed one of the *scanf() functions data that will cause problems.

Andrew Henle
  • 32,625
  • 3
  • 24
  • 56