ungetc(或 K&R 的 ungetch)的目的是什么?

发布于 2024-07-12 14:10:25 字数 638 浏览 4 评论 0原文

谁能向我解释一下 ungetch 的目的吗? 这是来自 K&R 第 4 章,您在其中创建了一个逆波兰计算器。

我在没有调用 ungetch 的情况下运行了该程序,并且在我的测试中它仍然工作正常。

 int getch(void) /* get a (possibly pushed back) character */
    {
        if (bufp > 0)
        {
            return buf[--bufp];
        }
        else
        {
            return getchar();
        }
    }

    void ungetch(int c) /* push character back on input */
    {
        if (bufp >= BUFSIZE)
        {
            printf("ungetch: too many characters\n");
        }
        else
        {
            buf[bufp++] = c;
        }

}

(我已经删除了 getch 中的三元运算符以使其更清晰。)

Can anyone explain to me the purpose of ungetch?
This is from K&R chapter 4 where you create a Reverse Polish Calculator.

I've ran the program without the call to ungetch and in my tests it still works the same.

 int getch(void) /* get a (possibly pushed back) character */
    {
        if (bufp > 0)
        {
            return buf[--bufp];
        }
        else
        {
            return getchar();
        }
    }

    void ungetch(int c) /* push character back on input */
    {
        if (bufp >= BUFSIZE)
        {
            printf("ungetch: too many characters\n");
        }
        else
        {
            buf[bufp++] = c;
        }

}

(I've removed the ternary operator in getch to make it clearer.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

晒暮凉 2024-07-19 14:10:25

我不知道你所指的具体例子(自从我读 K&R 以来大概有 23 年了,那是第一版。),但通常在解析时“查看”下一个字符很方便看看它是否是您当前正在解析的内容的一部分。 例如,如果您正在读取一个数字,您希望继续读取数字,直到遇到非数字为止。 Ungetc 让数字读取器查看下一个字符而不消耗它,以便其他人可以读取它。 在 Greg Hewgill 的“2 3+”示例中,数字读取器将读取 3 位数字,然后读取加号并知道数字已完成,然后取消加号以便稍后读取。

I don't know about the specific example you're referring to (It's probaby 23 years since I read K&R, and that was the first edition.), but often when parsing it's convenient to 'peek' at the next character to see if it is part of what you're currently parsing. For instance, if you're reading a number you want to keep reading digits until you come to a non-digit. Ungetc lets the number reader look at the next character without consuming it so that someone else can read it. In Greg Hewgill's example of "2 3+", the number reader would read the 3 digit, then read the plus sign and know the number is finished, then ungetc the plus sign so that it can be read later.

那些过往 2024-07-19 14:10:25

尝试运行该程序,运算符周围不要有空格。 我不记得该示例的确切格式,而且我手头没有 K&R,但不要使用“2 3 +”,而是尝试“2 3+”。 ungetch() 可能在解析数字时使用,因为数字解析器将读取数字,直到获得非数字的内容。 如果非数字是空格,则下一个 getch() 将读取 + ,一切正常。 但是,如果下一个非数字是 +,则需要将其推回输入流,以便主读取循环可以再次找到它。

希望我正确地记住了这个例子。

Try running the program without spaces around operators. I don't recall precisely the format of that example and I don't have K&R handy, but instead of using "2 3 +" try "2 3+". The ungetch() is probably used when parsing numbers, as the number parser will read digits until it gets something that is a non-digit. If the non-digit is a space, then the next getch() will read the + and all is well. However, if the next non-digit is a +, then it will need to push that back onto the input stream so the main read loop can find it again.

Hope I'm remembering the example correctly.

遇见了你 2024-07-19 14:10:25

它大量用于词法扫描器(编译器的一部分,将文本分解为变量名、常量、运算符等块)。 该功能对于扫描仪来说并不是必需的,只是非常方便。

例如,当您读取变量名称时,您不知道何时完成,直到读取到不能作为变量名称一部分的字符。 但随后您必须记住该字符并找到一种方法将其传达给词法分析器的下一个块。 您可以创建一个全局变量或其他东西,或者将其传递给调用者——但是如何返回其他东西,比如错误代码? 相反,您 ungetch() 字符将其放回到输入流中,对变量名执行任何您需要的操作并返回。 然后,当词法分析器开始读取下一个块时,它不必四处寻找周围的额外字符。

It's used a lot for lexical scanners (the part of the compiler that breaks your text into chunks like variable names, constants, operators, etc.). The function isn't necessary for the scanner, it's just very convenient.

When you're reading a variable name, for example, you don't know when you're done until you read a character that can't be part of the variable name. But then you have to remember that character and find a way to communicate it to the next chunk of the lexer. You could create a global variable or something, or pass it to the caller--but then how do you return other things, like error codes? Instead, you ungetch() the character to put it back into the input stream, do whatever you need to with your variable name and return. Then when the lexer starts reading the next chunk, it doesn't have to look around for extra characters lying around.

遗忘曾经 2024-07-19 14:10:25

看看这段代码,你就会明白:

#include <conio.h>
#include <stdio.h>
int main()
{
    int y=0;
    char t[10];
    int u=0;
    ungetch('a');
    t[y++]=getch();
    ungetch('m');
    t[y++]=getch();
    ungetch('a');
    t[y++]=getch();
    ungetch('z');
    t[y++]=getch();
    ungetch('z');
    t[y++]=getch();
    ungetch('a');
    t[y++]=getch();
    ungetch('l');
    t[y++]=getch();
    ungetch('\0');
    t[y++]=getch();
    ungetch('\0');
    t[y++]=getch();
    ungetch('\0');
    t[y++]=getch();
    printf("%s",t);
    return 0;
}

Take a look at this code, you'll understand:

#include <conio.h>
#include <stdio.h>
int main()
{
    int y=0;
    char t[10];
    int u=0;
    ungetch('a');
    t[y++]=getch();
    ungetch('m');
    t[y++]=getch();
    ungetch('a');
    t[y++]=getch();
    ungetch('z');
    t[y++]=getch();
    ungetch('z');
    t[y++]=getch();
    ungetch('a');
    t[y++]=getch();
    ungetch('l');
    t[y++]=getch();
    ungetch('\0');
    t[y++]=getch();
    ungetch('\0');
    t[y++]=getch();
    ungetch('\0');
    t[y++]=getch();
    printf("%s",t);
    return 0;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文