computer_knowledge_notes/Languages/CLang/libraries/stdio.md

7.2 KiB
Raw Blame History

概述

管理输入输出

基本概念

  • 是数据的源或目的地它实际上对应着的是一个设备比如磁盘。程序开始执行时stdin, stdout, stderr这3个流已经打开。

文件操作

/* 解读mode */
// r以读的方式打开文件流指向文件开头。
// r+:以读写的方式打开,流指向文件开头。
// w将文件截断为0长度或创建可写的文件流指向文件开头。
// w+:以读写的方式打开,文件不存在则会创建,存在则截断。流指向文件开头。
// a以附加的方式打开文件不存在则会创建流指向文件末尾。
// a+:以附加且可读的方式打开,文件不存在则会创建,但读是从文件开头,写是从文件末尾。
// 还可以附加`b`表示是二进制但这对POSIX兼容系统来说没有效果而只是为了与C89兼容。


/* 打开文件名为path的文件并关联到一个流。参数mode指打开的模式。 */
FILE *fopen(const char *path, const char *mode);
/* 把文件描述符关联到一个流 */
FILE *fdopen(int fd, const char *mode);
FILE *freopen(const char *path, const char *mode, FILE *stream);
/* 关闭流 */
int fclose(FILE *stream);

流的缓冲操作

/* 三种缓冲的方式 */
// unbuffered信息直接写到文件或终端上。stderr默认是无缓冲的。
// block buffered信息以块的形式保存和写入。通常所有的文件都是块缓冲的。
// line buffered信息以行的形式保存。当流指向终端(如stdout)则是行缓冲的。

/* 将缓冲区与流相关联。如buf为NULL则无缓冲否则全缓冲。缓冲区大小为BUFSIZ。 */
void setbuf(FILE *stream, char *buf);
/* 将缓冲区与流相关联。如buf为NULL则无缓冲否则全缓冲。
 * size : 缓冲区的大小。
 */
void setbuffer(FILE *stream, char *buf, size_t size);
/* 将流关联为行缓冲等价于setvbuf(stream, NULL, _IOLBF, 0); */
void setlinebuf(FILE *stream);
/* 将缓冲区与流相关联,本函数应该仅可以在打开一个流且没有进行其它操作前执行。
 * buf用于取代当前缓冲区的新缓冲区指针。如为NULL则会在下次读或写的时候分配缓冲区。
 * mode_IONBF无缓冲;_IOLBF行缓冲_IOFBF全缓冲。
 * size:缓冲区大小。
 * 返回值0成功非0错误。
 */
int setvbuf(FILE *stream, char *buf, int mode, size_t size);

格式化输出

int fprintf(FILE *stream, const char *format, ...)
  // fprintf函数将带有格式标记的字符串format写到stream流中。返回值是实际写入的字符数若出错则返回一个负值。
- printf(...)等价于fprintf(stdout, ...)
- dprintf是将输出流设定为文件描述符fd
- sprintf(char *s,const char *format, ...)是将format写入到字符串s中
- snprintf类似于sprintf,但给定了字符串的长度。
- vprintf等价于printf,但用arg代替了可变参数表arg由宏va_start或va_arg初始化
- vfprintf等价于fprintf,但用arg代替了可变参数表arg由宏va_start或va_arg初始化
- vdprintf等价于dprintf,但用arg代替了可变参数表
- vsprintf等价于sprintf,但用arg代替了可变参数表arg由宏va_start或va_arg初始化
- vsnprintf等价于snprintf,但用arg代替了可变参数表
/*
##### format的结构
格式化字符串format  普通字符串  转换说明
转换说明  % + 约束部分 + 转换字符

##### format约束部分
	标志:
	-		// 左对齐
	+		// 加正负号
	空格	// 如果第一个字符不是正负号,则在其前面加空格
	0		// 对于数值转换当输出长度小于字段宽度时则在其前面填充0
	#		// 指定另一种输出形式o转换则加前缀ox或X转换加前缀0x或0Xe、E、f、g、G转换结果有小数时才给出小数点。
	数值(宽度)	// 指定最小字段宽度
	.		// 分隔字段宽度和精度
	数值(精度)	//对于字符串指定最大长度e、E或f转换指定小数点后数位的长度g或G转换指定有效位长度对整型数则指定数位长度。
	h		// 按short或unsigned short输出。
	l		// 按long或unsigned long输出。
	j		// 按intmax_t或uintmax_t输出。
	L		// 按long double输出。
	*		// 宽度或精度的任何一个都可以用*指定

##### format转换字符
	d,i		// int,有符号十进制数
	u		// unsigned int,无符号十进制数
	o		// unsigned int,无符号八进制数
	x,X		// unsigned int,无符号十六进制无前导0x或0X)
	c		// int
	s		// char *,字符串
	f		// double,双精度型
	e,E		// double,双精度型(指数形式)
	g,G		// double,f或e,E类型取决于限定条件
	p		// void *,指针
	n		// int *,到当前为止输出的字符数
	%		// 不转换,打印%
	
 */

格式化输入

// 依据格式串format从*stream中读取输入把值赋给后续各个参数
int fscanf(FILE *stream, const char *format, ...);	
// 等价于fscanf(stdin, *format, ...)
int scanf(const char *format, ...);	
/* 从字符串读取格式化输入
 * 返回值:成功则返回写入的条目的数量,失败则返回-1。
 */
int sscanf(const char *str, const char *format, ...);

字符输入输出

/* 从流中读取下一个字符.
 * 返回值读取到的字符或EOF或error。
 */
int fgetc(FILE *);
/* 从流中读取下一个字符。它可以实现为宏对流进行多次运算。
 * 返回值读取到的字符或EOF或error。
 */
int getc(FILE *);
/* 从stdin中读取下一个字符。它可以实现为宏对流进行多次运算。
 * 返回值读取到的字符或EOF或error。
 */
int getchar(void);
/* 把字符推入到流中 */
int ungetc(int, FILE *);

int fputc(int, FILE *);
int putc(int, FILE *);
int putchar(int);

char *fgets(char *__restrict, int, FILE *__restrict);
int fputs(const char *__restrict, FILE *__restrict);
int puts(const char *);

直接输入输出

size_t fread(void *ptr, size_t size, size_t nobj, FILE *stream);	// 从流stream中最多读取nobj个长度为size的对象保存到ptr指向的数组中。返回读取的对象数此值可能小于nobj。
size_t fwrite(void *ptr, size_t size, size_t nobj, FILE *stream);	// 从ptr指向的数组中读取nobj个长度为size的对象输出到流stream中。返回输出的对象数。

文件定位

int fseek(FILE *stream, long offset, int origin);	// 设置流stream的位置为从origin开始的第offset个字符后续的读写操作将从新位置开始。origin的值可以是SEEK_SET(文件开始)SEEK_CUR(当前位置)SEEK_END(文件末尾)
long ftell(FILE *stream);	// 返回stream流当前的位置

错误处理

void perror(const char *s);	// 打印字符串s与错误信息
int feof(FILE *stream);	// 测试流stream的文件结束指示符如果设置了则返回非0。

其它

/* 打开一个动态内存缓冲区流 */
FILE *open_memstream(char **ptr, size_t *sizeloc);

/* 把内存作为stream打开 */
FILE *fmemopen(void *buf, size_t size, const char *mode);

/* 从stream中读取整行 */
ssize_t getline(char **lineptr, size_t *n, FILE *stream);

ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream);