unix环境高级编程 学习笔记5 标准IO库

第五章 标准IO库 [仅作学习笔记,其中可能有误解] 

1.	标准IO处理很多细节,如缓冲区分配,优化长度执行IO等,与系统调用的文件IO形成对比
2.	标准IO是围绕流进行的(stream)
3.	流的定向
	+标准IO文件流可用于单字节和多字节(宽)
	+初始流是不定向的,当使用宽定向函数时就将流设置为宽定向,若用单字节IO函数就为字节定向
#include <stdio.h>
FILE * freopen(const char * restrict pathname, const char * restrict type, FILE * restrict fp);
这个函数清除一个流的定向,type取"r"等值

#include <stdio.h>
#include <wchar.h>
int fwide(FILE * fp, int mode);
// mode: 	负 = 字节定向
// 			正 = 宽定向
// 			0  = 未定向

4.	FILE结构
	它包含了标准IO为管理该流的所有信息,包括:
	+包含实际IO的文件描述符
	+指向缓冲区的指针
	+缓冲区的长度、当前字符数
	+出错标志等等

5.	stdin、stdout、strerr
	在系统文件IO对应为 STDIN_FILENO STDOUT_FILENO STDERR_FILENO

6.	缓冲
6.1	标准IO库提供缓冲的目的是为了减少read和write系统调用,它也对缓冲进行管理,避免了应用程序对缓存的管理。

6.2	提供了三种缓冲:
	+全缓冲
	  填满标准IO缓冲区才进行实际IO操作,当填满缓冲区时,标准IO例程自动冲洗,或者在用户程序调用fflush
	+行缓冲
	  在输入输出遇到换行符时,才执行IO操作
	  限制:
	  	1)缓冲区是定长的,当满了的时候,即使没遇到换行符号,也要进行IO
		2)当要求从内核获取数据时候,就会冲洗所有行缓冲区。输入输出应该是同一的缓冲区
	+不带缓冲
	  不进行缓冲存储
	  	1)标准出错通常是不带缓冲的

6.3	一般来讲,标准出错不带缓冲,涉及终端设备是行缓冲,否则是全缓冲

6.4	buffer的设置函数
#include <stdio.h>
void setbuf(FILE *restrict fp, char *restrict buf);
//	buf 非空,则缓冲长度为BUFSIZ(在stdio.h)
//	buf 空,则无缓冲

#include <stdio.h>
int setvbuf(FILE * restrict fp, char * restrict buf, int mode, size_t size);
//	mode _IOFBF,buf 非空,则缓冲长度为size,buf空,合适长度的系统缓冲区
//	mode _IOLBF,buf 非空,则缓冲长度为size,buf空,合适长度的系统缓冲区
//	mode _IONBF,无缓冲
6.5 buffer的冲洗函数
#include <stdio.h>
int fflush(FILE * fp);

7.	打开流
7.1 流打开函数
#include <stdio.h>
FILE * fopen(const char * restrict pathname, const char * restrict type);
// type : "r"只读,"w"只写(截断),"a"尾部写,"r+"读写,"w+"读写(截断),无则建,"a+"读且尾部写,无则建

#include <stdio.h>
FILE * freopen(const char * restrict pathname, const char * restrict type, FILE * restrict fp);
//这个函数清除一个流的定向,type取"r"等值

#include <stdio.h>
FILE * fdopen(int fd, const char * type);
// 根据fd这一文件描述符号打开流,非ISO C

7.2 除非引用终端设备,否则流打开后是全缓冲的

8. 关闭流
#include <stdio.h>
int fclose(FILE * fp);
// 文件关闭或程序正常终止(非正常会?????)时,冲洗缓冲区

9.	读写流
9.1 函数
#include <stdio.h>
int fgetc(FILE *fp);
int getc(FILE *fp);// 宏
int getchar(void);
// 以上三个函数,出错或到文件尾部都返回EOF,所以需要继续判断错误类型,可用下面两个函数:
#include <stdio.h>
int ferror(FILE * fp);
#include <stdio.h>
int feof(FILE * fp);
注:	strerror(errno);
		perror("bad");
		这两个函数是不是标准C的?

#include <stdio.h>
int ungetc(int c,FILE *fp);
// 压回流中

#include <stdio.h>
void clearerr(FILE * fp);
// 清除错误标志

#include <stdio.h>
int putc(int c, FILE * fp);
int fputc(int c, FILE * fp);
int putchar(int c);
// 输出字符

#include <stdio.h>
char * fgets(char * restrict buf, int n, FILE * restrict fp);
// 能保证以null结束,且null占用n中的一个,返回buf
#include <stdio.h>
char * gets(char * buf);
// gets不要用了,有缓冲区溢出的危险

