【C语法学习】10 - scanf()函数

news2025/1/17 9:35:00

文章目录

  • 0 前言
  • 1 函数原型
  • 2 参数
    • 2.1 格式字符串
      • 2.1.1 转换说明
    • 2.2 参数列表
  • 3 返回值
  • 4 读取机制
    • 4.1 基本概念
    • 4.2 转换说明
    • 4.3 读取过程
    • 4.4 读取示例
    • 4.5 多参数
  • 6 示例
    • 6.1 示例1
    • 6.2 示例2
    • 6.3 示例3
    • 6.4 示例4

0 前言

scanf()函数虽然使用起来较为灵活,但是其读取机制还是有点复杂。

1 函数原型

scanf():从标准输入流stdin读取格式化输入,函数原型如下:

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

2 参数

scanf()函数的参数分为两类:

  1. format :格式字符串;
  2. … :参数列表。

2.1 格式字符串

在scanf()函数中:

  1. 格式字符串是必不可少的;
  2. 格式字符串由字面文本量、转义序列和转换说明三部分组成。

2.1.1 转换说明

  1. 格式字符串中的转换说明和参数列表在数量、顺序和类型上要完全匹配;
  2. 格式字符串中只包含转换说明即可,强烈建议不要包括字符串字面量和转义序列,但多个转换说明之间可以用空格隔开,便于阅读;
  3. 如果想从键盘获取字符,建议用getchar()函数替代%c;
  4. 如果想从键盘获取字符串,建议用gets()函数替代%s;%s会读取的字符串末尾加上空字符’\0’,作为字符串结束符;
  5. 与printf()函数不同,在scanf()函数中,%f对应float类型变量,%lf对应double类型变量。

2.2 参数列表

在scanf()函数中:

  1. 参数列表是必不可少的;
  2. 参数列表中参数的数量是可变的,但至少应包含一个参数;
  3. 参数列表中参数的类型是指针类型(&变量名)。

3 返回值

scanf()函数的返回值类型为int型:

  1. 读取成功,返回成功读取的项数;
  2. 读取失败,返回EOF。

C语言标准描述如下:

1. Both scanf and wscanf return the number of fields successfully converted and assigned; the return value does not include fields that were read but not assigned. A return value of 0 indicates that no fields were assigned. 
2. The return value is EOF for an error or if the end-of-file character or the end-of-string character is encountered in the first attempt to read a character.

4 读取机制

4.1 基本概念

  1. 键盘输入:从键盘输入的都是文本,因为键盘只能生成文本字符:字母、数字和标点符号;
  2. 空白字符:空格、制表符和换行符。

4.2 转换说明

转换说明不同,有效字符也不同:

  1. %d转换说明要求scanf()函数能识别十进制数0-9和正负号±;
  2. %x转换说明要求scanf()函数能识别十六进制数a-f和A-F;
  3. %f转换说明要求scanf()函数能识别小数点、e计数法和p计数法等;
  4. %s转换说明要求scanf()函数能识别除空白字符外的所有字符。

4.3 读取过程

scanf()函数读取标准输入流stdin过程如下:

  1. 在遇到第一个非空白字符前,所有的空白字符被读出且被丢弃;
  2. 从遇到第一个非空白字符始,直至
    (1)遇到无效字符:在遇到的第一个无效字符处停止读取,并将无效字符退回至标准输入流stdin中;
    (2)遇到空白字符:在遇到的第一个空白字符处停止读取,并将空白字符退回至标准输入流stdin中;
    (3)达到指定字段宽度:如果使用字段宽度修饰符,在有效字符数达到指定字段宽度处停止读取;
  3. 读取结束后对已读取的有效字符按照转换说明进行转换,然后储存在指定变量中。

特别说明:使用scanf()函数之后一定要清空标准输入流stdin。

4.4 读取示例

以scanf(“%d”, &num)为例:

  1. scanf()函数从标准输入流stdin中读取字符,跳过前面所有的空白字符,从第一个非空白字符开始,直至
    (1)遇到无效字符,将无效字符退回至标准输入流stdin中,读取结束;
    (2)遇到空白字符,将空白字符退回至标准输入流stdin中,读取结束;
    (3)达到指定字段宽度,读取结束;
  2. 将已读取的有效字符按照转换说明要求进行转换,并储存在指定的变量num中;

问题:如果第一次读到的非空白字符是无效字符(如字母a),会发生什么情况呢?

