9,流的随机访问
  不同的流类型一般支持对相关流中数据的随机访问。可以重新定位流,以便环绕跳过,首先读后一行,再读第一行,以此类推。标准库提供一对函数来定位(seek)给定位置并告诉(tell)相关流中的当前位置。
  9.1 seek和tell函数
  seekg:重新定位输入流中的标记
  tellg:返回输入流中标记的当前位置
  seekp:重新定位输出流中的标记
  tellp:返回输出流中标记的当前位置
  逻辑上,只能在istream或者ifstream或者istringstream上使用g版本,并且只能在ostream类型或其派生类性ofstream或者ostringstream之上使用p版本。iostream对象,fstream或者stringstream对象对相关流既可以读也可以写,可以使用两个版本的任意版本。9.
  9.2 只有一个标记
  虽然标准库区分输入和输入而有两个版本,但它只在文件中维持一个标记——没有可区分的读标记和写标记。
  只是试图在ifstream对象上调用tellp的时候,编译器将会给出错误提示。反之亦然。
  使用既可以读又能写的fstream类型以及stringstream类型的时候,只有一个保存数据的缓冲区和一个表示缓冲器中当前位置的标记,标准库将g版本和p版本都映射到这个标记。
  9.3 普通iostream对象一般不允许随机访问。 9.4 重新定位标记
  seekg(new_position);
  seekp (new_position);
  seekg( offset, dir);
  seekp( offset, dir);
  第一个版本将当前位置切换到给定地点,第二个版本接受一个偏移量以及从何处计算偏移的指示器。
  9.5 访问标记
  tell函数返回的一个值,使用适当类的pos_type成员来保存。
  10,一个实例
  假定给定一个文件来读,我们将在文件的末尾写一个新行,改行包含了每一行开头的相对位置(程序不必写第一行的偏移量,因为它总是0)。例如给定下面的文件,
  abcd
  efg
  hi
  j
  这段程序应产生修改过的文件如下:
  abcd
  efg
  hi
  j
  5 9 12 14
  #include <iostream>
  #include <fstream>
  #include <string>
  using std::fstream;
  using std::cerr;
  using std::endl;
  using std::ifstream;
  using std::ofstream;
  using std::string;
  using std::getline;
  using std::cout;
  //using namespace std;
  int main()
  {
  fstream inOut("copyOut.txt",
  fstream::ate | fstream::in | fstream::out);            //用ate方式打开,会将文件的位置定位到文件末尾。
  if( !inOut )        {
  cerr << "unable to open file" <<endl;
  return EXIT_FAILURE;
  }
  inOut.seekg(-1,fstream::end);            //go to the last char
  if( inOut.peek() != 10)                    //if the last char of the file is not a newline,add it.
  {
  inOut.seekg(0,fstream::end);
  inOut.put(' ');
  }
  inOut.seekg(0,fstream::end);
  ifstream::pos_type endMark = inOut.tellg();        //record the last position .
  inOut.seekg(0,fstream::beg);
  int cnt = 0;                        //accumulator for byte count
  string line;                        //hold each line of input
  while( inOut && inOut.tellg() != endMark
  && getline(inOut , line)
  )
  {
  cnt += line.size() + 1;            // add 1 to acount for the newline
  ifstream::pos_type mark = inOut.tellg();
  inOut.seekp( 0, fstream::end);    //set write marker to end
  inOut << cnt;
  if( mark != endMark) inOut << " ";
  inOut.seekg(mark);                //restore read position
  }
  inOut.clear();                        //clear flags in case we hit an error
  inOut.seekp(0 , fstream::end);        //seek to end
  inOut << endl;                        //write a newline at end of file
  return 0;
  }