Это общая проблема на Unix-машинах при чтении файлов, созданных на Windows-машине.Я бы посоветовал выполнить очистку на уровне ввода.
Одно из лучших решений, которое я нашел при чтении файлов на основе строк, - создать класс, подобный следующему:
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;
}
};
Вы можете добавлять другие функции по мере необходимости: автоматическое преобразование типов не срабатывает, например, при попытке сопоставления с шаблонами, и я нашел полезным добавить друзей для переноса boost::regex_match
.
Я использую это (безудаление '\015'
), даже когда мне не нужно беспокоиться о различиях в Windows / Linux;например, он поддерживает чтение строк с использованием std::istream_iterator<Line>
.
Другим решением будет использование фильтрующего потока буфера, вставленного во входной поток.Это также очень просто:
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 )
{
}
};
Чтобы вставить его:
std::streambuf* originalSB = source->rdbuf();
RemoveCRStreambuf newSB( originalSB );
source->rdbuf( &newSB );
// Do input here...
source->rdbuf( originalSB ); // Restore...
(Очевидно, что использование какого-либо RAII для восстановления было бы предпочтительнее. Мой собственный фильтрующий streambuf имеет конструкторкоторый принимает std::istream
; они также сохраняют указатель на него и восстанавливают потоковый буфер в их деструкторе.)