Last Edit: 2023/9/1
大家都知道 scanf
中可以以 %d
%s
%f
等作为占位符,但是有一种特殊的占位符 TA 的形式如: %[<Fmt>]
,下面称之为 集合占位符。
这是一种不大常用的方法,但是个人觉得很好用!
在这里有所提及:CppReference std::scanf,std::fscanf,std::sscanf
下面使用
scanf
来代指和scanf
有类似功能的函数 (scanf
/sscanf
/fscanf
等 )
大家可能听说过在字符串匹配操作中有一种常用操作叫正则。集合占位符的用法很类似正则。虽然 STL 中引入了正则库,但在算法竞赛中这个库常常是不被提供的,而集合占位符存在于 C 库中,于是我们可以很方便的使用 TA 来方便地编写字符串处理逻辑。
在上述占位符中的 <Fmt>
需要填入一些用于控制格式的字符,这会在下面简单地讲述并给出例子,具体建议参照 Cppreference 上的表格来了解。
某些时候,题目中会有用于标识类型的字符(e.g. 操作一以字符 'a' 开头, 操作二以字符 'b' 开头),我们就可以愉快地使用集合占位符了。
e.g.: 想要读取 #+?$
这四种字符中的任意一种 ( Luogu P2814 家谱 ),那么我们可以这样:
cppchar c;
scanf("%[#+?$]", &c);
在运行过程中,只有遇到 #+?$
中任意一个字符才会对变量 c 进行赋值操作,会给变量 c 赋值上上述提到的任一读到的字符,否则 scanf 将一直按位从 stdin 读取字符、直到遇到规定的字符或结束操作。
有一种特殊情况需要考虑,[
和 ]
显然也是 ASCII 字符。如果使用类似 %[]]
的占位符,会按照指定 ]
字符进行读取。
有些时候,我们可能会遇到需要读取数字/字母的情况。
这里介绍的使用方法,可以读取一个字符区间内的字符。
有的人就会问了:我干嘛不写个快读? 反问:就用一次你写啥快读?写炸了咋办?
e.g.: 想要读取一个字符的数字字符,那么我们可以这样:
cppchar c;
scanf("%[0-9]", &c);
那还想读一下多位的数字怎么办,看这里:
cppchar c[50];
scanf("%[0-9]", c);
你还记得上面使用指定字符的时候,我们可以同时放入多个字符吗?有没有一种可能,在范围读取的时候也可以这么做,下面给出常用情况的例子:
%[A-Za-z]
匹配所有的英语字母%[A-Za-z0-9]
匹配所有的英文字母和十进制数字%[a-f0-9]
匹配十六进制数字(注意,只能读入字符串。如果你希望读入,请使用 %x
)我们可以使用 ^
符号开头的限定符来规定直到哪个/哪些字符我们才停止读入,这样一来就可以读取到指定字符或抛弃不需要读取的字符了!
e.g.: 我们想读取到 \n
字符才结束,可以这样
cppchar l[50];
scanf("%[^\n]", l);
在这种情况,遇到了 \n
字符的时候会直接结束,所以字符串 l 的最后一位不是 \n
但在输入流里面还有一个 \n
字符,这时候我们最好这么写
cppchar l[50];
scanf("%[^\n] ", l);
相比于上一段代码多了个空格,这意味着清理掉输入流中的空白字符。
cppscanf("%*[^\n] ");
这样我们就可以直接抛弃掉一行输入(但好像不多用)。
很多时候我们需要限定读入字符的数量,这也可以通过某些方法来实现。
e.g.: stdin 为 123456
的情况下,使用如下代码,输出为 123
cppchar buf[50];
scanf("%3[0-9]", buf);
printf("%s", buf);
当然,不只是集合占位符才可以这样用,这同样适用于 %s
之类的占位符。
正常情况 scanf
需要在参数中提供一个指针来进行赋值
但总有一些时候我们希望不这么做,e.g. 去除一些无效的字符时。
如果你只是想忽略特定格式的字符串,在 %s
等占位符中,可以使用 *
来表明这个占位符不需要赋值
显然,集合占位符也可以使用抑制赋值标志 *
!
e.g.:
\n
的字符串,那么我可以这么用:
cppscanf("%*[^\n]");
cppscanf("%*[a-z]");
本文作者:CornWorld
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!