热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

GetChar缓存机制深入剖析

以下是对GetChar缓存机制进行了详细的介绍,需要的朋友可以过来参考下

与缓存区相关最常见的操作就是字符的输入与输出操作getchar,getc,getch,getche,gets系列函数。

第一个例子(与getchar有关):

代码如下:

#include 
int main() 

    int ch; 
    ch=getchar(); 
    ch=getchar(); 
    printf("%d\n",ch); 
    return 0; 


代码如上,当输入一个字符按下回车后程序没有等待你二次输入就结束了,而且无论输入什么运行结果均是10,是不是很奇怪(反正我第一次遇到时感觉是很奇怪),更奇怪的是当你一次性输入多个字符如abcd结果又正确的打印出了98,为什么呢?这就是缓冲区的原因。

解释如下:getchar定义在stdio.h文件中,我们在stdio.h中可以找到其相关的定义:

代码如下:

#define getchar()         getc(stdin)//即getchar等同于调用getc(stdin)

我们又找到getc的定义
代码如下:

#define getc(_stream)     (--(_stream)->_cnt >= 0 \ 
                ? 0xff & *(_stream)->_ptr++ : _filbuf(_stream)) 

将其展开即得:
代码如下:

if(--(stdin)->_cnt>=0) 
      return 0xff&*(stdin)->ptr++; 

代码如下:

else 
        return filbuf(stdin); 

代码译如下stdin是标准输入流,查看MSDN与stdio.h中可以看到定义如下:

Stdio.h中:

代码如下:

#define stdin  (&_iob[0]) 

跟踪即可得:
代码如下:

_CRTIMP extern FILE _iob[]; 

从上面代码可得_iob是FILE结构类型的,查看stdio.h中可以看到FILE结构体定义如下:
代码如下:

struct _iobuf { 
        char *_ptr; 
        int   _cnt; 
        char *_base; 
        int   _flag; 
        int   _file; 
        int   _charbuf; 
        int   _bufsiz; 
        char *_tmpfname; 
        }; 


从FILE结构中我们可以得到了上面getc宏定义中使用的_cnt,_ptr成员,但这些都是次要的,我们应该不难发现有这样几个成员_bufsize,_base分别对应的是缓冲区大小,缓冲区基地址,从这里得到一个显而意见的结论就是getchar函数使用了缓冲机制。(_cnt对应的是缓冲区的输入的字节数目,_ptr对应的是读指针的位置)

getc宏定义详解

代码如下:

--(stdin)->_cnt>=0 

此句判断是否缓冲区内有数据,有的话就减一(表示又读了一个),并读取数据return 0xff&*(stdin)->ptr++,读完成后,将读指针向前移一个位置【重要】

好了,讲了这么多都是铺垫,现在回到正题为什么会出现上述结果:)

出现上述结果追根结底还是由于getchar函数使用了缓冲(看了上面的,我想大家也知道了,确实使用了缓冲),当输入一个字符按下回车后程序没有等待你二次输入就结束了,而且无论输入什么运行结果均是10,这是因为当用户输入了一个字符后,并按下回车后,缓冲中会存入用户输入的字符以及换行键的ASCII码(10 ~)【略去的回车的ASCII码13,可能是为了跨平台,在Linux下,回车后就是换行10,Windows下回车是先回车回到首行,再换行,即13 10】(执行第一次getchar实际上是执行getc的else语句,填充缓存区后_cnt=2,_prt指向0位置,执行完后_cnt=1,_prt指向1位置),第二次执行getchar时,调用getc不会再执行else语句,执行的是if语句,故第二次不再等待用户输入了,直接执行,执行后cnt=0,prt指向位置2,并返回ptr指向位置1时的结果,即10,由于10为换行键,当执行遇到此时,会在执行完后清空缓存,ptr重新指向了位置0,cnt=0。

当输入abc的时候分析一样,只不过扫行了第二个getchar后,cnt=2,ptr指向了位置2。


推荐阅读
  • PyCharm下载与安装指南
    本文详细介绍如何从官方渠道下载并安装PyCharm集成开发环境(IDE),涵盖Windows、macOS和Linux系统,同时提供详细的安装步骤及配置建议。 ... [详细]
  • 本文详细介绍如何使用Python进行配置文件的读写操作,涵盖常见的配置文件格式(如INI、JSON、TOML和YAML),并提供具体的代码示例。 ... [详细]
  • 在计算机技术的学习道路上,51CTO学院以其专业性和专注度给我留下了深刻印象。从2012年接触计算机到2014年开始系统学习网络技术和安全领域,51CTO学院始终是我信赖的学习平台。 ... [详细]
  • Linux 系统启动故障排除指南:MBR 和 GRUB 问题
    本文详细介绍了 Linux 系统启动过程中常见的 MBR 扇区和 GRUB 引导程序故障及其解决方案,涵盖从备份、模拟故障到恢复的具体步骤。 ... [详细]
  • 1:有如下一段程序:packagea.b.c;publicclassTest{privatestaticinti0;publicintgetNext(){return ... [详细]
  • 解决Linux系统中pygraphviz安装问题
    本文探讨了在Linux环境下安装pygraphviz时遇到的常见问题,并提供了详细的解决方案和最佳实践。 ... [详细]
  • 本文介绍了一款用于自动化部署 Linux 服务的 Bash 脚本。该脚本不仅涵盖了基本的文件复制和目录创建,还处理了系统服务的配置和启动,确保在多种 Linux 发行版上都能顺利运行。 ... [详细]
  • CMake跨平台开发实践
    本文介绍如何使用CMake支持不同平台的代码编译。通过一个简单的示例,我们将展示如何编写CMakeLists.txt以适应Linux和Windows平台,并实现跨平台的函数调用。 ... [详细]
  • 在Linux系统中配置并启动ActiveMQ
    本文详细介绍了如何在Linux环境中安装和配置ActiveMQ,包括端口开放及防火墙设置。通过本文,您可以掌握完整的ActiveMQ部署流程,确保其在网络环境中正常运行。 ... [详细]
  • 如何配置Unturned服务器及其消息设置
    本文详细介绍了Unturned服务器的配置方法和消息设置技巧,帮助用户了解并优化服务器管理。同时,提供了关于云服务资源操作记录、远程登录设置以及文件传输的相关补充信息。 ... [详细]
  • 本文将介绍如何编写一些有趣的VBScript脚本,这些脚本可以在朋友之间进行无害的恶作剧。通过简单的代码示例,帮助您了解VBScript的基本语法和功能。 ... [详细]
  • 深入理解Cookie与Session会话管理
    本文详细介绍了如何通过HTTP响应和请求处理浏览器的Cookie信息,以及如何创建、设置和管理Cookie。同时探讨了会话跟踪技术中的Session机制,解释其原理及应用场景。 ... [详细]
  • 本文介绍如何在 Xcode 中使用快捷键和菜单命令对多行代码进行缩进,包括右缩进和左缩进的具体操作方法。 ... [详细]
  • 介绍一个提供正版Windows软件下载的权威网站,确保用户能够安全合法地获取所需软件。 ... [详细]
  • 优化版Windows 10 LTSC 21H2企业版:适用于低内存设备
    此版本为经过优化的Windows 10 LTSC 21H2企业版,特别适合低内存配置的计算机。它基于官方版本进行了精简和性能优化,确保在资源有限的情况下依然能够稳定运行。 ... [详细]
author-avatar
k3as0n_701
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有