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

news2024/11/25 10:27:13

文章目录

  • 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/1169978.html

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

相关文章

SpringBoot集成JPA实现分页和CRUD

SpringBoot集成JPA实现分页和CRUD 文章目录 SpringBoot集成JPA实现分页和CRUDpom.xmlapplication.propertiesaddCategory.jspeditCategory.jsphello.jsplistCategory.jspCategoryCategoryDAOCategoryServiceCategoryServiceImplPage4NavigatorRedisConfigCategoryControllerHel…

CH10_简化条件逻辑

分解条件表达式(Decompose Conditional) if (!aDate.isBefore(plan.summerStart) && !aDate.isAfter(plan.summerEnd))charge quantity * plan.summerRate; elsecharge quantity * plan.regularRate plan.regularServiceCharge;if (summer())…

C#中List<T>的 AddRange方法使用说明

文章目录 C#中List<T>的 AddRange方法使用说明 C#中List的 AddRange方法使用说明 AddRange可以一次性添加集合A到当前集合B。 本身不能为空&#xff0c;但是可以保存null的数据。 List 中会保留集合中元素的顺序 将集合A添加到集合B的末尾 本身为null&#xff0c;使用 A…

国际测试委员会BenchCouncil首发“开源系统杰出成果榜” 百度飞桨上榜

&#x1f4d5;作者简介&#xff1a;热爱跑步的恒川&#xff0c;致力于C/C、Java、Python等多编程语言&#xff0c;热爱跑步&#xff0c;喜爱音乐的一位博主。 &#x1f4d7;本文收录于恒川的日常汇报系列&#xff0c;大家有兴趣的可以看一看 &#x1f4d8;相关专栏C语言初阶、C…

轻量封装WebGPU渲染系统示例<14>- 多线程模型载入(源码)

当前示例源码github地址: https://github.com/vilyLei/voxwebgpu/blob/main/src/voxgpu/sample/ModelLoadTest.ts 此示例渲染系统实现的特性: 1. 用户态与系统态隔离。 细节请见&#xff1a;引擎系统设计思路 - 用户态与系统态隔离-CSDN博客 2. 高频调用与低频调用隔离。 …

uniapp 解决H5跨域的问题

uniapp 解决h5跨域问题 manifest.json manifest.json文件中&#xff0c;点击“源码视图”,在此对象的最后添加以下代码&#xff1a; "h5" : {"devServer" : {"port" : 8080, //端口号"disableHostCheck" : true,"proxy" :…

作为一个初学者,入门大模型其实没那么难

在生成式 AI 盛行的当下&#xff0c;你是否被这种技术所折服&#xff0c;例如输入一段简简单单的文字&#xff0c;转眼之间&#xff0c;一幅精美的图片&#xff0c;又或者是文笔流畅的文字就展现在你的面前。 相信很多人有这种想法&#xff0c;认为生成式 AI 深不可测&#xf…

通过@ConfigrationProperties读取配置文件属性并赋值

这种设计使得 Anything 成为 Something 类的静态成员&#xff0c;因此不依赖于外部类的实例。静态内部类通常更独立&#xff0c;它们可以单独存在且无需引用外部类的实例。 如果将 Anything 类定义为非静态的内部类&#xff0c;它将依赖于 Something 类的实例。这意味着每个 S…

Sybase PowerDesigner 16.7.7.7536 Crack

Power Designer 是Sybase公司的CASE工具集&#xff0c;使用它可以方便地对管理信息系统进行分析设计&#xff0c;他几乎包括了数据库模型设计的全过程。利用Power Designer可以制作数据流程图、概念数据模型、物理数据模型&#xff0c;还可以为数据仓库制作结构模型&#xff0c…

安装Nginx并且添加fastDFS模块

安装Nginx并且添加fastDFS模块 因为这个模块必须在Nginx的安装的过程中才能添加&#xff0c;所有我们需要重新安装一个nginx&#xff0c;为了和原来已安装的Nginx进行区分&#xff0c;我们把新安装的Nginx取名为nginx_fdfs 将Nginx的tar包上传到Linux上 解压上传的Nginx文件 …

