首页 > 解决方案 > 找不到 __fpurge(stdin); 的替换

问题描述

我正在研究 C 中的文本文件主题,我有一个问题:我可以使用什么来代替,__fpurge(stdin);但要让这个函数像这样工作,__fpurge(stdin);并且我不允许包含<stdlib.h>在这个程序中。我已经阅读了这个c - 需要 fflush 的替代方案,但只要我不被允许,#include <stdlib.h>所以我不能使用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;
    }
}

标签: ctext-files

解决方案


__fpurge是仅在某些系统(glibc 2.1.95、IBM zOS...)上可用的非标准函数,它丢弃读取到流缓冲区中尚未被getc().

正如linux 手册页中所解释的,通常想要丢弃输入缓冲区是错误的。

您使用 读取用户输入scanf(),它会在请求的转换完成时停止扫描输入,例如,%d当它读取无法继续数字的字符并将该字符留在输入流中时停止读取用户键入的字符。由于stdin连接到终端时通常是行缓冲的,因此您应该在处理输入后读取并丢弃用户输入的行中的任何剩余字节。

这是一个用于此目的的简单函数:

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

您将在处理用户输入后调用此函数,并且您应该测试 的返回值scanf()以确保用户输入具有预期的语法。

这是您功能的修改版本:

#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;
}

推荐阅读