Connecting Tech Pros Worldwide Help | Site Map

Valarray input from file

  #1  
Old July 22nd, 2005, 05:38 PM
Daniel Brewer
Guest
 
Posts: n/a
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
  #2  
Old July 22nd, 2005, 05:38 PM
John Harrison
Guest
 
Posts: n/a

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


  #3  
Old July 22nd, 2005, 05:38 PM
John Harrison
Guest
 
Posts: n/a

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


  #4  
Old July 22nd, 2005, 05:38 PM
Daniel Brewer
Guest
 
Posts: n/a

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
  #5  
Old July 22nd, 2005, 05:38 PM
Buster
Guest
 
Posts: n/a

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.
Closed Thread


Similar Threads
Thread Thread Starter Forum Replies Last Post
modifying a container outside function Gary Wessle answers 2 August 19th, 2006 04:05 AM
Datagrid link button click event in clientside Niclas Lindblom answers 2 November 18th, 2005 02:05 PM
Need help with conditional creation of a popup window Sol Linderstein answers 3 July 23rd, 2005 12:22 PM
Qs on 'late construction' and operator >> Michael Hopkins answers 6 July 23rd, 2005 05:32 AM