解答:如上所述,如果读到字母a,则立即停止读取,并将字母a退回stdin中,那么本次读取就未读到任何有效的字符,也就是说本次读取是失败的,不会有任何值储存在变量num中,scanf()函数的返回值为0。

4.5 多参数

参数列表中的多个参数对应格式字符串中的多个转换说明:

  1. 用空白字符将键盘输入分成多个字段;
  2. 字段间可以有多个空白字符,多个空白字符集中在一行或分散在多行;
  3. 多个字段与多个转换说明;
  4. 唯一例外的是%c转换说明:根据%c,scanf()函数会读取每个字符,包括空白字符。

6 示例

6.1 示例1

scanf()函数读取过程中的丢弃和回退,代码如下所示:

int main ()
{
	//定义变量
   int a;
   char str[80] = {0};
   //给变量a赋值,输入2个空格+12a+2个空格+Enter
   scanf("%d", &a);
   //打印变量a的值
   printf("a=%d\n", a);
   //用gets清空stdin
   gets(str);
   //打印str的内容和长度
   printf("str = %s, len = %d\n", str, strlen(str));

   return 0;
}

代码执行结果如下图所示:

在这里插入图片描述

代码及运行结果分析:
第一阶段:

  1. 标准输入流中有字符:2个空格+字符12a+2个空格+回车符共8个字符;
  2. scanf()函数读取前两个空格并丢弃;
  3. scanf()函数读取字符1和2,转换为数值12后储存在变量a中;
  4. scanf()函数读取字符a,发现a是无效字符,将a回退至标准输入流stdin中;
  5. 至此scanf()函数从标准输入流stdin中读取完毕;

第二阶段:
6. gets()函数继续从标准输入流stdin中读取字符串;
7. 因标准输入流stdin中仍残留有scanf()函数未读完的字符,故无需用户再次从键盘键入字符;
8. gets()函数会读空标准输入流stdin中的所有字符,直至遇到回车符’\n’;

第三阶段:
9. printf()函数打印a和str的内容,并统计str的长度;a=12符合预期;str长度为3符合预期,即字符’a’+2个空格。

6.2 示例2

scanf()函数返回值,代码如下所示:

void clear_stdin(void)
{
   while (getchar() != '\n');
}

int main()
{
   //变量定义
   int a = 0, b = 0, c = 0;
   int num = 0;
   //第1次输入
   puts("输入11 22 33 : ");
   num = scanf("%d%d%d", &a, &b, &c);
   clear_stdin();
   printf("a=%d, b=%d, c=%d, num=%d\n\n", a, b, c, num);
   //第2次输入
   puts("输入44 55 a6 : ");
   num = scanf("%d%d%d", &a, &b, &c);
   clear_stdin();
   printf("a=%d, b=%d, c=%d, num=%d\n\n", a, b, c, num);

   //第3次输入
   puts("输入77 a8 99 : ");
   num = scanf("%d%d%d", &a, &b, &c);
   clear_stdin();
   printf("a=%d, b=%d, c=%d, num=%d\n\n", a, b, c, num);

   //第4次输入
   puts("输入a0 11 22 : ");
   num = scanf("%d%d%d", &a, &b, &c);
   clear_stdin();
   printf("a=%d, b=%d, c=%d, num=%d\n\n", a, b, c, num);

   return 0;
}

代码执行结果如下图所示:

在这里插入图片描述

代码及运行结果分析:

  1. scanf()函数在%d转换说明下,希望从标准输入流stdin中读取数字字符0-9和正负符号(±),当读取到非数字字符’a’时,将’a’退回至标准输入流stdin中,并停止读取;理论分析和num的实际打印结果相符合。

6.3 示例3

scanf()函数读取字符%c,代码如下所示:

void clear_stdin(void)
{
   while (getchar() != '\n');
}

int main()
{
   //变量定义
   char c1 = 0, c2 = 0, c3 = 0;
   //第1次输入
   puts("输入字符abc,中间不加空格 : ");
   scanf("%c%c%c", &c1, &c2, &c3);
   clear_stdin();
   printf("c1=%c, c2=%c, c3=%c\n\n", c1, c2, c3);

   //第2次输入
   puts("输入字符a b c,中间加空格 : ");
   scanf("%c%c%c", &c1, &c2, &c3);
   clear_stdin();
   printf("c1=%c, c2=%c, c3=%c\n", c1, c2, c3);

   return 0;
}

代码执行结果如下图所示:

在这里插入图片描述

