473,320 Members | 1,799 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,320 software developers and data experts.

Copying with istream_iterator


------ foo.cpp : BEGIN ------
#include <cassert>
#include <vector>
#include <string>
#include <iostream>
#include <iterator>
#include <fstream>
using namespace std;
int main ()
{
ifstream f("foo.in", ios_base::binary);
assert (f);
istream_iterator<string> b(f), e;

cout << "(1) File : ";
copy (b, e, ostream_iterator<string> (cout, " "));
cout << endl;

cout << "(2) File : ";
copy (b, e, ostream_iterator<string> (cout, " "));
cout << endl;

return 0;
}
------ foo.cpp : END --------
------ Compilation & Run : BEGIN ------

$ g++ --version
g++ (GCC) 3.3.1 (cygming special)
[---omitted---]
$ g++ -mno-cygwin foo.cpp

$ a
(1) File : abc xyz ijk pqr
(2) File : abc

------ Compilation & Run : END --------

Why do two copy()'s produce different output?
--
Alex Vinokur
http://mathforum.org/library/view/10978.html
http://sourceforge.net/users/alexvn

Jul 22 '05 #1
9 3151
Alex Vinokur wrote:
------ foo.cpp : BEGIN ------
#include <cassert>
#include <vector>
#include <string>
#include <iostream>
#include <iterator>
#include <fstream>
using namespace std;
int main ()
{
ifstream f("foo.in", ios_base::binary);
assert (f);
istream_iterator<string> b(f), e;

cout << "(1) File : ";
copy (b, e, ostream_iterator<string> (cout, " "));
cout << endl;

cout << "(2) File : ";
copy (b, e, ostream_iterator<string> (cout, " "));
cout << endl;

return 0;
}
------ foo.cpp : END --------
------ Compilation & Run : BEGIN ------

$ g++ --version
g++ (GCC) 3.3.1 (cygming special)
[---omitted---]
$ g++ -mno-cygwin foo.cpp

$ a
(1) File : abc xyz ijk pqr
(2) File : abc

------ Compilation & Run : END --------

Why do two copy()'s produce different output?


Probably because you didn't rewind the stream. The 'istream_iterator'
holds a reference to the stream it's initialised with. Any attempt to
read past the end of the file produce undefined behaviour.

Victor
Jul 22 '05 #2

"Victor Bazarov" <v.********@comAcast.net> wrote in message news:rz*************@newsread1.dllstx09.us.to.veri o.net...
Alex Vinokur wrote:

[snip]
Why do two copy()'s produce different output?


Probably because you didn't rewind the stream. The 'istream_iterator'
holds a reference to the stream it's initialised with. Any attempt to
read past the end of the file produce undefined behaviour.

[snip]
Something like:

------ foo1.cpp : BEGIN ------
#include <cassert>
#include <string>
#include <iostream>
#include <iterator>
#include <fstream>
using namespace std;

int main ()
{
ifstream f("foo.in");
assert (f);
istream_iterator<string> b(f), e;

cout << distance (b, e) << endl;
f.seekg (0, ios::beg);
cout << distance (b, e) << endl;

return 0;
}
------ foo1.cpp : END --------

------ Run : BEGIN ------

$ a
4
1

------ Run : END --------

What happened to 'b' after first 'distance'?
Where should one put 'seekg' (rewind) to get the same result after second 'distance'?
--
Alex Vinokur
http://mathforum.org/library/view/10978.html
http://sourceforge.net/users/alexvn


Jul 22 '05 #3
Alex Vinokur wrote:
"Victor Bazarov" <v.********@comAcast.net> wrote in message news:rz*************@newsread1.dllstx09.us.to.veri o.net...
Alex Vinokur wrote:
[snip]
Why do two copy()'s produce different output?


Probably because you didn't rewind the stream. The 'istream_iterator'
holds a reference to the stream it's initialised with. Any attempt to
read past the end of the file produce undefined behaviour.


[snip]
Something like:

------ foo1.cpp : BEGIN ------
#include <cassert>
#include <string>
#include <iostream>
#include <iterator>
#include <fstream>
using namespace std;

int main ()
{
ifstream f("foo.in");
assert (f);
istream_iterator<string> b(f), e;

cout << distance (b, e) << endl;
f.seekg (0, ios::beg);
cout << distance (b, e) << endl;

return 0;
}
------ foo1.cpp : END --------

------ Run : BEGIN ------

$ a
4
1

------ Run : END --------

