C语言scanf()函数详解

目录

1. scanf()函数简介

 1.1  函数原型

1.2  头文件

1.3  返回值

1.4  参数

2.格式说明符

3.输入格式控制

 关于‘ * ’的例子

 关于width域宽的例子

 关于length长度修饰符的说明

4.  其他常见问题说明

4.1  scanf()函数连续读入和处理多个变量的情况


(本篇内容全面,篇幅较长,建议收藏,方便查阅)

1. scanf()函数简介

scanf()是C语言中的一个输入函数。与printf函数一样,都被声明在头文件stdio.h里,因此在使用scanf函数时要加上#include <stdio.h>。scanf函数从 stdin 读取数据,并根据参数格式将其存储到附加参数所指向的位置。 它是格式输入函数,即按用户指定的格式从键盘上把数据输入到指定的变量之中


关于printf()函数的详细介绍请看这篇文章C语言printf函数详解-CSDN博客

 1.1  函数原型

int scanf ( const char * format, ... ); 

1.2  头文件

<stdio.h>

1.3  返回值

scanf函数返回成功读入的数据项数,读入数据时遇到了“文件结束”则返回EOF。

请看下面的例子

#include<stdio.h>
int main()
{int a = 0, b = 0;int count = scanf("%d %d", &a, &b);//count存储scanf函数的返回值printf("\n返回值为%d\n", count);return 0;
}

函数返回值为int型。

第一种情况如果a和b都被成功读入,那么scanf的返回值就是2;

第二种情况:如果只有a被成功读入,返回值为1;

第三种情况:如果a读取失败,返回值为0;

第四种情况如果遇到错误或遇到end of file,返回值为EOF。end of file为Ctrl+z 或者Ctrl+d。(在某些编译器内,结束输入为三次Ctrl+z)

1.4  参数

函数的第一个参数是格式字符串,它指定了输入的格式,并按照格式说明符解析输入对应位置的信息并存储于可变参数列表中对应的指针所指位置。 

格式字符串分三种情况

一、空格字符该函数将读取并忽略在下一个非空格字符之前遇到的任何空格字符(空格字符包括空格、换行符和制表符 )

例如下面这种情况

当格式说明符之前有一个空格时,就会在读取时自动忽略一个空格字符(若没有读取到空格字符,也不影响后续读取)

#include<stdio.h>
int main()
{char a;scanf(" %c", &a);printf("%c\n", a);return 0;
}

 

二、非空格字符,格式说明符除外 (%):任何不是空格字符(空白、换行符或制表符)或格式说明符(以 % 字符开头)的字符都会导致函数从流中读取下一个字符,将其与此非空格字符进行比较,如果匹配,则将其丢弃,函数继续使用格式的下一个字符。如果字符不匹配,则函数将失败,返回流的后续字符并使其处于未读状态

例如下面这种情况

读取两个字符存入char a和char b,但是在scanf()函数的两个格式说明符之间写了一个非空字符b,这样就会导致从键盘输入两个字符存入变量时,中间必须输入一个b,b被读取之后会被丢弃,之后正常读取后面的内容

否则,如果没有读取到b,就会导致后面的读取出错

#include<stdio.h>
int main()
{char a, b;scanf("%cb%c", &a, &b);printf("%c %c\n", a, b);return 0;
}

 

 

三、格式说明符:由初始百分号 (%) 组成的序列表示格式说明符,该说明符用于指定要从中检索并存储到附加参数所指向的位置的数据的类型和格式

其中格式说明符是最重要的部分,放在文章后面部分专门介绍

它的其余参数就是存放用户输入的变量,格式字符串里面有多少个占位符,就有多少个变量。

注意:变量前⾯必须加上 & 运算符(指针变量除外),因为 scanf() 传递的不是值,⽽是地址, 即将变量 i 的地址指向用户输⼊的值。 如果这⾥的变量是指针变量(⽐如字符串变量),那就不⽤加 & 运算符。

2.格式说明符

