C/C++ cin, scanf, getchar(), 文件结束符EOF等常见问题
1. 为什么用while(cin>>a)一直跳不出循环?(cin的">>"函数返回值是什么?)
问题描述:
《C++ primer》上也出现过类似如下代码,然后自己在控制台输入数据,一直输入都跳不出循环。
int a;
while(cin>>a){
}
原因:
cin
是一个类,没有返回值,while
判断条件其实是在判断>>
函数的返回值。>>
是一个被重载过的运算符,这个重载函数的返回值类型为istream&
,返回值通常就是输入流cin本身,如果没有遇到错误输入或者文件末尾EOF
,cin
就一直有效,当然就跳不出while
循环。- 当你在键盘上输入
Ctrl+Z
,再按Enter
键,就等同于输入遇到了文件末尾EOF
,遇到EOF
后,>>
函数的返回值是0
,就能结束while
循环了。
2. scanf的返回值是什么?(EOF是什么类型的数据,值是多少?)
问题:
while(scanf("%d %d",&a,&b)){ }
为何是死循环?遇到文件结束符EOF也跳不出循环?
原因:
scanf
是函数,这和cin
不同,cin
是一个类,而>>
是cin
类中的函数。
scanf
返回的是成功输入数据的个数,例如scanf(”%d %d",&a,&b)
成功输入两个数,返回值就是2
,scanf("%d",&a)
成功输入一个数,返回值就是1
。- 当遇到文件末尾时,
scanf
函数返回值是EOF
。 EOF
是一个宏,标准规定EOF
必须是一个int
类型的负数,编译器通常令EOF
的值为-1
。因此,想要跳出循环,要写成while( scanf("%d %d",&a,&b) !=EOF){ }
。
3. 为什么我cin只输入1个或几个数,在键盘上输入了多个(超过几个)数之后,控制台输入界面仍然不停止?(输入的数据什么时候才会进入缓冲区?)
问题描述:
例如以下代码,明明只用cin
输入2
个数,在键盘上输入数据空格重复多次仍要继续输入。
输入示例:1空格2空格3空格4空格5回车
int a, b;
cin >> a >> b;
原因:
- 调用
cin
的">>
“函数时,程序就等着用户按键,直到用户按下回车键,包换换行符在内的这一行数据才被放入缓冲区中,形成输入流,提取符”>>
"才能从中提取数据。 - 也就是说,没按下回车键之前,你在键盘上输入的数据都还没被放入缓冲区只是在控制台上显示出你按下的数据了而已,这也是为什么我们输错了的时候还能按退格键删除数据然后重新输入。
- 以上面程序为例,当你在键盘上输入了超过
2
个字符时,其他字符也会被保留在缓冲区中,等待后面程序中的cin >>
读取,若后面程序中再出现cin >> c
之类的,程序也不会出现控制台等待用户输入,而是直接读取缓冲区中剩下的数据,直到缓冲区中的字符读完后,才等待用户按键。
4. getchar()函数的返回值是什么?输入数字1,为什么输入的确是49?
原因:
getchar()
函数会从stdin
中读入一个字符(空格回车等空白符它也不会跳过,通通都读),并返回一个int
型数据,返回的是输入字符的ASCII
码。- 也就是说,你输入数字
1
,它返回的是数字1
的ASCII
码49
,你输入字符A
,它返回的是字符A
的ASCII
码65
,你输入空格
,它返回的是空格
的ASCII
码32
。 - 一般都是用
getchar()
来判断是否已经到了一行末尾,因为它换行符也读。 - 以下为
getchar()
函数实测:
上图键盘输入的是:3空格AB空格7空格1空格2回车
,可以看到scanf
输入的3
输出也是3
,getchar
把空格也读进来了,并且输出空格的ASCII
码32
。
5. 在大多数场合,用scanf和printf是真的比cin和cout快。
但是scanf
和printf
用着麻烦,每次还要自己写输入输出类型%c%f%d
什么的,而cin
和cout
的">>
"、"<<
"都是被重载过的运算符,可以读入或输出各种类型的数据。