What happened to 'b' after first 'distance'?


'distance' uses operator++ to count the number of increments. That
changes the original iterator, doesn't it?
Where should one put 'seekg' (rewind) to get the same result after second 'distance'?


Nowhere. Don't use 'distance'. Perhaps it's a bug in your library
implementation. Did you check how 'distance' worked? The trouble
with 'istream_iterator' is that the connection between it and the
stream is mutating even after you make a copy of the iterator. You
might get lucky that your stream can be brought back to the same
state somehow, or you might never get lucky, and the stream, once it
has been read, can never go back to its beginning...

Why do you need to do that, anyway?

Victor
Jul 22 '05 #4

"Victor Bazarov" <v.********@comAcast.net> wrote in message news:ux*************@newsread1.dllstx09.us.to.veri o.net...
Alex Vinokur wrote:
"Victor Bazarov" <v.********@comAcast.net> wrote in message news:rz*************@newsread1.dllstx09.us.to.veri o.net...
Alex Vinokur wrote:
[snip]
Why do two copy()'s produce different output?

Probably because you didn't rewind the stream. The 'istream_iterator'
holds a reference to the stream it's initialised with. Any attempt to
read past the end of the file produce undefined behaviour.


[snip]
Something like:

------ foo1.cpp : BEGIN ------
#include <cassert>
#include <string>
#include <iostream>
#include <iterator>
#include <fstream>
using namespace std;

int main ()
{
ifstream f("foo.in");
assert (f);
istream_iterator<string> b(f), e;

cout << distance (b, e) << endl;
f.seekg (0, ios::beg);
cout << distance (b, e) << endl;

return 0;
}
------ foo1.cpp : END --------

------ Run : BEGIN ------

$ a
4
1

------ Run : END --------

What happened to 'b' after first 'distance'?


'distance' uses operator++ to count the number of increments. That
changes the original iterator, doesn't it?
Where should one put 'seekg' (rewind) to get the same result after second 'distance'?


Nowhere. Don't use 'distance'. Perhaps it's a bug in your library
implementation.


Microsoft C++ Version 13.00.9466 for 80x86,
Borland C++ 5.5.1,
Digital Mars C++ 8.38n
produce the same behavior.
Did you check how 'distance' worked? The trouble
with 'istream_iterator' is that the connection between it and the
stream is mutating even after you make a copy of the iterator. You
might get lucky that your stream can be brought back to the same
state somehow, or you might never get lucky, and the stream, once it
has been read, can never go back to its beginning...

Why do you need to do that, anyway?

[snip]

I didn't need that, but I came across strange (to me) behavior of copy() while preparing my reply to thread
http://groups-beta.google.com/group/...d64bb7a94fa3a/

Now I would like to understand this situation.
--
Alex Vinokur
http://mathforum.org/library/view/10978.html
http://sourceforge.net/users/alexvn


Jul 22 '05 #5
Alex Vinokur wrote:
"Victor Bazarov" <v.********@comAcast.net> wrote in message news:ux*************@newsread1.dllstx09.us.to.veri o.net...
Alex Vinokur wrote:
"Victor Bazarov" <v.********@comAcast.net> wrote in message news:rz*************@newsread1.dllstx09.us.to.veri o.net...
Alex Vinokur wrote:

[snip]
>Why do two copy()'s produce different output?

Probably because you didn't rewind the stream. The 'istream_iterator'
holds a reference to the stream it's initialised with. Any attempt to
read past the end of the file produce undefined behaviour.

[snip]
Something like:

------ foo1.cpp : BEGIN ------
#include <cassert>
#include <string>
#include <iostream>
#include <iterator>
#include <fstream>
using namespace std;

int main ()
{
ifstream f("foo.in");
assert (f);
istream_iterator<string> b(f), e;

cout << distance (b, e) << endl;
f.seekg (0, ios::beg);
cout << distance (b, e) << endl;

return 0;
}
------ foo1.cpp : END --------

------ Run : BEGIN ------

$ a
4
1

------ Run : END --------

What happened to 'b' after first 'distance'?


'distance' uses operator++ to count the number of increments. That
changes the original iterator, doesn't it?

Where should one put 'seekg' (rewind) to get the same result after second 'distance'?


Nowhere. Don't use 'distance'. Perhaps it's a bug in your library
implementation.

Microsoft C++ Version 13.00.9466 for 80x86,
Borland C++ 5.5.1,
Digital Mars C++ 8.38n
produce the same behavior.