代码及运行结果分析:

  1. scanf()函数在%c转换说明下会读取键盘键入的每一个字符,包括空白字符。

6.4 示例4

scanf()函数读取字符串%s,代码如下所示:

void clear_stdin(void)
{
   while (getchar() != '\n');
}

int main()
{
   //变量定义
   char str[80] = { 0 };
   //
   puts("输入hello world");
   scanf("%s", str);
   clear_stdin();
   puts(str);

   return 0;
}

代码执行结果如下图所示:

在这里插入图片描述

代码及运行结果分析:

  1. scanf()函数在读取字符的时候,如果遇到空白字符,则停止读取,所以%s只能读取单词,不能读取句子。

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

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

相关文章

项目实战:分页功能实战

1、在index.html添加点击事件 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title><link rel"stylesheet" href"style/index.css"><script src"scr…

VX-3R APRS发射试验

VX-3R本身是不带APRS功能的&#xff0c;不过可能通过外加TNC实现APRS功能。 有大佬已经用Arduino实现了相应的发射功能&#xff1a; https://github.com/handiko/Arduino-APRS 我要做的&#xff0c;就是简单修改一下代码&#xff0c;做一个转接板。 YEASU官方没有给出VX-3R的音…

基于单片机的智能饮水机系统

收藏和点赞&#xff0c;您的关注是我创作的动力 文章目录 概要 一、系统设计方案分析2.1 设计功能及性能分析2.2设计方案分析 二、系统的硬件设计3.1 系统设计框图系统软件设计4.1 总体介绍原理图 四、 结论 概要 现在很多学校以及家庭使用的饮水机的功能都是比较单一的&#…

【完美世界】石昊拒绝云曦相认,爱而不得,云曦悲伤无助

Hello,小伙伴们&#xff0c;我是小郑继续为大家深度解析国漫资讯。 深度爆料《完美世界云曦篇》最新一集&#xff0c;为了云曦&#xff0c;石昊不远十万里&#xff0c;亲自送她回家&#xff0c;这份感情之真挚&#xff0c;绝对毋庸置疑。然而&#xff0c;令人感到不解的是&…

读书笔记:《图解机械原理与构造》

通用零部件 轴&#xff1a;支撑回转零件 转轴&#xff1a;弯矩和转矩转动轴&#xff1a;转矩心轴&#xff1a;弯矩直轴曲轴软轴 轴承&#xff1a;支撑轴旋转 滑动轴承&#xff1a;承载高速旋转 径向滑动轴承&#xff1a;径向载荷推力滑动轴承&#xff1a;轴向载荷 滚动轴承&am…

故障诊断 | MATLAB实现GRNN广义回归神经网络故障诊断

故障诊断 | MATLAB实现GRNN广义回归神经网络故障诊断 目录 故障诊断 | MATLAB实现GRNN广义回归神经网络故障诊断故障诊断基本介绍模型描述预测过程程序设计参考资料故障诊断 基本介绍 MATLAB实现GRNN广义回归神经网络故障诊断 数据为多特征分类数据,输入12个特征,分3

modesim verilog仿真验证基本流程(新建工程方式)

文章目录 环境搭建一、在modelsim里创建一个新的工程二、新建verilog设计文件及仿真激励文件三、仿真结果本文演示如何使用modelsim新建工程进行功能仿真。 环境搭建 本文中采用的modelsim版本如下: modelsim altera 10.3d一、在modelsim里创建一个新的工程 打开modelsim软…

双链表详解(初始化、插入、删除、遍历)(数据结构与算法)

1. 单链表与双链表的区别 单链表&#xff08;Singly Linked List&#xff09;和双链表&#xff08;Doubly Linked List&#xff09;是两种常见的链表数据结构&#xff0c;它们在节点之间的连接方式上有所区别。 单链表&#xff1a; 单链表的每个节点包含两个部分&#xff1a;数…

利用大语言模型(LLM )提高工作效率

日常工作就是面向 google/ 百度编程&#xff0c;除了给变量命名是手动输入&#xff0c;大多时候就是通过搜索引擎拷贝别人的代码&#xff0c;或者找到旧项目一段代码拷贝过来使用。这无疑是开发人员的真实写照&#xff1b;然而&#xff0c;通过搜索引擎搜索答案&#xff0c;无疑…

【嵌入式开发工具】STM32+Keil实现软件工程搭建与开发调试

