OI 常用的输入方法和技巧
cin
cin
可能是最简单的输入方式,但相比于 scanf
,cin
的速度更慢(关闭同步后会变快)。
cin
可以输入多种类型的数据并且不必写出输入的每个数据的具体类型(不像 scanf
),但是在读入一些特殊的类型(如特殊格式、指定的文本)方面不易操作。
cin
读到文件尾则会返回 -1
(也就是 EOF
)。
scanf
scanf
是 C 中的输入方式,但是速度比 cin
快不少。使用 scanf
时注意要在双引号中选择正确的格式说明符,读入的数据要用 &
取地址。
注意:scanf
不能读取 string
类型的变量。
格式说明符
在 OI 中,常用的格式说明符如下:
%d
:读入int
型整数;%lld
:读入long long
型整数;%a
:读入float
型;%la
:读入double
型;%lla
:读入long double
型;%c
:读入一个字符;%s
:读入一个字符串;
(对于 %a
、%la
、%lla
,其中的 a
可以改为 e
、f
、g
。)
%c
只能读入一个字符,而 %s
读入的是字符数组。使用了错误的说明符会导致程序运行错误。
返回值与不定长输入
与 cin
一样,scanf
会返回成功读取的数据个数,读到文件尾则会返回 -1
(也就是 EOF
)。
对于一些输入数据个数不确定的题目(比如著名的导弹拦截),我们可以利用这点输入数据。参考代码:
int n=0,a[2005];
while(scanf("%d",&a[++n])!=EOF);
n--;
(读入到 EOF
时仍然执行了 ++n
,因此需要 n--
。)
输入固定格式的数据
在输入一些数据时有固定格式,例如在输入时间时有 hh:mm
,为了防止在输入时将冒号作为数据的一部分读取,我们可以在 scanf
中两个格式说明符之间加上 :
,即为 scanf("%d:%d",&h,&m)
。注意,这需要保证读入的数据满足这个格式。
示例:读入格式为 [编号]年/月/日 - 时:分:秒
的数据:
int n,y,m,d,hh,mm,ss;
scanf("[%d]%d/%d/%d - %d:%d:%d",&n,&y,&m,&d,&hh,&mm,&ss);
getchar
getchar
会返回读取到的一个字符,以此写成的快读(可能)比前两者更快,且更易于扩展。与前两者一样,读到文件尾时 getchar
会返回 EOF
。
注意:getchar
返回一个字符。若这个字符为数字,其 ASCII 码比其代表的数字多 48。
快读
最简单的快读的基本原理便是逐个读入字符直到数字,再逐个读入数字直到结束。代码实现如下:
int read(){
int w=0,f=1;//w 为数,f 为符号
char ch=getchar();
while(ch<'0'||ch>'9'){//读取数字之前的字符
if(ch=='-')f=-1;//如果是负号则 f=-1
ch=getchar();
}
while(ch>='0'&&ch<='9'){//读取数字
w=w*10+ch-48;//ASCII 码减去 48 才是真正的数字
ch=getchar();
}
return w*f;
}
读入指定字符
使用类似的方法,我们可以只读取指定的字符,忽略其他字符。
例一:读取 01 串,直至下一个其他字符:
int n=0;
bool a[105];
char ch=getchar();
while(ch!='0'&&ch!='1')ch=getchar();//读取串之前的其他字符
while(ch=='0'||ch=='1'){//读取 01 串
a[++n]=ch;
ch=getchar();
}
例二:读取一段话并统计其中出现的空格数量,直至文件尾。
int cnt=0;
char ch=getchar();
while(ch!=EOF){
if(ch==' ')cnt++;
ch=getchar();
}
后记
-
使用
getchar
快读不一定比关闭了同步的cin
快,因此更常用的方法是使用fread
写快读,在此不过多讲述。 -
从控制台读取时,需要按下 Ctrl+Z 输入文件尾。从文件读取或是在 OJ 上测评则不会有此问题。
-
参考资料: