C语言学习笔记-初阶(13)scanf介绍
当我们有了变量,我们需要给变量输入值就可以使用 scanf 函数,如果需要将变量的值输出在屏幕上的时候可以使用 printf 函数,下面看⼀个例子:
#include <stdio.h>
int main()
{int score = 0;printf("请输⼊成绩:");scanf("%d", &score);printf("成绩是:%d\n", score);return 0;
}

接下来我们介绍一下scanf函数。
1.基本用法
scanf() 函数用于读取用户的键盘输入。
程序运行到这个语句时,会停下来,等待用户从键盘输入。
用户输入数据、按下回车键后, scanf() 就会处理用户的输入,将其存入变量——对应的存储空间(地址)。
它的原型定义在头文件 stdio.h 。
scanf() 的语法跟 printf() 类似。
scanf("%d", &i); 它的第一个参数是一个格式字符串,里面会放置占位符(与 printf() 的占位符基本⼀致),占位符会告诉编译器如何解读用户的输入,需要提取的数据是什么类型。
这是因为 C 语言的数据都是有类型的, scanf() 必须提前知道用户输入的数据类型,才能处理数 据。
它的其余参数就是存放用户输入的变量,格式字符串黎明有多少个占位符,就有多少个变量。
上面示例中, scanf() 的第一个参数 %d ,表示用户输入的应该是⼀个整数。 %d 就是一个占位 符, % 是占位符的标志, d 表示整数。第二个参数 &i 表示,将用户从键盘输入的整数存入变量i。
注意:变量前面必须加上 & 运算符——取地址运算符(指针变量除外),因为 scanf() 传递的不是值,而是地址, 即将变量 i 的地址指向用户输入的值。 如果这里的变量是指针变量(比如字符串变量),那就不用加 & 运算符。
下,面是一次将键盘输入读入多个变量的例子。
scanf("%d%d%f%f", &i, &j, &x, &y); 上面示例中,格式字符串 %d%d%f%f ,表示用户输入的前两个是整数,后两个是浮点数,比如 1 -20 3.4 -4.0e3 。这四个值依次放入 i 、 j 、 x 、 y 四个变量。 scanf() 处理数值占位符时,会自动过滤空白字符,包括空格、制表符、换行符等。 所以,用户输入的数据之间,有一个或多个空格不影响 scanf() 解读数据。

另外,用户使用回车键,将输入分成几行,也不影响解读。
1
-20
3.4
-4.0e3 上面示例中,用户分成四行输入,得到的结果与一行输入是完全⼀样的。每次按下回车键以后, scanf() 就会开始解读,如果第一行匹配第一个占位符,那么下次按下回车键时,就会从第二个占 位符开始解读。 scanf() 处理用户输入的原理是,用户的输入先放入缓存,等到按下回车键后,按照占位符对缓存进行解读。 解读用户输入时,会从上一次解读遗留的第一个字符开始,直到读完缓存,或者遇到第一个不符合条件的字符为止。

#include <stdio.h>
int main()
{int x;float y;// ⽤⼾输⼊ " -13.45e12# 0"scanf("%d", &x);printf("%d\n", x);scanf("%f", &y);printf("%f\n", y);return 0;
} 上面示例中, scanf() 读取用户输入时, %d 占位符会忽略起首的空格,从 - 处开始获取数据,读 取到 -13 停下来,因为后面的 . 不属于整数的有效字符。这就是说,占位符 %d 会读到 -13 。第二次调用 scanf() 时,就会从上一次停止解读的地方,继续往下读取。这一次读取的首字符是 . ,由于对应的占位符是 %f ,会读取到 .45e12 ,这是采用科学计数法的浮点数格式。后面的 # 不属于浮点数的有效字符,所以会停在这里。

由于 scanf() 可以连续处理多个占位符,所以上面的例子也可以写成下面这样。
#include <stdio.h>
int main()
{int x;float y;// ⽤⼾输⼊ " -13.45e12# 0"scanf("%d%f", &x, &y);return 0;
}
2.scanf的返回值
scanf() 的返回值是⼀个整数,表示成功读取的变量个数。
如果没有读取任何项,或者匹配失败,则返回 0 。
如果在成功读取任何数据之前,发生了读取错误或者遇到读取到文件结尾,则返回常量 EOF(#define EOF -1,敲出EOF转到定义,或者VS里面鼠标放到EOF上都能发现EOF是-1)。
#include <stdio.h>
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;
} 
3.占位符
scanf() 常用的占位符如下,与 printf() 的占位符基本一致。



上面所有占位符之中,除了 %c 以外,都会自动忽略起首的空白字符。 %c 不忽略空白字符,总是返回当前第⼀个字符,无论该字符是否为空格。
如果要强制跳过字符前的空白字符,可以写成 scanf(" %c", &ch) ,即 %c 前加上⼀个空格,表示跳过零个或多个空白字符。
下面要特别说一下占位符 %s ,它其实不能简单地等同于字符串。%s的规则是,从当前第⼀个非空白字符开始读起,直到遇到空白字符(即空格、换行符、制表符等)为止。

因为 %s 不会包含空白字符,所以无法用来读取多个单词,除非多个 %s 一起使用。这也意味着, scanf() 不适合读取可能包含空格的字符串,比如书名或歌曲名。另外, scanf() 遇到 %s 占位 符,会在字符串变量末尾存储⼀个空字符 \0 。
scanf() 将字符串读入字符数组时,不会检测字符串是否超过了数组长度。所以,储存字符串时, 很可能会超过数组的边界,导致预想不到的结果。为了防止这种情况,使用 %s 占位符时,应该指定读入字符串的最长长度,即写成 %[m]s ,其中的 [m] 是⼀个整数,表示读取字符串的最大长度,后面的字符将被丢弃。
#include <stdio.h>
int main()
{char name[11];scanf("%10s", name);return 0;
} 上面示例中, name 是⼀个长度为11的字符数组, scanf() 的占位符 %10s 表示最多读取用户输入的10个字符,后面的字符将被丢弃,这样就不会有数组溢出的风险了。

程序崩溃了。

原因:因为scanf()函数的第二个参数“&变量”,这是一个地址——对应一定大小的内存空间,scanf()函数不会考虑目标内存空间能否存得下输入的数据,它只会管读入数据直到结束标志(空白字符——即空格、换行符、制表符等),然后将读入的数据放到目标内存空间,而不管目标内存空间能否放得下读入的数据。
而微软的scanf_s可以给第3个参数——指定读取数据的字符个数,相对更安全。
(不建议使用scanf_s——>代码失去可移植性)

而且使用scanf_s不报错了,但仍然有可能程序崩溃(使用了scanf_s但是不给第3个参数)。
建议:#define _CRT_SECURE_NO_WARNINGS 1(宏定义常量)
——只有VS上才有这个报错,才需要添加这一行代码。
#define _CRT_SECURE_NO_WARNINGS 也可以,但是_CRT_SECURE_NO_WARNINGS宏定义常量不完整,不能使用_CRT_SECURE_NO_WARNINGS,把它当宏常量使用会报错。
注意:scanf的规范使用

