程序员求职经验分享与学习资料整理平台

网站首页 > 文章精选 正文

C语言putc函数详解:“字符快递员”

balukai 2025-03-26 09:42:50 文章精选 11 ℃

一句话理解 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处理复杂表达式
最近发表
标签列表