zoukankan      html  css  js  c++  java
  • c程序设计语言_习题8-4_重新实现c语言的库函数fseek(FILE*fp,longoffset,intorigin)

      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

    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-4
     
    I 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 2
     
    int 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;
                    } else
                        offset -= 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;
    }
  • 相关阅读:
    AQS的子类在各个同步工具类中的使用情况
    SpringBoot RabbitMQ 延迟队列代码实现
    Java线程状态、线程start方法源码、多线程、Java线程池、如何停止一个线程
    Java内存模型,为啥线程要有自己的本地内存,CPU高速缓存
    Java内存模型中volatile关键字的作用
    Java内存模型、JVM内存结构和Java对象模型
    搞定springboot项目连接远程服务器上kafka遇到的坑以及完整的例子
    MongoDB导出与导入远程Linux服务器上的数据
    DeferredResult使用方式和场景
    【IT笔试面试题整理】二叉树中和为某一值的路径--从根到叶子节点
  • 原文地址:https://www.cnblogs.com/haore147/p/3648307.html
Copyright © 2011-2022 走看看