fseek库函数
#include <stdio.h> int fseek(FILE *stream, long int offset, int origin); 返回:成功为0,出错为非0
对流stream相关的文件定位,随后的读写操作将从新位置开始。
对于二进制文件,此位置被定位在由origin开始的offset个字符处。origin的值可能为SEEK_SET(文件开始处)、SEEK_CUR(当前位置)或SEEK_END(文件结束处)。
对于文本流,offset心须为0,或者是由函数ftell()返回的值(此时origin的值必须是SEEK_SET)(这里关于与ftell函数的交互,不是很理解。)。
ftell库函数
#include <stdio.h> long int ftell(FILE *stream);
返回与流stream相关的文件的当前位置。出错时返回-1L。
fflush库函数
#include <stdio.h> int fflush(FILE *stream); 返回:成功为0,失败返回EOF
对输出流(写打开),fflush()用于将已写到缓冲区但尚未写出的全部数据都写到文件中;对输入流,其结果未定义。如果写过程中发生错误则返回EOF,正常则返回0。
fflush(NULL)用于刷新所有的输出流。
程序正常结束或缓冲区满时,缓冲区自动清仓。
lseek库函数
头文件:#include <sys/types.h> #include <unistd.h>定义函数:off_t lseek(int fildes, off_t offset, int whence);
lseek函数不是ANSI C标准库函数,只是满足POSIX的UNIX下的函数。
函数说明:
每一个已打开的文件都有一个读写位置, 当打开文件时通常其读写位置是指向文件开头, 若是以附加的方式打开文件(如O_APPEND), 则读写位置会指向文件尾. 当read()或write()时, 读写位置会随之增加,lseek()便是用来控制该文件的读写位置. 参数fildes 为已打开的文件描述词, 参数offset 为根据参数whence来移动读写位置的位移数.
涉及到的枚举变量
enum _flags{_READ = 01,_WRITE = 02,_UNBUF = 04,_EOF = 010,_ERR = 020};
--------------------代码实现----------------------------
The standard library function
1 | int fseek(FILE*fp, long offset, int origin) |
is identical to lseek
except that fp
is a file pointer instead of a file descriptor and the return value is an int
status, not a position. Write fseek
. Make sure that your fseek
coordinates properly with the buffering done for the other functions of the library.
Here's Gregory's first solution:
/* Gregory Pietsch -- My category 0 solution to 8-4 */int fseek(FILE *f, long offset, int whence) {if ((f->flag & _UNBUF) == 0 && base != NULL)
{/* deal with buffering */if (f->flag & _WRITE)
{/* writing, so flush buffer */fflush(f); /* from 8-3 */}
else if (f->flag & _READ)
{/* reading, so trash buffer */f->cnt = 0;f->ptr = f->base;}}return (lseek(f->fd, offset, whence) < 0); }
...and here's his second, which is considerably more comprehensive:
/*[The following solution is in the zip file as krx80401.c - RJH (ed.) ]EXERCISE 8-4I thought I'd improve 8-4 too. I'm trying my best to get this as close to ISO C as possible given the restrictions that I'm under. (A real implementation would have fsetpos() borrow some of the same code.)*//* Gregory Pietsch -- My category 0 solution to 8-4 */#define SEEK_SET 0 #define SEEK_CUR 1 #define SEEK_END 2int fseek(FILE *f, long offset, int whence) {int result;if ((f->flag & _UNBUF) == 0 && base != NULL) {/* deal with buffering */if (f->flag & _WRITE) {/* writing, so flush buffer */if (fflush(f))return EOF; /* from 8-3 */} else if (f->flag & _READ) {/* reading, so trash buffer --* but I have to do some housekeeping first*/if (whence == SEEK_CUR) {/* fix offset so that it's from the last * character the user read (not the last* character that was actually read)*/if (offset >= 0 && offset <= f->cnt) {/* easy shortcut */f->cnt -= offset;f->ptr += offset;f->flags &= ~_EOF; /* see below */return 0;} elseoffset -= f->cnt;}f->cnt = 0;f->ptr = f->base;}}result = (lseek(f->fd, offset, whence) < 0);if (result == 0)f->flags &= ~_EOF; /* if successful, clear EOF flag */return result; }