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时则会陷入死循环,具体见下面的实例。

小结:

  1. C语言中用getchar()函数或scanf获取char类型时,可用EOF作为结束符,见测试1;
  2. 对scanf,要在输入ctrl+z时,结束循环,用while ( scanf("%c",&ivar) != EOF ),见测试5;测试4、6是错误的用法;
  3. EOF就是一宏定义,用cin获取输入时,输入ctrl+Z不可结束循环,只是结束了流的输入,因此陷入死循环,见测试3;
  4. 注意EOF的使用场合,EOF本质就是一个宏定义,一般为-1,弄清楚这个就不会在用scanf以及cin输入时用EOF去作为结束条件了;
  5. 对于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等如何结束键盘输入的更多相关文章

  1. getchar()函数的返回值赋给char型,用if(ch=getchar() != EOF)测试,输入ctrl+z同样可以结束循环的分析

    2013-07-18 21:35:58 getchar()函数的返回值赋给char型,用if(ch=getchar() != EOF)测试,输入ctrl+z同样可以结束循环的分析. char是字符型数 ...

  2. C# 中怎么将string转换成int型

    int intA = 0;1.intA =int.Parse(str);2.int.TryParse(str, out intA);3.intA = Convert.ToInt32(str);以上都可 ...

  3. 编写一个应用程序,在主类Test1类中,创建两个链表List<E>对象,分别存储通过键盘输入的字符串内容

    题目1:编写一个应用程序,在主类Test1类中,创建两个链表List<E>对象,分别存储通过键盘输入的字符串内容--"chen","wang",&q ...

  4. Oracle数据库中字段定义为Char类型,Hibernate用该字段进行动态绑定参数查询,获取不到结果的问题

    一.问题背景 产生环境:oracle数据库,hibernate操作 定义了一个表 create table STORE_INFORMATION ( id CHAR(32) not null, name ...

  5. 求int型正整数在内存中存储时1的个数 && int型的数到底最大是多少?

    输入一个int型的正整数(十位数之内!嘞!),计算出该int型数据在内存中存储时1的个数. #include<bits/stdc++.h> using namespace std; int ...

  6. 在n个任意不相同的数中,输出r个数的组合,并且n和r由键盘输入。

    主要是运用递归的思想,函数主要两个参数,point是上一次取到的位置,picked主要记录在数组b中所取的元素的个数,函数的每一轮递归都会取一个数.   package pack; import ja ...

  7. VC++中的CString、char、int类型转换

    1.如何将CString类型的变量赋给char*类型的变量   方法一:GetBuffer函数  使用CString::GetBuffer函数.  char *p;  CString str=&quo ...

  8. Python 实int型和list相互转换 现把float型列表转换为int型列表 把列表中的数字由float转换为int型

    第一种方法:使用map方法 >>> list = [, ] #带有float型的列表 >>> int_list = map(int,list) #使用map转换 & ...

  9. C++中几个输入函数的用法和区别(cin、cin.get()、cin.getline()、getline()、gets()、getchar())

    1.cin>> 用法1:最基本,也是最常用的用法,输入一个数字: #include <iostream>using namespace std;main (){int a,b; ...

随机推荐

  1. qml去标题栏

    只要加入"flags: Qt.Window | Qt.FramelessWindowHint "属性就可实现去标题栏. 注意:在使用这个属性的时候要先导入QtQuick.Windo ...

  2. js优化 ----js的有序加载

    说到有序加载,我们先来说说js的无序加载: <script src="jquery/jquery-1.4.1.js" type="text/javascript&q ...

  3. 《编写高质量代码-Web前端开发修改之道》笔记--第一章 从网站重构说起

    本章内容: 糟糕的页面实现,头疼的维护工作 Web标准--结构.样式和行为的分离 前端的现状 打造高品质的前端代码,提高代码的可维护性--精简.重用.有序 糟糕的页面实现,头疼的维护工作 工作中最大的 ...

  4. VS2010 常见错误总结

    错误一:“此时无足够的可用内存,无法满足操作的预期要求,可能是由于虚拟地址空间碎片造成的,请稍后重试” 安装VS2010补丁:http://xiazai.jb51.net/201007/tools/V ...

  5. JS中如何判断null

    var exp = null; if (exp == null) { alert("is null"); } exp 为 undefined 时,也会得到与 null 相同的结果, ...

  6. 为 Web 设计师准备的 25+ 款扁平 UI 工具包

    Flat UI Kit by Riki Tanone (free) Flat UI Kit (PSD) by Devin Schulz (free) Eerste UI Kit (free) Metr ...

  7. Spark Streaming揭秘 Day5 初步贯通源码

    Spark Streaming揭秘 Day5 初步贯通源码 引子 今天,让我们从Spark Streaming最重要的三个环节出发,让我们通过走读,逐步贯通源码,还记得Day1提到的三个谜团么,让我们 ...

  8. Qt 内存管理机制(转)

      许转载http://devbean.blog.51cto.com/448512/526734 强类型语言在创建对象时总会显式或隐式地包含对象的类型信息.也就是说,强类型语言在分配对象内存空间时,总 ...

  9. Python for 循环 失效

    昨天发现一个负责处理观察者模式的基类工作失败,默认的N个观察者负责处理 发送的一些东西, 其中提供一个内置接口移除观察者: def removeObserver(self, observer): if ...

  10. Asp.net之LINQ入门视频教程

    当前位置: 主页 > 编程开发 > Asp.net视频教程 > Asp.net之LINQ入门视频教程 > http://www.xin1234.com/Program/Aspn ...