羽夏闲谈—— C 的 scanf 的高级用法
前言
今天看到博友发了个有关scanf
的使用的注意事项,就是讨论缓冲区残存数据的问题,用简单的代码示例复述一下:
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
int a;
char b;
scanf("%d", &a);
scanf("%c", &b);
printf("a = %d , b = %d\n", a, b);
system("pause");
return 0;
}
你或许碰到这个输出:
5
a = 5 , b = 10
请按任意键继续. . .
我明明想输入个5,然后回车输入下一个字符,但是,回车符也是个字符,会被scanf
进去,绝大多数人的解决方案就是提前把这个字符读取走,但是如果缓冲区的东西太多的话,需要加个循环,才能处理,下面我来介绍scanf
的高级用法,之间研究过,忘记在哪里看到的,这个是我总结的,那些基础用法自己看看书就行了。
清空缓存区
我先把清空缓冲区的代码放上,因为后面的代码都会用到,至于为什么后面会有详细介绍:
scanf("%*[^\n]"); //清除到回车符的所有字符
scanf("%*c"); //清除回车符
指定输入长度
我们都知道scanf
可以指定小数位数和长度,如下是代码示例:
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
int n;
float f;
char str1[23];
scanf("%2d", &n);
//清空缓冲区代码{
scanf("%*[^\n]");
scanf("%*c");
//}
scanf("%5f", &f);
//清空缓冲区代码{
scanf("%*[^\n]");
scanf("%*c");
//}
scanf("%5s", str1);
puts("执行后:");
printf("n=%d, f=%g, str=%s\n", n, f, str1);
system("pause");
return 0;
}
如下是输入和输出结果:
5653 12
2.56458452 2356.9999
helloworld
执行后:
n=56, f=2.564, str=hello
请按任意键继续. . .
看到没,清空缓冲区的代码有效果了,如果没有这行清空缓冲区的代码,就会成这样子:
5653 12
执行后:
n=56, f=53, str=12
请按任意键继续. . .
这就是清除缓冲区的作用。
单范围匹配
不要惊讶,scanf
也是支持类似正则表达式的功能的,我们用如下代码进行演示:
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
char str2[30];
scanf("%[abcd]", str2); //%[abcd]表示只要字符串只有 a,b,c,d 范围内就匹配
puts("执行后:");
printf("%s\n", str2);
system("pause");
return 0;
}
如下是输入和输出结果:
babccbaxyz
执行后:
babccba
请按任意键继续. . .
代码中的注释可能说的不明白,这里我长篇大论一下:字符串从开头开始匹配,必须字符串只有abcd
中这四个字符任意一个才有效,如果开头没有这四个字符,则匹配为空。
多范围匹配
既然支持单范围了,肯定也支持多范围,什么是多范围匹配可以先看看一些基础示例,如果会正则表达式的话很容易懂:
- %[a-z]表示读取 abc...xyz 范围内的字符,也即小写字母;
- %[A-Z]表示读取 ABC...XYZ 范围内的字符,也即大写字母;
- %[0-9]表示读取 012...789 范围内的字符,也即十进制数字;
- %[a-zA-Z]表示读取大写字母和小写字母,也即所有英文字母;
- %[a-z-A-Z0-9]表示读取所有的英文字母和十进制数字;
- %[0-9a-f]表示读取十六进制数字
如果经常使用的话也就这些类型,如下是代码示例:
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
char str3[30];
scanf("%[a-zA-Z]", str3); //只读取字母
puts("执行后:");
printf("%s\n", str3);
system("pause");
return 0;
}
如下是输入和输出结果:
abcXYZ123abcXYZ123
执行后:
abcXYZ
请按任意键继续. . .
不匹配某些字符
既然有匹配的字符,肯定有不想匹配的字符。对于不匹配某些字符,scanf
允许我们在%[ ]
中直接指定某些不能匹配的字符,具体方法就是在不匹配的字符前面加上^
,给几个例子:
- %[^\n]表示匹配除换行符以外的所有字符,遇到换行符就停止读取;
- %[^0-9]表示匹配除十进制数字以外的所有字符,遇到十进制数字就停止读取。
如下是代码示例:
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
char str11[30], str12[30];
scanf("%[^0-9]", str11);
scanf("%*[^\n]");
scanf("%*c"); //清空缓冲区
scanf("%[^\n]", str12); //等效为gets()
puts("执行后:");
printf("str1=%s \nstr2=%s\n", str11, str12);
system("pause");
return 0;
}
如下是输入和输出结果:
abcXYZ@#87edf
Cnblog_wingsummer
执行后:
str1=abcXYZ@#
str2=Cnblog_wingsummer
请按任意键继续. . .
丢弃数据
scanf
还允许把读取到的数据直接丢弃,不往变量中存放,具体方法就是在%
后面加一个*
,如下是代码示例:
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
int nn;
char str[30];
scanf("%*d %d", &nn);
scanf("%*[a-z]");
scanf("%[^\n]", str);
puts("执行后:");
printf("n=%d, str=%s\n", nn, str);
system("pause");
return 0;
}
如下是输入和输出结果:
100 999abcxyzABCXYZ
执行后:
n=999, str=ABCXYZ
请按任意键继续. . .
羽夏闲谈—— C 的 scanf 的高级用法的更多相关文章
- 羽夏闲谈——VSCode 配置 C/C++环境
前言 VSCode是微软发布一款跨平台的源代码编辑器,其拥有强大的功能和丰富的扩展,使之能适合编写许多语言.我的环境是64位Win10,如果是其他系统请自行判断调整.本人根据网上的配置方法在结合本 ...
- 羽夏闲谈—— C 语言入门之问
前言 最近加入了一个QQ频道,有很多想学C的纯小白.为什么这么说呢?因为他们会问一些环境用啥?为啥我配置不行?看了教程配置环境我也不会,咋配置?为啥这里代码这里有错误?啥语言好不好?诸如此类的问题 ...
- 羽夏看Win系统内核—— VT 入门番外篇
写在前面 此系列是本人一个字一个字码出来的,包括示例和实验截图.由于系统内核的复杂性,故可能有错误或者不全面的地方,如有错误,欢迎批评指正,本教程将会长期更新. 如有好的建议,欢迎反馈.码字不易, ...
- 羽夏 Bash 简明教程(上)
写在前面 该文章根据 the unix workbench 中的 Bash Programming 进行汉化处理并作出自己的整理,并参考 Bash 脚本教程 和 BashPitfalls 相关内容 ...
- 跟羽夏学 Ghidra ——工具
写在前面 此系列是本人一个字一个字码出来的,包括示例和实验截图.本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正. 如有好的建议,欢迎反馈.码字不易,如果本篇文章 ...
- (五)羽夏看C语言——结构体与类
写在前面 由于此系列是本人一个字一个字码出来的,包括示例和实验截图.本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正. 如有好的建议,欢迎反馈.码字不易,如果本篇 ...
- (四)羽夏看C语言——循环与跳转
写在前面 由于此系列是本人一个字一个字码出来的,包括示例和实验截图.本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正. 如有好的建议,欢迎反馈.码字不易,如果本篇 ...
- (三)羽夏看C语言——进制
写在前面 由于此系列是本人一个字一个字码出来的,包括示例和实验截图.本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正. 如有好的建议,欢迎反馈.码字不易,如果本篇 ...
- (二)羽夏看C语言——容器
写在前面 由于此系列是本人一个字一个字码出来的,包括示例和实验截图.本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正. 如有好的建议,欢迎反馈.码字不易,如果本篇 ...
随机推荐
- MyBatis 流式查询
流式查询指的是查询成功后不是返回一个集合而是返回一个迭代器,应用每次从迭代器取一条查询结果.流式查询的好处是能够降低内存使用. 流式查询的过程当中,数据库连接是保持打开状态的,因此要注意的是:执行一个 ...
- Regularizing Deep Networks with Semantic Data Augmentation
目录 概 主要内容 代码 Wang Y., Huang G., Song S., Pan X., Xia Y. and Wu C. Regularizing Deep Networks with Se ...
- uniapp跳转webview后H5不执行UniAppJSBridgeReady 回调无用
开始时我在真机上测试使用 <web-view :src="'/hybrid/html/pages/index/index.html?userInfo='+JSON.stringify( ...
- [数据结构]链表LinkList
目录 1.3 链表 1.3.1 头插法建立单链表 1.3.2 限制链表长度建立单链表 1.3.3 尾插法建立单链表 1.3.4 按序号查找单链表 1.3.5 按值查找单链表 1.3.6 链表的插入 1 ...
- docker构建.net core运行的镜像
在docker很火的今天,越来越多的应用现在都在往docker上迁移,.net core怎么能落后? 项目要运行在docker上,我们需要先制作镜像,可以基于centos来制作,当然也可以基于Ubun ...
- .net core的Swagger接口文档使用教程(一):Swashbuckle
现在的开发大部分都是前后端分离的模式了,后端提供接口,前端调用接口.后端提供了接口,需要对接口进行测试,之前都是使用浏览器开发者工具,或者写单元测试,再或者直接使用Postman,但是现在这些都已经o ...
- hexo 升级5.4.0出现错误解决方法-hexo-theme-butterfly
本篇文章已同步个人博客,可移步食用.hexo 升级 5.4.0 出现错误解决方法 -hexo-theme-butterfly 周末升级了下 hexo 到新版本,发现升级后,构建时出现了一些错误,以下是 ...
- ES6解构与默认值的结合使用
在读源码框架时遇到方法中有这样的形参:{ message = 'ok' } = {} 有点懵为什么已经赋值了还又赋了一个空对象 随后我去看了阮一峰老师的 ECMAScript 6 入门才明白.这是参数 ...
- docker的无用镜像
dangling images build 自己的 docker 镜像的时候,有时会遇到用一个甚至多个中间层镜像,这会一定程度上减少最终打包出来 docker 镜像的大小,但是会产生一些tag 为 n ...
- 详解Scrapy的命令行工具
接触过Scrapy的人都知道,我们很多操作是需要借助命令行来执行的,比如创建项目,运行爬虫等.所以了解和掌握这些命令对于scrapy的学习是很有帮助的! Scrapy 命令 首先,在scrapy命令中 ...