ZetCode

C ungetc 函数

最后修改日期:2025 年 4 月 6 日

ungetc 函数是 C 编程中的一个强大工具,它允许您将字符推回输入流。当您需要“窥视”或撤销读取时,此功能对于解析操作至关重要。本教程将深入探讨 ungetc,解释其行为、限制和实际应用。通过清晰的示例,您将学会如何在 C 程序中有效地使用此函数。

什么是 ungetc?

ungetc 函数将字符推回输入流,使其可用于后续读取操作。它接受两个参数:要推回的字符和流指针。推回的字符必须在任何进一步的输入操作之前被读取。请注意,ungetc 对可以连续推回多少字符有实现定义的限制。请始终检查返回值以确保操作成功。

基本的 ungetc 示例

这个简单的示例演示了 ungetc 的基本用法。

basic_ungetc.c
#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 与文件流一起使用。

file_ungetc.c
#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 操作

此示例演示了多次回推操作及其限制。

multi_ungetc.c
#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 如何帮助解析数字。

parse_number.c
#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 的正确错误处理。

error_ungetc.c
#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 结合使用

此示例将 ungetcfscanf 结合使用以实现灵活的输入。

fscanf_ungetc.c
#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 函数。

peek_function.c
#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 的最佳实践

来源

C ungetc 文档

本教程探讨了 C 中的 ungetc 函数,展示了其在输入处理中的多功能性。从基本用法到高级解析技术,ungetc 为字符输入流提供了宝贵的控制。掌握此函数将提高您在 C 程序中创建健壮的输入处理例程的能力。

作者

我的名字是 Jan Bodnar,我是一名敬业的程序员,对编码充满热情。自 2007 年以来,我通过 1,400 多篇文章和 8 本电子书分享我的专业知识。凭借十多年的教学经验,我致力于使编程变得易于访问且引人入胜。

列表 C 标准库