Sunday, October 20, 2024

istream iterator

Overview
IOStream classes provides iterators for reading and writing from streams just like a containers. istream_iterator enables reading objects from the stream.

Details
istream iterators are input iterators that read successive elements from an input stream (such as cin).

They are constructed from a basic_istream object, to which they become associated, so that whenever operator++ is used on the iterator, it extracts an element from the stream (using operator>>).

Syntax
The syntax is as below. 

template< class T,
          class CharT = char,
          class Traits = char_traits<CharT>,
          class Distance = ptrdiff_t >
class istream_iterator;

NameDescription
TRepresents Element type for the iterator: The type of elements extracted from the stream
charTCharacter type of the associated istream object.
traitsCharacter traits of the associated istream object.
DistanceRepresent the difference between two iterators.

Members
 It defines following types.
member typedefinition
iterator_categoryinput_iterator_tag
value_typeT
difference_typeDistance
pointerconst T*
referenceconst T&

Operation
An istream_iterator  as an input iterator supports operators *, ++,->, == , and !=. 

istream_iterator is a single-pass input iterator that reads successive objects of type T from the basic_istream object (such as cin) for which it was constructed, by internally calling the appropriate operator >>. The actual read operation is performed when the iterator is incremented, not when it is dereferenced. The first object is read when the iterator is constructed. Dereferencing only returns a copy of the most recently read object.

In other words, unlike in a list or a vector, the iterator solely depends on the current position of the stream iterator of the stream object. 

The default-constructed istream_iterator is known as the end-of-stream iterator. When a valid istream_iterator  reaches the end of the underlying stream, it becomes equal to the end-of-stream iterator. 

When reading characters, istream_iterator skips whitespace by default. Also a sentry object is constructed and destructed once per character.

A typical implementation of istream_iterator holds two data members: a pointer to the associated istream_iterator object and the most recently read value of type T.

This can be clearly seen in the example below. 
istringstream ss{"20   30   30"};

//Calculates sum of the numbers from the stream. skips white space
//prints 80
cout << accumulate (
    istream_iterator<int>(ss),
    istream_iterator<int>(), //EOS
    0) << endl << endl;

//iterator and stream object behavior
istringstream ss2{"abcd"};

//prints 0
cout << ss2.tellg()  << endl;

istream_iterator<char>  it(ss2), it2(it);
//prints a a 1
cout << *it  << " " << *it2 << " "  << ss2.tellg() << endl;

++it;
//prints b a 2
cout << *it  << " " << *it2 << " "  << ss2.tellg() << endl;

//prints c
char c;
ss2 >> c;
cout << c << endl;

//prints b d 3
cout << *it  << " " << *it2 << " "  << ss2.tellg() << endl;
    
++it2;
//prints b d 4
cout << *it  << " " << *it2 << " "  << ss2.tellg() << endl;

Functionality
Constructors
NameDescription
istream_iterator()Default Constructor. Creates end of stream iterator.

Example:
istream_iterator eos;
istream_iterator( istream_type& s)Initializes the iterator, stores the address of stream s, and performs the first read from the input stream to initialize the cached value data member.
Example:
istringstream ss{"abcd"};
istream_iterator<char>  it(ss);
//prints a
cout << *it  << endl;
istream_iterator (const istream_iterator& x)
copy constructor
Constructs an istream iterator, with the same istream reference and current value.
Example:
istringstream ss{"abcd"};
istream_iterator<char>  it(ss), it2(it++);
//prints ba
cout << *it  << *it2 << endl;

Overloaded operators
NameExample
reference operator*() 
Returns a reference to the element pointed by the iterator.
Internally, the function returns the value the object stores as its current element.
Example:
istringstream ss{"abcd"};
istream_iterator<char>  it(ss);
//prints a
cout << *it  << endl;
  1. istream_iterator& operator++()
  2. istream_iterator& operator++(int)
Reads a value from the underlying stream (using its operator>>) and stores it into the iterator object. If the read fails (the underlying stream's fail() returns true), the iterator becomes the end-of-stream iterator.
Example:
istringstream ss{"abcd"};
istream_iterator<char>  it(ss), it2;

it2 = it++;
//prints b a
cout << *it  << " " << *it2 << endl;

it=++it2;
//prints c c
cout << *it  << " " << *it2  << endl;
pointer operator->() Returns reference to the member of the class.

Example:
struct rect
{
    int  h,w;
};

istream& operator>>(istream& is,  rect& r)
{
    is >> r.h;
    is >> r.w;
    return is;
}

rect r;
istringstream ss("4 5");

istream_iterator<rect>  it(ss);

//prints 4 5
cout << it->h << " " << it->w;



No comments:

Post a Comment