Valarray input from file

D

Daniel Brewer

Hi there,

I would like to define a general operator>> function for valarrays that
allows the input of an arbitary sized array from a file. An example data
file would be like:
0 1 2 3 4 5 6
4 5 6 7 8 9 10 11 12

With each line defining a different valarray. Is it possible to do this?
So far I have:

std::istream& operator>>( std::istream& is, std::valarray<double>& t )
{
for(i=0;;i++)
{
t.resize(i+1);
is >> t;
if (is.eof()) break;
}

return is;
}


but this does not seem to work.

Any ideas what the best approach to this would be?

Thanks

Dan
 
J

John Harrison

Daniel Brewer said:
Hi there,

I would like to define a general operator>> function for valarrays that
allows the input of an arbitary sized array from a file. An example data
file would be like:
0 1 2 3 4 5 6
4 5 6 7 8 9 10 11 12

With each line defining a different valarray. Is it possible to do this?

Its possible but I'm not sure its a good idea because it contradicts every
other operator>> which treat newlines in the same way as every other kind of
whitespace.

I'm not saying you shouldn't write a routine to do this, I just don't think
you should call it operator>>
So far I have:

std::istream& operator>>( std::istream& is, std::valarray<double>& t )
{
for(i=0;;i++)
{
t.resize(i+1);
is >> t;
if (is.eof()) break;
}

return is;
}


but this does not seem to work.


Well, one reason it doesn't work is that you aren't testing for a newline
anywhere.
Any ideas what the best approach to this would be?

How about this ugly (and untested) code

#include <iostream>
#include <sstream>
#include <string>
#include <iterator>
#include <valarray>
#include <vector>

std::istream& read_valarray(std::istream& in, std::valarray<double>& val)
{
// read a line
std::string line;
std::getline(in, line);

// copy line to a vector
std::vector<double> temp_vec;
std::istringstream buf(line);
std::copy(std::istream_iterator<double>(buf),
std::istream_iterator<double>(buf),
std::back_inserter(temp_vec));

// copy the vector to the valarray
val.resize(temp_vec.size());
val = std::valarray<double>(&temp_vec[0], temp_vec.size());
return in;
}

john
 
J

John Harrison

std::copy(std::istream_iterator said:
std::istream_iterator<double>(buf),
std::back_inserter(temp_vec));

Should be

std::copy(std::istream_iterator<double>(buf),
std::istream_iterator<double>(),
std::back_inserter(temp_vec));

As I said, untested code.

john
 
D

Daniel Brewer

John said:
Should be

std::copy(std::istream_iterator<double>(buf),
std::istream_iterator<double>(),
std::back_inserter(temp_vec));

As I said, untested code.

john
Thanks I will give it ago. So a standard operator>> ignores all
carriage returns, spaces etc. In that case maybe I should define a
"normal" operator>> and then adapt the resulting valarray some how.

Thanks for your help

Dan Brewer
 
B

Buster

Daniel said:
I would like to define a general operator>> function for valarrays that
allows the input of an arbitary sized array from a file. An example data
file would be like:
0 1 2 3 4 5 6
4 5 6 7 8 9 10 11 12

With each line defining a different valarray. Is it possible to do this?
So far I have:

std::istream& operator>>( std::istream& is, std::valarray<double>& t )
{
for(i=0;;i++)
{
t.resize(i+1);
is >> t;
if (is.eof()) break;
}

return is;
}


but this does not seem to work.

Any ideas what the best approach to this would be?


John's right, you should be using std::getline.

Another reason your function won't work is that 'resize' is destructive,
replacing the old valarray with a zero-initialized valarray of the new
size. This is described on page 666 of "The C++ Programming Language"
(3rd/Special edition). Bad omen?

You need to create your own valarray of the new size, and copy the old
contents across each time. All this copying will take time, so it's
probably best to allocate a larger valarray than you need, so you have
to resize less often. All this would be taken care of if you used a
vector instead of a valarray.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,818
Latest member
Brigette36

Latest Threads

Top