4.赋值忽略符
有时,用户的输入可能不符合预定的格式。
#include <stdio.h>
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;
} 上面示例中,如果用户输入 2020-01-01 ,就会正确解读出年、月、日。问题是用户可能输入其他 格式,比如 2020/01/01 ,这种情况下, scanf() 解析数据就会失败。 为了避免这种情况, scanf() 提供了⼀个赋值忽略符(assignment suppression character) * 。 只要把 * 加在任何占位符的百分号后面,该占位符就不会返回值,解析后将被丢弃。
#include <stdio.h>
int main()
{int year = 0;int month = 0;int day = 0;scanf("%d%*c%d%*c%d", &year, &month, &day);return 0;
} 上面示例中, %*c 就是在占位符的百分号后面,加入了赋值忽略符 * ,表示这个占位符没有对应的变量,解读后不必返回。读一个整型,读一个字符(不需要),再读一个整型,再读一个字符(不需要),再读一个整型,再读一个字符(不需要)。
相关文章:
C语言学习笔记-初阶(13)scanf介绍
当我们有了变量,我们需要给变量输入值就可以使用 scanf 函数,如果需要将变量的值输出在屏幕上的时候可以使用 printf 函数,下面看⼀个例子: #include <stdio.h> int main() {int score 0;printf("请输⼊成绩:")…...
Android MMKV集成指南
首先简单介绍一下MMKV当下Android Studio最版本及Gradle8.7 MMKV集成根据官方文档重新对mmkv重新包了一次(便于开发)总结首先简单介绍一下MMKV MMKV 是腾讯开源的一款专为移动端设计的高性能键值存储组件,旨在替代传统的 SharedPreferences 和 SQLite,尤其在频繁读写和数据…...
如何让传统制造企业从0到1实现数字化突破?
随着全球制造业不断向智能化、数字化转型,传统制造企业面临着前所未有的机遇与挑战。数字化转型不仅是技术的革新,更是管理、文化、业务流程等全方位的变革。从零开始,如何带领一家传统制造企业走向数字化突破,是许多企业领导者面…...
Centos7安装Python3.13
Centos7.5环境上安装Python3.13 # 安装依赖 yum install -y zlib zlib-devel openssl-devel sqlite-devel bzip2-devel libffi libffi-devel gcc gcc-c mkdir -p /opt/software cd /opt/software # openssl高版本安装 # 如果 Centos7 系统默认自带的 openssl 版本太低…...
C++之string类的模拟实现(超详细)
们学习东西,先学习如果使用它,然后再学习如何实现它 文章目录 目录 1. 命名空间以及头文件 2.string类的成员变量 3.string类的成员函数 3.1 构造函数 3.2 析构函数 3.3 拷贝构造函数 3.4 赋值运算符重载 3.5 c_str函数 3.6 size函数 3.7 clea…...
【HarmonyOS Next】鸿蒙应用公钥和证书MD5指纹的获取
【HarmonyOS Next】鸿蒙应用公钥和证书MD5指纹的获取 一、问题背景 政府的icp备案时,或者某些三方SDK以来的管理后台,都需要配置鸿蒙应用的公钥和证书MD5指纹 二、解决方案 专有名词解释: 华为AppGallery Connect简称 AGC平台࿰…...
【原创工具】同文件夹PDF文件合并 By怜渠客
【原创工具】同文件夹PDF文件合并 By怜渠客 原贴:可批量合并多个文件夹内的pdf工具 - 吾爱破解 - 52pojie.cn 他这个存在一些问题,并非是软件内自主实现的PDF合并,而是调用的pdftk这一工具,但楼主并没有提供pdftk,而…...
【红队利器】单文件一键结束火绒6.0
关于我们 4SecNet 团队专注于网络安全攻防研究,目前团队成员分布在国内多家顶级安全厂商的核心部门,包括安全研究领域、攻防实验室等,汇聚了行业内的顶尖技术力量。团队在病毒木马逆向分析、APT 追踪、破解技术、漏洞分析、红队工具开发等多个…...
Linux中文件目录类指令
1、pwd指令 基本语法:pwd 功能:显示当前工作目录的绝对路径 1.相对路径访问和绝对路径访问 当前处于home目录下,访问a.txt文件 相对路径访问:kim/better/a.txt,从当前位置开始定位 绝对路径访问:/home…...
vue2项目打包后js文件过大, 首次加载缓慢
vue2项目打包后js文件过大, 首次加载缓慢 安装插件 npm i compression-webpack-plugin6.1.1 -D配置vue.config.js const CompressionWebpackPlugin require(compression-webpack-plugin)module.exports {configureWebpack: {plugins:[new CompressionWebpackPlugin({filen…...
【DeepSeek】-macOS本地终端部署后运行DeepSeek如何分析图片
【DeepSeek】-macOS本地终端部署后运行DeepSeek如何分析图片 根据您的需求,目前需要了解以下几个关键点及分步解决方案: --- 一、现状分析 1. Ollama 的限制: - 目前Ollama主要面向文本大模型,原生不支持直接上传/处理图片 …...
开源模型应用落地-LangChain实用小技巧-获取token消耗(五)
一、前言 在当今的自然语言处理领域,LangChain 框架因其强大的功能和灵活性而备受关注。掌握一些实用的小技巧,能够让您在使用 LangChain 框架时更加得心应手,从而更高效地开发出优质的自然语言处理应用。 计算 Token 消耗对有效管理和优化语…...
mfy学习笔记
创建表并导入数据 CREATE TABLE sales (id INT,salesperson STRING,region STRING,sales_amount INT,sale_date DATE );INSERT INTO sales (id, salesperson, region, sales_amount, sale_date) VALUES (1, Alice, North, 1000, 2023-01-01), (2, Bob, South, 1500, 2023-01-0…...
LangChain大模型应用开发:LangGraph快速构建Agent工作流应用
介绍 大家好,博主又来给大家分享知识了。今天给大家分享的内容是使用LangChain进行大规模应用开发中的LangGraph快速构建Agent工作流应用。 通过对前几次对LangChain的技术分享。我们知道LangChain作为一个强大的工具集,为开发者们提供了丰富的资源和便…...
鸿蒙Next-方法装饰器以及防抖方法注解实现
以下是关于 鸿蒙Next(HarmonyOS NEXT)中 MethodDecorator 的详细介绍及使用指南,结合了多个技术来源的实践总结: 一、MethodDecorator 的概念与作用 MethodDecorator 是鸿蒙Next框架中用于装饰类方法的装饰器,属于 Ark…...
神经网络发展简史:从感知机到通用智能的进化之路
引言 神经网络作为人工智能的核心技术,其发展历程堪称一场人类对生物大脑的致敬与超越。本文将用"模型进化"的视角,梳理神经网络发展的五大关键阶段,结合具象化比喻和经典案例,为读者呈现一幅清晰的AI算法发展图谱。 一…...
计算机网络:应用层 —— 电子邮件
文章目录 电子邮件的起源与发展电子邮件的组成电子邮件协议邮件发送和接收过程邮件发送协议SMTP协议多用途因特网邮件扩展MIME 电子邮件的信息格式 邮件读取协议邮局协议POP因特网邮件访问协议IMAP 基于万维网的电子邮件 电子邮件(E-mail)是因特网上最早…...
zyNo.26
[GXYCTF2019]Ping Ping Ping(Web) 传/?ip1有ping回显,说明后端可能通过php参数接受了ip参数,并且拼接到了最终执行的命令里形成了ping -c 3$ip,这样可能存在一个命令注入漏洞 要判断是否符合 ping -c 3$ip …...
结构型模式 - 适配器模式 (Adapter Pattern)
结构型模式 - 适配器模式 (Adapter Pattern) 适配器模式是一种结构型设计模式,它允许将一个类的接口转换成客户希望的另一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。 类适配器,适用于要适配的类是一个接口…...
Linux 驱动模块稳定性检测框架 - 概要设计
Linux 驱动模块稳定性检测框架 1. 设计目标 实时监控:检测 Linux 设备驱动模块运行状态,及时发现异常。数据采集:通过内核打点,收集关键运行数据,分析模块稳定性。异常检测:分析错误日志、性能指标&#…...
ui设计公司兰亭妙微分享:科研单位UI界面设计
科研单位的UI界面设计是一项至关重要的任务,它不仅关乎科研工作的效率,还直接影响到科研人员的用户体验。以下是对科研单位UI界面设计的详细分析: 一、设计目标 科研单位的UI界面设计旨在提升科研工作的效率与便捷性,同时确保科…...
c# —— StringBuilder 类
StringBuilder 类是 C# 和其他一些基于 .NET Framework 的编程语言中的一个类,它位于 System.Text 命名空间下。StringBuilder 类表示一个可变的字符序列,它是为了提供一种比直接使用字符串连接操作更加高效的方式来构建或修改字符串。 与 C# 中的 stri…...
OpenGL ES -> GLSurfaceView绘制点、线、三角形、正方形、圆(顶点法绘制)
XML文件 <?xml version"1.0" encoding"utf-8"?> <com.example.myapplication.MyGLSurfaceViewxmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"…...
React + TypeScript 全栈开发最佳实践
React TypeScript 全栈开发最佳实践 一、环境搭建与项目初始化 node.js和npm的安装请参考我的文章。 1.1 脚手架选择与工程创建 # 使用Vite 5.x创建ReactTS项目(2025年主流方案) npx create-vitelatest my-app --template react-ts cd my-app npm in…...
AndroidAOSP定制隐藏某个应用的图标
AndroidAOSP定制隐藏某个应用的图标 1.前言: 之前在做AOSP定制的时候需要隐藏某些App的图标,或者默认不显示某个定制的App图标,这样可以让用户感觉不到已经安装了某个App,或者在做系统定制的时候需要修改桌面icon,有些系统的App图标默认不需要显示&…...
最小化重投影误差求解PnP
问题描述 已知n个空间点 P i [ x i , y i , z i ] T P_i[x_i,y_i,z_i]^T Pi[xi,yi,zi]T,其投影的像素坐标 p i [ u i , v i ] T p_i[u_i,v_i]^T pi[ui,vi]T求相机的位姿R,T。 问题分析 根据相机模型,像素点和空间点的位置…...
玩转Docker | 使用Docker部署IT-tools工具箱
玩转Docker | 使用Docker部署IT-tools工具箱 前言一、 IT-tools介绍简介主要特点二、系统要求环境要求环境检查Docker版本检查检查操作系统版本三、部署IT-tools服务下载镜像创建容器检查容器状态检查服务端口安全设置四、访问IT-tools应用五、测试与使用六、总结前言 在信息技…...
unity学习52:UI的最基础组件 rect transform,锚点anchor,支点/轴心点 pivot
目录 1 image 图像:最简单的UI 1.1 图像的基本属性 1.2 rect transform 1.3 image的component: 精灵 → 图片 1.4 修改颜色color 1.5 修改材质 1.6 raycast target 1.7 maskable 可遮罩 1.8 imageType 1.9 native size 原生大小 2 rect transform 2.1 …...
【Python系列】PYTHONUNBUFFERED=1的作用
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...
DeepSeek-R1技术全解析:如何以十分之一成本实现OpenAI级性能?
一、现象级爆火背后的技术逻辑 2025年1月20日,中国AI公司深度求索(DeepSeek)发布新一代大模型R1,其性能直接对标OpenAI的o1版本,但训练成本仅为后者的1/20(600万美元 vs. 1.2亿美元)࿰…...
