Читаем Thinking In C++. Volume 2: Practical Programming полностью

The rdbuf( ) function returns a pointer, so it must be dereferenced to satisfy the function’s need to see an object. Stream buffers are not meant to be copied (they have no copy constructor), so we define sb as a reference to cout’s stream buffer. We need the calls to fail( ) and clear( ) in case the input file has a blank line (this one does). When this particular overloaded version of get( ) sees two newlines in a row (evidence of a blank line), it sets the input stream’s fail bit, so we must call clear( ) to reset it so that the stream can continue to be read. The second call to get( ) extracts and echoes each newline delimiter. (Remember, the get( ) function doesn’t extract its delimiter like getline( ) does.).

You probably won’t need to use a technique like this often, but it’s nice to know it exists.[43]

<p>Seeking in iostreams</p>

Each type of iostream has a concept of where its "next" character will come from (if it’s an istream) or go (if it’s an ostream). In some situations, you might want to move this stream position. You can do so using two models: one uses an absolute location in the stream called the streampos; the second works like the Standard C library functions fseek( ) for a file and moves a given number of bytes from the beginning, end, or current position in the file.

The streampos approach requires that you first call a "tell" function: tellp( ) for an ostream or tellg( ) for an istream. (The "p" refers to the "put pointer," and the "g" refers to the "get pointer.") This function returns a streampos you can later use in calls to seekp( ) for an ostream or seekg( ) for an istream, when you want to return to that position in the stream.

The second approach is a relative seek and uses overloaded versions of seekp( ) and seekg( ). The first argument is the number of characters to move: it can be positive or negative. The second argument is the seek direction:.

ios::begFrom beginning of stream
ios::curCurrent position in stream
ios::endFrom end of stream

Here’s an example that shows the movement through a file, but remember, you’re not limited to seeking within files, as you are with C and cstdio. With C++, you can seek in any type of iostream (although the standard stream objects, such as cin and cout, explicitly disallow it):.

//: C04:Seeking.cpp

// Seeking in iostreams

#include

#include

#include

#include

#include "../require.h"

using namespace std;

int main() {

  const int STR_NUM = 5, STR_LEN = 30;

  char origData[STR_NUM][STR_LEN] = {

    "Hickory dickory dus. . .",

    "Are you tired of C++?",

    "Well, if you have,",

    "That's just too bad,",

    "There's plenty more for us!"

  };

  char readData[STR_NUM][STR_LEN] = { 0 };

  ofstream out("Poem.bin", ios::out | ios::binary);

  assure(out, "Poem.bin");

  for(size_t i = 0; i < STR_NUM; i++)

    out.write(origData[i], STR_LEN);

  out.close();

  ifstream in("Poem.bin", ios::in | ios::binary);

  assure(in, "Poem.bin");

  in.read(readData[0], STR_LEN);

  assert(strcmp(readData[0], "Hickory dickory dus. . .")

    == 0);

  // Seek -STR_LEN bytes from the end of file

  in.seekg(-STR_LEN, ios::end);

  in.read(readData[1], STR_LEN);

  assert(strcmp(readData[1], "There's plenty more for us!")

    == 0);

  // Absolute seek (like using operator[] with a file)

  in.seekg(3 * STR_LEN);

  in.read(readData[2], STR_LEN);

  assert(strcmp(readData[2], "That's just too bad,") == 0);

  // Seek backwards from current position

  in.seekg(-STR_LEN * 2, ios::cur);

  in.read(readData[3], STR_LEN);

  assert(strcmp(readData[3], "Well, if you have,") == 0);

  // Seek from the begining of the file

  in.seekg(1 * STR_LEN, ios::beg);

  in.read(readData[4], STR_LEN);

  assert(strcmp(readData[4], "Are you tired of C++?")

    == 0);

} ///:~

This program writes a (very clever?) poem to a file using a binary output stream. Since we reopen it as an ifstream, we use seekg( ) to position the "get pointer." As you can see, you can seek from the beginning or end of the file or from the current file position. Obviously, you must provide a positive number to move from the beginning of the file and a negative number to move back from the end.

Now that you know about the streambuf and how to seek, you can understand an alternative method (besides using an fstream object) for creating a stream object that will both read and write a file. The following code first creates an ifstream with flags that say it’s both an input and an output file. You can’t write to an ifstream, of course, so you need to create an ostream with the underlying stream buffer:.

ifstream in("filename", ios::in | ios::out);

ostream out(in.rdbuf());

You might wonder what happens when you write to one of these objects. Here’s an example:.

//: C04:Iofile.cpp

// Reading & writing one file

#include

#include

#include "../require.h"

using namespace std;

Перейти на страницу:

Похожие книги

3ds Max 2008
3ds Max 2008

Одни уверены, что нет лучшего способа обучения 3ds Мах, чем прочитать хорошую книгу. Другие склоняются к тому, что эффективнее учиться у преподавателя, который показывает, что и как нужно делать. Данное издание объединяет оба подхода. Его цель – сделать освоение 3ds Мах 2008 максимально быстрым и результативным. Часто после изучения книги у читателя возникают вопросы, почему не получился тот или иной пример. Видеокурс – это гарантия, что такие вопросы не возникнут: ведь автор не только рассказывает, но и показывает, как нужно работать в 3ds Мах.В отличие от большинства интерактивных курсов, где работа в 3ds Мах иллюстрируется на кубиках-шариках, данный видеокурс полностью практический. Все приемы работы с инструментами 3ds Мах 2008 показаны на конкретных примерах, благодаря чему после просмотра курса читатель сможет самостоятельно выполнять даже сложные проекты.

Владимир Антонович Верстак , Владимир Верстак

Программирование, программы, базы данных / Программное обеспечение / Книги по IT