C++初阶(七)类和对象

&#x1f4d8;北尘_&#xff1a;个人主页 &#x1f30e;个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上&#xff0c;不忘来时的初心 文章目录 一、流插入流提取1、流插入演示2、流提取演示3、cplusplus推荐 二、const成员三、取地址及con…

Ubuntu更新apt-get安装镜像源

前往清华开源镜像站获取镜像链接 修改镜像源&#xff0c;打开配置文件&#xff0c;将镜像源链接粘贴到配置文件 sudo vim /etc/apt/sources.list更新软件列表到本地 sudo apt-get update更新所有软件&#xff08;非必要&#xff09; sudp apt-get upgrade

Leetcode—100.相同的树【简单】

2023每日刷题&#xff08;十八&#xff09; Leetcode—100.相同的树 递归实现代码 /*** Definition for a binary tree node.* struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*/ bool isSameTree(struct TreeNode* p, struc…

如何当好一面面试官?

最近公司恢复了招聘&#xff0c;重新启动了校招流程&#xff0c;现在都已经 11 月了&#xff0c;刚好赶上校招黄金期&#xff0c;不过提前批的时间已经过了&#xff0c;也是有点神奇。 公司停止招聘好久了&#xff0c;突然重启&#xff0c;赶忙赶急地让我们推荐面试官&#xf…

「Verilog学习笔记」异步复位的串联T触发器

专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点&#xff0c;刷题网站用的是牛客网 分析 这道题目里我们有两个需要明确的点&#xff1a; 1. 什么是异步复位 2. 什么是串联的T触发器 关于第一个点&#xff0c;可以看我的这篇文章&#xff0c;已经整理好了&a…

[C++ 中]:6.类和对象下(static成员 + explicit +友元函数 + 内部类 + 编译器优化)

(static成员 explicit 友元函数 内部类 编译器优化&#xff09; 一.static 成员&#xff1a;1.概念引入&#xff1a;1-1&#xff1a;定义全局变量记录个数&#xff1f; 2.如果有多个类需要分开去记录类对象的个数&#xff1f;2-1&#xff1a;可不可以声明成员变量解决&#…

单片机温湿度-光照-DHT11-烟雾气体检测控制系统-proteus仿真-源程序

一、系统方案 本设计采用52单片机作为主控器&#xff0c;液晶1602显示&#xff0c;DHT11温湿度&#xff0c;光照、烟雾气体检测&#xff0c;按键设置报警阀值&#xff0c;蜂鸣器报警。 二、硬件设计 原理图如下&#xff1a; 三、单片机软件设计 1、首先是系统初始化 // // …

(免费领源码)php#MySQL软件测试文档管理系统28035-计算机毕业设计项目选题推荐

目 录 摘 要 Abstract 第1章 前 言 1.1 研究背景 1.2 开发意义 1.3 系统开发目标 第2章 系统开发环境 6 2.1 HTTP协议 6 2.2 HTML网页技术 6 2.3 B/S结构 6 2.4 PHP脚本语言 7 2.5 MySQL数据库 7 2.6 Apache简介 8 第3章 需求分析 3.1 需求分析 3.2 系统可…

ChatGPT商务英语邮件写作方法及案例模板

目录 1 前言 2 商务英语email写作技巧 3 商务email完整模板 4 求学科研email模板 5 工作email模板 6 商务沟通email模板 在现代商务环境中&#xff0c;通过电子邮件进行沟通已经成为一种普遍的方式。良好的商务英语邮件写作技巧和模板能够帮助我们有效地传达信息&#xf…

K8s-----pod详解

目录 一、Pod介绍 1、Pod的基础概念 2、pod定义&#xff08;资源清单&#xff09; 二、Pod相关实例 1、初始化容器&#xff08;init容器&#xff09; 2、镜像拉取策略&#xff08;image PullPolicy&#xff09; 3、pod容器重启策略&#xff08;restartPolicy&#xff09…