0%

scanf的使用(主要是针对char)

学的是C++,用cin cout也用的很顺溜,写自己的类时重载“<<”与“>>”运算符也很爽,但是发现在刷算法竞赛题时,cin cout很没优势,输入量大时一道题我用cin cout要50ms,用scanf printf只要10ms、20ms,这个就差的太大了时间都花在输入输出上也是很郁闷。于是开始使用C的输入输出标准。输出很正常,也可以轻松更改double输出的精度,c++还要个iomanip头文件,还烦一点。格式化字符%u %d %ld %lld %f %lf %s %c等就这几个限死了,也就是只能输入输出这几个系统自带的格式,是没法将自己的类重载到里面的,,只能自己做个print函数。不过毕竟面向对象是c++的内容。 就是那个输入scanf有些异类。首先输入得取地址,输入int的a要&a不能写a。这我总是忘记。先输入整形、long long、double、字符串什么的都没问题,可以任意换行。scanf("%d%d%d%d", &a, &b, &c, &d); 像下面这样输入

1
2
3
4
123  2

23
6
有任意空格和回车都可以接收。 而对于字符串char sss[100],不支持空格的读取,要读取空格得用gets()。 而scanf("%s",sss)还是scanf("%s",&sss)都可以,论坛里上说前者还少取个地址更快一点。 而对于char型,char ch;scanf("%c",ch);可以是可以,但是不能像int等一样随心所欲地加空格和回车,明明说好的scanf自带无视回车和空格。比如下一段代码

1
2
3
4
5
6
7
8
9
10
11
int main()
{
int a, b, c, d;
char x, y, z,s1[10],s2[10],s3[10];
scanf("%d%d%d%d", &a, &b, &c, &d);
scanf("%s%s%s", s1, s2, s3);
scanf("%c%c%c", &x, &y, &z);
printf("%c%c%c", x, y, z);
printf("%d%d%d%d\n'%c'\t'%c'\t'%c'\n%s\n%s\n%s", a, b, c, d, x, y, z,s1,s2,s3);
return 0;
}

输入:

1
111 222 333 444 555 666 777 8 9 0

输出:

1
2
3
4
5
111222333444
' ' '8' ' '
555
666
777请按任意键继续. . .

而输入:

1
2
3
4
5
6
7
8
111
222
333
444
555
666
777
890

则输出:

1
2
3
4
5
6
111222333444
'
' '8' '9'
555
666
777请按任意键继续. . .

char的什么回车啊空格啊都读进去了。 而如果先读入char,一旦char坏掉了,后面也全乱了。

####我总结的规律是: scanf读取int等内容时,读取完一个数据后后面的空格回车仅仅是表示这个数据输入完了,没有略过,它一直存在于输入缓冲区,而到了下一个数据,若也是int或字符串什么的,会自动把空格回车略过,直到找到应输入的内容,然后读取。而char不同,它不忽略本该读取的数据前面的空白,就把那空格或回车读进去了,如果是有多个空格回车,剩下那些空白就依然还存在与缓冲区,给下一个char读取了。

####我现在找到了以下几种解决方案

  1. 使用fflush(stdin)。scanf读取char之前,用fflush(stdin)空输入缓冲区,使其为空,然后输入char就不会有空白符阻碍了。
  2. scanf读取char之前使用getchar()把''和' '吃了,getchar()不跳过空格回车。当然getchar()几次,即吃几个字符也是个问题,所以本方法仅适用于比如竞赛题什么的,输入格式都很标准,不会出现不定多少的空格回车。不过现在想想好像scanf和getchar功能一样欸,都不跳空白的。那么这么说来直接用scanf吸收空格应该也是可以的,比如scanf("%c%c",&ch,&ch)但是好像没见人用过。
  3. VJ上看到这个写法scanf("%c",ch),即在每个输入char的scanf里的%c前面,都加上。对于在scanf里不仅仅写%c还写其他的东西,就像输出一样,我没细研究,就知道比如scanf("233%c666",ch)我必须先输入233再输入char再输入666,想想好像也有道理,以此来忽略,但是我发现它也可以忽略空格。虽然不是很懂,空格和回车在编译器眼里一样吗?于是试了试scanf(" %c",ch),也一样的效果!于是这就达到了与输入int、double一样的格式,任意输入多少空格和回车都没事了。现在也是这么在用,虽然其实我不是很懂其原理。
  4. CSDN论坛里看到有12级的大神说不要用scanf输入字符。。不是很懂,全用getchar()吗。。。还是输入字符转用cin。。。 0.0 [震惊哭]。

附[方法三]实例:

1
2
3
4
5
6
7
8
9
10
11
int main()
{
int a, b, c, d;
char x, y, z,s1[10],s2[10],s3[10];
scanf("%d%d%d%d", &a, &b, &c, &d);
scanf("%s%s%s", s1, s2, s3);
scanf(" %c\n%c %c", &x, &y, &z);
//x = getchar(), y = getchar(), z = getchar();
printf("%d%d%d%d\n'%c'\t'%c'\t'%c'\n%s\n%s\n%s", a, b, c, d, x, y, z,s1,s2,s3);
return 0;
}

输入:

1
2
3
4
5
6
7
1   2  3   
4 5
6
7
8
9
0

输出:

1
2
3
4
5
1234
'8' '9' '0'
5
6
7请按任意键继续. . .