ZetCode

C vfprintf 函数

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

在 C 编程中,格式化输出对于创建可读且结构化数据至关重要。vfprintf 函数提供了强大的功能,可以使用可变参数将格式化输出写入文件。本教程将深入探讨 vfprintf,解释它与 va_list 的关系,并演示实际用例。理解 vfprintf 有助于创建灵活的输出函数。

什么是 vfprintf?

vfprintf 函数使用可变参数列表将格式化输出写入文件流。它声明在 stdio.h 中,需要三个参数:文件指针、格式字符串和 va_list 参数。当创建类似 printf 的输出的包装函数时,此函数特别有用。在将 va_list 传递给 vfprintf 之前,请务必正确初始化它。

基本的 vfprintf 示例

此示例演示了 vfprintf 与可变参数的基本用法。

basic_vfprintf.c
#include <stdio.h>
#include <stdarg.h>

void write_log(FILE *fp, const char *format, ...) {
    va_list args;
    va_start(args, format);
    vfprintf(fp, format, args);
    va_end(args);
}

int main() {
    FILE *fp = fopen("log.txt", "w");
    if (!fp) {
        perror("Failed to open file");
        return 1;
    }

    write_log(fp, "Log entry: %s, error code: %d\n", "File not found", 404);
    fclose(fp);
    return 0;
}

此代码创建了一个接受可变参数的 write_log 函数。va_start 宏初始化参数列表,然后将其传递给 vfprintf。格式字符串指定如何解释参数。最后,va_end 清理参数列表。结果写入“log.txt”。

创建自定义 printf 函数

了解如何使用 vfprintf 创建自定义的类似 printf 的函数。

custom_printf.c
#include <stdio.h>
#include <stdarg.h>

void my_printf(const char *format, ...) {
    va_list args;
    va_start(args, format);
    vfprintf(stdout, format, args);
    va_end(args);
}

int main() {
    my_printf("Custom printf: %s %d %f\n", "Test", 42, 3.14);
    return 0;
}

在这里,my_printf 通过使用 vfprintfstdout 作为输出流来模仿标准的 printf。可变参数根据格式字符串进行处理。此模式对于创建具有自定义行为的专用输出函数很有用。

使用 vfprintf 进行错误日志记录

使用 vfprintf 实现健壮的错误日志记录系统,将错误写入文件和控制台。

error_logger.c
#include <stdio.h>
#include <stdarg.h>
#include <time.h>

void log_error(FILE *fp, const char *format, ...) {
    time_t now;
    time(&now);
    fprintf(fp, "[%.24s] ", ctime(&now));

    va_list args;
    va_start(args, format);
    vfprintf(fp, format, args);
    va_end(args);

    // Also print to stderr
    va_start(args, format);
    vfprintf(stderr, format, args);
    va_end(args);
}

int main() {
    FILE *fp = fopen("errors.log", "a");
    if (!fp) {
        perror("Failed to open log file");
        return 1;
    }

    log_error(fp, "Critical error: %s\n", "Disk full");
    fclose(fp);
    return 0;
}

此示例展示了一个全面的错误日志记录函数。它首先写入时间戳,然后使用 vfprintf 将格式化的错误消息输出到日志文件和 stderrva_list 会为两个输出重复使用。此方法可确保跨多个目标的一致错误报告。

格式化不同的数据类型

演示 vfprintf 在单次函数调用中处理各种数据类型的能力。

multi_format.c
#include <stdio.h>
#include <stdarg.h>

void print_data(FILE *fp, const char *format, ...) {
    va_list args;
    va_start(args, format);
    vfprintf(fp, format, args);
    va_end(args);
}

int main() {
    FILE *fp = fopen("data.txt", "w");
    if (!fp) {
        perror("Failed to open file");
        return 1;
    }

    print_data(fp, "Integer: %d\nFloat: %.2f\nString: %s\n", 
               42, 3.14159, "Hello");
    fclose(fp);
    return 0;
}

print_data 函数通过格式字符串接受多种数据类型。vfprintf 正确解释每个格式说明符(%d%f%s)并处理相应的参数。这种灵活性使 vfprintf 成为需要处理各种数据类型的函数的理想选择。

安全与不安全函数

在使用 vfprintf 时,请考虑安全隐患。如果用户输入被用作格式字符串,则标准的 vfprintf 容易受到格式字符串攻击。对于更安全的选择,请考虑

使用 vfprintf 的最佳实践

来源

C vfprintf 文档

本教程探讨了 C 语言中的 vfprintf 函数,演示了它在处理可变参数的格式化输出方面的多功能性。从基本用法到高级日志记录系统,vfprintf 为灵活的输出生成提供了强大的功能。

作者

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

列表 C 标准库