C缓冲区学习2 --- getchar getc getch getche gets函数

     与缓冲区相关的操作的常见的使我们的字符的输入输出操作,其实在接触过操作系统和编译原理之后,感觉计算机其实就是在处理一串又一串的字符串。今天给大家介绍get家族的几个函数。

      很多最初使用C语言进行字符串操作,并且认识到缓冲区问题的一般都是从类似下面的程序开始的:

      

                                      

    很多初学者会问,按下回车,为什么没等第二次输入程序就结束了,这就是缓冲区的原因了。这里需要了解一下getchar函数,这也是今天第一个要给大家介绍的stdio家族中getchar。

    

(1)   int  getchar(void)

    函数每次从stdin缓冲区读入一个字符遇到回车返回,并且回车也被存入缓冲区,所以getchar可以用来吃掉回车符。

    函数返回读到的第一个字符的ASC码值,如果失败则返回-1

    其定义为宏定义,即 #define getchar()         getc(stdin)

    因为是宏定义函数,所以getchar不支持指针的引用。

    现在解释跳过第二个输入的原因,假如我们第一次输入a按回车,这时候我们getchar实际上将a字符和回车放入了缓冲区中,并返回第一个字符的值,然后第二个getchar函数直接从缓冲区继续去字符,拿到了回车,没有需要用户再输入。为什么会有这种机制,可以参考

http://www.cnblogs.com/octobershiner/archive/2011/12/06/2278492.html

     所以很多人把getchar用来吃掉回车符,起到类似清空缓冲区的原因。清空缓冲区还可以使用fflush函数,但是这个函数不是C标准库中的函数,有时候是无效的。

   刚才说到了getchar的定义,其实就是getc函数的一种特殊的情况,下面介绍getc函数。

(2)   int  getc(FILE* stream)

   也是采用的宏定义,所以不支持函数指针调用。

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

    getc从指定的流中读取一个字符,刚才的getchar实际上就是getc(stdin) ,stdin是标准输入流,C在stdio.h中定义了三个流,也可以理解为是缓冲区。  

   #define stdin (&_iob[0])       //标准输入,一般指向键盘
   #define stdout (&_iob[1])     //标准输出
   #define stderr (&_iob[2])      //错误流

   基本实现过程

      

 在这里再补充两个函数,简单带过,因为getch和getche不是C标准的库函数。

(3)   int  getch(void)

从命令行读取一个字符,不显示在命令行,很多人用来模拟“按任意键继续的效果”

(4)   int  getche(void)

   从命令行中读取一个字符,显示在,命令行,与getch一样不是标准C函数库中的函数,在Windows平台下包含与conio.h中,在linux下与之相对的是curses.h库,但是在cygwin模拟的UNIX和ubuntu linux下gcc编译器均无法使用。

本文的最后介绍一下gets函数,他从流中读取字符串直到遇到换行符或者EOF或者遇到错误.

(5)   char*  gets(char* buffer)

   从stdin流中读取字符串,直至接受到换行符或EOF时停止,并将读取的结果存放在buffer指针所指向的字符数组中。换行符不作为读取串的内容,读取的换行符被转换为null值,并由此来结束字符串。

 

 

   其实gets这个函数还是有很多安全性的问题需要注意的,比如他要一直等EOF或者换行符才会结束,所以当程序无法预知可能存在的输入串长度时,是非常危险的,上一篇文章提到过缓冲区溢出的攻击,那么这里就是一个漏洞,我们不可能和攻击者比buffer的大小,及时我们定义很大很大的缓冲区,攻击者却能输入一个更长的字符串。

   其中VS 2005中提供了一个新的函数gets_s函数,带有安全性的gets,但是显然这不是标准库中所定义的。

   ========f的分割线=================

   stdio.h中还包含了与gets和getc想对的文件操作函数,fgets和fgetc

   char *fgets(char *s, int n, FILE *stream); //  n表示一次读入数据的长度,从stream中读取存入到s串中,遇到换行和结束符则结束

   int fgetc(FILE * stream);


   后续会分享put函数的系列。。。。

posted @ 2011-12-08 20:38  leeon  阅读(3235)  评论(3编辑  收藏  举报