news 2026/10/3 22:35:02

C输入输出函数详解:Coursebook printf/scanf完整参考

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C输入输出函数详解:Coursebook printf/scanf完整参考

C输入输出函数详解:Coursebook printf/scanf完整参考

【免费下载链接】coursebookOpen Source Introductory Systems Programming Textbook for the University of Illinois项目地址: https://gitcode.com/GitHub_Trending/co/coursebook

Coursebook 是伊利诺伊大学开源的系统编程入门教材,其"C 语言"一章用精炼的篇幅讲透了 C 输入输出的核心:三大标准流、printf格式占位符、缓冲机制以及scanf家族的安全用法。本文基于教材原文,为你整理一份面向新手的 C 输入输出函数完整参考,帮你一次搞懂printf/scanf背后的原理与常见坑点。

三大标准流:stdin、stdout 与 stderr

每个 C 程序启动时都自带三条数据流,由文件描述符 0、1、2 标识:

流描述符用途默认缓冲行为
stdin标准输入0接收程序输入(通常来自终端)重定向到文件时全缓冲,终端下行缓冲
stdout标准输出1输出程序结果(printf默认写到它)同上
stderr标准错误2输出错误与调试信息不缓冲,立即写出

教材特别强调:stderr按惯例是不缓冲的,而stdin/stdout只有在目标不是交互终端(比如重定向到文件)时才全缓冲。这解释了为什么printf写到终端时看到换行就立刻出现,写到文件时却"憋到最后才出现"。

三条流都可以用 shell 重定向指向文件或别的程序,形成管道。下图展示了多个进程通过标准输出/输入串联成管道的典型场景:

👉 这也正是 Unix 哲学"每个程序只做一件事,通过标准流组合"的体现。

printf 格式字符串与常用占位符

printf的第一个参数是格式字符串,其中的占位符决定后续参数如何被格式化输出:

占位符作用
%s按 C 字符串打印,直到遇到 NUL 字符
%d按十进制整数打印
%c打印单个字符
%p打印指针的内存地址
%f/%x打印浮点数 / 十六进制

一个典型的用法(来自教材示例):

printf("Hello %s, your result is %d\n", name, score);

注意:%s需要字符串指针,而打印整数变量的地址时必须写&score——这是新手最常犯的错之一。教材原文见 common_c_functions.tex。

只打印一行文字或单个字符时,还有更轻量的puts("...")和putchar('1')。

缓冲机制:printf 什么时候真正写出去

printf并不直接写系统,它先把数据放进缓冲区,再调用系统调用write真正落盘。ISO 标准定义了三种流类型:

  • 不缓冲:内容尽快到达目的地(stderr通常如此)
  • 行缓冲:遇到换行符就写出(连终端的stdout通常如此)
  • 全缓冲:缓冲区写满才写出(重定向到文件时)

如果等不及自动刷新,可以显式调用fflush()强制把缓冲区内容写出去。理解这一点,你排查"输出为什么没出现在日志文件里"这类问题时就有的放矢了。

其他输出函数:fprintf 与 sprintf 家族

  • fprintf(stderr, ...):把格式化输出写到任意FILE*流(预定义的stdout/stderr,或fopen返回的文件流)
  • dprintf(fd, ...):直接对文件描述符做格式化输出
  • 格式化到字符串:教材给出了一个安全优先级排序 👇
函数安全性说明
sprintf⚠️ 不检查边界仅在输出长度可确定时使用
snprintf✅ 永不越界传入缓冲区大小,超长会截断
asprintf✅✅ 最佳堆上自动分配恰好够大的缓冲区,用完记得free

snprintf的返回值值得记住:它返回"本应写入的字符数",如果返回值 ≥ 缓冲区大小,说明输出被截断了。

scanf 家族安全用法与避坑指南

读取输入时,教材的核心建议是:检查返回的解析数量是否等于期望值。scanf/fscanf/sscanf都会返回成功解析的项数,从默认输入流、任意文件流或 C 字符串中读取。

三个必记的安全要点:

  1. gets已被淘汰:无法限制读取长度,极易缓冲区溢出,C11 标准直接移除。请改用fgets(buffer, sizeof(buffer), stdin)或能自动扩容的getline。
  2. 用宽度限定符防溢出:scanf("%9s", buffer)最多读 9 个字符,给 10 字节的缓冲区留一个字节放结尾 NUL。
  3. 别把指针本身当数据:sscanf(line, "%c %d", &type, &data)中data是int*,传&data会改写指针本身,后续free(data)直接崩溃。

性能方面,scanf家族因要兼容所有printf规格符而开销较大,追求极致性能的程序可以手写解析。详见教材 introc.tex 引用的完整章节。

项目内延伸阅读资源

想深入 C 输入输出,这些仓库文件值得收藏:

  • 函数详解原文:introc/common_c_functions.tex —— 覆盖错误处理、I/O、string.h全家桶
  • 章末练习(含 stdout/stderr 交错输出思考题):introc/introc.tex
  • 全书章节顺序:order.yaml
  • 构建与部署脚本:Makefile、_scripts/

💡 教材还给了一个实用技巧:用man -S3 printf查阅 C 库函数的 man 手册(第 3 节是 C 库,第 2 节是系统调用),比翻书更快。

【免费下载链接】coursebookOpen Source Introductory Systems Programming Textbook for the University of Illinois项目地址: https://gitcode.com/GitHub_Trending/co/coursebook

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/3 22:34:20

merge 为什么有时只是移动指针,有时会多一个 commit

merge 为什么有时只是移动指针,有时会多一个 commit 前面讲 checkout 和 reset 时,我们一直围绕几样东西看: HEAD:当前站在哪里。分支引用:refs/heads/master 这种名字指向哪个 commit。index:下一次提交准…

作者头像 李华
网站建设 2026/10/3 22:23:02

企业AI Agent定制:把万元当元来比,错在哪里?

一家企业的经营分析岗让助手比较两个区域上半年的费用。助手很快给出结论,说A区比B区高出三成。同事看着数字觉得不对,回去翻原始报表才发现,A区的单位是万元,B区是元,两个数被直接放在一起比了。数字都是从系统里取出…

作者头像 李华
网站建设 2026/10/3 22:17:12

ai编程工具接入TaoToken:统一Key与API通道的配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华