Valarray input from file 
July 22nd, 2005, 04:38 PM
| | | Valarray input from file
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[i];
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 | 
July 22nd, 2005, 04:38 PM
| | | Re: Valarray input from file
"Daniel Brewer" <dan_list@brewer.me.uk> wrote in message
news:cdghrl$3070$1@uns-a.ucl.ac.uk...[color=blue]
> 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?[/color]
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>>
[color=blue]
> So far I have:
>
> std::istream& operator>>( std::istream& is, std::valarray<double>& t )
> {
> for(i=0;;i++)
> {
> t.resize(i+1);
> is >> t[i];
> if (is.eof()) break;
> }
>
> return is;
> }
>
>
> but this does not seem to work.[/color]
Well, one reason it doesn't work is that you aren't testing for a newline
anywhere.
[color=blue]
>
> Any ideas what the best approach to this would be?
>[/color]
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 | 
July 22nd, 2005, 04:38 PM
| | | Re: Valarray input from file
> std::copy(std::istream_iterator<double>(buf),[color=blue]
> std::istream_iterator<double>(buf),
> std::back_inserter(temp_vec));
>[/color]
Should be
std::copy(std::istream_iterator<double>(buf),
std::istream_iterator<double>(),
std::back_inserter(temp_vec));
As I said, untested code.
john | 
July 22nd, 2005, 04:38 PM
| | | Re: Valarray input from file
John Harrison wrote:
[color=blue][color=green]
>> std::copy(std::istream_iterator<double>(buf),
>> std::istream_iterator<double>(buf),
>> std::back_inserter(temp_vec));
>>[/color]
>
>
> Should be
>
> std::copy(std::istream_iterator<double>(buf),
> std::istream_iterator<double>(),
> std::back_inserter(temp_vec));
>
> As I said, untested code.
>
> john
>
>[/color]
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 | 
July 22nd, 2005, 04:38 PM
| | | Re: Valarray input from file
Daniel Brewer wrote:
[color=blue]
> 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[i];
> if (is.eof()) break;
> }
>
> return is;
> }
>
>
> but this does not seem to work.
>
> Any ideas what the best approach to this would be?[/color]
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.
--
Regards,
Buster. | | Thread Tools | Search this Thread | | | |
Posting Rules
| You may not post new threads You may not post replies You may not post attachments You may not edit your posts HTML code is Off | | | | | | What is Bytes?
We are a network of experts and professionals in IT and software development that help one another with answers to tough questions and share insights.
Get the best answers to your questions from over 220,989 network members.
|