This is a general problem on Unix machines when reading files created on
a Windows machine. I would suggest doing the clean-up at the input
level.
One of the best solution I've found when reading line based files is to
create a class something like:
class Line
{
std::string myText;
public:
friend std::istream& operator>>( std::istream& source, Line& dest )
{
std::getline( source, dest.myText );
if ( source ) {
dest.myText.erase(
std::remove( dest.myText.begin(), dest.myText.end(), '\015' ),
dest.myText.end() );
}
return source;
}
operator std::string() const
{
return myText;
}
};
You can add other functions as necessary: the automatic type conversion
doesn't play when trying to match templates, for example, and I found it
useful to add friends to wrap boost::regex_match
.
I use this (without the '\015'
removal) even when I don't have to
worry about Windows/Linux differences; it supports reading lines using
std::istream_iterator<Line>
, for example.
Another solution would be to use a filtering streambuf, inserted into
the input stream. This is also very simple:
class RemoveCRStreambuf : public std::streambuf
{
std::streambuf* mySource;
char myBuffer; // One char buffer required for input.
protected:
int underflow()
{
int results = mySource->sbumpc();
while ( results == '\015' ) {
results = mySource->sbumpc();
}
if ( results != EOF ) {
myBuffer = results;
setg( &myBuffer, &myBuffer + 1, &myBuffer + 1 );
}
return results;
}
public:
RemoveCRStreambuf( std::streambuf* source )
: mySource( source )
{
}
};
To insert it:
std::streambuf* originalSB = source->rdbuf();
RemoveCRStreambuf newSB( originalSB );
source->rdbuf( &newSB );
// Do input here...
source->rdbuf( originalSB ); // Restore...
(Obviously, using some sort of RAII for the restoration would be
preferable. My own filtering streambuf have a constructor which takes
an std::istream
; they save a pointer to this as well, and restore the
streambuf in their destructor.)