• 【C语言】 getchar()与EOF的疑难杂症


            《C语言程序设计》大师写的书本,需要字斟句酌,在接触到getchar()和EOF(文件结束符)感觉到疑惑,特此记录下来。

    一、getchar()总结如下:

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

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

    1. #include
    2. int main(void)
    3. {
    4. int c = 0;
    5. while((c=getchar())!= EOF){
    6. putchar(c);
    7. }
    8. return 0;
    9. }

            执行程序,输入:fac,然后回车。

            程序会向下执行puchar(c),然后输出fac和一个回车。然后可以继续输入,再次遇到换行符的时候,程序又会把 那一行的输入的字符输出在终端上。

            那为什么getchar不是以字符为单位读取的吗?按道理输入的肯定满足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。C语言中,EOF是个宏,在stdio.h文件中进行定义:
            #define EOF (-1)
            即:EOF就是整型数-1。

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

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

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

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

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

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

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

    一般情况下,实际考虑:

            windows下,在输入的空行位置,按ctrl+z可产生EOF
            linux下,在输入时,按ctrl+d可产生EOF

    2. EOF作为行结束符

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

            如果执行时输入edc,然后 Ctrl+D,程序输出结果为:edcedc

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

           

  • 相关阅读:
    【机器学习】线性回归【下】正则化最小二乘估计
    QT-飞机水平仪图标
    前端token知识梳理:token如何存储?token过期如何处理?如何无感刷新token?
    【强化学习论文合集】AAAI-2021 强化学习论文
    Linux中的crontab 定时任务设置
    【LeetCode第115场双周赛】100029. 和带限制的子多重集合的数目 | 前缀和背包 | 中等
    Java从入门到精通-流程控制(二)
    不仅仅是图书信息管理系统
    2022/08/19、20 day06/07:Linux的redis安装
    大数据——Spark
  • 原文地址:https://blog.csdn.net/weixin_45540638/article/details/126761173