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 标准库。