12

谁能向我解释 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 中的三元运算符以使其更清晰。)

4

4 回答 4

32

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

于 2009-01-24T20:37:51.553 回答
10

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

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

于 2009-01-24T20:33:22.357 回答
4

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

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

于 2009-01-24T20:43:43.333 回答
-3

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

#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;
}
于 2012-07-16T15:34:33.603 回答