getchar,putchar,EOF

前言

本文将以简单的代码介绍getchar(), putchar() 和 EOF 。

代码1

#include <stdio.h>

int main(void)
{
    int c;
    
    c = getchar();
    putchar(c);
    
    return 0;
}

运行结果如下:
在这里插入图片描述

键盘输入:abcdefg
屏幕输出:a(无换行,所以我的用户名和电脑名直接跟在运行结果后面了)


定义

getchar()

  1. “getchar() reads the next input character from a text stream and returns that as its value”
  2. “the characters normally come from the keyboard
  3. 字符还可以来源于文本,但是不常见。

putchar()

  1. “putchar() prints a character each time it is called.”
  2. “putchar( c )” prints the contents of the variable c as a character."

注意

  1. getchar()的字符直接来源于 "a text stream"而不是键盘,虽然这些字符是从键盘输入的。
  2. putchar()只是把ch的内容以字符的形式打印出来,不会自动换行。

疑问
问题1.
定义里面说getchar()返回的是一个字符,那为什么ch的数据类型是int ?

答案:

  1. 先看getchar()的函数原型:
int getchar(void);

getchar()返回的数据类型就是int,所以ch定义为int是对的。但是疑问还在,getchar()返回的是一个character,为什么不使用char呢?请继续往下看。

问题2.
只输出了a,那么bcdefg去哪里了?请看代码2.

代码2

#include <stdio.h>

int main(void)
{
    char ch;

    ch = getchar();
    
    /* 遇到回车符停止输出 */
    while ('\n' != ch) {
        putchar(ch);
        ch = getchar();
    }

    return 0;
}

运行结果:
在这里插入图片描述
可以看出,getchar()一次只获取一个字符,但是键盘输入的其他字符也没有被丢弃。继续使用getchar()可以取出后面的字符。

这种输入叫“缓冲输入”,键盘输入的数据会先存入缓冲区,当你按下回车键后,getchar()才会从缓冲区获取一个字符。

与之对应的是无缓冲输入。想想我们玩的游戏,比如射击游戏里面的“w(前进)”“a(左移)”“s(后退)”“d(右移)”,我们一旦按下去就会生效,而不是按下w键后还要按回车键。这里w键一旦输入就被游戏程序读走,而不能再先存入缓冲区再被读走。

但是代码2却存在一个问题,要是我需要在屏幕上输出一个换行符呢?一种方法就是将while的循环条件里面的’\n’换成其他字符x(x代表其他字符),但要是需要输出x呢?
有没有能输出任意字符的写法呢?请看代码3。


代码3

#include <stdio.h>

int main(void)
{
    int ch;

    ch = getchar();
    while (EOF != ch) {
        putchar(ch);
        ch = getchar();
    }

    return 0;
}

运行结果:
在这里插入图片描述
这次进行了五次输入,三次输入了字母,两次是输入了回车键,但是程序还是没有退出。


注意
在这种情况下,键盘输入任意字符(不能是特殊组合键),程序都不会退出。说明EOF不是我们用到的任何字符。


那EOF是什么呢?
我们先看看字符有哪些呢?
字符的数据类型是char,char长度一般为8bits,8位可表示的数值范围为2^8=256(即0~255)。
目前我们计算机用到的字符都包含在0~255这个范围了。
所以,只要在这个范围外,都可以替代EOF,代码3的功能不变。可以用一个负数或任意大于255的数来替换EOF.

解释
EOF相关描述:

EOF:

  1. a value that cannot be confused with any real character. this value is called EOF, for “end of file”
  2. EOF is an integer defined in <stdio.h>, but the specific numeric value does not matter as long as it is not the same as any char value.

第2个描述指出,EOF是一个整数,且说EOF具体数值其实不重要,重要的是它不能和任意字符相同。

虽然这样说,但我还是想看看EOF是什么数值?

方法一:既然是整数,那就可以打印出来看看

#include <stdio.h>

int main(void)
{
    printf("EOF = %d\n", EOF);

    return 0;
}

运行结果:
在这里插入图片描述
方法二:查看stdio.h文件
在这里插入图片描述

在这里插入图片描述
EOF定义的数值是"-1",不属于0~255这个范围。

注意
EOF的第1个描述中“for “end of file””
stdio.h文件中注释“The value returned by fgetc and similar functions to indicate the end of the file.”都说EOF代表文件结束的意思。这又是怎么回事呢?

问题出在getchar()上,getchar()不断从输入(内存)中按字节读取数据,那就要知道输入什么时候结束(读取到哪个位置)。

如果数据是从文件中输入的,那么getchar就需要知道文件内容在位置x处结束,不能再继续往下读取数据了。比如:我们的stdio.h文件,我们看着是一个文件,其实就是内存中的一段内存,我们读取里面的内容,只能从开头读取到结尾,不能多读,否则就是非法访问了。指针的非法使用会造成很多意想不到的问题。

如果是从键盘输入,大多数的系统都有办法模拟文件结束的条件。

所以,当getchar()读取数据的时候,正常情况下,返回的是读取的字符,一旦检测到输入的结束(文件结束或键盘输入结束),getchar()就会就不再读取数据了(此时不能再读了),所以它需要返回一个与任何字符不一样的整数(getchar()返回数据类型为int),来告诉调用它的程序已经读完了。

注意
EOF并不是getchar()在检测到输入结束时读取到的值,而是getchar()检测到输入结束的时候直接返回的一个值,之前返回的值的确是读取到的字符,此时的值是用来代表“已经读取到输入结束的位置了”。
看代码:

#include <stdio.h>

int main(void)
{
    int ch;

    ch = getchar();
    while (EOF != ch) {
        putchar(ch);
        ch = getchar();
    }

    return 0;
}

运行结果:
在这里插入图片描述

这里输入“EOF”还是“-1”,程序都不会退出。别忘了,getchar()是按字符读取数据的,看着输入EOF,其实getchar()分三次依次返回“E”,“O”,“F”,同样需要两次依次返回“-”和“1”。

这里,也就知道getchat()返回的“-1(即EOF)”一定不可能是读取到的.

因为getchar()不仅会返回字符也会返回整数,所以getchar()的返回值的数据类型采用int也就没毛病了。





阅读摘抄
PREP是一种“结论先行”的沟通法则。
P: point (结论)
R: reason (依据)
E: example (具体事例)
P: point (重申结论后结束)

ps:报告,日常邮件、说话、回答问题、会议推进等,都应该遵循PREP模式,结论先行。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值