谈一谈getchar()、EOF和Ctrl+D

原创 2015年07月10日 16:31:37

getchar()

  getchar从stdio流中读字符,getchar有一个int型的返回值.当程序调用getchar时.程序就等着用户按键.用户输入的字符被存放在键盘缓冲区中.直到用户按回车为止(回车字符也放在缓冲区中).当用户键入回车之后,getchar才开始从stdio流中每次读入一个字符.getchar函数的返回值是用户输入的第一个字符的ASCII码,如出错返回-1,且将用户输入的字符回显到屏幕.如用户在按回车之前输入了不止一个字符,其他字符会保留在键盘缓存区中,等待后续getchar调用读取.也就是说,后续的getchar调用不会等待用户按键,而直接读取缓冲区中的字符,直到缓冲区中的字符读完为后,才等待用户按键。[以上定义来自百度百科]

EOF

  计算机术语,缩写通常为EOF(End Of File),在操作系统中表示资料源无更多的资料可读取。资料源通常称为档案或串流。
  在C语言中,或更精确地说成C标准函数库中表示文件结束符(end of file)。在while循环中以EOF作为文件结束标志,这种以EOF作为文件结束标志的文件,必须是文本文件。在文本文件中,数据都是以字符的ASCII代码值的形式存放。我们知道,ASCII代码值的范围是0~255,不可能出现-1,因此可以用EOF作为文件结束标志。
  在 UNIX中, EOF表示能从交互式 shell (终端) 送出 Ctrl+D (习惯性标准)。在微软的 DOS 与 Windows 中能送出 Ctrl+Z。在控制台要输入eof的话 按ALT+65535就可以了。[以上概念来自百度百科]
  所以,EOF并不属于文件内容的一部分,它只是读不到更多内容时返回的结束标志。

看一个例子

1、

#include<stdio.h>
int main()
{
    int    a;
    while((a=getchar())!=EOF)
    {
        printf("a=%d\n",a);
    }
    printf("end:%d\n",a);
    return 0;
}

下面是几种不同情况下的输出:
(1)直接按Ctrl+D后,getchar()返回-1,退出
这里写图片描述
(2)输入一串字符后,再按Ctrl+D
这里写图片描述
所有字符被从缓冲区读出,与按回车不同的是,回车也会被送入缓冲,但Ctrl+D没有在缓冲区中体现出来。本来想,如同(1)一样,Ctrl+D相当于EOF(-1),在输出所有字符后,getchar()会遇到EOF输出-1的。
(3)输入一串字符后,连续按两次Ctrl+D
这里写图片描述
最后会得到-1,退出循环。
既然getchar()是从缓冲区中读字符,而根据(2)Ctrl+D是没有放入缓冲区的,为什么按两次Ctrl+D就会输出-1呢?
在网上查到的解释如下:
  输入缓冲是行缓冲。当从键盘上输入一串字符并按回车后,这些字符会首先被送到输入缓冲区中存储。每当按下回车键后,就会检测输入缓冲区中是否有了可读的数据。还会对键盘上是否有作为流结束标志的 Ctrl+Z(windows) 或者 Ctrl+D 键 按下作出检查,其检查的方式有两种:阻塞式以及非阻塞式。

  阻塞式检查方式指的是只有在回车键按下之后才对此前是否有 Ctrl+Z 组合键按下进行检查,非阻塞式样指的是按下 Ctrl+ D 之后立即响应的方式。如果在按 Ctrl+D 之前已经从键盘输入了字符,则 Ctrl+D的作用就相当于回车(但是回车自己也会进入缓冲),即把这些字符送到输 入缓冲区供读取使用,此时Ctrl+D不再起流结束符的作用。如果按 Ctrl+D 之前没有任何键盘输入,则 Ctrl+D 就是流结束的信号。

  Windows系统中一般采用阻塞式检查 Ctrl+Z、Unix/Linux系统下一般采用非阻塞式的检查 Ctrl+D。楼主是在Windows系统下,因此使用阻塞式的 Ctrl+Z 来标识流的结束。这种阻塞式的方式有一个特点:只有按下回车之后才有可能检测在此之前是否有Ctrl+Z按下。还有一个特点就是:如果输入缓冲区中有可读的数据则不会 检测Ctrl+Z(因为有要读的数据,还不能认为到了流的末尾)。还有一点需要知道:Ctrl+Z产生的不是一个普通的ASCII码值,也就是说它产生的 不是一个字符,所以不会跟其它从键盘上输入的字符一样能够存放在输入缓冲区。

