1

I'm studying textfile topic in C and I have got a question: what can I use instead of __fpurge(stdin); but make this function work like __fpurge(stdin); and I am not allowed to include <stdlib.h> in this program. I have read this c - need an alternative for fflush but as long as I'm not allowed to #include <stdlib.h> so I can't use strtol.

void generateBill() {
    FILE *fp, *fp1;
    struct Bill t;
    int id, found = 0, ch1, brel = 0;
    char billname[40];
    fp = fopen(fbill, "rb");
    printf("ID\tName\tPrice\n\n");
    while (1) {
        fread(&t, sizeof(t), 1, fp);
        if (feof(fp)) {
            break;
        }
        printf("%d\t", t.pid);
        printf("%s\t", t.pname);
        printf("%d\t\t\t\n", t.pprice);
        total = total + t.pprice;
    }
    printf("\n\n=================== Total Bill Amount %d\n\n", total);
    fclose(fp);
    if (total != 0) {
        //__fpurge(stdin);

        printf("\n\n\n Do you want to generate Final Bill[1 yes/any number to no]:");
        scanf("%d", &ch1);
        if (ch1 == 1) {
            brel = billFileNo();
            sprintf(billname, "%s%d", " ", brel);
            strcat(billname, "dat");

            fp = fopen(fbill, "rb");
            fp1 = fopen(billname, "wb");
            while (1) {
                fread(&t, sizeof(t), 1, fp);
                if (feof(fp)) {
                    break;
                }
                fwrite(&t, sizeof(t), 1, fp1);
            }
            fclose(fp);
            fclose(fp1);
            fp = fopen(fbill, "wb");
            fclose(fp);
        }
        total = 0;
    }
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189
Atirut
  • 11
  • 3
  • Suppose the input is redirected from file? You might as well `exit(0)`. If the objective is to prevent type-ahead causing unwanted input, you can issue a definite prompt like "Is it OK to format your drive: enter YES". – Weather Vane May 01 '21 at 13:02
  • 1
    Purgeing input blocks the opportunity to redirect the input, right now I'm terribly bothered by such a crap. Design your program to not need this. If you urgently need console-only usage, consider using a standard library like "ncurses", and document it. But expect less impressed users... – the busybee May 01 '21 at 16:29

2 Answers2

0

for a replacement for __fpurge(stdin) suggest:

int ch;
while( (ch = getchar() ) != EOF && ch != '\n' ){;}

which only requires #include <stdio.h>

chqrlie
  • 131,814
  • 10
  • 121
  • 189
user3629249
  • 16,402
  • 1
  • 16
  • 17
  • I must have been tired. The second check of EOF should be a check for '\n'. Answer corrected. – user3629249 May 03 '21 at 16:18
  • @thebusybee: [Control-D actually means “send input immediately.”](https://stackoverflow.com/a/21365313/298225) It causes an end-of-file indication only if it is entered immediately after a Return/Enter or preceding Control-D. – Eric Postpischil May 03 '21 at 17:17
0

__fpurge is a non-standard function only available on some systems (glibc 2.1.95, IBM zOS...) that discards input read into the stream buffer not yet consumed by getc().

As explained in the linux manual page, Usually it is a mistake to want to discard input buffers.

You read user input with scanf(), which stops scanning input when the requested conversion is completed, for example %d stops reading the characters typed by the user when it reads a character that cannot continue the number and leaves this character in the input stream. Since stdin is usually line buffered when attached to a terminal, you should just read and discard any remaining bytes in the line input by the user after you process the input.

Here is a simple function for this purpose:

int flush_input(FILE *fp) {
    int c;
    while ((c = getc(fp)) != EOF && c != '\n')
        continue;
    return c;
}

You would call this function after processing user input and you should test the return value of scanf() to ensure the user input had the expected syntax.

Here is a modified version of you function:

#include <errno.h>
#include <string.h>

// return a non zero error code in case of failure
int generateBill(void) {
    FILE *fp, *fp1;
    struct Bill t;
    int id, found = 0, ch1, brel = 0;
    char billname[40];
    fp = fopen(fbill, "rb");
    if (fp == NULL) {
        fprintf(sdterr, "cannot open %s: %s\n", fbill, strerror(errno));
        return 1;
    }
    printf("ID\tName\tPrice\n\n");
    while (fread(&t, sizeof(t), 1, fp) == 1) {
        printf("%d\t", t.pid);
        printf("%s\t", t.pname);
        printf("%d\t\t\t\n", t.pprice);
        total = total + t.pprice;
    }
    printf("\n\n=================== Total Bill Amount %d\n\n", total);
    if (total != 0) {
        int res;

        printf("\n\n\n Do you want to generate Final Bill[1 yes/any number to no]:");
        while ((res = scanf("%d", &ch1)) == 0) {
            fprintf("Invalid input. Try again\n");
            flush_input(stdin);
        }
        flush_input(stdin);
        if (res == EOF) {
            fprintf("premature end of file on input\n");
            fclose(fp);
            return 2; 
        }
        if (ch1 == 1) {
            brel = billFileNo();
            snprintf(billname, sizeof billname, "bill-%d-dat", brel);

            rewind(fp);
            fp1 = fopen(billname, "wb");
            if (fp1 == NULL) {
                fprintf(sdterr, "cannot open %s: %s\n", billname, strerror(errno));
                fclose(fp);
                return 1;
            }
            while (fread(&t, sizeof(t), 1, fp) == 1) {
                fwrite(&t, sizeof(t), 1, fp1);
            }
            fclose(fp1);
        }
    }
    fclose(fp);
    return 0;
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189