2012-01-17 2 views
3
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をコピーして変更する必要がない方がよいです)。キャリッジリターンを `std :: stringstream`に入れるときにキャリッジリターンを取り除くことはできますか?

どうすればよいですか?私はこれがとにかく、Linuxで、テキストモードのストリームのために起こると思っていただろう...しかし、おそらくそのメカニズムはファイルストリームのロジックです。

+0

あなたは、[このクエストでのもののように修正さgetline関数を使用することができます。イオン](http://stackoverflow.com/questions/6089231/getting-std-ifstream-to-handle-lf-cr-and-crlf)。 –

+0

「食べている」弦に他の空白が存在する可能性がありますか? – hmjd

+0

@hmjd:通常はありませんが、 'std :: skipws'を使用するには十分な自信がありません。 –

答えて

2

これはWindowsマシンで で作成されたファイルを読むとき、Unixマシンでの一般的な問題です。私は、入力 レベルでクリーンアップを行うことをお勧めします。あなたは、必要に応じて他の機能を追加することができます

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に追加すると便利です。

私は Windows/Linuxの違いについて心配する必要がない場合でもこれを使用します('\015'を削除しないでください)。例えば、 を使用して行を読み取ります。

もう1つの解決策は、入力ストリーム に挿入されたフィルタリング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を復元)

関連する問題