C ut缓冲区未读

C ut缓冲区未读,c,file,readfile,C,File,Readfile,如果您选择继续使用scanf,则至少在stdin中可能存在未读字符时,使用简单函数手动清空输入缓冲区(stdin)。一个简单的函数就可以做到这一点。只需使用getchar()读取每个字符,直到遇到'\n'或EOF为止,例如 void empty_stdin (void) { int c = getchar(); while (c != '\n' && c != EOF) c = getchar(); } 注意:如果函数不带参数,则正确的声明包括

如果您选择继续使用
scanf
,则至少在
stdin
中可能存在未读字符时,使用简单函数手动清空输入缓冲区(
stdin
)。一个简单的函数就可以做到这一点。只需使用
getchar()
读取每个字符,直到遇到
'\n'
EOF
为止,例如

void empty_stdin (void)
{
    int c = getchar();

    while (c != '\n' && c != EOF)
        c = getchar();
}
注意:如果函数不带参数,则正确的声明包括
(void)
作为参数列表,以明确表示不需要参数

现在有了一种正确处理删除stdin中保留的字符的方法,您可以查看输入函数了

如果您使用
getNumbers()
[1]和
getMoreNumbers()
的目的是简单地从
stdin
中读取一个整数,那么只需使用一个具有稍微更具描述性名称的函数即可完成此任务,例如:

