Originally Posted by
Elysia
One way I can think of is to use
std::getline to read a full line. Then, you can construct a
string stream from the string you read, and then construct an
istream_iterator from that. You can then use
std::copy to copy the items out of the line into a vector to hold your items using a back_insert operator (you can use
std::back_inserter to make one) as the third parameter, the output iterator to std::copy.
Then write everything back into an output file from the strings in your vector, putting whitespace and newlines as you desire.
Alright - I found a way to integrate stringstream, istream_operator and copy. Here's the current version of the code:
Code:
#include<iostream>
#include<sstream>
#include<fstream>
#include<iterator>
using namespace std;
template <class T>
class csv_istream_iterator: public iterator<input_iterator_tag, T>
{
istream * _input;
char _delim;
string _value;
public:
csv_istream_iterator( char delim = ',' ): _input( 0 ), _delim( delim ) {}
csv_istream_iterator( istream & in, char delim = ',' ): _input( &in ), _delim( delim ) { ++*this; }
const T operator *() const {
istringstream ss( _value );
T value;
ss >> value;
return value;
}
istream & operator ++() {
if( !( getline( *_input, _value, _delim ) ) )
{
_input = 0;
}
return *_input;
}
booloperator !=( const csv_istream_iterator & rhs ) const {
return _input != rhs._input;
}
};
template <>
const string csv_istream_iterator<string>::operator *() const {
return _value;
}
int main( int argc, char * args[] )
{
ifstream ft( "input1.csv" ); // declare ft stream
// 1) Get number of data points
string datapoints, dummy;
getline(ft, datapoints, ','); // read very first value: # data points
cout << "datapoints: " << string(datapoints) << endl;// display number of datapoints
double count = atof(datapoints.c_str());
getline(ft, dummy, '\n'); // read and drop second value
// 2) Start writing into output file
string outfilename = "out.txt";
ofstream fout(outfilename.c_str());
for (int row = 1; row <= count; row++)
{
// enumerator
fout << row << '\t';
if( ft )
{
copy( csv_istream_iterator<string>( ft ),
csv_istream_iterator<string>(),
ostream_iterator<string>( cout, "," ) );
}
}
fout.close();
return 0;
}
The output is as follows:
1 1:4,2:5,3:7,4:4,5:7
,
2 1:4,2:3,3:6,4:4,5:6
,
3 1:4,2:4,3:7,4:4,5:7
,
4 1:2,3:5,4:7,5:4,8:3
,
5 2:3,4:4,5:7,,
,
6 1:4,3:7,4:6,,
,
7 ,,,,
,
8 2:4,8:7,,,
,
9 3:1,4:4,6:7,,
,
10 1:5,2:8,,,
,
11 1:1,2:5,,,
,
12 3:4,4:5,6:8,,
However, there are a few things which are disturbing and must be mended: 1) All these extra commas. If there's no additional character, the commas must go away. 2) I have not made use of back_inserter yet. Where does that come in?