摘要:本文围绕 C 语言中最基础也最易混淆的一对标准库函数 printf 与 scanf 展开,先分别讲清二者的作用、基础语法、常用占位符与数据流向,再重点剖析 scanf 的返回值、%c 与 %lf 等占位符陷阱以及 VS 环境下的 C6031 警告处理;随后澄清「两个函数必须成对出现、数据直接传递」的常见误区,指出变量内存才是真正的数据中转站;最后汇总初学者高频踩坑,并用一张对比表从作用、数据流向、是否阻塞、参数是否加 &、返回值含义、%f 与 %lf 差异、是否跳过空白字符等维度横向对比二者,帮助读者一次性建立清晰、可落地的认知。
学 C 语言,最先接触、也最容易混淆的一对函数,就是 printf 和 scanf。很多人会简单记成“一个输出、一个输入”,但问到二者之间到底是什么关系,常常说不清楚:它们是不是必须成对出现?scanf 的数据是直接传给 printf 的吗?
这篇文章就把 scanf、printf 的各自作用、数据流向以及常见误区一次性讲明白。
前置:两个函数都来自标准输入输出库,使用必须引入头文件
#include <stdio.h>
一、printf:格式化输出,程序向屏幕输出内容
printf 全称 print format,名字中的 f 代表 format(格式化)。
作用:把程序内存中的常量、变量,按照我们定制的格式输出到标准输出设备(屏幕 stdout)。
数据流向:程序内存(变量/常量) → printf → 屏幕(stdout标准输出)
printf 的数据流向可以用下图表示:
#mermaid-svg-8b8jrk8ZENfUzMUV{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-8b8jrk8ZENfUzMUV .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-8b8jrk8ZENfUzMUV .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-8b8jrk8ZENfUzMUV .error-icon{fill:#552222;}#mermaid-svg-8b8jrk8ZENfUzMUV .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-8b8jrk8ZENfUzMUV .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-8b8jrk8ZENfUzMUV .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-8b8jrk8ZENfUzMUV .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-8b8jrk8ZENfUzMUV .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-8b8jrk8ZENfUzMUV .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-8b8jrk8ZENfUzMUV .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-8b8jrk8ZENfUzMUV .marker{fill:#333333;stroke:#333333;}#mermaid-svg-8b8jrk8ZENfUzMUV .marker.cross{stroke:#333333;}#mermaid-svg-8b8jrk8ZENfUzMUV svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-8b8jrk8ZENfUzMUV p{margin:0;}#mermaid-svg-8b8jrk8ZENfUzMUV .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-8b8jrk8ZENfUzMUV .cluster-label text{fill:#333;}#mermaid-svg-8b8jrk8ZENfUzMUV .cluster-label span{color:#333;}#mermaid-svg-8b8jrk8ZENfUzMUV .cluster-label span p{background-color:transparent;}#mermaid-svg-8b8jrk8ZENfUzMUV .label text,#mermaid-svg-8b8jrk8ZENfUzMUV span{fill:#333;color:#333;}#mermaid-svg-8b8jrk8ZENfUzMUV .node rect,#mermaid-svg-8b8jrk8ZENfUzMUV .node circle,#mermaid-svg-8b8jrk8ZENfUzMUV .node ellipse,#mermaid-svg-8b8jrk8ZENfUzMUV .node polygon,#mermaid-svg-8b8jrk8ZENfUzMUV .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-8b8jrk8ZENfUzMUV .rough-node .label text,#mermaid-svg-8b8jrk8ZENfUzMUV .node .label text,#mermaid-svg-8b8jrk8ZENfUzMUV .image-shape .label,#mermaid-svg-8b8jrk8ZENfUzMUV .icon-shape .label{text-anchor:middle;}#mermaid-svg-8b8jrk8ZENfUzMUV .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-8b8jrk8ZENfUzMUV .rough-node .label,#mermaid-svg-8b8jrk8ZENfUzMUV .node .label,#mermaid-svg-8b8jrk8ZENfUzMUV .image-shape .label,#mermaid-svg-8b8jrk8ZENfUzMUV .icon-shape .label{text-align:center;}#mermaid-svg-8b8jrk8ZENfUzMUV .node.clickable{cursor:pointer;}#mermaid-svg-8b8jrk8ZENfUzMUV .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-8b8jrk8ZENfUzMUV .arrowheadPath{fill:#333333;}#mermaid-svg-8b8jrk8ZENfUzMUV .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-8b8jrk8ZENfUzMUV .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-8b8jrk8ZENfUzMUV .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8b8jrk8ZENfUzMUV .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-8b8jrk8ZENfUzMUV .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8b8jrk8ZENfUzMUV .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-8b8jrk8ZENfUzMUV .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-8b8jrk8ZENfUzMUV .cluster text{fill:#333;}#mermaid-svg-8b8jrk8ZENfUzMUV .cluster span{color:#333;}#mermaid-svg-8b8jrk8ZENfUzMUV div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-8b8jrk8ZENfUzMUV .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-8b8jrk8ZENfUzMUV rect.text{fill:none;stroke-width:0;}#mermaid-svg-8b8jrk8ZENfUzMUV .icon-shape,#mermaid-svg-8b8jrk8ZENfUzMUV .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8b8jrk8ZENfUzMUV .icon-shape p,#mermaid-svg-8b8jrk8ZENfUzMUV .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-8b8jrk8ZENfUzMUV .icon-shape .label rect,#mermaid-svg-8b8jrk8ZENfUzMUV .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8b8jrk8ZENfUzMUV .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-8b8jrk8ZENfUzMUV .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-8b8jrk8ZENfUzMUV :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
程序内存变量 / 常量
printf 格式化
屏幕 stdout
1.1 基础语法
printf("格式字符串", 参数1, 参数2, …);
- 格式字符串内可以写普通文本,也可以写 % 开头的占位符;
- 占位符和后面参数一一对应:如果格式串内有 n 个占位符,则一共需要 n + 1 个参数;参数数量不足,会读取内存随机垃圾值;
- printf 不会自动换行,想要换行需要手动写转义字符 \\n。
简单示例:
#include <stdio.h>
int main(void)
{
int num = 66;
printf("数字的值 = %d\\n", num);
printf("Hello\\nWorld\\n"); // \\n 实现换行
return 0;
}
1.2 常用占位符对照表(和 C 内置数据类型匹配)
| %d / %i | 打印 int 十进制有符号整数 |
| %hd | 打印 short 短整型 |
| %ld | 打印 long 长整型 |
| %lld | 打印 long long 长长整型 |
| %u | 打印 unsigned int 无符号整数 |
| %f | 打印 float / double 浮点数,默认小数点后 6 位 |
| %c | 打印单个字符 |
| %s | 打印字符串 |
| %zd | 打印 size_t 类型,配合 sizeof 使用 |
| %p | 打印指针/内存地址 |
| %% | 输出一个百分号% |
1.3 拓展:格式化输出小技巧
printf("%5d\\n", 123); // 输出: 123
printf("%-5d\\n", 123); // 输出:123
printf("Number is %.2f\\n", 0.5); // Number is 0.50
💡执行特性:printf 执行时不会阻塞程序,运行到该行直接输出,不需要等待键盘操作。
二、scanf:格式化输入,读取键盘数据存入变量
scanf 全称 scan format。
作用:读取标准输入(键盘 stdin)的数据,按照格式解析,保存到变量对应的内存空间。
数据流向:键盘(stdin标准输入) → scanf → 变量内存
scanf 的数据流向与 printf 正好相反:
#mermaid-svg-vFcxDG9QFGrxABTE{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-vFcxDG9QFGrxABTE .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-vFcxDG9QFGrxABTE .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-vFcxDG9QFGrxABTE .error-icon{fill:#552222;}#mermaid-svg-vFcxDG9QFGrxABTE .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-vFcxDG9QFGrxABTE .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-vFcxDG9QFGrxABTE .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-vFcxDG9QFGrxABTE .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-vFcxDG9QFGrxABTE .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-vFcxDG9QFGrxABTE .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-vFcxDG9QFGrxABTE .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-vFcxDG9QFGrxABTE .marker{fill:#333333;stroke:#333333;}#mermaid-svg-vFcxDG9QFGrxABTE .marker.cross{stroke:#333333;}#mermaid-svg-vFcxDG9QFGrxABTE svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-vFcxDG9QFGrxABTE p{margin:0;}#mermaid-svg-vFcxDG9QFGrxABTE .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-vFcxDG9QFGrxABTE .cluster-label text{fill:#333;}#mermaid-svg-vFcxDG9QFGrxABTE .cluster-label span{color:#333;}#mermaid-svg-vFcxDG9QFGrxABTE .cluster-label span p{background-color:transparent;}#mermaid-svg-vFcxDG9QFGrxABTE .label text,#mermaid-svg-vFcxDG9QFGrxABTE span{fill:#333;color:#333;}#mermaid-svg-vFcxDG9QFGrxABTE .node rect,#mermaid-svg-vFcxDG9QFGrxABTE .node circle,#mermaid-svg-vFcxDG9QFGrxABTE .node ellipse,#mermaid-svg-vFcxDG9QFGrxABTE .node polygon,#mermaid-svg-vFcxDG9QFGrxABTE .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-vFcxDG9QFGrxABTE .rough-node .label text,#mermaid-svg-vFcxDG9QFGrxABTE .node .label text,#mermaid-svg-vFcxDG9QFGrxABTE .image-shape .label,#mermaid-svg-vFcxDG9QFGrxABTE .icon-shape .label{text-anchor:middle;}#mermaid-svg-vFcxDG9QFGrxABTE .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-vFcxDG9QFGrxABTE .rough-node .label,#mermaid-svg-vFcxDG9QFGrxABTE .node .label,#mermaid-svg-vFcxDG9QFGrxABTE .image-shape .label,#mermaid-svg-vFcxDG9QFGrxABTE .icon-shape .label{text-align:center;}#mermaid-svg-vFcxDG9QFGrxABTE .node.clickable{cursor:pointer;}#mermaid-svg-vFcxDG9QFGrxABTE .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-vFcxDG9QFGrxABTE .arrowheadPath{fill:#333333;}#mermaid-svg-vFcxDG9QFGrxABTE .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-vFcxDG9QFGrxABTE .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-vFcxDG9QFGrxABTE .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-vFcxDG9QFGrxABTE .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-vFcxDG9QFGrxABTE .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-vFcxDG9QFGrxABTE .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-vFcxDG9QFGrxABTE .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-vFcxDG9QFGrxABTE .cluster text{fill:#333;}#mermaid-svg-vFcxDG9QFGrxABTE .cluster span{color:#333;}#mermaid-svg-vFcxDG9QFGrxABTE div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-vFcxDG9QFGrxABTE .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-vFcxDG9QFGrxABTE rect.text{fill:none;stroke-width:0;}#mermaid-svg-vFcxDG9QFGrxABTE .icon-shape,#mermaid-svg-vFcxDG9QFGrxABTE .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-vFcxDG9QFGrxABTE .icon-shape p,#mermaid-svg-vFcxDG9QFGrxABTE .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-vFcxDG9QFGrxABTE .icon-shape .label rect,#mermaid-svg-vFcxDG9QFGrxABTE .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-vFcxDG9QFGrxABTE .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-vFcxDG9QFGrxABTE .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-vFcxDG9QFGrxABTE :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
键盘 stdin
输入缓冲区
scanf 格式化解析
变量内存
2.1 基础语法
scanf("格式字符串", &变量名);
⚠️核心重点:
普通变量前面必须加上取地址符 &。scanf 需要拿到变量的内存地址,才能把读取到的数据写进这块内存。
例外:字符数组(字符串),数组名本身代表首元素地址,不要加 &。
示例:
#include <stdio.h>
int main(void)
{
int score = 0;
printf("请输入成绩:");
scanf("%d", &score); // int普通变量,加&
printf("你的成绩:%d\\n", score);
char arr[11] = {0};
scanf("%10s", arr); // 字符数组,不加&;%10s限制最多读10字符,防止越界
printf("输入的字符串:%s\\n", arr);
return 0;
}
执行行为:代码运行到 scanf 时,程序阻塞暂停,等待用户键盘输入,按下回车之后,才继续向下执行。用户输入会先放入输入缓冲区,scanf 再从缓冲区中解析内容。
scanf 的阻塞执行过程如下:
#mermaid-svg-sPjzpg39nBp7r9fs{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-sPjzpg39nBp7r9fs .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-sPjzpg39nBp7r9fs .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-sPjzpg39nBp7r9fs .error-icon{fill:#552222;}#mermaid-svg-sPjzpg39nBp7r9fs .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-sPjzpg39nBp7r9fs .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-sPjzpg39nBp7r9fs .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-sPjzpg39nBp7r9fs .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-sPjzpg39nBp7r9fs .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-sPjzpg39nBp7r9fs .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-sPjzpg39nBp7r9fs .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-sPjzpg39nBp7r9fs .marker{fill:#333333;stroke:#333333;}#mermaid-svg-sPjzpg39nBp7r9fs .marker.cross{stroke:#333333;}#mermaid-svg-sPjzpg39nBp7r9fs svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-sPjzpg39nBp7r9fs p{margin:0;}#mermaid-svg-sPjzpg39nBp7r9fs .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-sPjzpg39nBp7r9fs .cluster-label text{fill:#333;}#mermaid-svg-sPjzpg39nBp7r9fs .cluster-label span{color:#333;}#mermaid-svg-sPjzpg39nBp7r9fs .cluster-label span p{background-color:transparent;}#mermaid-svg-sPjzpg39nBp7r9fs .label text,#mermaid-svg-sPjzpg39nBp7r9fs span{fill:#333;color:#333;}#mermaid-svg-sPjzpg39nBp7r9fs .node rect,#mermaid-svg-sPjzpg39nBp7r9fs .node circle,#mermaid-svg-sPjzpg39nBp7r9fs .node ellipse,#mermaid-svg-sPjzpg39nBp7r9fs .node polygon,#mermaid-svg-sPjzpg39nBp7r9fs .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-sPjzpg39nBp7r9fs .rough-node .label text,#mermaid-svg-sPjzpg39nBp7r9fs .node .label text,#mermaid-svg-sPjzpg39nBp7r9fs .image-shape .label,#mermaid-svg-sPjzpg39nBp7r9fs .icon-shape .label{text-anchor:middle;}#mermaid-svg-sPjzpg39nBp7r9fs .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-sPjzpg39nBp7r9fs .rough-node .label,#mermaid-svg-sPjzpg39nBp7r9fs .node .label,#mermaid-svg-sPjzpg39nBp7r9fs .image-shape .label,#mermaid-svg-sPjzpg39nBp7r9fs .icon-shape .label{text-align:center;}#mermaid-svg-sPjzpg39nBp7r9fs .node.clickable{cursor:pointer;}#mermaid-svg-sPjzpg39nBp7r9fs .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-sPjzpg39nBp7r9fs .arrowheadPath{fill:#333333;}#mermaid-svg-sPjzpg39nBp7r9fs .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-sPjzpg39nBp7r9fs .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-sPjzpg39nBp7r9fs .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-sPjzpg39nBp7r9fs .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-sPjzpg39nBp7r9fs .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-sPjzpg39nBp7r9fs .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-sPjzpg39nBp7r9fs .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-sPjzpg39nBp7r9fs .cluster text{fill:#333;}#mermaid-svg-sPjzpg39nBp7r9fs .cluster span{color:#333;}#mermaid-svg-sPjzpg39nBp7r9fs div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-sPjzpg39nBp7r9fs .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-sPjzpg39nBp7r9fs rect.text{fill:none;stroke-width:0;}#mermaid-svg-sPjzpg39nBp7r9fs .icon-shape,#mermaid-svg-sPjzpg39nBp7r9fs .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-sPjzpg39nBp7r9fs .icon-shape p,#mermaid-svg-sPjzpg39nBp7r9fs .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-sPjzpg39nBp7r9fs .icon-shape .label rect,#mermaid-svg-sPjzpg39nBp7r9fs .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-sPjzpg39nBp7r9fs .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-sPjzpg39nBp7r9fs .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-sPjzpg39nBp7r9fs :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
否
是
执行到 scanf
程序阻塞暂停
用户是否输入并回车
数据进入输入缓冲区
按格式串解析
写入变量内存
继续向下执行
2.2 scanf 的返回值(重要知识点)
scanf 会返回一个整数:
- 返回成功匹配读取到的数据项的个数;
- 读取失败或者读到文件末尾,返回 EOF(一般值为 -1)。
示例:
#include <stdio.h>
int main(void)
{
int a,b,c;
int ret = scanf("%d %d %d", &a, &b, &c);
printf("a = %d, b = %d, c = %d\\n", a, b, c);
printf("ret = %d\\n", ret); // ret表示成功读取的变量个数
return 0;
}
返回值经常用来做多组输入,两种经典写法:
//写法1:成功读到2个就继续
while (scanf("%d %d",&a,&b) == 2)
{
printf("%d %d\\n", a, b);
}
//写法2:读到EOF结束
while (scanf("%d %d",&a,&b)!=EOF)
{
printf("%d %d\\n", a, b);
}
2.3 scanf 占位符注意点
- 如果要在读取字符的同时跳过前置空白,写法为:scanf(" %c", &ch);(%c 前面写一个空格);
int year,month,day;
scanf("%d%*c%d%*c%d", &year, &month, &day);
2.4 VS 编译器特殊警告说明
在 VS 环境直接写标准 scanf,会报 C6031 警告,提示该函数不安全。
临时解决:在 .c 文件最顶部添加宏定义:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
⚠️ 注意:scanf_s 是微软 VS 独有的扩展函数,不是 C 语言标准库函数,GCC、Clang 等其他编译器并不识别,初学阶段优先使用标准 scanf。
一劳永逸地永久配置 VS:
键盘输入 → scanf →【变量内存】→ printf → 屏幕输出
printf 与 scanf 的协作关系,可以用下面这张图概括:
#mermaid-svg-2Uxh4dRwlEv1jHfX{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-2Uxh4dRwlEv1jHfX .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-2Uxh4dRwlEv1jHfX .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-2Uxh4dRwlEv1jHfX .error-icon{fill:#552222;}#mermaid-svg-2Uxh4dRwlEv1jHfX .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-2Uxh4dRwlEv1jHfX .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-2Uxh4dRwlEv1jHfX .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-2Uxh4dRwlEv1jHfX .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-2Uxh4dRwlEv1jHfX .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-2Uxh4dRwlEv1jHfX .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-2Uxh4dRwlEv1jHfX .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-2Uxh4dRwlEv1jHfX .marker{fill:#333333;stroke:#333333;}#mermaid-svg-2Uxh4dRwlEv1jHfX .marker.cross{stroke:#333333;}#mermaid-svg-2Uxh4dRwlEv1jHfX svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-2Uxh4dRwlEv1jHfX p{margin:0;}#mermaid-svg-2Uxh4dRwlEv1jHfX .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-2Uxh4dRwlEv1jHfX .cluster-label text{fill:#333;}#mermaid-svg-2Uxh4dRwlEv1jHfX .cluster-label span{color:#333;}#mermaid-svg-2Uxh4dRwlEv1jHfX .cluster-label span p{background-color:transparent;}#mermaid-svg-2Uxh4dRwlEv1jHfX .label text,#mermaid-svg-2Uxh4dRwlEv1jHfX span{fill:#333;color:#333;}#mermaid-svg-2Uxh4dRwlEv1jHfX .node rect,#mermaid-svg-2Uxh4dRwlEv1jHfX .node circle,#mermaid-svg-2Uxh4dRwlEv1jHfX .node ellipse,#mermaid-svg-2Uxh4dRwlEv1jHfX .node polygon,#mermaid-svg-2Uxh4dRwlEv1jHfX .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-2Uxh4dRwlEv1jHfX .rough-node .label text,#mermaid-svg-2Uxh4dRwlEv1jHfX .node .label text,#mermaid-svg-2Uxh4dRwlEv1jHfX .image-shape .label,#mermaid-svg-2Uxh4dRwlEv1jHfX .icon-shape .label{text-anchor:middle;}#mermaid-svg-2Uxh4dRwlEv1jHfX .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-2Uxh4dRwlEv1jHfX .rough-node .label,#mermaid-svg-2Uxh4dRwlEv1jHfX .node .label,#mermaid-svg-2Uxh4dRwlEv1jHfX .image-shape .label,#mermaid-svg-2Uxh4dRwlEv1jHfX .icon-shape .label{text-align:center;}#mermaid-svg-2Uxh4dRwlEv1jHfX .node.clickable{cursor:pointer;}#mermaid-svg-2Uxh4dRwlEv1jHfX .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-2Uxh4dRwlEv1jHfX .arrowheadPath{fill:#333333;}#mermaid-svg-2Uxh4dRwlEv1jHfX .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-2Uxh4dRwlEv1jHfX .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-2Uxh4dRwlEv1jHfX .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-2Uxh4dRwlEv1jHfX .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-2Uxh4dRwlEv1jHfX .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-2Uxh4dRwlEv1jHfX .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-2Uxh4dRwlEv1jHfX .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-2Uxh4dRwlEv1jHfX .cluster text{fill:#333;}#mermaid-svg-2Uxh4dRwlEv1jHfX .cluster span{color:#333;}#mermaid-svg-2Uxh4dRwlEv1jHfX div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-2Uxh4dRwlEv1jHfX .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-2Uxh4dRwlEv1jHfX rect.text{fill:none;stroke-width:0;}#mermaid-svg-2Uxh4dRwlEv1jHfX .icon-shape,#mermaid-svg-2Uxh4dRwlEv1jHfX .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-2Uxh4dRwlEv1jHfX .icon-shape p,#mermaid-svg-2Uxh4dRwlEv1jHfX .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-2Uxh4dRwlEv1jHfX .icon-shape .label rect,#mermaid-svg-2Uxh4dRwlEv1jHfX .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-2Uxh4dRwlEv1jHfX .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-2Uxh4dRwlEv1jHfX .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-2Uxh4dRwlEv1jHfX :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
输出交互提示
键盘 stdin
scanf
变量内存数据中转站
printf
屏幕 stdout
>
scanf 负责把输入写入变量内存;printf 仅仅读取变量内存的值进行打印。两个函数互相不知道对方的存在。。
2. **二者完全可以单独使用,不强制成对**
// 只使用printf:不需要用户输入,直接输出文本
printf(“Hello C语言\\n”);
// 只使用scanf:程序等待输入,无任何提示,实际开发不推荐
int a;
scanf(“%d”, &a);3. 为什么教程示例总把两者写在一起?工程上的搭配逻辑是:printf 输出提示文字,告诉用户需要输入什么;scanf 接收键盘输入存入变量;后续再用 printf 打印变量,校验输入结果。
#include <stdio.h>
int main(void)
{
int num = 0;
printf("请输入一个整数:"); // printf输出交互提示
scanf("%d", &num); // scanf读取输入存入变量
printf("你输入的数字是:%d\\n", num); // printf读取变量输出
return 0;
}
四、初学者高频踩坑汇总
坑 1:scanf 忘记写取地址 &
int a;
scanf("%d", a); // ❌错误,没有传入内存地址,程序运行崩溃
scanf("%d", &a); // ✔正确
坑 2:给字符数组画蛇添足加上 &
char buf[20]={0};
scanf("%s", &buf); // ❌数组名本身就是首元素地址,不需要&
scanf("%s", buf); // ✔
坑3:直接写 scanf,没有 printf 提示
控制台一片空白,用户完全不知道该输入什么,交互体验极差。
坑4:占位符和数据类型不匹配scanf 中读取 double 错误写 %f;printf 打印 int 用 %f,会出现乱码随机数值。。
区分小提示:
- printf:float、double都用%f;
- scanf:float用%f,double必须用%lf。
坑5:%c 读取遗留回车换行
scanf 读取数字之后,再用 %c 读取字符,会读到缓冲区残留回车。
解决方案:格式串内 %c 前面增加空格 scanf(" %c", &ch);。
坑 6:VS 直接替换为 scanf_s
scanf_s 是 MSVC 专属,不具备跨平台可移植性,初学不要盲目使用优先用宏屏蔽警告继续使用标准 scanf。。### 坑7:使用 %s 不限制长度,数组越界
char name[11] = {0};
scanf("%s", name); // ❌输入超过10字符,内存越界,危险
scanf("%10s", name); // ✔限制最多读取10个字符
五、printf 与 scanf 核心差异对比
| 作用 | 格式化输出,把内存中的常量、变量按指定格式打印到屏幕 | 格式化输入,把键盘读到的数据按指定格式写入变量内存 |
| 数据流向 | 程序内存(变量/常量)→ printf → 屏幕(stdout) | 键盘(stdin)→ scanf → 变量内存 |
| 是否阻塞 | 不阻塞,执行到该行立即输出,无需等待键盘 | 阻塞,执行到该行暂停,等待用户输入并回车后才继续 |
| 参数是否加 & | 不加,直接传变量值(传值调用) | 普通变量必须加 &;字符数组名本身即首元素地址,不加 & |
| 返回值含义 | 返回成功输出的字符个数,出错返回负数 | 返回成功匹配读取的数据项个数,失败或读到文件末尾返回 EOF(一般为 -1) |
| %f 与 %lf 差异 | float、double 都用 %f,%lf 也可用但无区别 | float 用 %f,double 必须用 %lf,写错会读入错误数据 |
| 是否自动跳过空白字符 | 不涉及输入,无此概念 | %d、%f、%s 会自动跳过开头空白;%c 不跳过,需在格式串中写 " %c" |
要点说明:
- 二者最本质的区别是数据流动方向相反:printf 从内存流向屏幕,scanf 从键盘流向内存,中间都依赖变量内存作为数据载体,彼此之间没有直接调用关系。
- 参数写法上,printf 传的是变量的值,scanf 传的是变量的地址,这也是初学者最容易漏写 & 的根源。
- 占位符并非完全通用:%f 与 %lf 在 scanf 中必须严格区分,而 %c 对空白字符的处理也是 scanf 独有的坑点,使用时需格外留意。
五、总结



