fprintf 是 C 语言标准库 stdio 头文件提供的格式化输出函数,核心作用是把按照格式控制符处理好的数据,写入到指定的文件流当中,它和大家熟悉的 printf 功能逻辑非常接近,最大区别就是 printf 默认输出到标准输出也就是控制台屏幕,而 fprintf 可以自定义输出目标,既可以写入磁盘文件,也可以输出到 stderr 这类标准错误流。之所以需要这个函数,是因为程序运行过程经常需要把日志计算结果报错信息持久保存到文件,单纯依靠控制台打印无法长期留存数据,fprintf 通过第一个参数传入文件指针,后续参数沿用和 printf 一致的格式化语法,不需要单独学习一套新的格式规则,降低代码学习成本,在日志系统配置文件生成数据导出这类场景使用非常广泛。使用的时候第一步要引入 stdio.h 头文件,第二步通过 fopen 打开文件拿到 FILE 类型的文件指针,第三步调用 fprintf 传入文件指针格式字符串和可变参数,第四步调用 fclose 关闭文件流,同时要做好返回值判断,写入成功之后函数会返回成功写入的字符总数,如果写入失败会返回负数也就是 EOF,这个返回值是排查写入异常的重要依据,很多初学者容易忽略返回值校验,遇到磁盘满权限不足这类问题很难定位。整体使用逻辑就是先打开文件建立文件流,再调用 fprintf 完成格式化写入,最后关闭文件释放系统资源,保证数据完整落盘。
函数原型
int fprintf (FILE stream, const char format, ...);
参数说明
第一个参数 stream 是 FILE 类型指针,代表目标输出流,可以是 fopen 返回的文件指针,也可以是预定义的标准流 stdin stdout stderr,注意 stdout 是标准输出 stderr 是标准错误流,stderr 默认不带缓冲,报错信息推荐使用 fprintf 输出到 stderr。
第二个参数 format 是格式控制字符串,里面包含普通文本和格式转换符,普通字符会原样写入文件,格式转换符用来占位,匹配后面传入的可变参数。
后续可变参数 数量和类型必须和格式控制符里面的转换符一一对应,如果参数类型不匹配数量不对,会出现未定义行为,比如乱码崩溃数据错乱。
返回值 成功时返回写入的字符个数,失败返回 EOF 也就是负数值。
常用格式转换符清单
| 转换符 | 作用 | 示例 |
|---|---|---|
| d i | 输出有符号十进制整数 | % d 输出 int 类型 |
| u | 输出无符号十进制整数 | % u 输出 unsigned int |
| x X | 输出十六进制整数 x 小写 X 大写 | % x 输出 abc % X 输出 ABC |
| o | 输出八进制整数 | %o |
| f | 输出小数浮点数 | % f 输出 double |
| e E | 科学计数法输出浮点数 | %e |
| c | 输出单个字符 | %c |
| s | 输出字符串 | %s |
| p | 输出指针地址 | %p |
| % | 输出百分号本身 | %% |
完整基础示例代码
include
int main ()
{
FILE fp = fopen ("test.txt", "w");
if (fp == NULL)
{
printf ("文件打开失败 \n");
return -1;
}
int num = 100;
double price = 99.5;
char name [] = "apple";
fprintf (fp, "名称 % s 数量 % d 价格 %.2f\n", name, num, price);
fclose (fp);
return 0;
}
这段代码执行之后 test.txt 文件里面就会保存格式化之后的一行文本,其中 %.2f 代表浮点数保留两位小数,属于格式修饰符,修饰符还支持宽度对齐补零,比如 %5d 代表占 5 位宽度右对齐,%-5d 代表左对齐,%05d 代表前面补零。
重要注意事项
第一 文件打开模式要匹配写入需求,w 模式会清空原有文件内容,a 模式是追加写入不会覆盖原有内容,如果是二进制场景不要混淆文本模式和二进制模式,fprintf 本身属于文本格式化输出,不适合直接写二进制原始数据。
第二 可变参数类型匹配是高频坑点,long 类型整数要用 % ld,long long 要用 % lld,如果 int 参数用 % ld 接收会出现数据错乱,属于未定义行为,编译器部分情况只会警告不会报错。
第三 缓冲机制,普通文件流默认是全缓冲,调用 fprintf 之后数据不一定立刻写入磁盘,只是放在内存缓冲区,想要立刻落盘可以调用 fflush 刷新缓冲区,程序退出或者 fclose 的时候缓冲区才会自动刷新,如果程序异常崩溃没有关闭文件,缓冲区数据可能丢失。
第四 stderr 使用 fprintf 的时候不需要 fopen,直接写 fprintf (stderr, "错误信息 % d\n", err); 这是标准错误流,不需要手动关闭。
第五 安全风险,格式字符串如果来自外部输入,会产生格式化字符串漏洞,所以格式字符串尽量写死在代码里面,不要把用户输入直接当成 format 参数传入 fprintf。
【常见问题】
问题 1 C 语言 fprintf 和 printf 有什么核心区别
回答 1 C 语言 fprintf 第一个参数可以指定输出流,能够写入文件或者 stderr,printf 固定输出到控制台 stdout,二者格式控制语法完全一致,fprintf 功能是 printf 的扩展版本。
问题 2 C 语言 fprintf 返回负数是什么原因
回答 2 C 语言 fprintf 返回负数代表写入失败,常见原因是文件指针无效磁盘空间不足文件只读程序没有写权限文件流已经关闭,需要检查 fopen 返回值和文件打开模式。
问题 3 C 语言 fprintf 写入之后文件看不到内容怎么办
回答 3 C 语言 fprintf 存在缓冲区缓存,数据还停留在内存没有落盘,可以调用 fflush 刷新缓冲区,或者正常执行 fclose 关闭文件流,关闭操作会自动刷新缓冲区,另外也要检查文件打开路径是否正确。
问题 4 C 语言 fprintf 可以写入二进制数据吗
回答 4 C 语言 fprintf 本质是文本格式化输出,会把数值转换成可读字符,不适合写入原始二进制字节,如果需要写入原始二进制数据应该使用 fwrite 函数。
【免责申明】
本文内容基于 C 语言标准库常规用法编写,不同编译器和操作系统底层实现存在细微差异,代码示例仅用于学习演示,实际项目开发请结合编译环境做充分测试,本文不保证所有特殊场景下行为完全一致,因直接复制代码产生的程序异常数据丢失等问题,使用者自行承担相关风险。