[摘自:http://wenku.baidu.com/view/44e58e1d227916888486d744.html]
2、

#include<stdio.h>
int main()
{
    int    a;
    while((a=getchar())!=EOF)
    {
        sleep(1);
        printf("%d\n",a);
    }
    printf("end:%d\n",a);
    return 0;
}

在缓冲区字符没读完的时候按Ctrl+D
这里写图片描述
结果在输出所有字符后,getchar()返回了-1,说明只要没有键盘输入,直接Ctrl+D就会起作用。
  我觉得可以这样理解,每按一次Ctrl+D就表示结束一轮输入,此时Ctrl+D就告诉getchar()你去读缓冲区吧。当Ctrl+D之前有字符输入时,getchar就会正常读到字符。当直接按Ctrl+D时,缓冲区没有任何字符送进去,getchar()去读的时候什么也没读到,就会出错返回-1。

3、

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int c;
    system("stty raw");
    /* 现在的终端驱动处于一次一个字符模式 */
    while(1)
    {
        c = getchar();
        putchar(c);
    }

    /* 终端驱动处又回到一次一行模式 */
     system("stty cooked");

    return 0;
}

stty raw 可以实现键入一个字符立即读出的效果。此时回车不再起换行作用,按回车后光标会定位到行开头。

版权声明:本文为博主原创文章,未经博主允许不得转载。

Linux中ctrl-c, ctrl-z, ctrl-d 区别

在Linux中:         ctrl-c:
  • mylizh
  • mylizh
  • 2014年08月05日 15:55
  • 12254

ctrl-c,ctrl-z,ctrl-d区别

linux下:ctrl-c 发送 SIGINT 信号给前台进程组中的所有进程。常用于终止正在运行的程序。ctrl-z 发送 SIGTSTP 信号给前台进程组中的所有进程,常用于挂起一个进程。ctrl-...
  • ptn3900
  • ptn3900
  • 2011年06月07日 16:54
  • 6000

python ctrl +d 退出

ctrl+d
  • hzdxw
  • hzdxw
  • 2016年06月28日 08:58
  • 1401

ctrl-c,ctrl-z,ctrl-d区别

linux下: ctrl-c 发送 SIGINT 信号给前台进程组中的所有进程。常用于终止正在运行的程序。 ctrl-z 发送 SIGTSTP 信号给前台进程组中的所有进程,常用于挂起一个进程。 ...
  • monsion
  • monsion
  • 2014年04月03日 15:46
  • 1675

ctrl-c,ctrl-z,ctrl-d区别

linux下: ctrl-c 发送 SIGINT 信号给前台进程组中的所有进程。常用于终止正在运行的程序。 ctrl-z 发送 SIGTSTP 信号给前台进程组中的所有进程,常用于挂起一个进程。 ...

(K&amp;R小结第1篇)1.5 中关于getchar,Ctrl+Z,EOF的一些问题讨论

最近在读K&R,故开此栏,希望能早点读完这一本C的巨作。 在1.5中,作者讨论了EOF,getchar()的一系列问题,我在测试过程中发现了关于ctrl+Z以及EOF的一些问题,改变了我之前的理解。...
  • azard5
  • azard5
  • 2013年10月30日 15:04
  • 209

选择排序---while( scanf("%d",&n)!= EOF)与getchar()简介及其存在的问题,

基本思想: n个记录的文件的直接选择排序可经过n-1趟直接选择排序得到有序结果: ①初始状态:无序区为R[1..n],有序区为空。 ②第1趟排序 在无序区R[1..n]中选出关键字最小的记录...

FatMouse's Speed Hdu1160 动态规划 EOF(Ubuntu 下codeblocks 按 Ctrl+D)

FatMouse's Speed Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)...
  • khn64
  • khn64
  • 2017年08月10日 10:14
  • 90

getchar函数和EOF总结

  • 2009年12月05日 15:49
  • 5KB
  • 下载

谈一谈Cocos2d-x中的某些“大小”

[Cocos2d-x相关教程来源于红孩儿的游戏编程之路 CSDN博客地址:http://blog.csdn.net/honghaier] 红孩儿Cocos2d-X学习园地QQ群:249941957加...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:谈一谈getchar()、EOF和Ctrl+D
举报原因:
原因补充:

(最多只允许输入30个字)