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

文章目录

  • 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个空格+Enterscanf("%d", &a);//打印变量a的值printf("a=%d\n", a);//用gets清空stdingets(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.hqwc.cn/news/159698.html

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

相关文章

msvcr110.dll丢失的解决方法都有哪些,有效解决msvcr110.dll丢失

今天在使用电脑的时候提示一个和“msvcr110.dll丢失”有关的报错,出现这样的问题小编也是一脸懵,一下也不是知道该怎么处理了,于是小编去了解了一下msvcr110.dll丢失是什么情况,为什么会有这样的问题发生,同时msvcr110…

go测试库之apitest

📢专注于分享软件测试干货内容,欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!📢交流讨论:欢迎加入我们一起学习!📢资源分享:耗时200小时精选的「软件测试」资…

基于 golang 从零到一实现时间轮算法 (一)

前言 时间轮是用来解决海量百万级定时器(或延时)任务的最佳方案,linux 的内核定时器就是采用该数据结构实现。 应用场景 自动删除缓存中过期的 Key:缓存中设置了 TTL 的 kv,通过把该 key 对应的 TTL 以及回调方法注册…

【MySQL索引与优化篇】数据库的设计规范

数据库的设计规范 文章目录 数据库的设计规范1. 范式2. 键和相关属性的概念3. 第一范式4. 第二范式5. 第三范式6. 小结7. 反范式化7.1 概述7.2 反范式的新问题7.3 反范式适用场景 8. 巴斯范式9. 第四范式、第五范式和域键范式 1. 范式 在关系型数据库中,关于数据表…

51单片机复位电容计算与分析(附带Proteus电路图)

因为iC x (dU/dt).在上电瞬间,U从0变化到U,所以这一瞬间就是通的,然后这就是一个直流回路,因为电容C直流中是断路的,所以就不通了。 然后来分析一下这个电容的电压到底是能不能达到单片机需要的复位电压。 这是一个线性电容&…

数据分析师的就业前景看好

IT行业哪个方向比较好就业? 目前IT行业的发展速度非常的快,很多领域都已经开始和IT技术进行紧密的结合,这也带来了很多岗位的空缺。那么就一起来说说,IT行业里,哪些方向会更好就业。 大数据时代,呼唤数据分析师。 …

压缩软件 7-Zip VS WinZips?

7-zip在联想应用商店给强烈推荐? 要说它好用还行,但每次压缩都显示网络连接失败等异常广告信息。 相反好用的7-ZIP必须鼠标点击右键点击更多才能够看到,这次更新体验也太差了吧? 用户放在第一位? 要不是更新后一直推…

EMC Unity存储系统如何查看SSD的使用寿命

为什么要写这个博客? 客户对老的EMC unity的存储系统要扩容,如何确定SSD磁盘是全新的还是拆机二手的?很多时候客户还有一个奇葩的要求,就是要和5年前的磁盘PN一致,甚至要求固件版本一致,最关键的还要求是全…

C++二分查找算法的应用:长度递增组的最大数目

本文涉及的基础知识点 二分查找 题目 给你一个下标从 0 开始、长度为 n 的数组 usageLimits 。 你的任务是使用从 0 到 n - 1 的数字创建若干组,并确保每个数字 i 在 所有组 中使用的次数总共不超过 usageLimits[i] 次。此外,还必须满足以下条件&…

学Python,一个月从小白到大神?看你怎么学!

Python是一门超强大而且超受欢迎的编程语言。它被用在各种领域,比如网站开发、数据分析、人工智能和机器学习。学会Python会给你创造很多职业机会,所以绝对是值得一试的。 但你有没有过这样的梦想:一个月时间,从Python小白变成Py…

【C语言初学者周冲刺计划】2.4求一个3×3矩阵对角线元素之和

1解题思路&#xff1a; 首先学会怎么输入3*3矩阵的数值&#xff1b;然后细节处&#xff0c;比如最后求和应该加什么&#xff0c;怎么写问题&#xff1b; 2代码&#xff1a; #include<stdio.h> int main() {int str[3][3],i,j,sum0;for(i0;i<3;i){for(j0;j<3;j){…

CodeWhisperer 的使用心得

文章作者&#xff1a;小SS 亚马逊云科技开发者社区为开发者们提供全球的开发技术资源。这里有技术文档、开发案例、技术专栏、培训视频、活动与竞赛等。帮助中国开发者对接世界最前沿技术&#xff0c;观点&#xff0c;和项目&#xff0c;并将中国优秀开发者或技术推荐给全球云社…