关闭

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

标签: 缓冲区EOFCtrl+Dgetchar
954人阅读 评论(0) 收藏 举报
分类:

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

0
0

猜你在找
【直播】机器学习&数据挖掘7周实训--韦玮
【套餐】系统集成项目管理工程师顺利通关--徐朋
【直播】3小时掌握Docker最佳实战-徐西宁
【套餐】机器学习系列套餐(算法+实战)--唐宇迪
【直播】计算机视觉原理及实战--屈教授
【套餐】微信订阅号+服务号Java版 v2.0--翟东平
【直播】机器学习之矩阵--黄博士
【套餐】微信订阅号+服务号Java版 v2.0--翟东平
【直播】机器学习之凸优化--马博士
【套餐】Javascript 设计模式实战--曾亮
查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:79004次
    • 积分:1545
    • 等级:
    • 排名:千里之外
    • 原创:70篇
    • 转载:18篇
    • 译文:0篇
    • 评论:14条
    友情链接
    最新评论