C ungetc 函数
最后修改日期:2025 年 4 月 6 日
ungetc
函数是 C 编程中的一个强大工具,它允许您将字符推回输入流。当您需要“窥视”或撤销读取时,此功能对于解析操作至关重要。本教程将深入探讨 ungetc
,解释其行为、限制和实际应用。通过清晰的示例,您将学会如何在 C 程序中有效地使用此函数。
什么是 ungetc?
ungetc
函数将字符推回输入流,使其可用于后续读取操作。它接受两个参数:要推回的字符和流指针。推回的字符必须在任何进一步的输入操作之前被读取。请注意,ungetc
对可以连续推回多少字符有实现定义的限制。请始终检查返回值以确保操作成功。
基本的 ungetc 示例
这个简单的示例演示了 ungetc
的基本用法。
#include <stdio.h> int main() { int ch; printf("Enter a character: "); ch = getchar(); // Read a character if (ch != EOF) { ungetc(ch, stdin); // Push it back printf("You entered: "); putchar(getchar()); // Read it again } return 0; }
此程序从标准输入读取一个字符,使用 ungetc
将其推回,然后再次读取。该字符有效地被“窥视”而没有被消耗。请注意,ungetc
在成功时返回字符,在失败时返回 EOF
。推回的字符必须在任何其他输入操作之前读取。
将 ungetc 与文件流一起使用
此示例演示了如何将 ungetc
与文件流一起使用。
#include <stdio.h> int main() { FILE *fp = fopen("data.txt", "r"); if (fp == NULL) { perror("Error opening file"); return 1; } int ch = fgetc(fp); // Read first character if (ch != EOF) { ungetc(ch, fp); // Push it back printf("First character: %c\n", fgetc(fp)); } fclose(fp); return 0; }
在这里,我们打开一个文件并读取它的第一个字符。ungetc
函数将字符推回文件流,使我们能够再次读取它。当您需要检查一个字符然后决定如何处理它时,此技术很有用。请记住,必须正确打开和关闭文件流以避免资源泄露。
多次 ungetc 操作
此示例演示了多次回推操作及其限制。
#include <stdio.h> int main() { int ch; printf("Enter a character: "); ch = getchar(); if (ch != EOF) { ungetc(ch, stdin); // First pushback if (ungetc('X', stdin) == EOF) { // Second pushback printf("Second ungetc failed\n"); } printf("Reading back: "); putchar(getchar()); // 'X' putchar(getchar()); // original character } return 0; }
此程序尝试执行两次 ungetc
操作。标准保证至少一次成功的推回,但多次推回取决于实现。在这里,我们推回了原始字符,然后尝试推回“X”。字符按推回的相反顺序读取。如果第二次 ungetc
失败,它将返回 EOF
。
在数字解析中使用 ungetc
此示例展示了 ungetc
如何帮助解析数字。
#include <stdio.h> #include <ctype.h> int main() { printf("Enter a number: "); int ch; int value = 0; while ((ch = getchar()) != EOF && isdigit(ch)) { value = value * 10 + (ch - '0'); } if (ch != EOF) { ungetc(ch, stdin); // Push back non-digit } printf("Parsed value: %d\n", value); printf("Next character: %c\n", getchar()); return 0; }
此程序读取数字以构成一个数字,然后推回遇到的第一个非数字字符。这使得非数字字符可以被单独处理。ungetc
函数在词法分析中特别有用,在词法分析中您需要“放回”不属于当前标记的字符。推回的字符可供下一次读取操作使用。
使用 ungetc 进行错误处理
此示例演示了 ungetc
的正确错误处理。
#include <stdio.h> int main() { int ch = getchar(); if (ch == EOF) { printf("Read error or EOF\n"); return 1; } if (ungetc(ch, stdin) == EOF) { printf("ungetc failed\n"); return 1; } printf("Successfully pushed back: %c\n", getchar()); return 0; }
此代码展示了如何处理使用 ungetc
时可能出现的错误。首先,我们检查 getchar
是否成功。然后,我们通过检查其返回值来验证 ungetc
是否工作。在使用输入流时,正确的错误处理至关重要,因为推回操作可能由于各种系统限制而失败。始终检查 ungetc
的返回值以确保操作成功。
将 ungetc 与 fscanf 结合使用
此示例将 ungetc
与 fscanf
结合使用以实现灵活的输入。
#include <stdio.h> int main() { int num; char ch; printf("Enter input (e.g., 123a): "); if (scanf("%d", &num) == 1) { scanf("%c", &ch); // Read next character ungetc(ch, stdin); // Push it back printf("Number: %d\n", num); printf("Next character: %c\n", getchar()); } return 0; }
在这里,我们使用 scanf
读取一个数字,然后读取接下来的字符。该字符使用 ungetc
推回并再次读取。当您需要解析混合输入格式时,此技术很有用。ungetc
函数允许您在数字之后“撤销”字符的读取,从而为您提供对输入处理的更多控制。
使用 ungetc 实现 peek()
此示例展示了如何使用 ungetc
创建一个 peek 函数。
#include <stdio.h> int peek(FILE *stream) { int ch = fgetc(stream); if (ch != EOF) { ungetc(ch, stream); } return ch; } int main() { printf("Enter text: "); int first = peek(stdin); if (first != EOF) { printf("First character will be: %c\n", first); printf("Actual input: %c\n", getchar()); } return 0; }
peek
函数读取一个字符并立即将其推回,允许您在不消耗它的情况下检查下一个字符。这是解析器和扫描器中的常见要求。如果到达文件末尾或发生错误,该函数将返回 EOF
。此实现有效地处理了文件流和标准输入。
使用 ungetc 的最佳实践
- 检查返回值:始终通过检查其返回值来验证
ungetc
是否成功。 - 注意限制:请记住,只有一次字符推回被保证可以移植地工作。
- 在其他操作之前使用:在执行其他输入操作之前读取推回的字符。
- 避免推回 EOF:切勿尝试将
EOF
推回流中。 - 与解析结合使用:使用
ungetc
来简化复杂的输入解析逻辑。
来源
本教程探讨了 C 中的 ungetc
函数,展示了其在输入处理中的多功能性。从基本用法到高级解析技术,ungetc
为字符输入流提供了宝贵的控制。掌握此函数将提高您在 C 程序中创建健壮的输入处理例程的能力。
作者
列表 C 标准库。