尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

C语言入门:printf与scanf格式化输入输出全解析

C语言入门:printf与scanf格式化输入输出全解析 很多刚开始学 C 语言的朋友都会遇到同一个困惑看了几节网课、翻了几篇教程觉得语法好像都懂了但自己动手写代码时连最基本的“把数据输出到屏幕”和“从键盘读入数据”都经常出问题。尤其是printf和scanf这两个函数看起来简单真正用起来却有一堆细节格式控制符怎么写为什么scanf必须加为什么输入字符串时不需要加中文输出为什么乱码这些问题不搞清楚后面学指针、结构体、文件操作时会更加吃力。这篇文章就以零基础入门 C 语言为背景把printf和scanf完整拆开讲清楚包含语法格式、格式控制符、转义字符、常见错误、综合实战和最佳实践。无论你是刚开始接触 C 语言还是学了一段时间但基础不牢这篇文章都值得完整看一遍。1. C 语言中的输入输出是什么1.1 程序为什么需要输入输出写程序的本质是让计算机帮助我们处理数据。数据从哪来处理完的结果又送到哪去这就是输入输出要解决的问题。在初学阶段最常见的输入输出场景就是输入用户在键盘上敲入内容程序读取这些内容。输出程序把处理结果打印到屏幕上。C 语言本身并没有内置“输入输出”语句而是通过标准库函数来完成。其中使用频率最高的两个函数就是printf和scanf。它们都声明在stdio.h头文件中stdio是standard input output的缩写。有不少初学者会把“头文件”理解成一个很神秘的东西其实可以简单理解为#include stdio.h就是把 C 语言标准库中的输入输出函数声明引入到你的代码里让编译器知道printf、scanf这些函数长什么样、参数是什么。对比 Python、Java 等语言C 语言的输入输出更加贴近底层它需要程序员自己指定数据的格式。这正是 C 语言入门阶段的一个小门槛也是理解计算机数据表示的好机会。1.2 printf 和 scanf 的分工printf格式化输出把程序中的数据按照指定格式输出到标准输出设备默认是屏幕。scanf格式化输入从标准输入设备默认是键盘读取数据并按照指定格式存储到变量中。一个负责“往外写”一个负责“往里读”。两者配合就能编写出最简单的交互式程序。比如#include stdio.h int main() { int age; printf(请输入你的年龄); scanf(%d, age); printf(你的年龄是%d\n, age); return 0; }运行后程序先打印提示文字然后等待用户输入一个整数最后把输入的内容再输出到屏幕上。这里有一个很重要的现象printf中的%d是格式占位符scanf中的%d同样表示要读入一个整数但scanf在变量age前面多了一个符号。这个是很多零基础学员第一个卡住的地方后面会专门解释。1.3 为什么从 printf 和 scanf 开始学C 语言的知识体系很庞大变量、数据类型、运算符、流程控制、数组、指针、函数、结构体、文件操作……如果一上来就学指针和内存管理很容易被劝退。而printf和scanf能让你用最短的时间看到程序的反馈。你写一个printf屏幕上立刻出现文字你写一个scanf程序就能接收你输入的数据。这种“即时反馈”对初学者建立信心非常重要。几乎所有 C 语言教材和课程比如很多大学用的《C 语言程序设计》教材以及网上流传的翁恺老师 C 语言入门课程第一节课都会围绕printf展开。掌握了这两个函数你就能写出大量练习程序比如计算器、成绩统计、日期计算等从而逐步熟悉分支、循环、数组等后续语法。2. 环境准备与第一个 C 程序2.1 编译器与 IDE 选择学习 C 语言第一步是准备开发环境。C 语言源代码需要通过编译器翻译成机器码然后才能运行。常见的方案有以下几种。方案一Dev-CDev-C 是很多高校初学者使用的 IDE自带 MinGW 编译器安装简单界面直观适合刚接触编程的同学。不过它停止更新较早在 Windows 10 / Windows 11 上可能出现兼容或调试方面的小问题。方案二Visual Studio Code MinGW这是目前比较流行的组合。VS Code 本身只是一个编辑器需要额外安装 C/C 插件和 MinGW 编译器。配置稍复杂但编辑体验好扩展丰富适合愿意折腾的初学者。方案三Code::BlocksCode::Blocks 也是一个开源的 C/C IDE自带编译器版本较多跨平台支持不错。相比 VS Code它不需要手动配置太多内容开箱即用。方案四在线编译器如果暂时不想安装任何软件可以使用在线 C 语言编译器比如一些刷题网站自带的在线编译功能。这类工具适合快速验证一小段代码但不适合大规模练习。版本方面C 语言标准目前常见的有 C89/C90、C99、C11、C17 等。初学者不需要纠结编译器具体支持哪个标准只要你的代码遵循常见写法主流编译器都能正常运行。本文示例以常见 Windows GCC 环境为例重点演示代码思路和运行效果。2.2 第一个 C 程序Hello World无论使用哪个 IDE先运行一个最简单的程序验证环境是否可用。#include stdio.h int main() { printf(Hello World\n); return 0; }代码说明#include stdio.h引入标准输入输出头文件。int main()主函数程序执行的入口。一个 C 程序有且只能有一个main函数。printf(Hello World\n);调用printf输出字符串\n表示换行。return 0;返回 0 给操作系统表示程序正常结束。编译运行后屏幕上会出现Hello World如果这个程序能正常运行说明你的开发环境已经准备就绪。3. printf 函数深度讲解3.1 printf 的基本语法printf是 C 语言中最常用的输出函数它的功能是按照指定的格式把数据输出到屏幕。函数原型如下int printf(const char *format, ...);第一个参数是格式控制字符串后面的...表示可变参数也就是可以传入任意多个待输出的数据。最简单的用法是直接输出字符串printf(你好C语言\n);稍微复杂一点字符串中带格式占位符int num 42; printf(答案是%d\n, num);这里的%d就是一个格式控制符它告诉printf后面要输出一个整数并且在%d所在的位置替换成实际值。如果同时输出多个数据int a 1; int b 2; printf(%d %d %d\n, a, b, a b);输出结果1 2 3这里要注意格式字符串中有多少个格式占位符后面就需要对应多少个数据并且顺序要一一对应。printf不会帮你检查参数个数是否匹配写错了编译器可能不报错但运行结果就会很奇怪。3.2 常用格式控制符格式控制符有很多但初学者真正常用的其实就几个。格式控制符含义示例%d以十进制形式输出 int 整数printf(%d, 10);%f以小数形式输出 float 浮点数printf(%f, 3.14);%lf以小数形式输出 double 浮点数printf(%lf, 3.14);%c输出单个字符printf(%c, A);%s输出字符串printf(%s, hello);%x以十六进制形式输出整数printf(%x, 255);%o以八进制形式输出整数printf(%o, 8);%e以指数形式输出浮点数printf(%e, 123.45);%p输出指针地址printf(%p, a);%%输出一个百分号printf(%%);来看一个综合示例#include stdio.h int main() { int age 20; float height 175.5f; double weight 65.25; char gender M; char name[] ZhangSan; printf(姓名%s\n, name); printf(性别%c\n, gender); printf(年龄%d\n, age); printf(身高%.1f\n, height); printf(体重%.2lf\n, weight); return 0; }运行结果姓名ZhangSan 性别M 年龄20 身高175.5 体重65.25这里的%.1f表示小数部分保留 1 位%.2lf表示小数部分保留 2 位。%f默认情况下输出 6 位小数所以在实际打印浮点数时通常需要指定精度。3.3 宽度、精度与对齐方式printf的格式控制符支持插入宽度和标志用来控制输出的形式。基本格式为%[标志][宽度][.精度]格式字符常见写法printf(%5d\n, 42); // 宽度为5右对齐 printf(%-5d|\n, 42); // 宽度为5左对齐 printf(%05d\n, 42); // 宽度为5前面补0 printf(%.2f\n, 3.14159); // 保留两位小数 printf(%8.3f\n, 3.14159); // 宽度8保留3位小数运行结果42 42 | 00042 3.14 3.142宽度有什么用在做表格对齐、比赛输出格式控制时非常有用。比如刷题平台要求输出结果右对齐宽度一致就可以通过这个方式实现。3.4 转义字符在printf的字符串中\加特定字符可以表示一些特殊含义这些被称为转义字符。转义字符含义\n换行\t水平制表符相当于按一下 Tab\\输出一个反斜杠\\输出一个双引号\输出一个单引号\r回车符\0空字符字符串结束标志看一个例子printf(C\t语言\n); printf(他说\你好\\n); printf(路径C:\\Users\\Admin\n);运行结果C 语言 他说你好 路径C:\Users\Admin初学者最容易犯的错误是在字符串里直接写\导致编译器把它当成转义字符。比如printf(C:\Users);编译时\U会被当成一个未知转义序列造成警告或错误。正确写法是printf(C:\\Users);。3.5 printf 常见误区和中文乱码误区一printf字符串中出现中文乱码这是 Windows 环境下非常常见的问题。C 语言源文件默认编码可能是 UTF-8而 Windows 控制台默认编码可能是 GBK导致中文字符输出乱码。解决方法在printf的字符串中避免中文改用英文提示。修改源文件编码为 GBK。在 Windows 代码开头添加以下代码把控制台代码页设置为 UTF-8#include stdio.h #include windows.h int main() { SetConsoleOutputCP(CP_UTF8); printf(你好C语言\n); return 0; }注意windows.h是 Windows 平台专用头文件Linux/macOS 下无法使用。误区二格式串中写了\n但输出没有换行可能是把\n写成了/n或者写成了n\。误区三printf中格式串数量与参数数量不匹配printf(%d %d, a); // 错误%d 有两个参数只有一个这种代码编译时可能只有警告运行时输出的第二个值是不可预测的内存数据。4. scanf 函数深度讲解4.1 scanf 的基本语法scanf的作用与printf相反用于从键盘读取数据。函数原型int scanf(const char *format, ...);最简单的用法int num; scanf(%d, num);这里需要特别强调的作用。是取地址运算符num表示变量num在内存中的地址。为什么scanf必须传地址因为scanf要把键盘读入的值写入变量它需要通过地址找到变量在内存中的位置。如果直接写scanf(%d, num);实际上是把num的当前值比如 0当成地址去写入程序运行时很可能会崩溃。这是一个非常经典的学习难点。建议刚入门时先强制记住scanf读入基本类型变量必须在变量前加。4.2 一次读入多个数据scanf能同时读入多个数据用空格、Tab 或换行符隔开即可。int a, b; scanf(%d%d, a, b);用户输入10 20程序得到a 10b 20。也可以写成分隔符形式scanf(%d,%d, a, b);这时用户必须输入10,20也就是说scanf格式串中的普通字符不是摆设如果写了逗号用户在输入时也必须输入逗号。初学者经常在这一步出错格式串写了逗号输入时却用空格分隔导致第二个变量读不到值。建议初学阶段使用scanf(%d%d, a, b);这种写法输入时用空格分隔即可简单不容易出错。4.3 scanf 读入不同类型的数据int age; float height; double weight; char gender; char name[50]; scanf(%d, age); scanf(%f, height); scanf(%lf, weight); scanf( %c, gender); scanf(%s, name);这里有两个细节需要留意。细节一%f与%lfscanf中float类型使用%fdouble类型使用%lf。这一点与printf不同。printf中由于默认参数提升float会转换成double所以printf用%f或%lf输出double一般没问题。但scanf必须严格匹配类型。细节二读取字符前的空格如果前面已经用scanf输入过整数或浮点数紧接着输入字符可能会遇到字符变量读不到值的情况。这是因为上一次输入后缓冲区中还残留一个换行符scanf(%c, gender);会把换行符读进去。解决办法是在%c前加一个空格scanf( %c, gender);这个空格会告诉scanf跳过输入流中的空白字符包括空格、Tab 和换行符。细节三字符串不需要用scanf读取字符串时数组名本身就代表数组首地址所以不需要加。如果写scanf(%s, name);虽然某些编译器不报错但语义上是不正确的应该避免。4.4 scanf 的返回值scanf是有返回值的它返回成功读取并赋值的参数个数。比如int a, b; int ret scanf(%d%d, a, b);如果用户输入了两个有效整数ret等于 2如果只成功读取了一个ret等于 1如果没有读取到任何数据ret等于 0如果输入格式不匹配可能返回 EOF。利用返回值可以判断用户输入是否有效这在写健壮程序时非常有用。#include stdio.h int main() { int num; printf(请输入一个整数); if (scanf(%d, num) 1) { printf(成功读入%d\n, num); } else { printf(输入无效不是一个整数\n); } return 0; }4.5 scanf 与缓冲区scanf读取数据时数据并不是直接从键盘进入变量而是先进入内存中的缓冲区scanf再从缓冲区读取。理解缓冲区能帮助你解决很多输入相关的疑难问题。常见的场景是混合使用scanf和getchar时getchar读到了换行符而不是预期字符。举例#include stdio.h int main() { int n; char ch; printf(请输入一个整数); scanf(%d, n); printf(请输入一个字符); scanf(%c, ch); printf(整数 %d字符 [%c]\n, n, ch); return 0; }运行效果请输入一个整数10 请输入一个字符整数 10字符 [ ]你还没输入字符程序就结束了而且ch读到了一个换行符。原因是第一次输入10后按下的回车键换行符留在了缓冲区中第二次scanf(%c, ch)直接把它读走了。解决办法前面已经提到在%c前加空格或者用getchar()清理缓冲区。scanf( %c, ch);5. 完整实战案例学生信息登记程序用前面讲的printf和scanf编写一个完整的学生信息登记程序。这个程序能读取姓名、学号、年龄和成绩然后格式化输出。5.1 需求分析程序功能提示用户输入姓名、学号、年龄、C 语言成绩。读取输入。按照指定格式输出。涉及的知识点字符串数组存储姓名和学号。int存储年龄。float存储 C 语言成绩。printf格式化输出。5.2 代码实现#include stdio.h int main() { char name[30]; char id[20]; int age; float score; printf(请输入姓名); scanf(%s, name); printf(请输入学号); scanf(%s, id); printf(请输入年龄); scanf(%d, age); printf(请输入C语言成绩); scanf(%f, score); printf(\n\n); printf(学生信息登记表\n); printf(姓名%s\n, name); printf(学号%s\n, id); printf(年龄%d\n, age); printf(C语言成绩%.1f\n, score); printf(\n); return 0; }5.3 运行与验证编译运行后依次输入数据请输入姓名Zhangsan 请输入学号2025001 请输入年龄19 请输入C语言成绩88.5输出结果 学生信息登记表 姓名Zhangsan 学号2025001 年龄19 C语言成绩88.5 程序运行正常说明printf和scanf的基本用法已经掌握了。5.4 功能扩展可以在此基础上增加一个计算功能比如根据成绩判断等级if (score 90) { printf(等级优秀\n); } else if (score 80) { printf(等级良好\n); } else if (score 70) { printf(等级中等\n); } else if (score 60) { printf(等级及格\n); } else { printf(等级不及格\n); }这样就把输入输出、分支判断串联起来了也为后面学习流程控制做了准备。6. 常见问题与排查思路6.1 printf 输出中文乱码问题现象常见原因解决思路中文字符显示为乱码源文件编码与控制台编码不一致修改源文件编码为 UTF-8 或 GBK或在 Windows 下调用SetConsoleOutputCP(CP_UTF8);中文字符变成问号编辑器保存编码与控制台解码不一致在编辑器中重新设置文件编码后保存代码里中文正常编译后就乱编译器默认字符集问题在 GCC 编译时添加-finput-charsetUTF-8 -fexec-charsetUTF-8等参数6.2 scanf 执行后变量还是没有值问题现象常见原因解决思路输出一个很大的随机数忘记加检查scanf中基本类型变量前是否加了输入后程序直接结束缓冲区残留换行符在%c前加空格或使用getchar()输入字符串出错给字符指针分配了无效空间使用字符数组并确保空间足够6.3 格式串不匹配问题现象常见原因解决思路输入格式稍微不同就读取失败格式串中写了普通字符输入时未匹配保持scanf格式串简洁多用空白符分隔float和double混用使用了错误的格式控制符记住scanf中float用%fdouble用%lf读入多个数据时第二个数据错误输入分隔符与格式串不一致统一使用空格分隔输入6.4 编译报错分析报错一undefined reference to main链接错误表示程序缺少主函数main或main拼写错误。检查代码中是否包含int main() { ... }报错二stray \xxx in program源文件中有中文全角字符或其他不可见字符。删除对应位置的非法字符重新输入。报错三expected ; before printf上一行缺少分号。检查printf之前的语句是否以分号结尾。6.5 排查清单如果程序运行结果不符合预期可以按以下顺序自查检查传入printf/scanf的参数数量是否与格式控制符数量一致。检查scanf中普通变量是否加了字符串数组是否没加。检查float和double是否使用了正确的格式控制符。检查格式串中的普通字符是否和输入内容匹配。检查是否有多余的换行符残留在缓冲区中。检查中文输入输出是否存在编码问题。7. 最佳实践与工程建议7.1 给用户明确的输入提示写程序时不要让用户面对一个光秃秃的等待输入状态。在scanf前用printf明确提示printf(请输入一个整数); scanf(%d, num);这样用户体验更好调试时也更清楚程序卡在哪一步。7.2 检查输入是否有效在生产环境或在线评测环境中简单的scanf可能因为输入不合法而出现非预期行为。推荐在读取后检查返回值int num; if (scanf(%d, num) ! 1) { printf(输入格式错误请重新输入\n); return 1; }7.3 注意缓冲区清理在需要读取字符或字符串时如果之前已经用scanf读取过数值类型建议在%c前加空格或者使用循环把缓冲区中的换行符读完int c; while ((c getchar()) ! \n c ! EOF) { // 清空缓冲区 }不过这种写法初学者理解起来有一定难度建议先把scanf( %c, ch)的用法掌握后续再深入了解缓冲区机制。7.4 尽量使用安全的输入函数scanf(%s, name)有一个安全隐患如果用户输入的内容超过了name数组的长度会越界写入内存导致程序崩溃或被攻击。在支持scanf_s的编译环境中建议使用scanf_s(%s, name, sizeof(name));不过scanf_s并不是标准 C 函数在 Linux 环境下可能不可用。要养成“输入长度限制”的意识后续学习字符串和指针时可以进一步优化。7.5 命名规范变量名尽量有意义不要总是a、b、c。比如年龄用age成绩用score姓名用name。代码是给人看的可读性很重要。7.6 分段测试写复杂程序时不要等全部代码写完再运行。每写完一个功能模块立刻编译运行看看输出是否符合预期这样排错会容易很多。8. 总结与下一步学习路线通过这篇文章你掌握了printf和scanf的核心用法包括格式控制符、转义字符、宽度精度、缓冲区问题、常见错误排查方法并且完成了一个包含输入输出和简单判断的学生信息登记程序。这些知识点虽然基础但非常重要因为几乎所有 C 语言程序都离不开输入输出。接下来可以按以下顺序继续学习分支结构if、if-else、switch让程序拥有判断能力。循环结构while、do-while、for让程序能够重复执行任务。数组与字符串用数组批量存储数据处理字符串函数。函数把代码封装成可复用的函数减少重复代码。指针C 语言的精髓理解内存地址和间接访问。结构体与文件操作组织复杂数据实现数据持久化。如果你在刷题或学习中遇到了其他输入输出相关的奇怪问题建议先把程序简化到最小复现版本再配合格式化输出逐行调试。把printf当作调试工具在可疑位置打印变量值往往能很快定位问题。学习 C 语言没有捷径多写多练是唯一的办法。建议每天保持至少一小时的手写代码时间亲手敲一遍不要复制粘贴这样才能真正把语法知识转化为自己的编程能力。如果这篇文章对你有帮助可以收藏备用后续我会继续更新数组、指针、文件操作等 C 语言进阶内容。
返回列表