What is the purpose of ungetc (or ungetch from K&R)?

末鹿安然 提交于 2019-12-03 12:25:51

问题


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.)


回答1:


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.




回答2:


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.




回答3:


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.




回答4:


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


来源:https://stackoverflow.com/questions/476615/what-is-the-purpose-of-ungetc-or-ungetch-from-kr

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!