Search code examples
c++inputstreamifstreamoutputstreamofstream

Reading from std::ofstream line by line (but not from the file)


in my project I need to use the following library (OMPL). I am interested in particular in a the member function printAsMatrix(std::ofstream &out) which outputs data to a terminal or to a file. Here the function:

 void ompl::geometric::PathGeometric::printAsMatrix(std::ostream &out) const
 {
  const base::StateSpace* space(si_->getStateSpace().get());
  std::vector<double> reals;
  for (unsigned int i = 0 ; i < states_.size() ; ++i)
  {
  space->copyToReals(reals, states_[i]);
  std::copy(reals.begin(), reals.end(), std::ostream_iterator<double>(out, " "));
  out << std::endl;
  }
  out << std::endl;
 }

but I need those the outputted values in thier original form, as double. For this reason I thought to read them though the ifstringstream library using the following function implemented on my own:

std::ofstream solution_matrix; 

pg->printAsMatrix( solution_matrix ); // generate the solution with OMPL and copy them into "solution_matrix"

std::istringstream istr; // generate a variable 
std::string buffer;      // the buffer in which the string is going to be copied t

double var1, var2; // dummies variables

while( getline( solution_matrix, buffer ) ) {
   istr.str( buffer );
   istr >> var1 >> var2 >> var3 >> var4 >> var5 >> var6 >> var7;
   std::cout >> var1 >> var2; // did you copy all data!?!? Show me please!
}

I get a lot of compilation errors because of the getline function which accepts only std::ifstream data.

So heir what I did as a temporary workaround:

  1. Created a new ifstream variable:

    std::ifstream input_matrix;

  2. Tried to copy the outputted matrix into the input:

    solution_matrix << input_matrix;

  3. call the getline function with the new variable:

    getline( input_matrix, buffer );

I have now no compilation errors but the code simply doesn't work. Plus I m not really sure that I did it in the right way.

Looking around I found lot of example using a file to copy at first the data and then reading from the same file with ifstream. Something like:

  // Print the solution path to a file
  std::ofstream ofs("path.dat");
  pg->printAsMatrix(ofs);

But to do that I need to create a new file, save it on the hard disk and then open it a second time using ifstream:

std::ifstream file;
file.open( "path.dat" );

This way works but I really don't want to create a file. Is there a way to do it:

  1. without creating a file;
  2. reading the matrix line by line (I will sort out the values);

Many thank in advance


Solution

  • You can use a std::stringstream with std::getline, which can be passed to your function as the ostream parameter. For example:

    std::stringstream solution_matrix; 
    
    pg->printAsMatrix( solution_matrix ); 
    
    std::string line;
    while (std::getline(solution_matrix, line)) {
        std::cout << line << std::endl;
    }
    

    Also, your << are the wrong way round in your cout statement:

    std::cout >> var1 >> var2;
    

    Should be:

    std::cout << var1 << var2;
    

    EDIT

    To clarify this here is a full example to show this working:

    #include <algorithm>
    #include <iostream>
    #include <iterator>
    #include <sstream>
    #include <fstream>
    #include <vector>
    #include <string>
    
    void func(std::ostream&, const std::vector<double>&);
    
    int main(int argc, char *argv[]) 
    {
      std::stringstream solution_matrix; 
      std::vector<double> example;
      for (int i=0; i<10; ++i) {
        example.push_back(i);
      }
    
      func(solution_matrix, example);
    
      std::string line;
      while (std::getline(solution_matrix, line)) {
        std::cout << line << std::endl;
      }
    
    }
    
    void func(std::ostream& out, const std::vector<double>& data)
    {
      std::copy(data.begin(), data.end(), std::ostream_iterator<double>(out, "\n"));
    }
    

    Here func is similar to your printAsMatrix() function, in that it writes to an ostream. The vector example contains the values 0-9. The output is:

    0
    1
    2
    3
    4
    5
    6
    7
    8
    9