scanf 的格式说明符遵循以下原型: %[*][width][length]说明符

 下面先对说明符做详细的讲解

  • c     读入域宽指定的数目个字符组成的字符序列(后面不会加上空字节),如果省略宽度则读入单字符。如%c或%1c读入单字符,%2c读入两个字符(后面不会加上空字节),以此类推。

  •   读入一个指定宽度的字符序列,后面会加上空字节,遇到空白字符(\t \r \n 空格等)完成读取

  •   读入可选有符号(可选有符号表示输入时可以带符号也可以不带符号,不带符号则视为非负)十进制整数。输入格式应该像strtol函数的base实参为10调用时识别的字符序列一样。

  •    读入无符号符号十进制整数。输入格式应该像strtol函数的base实参为10调用时识别的字符序列一样。

  •     读入可选有符号整数。输入格式应该像strtol函数的base实参为0调用时识别的字符序列一样。

  • a,e,f,g,A,E,F,G 读入可选有符号浮点数,输入格式应该像strtod函数识别的字符序列一样。

  •    读入可选有符号八进制整数。输入格式应该像strtoul函数的base实参为8调用时识别的字符序列一样。

  • x,X   读入可选有符号十六进制整数。输入格式应该像strtoul函数的base实参为16调用时识别的字符序列一样。

  •    读入一个指针值。读入的字符序列应该与fprintf的%p产生的字符序列形式相同。

  •    不读入任何字符,而是把到该位置已读入的字符数存储到与之对应的int*指向的位置。本转换说明符如果带有*或者带有域宽信息(如:%*n或%3n等),则后果是未定义的。

  •   读入% 符号(连续两个百分号表示一个百分号

  • 无效的转换说明符将引起未定义的行为

3.输入格式控制

这里讲解%[*][width][length]说明符中* width 和 length的作用和使用

子说明符描述
*可选的起始星号表示要从流中读取数据,但会忽略数据(即,数据不存储在参数所指向的位置)。
width又被称为域宽,指定在当前读取操作中要读取的最大字符数(可选)。
lengthhh、h、l、ll、j、z、t、L(可选)之一。
这会更改相应参数所指向的预期存储类型

 关于‘ * ’的例子

带*的格式说明符,读取后不会赋给变量

#include<stdio.h>
int main()
{int a = 0, b = 0;scanf("%*d %d %d", &a, &b);printf("%d %d\n", a, b);return 0;
}

 

 关于width域宽的例子

读取10个字符到字符数组arr

顺便说一下关于%s这里有几个需要注意的地方

第一、因为 %s 不会包含空白字符,所以⽆法⽤来读取多个单词,除⾮多个 %s ⼀起使⽤。这也意味着,scanf() 不适合读取可能包含空格的字符串,⽐如书名或歌曲名。

第二、scanf() 将字符串读⼊字符数组时,不会检测字符串是否超过了数组⻓度。所以,储存字符串时, 很可能会超过数组的边界,导致预想不到的结果。为了防⽌这种情况,使⽤ %s 占位符时,应该指定 读⼊字符串的最长长度

第三、scanf() 遇到 %s 占位 符,会在字符串变量末尾存储⼀个空字符 \0。比如想要存储10个大小的字符串,就必须申请11个大小的字符数组,因为最后一个空间要存储\0

#include<stdio.h>
int main()
{char arr[11];scanf("%10s", &arr);printf("%s\n", arr);return 0;
}

 

 关于length长度修饰符的说明

  • hh与d, i, o, u, x, X, or n配合使用,表示对应一个signed char或unsigned char数据。

  • h与d, i, o, u, x, X, or n配合使用,表示对应一个short int或unsigned short int数据。

  • l 与d, i, o, u, x, X, or n配合使用,表示对应一个long int或unsigned long int数据;与a, A, e, E,

  • f, F, g, or G 配合使用表示对应一个double数据;与c,s,[配合使用表示对应wchar_t数据。

  • ll与d, i, o, u, x, X, or n配合使用,表示对应一个long long int或unsigned long long int数据。

  • j与d, i, o, u, x, X, or n配合使用,表示对应一个intmax_t或uintmax_t数据。

  • z与d, i, o, u, x, X, or n配合使用,表示对应一个size_t数据(或与size_t对应的有符号整型数据)。

  • t与d, i, o, u, x, X, or n配合使用,表示对应一个ptrdiff_t数据(或与ptrdiff_t对应的无符号整型数据)。

  • L 与a, A, e, E, f, F, g, or G 配合使用,表示对应一个long double数据。

  • 如果长度修饰符与格式说明符不匹配则引起未定义的行为

长度修饰符length的作用是为了改变说明符的预期存储类型,受于篇幅所限,这里不再展开介绍

4.  其他常见问题说明

4.1  scanf()函数连续读入和处理多个变量的情况

这里需要对scanf()函数的处理原理做一下补充说明

scanf() 处理用户输⼊的原理是,用户的输⼊先放⼊缓存,等到按下回⻋键后,按照占位符对缓存 进⾏解读。 解读用户输⼊时,会从上⼀次解读遗留的第⼀个字符开始,直到读完缓存,或者遇到第⼀个不符合条 件的字符为⽌。

来看下面这个例子

输入     -89.2345#67t

scanf()读取数据时,先忽略掉起始的空格字符,从 - 开始读取有效字符,因为第一个说明符是整型,所以读到-89 为止;第二个浮点型读取了 .2345 赋给变量b,因为到#已经不是浮点型的有效字符;第三个说明符是字符型,读取一个#  此时scanf()函数已经读取完成,剩下的字符会停留在缓存中

#include<stdio.h>
int main()
{int a = 0;float b = 0.0;char c = '0';scanf("%d%f%c", &a, &b, &c);//输入     -89.2345#67tprintf("%d %f %c\n", a, b, c);return 0;
}

程序运行结果如下

 在上面的例子的基础上,再深入一点

如果我们创建一个字符数组,进行scanf()读取并printf,来试一下scanf()函数是否会读取上次遗留在缓存中的数据

#include<stdio.h>
int main()
{int a = 0;float b = 0.0;char c = '0';char arr[10];scanf("%d%f%c", &a, &b, &c);printf("%d %f %c\n", a, b, c);scanf("%s", &arr);printf("%s\n", arr);return 0;
}

 运行结果如下,可以看到后面的scanf()函数直接读取了上次遗留在缓存的数据

本篇文章讲解完毕,后续遇到或想到需要补充的点会持续更新的

文章创作不易,欢迎点赞收藏支持一下!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/602133.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Diffusion扩散模型学习2:DDPM前向加噪过程torch实现

参考: https://arxiv.org/pdf/2006.11239.pdf ##论文 https://github.com/dtransposed/code_videos/blob/main/01_Diffusion_Models_Tutorial/Diffusion%20Model.ipynb ##code https://spaces.ac.cn/archives/9119 1、红色框: 前向过程论文公式推出可以从x0原图一步到最终噪声…

jetson AGC orin 配置pytorch和cuda使用、yolov8 TensorRt测试

文章目录 1、安装环境1.1、检查系统环境1.2、下载安装pytorch1.3、下载安装torchvision1.3、测试安装是否成功 2、yolov8测试2.1、官方python脚本测试2.2、tensorrt 模型转换2.3、tensorrt c 测试 1、安装环境 1.1、检查系统环境 检查系统环境、安装jetpack版本&#xff0c;执…

Linux操作系统基础(12):Linux的Shell解释器

1. Shell的介绍 在Linux中&#xff0c;Shell 是一种命令行解释器&#xff0c;它是用户与操作系统内核之间的接口&#xff0c;它负责解释用户输入的命令&#xff0c;并将其转换成系统调用或其他操作系统能够执行的指令。 Shell 提供了一种交互式的方式来与操作系统进行通信&am…

内核线程创建-kthread_create

文章参考Linux内核线程kernel thread详解 - 知乎 大概意思就是早期创建内核线程&#xff0c;是交由内核处理&#xff0c;由内核自己完成&#xff08;感觉好像也不太对呢&#xff09;&#xff0c;创建一个内核线程比较麻烦&#xff0c;会导致内核阻塞。因此就诞生了工作队列以及…

Linux 目录结构及其说明

Linux 操作系统遵循一种标准的目录结构&#xff0c;称为 Filesystem Hierarchy Standard&#xff08;文件系统层次结构标准&#xff09;&#xff0c;其定义了不同目录的用途和内容。 浅蓝色文字 /&#xff08;根目录&#xff09;&#xff1a; /根目录是整个文件系统的起点&…

力扣2807.在链表中插入最大公约数

思路&#xff1a;遍历链表&#xff0c;对于每一个结点求出它与下一个结点的最大公约数并插入到俩个结点之间 代码&#xff1a; /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}…

【数据库系统概念】第7-14章集合

文章目录 第七章 数据库设计和E-R模型&#xff08;重点&#xff01;&#xff01;&#xff01;&#xff09;~~7.1 设计过程概览&#xff08;了解&#xff09;~~7.1.1 设计阶段7.1.2 设计选择 7.2 实体-联系模型&#xff08;重点掌握&#xff09;7.2.1 实体集7.2.2 联系集联系集的…

BLE Mesh蓝牙组网技术详细解析之Model Layer模型层(八)

目录 一、什么是BLE Mesh Model Layer模型层&#xff1f; 二、SIG Model 2.1 模型概念 2.2 消息格式 2.3 开关模型 四、资料获取 一、什么是BLE Mesh Model Layer模型层&#xff1f; Models Layer的作用是定义了一些通用的或特定的模型&#xff0c;用于实现网络节点设备…

Beauty algorithm(四)眼影

一、skills 前瞻 略 二、目标区域定位 1、 眼影区域 1、眼部关键点 左侧:36,37,38,39,40,41 右侧:42,43,44,45,46,47 2、计算roi区域的w,h,center 目的调整mask的比列。 FaceRegion left_es, right_es; left_es.w = landmarks.at(39).x - landmarks.at(36).x; left_es.…

书生·浦语大模型实战营第一次课堂笔记

书生浦语大模型全链路开源体系。大模型是发展通用人工智能的重要途径,是人工通用人工智能的一个重要途径。书生浦语大模型覆盖轻量级、重量级、重量级的三种不同大小模型,可用于智能客服、个人助手等领域。还介绍了书生浦语大模型的性能在多个数据集上全面超过了相似量级或相近…

并发(3)

目录 11.Synchronized本质上是通过什么保证线程安全的&#xff1f; 12.Synchronized使得同时只有一个线程可以执行&#xff0c;性能比较差&#xff0c;有什么提升的方法&#xff1f; 13.Synchronized由什么样的缺陷&#xff1f;Java Lock是怎么弥补这些缺陷的&#xff1f; 1…

看了致远OA的表单设计后的思考

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a;RuoYi-Nbcio后台管理系统 更多nbcio-boot功能请看演示系统 gitee源代码地址 后端代码&#xff1a; https://gitee.com/nbacheng/n…

通信原理期末复习——计算大题(一)

个人名片&#xff1a; &#x1f981;作者简介&#xff1a;一名喜欢分享和记录学习的在校大学生 &#x1f42f;个人主页&#xff1a;妄北y &#x1f427;个人QQ&#xff1a;2061314755 &#x1f43b;个人邮箱&#xff1a;2061314755qq.com &#x1f989;个人WeChat&#xff1a;V…

交换机04_远程连接

通过远程管理方式连接交换机 1、telnet简介 telnet 是应用层协议 基于传输层TCP协议的&#xff0c;默认端口&#xff1a;23 采用的是明文密码方式 不是很安全&#xff0c;一般用于内网管理。 2、ssh协议简介 ssh 是应用层的协议&#xff0c;基于传输层的TCP协议&#x…

打造清晰的日志管理策略:如何在 NestJS 中集成 winston 高级日志系统

前言 在Web应用程序的开发过程中&#xff0c;日志管理是不可或缺的一部分。日志可以帮助我们了解应用程序的运行状态&#xff0c;监控系统行为&#xff0c;以及在出现问题时快速定位和解决问题。 对于使用NestJS框架的项目来说&#xff0c;集成一个高效、可扩展的日志系统尤为…

面试官:说说接口和抽象类有什么区别

程序员的公众号&#xff1a;源1024&#xff0c;获取更多资料&#xff0c;无加密无套路&#xff01; 最近整理了一波电子书籍资料&#xff0c;包含《Effective Java中文版 第2版》《深入JAVA虚拟机》&#xff0c;《重构改善既有代码设计》&#xff0c;《MySQL高性能-第3版》&…

Python中的cls语法

在Python中&#xff0c;cls 是一个用于指代类本身的约定性名称&#xff0c;通常用作类方法&#xff08;class method&#xff09;中的第一个参数。cls 类似于 self&#xff0c;它是对类的引用&#xff0c;而不是对实例的引用。cls 通常在类方法中用于访问类级别的属性和方法。举…

LLM Agent之数据分析领域的应用

数据分析&#xff1a;Data-Copilot paper: Data-Copilot: Bridging Billions of Data and Humans with Autonomous Workflow github: https://github.com/zwq2018/Data-Copilot 先介绍下浙大提出的已扩展的数据分析框架&#xff0c;支持多种金融数据类型的查询&#xff0c;数…

论文笔记 Understanding Electricity-Theft Behavior via Multi-Source Data

WWW 2020 oral 1 INTRO 1.1 背景 1.1.1 窃电 窃电&#xff08;electricity theft&#xff09;指用户为了逃避电费而进行非法操作的一种行为 常用的反窃电方法可分为两类&#xff1a; 基于硬件驱动的反窃电方法 ​​​​​​​电表开盖检测、集中器检测。。。。 硬件驱动的…

MySQL之视图案例

目录 一.视图1.1 含义1.2 操作 二.案例三.思维导图 一.视图 1.1 含义 虚拟表&#xff0c;和普通表一样使用 1.2 操作 1.创建视图 create view 视图名 as 查询语句&#xff1b; 2.视图的修改 方式一&#xff1a; create or replace view 视图名 as 查询语句 方式二&#x…