when I run the code below I get garbage output after reading the data from the text file and printing it out. I believe the problem is with my user defined input operator but I can't be sure. The data gets written to the text file just fine, as follows:
1 2 3 4 5 6 7
(1,1)
(2,2)
(3,3)
(4,4)
(5,5)
(6,6)
(7,7)
the data that gets input from the textfile and printed out at the end of main looks like this...
#include <iostream>
#include <vector>
#include <fstream>
usingnamespace std;
struct Point
{
int x;
int y;
};
ostream& operator<<( ostream& os, Point& p )
{
return os << "(" << p.x << "," << p.y << ")";
}
istream& operator>>( istream& is, Point& p )
{
int x, y;
char ch1, ch2, ch3;
is >> ch1 >> x >> ch2 >> y >> ch3;
p = Point{x,y};
return is;
}
int main()
{
//read data from keyboard into vector op.
vector<Point> op;
int x, y;
cout << "Enter 7 points\n";
for( int i=0; i<7; i++ )
{
cin >> x >> y;
op.push_back( Point{x,y} );
}
// write the data to the screen using user defined output operator
for( Point p : op )
{
cout << p << "\n";
}
// write the data to a text file using user defined output operator
ofstream ost( "data.txt" );
for( Point p : op )
{
ost << p << "\n";
}
// read data from text file using user defined input operator
vector<Point> ip;
Point p;
ifstream ist{ "data.txt" };
for( int i=0; i<7; i++ )
{
ist >> p;
ip.push_back( p );
}
// write data to screen using user defined output operator
for( int i=0; i<ip.size(); i++ )
cout << ip[i] << "\n";
return 0;
}
when I strip my code down to the following, the input operator works fine and the data gets input from the text file and printed out properly. This puzzles me, since the remaining code has not changed.
If anyone can find where I am messing up, it would be most appreciated.
#include <iostream>
#include <vector>
#include <fstream>
usingnamespace std;
struct Point
{
int x;
int y;
};
ostream& operator<<( ostream& os, Point &p )
{
cout << "(" << p.x << "," << p.y << ")";
}
istream& operator>>( istream& is, Point& p )
{
int x, y;
char ch1, ch2, ch3;
is >> ch1 >> x >> ch2 >> y >> ch3;
p = Point{x,y};
return is;
}
int main()
{
// read data from text file using user defined input operator
vector<Point> ip;
Point p;
ifstream ist{ "data.txt" };
for( int i=0; i<7; i++ )
{
ist >> p;
ip.push_back( p );
}
// write data to screen using user defined output operator
for( int i=0; i<ip.size(); i++ )
cout << ip[i] << "\n";
return 0;
}
your remark about ofstream using an intermediate buffer proved to be right. I added an ost.close() to close the output stream before opening an input stream. This flushed the output buffer to file, and this time there was data for the input stream to read.
#include <iostream>
#include <vector>
#include <fstream>
struct Point
{
int x;
int y;
};
// note: required for comparing vectors of points using ==
booloperator== ( Point a, Point b ) { return a.x == b.x && a.y == b.y ; }
// this is not really required in this particular program; just being decent
booloperator!= ( Point a, Point b ) { return !(a==b); }
std::ostream& operator<< ( std::ostream& os, const Point& p )
{ return os << '(' << p.x << ',' << p.y << ')'; }
std::istream& operator>>( std::istream& is, Point& p )
{
int x, y;
char ch1, ch2, ch3;
if( is >> ch1 >> x >> ch2 >> y >> ch3 &&
ch1 == '(' && ch2 == ',' && ch3 == ')' ) p = {x,y}; // validate
else is.setstate( is.rdstate() | std::ios_base::failbit ) ; // input failed
return is;
}
int main()
{
//read data from keyboard into vector op.
std::vector<Point> op;
std::cout << "Enter points one by one, enter eof to end input\n";
int x, y;
while( std::cin >> x >> y ) op.push_back( { x, y } );
// write the data to the screen using user defined output operator
for( Point p : op ) std::cout << p << '\n';
// write the data to a text file using user defined output operator
// canonical: if the file was opened, write every object in the sequence to the file
if( std::ofstream ost{ "data.txt" } ) for( Point p : op ) ost << p << '\n';
else std::cerr << "error opening output file\n" ;
// note: the output stream ost is destroyed when it goes out of scope
// read data from text file using user defined input operator
std::vector<Point> ip;
Point p;
if( std::ifstream ist{ "data.txt" } ) while( ist >> p ) ip.push_back(p) ;
else std::cerr << "error opening input file\n" ;
// verify that the two vectors are equal (lexicographically equal)
if( ip == op ) std::cout << "read back the points successfully\n" ;
else std::cerr << "error in i/o of point\n" ;
// write data to screen using user defined output operator
for( auto p : ip ) std::cout << p << '\n';
}
#include <iostream>
#include <vector>
#include <fstream>
#include <utility>
using Point = std::pair<int,int> ;
std::ostream& operator<< ( std::ostream& os, const Point& p )
{ return os << '(' << p.first << ',' << p.second << ')'; }
std::istream& operator>>( std::istream& is, Point& p )
{
int x, y;
char ch1, ch2, ch3;
if( is >> ch1 >> x >> ch2 >> y >> ch3 &&
ch1 == '(' && ch2 == ',' && ch3 == ')' ) p = {x,y}; // validate
else is.setstate( is.rdstate() | std::ios_base::failbit ) ; // input failed
return is;
}
int main()
{
//read data from keyboard into vector op.
std::vector<Point> op;
std::cout << "Enter points one by one, eof to end input\n";
int x, y;
while( std::cin >> x >> y ) op.emplace_back( x, y ); // construct Point directly in the vector
// http://en.cppreference.com/w/cpp/container/vector/emplace_back
// write the data to the screen using user defined output operator
for( Point p : op ) std::cout << p << '\n';
// write the data to a text file using user defined output operator
// canonical: if the file was opened, write every object in the sequence to the file
if( std::ofstream ost{ "data.txt" } ) for( Point p : op ) ost << p << '\n';
else std::cerr << "error opening output file\n" ;
// the output stream ost is destroyed when it goes out of scope
// read data from text file using user defined input operator
std::vector<Point> ip;
Point p;
if( std::ifstream ist{ "data.txt" } ) while( ist >> p ) ip.push_back(p) ;
else std::cerr << "error opening input file\n" ;
// verify that the two vectors are equal (lexicographically equal)
if( ip == op ) std::cout << "read back the points successfully\n" ;
else std::cerr << "error in i/o of point\n" ;
// write data to screen using user defined output operator
for( auto p : ip ) std::cout << p << '\n';
}