1、标准规定了标准函数库中的函数接口操作,有助于提高程序的可移植性;
2、标准库函数在errno中保存错误代码之后将这个信息传递给用户,提示操作失败的原因;
注:只有当一个库函数失败时,errno才会被设置,当函数成功执行时,errno的值不会被修改,因此我们不能通过测试errno的值来判断是否有错误发生,使用perror是一个很好的办法;
3、perror函数与exit函数
perror函数原型:
void perror(char const *message);
exit函数原型:
void exit(int status);
注:预定义符号EXIT_SUCCESS与EXIT_FAILURE分别提示程序的终止的成功还是失败;
4、标准I/O函数库的两个缺陷:
(1)在某台特定类型的机器上实现,并没有对其他具有不同特性的机器做过多的考虑(有时是因为架构的不同,例如x86与ARM);
(2)由于第一个缺陷的影响,往往会修改其中的函数实现,从而导致可移植性低;
5、解决调试程序时,某些函数调用的输出结果被写入缓冲区中,但是并不马上显示在屏幕上,而需要查看结果的情况:
在每个调试的printf函数之后立即调用fflush函数;
printf("hello");
ffulsh(stdout);
6、一个程序同时最多能打开多少文件——可以查看FOPEN_MAX了解,它的值至少为8;
最长文件名——可以查看FILENAME_MAX;
7、I/O函数以三种基本的形式处理数据:单个字符、文本行和二进制数据;
8、fopen函数原型:
FILE *fopen(char const *name, char const *mode);
name是希望打开文件或设备的名字,mode参数提示流是用于只读、只写、还是读写以及是文本流还是二进制流;
注:应该始终检查fopen的返回值,如果函数失败会返回一个NULL值;否则NULL指针会传给后续的函数,它们将对其进行间接访问会导致失败;
9、fclose函数原型:
int fclose(FILE * f);
fclose函数在文件关闭之前刷新缓冲区,如果执行成功,fclose返回零值,否则返回EOF(这也是为什么返回int值的原因,在之前有阐述);
10、关于错误检查:
在考虑错误检查的时候,思考两个问题:(1)如果操作成功应该执行什么?(2)如果操作失败应该执行什么?
如果两个问题的答案是不同的,应该进行错误检查,否则跳过错误检查才是合理的;
11、字符I/O:
int fgetc(FILE *stream);
int getc(FILE *stream);
int getchar(void);
int fputc(FILE *stream);
int putc(FILE *stream);
int putchar(void);
注:它们都是返回一个int值而不是char值,是为了允许报告文件的末尾EOF;
fgetc和fputc都是真正的函数,而getc、putc、getchar、putchar都是通过#define指令定义的宏;
12、未格式化的行I/O
char *fgets(char *buffer, int buffer_size, FILE *stream);
char *gets(char *buffer);
fgets是从指定的流读取字符串的,当读取到换行符或者缓冲区存储的字符数达到buffer_size-1时,停止读取并将一个NUL字节添加到数据的末尾,使之成为一个字符串,fgets读取到达了文件的末尾就返回一个NULL值,否则返回它的第一个参数(fgets无法把字符串读入到一个长度小于两个字符的缓冲区,因为其中一个用于NUL字节);
gets无法判断缓冲区的长度,因此应该少用gets,当gets读取一行输入时,并不在缓冲区中存储结尾的换行符;
int fputs(char const *buffer, FILE *stream);
int puts(char const *buffer);
fputs如果写入错误时,返回EOF,否则返回一个非负值;使用fputs时,如果缓冲区中不包含一个换行符,就不会写入换行符,如果包含多个换行符,所有的换行符都会被写入;
当puts写入一个字符串时,它在字符串写入之后向输出再添加一个换行符,而fputs则不会;
13、scanf家族
int fscanf(FILE *stream, char const *format, ...);
int scanf(char const *format, ....);
int sscanf(char const *string, char const *format, ....);
fscanf输入源是作为参数给出的流,scanf从标准输入读取,sscanf从第一个参数所给出的字符串中读取字符;
format字符串参数可能包含以下内容:
(1)空白字符——处理中会被忽略
(2)格式代码——解释输入的字符
(3)其他字符——当任何其他字符出现在格式字符串中,下一个输入字符必须跟它匹配,如果匹配,该输入字符就被丢弃,否则函数就不再读取直接返回;
格式代码格式:
以一个%开头,(1)一个可选的星号(2)一个可选的宽度(3)一个可选的限定符(4)格式码
星号:使转换后的值被丢弃而不是存储(用于跳过不需要的输入字符);
宽度:用于限制将被读取用于转换的输入字符的个数,如果未给出宽度,函数就连续读入字符直到遇见输入中的下一个空白字符;
限定符:用于修改有些格式码的定义,目的是指定参数的长度;
格式码:用于指定输入字符如何被解释;
限定符:
格式码:
14、printf家族
int fprintf(FILE *stream, char const *format, ...);
int printf(char const *format, ...);
int sprintf(char *buffer, char const *format, ...);
printf将结果输出到标准输出,fprintf将结果输出到任何流,sprintf将结果作为一个NUL结尾的字符串存储到特定的buffer中而不是写入流中;它们的返回值都是实际打印或存储的字符数;
printf的format参数与scanf一样
format中的格式代码:以一个%开头,(1)一个或多个标志字符(2)一个可选的最小字段宽度(3)一个可选的精度(4)一个可选的修改符(5)转换类型
标志字符:
修改符:
参数类型:
该部分最好查阅《C和指针》的原文内容;