C和指针读书笔记(第十五章)

1. perror()函数用于向用户报告错误,原型定义于stdio.h

void perror(char const * message);

如果message不是NULL并且指向一个非空的字符串,perror函数就打印这个字符串,后面跟一个分号和一个空格,然后打印出一条用于解释errno当前错误代码的信息。


2. exit用于终止程序的执行,原型定义于stdio.h

void exit(int status);

status参数返回给操作系统,用于提示程序是否正常完成,这个值和main函数返回的整型状态值相同。
这个函数没有返回值,当exit函数结束时,程序已经消失。


3.
绝大多数流时完全缓冲的,这就意味着“读取”和“写入”实际上是从一块被称为缓冲区的内存区域来回复制数据。用于输出流的缓冲区只有当它写满才会被刷新到设备或文件中,类似的,输入缓冲区当它为空时通过从设备或文件读取下一块较大的输入,重新填充缓冲区。
通过在printf函数后调用fflash函数可以迫使缓冲区域的数据立即写入,不管它是否已满。

printf"something");
fflash(stdout);

4. 函数名或函数家族名
1. 只用于stdin和stdout。
2. 随作为参数的流使用。
3. 使用内存中的字符串而不是流。
输入输出函数家族
① 对指针使用下标引用或间接访问操作从内存获得一个字符(或向内存写入一个字符)
② 使用strcpy函数从内存读取文本行(或向内存写入文本行)


5. 打开流
fopen函数打开一个特定的文件,并把一个流和这个文件相关联。函数原型如下

FILE *fopen(char const *name, char const *mode);

两个参数都是字符串。name是打开的文件或者设备的名字,创建文件名的规则在不同的系统中可能各不相同,所以fopen把文件名作为一个字符串,mode参数提示流是用于只读,只写还是既读又写,以及是文本流还是二进制流。下表使一些常用的模式。
常用模式
mode以r、w或者a开头,表示打开的流用于读取,写入还是添加。如果一个文件打开是用于读取的,那么它必须原先就存在。但是如果一个文件打开是用于写入的,如果它原先就存在,那么它原先的内容就会被删除。如果原先不存在,那么就创建一个新文件。如果一个打开用于添加的文件原先并不存在,那么它将被创建。如果它原先已经存在,它原先的内存并不会被删除。无论是哪一种情况,数据只能从文件的尾部写入。
fopen的值应该被检查,如果函数失败会返回一个NULL值。
freopen函数用于打开(或重新打开)一个特定的文件流。原型如下:

FILE *open(char const *filename, char const *mode, FILE *stream);

最后一个参数就是需要打开的流,它可能是一个先前从fopen函数返回的值,也可能是标准流函数stdin,stdout或stderr。这个函数首先试图关闭这个流,然后用指定的文件和模式重新打开这个流。如果打开失败,函数返回NULL。如果成功返回第三个参数值。


6. 关闭流
函数fclose关闭流。

int fclose(FILE *f);

对于输出流,fclose函数在文件关闭之前刷新缓冲区。如果执行成功,fclose返回零值,否则返回EOF。


7. 字符I/O
字符输入是由getchar函数家族执行的,原型如下:

int fgetc(FILE *stream);
int getc(FILE *stream);
int getchar(void);

需要操作的流作为参数传递给getc和fgetc,但是getchar始终从标准输入读取。每个函数从流中读取下一个字符,并把它作为函数的返回值返回。如果流中不存在更多的字符,就返回EOF。
这些函数都用于读取字符,但它们都返回int型值而不是char型值,尽管表示字符的代码本身就是小整型,但返回int型值的原因是为了返回EOF(EOF是整型)。这样EOF不会和字符重复,这些函数可以读取二进制文件。

把单个字符写入流中,可以使用putchar函数家族。

int fputc(int character, FILE *stream);
int putc(int character, FILE *stream);
int putchat(int character);

第一个参数是要被打印的字符,在打印之前,函数会把这个整型参数裁剪为一个无符号字符整型。函数失败返回EOF。

