C基础——文件I/O (3)【自我答疑】
## 1、标准I/O的机理
使用标准I/O的第1步是调用fopen()打开文件。fopen()函数不仅打开文件,还创建了一个缓冲区(读写模式下会创建两个缓冲区),以及一个包含文件和缓冲区数据的结构。
fopen()函数返回一个指向该结构的指针,以便其他函数直到如何找到该结构。
此结构通常包含一个指定流中当前位置的文件位置指示器,还包含错误和文件结尾指示器、一个指向缓冲区开始处的指针、一个文件标识符和一个计数(统计实际拷贝进缓冲区的字节数)。
通常,使用标准I/O的第2步是调用一个定义在stdio.h中的输入函数,入fscanf()、getc()或fgets()。一调用这些函数,文件中的缓冲大小的数据块就被拷贝到了缓冲区中。最初调用函数,除了填充缓冲区,还要设置fp所指向的结构中的值。尤其是要设置流中的当前位置和拷贝进缓冲区的字节数。通常,当前位置从字节0开始。
----
## 2、自我答疑:关于fseek的疑惑
初始化结构和缓冲区后,输入函数按要求从缓冲区读取数据。
==在输入函数读取数据时,文件位置指示器被设置为指向刚读取字符的下一个字符!!!==
==由于***stdio.h系列的所有输入函数都使用相同的缓冲区***,所以调用任何一个函数都将冲上一次函数停止调用的位置开始==
```C
#include
int main(void)
{
FILE* fp;
char ch;
fp = fopen("test", "w+");
fprintf(fp, "abcdefg");
fseek(fp, 0L, SEEK_SET); // #1 将fp定位至文件开头,fp指向字符a
ch = getc(fp); //getc(fp)为ch赋值之后,使fp指向了第2个字符b
printf("%c\n", ch); //所以,这里输出的ch虽然为a,但此刻fp实际已经指向字符b所在的位置
fseek(fp, 0L, SEEK_CUR);
ch = getc(fp);
printf("%c\n", ch);
fseek(fp, 0L, SEEK_CUR);
ch = getc(fp);
printf("%c\n", ch);
return 0;
}
```
==在以上代码中,调用fseek()函数后,又调用了getc()从文件中读取字符,导致fp的位置发生了改变==
----
# 读书千万不要跳着读!!!!
----
当输入函数发现已经读完缓冲区中的所有字符时,会请求把下一个缓冲大小的数据块从文件拷贝到该缓冲区。以这种方式,输入函数可以读取文件中所有的内容,直到文件结尾。
函数在读取缓冲区中的最后一个字符后,把结尾治时期设置为真。于是,下一次被调用的输入函数将返回EOF。