How to FSEEK previous line of text?
Tom Armistead
toma at swsrv1.cirr.com
Sat May 11 16:34:36 AEST 1991
In article <4508.28269613 at iccgcc.decnet.ab.com> maslar at iccgcc.decnet.ab.com writes:
>
>Does anyone know of a function or technique that is similar to FSEEK
>that will allow me to go back to the previous line? The lines of
>ASCII text are being read from a file by the FGETS function. The
>length of the lines varies. I'm writing an application-specific
>file reader, and need to implement a PageUp and UpArrow feature.
>
>Thanks,
>
>Mark Maslar
>
>INTERNET: maslar at icd.ab.com
In a text file, you can generally assume that the lines will have a max length
of BUFSIZ. So, you could seek backward BUFSIZ*2 bytes, read the number of
bytes that were backward seeked and search from the end of that buffer,
backward until you find a the \n prior to the previous line.
Or you could fseek back one character at a time, read that character and look
for '\n's.
Either way is going to be fairly slow (the second option will be REAL slow).
I did this once using the 1st method, like this:
/*===========================================================================*/
#include <stdio.h>
/*
** Seek back 1 line in the text file associated with the passed fp.
** Returns 0 on success, or -1 on error (probally because positioned at 1st
** line in file).
*/
int
backup_one_line( fp )
FILE *fp;
{
char buf[BUFSIZ*2]; /* buffer for fread */
long posn; /* ftell() position */
int backup_ofs; /* distance arg to fseek */
int indx; /* index into buf[] */
int ret=-1; /* function return; assume error */
int lf_cnt = 0; /* line feed character counter */
posn = ftell( fp ); /* get current position in file */
/*************************************************************************
** If not far enough down in the file to read the the entire buffer size,
** then read all of the file up to the current point.
**************************************************************************/
if( posn <= (long)sizeof( buf ) )
backup_ofs = posn;
else /* else read entire buffer from file */
backup_ofs = sizeof( buf );
fseek( fp, (long)-backup_ofs, 1 ); /* backup size of buffer */
fread( buf, backup_ofs, 1, fp ); /* read buffer into memory */
/*************************************************************************
** Search backward from the end of the buffer to the 3rd \n character.
** 1st one is for end of current line, 2nd is for end of previous
** line and 3rd is for 1 character before previous line.
**************************************************************************/
for( indx=backup_ofs-1; indx > 0; indx-- )
if( buf[indx] == '\n' && ++lf_cnt == 3 ) /* count \n's */
break; /* leave on 3rd one */
if( indx > 0 ) /* if 3rd linefeed back found */
{
ret = 0; /* signify success */
posn = (backup_ofs - indx - 1); /* position to start of prev line */
fseek( fp, -posn, 1 ); /* position there */
}
else if( indx == 0 && lf_cnt == 2 ) /* else, prev line is 1st in file */
{
ret = 0; /* signify success */
fseek( fp, 0, 0 ); /* move to start of file */
}
/*************************************************************************
** Else positioned at 1st line in file (can't go back) or was unable to
** find \n line separators.
**************************************************************************/
else
fseek( fp, posn, 0 ); /* position back to original pos'n */
return ret;
}/*end backup_one_line*/
/*===========================================================================*/
Tom
--
Tom Armistead - Software Services - 2918 Dukeswood Dr. - Garland, Tx 75040
===========================================================================
toma at swsrv1.cirr.com {egsner,letni,ozdaltx,void}!swsrv1!toma
More information about the Comp.lang.c
mailing list