Did you check how 'distance' worked? The trouble
with 'istream_iterator' is that the connection between it and the
stream is mutating even after you make a copy of the iterator. You
might get lucky that your stream can be brought back to the same
state somehow, or you might never get lucky, and the stream, once it
has been read, can never go back to its beginning...

Why do you need to do that, anyway?


[snip]

I didn't need that, but I came across strange (to me) behavior of copy() while preparing my reply to thread
http://groups-beta.google.com/group/...d64bb7a94fa3a/

Now I would like to understand this situation.


If you feel like it, dig in the source of the C++ library (or libraries)
you're using. It seems that since 'copy' is a template, it probably gets
its arguments in the form of references (and not objects copied due to
passing by value). If it's so, the objects change while 'copy' does its
thing. How they change you can also discover by looking at the code. If
you find it interesting/revealing/puzzling, do post again.

You could also experiment with passing by value:

...
void foo(istream_iterator b, istream_iterator e)
{
std::copy(b, e, ...
}

int main()
{
...
foo(b, e);
// reset the stream
std::copy(b, e, ...
}

and see if it makes any difference...

V
Jul 22 '05 #6
On Wed, 21 Jul 2004 19:58:32 +0300, "Alex Vinokur"
<al****@big-foot.com> wrote:
int main ()
{
ifstream f("foo.in", ios_base::binary);
assert (f);
istream_iterator<string> b(f), e;

cout << "(1) File : ";
copy (b, e, ostream_iterator<string> (cout, " "));
cout << endl;

cout << "(2) File : ";
copy (b, e, ostream_iterator<string> (cout, " "));
cout << endl;

return 0;
}
(1) File : abc xyz ijk pqr
(2) File : abc
Why do two copy()'s produce different output?


When you take a copy of an input iterator, the original one is still
affected by changes to the copy. istream_iterator can only be used for
1-pass algorithms. Rewinding the stream and then constructing a new
iterator from the stream is the only safe way to do a second pass.
e.g. something like:
int main ()
{
ifstream f("foo.in", ios_base::binary);
assert (f);
istream_iterator<string> b(f), e;

cout << "(1) File : ";
copy (b, e, ostream_iterator<string> (cout, " "));
cout << endl;

f.seekg(0, std::ios_base::beg);
b = istream_iterator<string>(f);

cout << "(2) File : ";
copy (b, e, ostream_iterator<string> (cout, " "));
cout << endl;

return 0;
}

Tom
Jul 22 '05 #7

"tom_usenet" <to********@hotmail.com> wrote in message news:iv********************************@4ax.com...
On Wed, 21 Jul 2004 19:58:32 +0300, "Alex Vinokur"
<al****@big-foot.com> wrote:
int main ()
{
ifstream f("foo.in", ios_base::binary);
assert (f);
istream_iterator<string> b(f), e;

cout << "(1) File : ";
copy (b, e, ostream_iterator<string> (cout, " "));
cout << endl;

cout << "(2) File : ";
copy (b, e, ostream_iterator<string> (cout, " "));
cout << endl;

return 0;
}
(1) File : abc xyz ijk pqr
(2) File : abc
Why do two copy()'s produce different output?
When you take a copy of an input iterator, the original one is still
affected by changes to the copy. istream_iterator can only be used for
1-pass algorithms. Rewinding the stream and then constructing a new
iterator from the stream is the only safe way to do a second pass.
e.g. something like:
int main ()
{
ifstream f("foo.in", ios_base::binary);
assert (f);
istream_iterator<string> b(f), e;

cout << "(1) File : ";
copy (b, e, ostream_iterator<string> (cout, " "));
cout << endl;

f.seekg(0, std::ios_base::beg);
b = istream_iterator<string>(f);


It doesn't help.

cout << "(2) File : ";
copy (b, e, ostream_iterator<string> (cout, " "));
cout << endl;

return 0;
}

Tom


Here is some program which demonstrates behavior of istream_iterator.

====== File foo.cpp : BEGIN ======
#include <cassert>
#include <string>
#include <iostream>
#include <iterator>
#include <fstream>
using namespace std;

int main ()
{
ifstream f("foo.in", ios::binary);
assert (f);

cout << "Before istream_iterator : tellg() = " << f.tellg() << endl;
cout << endl;

istream_iterator<string> b(f), e;
cout << "--- First ---" << endl;
cout << "After istream_iterator : tellg() = " << f.tellg() << endl;
cout << "Output-1.1 = ";
copy (b, e, ostream_iterator<string> (cout, " "));
cout << endl;
cout << "After first copy : tellg() = " << f.tellg() << endl;
cout << "Output-1.2 = ";
copy (b, e, ostream_iterator<string> (cout, " "));
cout << endl;
cout << endl;
cout << "--- Second ---" << endl;
f.clear();
f.seekg(0, ios::beg);
cout << "After clear and seekg : tellg() = " << f.tellg() << endl;
cout << "Output-2.1 = ";
copy (b, e, ostream_iterator<string> (cout, " "));
cout << endl;
cout << "After second copy : tellg() = " << f.tellg() << endl;
cout << endl;
cout << "--- Third ---" << endl;
f.clear();
f.seekg(0, ios::beg);
cout << "After clear and seekg : tellg() = " << f.tellg() << endl;
b++;
cout << "After b++ : tellg() = " << f.tellg() << endl;
cout << "Output-3.1 = ";
copy (b, e, ostream_iterator<string> (cout, " "));
cout << endl;
cout << "After third copy : tellg() = " << f.tellg() << endl;
cout << endl;
return 0;
}
====== File foo.cpp : END ========
====== Compilation & Run : BEGIN ======

$ g++ --version
g++ (GCC) 3.3.1 (cygming special)
[---omitted---]

$ g++ foo.cpp

$ a

Before istream_iterator : tellg() = 0

--- First ---
After istream_iterator : tellg() = 3
Output-1.1 = aaa bbb ccc ddd
After first copy : tellg() = -1
Output-1.2 = aaa

--- Second ---
After clear and seekg : tellg() = 0
Output-2.1 = aaa aaa bbb ccc ddd
After second copy : tellg() = -1

--- Third ---
After clear and seekg : tellg() = 0
After b++ : tellg() = 3
Output-3.1 = aaa bbb ccc ddd
After third copy : tellg() = -1

====== Compilation & Run : END ========
--
Alex Vinokur
http://mathforum.org/library/view/10978.html
http://sourceforge.net/users/alexvn

Jul 22 '05 #8
Alex Vinokur wrote:
"tom_usenet" <to********@hotmail.com> wrote in message news:iv********************************@4ax.com...
On Wed, 21 Jul 2004 19:58:32 +0300, "Alex Vinokur"
<al****@big-foot.com> wrote:
int main ()
{
ifstream f("foo.in", ios_base::binary);
assert (f);
istream_iterator<string> b(f), e;

cout << "(1) File : ";
copy (b, e, ostream_iterator<string> (cout, " "));
cout << endl;

cout << "(2) File : ";
copy (b, e, ostream_iterator<string> (cout, " "));
cout << endl;

return 0;
}
(1) File : abc xyz ijk pqr
(2) File : abc
Why do two copy()'s produce different output?
When you take a copy of an input iterator, the original one is still
affected by changes to the copy. istream_iterator can only be used for
1-pass algorithms. Rewinding the stream and then constructing a new
iterator from the stream is the only safe way to do a second pass.
e.g. something like:
int main ()
{
ifstream f("foo.in", ios_base::binary);
assert (f);
istream_iterator<string> b(f), e;

cout << "(1) File : ";
copy (b, e, ostream_iterator<string> (cout, " "));
cout << endl;

f.seekg(0, std::ios_base::beg);
b = istream_iterator<string>(f);

It doesn't help.


You probably also need to do

f.clear();

before f.seekg( ..

Once the EOF is reached, the stream becomes non-responsive until
you clear its error state.

V

cout << "(2) File : ";
copy (b, e, ostream_iterator<string> (cout, " "));
cout << endl;

return 0;
}

Tom


[...]

Jul 22 '05 #9

"Victor Bazarov" <v.********@comAcast.net> wrote in message news:lG*************@newsread1.dllstx09.us.to.veri o.net...
[snip]
If you feel like it, dig in the source of the C++ library (or libraries)
you're using. It seems that since 'copy' is a template, it probably gets
its arguments in the form of references (and not objects copied due to
passing by value). If it's so, the objects change while 'copy' does its
thing. How they change you can also discover by looking at the code. If
you find it interesting/revealing/puzzling, do post again.

You could also experiment with passing by value:

...
void foo(istream_iterator b, istream_iterator e)
{
std::copy(b, e, ...
}

int main()
{
...
foo(b, e);
// reset the stream
std::copy(b, e, ...
}

and see if it makes any difference...

V

We can see that there is no difference between passing by value and passing by reference because
a position of the pointer in istream 'f' (not istream_iterator 'b') determines such behavior.

====== foo.cpp : BEGIN ======
#include <cassert>
#include <string>
#include <iostream>
#include <iterator>
#include <fstream>
using namespace std;

void copy_by_value(istream_iterator<string> b, istream_iterator<string> e)
{
copy (b, e, ostream_iterator<string> (cout, " "));
}

void copy_by_ref(const istream_iterator<string>& b, const istream_iterator<string>& e)
{
copy (b, e, ostream_iterator<string> (cout, " "));
}

void test_by_value()
{
cout << "=== test_by_value ===" << endl;
ifstream f("foo.in", ios_base::binary);
assert (f);
cout << "Before istream_iterator : tellg() = " << f.tellg() << endl;
istream_iterator<string> b(f), e;
cout << "After istream_iterator : tellg() = " << f.tellg() << endl;
cout << "Output-1 =";
copy_by_value (b, e);
cout << endl;
cout << "After copy_by_value : tellg() = " << f.tellg() << endl;

cout << "Output-2 =";
copy (b, e, ostream_iterator<string> (cout, " "));
cout << endl;
cout << endl;
}

void test_by_ref()
{
cout << "=== test_by_ref ===" << endl;
ifstream f("foo.in", ios_base::binary);
assert (f);
cout << "Before istream_iterator : tellg() = " << f.tellg() << endl;
istream_iterator<string> b(f), e;
cout << "After istream_iterator : tellg() = " << f.tellg() << endl;
cout << "Output-1 =";
copy_by_ref (b, e);
cout << endl;
cout << "After copy_by_ref : tellg() = " << f.tellg() << endl;

cout << "Output-2 =";
copy (b, e, ostream_iterator<string> (cout, " "));
cout << endl;
cout << endl;
}
int main ()
{
test_by_value();
test_by_ref();

return 0;
}
====== foo.cpp : END ========
###### Run : BEGIN ######

=== test_by_value ===
Before istream_iterator : tellg() = 0
After istream_iterator : tellg() = 3
Output-1 =aaa bbb ccc ddd
After copy_by_value : tellg() = -1
Output-2 =aaa

=== test_by_ref ===
Before istream_iterator : tellg() = 0
After istream_iterator : tellg() = 3
Output-1 =aaa bbb ccc ddd
After copy_by_ref : tellg() = -1
Output-2 =aaa
###### Run : END ######

--
Alex Vinokur
http://mathforum.org/library/view/10978.html
http://sourceforge.net/users/alexvn

Jul 22 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: Bill Rudolph | last post by:
The member function basic_ios::operator!() returns the bool result of the basic_ios::fail() function which is true if either failbit or badbit is set (This is per p. 616 of TC++PL by B. Stroustrup...
10
by: Alex Vinokur | last post by:
ofstream outfile ("out"); ifstream infile ("in"); istream_iterator<char> iter(infile), eos; Is it possible to copy 'infile' to 'outfile' using 'iter' and 'eos'? -- Alex Vinokur...
3
by: NPC | last post by:
Hi, Is there any way to use an istream_iterator<> in a way which inserts each element at the end of a newline character rather than a space character? Could be it looks for any type of whitespace...
2
by: alberto | last post by:
I am learning STL with the book STL Tutorial and Reference guide (1 edition), the following example don't run : int main() { // Initialize array a with 10 integers: int a = {12, 3, 25, 7, 11,...
15
by: Shuch | last post by:
Hi all, i m trying to read from a file and then copy it into an array...my code is as follow..it runs fine but i cant understand y it doesnt show me any output?? here is my code... using...
3
by: jmoy.matecon | last post by:
I get an error while compiling the following program: int main() { vector<int> v(istream_iterator<int>(cin), istream_iterator<int>()); copy(v.begin(),v.end(),ostream_iterator<int>(cout,"\n"));...
2
by: Juha Nieminen | last post by:
I'm using gcc 3.3.5. This code: std::set<std::stringt(std::istream_iterator<std::string>(std::cin), std::istream_iterator<std::string>()); gives a strange error message: error: cannot use...
12
by: arnuld | last post by:
It works fine. any advice on making it better or if I can improve my C++ coding skills: /* C++ Primer - 4/e * * Chapter 9 - Sequential Containers * exercise 9.18 - STATEMENT * ...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
0
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
0
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.