Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!dali.cs.montana.edu!uakari.primate.wisc.edu!sdd.hp.com!mips!pacbell.com!att!linac!convex!egsner!swsrv1!toma From: toma@swsrv1.cirr.com (Tom Armistead) Newsgroups: comp.lang.c Subject: Re: How to FSEEK previous line of text? Message-ID: <1991May11.063436.18318@swsrv1.cirr.com> Date: 11 May 91 06:34:36 GMT References: <4508.28269613@iccgcc.decnet.ab.com> Organization: Software Services: Garland, Tx Lines: 97 In article <4508.28269613@iccgcc.decnet.ab.com> maslar@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@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 /* ** 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@swsrv1.cirr.com {egsner,letni,ozdaltx,void}!swsrv1!toma