Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

AhmadLang / Object Oriented Programing using C++

.pdf
Скачиваний:
92
Добавлен:
31.05.2015
Размер:
799.32 Кб
Скачать

Object Oriented Programming using C++

line;

 

while (getline(ipb, line))

// `cout << ipb.rdbuf()' doesn't work

cout << line << endl;

 

}

Note that, maybe contrary to what is expected, the pipe symbol ( |) must be given as the first character of the ipfstream command string.

Although an ipfstream can be considered a istream, the current implementation appears to have its flaws. One of the unexpected characteristics of the ipfstream is that its rdbuf() member does not appear to work properly. While it should be possible to insert a streambuf pointer into an ostream, the statement cout << ipstr.rdbuf() produces no output. This is confusing, especially as it is not difficult to construct a wrapper class around procbuf that does allow the insertion of its streambuf pointer into an ostream. But allowing for these small inconveniences, the ipfstream object seems to be a useful wrapper class for the procbuf object.

Writing to a separate process

Apart from using a procbuf for reading the standard output from external processes, it is also possible to use procbuf to write information to the standard input of external processes. In order to use a procbuf, sources must

#include <procbuf.h>

A procbuf object may be given as argument to an ostream object, thus creating a process that will receive information wriiten to the ostream object at its standard input. When the ostream object goes out of scope, the associated procbuf will not be destroyed. This is no problem, as the procbuf will be destroyed automatically when its own scope ends.

If an opfstream object is used, all memory management associated with the opfstream is properly handled by the opfstream object.

In the following program the program sort is used to sort lines of input that are fed to it. The lines of imput are originally read via the standard input of our program. Our little program will filters out empty lines and lines having a hash mark ( #) as its first non-blank character. The program uses a procbuf to start the external sort command, which is called with a -f flag, to, as its manual page explains, `fold lower case to upper case characters in keys'. A complex way to tell us that the sorting will be done case insensitively:

#include <iostream> #include <string> #include <procbuf.h>

int main()

{

procbuf pb;

pb.open("sort -f", ios::out);

ostream opb(&pb);

string line;

while (getline(cin, line))

{

161

Object Oriented Programming using C++

unsigned pos;

if

(

line.length() == 0 ||

(pos = line.find_first_not_of(" \t")) != string::npos && line[pos] == '#'

)

continue;

opb << line << endl;

}

}

The following program does the same filtering , using an opfstream object:

#include <pfstream.h> #include <string>

int main()

{

opfstream opb("|sort -f");

string line;

while (getline(cin, line))

{

int

pos;

if

(

line.length() == 0 ||

(pos = line.find_first_not_of(" \t")) != string::npos && line[pos] == '#'

)

continue;

opb << line << endl;

}

}

Remembering positions: the class `streammarker'

Objects of the class streammarker can be used to remember a position in a stream, an to reset the stream to the remembered position quickly. Streammarkers are convenient tools in situations where input is parsed and one of several alternate inputs can be expected. One input route may eventually fail, in which case it is desirable to backtrack to an initial point, from where an alternate route is taken. Much like the way we tend to traverse a maze, but then a bit quicker.

The streammarker class has the following constructor and methods:

Constructor:

A streammarker can be constructed using an existing streambuf pointer. The thus constructed streammarker object stores the current position of the stream for which it is constructed. For example:

streammarker mark(cin.rdbuf());

Member functions:

162

Object Oriented Programming using C++

streammarker::delta():

This member returns the difference in positions between the current position in the stream and another position in the stream stored in the streammarker object. The returned difference is positive if the stored location is farther into the stream than the current position of the stream.

int streammarker::delta(streammarker &other):

This member returns the difference in positions between the current streammarker object and another streammarker object. The returned difference is positive if the current object stores a position that is located farther into the stream than the position that is stored by the other streammarker object.

int streambuf::seekmark(streammarker &mark):

This member sets the postion of the stream to the position where it was when the used streammarker was constructed. The value 0 is returned if resetting succeeds.

Here is a short example showing the use of the various streammarker members:

#include <iostream> #include <string>

int main()

{

string line;

getline(cin, line);

streammarker mark(cin.rdbuf());

getline(cin, line);

streammarker mark2(cin.rdbuf());

cout << "The beginning of the second line is at offset " << cin.tellg() + mark.delta() << endl <<

"The length of the 2nd line, using 2 streammarker objects: " << mark2.delta(mark) << endl;

cout << cin.rdbuf()->seekmark(mark) << endl; getline(cin, line);

cout << "rereading: " << line << endl;

}

/*

Using input: one

two three Generated output:

The beginning of the second line is at offset 4

The length of the 2nd line, using 2 streammarker objects: 10 0

rereading: two three */

163