scanf 分隔符完整详解
基础规则:
%d、%lf、%f、%s这类转换符,默认自动跳过 空格、Tab\t、回车换行\n,这三类叫空白符 。 遇到,;:#这类普通字符不会自动跳过,会停止读取。
情况 1:想用别的符号当分隔符(比如逗号 ,)
输入样例:100,88.5,72 数字用逗号隔开
方法:把分隔字符直接写进 scanf 格式字符串里面
int a;
double b,c;
//格式串里面写逗号 ,
scanf("%d,%lf,%lf", &a, &b, &c);
✅输入必须:100,88.5,72
原理:scanf 读到
%d读完数字之后,去格式串找一个逗号,去输入流里面吃掉这个逗号字符,才继续读下一个 % lf。
⚠️坑:输入不能多空格! 比如输入 100 , 88.5 ,72(逗号两边带空格),上面代码读取失败。 想要允许逗号前后随便带空格,写成:
scanf("%d ,%lf ,%lf", &a, &b, &c);
%d后面加一个空格:scanf 空格代表吃掉任意数量空白(0 个 / 多个空格 tab 回车),然后再读逗号。
示例 1:分号;做分隔,输入:50;20.5;33
scanf("%d;%lf;%lf", &a, &b, &c);
示例 2:输入格式 id:123 score:98.5
int id;
double score;
scanf("id:%d score:%lf", &id, &score);
输入就必须照样子输入:id:123 score:98.5
scanf 格式串里面除了
%格式符号,其余普通字符要求输入流原样匹配吃掉。
区分两个概念非常重要
- 格式串里面的空白字符(空格、\t、\n)
scanf("%d %lf", &a,&b);
这里两个 % d 中间多个空格:吃掉输入中任意多空白(0、1、N 个空格 /tab/ 换行都可以)。 👉 不管输入中间 1 个空格、10 个空格、换一行,全部兼容。
- 格式串里面写普通可见字符
, ; : -scanf("%d,%lf", &a,&b);
要求输入流必须实实在在出现这个字符,scanf 才会把它读走丢弃;没读到这个字符,直接终止读取,后续变量读取失败,值是垃圾。
常见坑演示
❌错误例子
int a,b;
scanf("%d%d",&a,&b);
输入:10,20(用逗号分隔)
%d读走 10,接下来输入缓冲区字符是,,%d遇到逗号不是数字直接停止。- b 读取失败,b 里面是随机垃圾值,输出 0 或者乱码。
这就是你刚才牛客自测输入写
17140216;80.845,90.55,100.00全部变成 0 的根源!
拓展:如果分隔符不确定,一会逗号,一会空格怎么办?
scanf 本身做不到,这种场景就不要用 scanf,改用getchar()手动读取吃掉多余字符。
int a,b;
scanf("%d", &a);
getchar(); //手动吃掉逗号/分号
scanf("%d", &b);
% c 特殊(重中之重刷题坑)
%c不会自动跳过空白符!!
char ch;
scanf("%c", &ch);
输入: A(前面有空格),ch 读到的是空格字符,不是 'A'。
如果想要读字符,跳过前面空格,两种写法:
写法 1(最常用):scanf(" %c", &ch);
%c格式符前面加一个空格
char ch;
scanf(" %c", &ch);
写法 2:手动调用getchar()吃掉空白字符
手动循环把空格、换行、tab 全部读走丢掉,直到遇到普通字符。
简单版本(只吃掉 1 个字符,只适合确定只有 1 个空白)
char ch;
getchar(); //手动吃掉前面那一个空格
scanf("%c", &ch);
❌缺点:如果前面有好几个空格 / 多个换行,只吃掉 1 个,剩下空格依旧被 % c 读进去,不安全,OJ 不推荐。
✅健壮循环版本(真正第二种标准写法,处理任意多个空白)
char ch;
//只要读到的还是空白字符,就一直丢弃
while( (ch = getchar()) == ' ' || ch == '\t' || ch == '\n' )
{
//循环体空,什么都不干,仅仅消耗掉空白字符
}
//退出循环的时候ch已经读到非空白字符A
原理:循环不断 getchar,遇到空格、tab、换行就扔掉;读到 A 就退出循环,ch 存 'A'。
对比:
scanf(" %c", &ch):scanf 内部已经帮你封装好了这个循环,一行搞定,刷题首选。- while+getchar 循环:手动实现,自由度更高,可以自定义要跳过哪些字符(不止空格,也可以跳过逗号分号)。
补充拓展:还有scanf()集合 %[ ] 高级格式(了解即可,入门很少用)
char ch;
scanf("%*[ \t\n]%c", &ch);
%*[ \t\n]
[]:匹配括号内的字符集合*:读取但是不保存到变量,直接丢弃 含义:读入并丢弃所有空格、tab、换行,之后再读取一个字符到 ch。 效果等价于" %c",属于 scanf 高级语法,刷题几乎不用。