while ((ch = getchar()) != EOF)中ch定义为char还是int型?cin、scanf等如何结束键盘输入
2013-07-09 18:55:42
EOF是文件的结束符,具体可以作为文本文件的结束符,也可以作为键盘输入char类型数据时的结束符。对于不同的系统,EOF的定义可能不同,一般定义为-1。因为char类型的数据范围是0~255,不可能是-1,EOF定义为0~255之外的数据理论上都是可以的。
一般在C语言中用getchar()函数或scanf获取char类型时,可用EOF作为结束符。但对于C++,若用getchar()函数或scanf获取char类型时,也可用EOF作为结束符,这是兼容C的特性;但若用cin获取char类型数据,若试图用EOF结束输入,输入ctrl+z时则会陷入死循环,具体见下面的实例。
小结:
- C语言中用getchar()函数或scanf获取char类型时,可用EOF作为结束符,见测试1;
- 对scanf,要在输入ctrl+z时,结束循环,用while ( scanf("%c",&ivar) != EOF ),见测试5;测试4、6是错误的用法;
- EOF就是一宏定义,用cin获取输入时,输入ctrl+Z不可结束循环,只是结束了流的输入,因此陷入死循环,见测试3;
- 注意EOF的使用场合,EOF本质就是一个宏定义,一般为-1,弄清楚这个就不会在用scanf以及cin输入时用EOF去作为结束条件了;
- 对于cin常用的是用while(cin>>ch)结束,这是与cin的工作方式有关的,这里不再赘述,不要将cin与EOF结合起来使用,如测试3所示,就是一种很另类的写法。
下面给出了C语言下EOF的测试、以及C++下用getchar()函数获取输入以及用cin获取输入时的测试。
测试1:
C语言下EOF的测试代码:
#include <stdio.h> int main()
{
//int ch; char ch; while ( ( ch = getchar() ) != EOF )
{
putchar(ch);
}
}
输入ctrl+z可结束循环。若定义ch为int型,同样可以正常结束循环,在好多文章(如博文http://www.cnblogs.com/youngforever/articles/3180812.html,以及http://www.cnblogs.com/youngforever/articles/3180896.html
)提到不能将ch定义为char,不是为何???
原因分析见:http://www.cnblogs.com/youngforever/p/3199564.html
测试2:
C++下用getchar()函数获取输入的测试
上面的是对C语言而言的,一般在C语言中用getchar()函数或scanf获取char类型时,可用EOF作为结束符。但对于C++,若用getchar()函数或scanf获取char类型时,也可用EOF作为结束符,这是兼容C的特性;如下:
#include <iostream>
using namespace std; int main()
{
//int ch;
char ch; while ( ( ch = getchar() ) != EOF )
{
putchar(ch);
}
}
与上面的C代码运行结果一样,输入ctrl+z可结束循环。若定义ch为int型,同样可以正常结束循环。
测试3:
C++下用cin函数获取输入的测试
但若用cin获取输入,就不能用EOF作为结束符。我们知道用cin时,一般这样写while(cin>>ch),windows下,输入ctrl+z,便可结束输入(具体原因,参见cin的介绍)。
而下面的写法就是很另类的写法,会使得程序陷入死循环:
#include <iostream>
using namespace std; int main()
{
char ivar;
//int ivar;
cin>>ivar;
while ( ivar != EOF )
{
cout<<"display the input : "<<ivar<<endl;
cin>>ivar;
}
}
ivar为char类型时,会显示从键盘上输入的一切字符,除非ivar的值为-1,但因为ivar是char类型的,因此通过cin输入的ivar不可能为-1,自由通过ctrl+c才能结束程序,若试图通过输入ctrl+z,则会一直输出最后输入的字符,如下为上面代码的运行结果:
(可以看到,输入-1,会当做字符'-' '1'处理,而输入ctrl+z后,则一直输出最后输入的字符d,按下ctrl+c才结束)
display the input :
display the input :
-
display the input : -
display the input :
fsi
display the input : f
display the input : s
display the input : i
d
display the input :
display the input : d
^Z
display the input : d
display the input : d
display the input : d
display the input : d
display the input : d
display the input : d
display the input : d
display the input : d
display the input : d
display the input : d
display the input : d
display the input : d
display the input : d
display the input : d
display the input : d
display the input : d
display the input : d
display the input : d
display the input ^C请按任意键继续. . .
原因分析:
cin将ctrl+z作为输入流的结束,此时再从键盘接收输入,而ivar的值保留为上一个从cin接收的值d,ivar='d',这样while 的条件( ivar != EOF )一直为true,因此陷入死循环
一直执行while中的cout,cin不再执行,因为输入的ctrl+z已经结束了流的输入。
若上面代码中的ivar为int型,输入-1便可结束循环,因为EOF就是-1,但若输入ctrl+z,陷入死循环,原因同上。
ivar为int型时的运行结果:
(输入-1结束循环)
display the input : display the input :
-
display the input : -
-
请按任意键继续. . .
(输入ctrl+z陷入死循环,要用ctrl+c结束):
display the input :
-
display the input : -
^Z
display the input : -
display the input : -
display the input : -
display the input : -
display the input : -
display the input : -
display the input : -
display the input : -
display the input : -
display the input : -
^C请按任意键继续. . .
测试4:
scanf函数输入int(输入ctrl+z,不会陷入死循环):
#include <iostream>
using namespace std; int main()
{
int ivar;
scanf("%d",&ivar);
while ( ivar != EOF )
{
printf("display the input : \n");
printf("%d\n",ivar);
scanf("%d",&ivar);
} return ;
}
此时,输入-1便可结束循环,但是输入ctrl+z不会陷入死循环,而是输出上一个scanf输入的数据,这是因为循环的结束条件是输入-1,ctrl+z不是-1,因此不会结束循环,但是scanf函数也不会结束,因为对于scanf函数而言,ctrl+z并不是它的结束标志,因此会输出ivar,而ivar保持原来的值。
运行结果为:
display the input : -
display the input :
-
^Z
display the input :
-
^Z
display the input :
-
-
请按任意键继续. . .
测试5:
scanf函数控制输入的正确用法:
#include <iostream>
using namespace std; int main()
{
char ivar;
while ( scanf("%c",&ivar) != EOF )
{
printf("display the input : \n");
printf("%c\n",ivar);
} return ;
}
运行结果与测试1相同。
测试6:
scanf函数控制输入的错误用法:
scanf函数输入char(输入ctrl+z,不会陷入死循环):
#include <iostream>
using namespace std; int main()
{
char ivar;
scanf("%c",&ivar);
while ( ivar != EOF )
{
printf("display the input : \n");
printf("%c\n",ivar);
scanf("%c",&ivar);
} return ;
}
测试结果:
(可以看到scanf是可以接受回车的,在输出时同样为回车,且输入-1时,是当做字符处理的,因为ivar此时为char类型,输入ctrl+z时不结束循环,输出为为右箭头,原因未知)
12a
display the input : display the input : display the input :
a
display the input : -
display the input :
-
display the input : display the input : 2s^Z
display the input : display the input :
s
display the input : ^Z
display the input : display the input : display the input : display the input : ^C请按任意键继续. . .
while ((ch = getchar()) != EOF)中ch定义为char还是int型?cin、scanf等如何结束键盘输入的更多相关文章
- getchar()函数的返回值赋给char型,用if(ch=getchar() != EOF)测试,输入ctrl+z同样可以结束循环的分析
2013-07-18 21:35:58 getchar()函数的返回值赋给char型,用if(ch=getchar() != EOF)测试,输入ctrl+z同样可以结束循环的分析. char是字符型数 ...
- C# 中怎么将string转换成int型
int intA = 0;1.intA =int.Parse(str);2.int.TryParse(str, out intA);3.intA = Convert.ToInt32(str);以上都可 ...
- 编写一个应用程序,在主类Test1类中,创建两个链表List<E>对象,分别存储通过键盘输入的字符串内容
题目1:编写一个应用程序,在主类Test1类中,创建两个链表List<E>对象,分别存储通过键盘输入的字符串内容--"chen","wang",&q ...
- Oracle数据库中字段定义为Char类型,Hibernate用该字段进行动态绑定参数查询,获取不到结果的问题
一.问题背景 产生环境:oracle数据库,hibernate操作 定义了一个表 create table STORE_INFORMATION ( id CHAR(32) not null, name ...
- 求int型正整数在内存中存储时1的个数 && int型的数到底最大是多少?
输入一个int型的正整数(十位数之内!嘞!),计算出该int型数据在内存中存储时1的个数. #include<bits/stdc++.h> using namespace std; int ...
- 在n个任意不相同的数中,输出r个数的组合,并且n和r由键盘输入。
主要是运用递归的思想,函数主要两个参数,point是上一次取到的位置,picked主要记录在数组b中所取的元素的个数,函数的每一轮递归都会取一个数. package pack; import ja ...
- VC++中的CString、char、int类型转换
1.如何将CString类型的变量赋给char*类型的变量 方法一:GetBuffer函数 使用CString::GetBuffer函数. char *p; CString str=&quo ...
- Python 实int型和list相互转换 现把float型列表转换为int型列表 把列表中的数字由float转换为int型
第一种方法:使用map方法 >>> list = [, ] #带有float型的列表 >>> int_list = map(int,list) #使用map转换 & ...
- C++中几个输入函数的用法和区别(cin、cin.get()、cin.getline()、getline()、gets()、getchar())
1.cin>> 用法1:最基本,也是最常用的用法,输入一个数字: #include <iostream>using namespace std;main (){int a,b; ...
随机推荐
- 基于IOS和Android设备MDM技术方案服务价格
导读:前段时间 www.mbaike.net 博客被恶意攻击,导致程序崩溃,目前已经替换了以前的Wordpress程序,现提供IOS和Android版本MDM的代码和相关文档咨询服务. 一.IOS版M ...
- [转]PHP5.5安装PHPRedis扩展
phpredis是个人觉得最好的一个php-redis客户端,因为其提供的function与redis的命令基本一致,降低的了学习成本,同时功能也很全面. 一.linux安装方法 phpredis下载 ...
- String inputStream file转化
String --> InputStreamByteArrayInputStream stream = new ByteArrayInputStream(str.getBytes()); Inp ...
- DTCMS获取栏目子类
<%set DataTable categoryList=get_category_child_list(channel,0)%> <%foreach(DataRow cdr in ...
- php无极分类
<?php date_default_timezone_set('PRC'); header('Content-type:text/html;charset=UTF-8'); /* $a_lis ...
- hibernate的n+1问题
下面选自<精通Hibernate:Java对象持久化技术详解>作者:孙卫琴 在Session的缓存中存放的是相互关联的对象图.默认情况下,当Hibernate从数据库中加载Customer ...
- phpmailer 实现发送邮件
在注册的时候,常常会用到邮件验证,一直想弄明白这是怎么实现的,记得2年前曾经试过这个问题,没有实现,今天困到不行的时候开始决定搞明白这个,然后,然后就出来了. <?php require(&qu ...
- 浅析nginx的负载均衡
Nginx 的 HttpUpstreamModule 提供对后端(backend)服务器的简单负载均衡.一个最简单的 upstream 写法如下: upstream backend { server ...
- linux下使用sqlplus使用上下键显示历史命令
在linux下使用sqlplus没有在windows下方便,既不好用习惯的退格键,也无法通过上键来显示上一条的命令,这里我们使用rlwrap来解决. 1.安装rlwrap [root@toughhou ...
- Button控件
1.通过设置AutoSize(bool)属性来控制按钮的大小以适应文本的长度 btn_One.AutoSize = true;//设置按钮基于内容自动调整大小 2.当按钮得到焦点是自动放大,失去焦点时 ...