ungetc()函数无法正常回退字符求助:输入ABC后输出不符合预期
问题描述
我把代码写得非常简洁,方便排查程序问题,但就是没法让ungetc()正常工作,也没完全搞懂它的用途。按预期,ungetc()应该把字符放回输入流,比如输入ABC后,三次调用getchar()获取字符,我调用ungetc()回退字符后,后续putchar()应该输出'B',但实际输出的还是'C'。我试过getchar()和getc(),问题都一样。简化场景:输入"ABC",预期ungetc()让后续的输入操作返回'B',但实际得到的还是'C',这是为什么?
附上代码:
#include <stdlib.h> #include <stdio.h> #include <string.h> int main(void) { char c; c=getchar(); c=getchar(); c=getchar(); ungetc(c, stdout); putchar(c); }
问题原因与解决方案
1. 流参数传错了
ungetc()是操作输入流的函数,它的第二个参数必须是输入流(比如stdin),而你传了输出流stdout,这完全是错误的目标流,相当于把字符放回了输出缓冲区,对输入操作没有任何影响。
2. 对ungetc()的作用理解错误
ungetc()的作用是把字符放回输入流,供后续的**输入函数(比如getchar()、getc())**读取,它不会修改你当前变量c的值。你现在直接调用putchar(c),输出的是之前三次getchar()后存在c里的'C',和ungetc()没有任何关系。
3. 预期逻辑错误
就算你正确调用ungetc(c, stdin),下一次输入操作读到的也是你放回的'C',而不是'B'。ungetc()只能把你刚刚读取的字符压入输入流的缓冲区,无法让你回溯到之前已经读取过的'B'——因为输入流的指针已经移动到'C'之后,之前的'B'已经被读取并处理掉了,ungetc()做不到让输入流回退到上一个原始字符的位置。
修正后的代码示例
如果想验证ungetc()的正确用法,比如把读取到的'C'放回输入流,再重新读取并输出:
#include <stdio.h> int main(void) { char c; // 依次读取A、B、C,最终c的值是'C' c = getchar(); c = getchar(); c = getchar(); // 把'C'放回输入流stdin ungetc(c, stdin); // 从输入流读取回退的字符,此时得到的是放回的'C' c = getchar(); // 输出这个字符 putchar(c); return 0; }
正确使用场景
ungetc()的典型用法是:当你读取了一个字符后,发现这个字符不是你需要的(比如解析数字时读到了字母),可以用ungetc()把它放回输入流,让后续的输入函数能再次处理这个字符。
内容的提问来源于stack exchange,提问作者Ratdude

