zoukankan      html  css  js  c++  java
  • 解剖getchar和putchar

    一、首先来看一个例子:

    #include <stdio.h>

    int main( )

    {

    int c;

    c = getchar();

    while (c != EOF)

    {

    putchar();

    c= getchar();

    }

    return 0;

    }

    这里主要解释下为什么要用int型来接受getchar函数。

    很多时候,我们会写这样的两行代码:

    char c;

    c = getchar();

    这样就很有可能出现问题。因为getchar函数除了返回终端输入的字符外,在遇到Ctrl+D即文件结束符EOF时,getchar ()的返回EOF,这个EOF在函数库里一般定义为-1。因此,在这种情况下,getchar函数返回一个负值,把一个负值赋给一个char型的变量是不正确的。

    二、下面用一个题目来看其实如何获取字符和输出字符的。

    #include "stdio.h"

    main()

    {

    char c,d,e,f;

    printf("please input two characters: ");

    c=getchar();

    putchar(c);

    putchar(' ');

    d=getchar();

    putchar(d);

    putchar(' ');

    e=getchar();

    putchar(e);

    putchar(' ');

    f=getchar();

    putchar(f);

    putchar(' ');

    printf("c= %c ",c);

    printf("d= %c ",d);

    printf("e= %c ",e);

    printf("f= %c ",f);

    }

    运行后先输入“12”,回车,再输入“34”,回车。

    运行环境是redhat gcc

    运行结果:

    $: please input two characters:

    12

    1

    2

    34

    3

    c=1

    d=2

    e=

    f=3

    下面具体解释一下:

    getchar函数每次从缓冲区中得到一个字符(包括换行符),putchar函数每次输出一个字符(包括换行符)。

    首先输入了两个字符12,然后回车,注意这时写入缓存中的有3个字符1,2,回车。

    程序中有四个getchar(),于是c='1',d='2',e=' '。

    这时运行到f=getchar();输入缓存中的三个字符均被前三个getchar获取,这时需要用户输入,

    这里输入了34

    于是f='3',4和后面的回车没有被利用。

    这便是整个流程。

    这里我们要注意下面几条:

    1)用getchar读入时,如果不按回车符,所有输入会放入缓冲区,而不会被读入,所以执

    行c=getchar();时,我们输入12,如果不按回车键,1仍然不会读入;

    2)最后按下的回车键,虽是用来告诉系统输入已结束,但同时也会作为一个字符放入缓冲

    区,所以我们输入12,按回车后,输入流其实有三个字符:1、2、回车,而这个回车就被e读取了;

    3) 12是被当做两个字符1和2(注意,不是数字1、2),而不像%d时,作为一个数字12

    来看待;

    4) putchar()输出指定字符,不会在输出后自动换行,所以putchar(c);和putchar(d);之间要加

    putchar(' ');如果不加的话,会把c和d两个自动(1、2)输入到同一行。

    5)getchar可以读入所有字符。

    6)windows下如果想结束,就输入Ctrl+Z,表示EOF。

    师级经典的著作,要字斟句酌的去读,去理解。以前在看K&R的The C Programming Language(Second Edition)中第1.5节的字符输入/输出,很迷惑getchar()和EOF的行为。因此,感觉很有必要总结一下,不然,很多琐碎的知识点长时间过后就会淡忘的,只有写下来才是最好的方法。

    一、对getchar的两点总结:

    1. getchar是以行为单位进行存取的。

    当调用getchar函数读取输入时,只有当输入字符为换行符'/n'或文件结束符EOF时,getchar才会停止执行,整个程序将会往下执行。并且,如果输入行是以EOF结束的(EOF之前不是换行符),则EOF会被“吃掉”(即不会被getchar 读取到)。譬如下面程序段:

    while((c = getchar()) != EOF){

    putchar(c);

    }

    执行程序,输入:abc,然后回车。则程序就会去执行puchar(c),然后输出abc 和一个回车。然后可以继续输入,再次遇到换行符的时候,程序又会把那一行的

    输入的字符输出在终端上。令人迷惑的是,getchar不是以字符为单位读取的吗?那么,既然我输入了第一个字符a,肯定满足while循环(c = getchar()) != EOF 的条件,那么应该执行putchar(c)在终端输出一个字符a。但是程序就偏偏不这样执行,而是必需读到一个换行符或者文件结束符EOF才进行一次输出。

    造成这种结果的一种解释是,输入终端驱动处于一次一行的模式下。也就是虽然getchar()和putchar()确实是按照每次一个字符进行的。但是终端驱动处于一次一行的模式,它的输入只有到'/n'或者EOF时才结束。在本例中,程序段调用了getchar函数,则控制权从程序段转移到getchar函数,而getchar函数要依赖于操作系统的驱动来读取输入,没遇到换行符或者EOF,驱动不会通知getchar函数,getchar函数处于“阻塞”状态。而遇到换行符或者EOF 后, getchar函数解除“阻塞”,读取一个字符,控制权返回程序段,执行putchar 函数,循环执行。直到遇到EOF字符或者这行输入全部处理完。

    2. getchar()的返回值一般情况下是非负值,但也可能是负值,即返回EOF。这个EOF在函数库里一般定义为-1。正确的定义方法如下(K&R C中特别提到了这个问题):

    int c;

    c = getchar();

    二、EOF的两点总结(主要指普通终端中的EOF)

    1. EOF作为文件结束符时的情况:

    EOF虽然是文件结束符,但并不是在任何情况下输入Ctrl+D(Windows下Ctrl+Z)都能够实现文件结束的功能,只有在下列的条件下,才作为文件结束符。

    (1)遇到getcahr函数执行时,要输入第一个字符时就直接输入Ctrl+D;

    (2)在前面输入的字符为换行符时,接着输入Ctrl+D;

    (3)在前面有字符输入且不为换行符时,要连着输入两次Ctrl+D,这时第二次输入的Ctrl+D起到文件结束符的功能,至于第一次的

    Ctrl+D作为行结束符(如1.1所讲)。

    其实,这三种情况都可以总结为只有在getchar()提示新的一次输入时,直接输入Ctrl+D才相当于文件结束符。

    2. EOF作为行结束符时的情况,这时候输入Ctrl+D作为行结束的标志能结束getchar()的“阻塞”,使getchar()逐个字符读入,但是EOF会被“吃掉”,并不会被读取。

    以上面的代码段为例,如果执行时输入abc,然后Ctrl+D,程序输出结果为: abcabc

    注意:第一组abc是你从终端输入的,然后输入Ctrl+D,getchar逐个字符读取并逐个输出打印出第二组abc,同时光标停在第二组字符的c后面,然后可以进行新一次的输入。这时如果再次输入Ctrl+D,就会起到了文件结束符的作用,因为EOF是一行输入的第一个字符。如果输入abc之后,然后回车,输入换行符的话,则终端显示为:

    abc'/n'

    abc'/n'

    //第三行

    其中第一行为你是终端输入的,第二行是终端输出(含换行符),光标停在了第三行处,等待新一次的终端输入。从这里也可以看出Ctrl+D和换行符分别作为行结束符时,输出的不同结果。

  • 相关阅读:
    svn使用教程各种杂七杂八!
    Python+Django+Eclipse 在Windows下快速网站
    Python Django 框架开发
    【多肉】播种育苗 友情推荐:教你如何买到真种子
    (十一)Json文件配置
    (十)命令行配置
    (九)配置介绍
    visual studio 注释模板
    使用批处理自动发布IIS站点,基于IIS7及以上
    Win10系统无法安装可选功能提示错误代码0x800F081F的解决方法
  • 原文地址:https://www.cnblogs.com/leon1124/p/14039848.html
Copyright © 2011-2022 走看看