#include <stdio.h>
int fputs(const char * restrict str, FILE * restrict fp);
// 将一个以null终止的字符串输出到fp流,正确返回非负数
int fputs(const char * str);
// 也不要用,因为默认会多输出一个换行符,还是自己处理以免混乱

9.2 最好都用f开头的函数就行了,虽然宏实现的getc\putc效率可能会好一点点

9.3 经测试,标准IO比直接调用read、write相比会稍慢


10	二进制IO
#include <stdio.h>
size_t fread(void * restrict ptr, size_t size, size_t nobj, FILE * restrict fp);

#include <stdio.h>
size_t fwrite(const void * restrict ptr, size_t size, size_t nobj, FILE * restrict fp);
// 以上两个函数返回成功处理对象数,若少于nobj,则用ferror、feof

10.1 由于系统间具有异构性,如编译器、存储格式之类不同,二进制文件不具有可移植性

11 	定位流

#include <stdio.h>
int fseek(FILE * fp, long offset, int whence);
// whence: SEEK_SET, SEEK_CUR, SEEK_END
#include <stdio.h>
long ftell(FILE * fp);

#include <stdio.h>
int fseeko(FILE *fp, off_t offset, int whence);
// whence: SEEK_SET, SEEK_CUR, SEEK_END
#include <stdio.h>
off_t ftello(FILE * fp);

#include <stdio.h>
int fsetpos(FILE * fp, const fpos_t * pos);
#include <stdio.h>
int fgetpos(FILE * restrict fp, fpos_t * restrict pos);

12	格式化IO
12.1 非变长参数
+ 输出
#include <stdio.h>
int fprintf(FILE * restrict fp, const char * restrict formate,...);
#include <stdio.h>
int printf(const char * restrict formate, ...);
#include <stdio.h>
int sprintf(char *restrict buf, const char * restrict format, ...);// 这个最好不要用了
#include <stdio.h>
int snprintf(char * restrict buf, size_t n, const char * restrict format, ...);
+ 输入
#include <stdio.h>
int scanf(const char * restrict format,...);
#include <stdio.h> 
int fscanf(FILE * restrict fp, const char * restrict format, ...);
#include <stdio.h>
int sscanf(char * restrict buf, const char * restrict format, ...);

12.1 变长参数
+ 输出
#include <stdio.h>
#include <stdarg.h>
int vprintf(const char * restrict format, va_list arg);

#include <stdio.h>
#include <stdarg.h>
int vfprintf(FILE *restrict fp, const char *restrict format, va_list arg);
#include <stdio.h>

#include <stdio.h>
#include <stdarg.h>
int vsprintf(char * restrict buf, const char * restrict format, va_list arg);

#include <stdarg.h>
int vsnprintf(char * restrict buf, size_t n, const char * restrict format, va_list arg);

+ 输入
#include <stdio.h>
#include <stdarg.h>
int vscanf(const char * restrict format, va_list arg);
#include <stdio.h>
#include <stdarg.h>
int vfscanf(FILE *restrict fp, const char *restrict format, va_list arg);
#include <stdio.h>
#include <stdarg.h>
int vsscanf(char * restrict buf, chonst char * restrict format, va_list):

13.	获取描述符
#include <stdio.h>
int fileno(FILE * fp);

14.	临时文件
14.1
#include <stdio.h>
char * tmpnam(char *ptr);
// ptr是NULL时,路径名放在静态区,下一次调用会重写
// ptr不是NULL时,ptr指向至少为L_tmpnam的数组,保存路径名
#include <stdio.h>
FILE *tmpfile(void);
// 返回临时文件的指针

14.2 变体:
#include <stdio.h>
char * tempnam(consnt char * directory, const char * prefix);
// 跟tmpname的作用查不多,不过路径名和前缀可自己指定

#include <stdlib.h>
int mkstemp(char * template);
// 不会自动调用link

15. tmpnam 和 tempnam不足之处在与返回唯一路径名和用该路径名创建文件前有时间间隔,有可能在另一个进程产生同名文件。

题外话:
// 带n的函数有:
fgets
snprintf
vsnprintf
strncpy
strncat
// fgets保证以null结束,且null占用n中的一个,返回值为字符串
// snprintf保证以null结束,且null占用n中的一个,返回值不包括null
// vsnprintf保证以null结束,且null占用n中的一个,返回值不包括null
// strncpy不保证以null结束,且,如果遇到null,则复制并添加至n个,返回值为字符串
// strncat保证以null结束,null不占n中的一个,只是接了n个字节后在在后面补一个null,返回值为字符串
// *getc* *gets都会吸收回车换行符的
// strnpy可以用strncat替代,strncpy\strncat是很容易导致越界的,所以n的值应当保证不会越界,n的值每次最多为(初始数组长度+1(1是为null分配的))-使用了的长度

[转载请表明]http://blog.csdn.net/kangquan2008  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值