getchar() 函数是否有自己的缓冲区来存储剩余的输入?

Does getchar() function has it's own buffer to store remaining input?

我正在浏览 K&R 的 "C Programming Book"。 现在函数 "getint()" 的代码如下:-->

#include<stdio.h>

#define BUFSIZE 100

char buf[BUFSIZE];
int bufp = 0;

int getch(void) {
    return (bufp > 0)?buf[--bufp]:getchar();
}

void ungetch(int c) {
    if(bufp >= BUFSIZE)
        printf("ungetch: too many characters\n");
    else
        buf[bufp++] = c;
}

int getint(int *pn) {
    int c, sign;

    while(isspace(c = getch()));

    if(!isdigit(c) && c != EOF && c != '-' && c != '+') {
        ungetch(c);
        return 0;
    }

    sign = (c == '-')?-1:1;
    if(c == '+' || c == '-')
        c = getch();

    *pn = 0;
    while(isdigit(c)) {
        *pn = (*pn * 10) + (c - '0');
        c = getch();
    }

    *pn *= sign;

    if(c != EOF)
        ungetch(c);


    return c;
}


int main(int argc, char** argv) {

    int r, i;

    while((r = getint(&i)) != EOF)
        if(r != 0)
            printf("res: %d\n", i);

    return 0;
}

现在我没有得到这个函数的逐步工作过程,即使我试图运行它在理论上写在纸上。

以及当我输入“23”时的事实。它是如何转换为 23 的,我知道有将“23”转换为 23 的逻辑,但 c = getch() 在输入后不会将剩余的“3”存储在缓冲区中,那么它如何取回 3,在转换。 getchar() 是否有自己的缓冲区,它存储所有 inout 字符并逐一获取它们。 非常感谢任何帮助。

And the fact that when I input "23". how does it converted to 23 , I know there is the logic to convert "23" to 23 but c = getch() doesn't store the remaining "3" in the buffer after input then how does it get back the 3, during the conversion. Does getchar() have it's own buffer where it stores all the inout characters and fetch them 1 by 1.

据此,我了解到您希望 getch() 以某种方式接收您的整行输入。好吧,那是错误的。

首先简要说明一下 getchar()getch() 之间的混淆。在 standard C 中,getch() 需要一个 FILE * 类型的参数。这是一个getchar() 等同于 getch(stdin)。此处显示的代码似乎是预标准 C。我假设 getch() 的任何出现都应该是 getchar().

你必须知道的是 stdio.h FILE * streams 是缓冲的。有不同的模式(无缓冲、行缓冲和全缓冲)可用。

stdin 是您的默认输入流。它通常来自键盘(但您的程序不关心这一点,它可以被重定向为来自文件、管道等)。 stdin的默认缓冲模式是line buffered.

那么当您输入 23 <enter> 时会发生什么,2 也只会进入 stdin 输入缓冲区 作为 3,并且仅当换行符后跟(按回车键,这是字符 \n)时,终于在 stdin.

上有可读的内容

getchar() 不关心缓冲。它从 stdin 读取,等待直到有可读取的内容。然后它读取 单个字符 ,因此如果 stdin 的输入缓冲区中有更多字符,它们 将留在那里 直到被读取通过 getchar() 任何其他函数 stdin.

读取

在您提供的代码片段中,主要逻辑在这里:

1. *pn = 0;
2. while(isdigit(c)) {
3.     *pn = (*pn * 10) + (c - '0');
4.     c = getch();
5. }

pn 是一个缓冲区,它将保存整数的最终值,而 c 是每次由 getchar() 逐一读取的字符。因此,当您阅读“23”时,会发生以下情况:

  1. '2' 被读到 c
  2. pn = 0; c = '2'; 在第 3 行(来自具有主要逻辑的代码段)我们将缓冲区中的值乘以 10 并添加 (0x32 - 0x30)
  3. pn = 2; c = 2;
  4. '3' 读到 c
  5. pn 乘以 10 得到 20,你加上 (0x33 - 0x30) 得到最后的 23.

注意事项:

  • getchar() 从 stdin
  • 一个一个地读取字符
  • 添加简单的 printf() 语句将有助于您理解程序的流程
  • 尝试在 gdb 下运行它,检查变量的值