fgetc,fputc是真正的函数,但是getc,putc,getchar,putchar,都是通过#define指令定义的宏。

ungetc函数是为了撤销字符I/O。

int ungetc(int character, FILE *stream);

ungetc把一个先前读出的字符返回到流中,这样它可以在以后被重新读入。


7. 格式化的行I/O
未格式化的行I/O简单读取或写入字符串。
gets和puts函数是用于操作字符串而不是单个字符。这个特征使它们在处理一行行文本输入的程序中非常有用。函数原型如下:

char *fgets(char *buffer, int buffer_size, FILE *stream);
char *gets(char *buffer);

fgets从指定的stream中读取字符并复制到buffer中。当它读取一个换行符并存储到缓冲区后就不再读取。如果缓冲区的内存储的字符达到BUFFER_SIZE-1时它也停止读取。在这种情况下并不会出现数据丢失的情况,因为下一次调用fgets将从流的下一个字符开始读取。在任何一种情况下,一个NUL字节被添加到缓冲区所存储数据的末尾,使它成为一个字符串。
如果任何字符读取前就达到了文件尾,缓冲区就未进行修改,fgets函数返回一个NULL指针,否则fgets返回第1个参数(指向缓冲区的指针),此返回值一般用于检测是否到达文件尾。

int fputs(char const *buffer, FILE *stream);
int puts(char const *buffer);

传递给fputs的缓冲区必须包含一个字符串,它的字符被写入到流中。这个字符串预期以NUL字节结尾,所以这个函数没有一个缓冲区长度参数。这个字符串是逐字写入的:不包含一个换行符就不写入换行符。如果包含好几个换行符,所有的换行符都会被写入。因此当fgets每次都读取一个整行时,fputs可以每次写入一行的一部分也可以写入一整行或好几行。写入错误时,fputs返回常量值EOF,否则返回一个非负值。
gets和puts函数几乎和fgets和fputs相同,之所以存在是因为他们为了允许向后兼容,他们之间的一个主要的功能性区别在于当gets读取一行输入时,它并不在缓冲区中存储结尾的换行符。当puts写入一个字符串时,它在字符串写入之后想输出再添加一个换行符。

P.S. gets函数无法判断缓冲区的长度,如果长输入行被定位到短缓冲区时,多出来的字符会被写到缓冲区的后面。


8. 格式化的行I/O
格式化的行I/O执行数字和其他变量的内部和外部表示形式之间的转换。
scanf家族
每个原型的省略号表示一个可变长度的指针列表。从输入转来的值逐个存储到这些指针参数所指向的内存位置。

int fscanf(FILE *stream, char const *format, ...);
int scanf(char const *format, ...);
int sscanf(char const *string, char const *format, ...);

这些函数都从输入源读取字符并根据format字符串给出的格式代码对它们进行转换。fscanf的输入就是作为参数给出的流,scanf从标准输入读取,sscanf从第一个参数所给的字符串中读取字符。
当格式化字符串到达末尾或者读取的输入不再匹配格式字符串所指定的类型时,输入就停止,在任何一种情况下,被转换的输入值的数目作为函数的返回值返回。如果在任何输入值被转换之前文件就已经到达尾部,函数就返回常量值EOF。
scanf格式码
printf家族
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格式码
printf打印的例子:P315


9.二进制I/O
数据写入文件最搞笑的方法是二进制写入。二进制输出避免了在数值转换为字符串过程中所涉及的开销和精度损失。
fread函数用于读取二进制数据,fwrite函数用于写入二进制数据。
函数原型如下:

size_t fread(void *buffer, size_t size, size_t count, FILE *stream);
size_t fwrite(void *buffer, size_t size, size_t count, FILE *stream);

buffer是一个指向用于保存数据的内存位置的指针,size是缓冲区每个原色的字节数,count是读取或写入的元素数,stream是数据读取或写入的流。
buffer参数被解释为一个或多个值的数组,count参数指定数组中有多少个值,所以读取写入一个标量时,count的值应该是1。


未完待续

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值