本篇文章介绍了使用Keil来对STM32F103C8芯片进行初始工程搭建&#xff0c;以及开发与工程调试的完整过程&#xff0c;帮助读者能够在实战中体会到Keil这个开发环境的使用方法&#xff0c;了解一个嵌入式工程从无到有的过程&#xff0c;并且具备快速搭建一个全新芯片对应最小软件…

CMU/MIT/清华/Umass提出生成式机器人智能体RoboGen

文章目录 导读1. Introduction2. 论文地址3. 项目主页4. 开源地址5. RoboGen Pipeline6. Experimental Results作者介绍Reference 导读 CMU/MIT/清华/Umass提出的全球首个生成式机器人智能体RoboGen&#xff0c;可以无限生成数据&#xff0c;让机器人7*24小时永不停歇地训练。…

CVE-2023-21839 weblogic rce漏洞复现

文章目录 一、漏洞影响版本二、漏洞验证三、启动反弹shell监听切换路径到jdk1.8 四、启动ldap服务五、使用CVE-2023-21839工具来进行攻击测试六、反弹shell 一、漏洞影响版本 CVE-2023-21839是Weblogic产品中的远程代码执行漏洞&#xff0c;由于Weblogic IIOP/T3协议存在缺陷&…

Python基础入门例程35-NP35 朋友的年龄是否相等(运算符)

最近的博文&#xff1a; Python基础入门例程34-NP34 除法与取模运算&#xff08;运算符&#xff09;-CSDN博客 Python基础入门例程33-NP33 乘法与幂运算&#xff08;运算符&#xff09;-CSDN博客 Python基础入门例程32-NP32 牛牛的加减器&#xff08;运算符&#xff09;-CSD…

【源码解析】聊聊SpringBean是如何初始化和创建

我们知道通过类进行修复不同的属性&#xff0c;比如单例、原型等&#xff0c;而具体的流程是怎么样的呢&#xff0c;这一篇我们开始从源码的视角分析以下。 刷新方法 在刷新容器中有一个方法&#xff0c;其实就是 Bean创建的过程。 finishBeanFactoryInitialization(beanFact…

大数据分析:基于时间序列的股票预测于分析 计算机竞赛

1 简介 Hi&#xff0c;大家好&#xff0c;这里是丹成学长&#xff0c;今天向大家介绍一个大数据项目 大数据分析&#xff1a;基于时间序列的股票预测于分析 2 时间序列的由来 提到时间序列分析技术&#xff0c;就不得不说到其中的AR/MA/ARMA/ARIMA分析模型。这四种分析方法…

一篇文章带你学会MybatisPlus~

实现MybatisPlus的简单使用&#xff1a; 数据库准备部分&#xff1a; //创建名为mybatisPlus的数据库 create database mybatisPlus;//使用该数据库 use mybatisPlus;//创建user表 CREATE TABLE user( id bigint(20) NOT NULL COMMENT 主键ID , name varchar(30) DEFAULT NUL…

信道编码译码及MATLAB仿真

文章目录 前言一、什么是信道编码&#xff1f;二、信道编码的基本逻辑—冗余数据1、奇偶检验码2、重复码 三、编码率四、4G 和 5G 的信道编码1、卷积码2、维特比译码&#xff08;Viterbi&#xff09;—— 概率译码3、LTE 的咬尾卷积码4、LTE 的 turbo 码 五、MATLAB 仿真1、plo…

深度学习_9_图片分类数据集

散装代码&#xff1a; import matplotlib.pyplot as plt import torch import torchvision from torch.utils import data from torchvision import transforms from d2l import torch as d2ld2l.use_svg_display()# 通过ToTensor实例将图像数据从PIL类型变换成32位浮点数格式…

Win11系统下Oracle11g数据库下载与安装使用教程

文章目录 一、Oracle下载与安装1.1 解压安装包1.2 开始安装Oracle11g1.2.1 用户 1.3 测试数据库是否配置成功1.4 了解一下 Oracle相关服务1.5 了解Oracle体系结构 二、使用工具连接数据库2.1 PL/ SQL 连接本地oracle 三、PL/ SQL远程访问数据库3.1 可能踩坑问题&#xff08;TNS…

10.MySQL事务(上)

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 目录 前言&#xff1a; 是什么&#xff1f; 为什么? 怎么做&#xff1f; 前言&#xff1a; 本篇文章将会说明什么是事务&#xff0c;为什么会出现事务&#xff1f;事务是怎么做的&#xff1f; 是什么&#xff1f; 我…