int readintstdin (int *value) {

    int rtn = 0;

    printf ("Enter digits: ");

    rtn = scanf ("%d", value);     /* read 1 integer */

    if (rtn == EOF)
        fputs ("(user canceled input.)\n", stderr);
    else if (rtn == 0)
        fputs (" readintstdin() error: invalid input.\n", stderr);

    empty_stdin();  /* remove all remaining chars from stdin */

    return rtn;
}
注意:使用
scanf
时,您负责处理三种情况:

  • 用户通过按Ctrl+d(或windows上的Ctrl+z)手动生成
    EOF
    来取消输入
  • 匹配或输入失败;及
  • 良好输入案例,您必须验证接收的输入是否在预期范围内,等等
  • 考虑到这一点,您可以创建一个函数来读取
    stdin
    ,类似于:

    int readintstdin (int *value) {
    
        int rtn = 0;
    
        printf ("Enter digits: ");
    
        rtn = scanf ("%d", value);     /* read 1 integer */
    
        if (rtn == EOF)
            fputs ("(user canceled input.)\n", stderr);
        else if (rtn == 0)
            fputs (" readintstdin() error: invalid input.\n", stderr);
    
        empty_stdin();  /* remove all remaining chars from stdin */
    
        return rtn;
    }
    
                case 2:
                    printf ("\n enter filename: "); /* get filename to read */
                    if (scanf ("%1023[^\n]", fname) != 1) {
                        fputs ("(user canceled input)\n", stderr);
                        empty_stdin();
                        break;
                    }
                    /* open/validate file open for reading */
                    if ((fp = fopen (fname, "r")) == NULL) {
                        perror ("fopen-fname");
                        empty_stdin();
                        break;
                    }
                    if (!readfromfile (fp)) /* read/output integers */
                        fprintf (stderr, "error: no values read from '%s'\n",
                                fname);
                    fclose (fp);        /* close file */
                    break;
    
    注意两件事,值的**地址作为参数传递,允许输入存储在该内存地址,并返回调用函数(
    main()
    此处)而
    scanf
    返回值作为函数返回返回,指示
    main()
    中的回读成功/失败。您必须始终使用适当的返回类型来创建函数,该返回类型将在调用函数中指示函数的成功或失败。否则,没有首先检查
    scanf
    的返回也没有什么不同

    您的下一个目标似乎是从
    “digits.txt”
    读取所有值。由您决定,一般的方法是在调用者中打开
    文件*流
    ,在将文件流作为参数传递给函数之前,验证文件是否已打开以供读取。否则,如果打开失败,则无需调用函数开始,例如:

    int readfromfile (FILE *fp) {
    
        int value = 0, count = 0;
    
        while (fscanf (fp, "%d", &value) == 1) {    /* while valid int read */
            printf ("%d ", value);
            count++;
        }
    
        putchar ('\n'); /* tidy up with newline */
    
        return count;   /* return value indicating number of values read */
    }  
    
    在这里,为了指示从文件读取的成功/失败,将返回从文件读取的值的数量。如果返回值为
    0
    ,则未从文件中读取任何值

    接下来是菜单。您需要将这些相同的课程应用到菜单中。这意味着您需要处理
    scanf
    的所有三种情况,并删除菜单每次显示之间
    stdin
    中保留的所有字符。将这些保护措施落实到位后,您可以执行以下操作,例如:

    #define MAXC 1024
    ...
    int main (void) {
    
        int input = 1,          /* initialize all variables */
            value = 0;
        char fname[MAXC] = "";  /* buffer to hold filename to read */
        FILE *fp = NULL;
    
        while (0 < input && input < 3) {
            int rtn = 0;    /* store scanf return */
            printf ("\nPlease select which method you'd like to access:\n"
                    " 1) readintstdin()\n"
                    " 2) readfromfile()\n"
                    " (any other numeric input exits)\n\n"
                    " choice: ");
            rtn = scanf ("%d", &input);
            if (rtn == EOF) {   /* user generated manual EOF */
                fputs ("(user canceled input)\n", stderr);
                break;
            }
            else if (rtn == 0) {    /* no integer input */
                fputs (" error: invalid integer input.\n", stderr);
                empty_stdin();  /* empty all chars from stdin */
                continue;       /* re-display menu, try again */
            }
            else    /* good integer input */
                empty_stdin();  /* empty all chars from stdin */
            ...
    
    第二种情况需要更多的思考。您将从用户处获取文件名的输入(因此变量
    fname
    main()
    开头的用途)。在这里,您只需提示并读取文件名(可能包含空格),验证读取内容,然后将文件名传递给
    fopen
    以验证文件是否已打开以供读取。确认文件已打开以供读取后,只需将打开的文件流传递给函数(检查函数返回是否成功/失败),然后在完成后关闭文件。这可以类似于:

    int readintstdin (int *value) {
    
        int rtn = 0;
    
        printf ("Enter digits: ");
    
        rtn = scanf ("%d", value);     /* read 1 integer */
    
        if (rtn == EOF)
            fputs ("(user canceled input.)\n", stderr);
        else if (rtn == 0)
            fputs (" readintstdin() error: invalid input.\n", stderr);
    
        empty_stdin();  /* remove all remaining chars from stdin */
    
        return rtn;
    }
    
                case 2:
                    printf ("\n enter filename: "); /* get filename to read */
                    if (scanf ("%1023[^\n]", fname) != 1) {
                        fputs ("(user canceled input)\n", stderr);
                        empty_stdin();
                        break;
                    }
                    /* open/validate file open for reading */
                    if ((fp = fopen (fname, "r")) == NULL) {
                        perror ("fopen-fname");
                        empty_stdin();
                        break;
                    }
                    if (!readfromfile (fp)) /* read/output integers */
                        fprintf (stderr, "error: no values read from '%s'\n",
                                fname);
                    fclose (fp);        /* close file */
                    break;
    
    注意:您的
    默认值:
    案例应告知用户收到的值不在可接受的菜单值内,然后您可以指示程序已完成。(这只是一个小问题,你可以随意处理)

    总而言之,您可以执行以下操作:

    #include <stdio.h>
    
    #define MAXC 1024
    
    void empty_stdin (void)
    {
        int c = getchar();
    
        while (c != '\n' && c != EOF)
            c = getchar();
    }
    
    int readintstdin (int *value) {
    
        int rtn = 0;
    
        printf ("Enter digits: ");
    
        rtn = scanf ("%d", value);     /* read 1 integer */
    
        if (rtn == EOF)
            fputs ("(user canceled input.)\n", stderr);
        else if (rtn == 0)
            fputs (" readintstdin() error: invalid input.\n", stderr);
    
        empty_stdin();  /* remove all remaining chars from stdin */
    
        return rtn;
    }
    
    int readfromfile (FILE *fp) {
    
        int value = 0, count = 0;
    
        while (fscanf (fp, "%d", &value) == 1) {    /* while valid int read */
            printf ("%d ", value);
            count++;
        }
    
        putchar ('\n'); /* tidy up with newline */
    
        return count;   /* return value indicating number of values read */
    }  
    
    int main (void) {
    
        int input = 1,      /* initialize all variables */
            value = 0;
        char fname[MAXC] = "";
        FILE *fp = NULL;
    
        while (0 < input && input < 3) {
            int rtn = 0;    /* store scanf return */
            printf ("\nPlease select which method you'd like to access:\n"
                    " 1) readintstdin()\n"
                    " 2) readfromfile()\n"
                    " (any other numeric input exits)\n\n"
                    " choice: ");
            rtn = scanf ("%d", &input);
            if (rtn == EOF) {   /* user generated manual EOF */
                fputs ("(user canceled input)\n", stderr);
                break;
            }
            else if (rtn == 0) {    /* no integer input */
                fputs (" error: invalid integer input.\n", stderr);
                empty_stdin();  /* empty all chars from stdin */
                continue;       /* re-display menu, try again */
            }
            else    /* good integer input */
                empty_stdin();  /* empty all chars from stdin */
    
            switch (input) {    /* switch on integer input */
                case 1:
                    if (readintstdin (&value))  /* read from stdin */
                        printf ("value: %d\n", value);
                    break;
                case 2:
                    printf ("\n enter filename: "); /* get filename to read */
                    if (scanf ("%1023[^\n]", fname) != 1) {
                        fputs ("(user canceled input)\n", stderr);
                        empty_stdin();
                        break;
                    }
                    /* open/validate file open for reading */
                    if ((fp = fopen (fname, "r")) == NULL) {
                        perror ("fopen-fname");
                        empty_stdin();
                        break;
                    }
                    if (!readfromfile (fp)) /* read/output integers */
                        fprintf (stderr, "error: no values read from '%s'\n",
                                fname);
                    fclose (fp);        /* close file */
                    break;
                default:    /* handle invalid input */
                    fputs ("Selection not menu entry.\n", stderr);
                    break;
            }  
        }
        printf ("Program complete\n");
    
        return 0;
    }
    
    希望这能解决您的大多数问题,并帮助您避免“因为我觉得这是一个简单的问题而感到压力。”确实如此,但C需要的理解深度远远超过“我会尝试这个,如果它不起作用,我会更改某些内容,重新编译并重试…”您可以控制整个机器,负责处理输入缓冲区的每个字节,并确保程序处理的每个字节都有足够的存储空间。C上没有训练轮。这就是它获得燃烧速度的地方。但是,“强大的力量带来巨大的责任”

    脚注:


    1。虽然不是错误,但C通常避免使用
    camelCase
    MixedCase
    变量名,而使用所有小写,同时保留大写名称以用于宏和常量。这是一个风格的问题——所以完全取决于你,但如果不遵循它,可能会在某些圈子里给人留下错误的第一印象。

    查看此链接,我想知道是否有香草c解决方案,而没有任何库。我不明白这个问题。你是在问如何设置变量吗?为此,请使用
    =
    。作为第一步,不要对参数和全局变量使用相同的名称。请提供一个输入文件
    “digits.txt”“
    的示例(如果太长,则为10行左右)。这将提供一种方法来衡量您迄今为止展示的方法是否合理。当然。每个人都需要不时举手。我们都是从同样的问题开始的。C不是你在一个月或一年内学会的东西。。。这更像是一次旅行,而不是一两个学期内所做的事情。学习C语言的关键就是放慢速度。阅读您使用的每个函数的手册页,慢慢地了解细节——有很多东西需要学习。但是没有比这更好的语言了。C将使你成为一个更好的程序员,不管你最终用什么语言编写。任何人都能学会一门语言,很少有人能学会编程。C是关于编程的。@frlzjosh如果
    $ ./bin/menureadfilestdin
    
    Please select which method you'd like to access:
     1) readintstdin()
     2) readfromfile()
     (any other numeric input exits)
    
     choice: 1
    Enter digits: four-hundred twenty-one
     readintstdin() error: invalid input.
    
    Please select which method you'd like to access:
     1) readintstdin()
     2) readfromfile()
     (any other numeric input exits)
    
     choice: 1
    Enter digits: 421
    value: 421
    
    Please select which method you'd like to access:
     1) readintstdin()
     2) readfromfile()
     (any other numeric input exits)
    
     choice: 2
    
     enter filename: somefile.ext
    fopen-fname: No such file or directory
    
    Please select which method you'd like to access:
     1) readintstdin()
     2) readfromfile()
     (any other numeric input exits)
    
     choice: 2
    
     enter filename: dat/digits.txt
    1 10 299 1 200 15 3 150 13 2 150
    
    Please select which method you'd like to access:
     1) readintstdin()
     2) readfromfile()
     (any other numeric input exits)
    
     choice: 1
    Enter digits: 422
    value: 422
    
    Please select which method you'd like to access:
     1) readintstdin()
     2) readfromfile()
     (any other numeric input exits)
    
     choice: (user canceled input)
    Program complete