一句话理解 putc
「将字符像‘快递包裹’一样高效投递到文件或屏幕,但需小心‘包裹地址’(文件流)被多次计算!」
函数原型
#include
int putc(int char, FILE *stream); // 注意:通常是宏实现!
入口参数
参数 | 类型 | 比喻解释 |
char | int | 要投递的「包裹」(ASCII字符) |
stream | FILE* | 快递的「目的地」(文件/屏幕) |
返回参数
返回值 | 含义 |
int | 成功投递的字符(ASCII码) |
EOF | 投递失败(如磁盘满/文件未打开) |
核心功能图解
putc('A', stdout); → 屏幕显示:A
putc('\n', file); → 文件写入:换行符
代码实例:高效快递实战
场景1:快速生成ASCII艺术字
#include
void print_logo() {
// 用putc快速输出像素画
for (int y = 0; y < 5; y++) {
for (int x = 0; x < 10; x++) {
putc((x + y) % 2 ? '█' : ' ', stdout); // 棋盘格效果
}
putc('\n', stdout);
}
}
int main() {
print_logo();
return 0;
}
输出效果:
复制
█ █ █ █ █
█ █ █ █ █
█ █ █ █ █
█ █ █ █ █
█ █ █ █ █
场景2:实现二进制文件拷贝(极简版)
#include
int main() {
FILE *src = fopen("source.bin", "rb");
FILE *dest = fopen("backup.bin", "wb");
if (!src || !dest) return 1;
int c;
while ((c = getc(src)) != EOF) { // 逐字节读取
if (putc(c, dest) == EOF) { // 逐字节写入
printf(" 磁盘空间不足!");
break;
}
}
fclose(src);
fclose(dest);
return 0;
}
场景3:危险操作演示(副作用陷阱)
#include
FILE *get_stream() {
static int count = 0;
printf("get_stream() 被调用 %d 次\n", ++count);
return stdout;
}
int main() {
// putc是宏,参数会被多次计算!
putc('A', get_stream()); // 输出:get_stream() 被调用 2次
return 0;
}
结果说明:
由于putc是宏,get_stream()会被展开为两次调用,导致计数器异常增加。
技术细节剖析
1. 与 fputc 的致命差异
特性 | putc | fputc |
实现方式 | 宏(可能更快) | 普通函数(更安全) |
参数计算次数 | 可能多次计算stream参数 | 保证参数只计算一次 |
典型用途 | 高频字符输出循环 | 需要稳定性的场景 |
2. 字符编码的奥秘
- 支持扩展ASCII(0-255):
putc(176, stdout); // 输出(在控制台字体支持的情况下)
putc(219, stdout); // 输出█
死亡陷阱:常见错误
1. 向未打开的文件投递
FILE *file = NULL;
putc('X', file); // 程序崩溃!
2. 错误处理缺失
// 危险!不检查是否成功
putc('A', file);
// 安全写法:
if (putc('A', file) == EOF) {
perror("字符投递失败");
}
高级技巧:实现内存压缩编码
#include
void run_length_encode(FILE *src, FILE *dest) {
int current = getc(src);
while (current != EOF) {
int count = 1;
int next;
while ((next = getc(src)) == current) count++;
putc(current, dest); // 写入字符
putc(count, dest); // 写入重复次数(简易版)
current = next;
}
}
int main() {
FILE *file = fopen("origin.txt", "r");
FILE *encoded = fopen("compressed.bin", "wb");
run_length_encode(file, encoded);
fclose(file);
fclose(encoded);
return 0;
}
总结表格
特性 | 说明 |
核心优势 | 执行效率高(宏实现) |
致命缺陷 | 参数副作用风险 |
适用场景 | 高频字符输出/性能敏感循环 |
安全准则 | 确保stream参数无副作用 |
总结
- 像闪电快递员:putc 是C语言中最高效的字符输出工具,但需要严格管理「快递地址」(文件流参数)。
- 适用场景:高频日志写入、二进制数据处理、性能敏感型循环。
- 安全法则:
1 绝对不要传递含副作用的stream参数
2 永远检查EOF返回值
3 优先用fputc处理复杂表达式