[comp.lang.c++] Binary Search Using seekg/tellg

sdm@cs.brown.edu (Scott Meyers) (04/09/91)

Regarding direct access in input streams, the istream man page says:

          insp=&ins.seekg(off,dir)
               Repositions  ins.rdbuf()'s   get   pointer.    See
               sbuf.pub(3C++) for a discussion of positioning.

          insp=&ins.seekg(pos)
               Repositions  ins.rdbuf()'s   get   pointer.    See
               sbuf.pub(3C++) for a discussion of positioning.

          pos=ins.tellg()
               The current position of ios.rdbuf()'s get pointer.
               See  sbuf.pub(3C++)  for a discussion of position-
               ing.

Okay, this is from the sbuf.pub man page:

     pos=sb->seekpos(pos, mode)
          Repositions the streambuf get  and/or  put  pointer  to
          pos.  mode specifies which pointers are affected as for
          seekoff().  Returns pos (the argument) or  EOF  if  the
          class  does  not  support  repositioning  or  an  error
          occurs.  In general a streampos should be treated as  a
          "magic cookie" and no arithmetic should be performed on
          it.

So how do I implement a binary search using iostream I/O?  I need to be
able to get two stream positions (corresponding to the top and bottom of
the region I'm about to bisect) that I can perform arithmetic on.  For
example, during the first iteration of the search, I want to go to the top
of the file and get a streampos, call it TOP, then to the BOTTOM of the
file to get another streampos, call it BOTTOM, then I want to jump to the
position in the file corresponding to (BOTTOM-TOP)/2.  However, the man
page says that streampos objects don't have to obey the laws of arithmetic.
What do I do?

Thanks,

Scott


-------------------------------------------------------------------------------
What do you say to a convicted felon in Providence?  "Hello, Mr. Mayor."

jss@gold.kpc.com (Jerry Schwarz) (04/10/91)

In article <71329@brunix.UUCP> sdm@cs.brown.edu (Scott Meyers) writes:

   So how do I implement a binary search using iostream I/O?  I need to be
   able to get two stream positions (corresponding to the top and bottom of
   the region I'm about to bisect) that I can perform arithmetic on.  For
   example, during the first iteration of the search, I want to go to the top
   of the file and get a streampos, call it TOP, then to the BOTTOM of the
   file to get another streampos, call it BOTTOM, then I want to jump to the
   position in the file corresponding to (BOTTOM-TOP)/2.  However, the man
   page says that streampos objects don't have to obey the laws of arithmetic.
   What do I do?


The iostream interface doesn't allow you do to this because it can't
be done portably.  On operating systems with record oriented file
systems there is just no way of doing arbitrary arithmetic on file
positions.  If you aren't worried about portability to such systems
and the system you're on defines |streampos| as an integral type (as
some do) then you can do arithmetic to your hearts content.  

Jerry Schwrz

mjv@objects.mv.com (Michael J. Vilot) (04/10/91)

>From brunix!sdm
>Newsgroups: comp.lang.c++
>Message-ID: <71329@brunix.UUCP>
>Organization: Brown University Department of Computer Science
>
>So how do I implement a binary search using iostream I/O? ... the 
man
>page says that streampos objects don't have to obey the laws of 
> arithmetic.
>What do I do?

Scott,

The semantics of tellg() and seekg() are more analogous to the ANSI C 
library functions fgetpos() and fsetpos() than to ftell() and 
fseek(), and the type 'streampos' is akin to 'fpos_t'.

The wording of the ANSI C standard is very careful to permit 
implementation of its library functions on non-Unix systems.  We've 
received comments on the version of iostreams proposed for the C++ 
standard that we'd better be just as careful in our semantics.

To solve your specific problem, I'd suggest that you derive a new 
kind of streambuf that knows how to do seeking arithmetic on your 
system, and use that.  You can probably implement it in a way that 
works on all UNIX systems, and localizes your porting efforts if you 
have to move onto a non-UNIX platform (best case would result in a 
sibling class for the new platform).

Hope this helps,

Mike