我可以在进入`std :: stringstream`时去掉回车吗?

时间:2012-01-17 12:32:50

标签: c++ iostream line-endings

struct T
{
   void eat(std::string const& segment)
   {
      buffer << segment;

      std::string sentence;
      while (std::getline(buffer, sentence))
         std::cout << "[" << sentence.size() << "]";
   }

   std::stringstream buffer;
};

int main() {
   T t;
   t.eat("A\r\nB\nC\nD");
//        ^^   ^  ^  ^
}

// Actual output:  [2][1][1][1]
// Desired output: [1][1][1][1]

我希望std::stringstream为我取消回车(并且不希望复制和修改segment)。

我怎么能这样做?我本以为无论如何,这会发生在Linux上,对于文本模式的流......但也许这种机制是在 file 流的逻辑中。

1 个答案:

答案 0 :(得分:2)

在读取创建的文件时,这是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>

另一个解决方案是使用插入的过滤streambuf 输入流。这也很简单:

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;他们也保存了一个指针,并恢复 streambuf在他们的析构函数中。)