"The C Programming Language", 2nd edition, Kernighan and Ritchie

Answer to Exercise 8-4, page 179

Solution by Gregory Pietsch

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;
}





Back to index





You are visitor number - call again soon!