2012-01-17 44 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)。 – 2012-01-17 12:42:20

+0

這樣的情況下,可能會有其他空白字符出現在字符串中嗎? – hmjd 2012-01-17 13:09:18

+0

@hmjd:通常不會,但我對使用'std :: skipws'沒有足夠的信心。 – 2012-01-17 13:25:17

回答

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爲恢復將是 最好我自己的過濾流緩衝有一個構造函數,需要 一個std::istream;他們也保存了一個指針,並在其析構函數中恢復了streambuf。)

相關問題