一、scanf 介绍scanf是 C 语言标准库stdio.h中一个非常重要的输入函数它的名字来源于“scan formatted”格式化扫描示例代码int main() { int a, b; printf(请输入两个数字); // 让用户自己随便输入 scanf(%d %d, a, b); // 是取地址操作符必须要有 printf(结果是%d\n, a b); return 0; } // 请输入两个数字1 2 // Enter // 结果是3注此时运行可能会弹出“This function or variable may be unsafe ……”警告。在 Visual Studio 中可以通过以下两种方式消除警告在scanf后加_s即使用scanf_s。在文件第一行添加#define _CRT_SECURE_NO_WARNINGS。为什么不建议用scanf_s这是 VS2022 的报错它认为scanf确实有不安全的地方但是scanf_s是 VS2022 自己提供的不是 C 语言标准库提供的。如果使用它代码只能在 VS2022 等微软编译器上编译其他编译器如 GCC、Clang无法编译代码就失去了跨平台性。二、基本用法scanf()函数用于获取用户的键盘输入。程序运行到这个语句时会停下来 → 用户从键盘输入 → 按下回车 → 处理输入 → 存入变量。1. 头文件scanf()语法跟printf()类似头文件为stdio.h。2. 基本语法int i 0; scanf(%d, i);%d告诉程序用户输入类型。i其余参数存放用户输入到变量。占位符 变量数注意变量前面必须加上运算符像字符串变量这种指针变量除外因为scanf()传递的不是值而是地址即将变量i的地址指向用户输入值。3. 一次读取多个变量可以一次将键盘输入读入多个变量scanf(%d %d %f %f, i, j, x, y);类型一一对应。示例代码int main() { int i 0; int j 0; float x 0.0; float y 0.0; scanf(%d %d %f %f, i, j, x, y); printf(i%d\n, i); printf(j%d\n, j); printf(x%f\n, x); printf(y%f\n, y); return 0; }输入示例1 -20 3.4 -4.0e3数字间有空格-4.0e3 -4.0×10³科学计数法输出结果i1 j-20 x3.400000 y-4000.0000004. 空白字符等会被过滤scanf()处理数值占位符时会自动过滤空白字符包括空格、制表符、换行符等。换行符 输入回车 Enter 键不是输入\n制表符 Tab 键。如上代码输入分行写1 -20 3.4 -4.0e3运行结果和一行输入完全一样。第一个%d读完匹配完成就会从第二个占位符开始解读。5. 读取原理示例int main() { int x 0; float y 0.0; scanf(%d, x); printf(%d\n, x); scanf(%f, y); printf(%f\n, y); return 0; }输入示例-13.45e12# 0分析未按下回车字符还在缓存按下后按照占位符的顺序对缓存进行解读。%d只能读到-13存入x。%f从剩下字符开始读取即.45e12匹配成功存入y。输出x-13 y4497994880.000000浮点有精度内存可能无法精确保存上述代码等价写法int main() { int x 0; float y 0.0; scanf(%d%f, x, y); printf(%d\n, x); printf(%f\n, y); return 0; }三、scanf 的返回值1. 返回值含义scanf()的返回值是一个整数表示成功读取的变量个数如果没有读取任何项或者匹配失败则返回0如果在成功读取任何数据之前发生读取错误或者读到文件末尾则返回常量EOF-1。补充EOF end of file文件结束标志值是-1。示例代码int main() { int a 0; int b 0; float f 0.0f; int r scanf(%d %d %f, a, b, f); printf(a%d b%d f%f\n, a, b, f); printf(r %d\n, r); return 0; }五种输入情况输入100 200 5.5a100 b200 f5.500000r3输入100 200 9a100 b200 f0.000000r2输入100 wa100 b0 f0.000000r1输入wa0 b0 f0.000000r0按下CtrlZ^Zscanf读取报错VS 需要按三次CtrlZDevC 一次即可输出r-1a0 b0 f0.000000r-12. 竞赛常用判断写法反推int main() { int a 0; int b 0; float f 0.0f; int r scanf(%d %d %f, a, b, f); if (r 3) printf(a%d b%d f%f\n, a, b, f); else { printf(读取到的数据可能存在问题\n); printf(a%d b%d f%f\n, a, b, f); } printf(r%d\n, r); return 0; }3. 不接收返回值的情况代码中没有写类似于int r scanf(%d %d %f, a, b, f);时编译器会报警告原因scanf自带返回值编译器希望你接收不接收就弹出警告警告可忽略。四、占位符1. scanf() 与 printf() 占位符差异printf 中float%fdouble%f/%lflong double%Lfscanf 中float%fdouble%lf2. %[]字符集合匹配方括号中指定一组匹配字符例如%[0-9]遇到不在集合中的字符匹配停止。3. 空白字符处理除%c以外其余占位符会自动忽略前置空白字符%c不忽略空白符总是返回当前第一个字符无论该字符是否为空格。示例①int main() { int a 0; scanf(%d, a); printf(%d\n, a); return 0; }输入多个空格再输100正常输出100。原因%d自动跳过开头空白连续读取一串数字直到遇到非数字字符停止。示例②int main() { char ch 0; scanf(%c, ch); printf(%c----\n, ch); return 0; }输入 空格X运行出(空格)----原因%c只抓取一个字符空格会被直接读取换行、空格都算有效字符。如果想在%c强制跳过字符前空白字符写成scanf( %c, ch);%c前面加空格可跳过多个空白。4. %s 读取字符串①printf(%s,abcdef);打印字符串遇到结束标志\0停止。② 读取字符串代码示例int main() { char arr[20]; // char字符数组20个char元素 scanf(%s, arr); // 直接填数组名数组名本身是地址不用加 printf(%s\n, arr); return 0; }输入abcdef输出abcdef。%s会跳过前置空白字符从第一个非空白字符读起再次遇到空白字符空格、换行、制表符停止。一次只能读取单个单词搭配多个%s读取多个单词。scanf()不适合读取包含空格的字符串、书名、歌名。int main() { char arr1[20]; char arr2[20]; scanf(%s %s, arr1, arr2); printf(%s\n, arr1); printf(%s\n, arr2); return 0; }输入abc defarr1存abcarr2存def末尾自动补充\0。5. scanf 不安全的原因及解决方法不安全原因scanf向字符数组输入字符串时不会检测字符串是否超过数组长度极易数组越界。解决写成%[m]sm为整数代表读取字符串最大长度多余字符丢弃。示例int main() { char arr[5]; scanf(%4s, arr); // 预留1位存\0最多读4个字符 printf(%s\n, arr); return 0; }输入abcdefgic仅读取abcd存入数组末尾自动加\0。注即使写%[m]sVS 开头仍要写#define _CRT_SECURE_NO_WARNINGS微软不认可标准scanf强制安全检查。6. 补充不搭配多个“%s”使用%[^\n]s读取带空格字符串int main() { char arr[20]; scanf(%[^\n]s, arr); printf(%s\n, arr); return 0; }五、赋值忽略符1. 输入格式必须与代码格式一致示例代码int main() { int a 0; int b 0; scanf(%d %d, a, b); printf(a%d b%d\n, a, b); return 0; }输入示例13 4结果a3 b4输入示例2a34解析a在读整数时把3和4读完遇到不属于整数的字符才停下最终a34b0输入示例33,4解析a读取整数读到逗号停下a3b从逗号开始读取逗号不是数字读取失败。结果a3 b0结论输入数据的格式必须和代码scanf内格式完全一致才能得到正确数据。2. 格式字符串中的普通字符必须匹配示例代码int main() { int a 0; int b 0; scanf(%d,%d, a, b); printf(a%d b%d\n, a, b); return 0; }输入3 , 4结果a3 b4笔记代码格式%d , %d输入里所有符号要一一对应。3. 日期格式匹配示例int main() { int year 0; int month 0; int day 0; scanf(%d-%d-%d, year, month, day); printf(%d %d %d\n, year, month, day); return 0; }输入12025 4 7结果2025 0 0输入22025-4-7结果2025 4 74. 赋值忽略符 *作用规避输入格式不匹配导致读取失败scanf提供*赋值忽略符。int main() { int year 0; int month 0; int day 0; scanf(%d%*c%d%*c%d, year, month, day); printf(%d %d %d\n, year, month, day); return 0; }输入12025-4-7→ 输出2025 4 7输入22025/4/7→ 输出2025 4 7输入32026*5-24→ 输出2026 5 24注释解析%*c*代表当前占位符不对应变量读取到的字符直接丢弃不存入任何变量%c用来吃掉中间任意分隔字符。六. 总结scanf是 C 语言中读取用户输入的基础函数掌握它需要注意以下几点格式要匹配输入数据的格式必须和scanf中的格式字符串完全一致否则会读取失败。地址不能忘除了字符串数组其他变量前都要加取地址符。空白字符处理数值占位符会自动跳过空格、Tab 和换行但%c不会。字符串要小心用%s读取字符串时容易数组越界最好指定宽度如%4s。检查返回值通过返回值可以知道成功读取了几个变量避免输入错误。跨平台注意VS 的scanf_s不是标准 C用#define _CRT_SECURE_NO_WARNINGS消除警告更通用。后续可能还会补充其他相关知识点感谢