什么是 ungetc (或 K&R 中的 ungetch) 的用途?

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个回答

32

我不知道你所提到的具体例子(我可能已经23年没读K&R了,而且那是第一版),但通常在解析时,查看下一个字符是否属于你当前正在解析的内容是很方便的。例如,如果你正在读取一个数字,你希望继续读取数字直到遇到非数字字符。ungetc允许数字阅读器查看下一个字符而不将其消耗掉,以便其他人可以读取它。在Greg Hewgill的例子中,“2 3+”,数字阅读器将读取3个数字,然后读取加号并知道该数字已完成,然后使用ungetc放回加号以便稍后读取。


非常感谢。 现在更有意义了。 - Tyler
2
虽然这可能只是语义问题,但 ungetc 允许您在读取字符后“推回”该字符,以便下一个读取调用重新读取它。这与窥视不同,窥视意味着读取而不消耗。 - Lawrence Dol
3
是的,peek等同于执行getc后再执行ungetc。 - David Norman
@DavidNorma,bufp [] 每次只读取一个字符,并且给定 BUFSIZE = 100,那么在这个 K&R 的特定示例中,什么时候执行 printf(“ungetch:too many characters \ n”); - noufal
如果您在不调用getch的情况下调用ungetch超过BUFSIZE次,那么将打印出该信息。 - David Norman

10

尝试在运算符周围不加空格来运行程序。我不确切记得那个例子的格式,也没有K&R手边,但是请尝试使用"2 3+"而非"2 3 +"。 ungetch() 在解析数字时可能会被使用,因为数字解析器会一直读取数字直到读取到一个非数字字符。如果这个非数字字符是空格,则下一个getch()将会读取到+,所有事情都很顺利。然而,如果下一个非数字字符是+,则需要将其推回到输入流中,以便主读取循环可以再次找到它。

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


1
太好了!由于您是 Stack Overflow 的新用户,请不要忘记“接受”(点击复选标记)最有帮助的答案。 - Greg Hewgill

4

它在词法分析器中被广泛使用(编译器的一部分,用于将文本分成变量名、常量、运算符等块)。该函数对于词法分析器并不是必需的,但非常方便。

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


谢谢回复。拥有实际使用的例子很有帮助。 - Tyler

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接